AN90833 PSoC 1 Interrupts.pdf

AN90833
PSoC® 1 Interrupts
Author: Rajiv Badiger, Anshul Gulati
Associated Project: Yes
®
Associated Part Family: All PSoC 1 families
Software Version: PSoC Designer™ 5.4
®
AN90833 introduces you to the PSoC 1 interrupt architecture and interrupt sources. This document also includes
sections on interrupt priority, interrupt latency, and several recommendations on writing efficient and defect-free interrupt
routines.
Contents
Introduction
Introduction .......................................................................1
PSoC 1 Interrupt Architecture ...........................................1
PSoC 1 Interrupt Sources.............................................1
Interrupt Controller .......................................................2
PSoC 1 Interrupt Priority...............................................3
Interrupt Support in PSoC Designer ..................................9
Interrupt Latency ............................................................. 11
Project - Timer_Interrupt ................................................ 13
Tips and Tricks ................................................................ 17
Optimizing the Interrupt Code..................................... 17
Multi-byte Variable Usage .......................................... 17
Nested Interrupts ........................................................ 17
Conditional Loop in ISR .............................................. 18
Summary ......................................................................... 18
Related Application Notes ............................................... 18
Worldwide Sales and Design Support ............................. 20
Interrupts are an important part of any embedded
application because they free the CPU from continuously
polling the occurrence of a specific event. Instead,
interrupts notify the CPU only when that event occurs. In a
®
system-on-chip (SoC) architecture, such as PSoC 1,
interrupts are frequently used to communicate the status
of on-chip peripherals to the CPU.
AN90833 introduces you to the PSoC 1 interrupt
architecture and explains how interrupt service routines
(ISRs) are implemented in PSoC Designer™, the
integrated design environment (IDE) for PSoC 1. An
example project is also provided with this application note.
PSoC 1 Interrupt Architecture
This section gives an overview of the PSoC 1 interrupt
architecture.
Figure 1. Basic PSoC 1 Interrupt Architecture
Interrupt
Sources
{
INT[0]
INT[1]
INT[25]
Interrupt
Controller
CPU
(M8C Core)
Figure 1 shows a simplified view of the PSoC 1 interrupt
architecture. PSoC 1 can have up to 26 interrupt sources.
Each one is assigned a fixed priority and fixed interrupt
vector address. The interrupt controller acts as the
interface between the interrupt lines and the CPU. The
controller sends the interrupt vector address of an interrupt
line to the CPU along with the interrupt request signal.
PSoC 1 Interrupt Sources
Almost every functional block in PSoC 1 has an interrupt
associated with it. Interrupts are available for the following:
www.cypress.com
Document No. 001-90833 Rev. **
1
PSoC® 1 Interrupts
Reset
This is the highest-priority interrupt, and is caused by the
following events:

A logic HIGH signal on the XRES pin

A Watchdog timer overflow event – refer to the
®
application note AN32200 – PSoC 1 Clocks and
Global Resources for details on watch dog timer.

A drop in the VDD below the power-on-reset (POR)
threshold. POR levels are configured based on the
VDD setting. See the DC POR Specifications section
of PSoC 1 Device Datasheet for more details.
Supply Voltage (LVD)
The low-voltage detect (LVD) circuitry in PSoC 1
continuously monitors the VDD of the device. When it drops
below the threshold, it causes an interrupt to the CPU. The
LVD interrupt is disabled by default. When enabled, the
default instruction executed on an LVD interrupt is the
“halt” instruction that halts the CPU. You can change this
default “halt” instruction to execute your own interrupt
handler. You can configure the LVD thresholds in PSoC
Designer with the options in the Global Resources section.
For details on LVD, refer to the LVD Specifications section
of PSoC 1 Device Datasheet and the application note
®
AN32200 – PSoC 1 Clocks and Global Resources.
Analog Column
PSoC 1 has many analog blocks organized in columns. A
column consists of one to three analog blocks. At a time,
one block in an analog column can generate an interrupt
through its comparator output.
Digital Block
Each digital block of PSoC 1 can generate an interrupt.
Depending on the type of function, the interrupt type may
vary. For example, a counter can generate an interrupt
either on compare true or terminal count; a timer on
capture or terminal count; a UART on events such as the
TX buffer empty, TX complete, or RX buffer full. See the
respective User Module Data Sheets for more information
on interrupts associated with specific functions.
VC3 Clock
VC3 is a variable clock that can take its input from VC1 or
VC2, SysClk or SysClk*2, and can have a divider of 1 to
256. This clock can trigger an interrupt on every period,
which can be used for implementing a timer when all the
digital blocks have been used.
GPIO
Each I/O of PSoC 1 can generate an interrupt. However,
all GPIOs share a common interrupt vector. You can
configure each pin to interrupt on the rising edge, falling
edge, or a change from the last read. For more information
®
on GPIOs, refer the application note AN2094 – PSoC 1
Getting Started with GPIO.
www.cypress.com
2
I C
2
PSoC 1 has a maximum of two hardware I C blocks. Each
block can generate interrupts on the following events:

Start or Address byte received

Byte complete

Stop event

Bus Error
2
For more information on I C, see the application note
2
AN50987 - Getting Started with I C in PSoC® 1.
Sleep Timer
This is a 15-bit timer with the clock input set to a 32-kHz
ILO or an external crystal oscillator (ECO). When enabled,
the sleep timer generates periodic interrupts with a
frequency configurable to 1, 8, 64, or 512 Hz. For details
on how to use sleep timer, see the application note,
AN47310 - PSoC® 1 Power Savings Using Sleep Mode.
Interrupt Controller
The interrupt controller takes the interrupt signals as
inputs and triggers the CPU with a request signal and a
corresponding vector address when any enabled interrupt
becomes active. Figure 2 shows the block diagram of the
interrupt controller. Here’s how the interrupt mechanism
works:
1. A rising-edge signal at the interrupt line “posts”
an interrupt.
2. If this interrupt is enabled, it is tagged as a
“pending”.
3. A priority encoder scans the pending interrupts
and selects the one with the highest priority.
4. If the global interrupt is enabled, the priority
encoder forwards the vector address of the
selected interrupt with a request signal to the
CPU.
5. The CPU finishes the instruction currently in
execution, and then pushes the program counter
(PC) and flag register (CPU_F) to the stack.
6. CPU_F is then cleared by CPU which disables
the global interrupt, thereby blocking any other
interrupt request.
7. The vector address from the interrupt controller is
loaded onto the PC. The CPU jumps to execute
the interrupt service routine (ISR) written at the
vector address. The posted and pending states of
this interrupt are cleared.
8. At the end of the ISR, the return from interrupt
(RETI) instruction restores the PC and CPU_F
register. This re-enables the global interrupt.
9. If there are any other pending interrupts, the
priority encoder again sends the vector address
of the highest-priority interrupt that is pending
with a request signal to the CPU, and the process
repeats.
Document No. 001-90833 Rev. **
2
PSoC® 1 Interrupts
Figure 2. Interrupt Controller
Posted
Interrupt
INT[0]
Pending
Interrupt
INT[1]
0
1
D
Q
INT[n]
R
Interrupt
Sources
INT_CLR
Vector
address
INT_MSK
Interrupt
Request
CPU
(M8C Core)
CPU_F[0]
Global Interrupt
Enable
INT[25]
Interrupt Controller
25
(max)
Priority
Encoder
A particular interrupt can be disabled by writing into the Interrupt Mask register, INT_MSKx. There are four mask registers:
INT_MSK0, INT_MSK1, INT_MSK2, and INT_MSK3. Each bit in these registers enables or disables a particular interrupt. For
example, as shown in Figure 3, in INT_MSK1, bit 0 corresponds to the digital block DBB00. Writing a logic 1 to this bit enables
the DBB00 interrupt. However, when disabled by writing 0 to this bit, an interrupt signal from DBB00 can still post the interrupt,
but it will not be executed. A posted interrupt can be cleared by writing into the Interrupt Clear register, INT_CLRx. Like the
INT_MSK mask registers, there are four INT_CLR registers. Each bit in these registers clears a particular posted interrupt
when written with a logic 0. Figure 4 shows the INT_CLR1 register. Notice the 1-to-1 correspondence with the INT_MSK1
register. Reading the INT_CLR register returns the status of the posted interrupts – a logic 1 indicates that the interrupt is
posted. When a logic 0 is written to a particular bit and if the bit has a posted interrupt, then the posted interrupt is cleared.
When a 1 is written to a particular bit, and if the ENSWINT (Enable Software Interrupt) in INT_MSK3 is enabled, this will result
in the interrupt getting posted. If the ENSWINT bit is not set, then writing a 1 to a bit does not have any effect.
Figure 3. INT_MSK1 Interrupt Mask Register
Figure 4. INT_CLR1 Interrupt Clear Register
To clear all pending interrupts, use the INT_VC register. Writing any value to this register clears all the posted and pending
interrupts. Reading this register returns the address of the next highest-priority interrupt that is pending. This helps to know the
other pending interrupts while executing a specific ISR.
All interrupts can be controlled by a Global Interrupt Enable (GIE) bit in the CPU_F register. Setting this bit to 1, enables all the
interrupts. However, individual interrupts can still be controlled using the INT_MSKx register.
For details on these registers, refer to the Technical Reference Manual of the PSoC 1 device.
PSoC 1 Interrupt Priority
PSoC 1 has interrupt sources with fixed vector addresses and priorities. As Table 1 and Table 2 shows, Reset (watchdog timer
reset or external reset) has the highest priority, followed by LVD, configurable analog blocks, VC3 clock, GPIOs, configurable
2
digital blocks, I C, and Sleep Timer. Many times, it becomes essential to keep some interrupts with the priority higher than the
others. Even with fixed priority interrupts in PSoC 1, you can get the required priority among the digital blocks and analog
blocks. The interrupt priority in the analog section depends on the column being used; interrupt from analog column 0 has the
highest priority. In the digital section, a user module placed in the left-most and highest block has the highest priority, as Figure
5 shows. Place the user modules so that it occupies blocks of a particular priority.
www.cypress.com
Document No. 001-90833 Rev. **
3
PSoC® 1 Interrupts
Interrupt
Vector #
Interrupt
Address
CY8C29X66
CY8C27X43
CY8C24x94
CY8C24x23
CY8C24x23A
CY8C22x13
CY8C21x34
CY8C21x23
CY8C22x45
CY8C21345
Table 1. Device Interrupts for PSoC 1 Devices Except CY8C28xxx
0
(Highest
Priority)
0000h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
Reset
1
0004h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
Supply Voltage Monitor (LVD)
2
0008h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Analog Column 0
3
000Ch
Y
Y
Y
Y
Y
Y
Y
Y
Y
Analog Column 1
4
0010h
Y
Y
Y
Y
Analog Column 2
5
0014h
Y
Y
Y
Y
Analog Column 3
6
0018h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
VC3
7
001Ch
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
GPIO
8
0020h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
PSoC Block DBB00
9
0024h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
PSoC Block DBB01
10
0028h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
PSoC Block DCB02
11
002Ch
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
PSoC Block DCB03
12
0030h
Y
Y
Y
PSoC Block DBB10
13
0034h
Y
Y
Y
PSoC Block DBB11
14
0038h
Y
Y
Y
PSoC Block DCB12
15
003Ch
Y
Y
Y
PSoC Block DCB13
16
0040h
Y
17
0044h
Y
18
00048h
Y
19
004Ch
Y
20
0050h
Y
21
0054h
Y
22
0058h
Y
23
005Ch
Y
24
0060h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
I2C
25
(Lowest
Priority)
0064h
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
Sleep Timer
www.cypress.com
Y
USB Bus
Reset
USB Start
of
Frame
USB
Endpoint 0
USB
Endpoint 1
USB
Endpoint 2
USB
Endpoint 3
USB
Endpoint 4
USB
Wakeup
Interrupt
PSoC Block DBB20
PSoC Block DBB21
PSoC Block DCB22
PSoC Block DCB23
Document No. 001-90833 Rev. **
Y
PSoC Block DBB30/
SARADC
Y
PSoC Block DBB31/ CSD0
Y
PSoC Block DCB32/ CSD1
Y
PSoC Block DCB33/ RTC
4
PSoC® 1 Interrupts
Interrupt
Vector #
Interrupt
Address
CY8C28x03
CY8C28x13
CY8C28x23
CY8C28x33
CY8C28x43
CY8C28x45
CY8C28x52
Table 2. Device Interrupts for CY8C28xxx
0
(Highest
Priority)
0000h
Y
Y
Y
Y
Y
Y
Y
Reset
1
0004h
Y
Y
Y
Y
Y
Y
Y
Supply Voltage Monitor (LVD)
2
0008h
Y
Y
Y
Y
Y
Analog Column 0/ Decimator 0
3
000Ch
Y
Y
Y
Y
Y
Analog Column 1/ Decimator 1
4
0010h
Y
Y
Y
Analog Column 2/ Decimator 2
5
0014h
Y
Y
Y
Analog Column 3/ Decimator 3
6
0018h
Y
Y
Y
Y
Y
Y
Y
VC3
7
001Ch
Y
Y
Y
Y
Y
Y
Y
GPIO
8
0020h
Y
Y
Y
Y
Y
Y
Y
PSoC Block DBC00
9
0024h
Y
Y
Y
Y
Y
Y
Y
PSoC Block DBC01
10
0028h
Y
Y
Y
Y
Y
Y
Y
PSoC Block DCC02
11
002Ch
Y
Y
Y
Y
Y
Y
Y
PSoC Block DCC03
12
0030h
Y
Y
Y
Y
Y
Y
Y
PSoC Block DBC10
13
0034h
Y
Y
Y
Y
Y
Y
Y
PSoC Block DBC11
14
0038h
Y
Y
Y
Y
Y
Y
Y
PSoC Block DCC12
15
003Ch
Y
Y
Y
Y
Y
Y
Y
PSoC Block DCC13
16
0040h
Y
Y
Y
Y
Y
Y
PSoC Block DBC20
17
0044h
Y
Y
Y
Y
Y
Y
PSoC Block DBC21
18
00048h
Y
Y
Y
Y
Y
Y
PSoC Block DCC22
19
004Ch
Y
Y
Y
Y
Y
Y
PSoC Block DCC23
20
0050h
Reserved
21
0054h
Reserved
22
0058h
Reserved
23
005Ch
Reserved
24
0060h
Y
25
0064h
Y
26
0068h
Y
Y
27
006Ch
Y
Y
28
0070h
Y
29
0074h
Y
30
0078h
31
(Lowest
Priority)
007Ch
www.cypress.com
Y
Y
Y
Y
Y
Y
I2C1
Y
Y
Y
SAR ADC
Y
Y
Y
Y
RTC
Y
Y
Y
Analog Column 4
Y
Y
Y
Analog Column 5
Y
Y
Y
I2C0
Y
Reserved
Y
Y
Y
Y
Y
Y
Document No. 001-90833 Rev. **
Y
Sleep Timer
5
PSoC® 1 Interrupts
Figure 5. Interrupt Priority for Digital and Analog Blocks
Highest
Priority
Block
Digital
Section
Lowest
Priority
Block
Analog
Section
Highest
Priority
Column
www.cypress.com
Lowest
Priority
Column
Document No. 001-90833 Rev. **
6
PSoC® 1 Interrupts
For example, if you have two comparator user modules (UM) in the analog section (COMP_1 and COMP_2), and if you want
COMP_1 to be of higher priority than COMP_2, then place COMP_1 in the column to the left side of COMP_2 as Figure 6
shows.
Figure 6. PSoC Designer Project Showing the Placement of Two Comparators With the Interrupt Priority of COMP_1 Higher
Than That of COMP_2
If you have an analog-to-digital converter UM (ADCINC) and timer UM (Timer8) in your design, to have the ADCINC interrupt
priority higher than that of the timer interrupt, place the ADCINC UM in DBB00 and the Timer8 user module in DBB01, as
Figure 7 shows.
Figure 7. PSoC Designer Project Showing the Placement of ADCINC and Timer8 with Interrupt Priority of ADCINC Higher
Than That of Timer8
www.cypress.com
Document No. 001-90833 Rev. **
7
PSoC® 1 Interrupts
Vectors are listed in the boot.asm file, which is automatically added to the PSoC Designer project when it is generated. With
the placement as shown Figure 6 and Figure 7, the interrupt priorities can be seen in Figure 8. Modules with higher priority
are placed higher in the order.
Figure 8. Boot.asm File Contents Showing the Vectors Assigned for Each Interrupt
www.cypress.com
Document No. 001-90833 Rev. **
8
PSoC® 1 Interrupts
useful application. With a jump instruction
consuming 3 bytes, a custom ISR code can be
written somewhere else in the flash. For the UMs,
the ISR is written in the associated interrupt
source file.
Interrupt Support in PSoC Designer
The boot.asm file of a project has the code for interrupt
vectors. It is generated whenever a “Generate Source”
operation of the project is performed in PSoC Designer.
Depending on the UMs placed, PSoC Designer performs
the following related to interrupts:
1.
2.
Generates the interrupt source file associated
with the UM
Note that PSoC Designer does not generate source files
for interrupt sources such as analog columns, LVD, and
VC3. You should add the jump instruction manually to
jump to a custom ISR.
The boot.asm code and the sample interrupt source file for
a Timer8 UM (Timer8INT.asm) are shown in Figure 9.
Inserts an ljmp instruction in the vector location
in the boot.asm file to jump to the function in the
generated interrupt source file. This is done as
there are only four bytes available between the
vector locations and is not sufficient for any
Figure 9. Interrupt Source File
Chip Editor
Boot.asm file
Timer Interrupt source file
On Project
Generation
As Figure 9 shows, the PSoC Designer assembly
instruction ljmp _Timer8_ISR is inserted at the vector
location 24h (depending on the placement of the Timer8
module). The assembly function _Timer8_ISR is in the
interrupt source file Timer8INT.asm associated with the
user module. You can write the custom assembly code or
call a custom ‘C’ function from _Timer8_ISR. Make sure
that you uncomment the code PRESERVE_CPU_CONTEXT
and RESTORE_CPU_CONTEXT while calling a ‘C’ function
from the ISR. The PRESERVE_CPU_CONTEXT macro
saves the accumulator register value, all virtual registers,
and page pointers (current page pointer CUR_PP, Indexed
Memory Access page pointer IDX_PP, MVI Read page
pointer MVR_PP, and MVI Write page pointer MVW_PP) in
the stack. The RESTORE_CPU_CONTEXT
function
www.cypress.com
restores these register values. Thus, a CPU state is
maintained to what it was executing earlier before
branching to an ISR. Note that here a Timer8 example is
taken, but the same is applicable for other user modules.
The use of PRESERVE and RESTORE macros, however,
results in a lot of CPU overhead and flash and stack
consumption. It consumes around 190 CPU cycles, 59
bytes of flash, and 20 bytes of stack space. If you are
planning to write a ‘C’ ISR, it is recommended to use the
#pragma interrupt_handler compiler directive.
Follow the steps given below to write a ‘C’ ISR:
1.
Write a C function ISR with a name such as
MyTimerInt.
Document No. 001-90833 Rev. **
9
PSoC® 1 Interrupts
2.
Add the
#pragma directive to inform the
compiler that MyTimerInt is an interrupt
handler:
Figure 10. Boot.tpl file Directory
#pragma interrupt_handler MyTimerInt
void MyTimerInt(void)
{
//handler code
}
The #pragma interrupt_handler directive
inserts instructions at the beginning of an ISR to
save only the used virtual registers, accumulator
register, and page pointers in the stack. It also
inserts a RETI (return from interrupt) instruction
at the end of the ISR instead of a RET
instruction. This restores the CPU_F register
status to the state before the ISR execution.
Adding the #pragma directive moves only the
selected registers to stack, thus reducing the
CPU overhead and memory usage as compared
to using the PRESERVE and RESTORE macros.
3.
Link this function with the interrupt vector. As
Interrupt vectors are listed in the boot.asm file,
you add the ljmp instruction in this file to make
the CPU jump to the ‘C’ function on interrupt.
Note that the boot.asm file is overwritten every
time “Generate Source” operation is performed.
To avoid this, modify the boot.tpl file of the
project. This is a template file and PSoC
Designer uses this file to generate the boot.asm
file. The boot.tpl file is present in the project
directory. Go to File > Open File menu option.
Window will open as Figure 10 shows. Clear the
filter to display all the files. Select the boot.tpl file
and click the Open button as Figure 11 shows.
4.
Add the ljmp instruction at the vector location in
the boot.tpl file. To know the vector location, use
the comments in the boot.tpl file, which mentions
the block number. Figure 12 shows an example
with Timer8 UM placed at DBB01 block. When a
timer interrupt occurs, the CPU will first land at
the location 24h and it will then be redirected to
the ‘C’ function MyTimerInt. Make sure that you
precede the function name with an underscore
‘_’. Every function or variable declared in ‘C’
when called from an asm file must begin with an
underscore.
www.cypress.com
Figure 11. Boot.tpl file Selection
Figure 12. Adding the ljmp Instruction in the boot.tpl File
Document No. 001-90833 Rev. **
10
PSoC® 1 Interrupts
In
most
cases,
you
won’t
need
the
M8C_EnableIntMask and M8C_DisableIntMask
macros as the user modules provide the
EnableInt() and DisableInt() APIs to enable
or disable the interrupt, which is easier than working
with macros. However, the macros have some
advantage over the APIs: APIs are executed using a
call and therefore take longer time to execute than the
macros.
I n t e r r u p t AP I s a n d M a c r o s A va i l a b l e i n
PSoC Designer
The source and header files generated for the user
modules provide the following APIs to enable or disable
the interrupts:

<User Module Name>_EnableInt()enabling the interrupt.

<User Module Name>_DisableInt() - API for
disabling the interrupt.
API for
There are macros defined in the m8c.h file that you can
use to enable or disable interrupt masks, clear the
interrupt flags, and so on. The following macros are
available:

M8C_EnableGInt – Macro for enabling the global
interrupt.

M8C_DisableGInt – Macro for disabling the global
interrupt.

M8C_EnableIntMask – Macro for enabling the
interrupt mask by configuring the register INT_MSKx.
The inputs required for this macro are registers
INT_MSKx and MASK. INT_MSKx stands for the
registers INT_MSK0, INT_MSK1, INT_MSK2, or
INT_MSK3; MASK is the pointer to the bit field in the
mask register. The name of the bit masks can be
found in the m8c.h header file. Some examples follow:
M8C_ClearIntFlag – Macro for clearing the
interrupt flag by writing into the INT_CLRx register.
The inputs required for this macro are INT_CLRx and
MASK. INT_CLRx stands for the registers INT_CLR0,
INT_CLR1, INT_CLR2, or INT_CLR3; MASK is the
pointer to the bit field in the INT_CLR register. For
example:
/* Clear GPIO Interrupt flag */
M8C_ClearIntFlag(INT_CLR0, INT_MSK0_GPIO);
/* Clear Sleep Interrupt flag */
M8C_ClearIntFlag(INT_CLR0, INT_MSK0_SLEEP);
/* Clear DBB00 Interrupt flag */
M8C_ClearIntFlag(INT_CLR1, INT_MSK1_DBB00);
/* Clear I2C Interrupt flag */
M8C_ClearIntFlag(INT_CLR3, INT_MSK3_I2C);
/* Enable DBB00 Interrupt mask */
M8C_EnableIntMask(INT_MSK1, INT_MSK1_DBB00);
Important Note: The software interrupt should be disabled
while using the macro M8C_ClearIntFlag. Software
interrupt is controlled by the ENSWINT bit in the
INT_MSK3 register; it is disabled by default (ENSWINT is
logic 0). If software interrupt is enabled, executing the
macro M8C_ClearIntFlag will result in seven bits of the
INT_CLR register to be set to logic 1, thus triggering
seven software interrupts.
/* Enable I2C Interrupt mask */
M8C_EnableIntMask(INT_MSK3, INT_MSK3_I2C);
Interrupt Latency
M8C_DisableIntMask – Macro for disabling the
interrupt mask by configuring the register INT_MSKx.
The inputs required are INT_MSKx and MASK.
INT_MSKx stands for the registers INT_MSK0,
INT_MSK1, INT_MSK2, or INT_MSK3; MASK is the
bit-field in the mask register. For example:
The assertion of an interrupt results in the following:
/* Enable GPIO Interrupt mask */
M8C_EnableIntMask(INT_MSK0, INT_MSK0_GPIO);
/* Enable Sleep Interrupt mask */
M8C_EnableIntMask(INT_MSK0, INT_MSK0_SLEEP);


/* Disable GPIO Interrupt mask */
M8C_DisableIntMask(INT_MSK0, INT_MSK0_GPIO);
/* Disable Sleep Interrupt mask */
M8C_DisableIntMask(INT_MSK0, INT_MSK0_SLEEP);
/* Disable DBB00 Interrupt mask */
M8C_DisableIntMask(INT_MSK1, INT_MSK1_DBB00);
/* Disable I2C Interrupt mask */
M8C_DisableIntMask(INT_MSK3, INT_MSK3_I2C);
www.cypress.com

Saving of the PC and CPU_F registers in the
stack

Clearing of the CPU_F register

Loading the vector address of an interrupt in the
PC
These three actions are completed in 13 CPU cycles.
Apart from this, the CPU needs to complete the execution
of the current instruction in hand (in the worst case, five
cycles) and execute the ljmp instruction at the vector
location (seven cycles) as mentioned in the section
Interrupt Support in PSoC Designer. Thus, it takes 13 + 5
+ 7 = 25 CPU cycles. At 24 MHz CPU frequency, it takes
1.04µs; at 12 MHz, it takes 2.08µs.
Document No. 001-90833 Rev. **
11
PSoC® 1 Interrupts
Note that there is additional overhead of preserving the
virtual registers, accumulator, and page pointer registers.
The time taken for these actions varies from project to
project, depending on whether the registers are in use or
not. You can check the instructions added in the beginning
of an ISR in list file (<project name>.lst) of the project.
Figure 13 shows an example ISR from the .lst file.
Figure 13. CPU Cycles Overhead in ISR
Configures Addressing Mode
Save Accumulator in Stack
}
}
}
Save Current Page Pointer in Stack
Save MVI Read Page Pointer in Stack
Save MVI Write Page Pointer in Stack
Set current page pointer to page 0 of RAM
Save Virtual Registers r0, r1, r2 and r3 in Stack
User Code
As Figure 13 shows, the compiler adds instructions to save the accumulator, page pointers, and virtual registers in the stack.
The execution of these instructions adds to the interrupt latency. Remember, this is the minimum latency when no other
interrupts are enabled. When there are multiple interrupts enabled in a project, calculation of interrupt latency is much more
complex. For example, if an interrupt is triggered when another interrupt routine is already being executed, the processor has
to complete the execution of the current interrupt routine first before servicing the new interrupt. If another interrupt with a
higher priority is posted meanwhile, the processor would then execute the next highest priority interrupt before servicing the
lower priority one.
www.cypress.com
Document No. 001-90833 Rev. **
12
PSoC® 1 Interrupts
Figure 14. Creating a PSoC Designer Project
Project - Timer_Interrupt
This section shows you how to create a simple interruptbased project in PSoC Designer. With this code example,
you will learn how to configure a timer interrupt and link a
‘C’ function to its vector.
In this code example, an LED connected at port P1[7] is
toggled when a timer overflows. The code to toggle the
LED state is written in the timer ISR. The timer interrupt
frequency is configured as 1 Hz.
Use the following steps to create the project:
1.
Create a PSoC Designer project (File > New Project)
and name it Timer_Interrupt, as shown in Figure 14 .
2.
Select the part number for the device and the
preference of coding language for the main program
file. For this project, CY8C29466-24PXI is selected;
thus, project can be easily tested on CY3210PSoCEval1 kit. Select ‘C’ language for coding, as
Figure 14 shows. After you have made all the
changes, click OK. The Chip Editor view of PSoC
Designer will open as Figure 15 shows.
Figure 15. PSoC Designer
Global
Resources
Workspace
Explorer
UM Parameter
Configuration Window
CHIP EDITOR
Pin Configuration Window
www.cypress.com
User Module
Catalog
Document No. 001-90833 Rev. **
13
PSoC® 1 Interrupts
3.
Select View > User Module Catalog to display the
User Module Catalog, and then expand the Misc
Digital folder. Locate the LED User Module, rightclick on it, and select Place as Figure 16 shows. This
UM will be used to drive the external LED.
Figure 18. LED User Module Parameters
Figure 16. LED User Module Placement
The drive mode of the pin P1_7 is automatically set to
strong mode by the UM. You can verify this in the Pin
Configuration window as Figure 19 shows.
Figure 19. Port_1_7 Parameters
4.
Expand the workspace explorer as Figure 17 shows.
Click on LED_1 to configure the user module
properties. After clicking on LED_1, on the left-hand
side of PSoC Designer, the parameters window
allows you to edit the LED’s properties.
6.
Select and place the 32-bit timer user module
(Timer32) from the User Module Catalog as shown in
Figure 20.
Figure 17. Selecting LED_1 UM to Configuring the
Parameters
Figure 20. Timer32 UM Placement
7.
Configure the input clock and the period of the timer
to get the required interrupt frequency. Select the
system clock of 24 MHz as the timer input. To get a
1-Hz timer input interrupt frequency, the required
period is 24 MHz / 1 Hz = 24000000 (0x016E3600).
Figure 21. Timer32_1 Parameter Configuration
5.
Configure the port and pin of LED_1 UM to “Port_1”
and “Port_1_7”, respectively, as Figure 18 shows.
www.cypress.com
Document No. 001-90833 Rev. **
14
PSoC® 1 Interrupts
Set the Period parameter to 24000000, Interrupt
Type to Terminal Count and Clock Sync to Use
SysClk Direct. This Clock Sync option overrides the
Clock parameter and uses System Clock as the input
to the timer. Other settings do not affect the project
operation.
8.
After the user modules are placed and configured,
generate the configuration files for the project. Select
Build > Generate Configuration Files for
‘Timer_Interrupt’ Project as shown in Figure 22 (or,
press [Ctrl] + [F6]).
Figure 22. Generate Configuration Files
section Interrupt Support in PSoC Designer. You can
write the assembly code inside the timer interrupt
source file (Timer32_1INT.asm) or write a ‘C’ function
and link it to the timer interrupt. This example project
uses the ‘C’ function. Add the code below in the
main.c file. This code is executed at the frequency of
1 Hz.
#pragma interrupt_handler Timer_ISR
/* Timer ISR in C where timer
interrupts are processed */
void Timer_ISR(void)
{
/* Toggle LED */
LED_1_Invert();
}
Map the Timer_ISR function to the Timer32_1
Interrupt vector in the boot.tpl file as explained in the
section Interrupt Support in PSoC Designer. Figure 23
shows the boot.tpl file. Notice that the interrupt vector
is for the “most significant byte” block out of four
blocks used by the Timer32 user module.
9.
In the main.c file, start the timer and enable its
interrupt and the global interrupt. Go to Workspace
Explorer, locate the Source Files folder and open the
main.c file. In this file, place the following source
code.
/* Part specific constants and macros
*/
#include <m8c.h>
Make sure that the function name begins with an
underscore (“_“) because it is a ‘C’ function. Every
function or variable declared in ‘C’ when called from a
.asm file must begin with an “_”.
Figure 23. boot.tpl File Showing the Mapping of
Timer_ISR
/* PSoC API definitions for all User
Modules */
#include "PSoCAPI.h"
void main(void)
{
/* Enable Global Interrupt */
M8C_EnableGInt;
/* Start the Timer */
Timer32_1_Start();
/* Enable Timer Interrupt. This
library function writes into
INT_MSK0 register */
Timer32_1_EnableInt();
10. Now, build and generate the project. Select Build >
Generate/Build ‘Timer_Interrupt’ Project as shown
in Figure 24 (or, press [F6]).
while(1);
}
Write the code in the timer ISR to toggle the LED
state. In PSoC Designer, most of the ISRs are
implemented as a part of the user module library.
There are two ways of writing the ISR as described in
www.cypress.com
Document No. 001-90833 Rev. **
15
PSoC® 1 Interrupts
Figure 24. Build and Generate Option
Place a wire connecting P1[7] to LED1 as Figure 27
shows.
Figure 27. CY3210-PSoCEval1 Pin Connections
Test Procedure
This section provides the procedure to test the project with
the CY3210 – PSoCEval1 kit. To test it on any other
development platform, make the connections as given in
Figure 25.
Figure 25. External Connections
Power the device from MiniProg1 or MiniProg3 by
clicking on the Toggle Power button as Figure 28
shows.
Figure 28. Power and Program Connections
PSoC
CY8C29466-24PXI
To MiniProg1
/Miniprog3
VDD
28
GND
14
XRES
19
SCL/P1[1]
SDA/P1[0]
13
10
P1[7]
15
After the build process is completed without warnings or
errors, the next step is to program the device. Connect the
MiniProg1 or MiniProg3 programmer between your PC
and CY3210-PSoCEval1. Ensure that a CY8C2946624PXI is the device currently on the board. In
PSoC Designer, locate Program in the menu bar and click
on the Program Part button.
Figure 26. Programming Status
Notice that LED1 blinks at 0.5 Hz rate, that is, half the
timer interrupt frequency.
www.cypress.com
Document No. 001-90833 Rev. **
16
PSoC® 1 Interrupts
Tips and Tricks
Optimizing the Interrupt Code
An important performance parameter in interrupt-based
applications is the ISR code execution time. In some
applications, the critical code in the ISR must be serviced
within a particular time of receiving the interrupt request. In
some other applications, interrupt execution should not
take long because it could stall the main code execution or
other interrupts. Follow the guidelines below when writing
the ISR code to meet these requirements:
Avoiding function calls in the ISR
When function calls are made inside a ‘C’ ISR defined as
#pragma interrupt_handler, the compiler preserves
and restores the virtual registers, page pointers, and
accumulator, which results in a large execution time
overhead and high risk of stack overflow. Avoid making
function calls in an ISR. The recommended technique is to
move the non-critical function calls to the main code by
setting a flag variable in the ISR. Then, periodically check
the flag in the main code.
Assigning proper priority to the interrupts
among digital and analog blocks
In applications that have multiple interrupts, place those
interrupts that require time-critical servicing, at blocks that
have a higher priority associated with it.
Multi-byte Variable Usage
Accessing multi-byte global variables in an 8-bit system
requires careful attention because multi-byte variables are
read byte-by-byte. Make sure that the ISR is not triggered
and, therefore, modify the variable when one or more
bytes of the multi-byte variable have already been read
but the read has not been completed. This would lead to
data corruption. The following example illustrates this
scenario:
Case 1
void main()
{
unsigned int localData;
/* code */
while (1)
{
localData = data;
/* code */
}
}
void TEST_ISR(void)
{
data = BUF[0];
data = (data<<8)|(BUF[1]);
}
www.cypress.com
An 8-bit system like PSoC 1 splits the 16-bit operation
into two 8-bit operations. In PSoC 1, for a 16-bit move
instruction (localData = data), first the MSB is moved,
followed by the LSB. If the interrupt “TEST_ISR”
occurs after moving the MSB but before the LSB and
at the end of the execution of move instruction,
variable localData will have old MSB and new LSB. To
avoid this problem, disable the global interrupt before
executing the move instruction and re-enable it after
completing the move instruction. This causes the
interrupt to remain in pending state until the global
interrupt is re-enabled.
Case 2
unsigned int data;
void main()
{
unsigned int localData;
/* code */
while (1)
{
M8C_DisableGInt;
localData = data;
M8C_EnableGInt;
/* code */
}
}
void TEST_ISR(void)
{
data = BUF[0];
data = (data<<8)|(BUF[1]);
}
Nested Interrupts
In PSoC 1, the global interrupt is disabled during the
service of an interrupt, thereby disabling the CPU from
jumping to another ISR. To enable execution of another
interrupt while executing an ISR, enable the global
interrupt. Note that priority of the new interrupt is not
considered while branching.
The following code gives an example of enabling the
nested interrupt with two timer interrupts. Global interrupt
is enabled in Timer2_ISR. If the CPU is currently
executing Timer2_ISR and if the Timer1 interrupt occurs,
the CPU branches to execute Timer1_ISR. After
completion, the CPU returns to complete the execution of
Timer2_ISR.
Document No. 001-90833 Rev. **
17
PSoC® 1 Interrupts
void main(void)
{
/* Start Timers */
Timer8_1_Start();
Timer8_2_Start();
The ADC in PSoC 1 (except SAR ADC) requires CPU in
processing the reading. It is done with interrupts. As the
global interrupt is disabled while servicing an ISR, the
ADC interrupt is never executed during this period. If an
attempt is made to check the status of ADC with a
blocking statement, the CPU will remain permanently
stuck. It is recommended to put an “if” statement, instead
of a loop “while” statement, to avoid blocking.
/* Enable Timer Interrupts */
Timer8_1_EnableInt();
Timer8_2_EnableInt();
/* Enable Global Interrupt */
M8C_EnableGInt;
Summary
while (1);
Interrupts are commonly used in embedded applications.
For system-on-chip architectures, such as those of PSoC
1, interrupts play the critical role of communicating the
status of on-chip peripherals to the CPU. This application
note has provided the information needed to quickly and
easily create interrupt-based PSoC Designer projects.
}
#pragma interrupt_handler Timer1_ISR
void Timer1_ISR(void)
{
//code
}
#pragma interrupt_handler Timer2_ISR
void Timer2_ISR(void)
{
/* Enable Global Interrupt to
allow nested interrupts */
M8C_EnableGInt;
About the Author
//code
}
There is a risk of stack overflow when working with nested
interrupts. PSoC 1 CY3215A-DK In-Circuit-Emulation
(ICE) Lite Development Kit can be used to verify the risk of
stack overflow. Refer to the application note AN73212 –
Debugging with PSoC 1 for more details.
Conditional Loop in ISR
In some applications, a conditional loop in an ISR can
cause the CPU to get stuck. Here is an example in an
ADC application:
Name:
Rajiv Badiger
Title:
Applications Engineer Staff
Background:
Rajiv Badiger holds a Bachelor’s
degree
in
Electronics
and
Communications Engineering from
Nagpur University, India. He has 6
years of experience in embedded
systems design.
Contact:
[email protected]
Related Application Notes
AN75320 – Getting Started with PSoC 1
AN2094 – PSoC 1 Getting Started with GPIO
AN73212 – Debugging with PSoC 1
#pragma interrupt_handler Timer1_ISR
void Timer1_ISR(void)
{
unsigned int Value;
®
AN32200 – PSoC 1 Clocks and Global Resources
AN47310 – PSoC ® 1 Power Savings Using Sleep Mode
/* Check if ADC data is available. As
this function is written in an ISR,
if no previous ADC data is available,
CPU will never come out of this loop
*/
while(!ADCINC_1_fIsDataAvailable());
/* Read ADC Data */
Value = ADCINC_1_iClearFlagGetData();
}
www.cypress.com
Document No. 001-90833 Rev. **
18
PSoC® 1 Interrupts
Document History
®
Document Title: PSoC 1 Interrupts – AN90833
Document Number: 001-90833
Revision
**
ECN
4250789
www.cypress.com
Orig. of
Change
RJVB
Submission
Date
01/28/2014
Description of Change
New Application Note
Document No. 001-90833 Rev. **
19
PSoC® 1 Interrupts
Worldwide Sales and Design Support
Cypress maintains a worldwide network of offices, solution centers, manufacturer’s representatives, and distributors. To find
the office closest to you, visit us at Cypress Locations.
Products
PSoC® Solutions
Automotive
cypress.com/go/automotive
Clocks & Buffers
cypress.com/go/clocks
Interface
cypress.com/go/interface
Lighting & Power Control
cypress.com/go/powerpsoc
cypress.com/go/plc
Memory
cypress.com/go/memory
PSoC
cypress.com/go/psoc
Touch Sensing
cypress.com/go/touch
Technical Support
USB Controllers
cypress.com/go/usb
cypress.com/go/support
Wireless/RF
cypress.com/go/wireless
psoc.cypress.com/solutions
PSoC 1 | PSoC 3 | PSoC 4 | PSoC 5LP
Cypress Developer Community
Community | Forums | Blogs | Video | Training
PSoC is a registered trademark of Cypress Semiconductor Corp. All other trademarks or registered trademarks referenced herein are the property of
their respective owners.
Cypress Semiconductor
198 Champion Court
San Jose, CA 95134-1709
Phone
Fax
Website
: 408-943-2600
: 408-943-4730
: www.cypress.com
© Cypress Semiconductor Corporation, 2014. The information contained herein is subject to change without notice. Cypress Semiconductor
Corporation assumes no responsibility for the use of any circuitry other than circuitry embodied in a Cypress product. Nor does it convey or imply any
license under patent or other rights. Cypress products are not warranted nor intended to be used for medical, life support, life saving, critical control or
safety applications, unless pursuant to an express written agreement with Cypress. Furthermore, Cypress does not authorize its products for use as
critical components in life-support systems where a malfunction or failure may reasonably be expected to result in significant injury to the user. The
inclusion of Cypress products in life-support systems application implies that the manufacturer assumes all risk of such use and in doing so indemnifies
Cypress against all charges.
This Source Code (software and/or firmware) is owned by Cypress Semiconductor Corporation (Cypress) and is protected by and subject to worldwide
patent protection (United States and foreign), United States copyright laws and international treaty provisions. Cypress hereby grants to licensee a
personal, non-exclusive, non-transferable license to copy, use, modify, create derivative works of, and compile the Cypress Source Code and derivative
works for the sole purpose of creating custom software and or firmware in support of licensee product to be used only in conjunction with a Cypress
integrated circuit as specified in the applicable agreement. Any reproduction, modification, translation, compilation, or representation of this Source
Code except as specified above is prohibited without the express written permission of Cypress.
Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS MATERIAL, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress reserves the
right to make changes without further notice to the materials described herein. Cypress does not assume any liability arising out of the application or
use of any product or circuit described herein. Cypress does not authorize its products for use as critical components in life-support systems where a
malfunction or failure may reasonably be expected to result in significant injury to the user. The inclusion of Cypress’ product in a life-support systems
application implies that the manufacturer assumes all risk of such use and in doing so indemnifies Cypress against all charges.
Use may be limited by and subject to the applicable Cypress software license agreement.
www.cypress.com
Document No. 001-90833 Rev. **
20