Documente Academic
Documente Profesional
Documente Cultură
QDK™
Atmel AT91SAM7S-EK with
IAR Toolset
Document Revision H
April 2009
www.quantum-leaps.com
www.state-machine.com
1 Introduction.................................................................................................... 1
1.1 What’s Included in the QDK-AT91SAM7S-EK? ....................................................... 2
1.2 Licensing QDK-AT91SAM7S-EK ........................................................................... 2
2 Getting Started ............................................................................................... 3
2.1 Directories and Files .......................................................................................... 3
2.2 Building the QP Libraries .................................................................................... 4
2.3 Building the Examples ....................................................................................... 4
2.4 Running the Examples ....................................................................................... 5
3 Board Support Package................................................................................... 7
3.1 Startup Code in Assembly .................................................................................. 7
3.1.1 Exception Vectors ....................................................................................... 7
3.1.2 Reset and MC Remapping ............................................................................ 8
3.2 Linker Command File....................................................................................... 11
3.3 Controlling Placement of the Code in Memory and ARM/THUMB Compilation ............ 12
3.4 BSP Functions in C .......................................................................................... 13
3.4.1 The Low-Level Initialization ........................................................................ 13
3.4.2 The Board Initialization .............................................................................. 14
3.4.3 The ISRs ................................................................................................. 15
3.4.3.1 ISRs in the Vanilla Port ..........................................................................15
3.4.3.2 ISRs in the QK Port, Mixed ARM/THUMB Mode...........................................17
3.4.4 QS Instrumentation................................................................................... 18
3.4.5 Idle Loop Customization............................................................................. 20
3.4.5.1 Idle Loop in the Vanilla Port....................................................................20
3.4.5.2 Idle Loop in the QK Port.........................................................................22
3.5 Loading the Code to Flash ................................................................................ 23
3.6 Manual Testing of Interrupt Preemptions Scenario ............................................... 24
4 References .................................................................................................... 26
5 Contact Information...................................................................................... 27
J-Link
J-TAG pod
external
power
4 LEDs
QSPY output
(NULL-modem
cable to PC)
Atmel
AT91SAM7S64
device
Figure 1 AT91SAM7S-EK evaluation board from Atmel and the J-Link pod.
1. AT91SAM7S-EK evaluation board from Atmel (the board is based around the AT91SAM7S64
MCU) NOTE: The board, the J-Link pod, and software are bundled into the IAR AT91SAM7 Kick-
Start™ Kit available from IAR Systems (www.iar.com).
2. The J-Link J-Tag pod from Segger (www.segger.com). NOTE: IAR Embedded Workbench sup-
ports also several other J-Tag pods.
3. IAR Embedded Workbench® for ARM version 5.30, the free KickStart edition (www.iar.com)
4. QP/C/C++ version 4.0 or later (QEP, QF, QK, and QS)
NOTE: This QDK covers both the C and C++ version of QP. The concrete code examples are
taken from the C version, but the C++ version is essentially identical except for some trivial
syntax differences.
2 Getting Started
This section describes how to install, build, and use the QDK- AT91SAM7S-EK based on two ver-
sions of an example application.
This document describes the standard QDK distribution, which must be augmented with the generic
ARM code accompanying the Application Note “QP and ARM7/ARM with IAR Toolset” [QL 08a] and
the standard distributions of the QP components. You need to download the following archives and
unzip all of them into the same directory of your choice. This directory will be referred to as QP
root directory and denoted <qp>:
1. QP baseline code: qpc_x.y.zz.zip (QP/C) or qpcpp_x.y.zz (for QP/C++)
2. This QDK: qdkc_arm-at91sam7s-iar_x.y.zz.zip (QP/C) or qdkcpp_arm-at91sam7s-iar_x.y.zz
(QP/C++)
NOTE: Please refer to the document “QL Licensing and Support” or to the HTML page at
www.quantum-leaps.com/licensing for details about the terms of licensing and technical sup-
port.
Select build
configuration
This will start the qspy utility to listen on COM1 serial port with baud rate 115200. (Please use –c
COM2, or higher if you connected the NULL-cable to a different COM port on your PC.)
The following screen shot shows the QSPY output from the DPP run:
The BSP does not include drivers for all AT91SAM7 peripherals. However, it should be fairly com-
plete in that it supports debugging in RAM, code downloading to Flash, software tracing with Quan-
tum Spy (QS), fine-tuning of the release version, and more.
;-----------------------------------------------------------------------------
; Reset and other vectors
;
(1) SECTION .intvec:CODE:NOROOT(2)
PUBLIC __vector
PUBLIC __iar_program_start
; Execution starts here.
; After a reset, the mode is ARM, Supervisor, interrupts disabled.
(2) CODE32 ; Always ARM mode after reset
(3) __vector:
(4) LDR pc,[pc,#24] ; load the secondary vector
LDR pc,[pc,#24] ; load the secondary vector
LDR pc,[pc,#24] ; load the secondary vector
LDR pc,[pc,#24] ; load the secondary vector
LDR pc,[pc,#24] ; load the secondary vector
LDR pc,[pc,#24] ; load the secondary vector
LDR pc,[pc,#24] ; load the secondary vector
LDR pc,[pc,#24] ; load the secondary vector
; The secondary jump talbe starts below. It contains the
; addresses for the PC-relative loads from the primary vector table.
; The secondary vectors are to be overwritten by the application to hook
(1) This module defines interrupt vectors and is placed in the .intvec section.
(2) The ARM core always starts in ARM state, Supervisor mode, all interrupts disabled.
(3) The symbol __vector denotes the beginning the primary vector table.
(4) The primary vector table is pre-filled with jumps to the secondary jump table located immedi-
ately after the primary vector table at address 0x20. The secondary vector table is used for
maximum flexibility. Such jump table makes it much easier to hook any exception vector at real
time, by simply writing a pointer to one of the locations 0x20-0x3C, rather than having to syn-
thesize a branch instruction at the primary vector table. Also, the LDR instruction can access any
code within the full 32-bit address range, while the PC-relative branch instruction is limited to
0x02000000 from the current PC.
NOTE: Please note that the ARM core starts execution at address 0x0. Out of reset, the Flash
memory is mapped at this address. However, immediately after executing the LDR pc,[pc,#24]
instruction, the code starts executing from the address range above 0x00100000, in which al-
ways Flash is mapped, even after the MC remapping.
(5) The secondary jump table is initialized in such a way that any exception (except reset) causes
an endless loop to itself. For example, a Prefetch Abort exception located at address 0x0C
causes a jump also to 0x0C, so the CPU hangs in an endless loop around address 0x0C. Of
course this is only the initial setting, after which you application code should initialize the sec-
ondary vector table to handle exceptions any way you want.
NOTE: The simple exception vectors are only for initial setting, after which you application code
should initialize the secondary vector table to handle exceptions any way you want. In particu-
lar, you will need to adjust the interrupt exceptions (IRQ and FIQ).
SECTION FIQ_STACK:DATA:NOROOT(3)
SECTION IRQ_STACK:DATA:NOROOT(3)
SECTION SVC_STACK:DATA:NOROOT(3)
NOTE: Unlike the earlier AT91X40 MCUs, the AT91SAM family keeps the RAM permanently
mapped to the address range starting at 0x00200000, and the MC remapping operation only
creates the RAM alias at the address 0x0.
NOTE: In the AT91SAM the Memory Controller remap is a toggle, so doing a remap twice would
revert the remap, which is not what you want.
Also, please note that the value zero cannot be located at zero address of the ROM before the
remap. This location is the ARM reset vector and must contain a valid ARM instruction.
Finally, please note that the testing for remap is very handy when resetting the MCU from a
debugger, which resets only the ARM core, but does not reset the Memory Controller (including
the remap operation).
(9-10) The primary vector table copied to the RAM. This vector table is identical to the ROM table
in Listing 2. Please note that the ADDR pseudo-instruction is PC-relative, so the code is poison-
independent.
(11-12) The secondary jump table copied to the RAM. This jump table is also identical to the ROM
table in Listing 2.
(13-15) The actual Memory Controller remap is performed only if the ZERO flag hasn’t been set
earlier in the TEQ instruction (i.e., the memory remap has not occurred yet).
(16-21) All stacks are initialized to the end of the stack sections, because the stack grows towards
lower memory addresses (descending stack)
NOTE: This startup code is generic, so it allows configuring all the available stacks in the ARM
core. However, the QP ports (both the vanilla and the QK versions) use only the SYSTEM/USER
stack.
(22) The code branches to the low-level initialization ?main provided by the IAR standard library.
The IAR code initializes all the RAM sections from the ROM sections and finally invokes your
main() function in C. The “System Startup and Termination” Section in the “ARM® IAR C/C++
Compiler Reference Guide” describes in more detail what happens from that point on and how
you can customize further the initialization of the various sections.
(23) The control should never return back to the startup code, but just in case this branch will hang
the CPU in a tight loop.
Figure 4 Editing the linker control script in the IAR Embedded Workbench IDE.
Copyright © Quantum Leaps, LLC. All Rights Reserved. 11 of 27
QDK™
QDK Atmel AT91SAM7S-EK with IAR Toolset
www.state-machine.com/arm
Typically, you don’t need to adjust the memory addresses for the ARM device (in the Memory Re-
gions tab in Figure 4), because they come pre-configured when you select the specific device in the
General Options section. However, you should adjust the Stack and Heap Sizes on the third tab of
the “Linker configuration file editor” shown in Figure 4. Again, note that QP uses only the
USER/SYSTEM stack and does not use any other stacks. If you don’t use the heap, which is highly
recommended in any embedded application, you should also set the size of the heap to zero.
The module qa_sub.c, for instance, which contains subscribe/unsubscribe functions for active ob-
jects, is compiled to THUMB and placed in the default location, which is ROM (Flash). This is be-
cause the functionality must be merely correct, but not necessarily fast. On the other hand, the
module qvanilla.c is clearly a “hot-spot”, because it contains the cooperative “vanilla” klernel run-
ning the whole application (see Chapter 7 in [PSiCC2]) and therefore it is compiled to ARM and
placed in the fast RAM. Of course, you can fine-tune the code placement any way you like for your
particular project.
You could also apply similar strategy to your application code. Additionally, you could use the IAR
extended keyword __ramfunc to place selected functions in RAM. This option is used in the ISR code
discussed in Section 0.
/* Select Master Clock and CPU Clock select the PLL clock / 2 */
pPMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
while ((pPMC->PMC_SR & AT91C_PMC_MCKRDY) == 0) {
}
pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
while ((pPMC->PMC_SR & AT91C_PMC_MCKRDY) == 0) {
}
(1) __low_level_init() is called from the IAR startup code before copying the DATA section and be-
fore zeroing the BSS section. (And also before calling the static constructors in C++).
(2) The number of Flash wait states FWS is set to 1 and the number FMCN (number of MCK cycles
in a microsecond) is set to the programmed MCK.
(3) The PLL is programmed
(4) The value returned by __low_level_init() determines whether or not data segments should be
initialized by __seqment_init(). If __low_level_init() returns 0, the data segments will NOT be
initialized. For more information see the "IAR ARM C/C++ Compiler Reference Guide".
void BSP_init(void) {
uint32_t i;
(1) for (i = 0; i < Q_DIM(l_led); ++i) { /* initialize the LEDs... */
AT91C_BASE_PIOA->PIO_PER = l_led[i]; /* enable pin */
AT91C_BASE_PIOA->PIO_OER = l_led[i]; /* configure as output pin */
LED_OFF(i); /* extinguish the LED */
}
/* configure Advanced Interrupt Controller (AIC) of AT91... */
(2) AT91C_BASE_AIC->AIC_IDCR = ~0; /* disable all interrupts */
AT91C_BASE_AIC->AIC_ICCR = ~0; /* clear all interrupts */
for (i = 0; i < 8; ++i) {
AT91C_BASE_AIC->AIC_EOICR = 0; /* write AIC_EOICR 8 times */
}
/* set the desired ticking rate for the PIT... */
i = (MCK / 16 / BSP_TICKS_PER_SEC) - 1;
(3) AT91C_BASE_PITC->PITC_PIMR = (AT91C_PITC_PITEN | AT91C_PITC_PITIEN | i);
NOTE: The PIT has been specially designed to deliver the operating system time tick.
(4) Initialize the QS software tracing (this code is active only when the macro Q_SPY is defined).
(1) This typedef defines the pointer-to-function type for calling the interrupt handlers.
(2) As described in Application Note “QP and ARM7/ARM with IAR Toolset” [QL 08a], the low-level
IRQ interrupt “wrapper” in assembly calls function BSP_irq(). This function is a regular C func-
tion (not an __irq function!) and can be compiled to THUMB or ARM, as you like. Here, the
function BSP_irq() is defined as an ARM function (via the __arm keyword) to be able to use the
very efficient, unconditional interrupt locking and unlocking macros QF_INT_UNLOCK_ARM()/
QF_INT_LOCK_ARM(). The __ramfunc extended keyword makes the function to execute from the
RAM, which is only done for better performance.
(3) The current interrupt vector is loaded from the AIC IVR register into a temporary variable.
(4) Interrupts are enabled unconditionally at the ARM core level by means of the macro
QF_INT_UNLOCK_ARM(). Please note that the QF_INT_UNLOCK() macro is not used, because it
unlocks interrupts conditionally depending on the interrupt lock key parameter.
NOTE: Enabling all IRQs and FIQs is safe, because the AIC performs interrupt prioritization in
hardware.
(5) The interrupt handler is invoked via the pointer-to-function (vector address) extracted from the
AIC. Please note that the vectoring capability of the AIC is actually used, even though this is
not the traditional auto-vectoring. For the vectoring to work, the AIC SVR registers must be ini-
tialized with the addresses of interrupt handlers, such as the time tick ISR tickIRQ().
(6) After ISR function returns, the interrupts are disabled unconditionally at the ARM core level by
means of the macro QF_INT_UNLOCK_ARM().
(7) The EOI command is written to the AIC, which informs the interrupt controller that the interrupt
processing has ended.
(8) As described in Application Note “QP and ARM7/ARM with IAR Toolset” [QL 08a], the low-level
FIQ interrupt “wrapper” in assembly calls function BSP_fiq(). This function is a regular C func-
tion (not an __fiq function!) and can be compiled to THUMB or ARM, as you like. Here, the
function BSP_fiq() is defined as __ramfunc to execute from the RAM, which is only done for bet-
ter performance. Because the AIC does not provide priority controller for the FIQ (see the
“AT91SAM Datasheet”) there is really not any value added by indirecting via the AIC_FVR regis-
ter. The body of the interrupt might as well be directly implemented in BSP_fiq().
NOTE: Because the AIC does not protect the FIQ line with the priority controller, the whole
work of FIQ should be performed with interrupts permanently locked at the ARM core level. In
particular, the IRQ interrupt should never be unlocked during FIQ processing.
(9) As described at Listing 6(5), the interrupt handler is a regular C function. Declaring this func-
tion as __ramunc is just an optimization.
(10) The interrupt source (Timer/Counter 1 in this case) must be cleared.
NOTE: Please note that the interrupt handler executes with interrupt unlocked at the ARM core
level. However, the prioritization performed in AIC prevents the same (or any other lower-
priority) interrupt from preempting the currently serviced interrupt.
(11) The work of the interrupt is performed, which consists of the system clock tick processing
QF_tick() in this case.
Listing 5(12) The spurious interrupt handler is empty.
(13) The QF callback QF_onStartup() is called just before entering the background loop of the “va-
nilla” QF port (see Chapter 7 in [PSiCC2]). This purpose of the QF_onStartup() function is to
configure and enable the interrupts.
(14) All interrupts (both IRQ and FIQ) are locked unconditionally with the macro
QF_INT_LOCK_ARM().
(15-21) The secondary jump table at address 0x20 is initialized with the addresses of the “wrap-
per” functions in assembly. Among others, the table entry at 0x38 is initialized with the address
of BSP_irq() and the entry at 0x3C with the address of BSP_fiq().
(22,23) The AIC is initialized with the addresses of all used interrupt handlers.
(24) All interrupts (both IRQ and FIQ) are unlocked unconditionally with the macro
QF_INT_UNLOCK_ARM().
(1-2) The IRQ and FIQ interrupt handlers are set to QK_irq and QK_fiq, respectively (see Applica-
tion Note “QP and ARM7/ARM with IAR Toolset” [QL 08a]).
(3) The Timer-Counter 1 (TC1) is configured to deliver the FIQ interrupt for testing of various pre-
emption scenarios in the QK port (see also Section 3.6).
(4) As described in Application Note “QP and ARM7/ARM with IAR Toolset” [QL 08a], the low-level
FIQ interrupt “wrapper” in assembly calls function BSP_irq(). This function is a regular C func-
tion (not an __fiq function!) and can be compiled to THUMB or ARM, as you like. Here, the
function BSP_fiq() is defined as __ramfunc to execute from the RAM, which is only done for bet-
ter performance. The BSP_fiq() function is setup to generate an event for the highest-priority
active object Table in the DPP application. This allows testing of various asynchronous preemp-
tion scenarios in the QK port (see Section 3.6)
3.4.4 QS Instrumentation
This QDK demonstrates how to use the Quantum Spy (QS) to obtain real-time trace of a running
QP application.
Quantum Spy (QS) is a software tracing facility built into all Quantum Platform components and
also available to the Application code. QS allows you to gain unprecedented visibility into your ap-
plication by selectively logging almost all interesting events occurring within state machines, the
framework, the kernel, and your application code. QS software tracing is minimally intrusive, offers
precise time-stamping, sophisticated runtime filtering of events, and good data compression (see
Chapter 11 in [PSiCC2]).
QS can be configured to send the real-time data out of the serial port of the target device. On the
AT91SAM7S-EK board, the QS has been configured to send data out of the debug serial port (De-
bug UART, see Figure 1). The QS platform-dependent implementation is located in the file bsp.c
and looks as follows:
(1) The QS instrumentation is enabled only when the macro Q_SPY is defined
(2) This variable is used to extend the 16-bit timestamp counter to 32-bits
(3) The QS_onStartup() callback performs the initialization of QS
(4) You must allocate the QS trace buffer of adequate size
(5) You always need to call QS_initBuf() from QS_onStartup() to initialize the trace buffer
(6) This particular QS port initializes the DEBUG UNIT UART for polled DMA data transfer at the
given baud rate (BAUD_RATE = 115200 bits per second)
(7) This QS port uses Timer/Counter 0 for sub-microsecond time-stamping of the trace records.
The clock to this peripheral must be enabled before it can be used.
(8) Timer/Counter 0 is configured to tick at the rate of MCK/32.
(8) The QS_onCleanup() callback performs the cleanup of QS. Here nothing needs to be done.
Listing 8(9) The QS_onFlush() callback flushes the QS trace buffer to the host. It is only used in the
initialization phase for sending the QS dictionary records to the host (see Chapter 11 in
[PSiCC2])
(10) QS_onFlush() busy-waits for the DMA transfer to complete.
(11) The function QS_getBlock() returns a non-NULL pointer when the trace buffer has data.
(12-13) If a data block is available, it is used to setup the DMA pointer and the number of bytes for
the DMA counter.
(14) The number of bytes to accept is reset to the buffer size
(15) The function QS_getBlock() is called again, because the QS buffer is circular and could wrap
around.
(16-17) If a data block is still available, its used to setup the NEXT DMA pointer and the NEXT DMA
counter.
NOTE: This hardware structure of the AT91SAM7 DMA with two levels of pointers and chaining
the DMA transfers is exactly designed to flush circular buffers, like the QS trace buffer.
(18) The QS_onGetTime() callback provides the time-stamp to the QS trace records. The QS time-
stamping implementation uses the high-resolution Timer-Counter 0 of the AT91. The timer is
configured to use the MCK with the 1/32 prescaler, which on AT91SAM7S-EK works out to be
47923200Hz/32 = 1.4976MHz (0.667735 microsecond per count).The 16-bit counter is ex-
tended to 32-bits by looking at the overflow bit pTC0->TC_SR & AT91C_TC_COVS. The assumption
here is that the QS_onGetTime() callback will be called at least once per the 16-bit overflow time.
(3) QF_INT_UNLOCK(key);
(4) if ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXBUFE) != 0) { /* not busy? */
uint16_t nBytes = QS_BUF_SIZE;
(1) The function QF_onIdle() is placed in RAM (__ramfunc), because it is executed very often and
therefore is a clear “hot-spot”.
NOTE: The signature of the QF_onIdle() callback depends on the interrupt locking policy. In
case of the “save and restore interrupt status” policy, the function takes the interrupt lock key
as the parameter to be able to unlock the interrupts internally.
(2) If Q_SPY is enabled, QF_onIdle() performs QS trace data transfer using the DMA mode of
UART1.
(3) If Q_SPY is enabled, the interrupts are unlocked immediately (no power-saving is applied).
(4) The UART1 transmit counter is examined. If it’s zero the DMA is done with the transfer.
(6,10) The QS buffer access function QS_getBlock() is not protected internally with a critical sec-
tion. Here, in the background loop, such protection is needed.
(6) The function QS_getBlock() returns a non-NULL pointer when the trace buffer has data.
(7-8) If a data block is available, it is used to setup the DMA pointer and the number of bytes for
the DMA counter.
(9) The number of bytes to accept is reset to the buffer size
(10) The function QS_getBlock() is called again, because the QS buffer is circular and could wrap
around.
(11-12) If a data block is still available, its used to setup the NEXT DMA pointer and the NEXT DMA
counter.
NOTE: This hardware structure of the AT91SAM7 DMA with two levels of pointers and chaining
the DMA transfers is exactly designed to flush circular buffers, like the QS trace buffer.
(14) If the Q_SPY is not configured, the QF_onIdle() function uses the power saving feature of the
AT91 to gate the clock to the CPU. An active interrupt first re-starts the CPU clock.
NOTE: The power-saving mode is applied with interrupts locked. Interrupts are unlocked only
later, after an interrupt restarts the CPU clock again.
(15) Immediately after the CPU clock re-starts the interrupts are unlocked to allow processing of
the interrupt.
(1) The function QK_onIdle() is placed in RAM (__ramfunc), because it is executed very often and
therefore is a clear “hot-spot”.
(2) If Q_SPY is enabled, QK_onIdle() performs QS trace data transfer using the DMA mode of the
DEBUG UNIT UART.
(3) The UART transmit buffer-empty bit is examined. If it’s set the DMA is done with the transfer.
(4,12) The QS buffer access function QS_getBlock() is not protected internally with a critical sec-
tion. Here, in the background loop, such protection is needed.
(5) The function QS_getBlock() returns a non-NULL pointer when the trace buffer has data.
(6-7) If a data block is available, it is used to setup the DMA pointer and the number of bytes for
the DMA counter.
(8) The number of bytes to accept is reset to the buffer size
(9) The function QS_getBlock() is called again, because the QS buffer is circular and could wrap
around.
(10-11) If a data block is still available, its used to setup the NEXT DMA pointer and the NEXT DMA
counter.
(13) If the Q_SPY is not configured, the QK_onIdle() function uses the power saving feature of the
AT91SAM7 to gate the clock to the CPU. Only an interrupt can wake the CPU up.
NOTE: The power-saving mode can interfere with debugging. You’ll see that you can break into
a running code only at the IRQ vector at 0x18.
Loading the application image into the Flash memory of the AT91SAM7 microcontroller is very
easy, because the whole functionality is already provided in the IAR toolset. The IAR Flash Loader
utility is described in the IAR document “IAR Embedded Workbench Flash Loader Developer Guide”,
which is included in PDF in the IAR KickStart™ development toolset for ARM. The process of config-
uring the C-Spy debugger for the flash loader is described in Section “Using Flash Loaders” in the
“ARM® IAR Embedded Workbench® IDE User Guide” [IAR 05b].
Once the C-Spy is configured for the device you’re using, you need to configure the Debugger sec-
tion of the “Options for Node” dialog box.
Figure 5 Configuring the Download tab of the “Options” dialog box, and editing the
Flash Loader parameters.
Figure 5 shows how to setup the Debugger options to “Use flash loaders” and how to configure the
flash loader. In particular, the Atmel AT91SAM7S64 flash loader requires relocating the Base ad-
dress to 0x00100000, if the image is linked to RAM after the Memory Controller remapping, which
is typically the case.
NOTE: All IAR examples for the AT91SAM7 show only how to load the image to Flash without
the MC remapping. The code provided in these examples will not load correctly if you try to link
the image to ROM at 0x00100000 (i.e., after the MC remap), even if you select the “Relocate”
checkbox and specify the address 0x00100000, as shown in Figure 5.
The general testing strategy is to break into the application at an interesting point for preemption,
set breakpoints to verify which path through the code is taken, and trigger the desired timer. Next,
you need to free-run the code (don’t use single stepping) so that the interrupt controller can per-
form prioritization. You observe the order in which the breakpoints are hit. This procedure will be-
come clearer after some examples.
The first interesting test is verifying the prioritization of IRQ interrupts by the AIC. To test this sce-
nario, you place a breakpoint at the beginning of QK_irq assembler “wrapper” function in the
qk_port.s file. When the breakpoint is hit, you move the original breakpoint to the beginning of
QK_fiq assembler “wrapper” function. Next you trigger the Timer1 interrupt by writing 0x5 to the
address 0xFFFA0040. You hit the Run button.
After the breakpoint in QK_fiq is hit, you need to disable Timer1 from expiring again, by writing 0x2
(CLKDIS) to the address 0xFFFA0040. You then step through the QK_fiq assembler “wrapper”. In
particular, you can verify that the QK scheduler QK_schedule_() is not executed, because the FIQ
nests on the IRQ, even though the QK_intNest_ variable has not been incremented yet inside the
QK_irq handler.
4 References
Document Location
[PSiCC2] “Practical UML Statecharts in Available from most online book retailers, such as
C/C++, Second Edition”, Miro Samek, New- amazon.com. See also: http://www.state-
nes, 2008 machine.com/psicc2.htm
[IAR 08a] “ARM® IAR C/C++ Compiler Ref- Available in PDF as part of the ARM KickStart™ kit
erence Guide”, IAR 08 in the file EWARM_CompilerReference.pdf.
[IAR 08b] “IAR Linker and Library Tools Ref- Available in PDF as part of the ARM KickStart™ kit
erence Guide”, IAR 08
[IAR 08c] “ARM® Embedded Workbench® Available in PDF as part of the ARM KickStart™ kit
IDE User Guide”, IAR 08 in the file EWARM_UserGuide.pdf.
5 Contact Information
Quantum Leaps, LLC “Practical UML
103 Cobble Ridge Drive Statecharts in C/C++,
Chapel Hill, NC 27516 Second Edition: Event
USA Driven Programming
for Embedded Sys-
+1 866 450 LEAP (toll free, USA only) tems”, by Miro Samek,
+1 919 869-2998 (FAX) Newnes, 2008
e-mail: info@quantum-leaps.com
WEB : http://www.quantum-leaps.com
http://www.state-machine.com