AN90799 PSoC® 4 Interrupts (Chinese).pdf

AN90799
PSoC® 4 中断
作者:Rajiv Badiger
相关项目:代码示例
相关器件系列:所有 PSoC 4 器件
软件版本:PSoC Creator™ 3.3. 或更高版本
如果需要本应用笔记的最新版本,请访问 http://www.cypress.com/AN90799。
AN90799 介绍了 PSoC 4 中的中断架构以及它在 PSoC Creator™中的配置。本文档作为开发基于中断的项目的向导。
本应用笔记还说明了中断相关的高级概念, 比如:延迟、向量选择、中断代码优化以及调试技术。
目录
1
简介 ..........................................................................1
7.1
异常事件 ........................................................ 15
2
PSoC 中断架构 .........................................................2
7.2
中断延迟 ........................................................ 15
2.1
中断源 ..............................................................2
7.3
优化中断代码 ................................................. 16
2.2
3
4
电平及边沿触发中断 ........................................4
7.4
带有内置中断的组件 ...................................... 16
PSoC Creator 的中断支持.........................................5
7.5
强制中断向量编号 .......................................... 16
3.1
中断组件配置 ...................................................5
7.6
Systick 定时器................................................ 18
3.2
中断优先级配置................................................7
7.7
中断嵌套 ........................................................ 19
3.3
中断 API 函数 ...................................................8
8
总结 ........................................................................ 19
写入一个中断服务子程序(ISR) ........................... 10
A
附录 A – PSoC 4 中的中断源和向量编码 ................ 20
4.1
使用自动生成的 ISR ....................................... 11
文档修订记录................................................................... 22
4.2
创建自定义 ISR .............................................. 12
全球销售和设计支持 ........................................................ 23
5
代码示例 ................................................................. 13
产品 ................................................................................. 23
6
调试提示 ................................................................. 13
PSoC 解决方案............................................................... 23
7
高级中断主题 .......................................................... 15
1
®
简介
中断是嵌入式应用的重要组成部分。它们使 CPU 不必连续轮询某个特定事件的发生情况。它仅在该事件发生时通知
CPU。在片上系统(SoC)的架构(如 PSoC)中,经常使用中断向 CPU 报告片上外设的状态。
如何使用本文档
该文件先对 PSoC 4 中断结构进行了介绍。如果您想了解 PSoC Creator IDE 的中断支持的内容,请跳到 PSoC
Creator 的中断支持一节。对于中断代码示例,请参考代码示例。如果您正在调试中断项目,请转到调试提示部分,该
部分提供了一些用于发现和解决中断问题的提示。高级中断主题部分提供了与中断相关的高级主题内容。
本应用笔记假定您已经熟悉了 PSoC 器件和 PSoC Creator 集成开发环境(IDE)。如果您尚未了解 PSoC,可通过
AN79953 PSoC 入门应用笔记并参考 PSoC Creator 主页来获取相关信息。
www.cypress.com
文档编码:002-11590 版本**
1
PSoC® 4 中断
2
PSoC 中断架构
图 1 显示了 PSoC 4 的中断架构的简化框图:
图 1. PSoC 4 中断架构
ARM® Cortex® M0
Interrupt
Sources
{
IRQ[0]
IRQ[1]
IRQ[2]
IRQ[31]
Nested Vectored
Interrupt Controller
(NVIC)
-
-
Cortex – M0
Processor Core
Wakeup Interrupt
Controller (WIC)
To Power Management System
有 32 个中断线 – 从 IRQ[0]到 IRQ[31] – 每线有四个优先级:从 0 到 3。每个中断线被分配了一个中断向量地址。接收
到一个中断请求后,CPU 会跳转到该地址,并会在这里执行一个特殊函数,即中断服务子程序(ISR)。
中断信号由嵌套向量中断控制器(NVIC)接收。某个中断信号有效时,NVIC 通过中断请求信号将中断向量地址发送给
处理器内核。作为回答,处理器内核在进入和离开 ISR 时都将发送一个确认信号。NVIC 负责启用/禁用用户配置所指
定的中断。发生多个中断请求时,它会按中断优先级高低进行处理,支持嵌套中断,能够暂停一个优先级低的 ISR 转
而执行一个优先级高的中断。
唤醒中断控制器(WIC)模块支持使用中断将器件从低功耗模式唤醒。低功耗模式包括:睡眠模式、深度睡眠模式和休
眠模式。当 NVIC、处理器内核和其他外围设备掉电时,WIC 模块仍保持有效。当触发了某个中断时,WIC 将激活电源
管理系统,这样会恢复 NVIC、处理器内核以及其他外设。这时 NVIC 将接管并发送向量地址到处理器内核,以执行
ISR。在 PSoC 4 器件中存在几种源,它们均能够唤醒器件。例如,图 1 显示了 IRQ[0]和 IRQ[1]都被路由到了 WIC 和
NVIC。这些是来自 GPIO 的中断线路。
PSoC 4 具有以下中断特性:


2.1
可配置中断向量地址:发生中断时,CPU 可以直接跳转并执行任何 ISR 代码,这样可缩短延迟。
灵活的中断源:在传统的微控制器中,中断源是固定连接到各个中断线的。在 PSoC 中,您可灵活选择每条中断
信号线的中断源。这种灵活的架构允许配置任何数字信号作为中断源使用。
中断源
PSoC 4 中断源分两种类型:
1.
固定功能的中断源:这些是片上外设的一些预定义中断源。
2.
通用数字模块(UDB)中断源(在 PSoC 4200、PSoC 42x7_BLE、 PSoC 4200M 和 PSoC 4200L 中可用):
UDB 是不同数字功能(如定时器、PWM、UART、SPI 等)的基本构建模块。它包括可编程逻辑(PLD)、数据
路径和灵活的路由。与功能固定的中断源相比,某个 UDB 生成的所有数字信号都能触发一个中断。信号通过一个
被称为数字系统互连(DSI)的结构路由到中断控制器。请参见 PSoC 4 技术参考手册,了解更多信息。
www.cypress.com
文档编码:002-11590 版本**
2
PSoC® 4 中断
表 1 显示了各个中断源。除非另有说明,否则表中提及的中断源可用于所有 PSoC 4。有关每个中断源的详细信息,
请参考表 1 中列出的 PSoC Creator 组件数据手册。附录 A 依据器件给出了中断源的完整列表。
表 1. PSoC 4 中断源
中断源
详细说明
每个端口包含 8 个引脚。每个引脚可以产生一个中断,但是端口中的所有引脚共用了一个向量地址。
必须由固件区分引起中断的引脚。
GPIO
PSoC 4 会在 GPIO 信号的上升沿、下降沿或双边沿上触发中断。该中断可将器件从睡眠、深度睡眠和
休眠模式唤醒。
低功耗比较器
(LPCOMP)(1)
与 GPIO 相似,某个中断能够在比较器输出信号的上升沿、下降沿或双边沿上被触发。LPCOMP 也能
够将器件从睡眠、深度睡眠和休眠模式唤醒。
WDT
看门狗定时器(WDT)是一个定时器,它可以复位器件或生成一个中断。PSoC 4000 具有一个 16 位
的自由运行 WDT,而其他 PSoC 4 系列则有两个 16 位的 WDT 和一个 32 位的 WDT。WDT 可将器件
从睡眠和深度睡眠模式唤醒。
PSoC 4 具有多达 4 个串行通信模块(SCB),它们可被配置为 I2C、SPI 或 UART。
I2C
以下事件会生成一个中断:仲裁失败、从设备地址匹配、启动/停止检测、总线错误、字节
/字传输完成、TX FIFO 不满、TX/RX FIFO 为空、RX FIFO 非空、RX FIFO 溢出以及 RX
FIFO 已满。从设备的地址匹配事件可将器件从睡眠和深度睡眠模式唤醒。
SPI
下列事件会生成一个中断:传输完成、闲置、TX FIFO 不满、TX/RX FIFO 为空、字节/字
传输完成、RX FIFO 非空、尝试写已满的 RX FIFO 以及 RX FIFO 已满。
UART
下列事件会生成一个中断:传输完成、UART TX 接收到 SmartCard 模式的 NACK、
UART 在 LIN 或 SmartCard 模式下仲裁丢失、帧错误、奇偶校验错误、LIN 波特率检测
完成以及 LIN 成功中断检测。
SCB
系统性能控制器
(SPC)
SPC 模块控制着闪存写操作。当闪存写操作完成时,它会触发一个中断。
SYSTICK
SysTick 是 ARM® Cortex®-M0 处理器中内置的 24 位定时器。实时操作系统(RTOS)通常将其作为一
个触发定时器使用。另外它也可作为一个通用定时器使用。请查看 Systick 定时器章节,了解更多信
息。
电源管理程序(1)
当器件供电电压下降到某个阀值以下时,该模块会生成一个低压检测(LVD)中断。
SAR ADC(1)
当发生转换结束、数据溢出、扫描冲突、数据饱和以及数据超出范围等事件时,逐次逼近寄存器的模
数转换器(SAR ADC)会生成中断。
CapSense(CSD)
传感器扫完成描过程时,用于触摸应用的 CSD 会生成一个中断。
定时器/计数器/脉宽
调制器(TCPWM)
可将 TCPWM 模块配置作为 16 位定时器、计数器或 PWM 使用。它可以在发生终端计数、输入捕获信
号或某个“比较结果为真”事件时生成中断。
控制器区域网络
(CAN)
PSoC 4200M 和 PSoC 4200L 器件具有两个 CAN 模块,这两个模块能够在发生接收到信息、发送信息
以及各种错误事件时生成中断。请参见 CAN 中技术参考手册章节,了解更多信息。
直接储存器访问
(DMA)
PSoC 4100M/4200M 和 PSoC 4200L 具有 DMA 用于在外设之间传输数据。数据传输完成时会生成
中断。
通用数字模块(UDB)
通过 UDB 实现的定时器、PWM、计数器、UART 等之类的功能,可以在发生不同事件时生成中断,
同固定功能的相应模块相类似。UDB 可用于 PSoC 4200、PSoC 42x7_BLE、PSoC 4200M 和 PSoC
4200L。
USB
PSoC 4200L 中的 USB 具有帧起始(SOF)和通过数据端点进行的通信结束等中断。
(1)
不适用于 PSoC 4000
www.cypress.com
文档编码:002-11590 版本**
3
PSoC® 4 中断
2.2
电平及边沿触发中断
PSoC 4 支持电平和边沿触发的中断。图 2 显示的是用于选择触发类型的逻辑运算。NVIC 支持的所有中断线都遵循该
逻辑运算。应该注意,固定功能的中断只能被配置为电平触发,但是对于包含了 UDB 的 DSI 源,中断可被上升沿触
发,并且也可以通过电平触发。上升沿检测模块会在 DSI 中断信号每个上升沿上产生一个脉冲。请参考时序图(图 3
和图 4),了解 NVIC 如何响应电平和边沿触发的中断。
图 2. 电平触发和边沿触发
Level
Fixed Function Interrupt Source
DSI Interrupt
Source
(irq_out[n])
Level
Rising
Edge
Detect
0
IRQn
( n = 0 to 31)
0
1
To NVIC
1
UDB_INT_ CFG
register
CPUSS_ INTR_ SELECT
register
图 3. 电平触发中断
int[x]
CPU
Execution
main
State
ISR
int[x] is still high
ISR
main
ISR
main
图 4. 边沿触发中断
int[x]
CPU
Execution
main
State
ISR
ISR
main
ISR
main
注意:GPIO 中断逻辑具有额外的电路,用于支持在上升沿、下降沿以及双沿上触发的中断。请参见 PSoC 4 技术参考
手册,了解更多信息。
www.cypress.com
文档编码:002-11590 版本**
4
PSoC® 4 中断
3
PSoC Creator 的中断支持
上述章节介绍的一些中断特性必须设置,如:电平或边沿触发、向量地址以及中断优先级。配置操作是通过 PSoC
Creator 中断组件进行的。该组件位于 Component Catalog(组件目录)窗口中的 System(系统)选项卡下,如图 5
所示。
每个中断组件实例均使用了连向 NVIC 的 32 根导线中的一根中断线。图 5 所示的示例,来自 SAR ADC 的结束转换信
号(EOC)被连接到中断组件“isr_1”上。SAR ADC 有一根 NVIC 的分配向量线(请参考附录 A)。例如,在 PSoC
4200 中,IRQ14 可用于 SAR ADC 中断。因此,中断组件“isr_1”通过 MUX 逻辑将 EOC 信号连接到 IRQ14 导线,
如图 2 所示。
图 5. PSoC Creator 中断组件
3.1
中断组件配置
图 6 显示的是中断组件配置对话框。组件中有三个选项:DERIVED、RISING_EDGE 和 LEVEL。
图 6. 中断组件配置
这些设置用于配置图 2 所示的复用器。根据中断源(功能固定或 UDB/DSI)和应用要求决定某个特定选项的选择
情况。
www.cypress.com
文档编码:002-11590 版本**
5
PSoC® 4 中断
固 定 功 能 模 块 : 从固定功能模块引出的中断线通常使用“专用布线”完成,如图 7 中红线所示。配置该路径时,中断
是电平触发的,并且根据正在使用的硬件模块确定中断信号线。连接到中断线的中断组件(isr_1)只能被配置为电平
触发。将中断设置为 RISING_EDGE 触发,会引起构建错误。配置为 DERIVED 时,工具只能将其配置为电平触发。
但是,在具有 DSI 的 PSoC 器件中,来自固定功能模块的其他输出信号可作为中断源使用。这样允许将中断组件配置
为 RISING_EDGE 项,如图 7 中蓝线所示。连接到来自 PWM 输出的中断组件(isr_2)可被配置为电平触发项
(Level)或上升沿触发项(RISING_EDGE)。选中 DERIVED 选项时,工具会选择电平触发配置。在这种情况下,
电平触发没有任何效果,这是因为它会使 ISR 在信号为高电平的情况下重复执行。因此大多情况下使用上升沿触发项
(RISING_EDGE)。
图 7. 固定功能模块的中断路由
Level
Fixed Function Interrupt Source
DSI
DSI Interrupt
Source
(irq_out[n])
Level
IRQn
( n = 0 to 31)
0
1
Rising
Edge
Detect
TCPWM
(Fixed Function)
0
To NVIC
1
UDB_INT_ CFG
register
CPUSS_ INTR_ SELECT
register
U D B : 对于 UDB,使用 DSI 将信号(来自 UDB 组件的中断线或任何输出)输送给 MUX 逻辑,如图 8 所示。因此,
LEVEL 和 RISING_EDGE 选项都适用于来自 UDB 的所有信号。选中中断组件(isr_1 或 isr_2)中的 DERIVED 项时,
也便选中了 RISING_EDGE 项。这种情况恰好与功能固定模块输出的 DSI 信号路由情况相反。
图 8. UDB 的中断路由
Fixed Function Interrupt Source
DSI
DSI Interrupt
Source
(irq_out[n])
Level
0
1
Rising
Edge
Detect
Fixed Function Interrupt Source
DSI
DSI Interrupt
Source
(irq_out[n])
Level
CPUSS_ INTR_ SELECT
register
0
IRQn
( n = 0 to 31)
0
1
Rising
Edge
Detect
To NVIC
1
UDB_INT_ CFG
register
PWM
(UDB)
IRQn
( n = 0 to 31)
0
To NVIC
1
UDB_INT_ CFG
register
CPUSS_ INTR_ SELECT
register
注意:PSoC 4 BLE、PSoC 4 M 和 PSoC 4 L 有 8 个 DSI 通道,每个通道对应 4 路中断信号线,从而为 ARM CortexM0 处理器提供 32(8x4)个中断信号线。因此,一个设计中 DSI 中断的最大数量被限制为 8。
www.cypress.com
文档编码:002-11590 版本**
6
PSoC® 4 中断
表 2 提供了中断组件中设置 InterruptType 参数的指南。
表 2. 中断组件配置
中断源
信号
中断
选择 LEVEL 或 DERIVED。不允许使用 RISING_EDGE。
模块输出
选择 RISING_EDGE 项,否则在逻辑高电平信号期间,中断将被重复触发。
中断
选择 RISING_EDGE 或 DERIVED。
模块输出
选择 RISING_EDGE 项;如果选择 LEVEL 项,那么在逻辑高电平信号期间,中断将被重复触发。
固定功能
UDB 函数
3.1.1
中断组件配置
粘 滞 ( S t i c k y) 位
中断信号可以是“粘滞”(sticky)的,这便意味
着中断线保持有效状态(高电平),直到它被读取
或者清除为止。在这种情况下,如果中断组件被配
置为 RISING_EDGE,那么将执行一次 ISR。如
果中断组件被配置为 LEVEL,那么 ISR 将重复被
执行。为解决这个问题,需要使用由组件提供的
API 清除中断源。请查看中断源的组件数据手册。
您也可以参考写入一个中断服务子程序(ISR)章
节,这部分内容提供了一个使用定时器中断的例
子。
图 9. “粘滞”信号
请注意,当一个功能固定模块或 UDB 的输出线
(例如,图 9 所示 PWM 组件的“pwm”线)被
连接到中断组件,而不是中断线时,便不用清除中
断。但是如果中断组件被配置为 LEVEL,那么
ISR 在信号为 HIGH 期间将重复被执行。
3.2
中断优先级配置
PSoC Creator 项目的 Design Wide Resource(设计范围资源)窗口(project_name.cydwr)中包含一个 Interrupts 选项
卡,该选项卡显示了中断组件的名称、它们的优先级以及向量编号,如图 10 所示。 isr_1、isr_2 和 isr_3 为设计中使用
的中断组件。
图 10.cydwr 窗口中的 Interrupt 选项卡
www.cypress.com
文档编码:002-11590 版本**
7
PSoC® 4 中断
使用 cydwr 窗口更改中断优先级。请注意:最高优先级为 0,最低优先级为 3。Cortex-M0 支持中断嵌套,请参考中断
嵌套了解详细信息。
构建项目时,PSoC Creator 将自动分配每个中断组件的中断向量编号,但可以手动更改。请参考强制中断向量编号一
节中的内容,了解更详细的信息。另外,应注意.cydwr 窗口中显示的是向量编号的偏移量。在 Cortex-M0 中,向量编
号 0 对应异常编号 16。请参考异常事件,了解 Cortex-M0 异常的大概情况。
3.3
中断 API 函数
PSoC Creator 为项目中每一个组件生成一个 API –.c 和.h 文件。这些 API 所包含的函数用于配置和使用每一个组件。
下面显示的各个 API 函数同一个中断组件相关联:


<instance_name> Start()和 <instance_name>_Stop()
Start()
使能中断、将其向量设置为默认的 ISR 并设置中断优先级。
Stop()
禁用中断。
<instance_name>_StartEx()
它的功能与 Start()相似。唯一不同的地方表现在:该函数将一个向量地址作为一个输入,这样您能够写入一个
自定义 ISR,而不必使用组件生成的默认 ISR。

<instance_name> Enable()和 <instance_name>_Disable()
这些函数由 Start()和 Stop()内部调用,用以使能和禁用中断。可以通过调用这些函数来动态使能和禁用某个
中断。

<instance_name> SetVector()和 <instance_name> SetPriority()
这些函数被 Start()和 Stop()内部调用,用以设置中断向量地址和中断优先级。也可以调用这些函数,动态设
置中断的向量和优先级。请确保在调用这些函数前已经禁用了该中断。

<instance_name> SetPending()
使中断保持等待状态,而不需要硬件的中断请求。

<instance_name> ClearPending()
清除中断的挂起状态,使该中断不被服务。该函数不对中断源信号产生任何影响;它只会清除 NVIC 的中断信号线
的挂起状态位。
请参见中断组件数据手册,了解 API 的详细介绍。
3.3.1
关键部分控制函数
在 CyLib.h 和 CyLib.c 文件中,PSoC Creator 还提供了一组通用的中断函数。该项目建成时,将生成这些文件。
CyEnterCriticalSection 和 CyExitCriticalSection 是关键内容。通过这两个函数可使固件变量和硬件寄存
器避免发生损坏。CyEnterCriticalSection 可禁用中断,并返回一个中断状态值。CyExitCriticalSection
可恢复中断状态。
如要了解中断具体如何工作,可考虑写一个定时器控制寄存器的示例:
TCPWM_BLOCK_CONTROL_REG |= TCPWM_MASK;
执行上述语句的过程中,具体操作如下:
1.
CPU 会读取 TCPWM 的控制寄存器并将数据存储在一个临时寄存器内。
2.
CPU 对临时寄存器中的数据和它的掩码值进行逻辑或(OR)运算。
3.
CPU 将逻辑或运算后的结果加载到控制寄存器内。
在步骤 1 和步骤 2 之间,可能会发生一个中断,并且它的 ISR 可能会将一个新值加载到相同的控制寄存器内。执行
ISR 后,当 CPU 继续执行步骤 2 时,它使用临时寄存器中的旧控制寄存器值,从而引起数据损坏。
www.cypress.com
文档编码:002-11590 版本**
8
PSoC® 4 中断
为避免发生这种情况,添加了以下代码:
InterruptState = CyEnterCriticalSection();
TCPWM_BLOCK_CONTROL_REG |= TCPWM_MASK;
CyExitCriticalSection(InterruptState);
CyEnterCriticalSection 和 CyExitCriticalSection 函数在控制寄存器被写入时禁止中断,从而能够解决该
问题。某个共享的变量或寄存器被写入时,使用这些函数。
更多有关这些函数的信息,请参见系统参考指南(也可以在 PSoC Creator 菜单依次选择 Help > Documentation,
找到该文档)。
www.cypress.com
文档编码:002-11590 版本**
9
PSoC® 4 中断
4
写入一个中断服务子程序(ISR)
要想了解如何编写一个 ISR,可考虑定时器中断实例。中断组件“isr_1”连接到 Timer_1 的中断终端,如图 11 所示。
编译项目后,PSoC Creator 生成与组件相关的所有文件,如图 12 所示。isr_1.c 和 isr_1.h 是中断组件 isr_1 生成的文
件。这些文件提供了 API 用于配置和使用组件(包括 ISR)。
图 11. 定时器中断示例
图 12. 中断组件生成的文件
有两种方式能够进行编写一个 ISR — 使用 PSoC Creator 自动生成的 ISR;创建一个自定义的 ISR 函数。
www.cypress.com
文档编码:002-11590 版本**
10
PSoC® 4 中断
4.1
使用自动生成的 ISR
下面显示的是 isr_1.c 中默认生成的 ISR。ISR 函数名称的格式为 CY_ISR(<isr_name>_interrupt)。
CY_ISR(isr_1_Interrupt)
{
/* Place your Interrupt code here. */
/* `#START isr_1_Interrupt` */
/* `#END` */
}
您可以将代码写在这个自动生成的 ISR 中标记#START 和#END 之间。请注意,重新生成项目文件时,写在这两个标
记外的代码将被清除。
为使能中断,需要启动 ISR 组件。下面显示的是 main.c 代码,用以启动中断源,既为定时器和中断组件。
int main()
{
/* Start the timer component */
Timer_1_Start();
/* Start the interrupt component */
isr_1_Start();
/* Enable global interrupt */
CyGlobalIntEnable;
for(;;)
{
/* Place your application code here. */
}
}
请注意,除了需要使能中断组件外,您还要通过 CyGlobalIntEnable 宏使能全局中断。如粘滞(Sticky)位中的
解释,在 ISR 内部,清除中断。在该示例中,定时器中断通过下面的 API 函数被清除:
void Timer_1_ClearInterrupt(uint32 interruptMask)
参数 interruptMask 可以是定时器组件的终端计数中断掩码,也可能是比较/捕获计数中断掩码 – 请参见定时器组
件数据手册或文件 timer_1.h。请参阅其他组件数据手册,了解 API 和中断屏蔽,它通过一个特定组件来清除中断。
www.cypress.com
文档编码:002-11590 版本**
11
PSoC® 4 中断
4.2
创建自定义 ISR
可以在您自己的源文件中编写 ISR,而不一定要通过自动生成的代码。为了将自己的函数(例如:MyCustomISR)当
作某个 isr_1 中断组件的 ISR,请执行以下操作:
1. 通过使用 CY_ISR_PROTO 宏来声明这个自定义函数:
CY_ISR_PROTO(MyCustomISR);
2. 使用 CY_ISR 宏来定义自定义函数:
CY_ISR(MyCustomISR)
{
/* ISR code goes here */
}
3.
在 main.c 文 件 的 启 动 代 码 中 , 请 添 加 对 isr_1_StartEx() 函 数 的 调 用 , 不 是 isr_1_Start() 函 数 。
isr_1_StartEx() API 函数类似于 isr_1_Start() API 函数,只是 isr_1_StartEx()调用需要传入一个可
用于 ISR 的函数名作为函数参数:isr_1_StartEx(MyCustomISR);
CY_ISR_PROTO(MyCustomISR);
/********************************************************************
* Function Name: MyCustomISR
*********************************************************************
CY_ISR(MyCustomISR)
{
/* Add code here */
}
int main()
{
/* Start the timer component */
Timer_1_Start();
/* Set the custom ISR */
isr_1_StartEx(MyCustomISR);
/* Enable global interrupt */
CyGlobalIntEnable;
for(;;)
{
/* Place your application code here. */
}
}
4.2.1
关键字 CY_ISR 的重要性
中断源文件通过使用 CY_ISR 宏来定义 ISR 函数。这个宏被定义在自动生成的 cytypes.h 文件内。将代码移植到其他
PSoC 器件系列(如 PSoC 3 或 PSoC 5LP)时,它提供兼容性,并使移植变得更加简单。
同样,CY_ISR_PROTO 宏声明了一个 ISR 函数原型。该声明位于中断组件的头文件中。例如,在头文件 isr_1.h 中,
中断组件 isr_1 含有以下函数原型的声明:
CY_ISR_PROTO(isr_1_Interrupt);
www.cypress.com
文档编码:002-11590 版本**
12
PSoC® 4 中断
5
代码示例
表 3 显示的是使用中断特性的代码示例清单。
表 3. 中断代码示例
代码示例
CE210557 – PSoC 4 定时器中断
定时器
CE210558 – PSoC 4 GPIO 中断
GPIO
®
6
中断源
CE95915 – PSoC 4100/PSoC 4200 器件中 RTC 的实现
TCPWM
CE95333 – PSoC 4 的低功耗比较器
LPCOMP1:P
CE95321 – PSoC 4 的休眠和停止模式
LPCOMP、GPIO
CE95400 – PSoC 41xx/42xx 器件的看门狗定时器复位和中断
WDT
CE95275 – PSoC 4 中的序列 SAR ADC 和晶片温度传感器
SAR ADC
CE95298 – PSoC 3/4/5LP 的开关去抖动组件
GPIO、去抖动组件
CE97089 – PSoC 4 ADC 到存储器缓冲区 DMA 的传输
DMA
调试提示
本节针对调试中断项目提供了一些提示信息。下面是常会遇到的情况:
a.
b.
中断未被触发

请确保中断源和全局中断被使能。

请检查向量是否被设置为准确的 ISR。请参考写入一个中断服务子程序(ISR),了解有关为某个中断源
编写和分配处理程序的详细信息。

请检查是否有其他被重复触发的中断源,因而占用了整个 CPU 的带宽。

检查中断是否仅被触发了一次。如果中断组件被配置为上升沿触发并且中断源未被清除,那么将发生上述
情况。
中断被重复触发
在下面各种情况下,中断会被重复触发:

来自源组件的中断线连接到被配置为电平触发类型的中断组件上。可通过清除中断源来解决这个问题。

来自组件的数字输出(并非中断线)连接到被配置为电平触发类型的中断组件上。将中断组件配置为上升
沿触发,从而在每个上升沿上触发一次中断。
请参考粘滞(Sticky)位,了解更多信息。
c.
中断仅触发一次
来自源组件的中断线连接到被配置为上升沿触发类型的中断组件上。清除中断源,从而允许在每个上升沿上触
发中断。请参考粘滞(Sticky)位,了解更多信息。
d.
执行中断服务子程序(ISR)比预期的时间长
在 ISR 执行过程中,如果有其他优先级更高的中断被触发,会发生这种情况。可更大该中断的优先级,使它
的优先级高于其他中断源的。
www.cypress.com
文档编码:002-11590 版本**
13
PSoC® 4 中断
可通过串行线调试(SWD)接口调用 PSoC 4 器件的片上调试功能。通过该接口,您能够添加断点、评估和编辑变量
值、检查 CPU 寄存器、观察汇编指令,以及读取和写入存储器。
调试模式有助于检查中断,具体如下:

要想检查中断是否被执行,将一个断点添加到 ISR 指令之一。

使用调试器的 Call Stack 窗口来检查特殊中断被执行的时间。您也可以通过该窗口检查在一个低优先级 ISR 的执
行过程中是否发生了一个优先级更高的中断。
使用断点触发计数来检测中断被触发的次数。它对检查中断信号是否有干扰特别有用,若存在干扰,则这个中断可能被
多次触发。
欲了解调试器的使用, 请参见 PSoC Creator Help 中的“使用调试器”一节。要访问本文档,请在 PSoC Creator 中
按下 F1 按键或者使用 Help > Topics 菜单。
除了使用调试器的方式外,您也可以通过引脚的“bit bang”技术实现以下操作:

检查 CPU 是否正在进入 ISR。

测量 ISR 执行时间。通过在 ISR 开始和结束时分别设置和重设置引脚,可以完成这个操作。
www.cypress.com
文档编码:002-11590 版本**
14
PSoC® 4 中断
7
高级中断主题
7.1
异常事件
使处理器暂停执行当前的代码,并转移到某个处理程序,这便是一个异常事件。中断是异常事件的一个子集。除中断
外,操作系统应用和故障处理也是异常事件,如表 4 所示。
表 4. ARM Cortex M0 中的异常事件
异常事件
异常编号
中断优先级
复位
1
–3(最高级)
硬故障
3
–1
SVCall(管理程序调用)
11
可编程
在调用某个管理程序时(执行 SVC 指令),会触发该类异常。通常在
操作系统应用中使用它。
PendSV (可挂起服务调用)
14
可编程
这种异常同 SVCall 相似,但是完成所有高优先级任务后才会转换到处
理程序。
SYSTICK
15
可编程
SysTick 是 Cortex M0 中的 24 位递减计数定时器。它为操作系统应用
提供周期性中断。
16 – 47
可编程
外部(引脚)或内部外设中断
1
–3(最高级)
IRQ0 到 IRQ31
复位
说明
在上电复位或外部复位时,会触发该类异常事件。
在检测未定义操作码之类的故障条件下,将产生这种异常事件。
在上电复位或外部复位时,会触发该类异常事件。
请注意,异常事件编号由 ARM 定义。PSoC Creator 项目的.cydwr 窗口内,在 Interrupt 选项卡显示的中断向量编号包
含了一个异常偏移量。例如,中断向量 0 为异常编号 16(IRQ0)。
在器件中,复位是优先级最高的异常事件,然后是硬故障。它们的优先级是固定的,其他异常的优先级则是可编程的。
PSoC Creator 为所有异常事件提供了一个默认的处理程序。对于复位,默认的处理程序为 Cm0Start.c 文件中的
Reset() 。启动后首先会执行这个函数。对于所有其他异常事件,Cm0Start.c 文件中的函数 IntDefaultHandler()是默认
的处理程序。然而,所使用的包括中断的异常事件向量地址(由 PSoC Creator 组件或用户自己定义),在程序执行期
间被加载到向量表内。未使用的异常事件仍使用默认的处理程序。
要确定当前正在处理的异常事件,请读取中断程序状态寄存器(IPSR)。默认处理程序正在执行时,这种方法非常
有用。
有关异常事件的详细信息,请参考 http://infocenter.arm.com/help/index.jsp。
7.2
中断延迟
中断延迟被定义为从中断被确认到 ISR 中第一个指令被执行的延迟时间。PSoC 4 器件中的 ARM Cortex-M0 处理器的
中断延迟为 16 个 CPU 时钟周期(最坏情况),但是由于外设和 Cortex-M0 中断线之间的同步,再需要几个 CPU 周
期。表 5 提供了对于 DSI 和功能固定源中断,不同 PSoC 4 系列的同步 CPU 时钟周期延迟。
表 5. DSI 和功能固定源中断的同步时钟周期延迟
器件
DSI 中断
固定功能中断
具体情况取决于外设:


PSoC 4000
NA
PSoC 4100/PSoC 4200
0 个 CPU 周期
SCB-I2C、GPIO、WDT:3 个 CPU 周期
SPC、CSD、TCPWM:0 个 CPU 周期
3 个 CPU 周期
具体情况取决于外设:
PSoC 42x7 BLE / PSoC 41x7 BLE
www.cypress.com
3 个 CPU 周期

SCB-I2C、 GPIO 、WDT 、 CTBm 、 LPCOMP 、 BLE 、 LVD: 3 个
CPU 周期

SPC、CSD、TCPWM、SAR:0 个 CPU 周期
文档编码:002-11590 版本**
15
PSoC® 4 中断
器件
DSI 中断
固定功能中断
具体情况取决于外设:
PSoC 4200M / PSoC 4100M /
PSoC 4200L
3 个 CPU 周期


SCB-I2C、GPIO、WDT、CTBm、LPCOMP、LVD:3 个 CPU 周期
SPC、CSD、TCPWM、SAR、DMA、CAN、USB(仅使用于 PSoC
4200L):0 个 CPU 周期
在 Cortex M0 中 16 个周期延迟中,会发生下列操作:
1.
2.
3.
处理器将当前的程序计数器(PC)、链接寄存器 (LR)、编程状态寄存器(PSR)以及一些通用的寄存器推进
到堆栈中。
处理器从 NVIC 读出向量地址并将其更新到 PC 中。
处理器更新 NVIC 寄存器。
因此,当某个 ISR 当前正在执行或即将开始的时候,延迟并非 16 个周期。要使流程更有效,Cortex-M0 处理器将实现
下面两个设置:
1.
末尾连锁:如果中断处于挂起状态,而处理器正在执行另一个中断处理,当执行完第一次中断时,跳过出栈,并立即处
理挂起中断。该步骤将帮您减少从堆栈恢复寄存器并将相同寄存器重新放入堆栈的时间。该方法也对减少低优先级中断
的延迟起着作用。
2.
迟到:如果在低优先级中断的入栈期间发生更高优先级中断,处理器将优先处理更高优先级中断。入栈过程结束时,处
理器将读取更高优先级中断的向量地址。一旦更高优先级中断的处理过程完成,将读取及执行被挂起的更低优先级中断
处理的向量地址。该过程可排除因进入优先级更低的 ISR 并将寄存器值放入堆栈中所导致的延迟,从而减少更高优先
级中断的延迟。
请注意,触发中断时,如果当前正在执行某个指令,则 ISR 的执行会产生额外的延迟。器件从中断唤醒时,执行上电
序列后电压的稳定过程需要一段延迟时间。有关详细信息,请参考器件数据手册。
7.3
优化中断代码
在基于中断的应用中,ISR 代码执行时间是重要的性能要求之一。在某些应用中,当接收某个中断请求时,必须在特定
的时间内执行 ISR 中的关键处理代码。此外,中断的执行时间也不能太长,否则会使主代码和其他中断的执行被停
顿。要想满足这些要求,请遵循下面指南:

避免在 ISR 中调用冗长函数:诸如字符 LCD 显示子程序之类函数的执行占用更长的时间,因此阻止执行优先级更
低的中断。
推荐将不重要的函数调用移到主代码内,在 ISR 中只设置了一个标志变量。主代码将定期检查该标志。如果该标
志被置位,主代码会清除它,并调用函数。

7.4
请为各个中断分配合适的优先级: 在包含了多个中断的应用中,请给时间关键的中断配置更高的优先级。
带有内置中断的组件
很多PSoC Creator组件在实现其功能时,已经包含了一个内部中断组件。示例包括CapSense、SAR ADC、EZI2C和
段式LCD。
与中断组件相同,这些组件中的内部ISR提供了一个用于编写用户代码的占位符区域。请参见PSoC Creator中所提供的
相应组件数据手册以及相关的代码示例,了解这些组件中的中断用法。
7.5
强制中断向量编号
PSoC Creator 自动给项目中的中断组件分配向量编号。编译项目后,您可以在.cydwr 窗口中的 Interrupts(中断)选
项卡下查看所分配的向量编号,如图 13 所示。当该中断来自 DSI 时,您也可以为某个中断信号选择一个特定的向量编
号。本节逐步介绍了该过程。
www.cypress.com
文档编码:002-11590 版本**
16
PSoC® 4 中断
图 13. cydwr 窗口中的中断向量编号
要覆盖掉由 PSoC Creator 分配的向量编号,并想手动分配一个向量编号,请使用控制文件。按照下面步骤进行操作:
1.
点击‘Workspace Explorer’窗口中的 Components 选项卡。
2.
右键点击 TopDesign 组件,然后点击 Add Component Item…项。打开‘Add Component Item’对话框。
3.
向下滑动到 Misc 组,选择 Control File 项,然后点击 Create New 按键,如图 14 所示。
图 14. 添加控制文件
一个 TopDesign.ctl 文件将被创建并添加到‘Workspace Explorer’窗口内。
4. 双击打开 TopDesign.ctl 文件,进行编辑。在控制文件中通过使用 attribute 关键词,可以指定每个中断组件的中断
向量编号。指定中断向量编号的方法取决于下面两种情况:用户将中断组件放在示例原理图内;或在原理图中,
PSoC Creator 组件内部使用了中断组件。两种方法具体如下:
a)
用户将中断组件放在原理图内时,句法将为:
attribute placement_force of instance_name : label is "Intr(0, DesiredVectorNumber)";
这里,instance_name 是指原理图中中断组件的名称,DesiredVectorNumber 为向量编号(0 至 31)。
例如,要想将向量 17 分配给中断组件 isr_1,该句法为:
attribute placement_force of isr_1 : label is "Intr(0, 17)";
www.cypress.com
文档编码:002-11590 版本**
17
PSoC® 4 中断
b)
对于内部使用中断的组件,如 EZI2C,句法将为:
attribute placement_force of \top_instance_name
"Intr(0, DesiredVectorNumber)";
:
InternalInterruptName\:
label
is
这里,top_instance_name 是指使用内部中断的组件名称。InternalInterruptName 为组件中分配给
内部中断的名称。可以在 cydwr 窗口中的 Interrupts 选项卡下查找该名称。其中,中断名称是组件实例名称的
前缀。在图 13 中,SCB_IRQ 是 EZI2C 组件和 UART 组件的内部中断名称。下面的语句将向量 11 分配给
EZI2C 组件。
attribute placement_force of \I2C_1:I2C_IRQ\ : label is "Intr(0,19)";
分配中断向量编号后,请点击 Save 按键,以保存控制文件中所修改的内容。
5.
7.6
Clean and Build(清除并编译)该示例,以使新的中断向量编号分配生效。cydwr 窗口中的‘Interrupts’选项卡
下显示了修改后的中断向量编号的分配情况。
Systick 定时器
SysTick 是一个 24 位的递减计数定时器。它的中断通常用于在实时系统中进行任务切换。它使用 Cortex-M0 内部时钟
进行计数。使用下面给出的 API 配置 SysTick:
1. 设置中断处理程序
CyIntSetSysVector(SYSTICK_VECTOR_NUMBER, SysTick_ISR);
SYSTICK_VECTOR_NUMBER 是 SysTick 中断的异常编号,在 Cortex–M0 中是 15。SysTick_ISR 是中断处
理程序。
2.
配置中断周期
(void)SysTick_Config(CLOCK_FREQ / INTERRUPT_FREQ);
CLOCK_FREQ 为 CPU 时钟频率。INTERRUPT_FREQ 是由 SysTick 派生出的中断速率。
下面的内容是 SysTick 定时器用法的代码片段:
#define SYSTICK_INTERRUPT_VECTOR_NUMBER 15u /* Cortex-M0 hard vector */
/* clock and interrupt rates, in Hz */
#define CLOCK_FREQ
24000000u
#define INTERRUPT_FREQ 2u
void main()
{
/* Point the Systick vector to the ISR */
CyIntSetSysVector(SYSTICK_INTERRUPT_VECTOR_NUMBER, SysTick_ISR);
/* Set the number of ticks between interrupts */
(void)SysTick_Config(CLOCK_FREQ / INTERRUPT_FREQ);
/* Enable Global Interrupt */
CyGlobalIntEnable;
for(;;)
{
}
}
CY_ISR(SysTick_ISR)
{
/* Interrupt Handler */
}
www.cypress.com
文档编码:002-11590 版本**
18
PSoC® 4 中断
7.7
中断嵌套
NVIC 会自动处理中断嵌套,不需要任何软件开销。如果在执行优先级低的中断的过程中,有某个优先级更高的中断被
触发,那么将有一些通用寄存器被推入到堆栈内,处理器从 NVIC 读取向量地址,并跳转到优先级更高的中断处理程
序。完成执行后,处理器将恢复寄存器值,并执行优先级低的中断。
8
总结
中断被广泛应用于嵌入式应用中。对于片上系统架构(如 PSoC 4),将片上外设的状态传输给 CPU 时,中断起着关
键作用。通过本应用笔记所提供的信息,可以了解可用的基础设施并创建基于中断的项目。
关于作者
姓名:
Rajiv Badiger
职务:
应用工程师
背景:
获得电子与通信学学士学位
www.cypress.com
文档编码:002-11590 版本**
19
PSoC® 4 中断
A
附录 A – PSoC 4 中的中断源和向量编码
表 6 列出了 PSoC 4 中用于 32 个中断向量的中断源列表。
表 6. PSoC 4 中断源(‘-’表示功能不可用)
固定功能的中断源
DSI 中断源
(不适用于 PSoC
4000)
中断向量编号
PSoC
4000
PSoC
4100/4200
PSoC 4 BLE
PSoC 4 M
PSoC 4 L
GPIO 中断 — 端口 0
DSI
IRQ0
IRQ0
IRQ0
IRQ0
IRQ0
GPIO 中断 — 端口 1
DSI
IRQ1
IRQ1
IRQ1
IRQ1
IRQ1
GPIO 中断 — 端口 2
DSI
IRQ2
IRQ2
IRQ2
IRQ2
IRQ2
GPIO 中断 — 端口 3
DSI
IRQ3
IRQ3
IRQ3
IRQ3
IRQ3
GPIO 中断 — 端口 4
DSI

IRQ4
IRQ4
IRQ4
IRQ4
GPIO 中断 — 端口 5
DSI


IRQ5


GPIO 中断 — 端口 13
(USB 唤醒)
DSI




IRQ5
GPIO 中断 — 所有端口*
DSI


IRQ6
IRQ5
IRQ6

DSI

IRQ5




DSI

IRQ6




DSI

IRQ7



LPCOMP(低功耗比较器)
DSI

IRQ8
IRQ7
IRQ6
IRQ7
WDT(看门狗定时器)
DSI
IRQ4
IRQ9
IRQ8
IRQ7
IRQ8
SCB0(串行通信模块 0)
DSI
IRQ5
IRQ10
IRQ9
IRQ8
IRQ9
SCB1(串行通信模块 1)
DSI

IRQ11
IRQ10
IRQ9
IRQ10
SCB2(串行通信模块 2)
DSI



IRQ10
IRQ11
SCB3(串行通信模块 3)
DSI



IRQ11
IRQ12
CTBm 中断(所有 CTBm)
DSI


IRQ11
IRQ12
IRQ13
BLE 子系统中断
DSI


IRQ12


DMA 中断
DSI



IRQ13
IRQ14
SPCIF 中断
DSI
IRQ6
IRQ12
IRQ13
IRQ14
IRQ15
SRSS LVD 中断
DSI

IRQ13
IRQ14
IRQ15
IRQ16
SAR(逐次逼近 ADC)
DSI

IRQ14
IRQ15
IRQ16
IRQ17
CSD0(CapSense)
DSI
IRQ7
IRQ15
IRQ16
IRQ17
IRQ18
CSD1(CapSense)
DSI



IRQ18
IRQ19
TCPWM0(定时器/计数器/
PWM 0)
DSI
IRQ8
IRQ16
IRQ17
IRQ19
www.cypress.com
文档编码:002-11590 版本**
IRQ20
20
PSoC® 4 中断
固定功能的中断源
DSI 中断源
(不适用于 PSoC
4000)
中断向量编号
PSoC
4000
PSoC
4100/4200
PSoC 4 BLE
PSoC 4 M
IRQ17
IRQ18
IRQ20
IRQ18
IRQ19
IRQ21
IRQ19
IRQ20
IRQ22


PSoC 4 L
TCPWM1(定时器/计数器/
PWM 1)
DSI

TCPWM2(定时器/计数器/
PWM 2)
DSI

TCPWM3(定时器/计数器/
PWM 3)
DSI

TCPWM4(定时器/计数器/
PWM 4)
DSI

TCPWM5(定时器/计数器/
PWM 5)
DSI

TCPWM6(定时器/计数器/
PWM 6)
DSI

TCPWM7(定时器/计数器/
PWM 7)
DSI

CAN0 中断
DSI



IRQ27
IRQ28
CAN1 中断
DSI



IRQ28
IRQ29
USB 的起始帧
DSI




IRQ30
USB EP1-EP8 数据
DSI




IRQ31
DSI

IRQ20
IRQ21
IRQ29


DSI

IRQ21
IRQ22
IRQ30


DSI

IRQ22
IRQ23
IRQ31


DSI

IRQ23
IRQ24



DSI

IRQ24
IRQ25



DSI

IRQ25
IRQ26



DSI

IRQ26
IRQ27



DSI

IRQ27
IRQ28



DSI

IRQ28
IRQ29



DSI

IRQ29
IRQ30



DSI

IRQ30
IRQ31



DSI

IRQ31




www.cypress.com
IRQ23


IRQ24


IRQ25


IRQ26
文档编码:002-11590 版本**
IRQ21
IRQ22
IRQ23
IRQ24
IRQ25
IRQ26
IRQ27
21
PSoC® 4 中断
文档修订记录
®
文档标题:AN90799 – PSoC 4 中断
文档编码:002-11590
版本
ECN
变更者
提交日期
**
5184198
YANS
03/22/2016
www.cypress.com
变更说明
本文档版本号为Rev**,译自英文版 001-90799 Rev*B。
文档编码:002-11590 版本**
22
PSoC® 4 中断
全球销售和设计支持
赛普拉斯公司具有一个由办事处、解决方案中心、厂商代表和经销商组成的全球性网络。要想查找离您最近的办事处,请访问
赛普拉斯所在地。
产品
汽车级产品
cypress.com/go/automotive
PSoC®解决方案
时钟与缓冲区
cypress.com/go/clocks
psoc.cypress.com/solutions
接口
cypress.com/go/interface
PSoC 1 | PSoC 3 | PSoC 4 | PSoC 5LP
照明与电源控制
cypress.com/go/powerpsoc
存储器
cypress.com/go/memory
PSoC
cypress.com/go/psoc
触摸感应
cypress.com/go/touch
USB 控制器
cypress.com/go/usb
无线/射频
cypress.com/go/wireless
赛普拉斯开发者社区
社区 | 论坛| 博客 | 视频 | 培训
技术支持
cypress.com/go/support
PSoC 是赛普拉斯半导体公司的注册商标。此处引用的所有其他商标或注册商标归其各自所有者所有。
赛普拉斯半导体公司
198 Champion Court
San Jose, CA 95134-1709
电话
传真
网址
:408-943-2600
:408-943-4730
:www.cypress.com
© 赛普拉斯半导体公司,2014-2016。此处所包含的信息可随时更改,恕不另行通知。除赛普拉斯产品内嵌的电路外,赛普拉斯半导体公司不对任何其他
电路的使用承担任何责任。也不会根据专利权或其他权利以明示或暗示方式授予任何许可。除非与赛普拉斯签订明确的书面协议,否则赛普拉斯不保证产
品能够用于或适用于医疗、生命支持、救生、关键控制或安全应用领域。此外,对于可能发生运转异常和故障并对用户造成严重伤害的生命支持系统,赛
普拉斯不授权将其产品用作此类系统的关键组件。若将赛普拉斯产品用于生命支持系统中,则表示制造商将承担因此类使用而招致的所有风险,并确保赛
普拉斯免于因此而受到任何指控。
该源代码(软件和/或固件)均归赛普拉斯半导体公司(赛普拉斯)所有,并受全球专利法规(美国和美国以外的专利法规)、美国版权法以及国际条约
规定的保护和约束。赛普拉斯据此向获许可者授予适用于个人的、非独占性、不可转让的许可,用以复制、使用、修改、创建赛普拉斯源代码的派生作
品、编译赛普拉斯源代码和派生作品,并且其目的只能是创建自定义软件和/或固件,以支持获许可者仅将其获得的产品依照适用协议规定的方式与赛普
拉斯集成电路配合使用。除上述指定的用途外,未经赛普拉斯明确的书面许可,不得对此类源代码进行任何复制、修改、转换、编译或演示。
免责声明:赛普拉斯不针对此材料提供任何类型的明示或暗示保证,包括(但不限于)针对特定用途的适销性和适用性的暗示保证。赛普拉斯保留在不做
出通知的情况下对此处所述材料进行更改的权利。赛普拉斯不对此处所述之任何产品或电路的应用或使用承担任何责任。对于发生故障(包括运转异常)
或失效可能会对用户造成严重伤害的生命支持系统,赛普拉斯不授权将其产品用作此类系统的关键组件。若将赛普拉斯产品使用于生命支持系统中,则表
示制造商将承担因此类使用而招致的所有风险,并确保赛普拉斯免于因此而受到任何指控。
产品使用可能受赛普拉斯软件许可协议的限制。
www.cypress.com
文档编码:002-11590 版本**
23
Similar pages