12.07.2015 Views

QDK-nano AVR-GNU - Quantum Leaps

QDK-nano AVR-GNU - Quantum Leaps

QDK-nano AVR-GNU - Quantum Leaps

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

QP-<strong>nano</strong> state machine framework for <strong>AVR</strong><strong>QDK</strong>-<strong>nano</strong>Atmel <strong>AVR</strong>-<strong>GNU</strong>Document Revision IMarch 2014Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLCwww.quantum-leaps.comwww.state-machine.com


Table of Contents1 Introduction ..................................................................................................................................................... 11.1 About QP-<strong>nano</strong> ........................................................................................................................................... 21.2 About QM ................................................................................................................................................... 31.3 What’s Included in the <strong>QDK</strong>-<strong>nano</strong>? ................................................................................................................ 31.4 Licensing QP-<strong>nano</strong> ..................................................................................................................................... 41.5 Licensing QM .............................................................................................................................................. 42 Getting Started ................................................................................................................................................ 52.1 Installation ...................................................................................................................................................... 52.2 Building the Examples .................................................................................................................................... 62.3 Programming and Debugging the <strong>AVR</strong> Device .............................................................................................. 73 Non-Preemptive Configuration of QP-<strong>nano</strong> .................................................................................................. 83.1 ISRs in the Non-preemptive “Vanilla” Configuration ....................................................................................... 93.2 QP Idle Loop Customization in QF_onIdle() ................................................................................................... 104 Preemptive Configuration with QK-<strong>nano</strong> ...................................................................................................... 124.1 ISRs in the Preemptive Configuration with QK-<strong>nano</strong> ...................................................................................... 134.2 Idle Loop Customization in the QK Port ......................................................................................................... 135 BSP for <strong>AVR</strong> .................................................................................................................................................... 145.1 Board Initialization and the Timer Tick ........................................................................................................... 145.2 Starting Interrupts in QF_onStartup() ............................................................................................................. 145.3 Assertion Handling Policy in Q_onAssert() .................................................................................................... 146 Related Documents and References ............................................................................................................. 157 Contact Information ........................................................................................................................................ 16Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.i


1 IntroductionThis QP-<strong>nano</strong> Development Kit (<strong>QDK</strong>-<strong>nano</strong>) describes how to use QP-<strong>nano</strong> state machineframework with the Atmel <strong>AVR</strong> and the Atmel Studio 6 and the <strong>GNU</strong> <strong>AVR</strong> compiler. The actualhardware/software used to test this <strong>QDK</strong> as shown in Figure 1 and described below:Figure 1: Atmel <strong>AVR</strong> Butterfly evaluation board connected to the <strong>AVR</strong> Dragon emulator, theRS232, external power, and external LEDs for PORTD.Powerfrom PCvia USBPowerswitchJTAGICEmkIISTK600-ATMEGA2560cardAtmega2560deviceJTAGconnectorPORTDconnectionfor LEDsUserswitchesUserLEDsThe actual hardware/software used to test this <strong>QDK</strong> is described below:Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.1 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr• STK600 board with STK600-ATMEGA2560 routing board• JTAGICE mkII debugger• Atmel Studio 6• <strong>AVR</strong>-GCC for windows (bundled with Atmel Studio 6.0)• QP-<strong>nano</strong> 5.2.1 or higher and QM v 2.2.03 or higher.As shown in Figure 1, the Atmel’s STK600 is powered via a USB cable and is connected to the JTAGmkIIemulator via the JTAG ribbon cable. This <strong>QDK</strong> has been tested on the ATmega2560 device with8KB of RAM and 256KB of on-board flash. However, the described port should be applicable to most<strong>AVR</strong>mega devices (such as ATtiny and ATmega families) big enough to accommodate QP-<strong>nano</strong>.1.1 About QP-<strong>nano</strong>QP-<strong>nano</strong> is an ultra-lightweight, open source, state machineframework and RTOS for developing real-time embeddedapplications. QP-<strong>nano</strong> has been specifically designed to enable eventdrivenprogramming with concurrent hierarchical state machines (UMLstatecharts) on low-end 8- and 16-bit single-chip MCUs and DSPs,such as <strong>AVR</strong>. All versions of QP, including QP-<strong>nano</strong>, are described indetail in the book "Practical UML Statecharts in C/C++, 2nd Edition:Event-Driven Programming for Embedded Systems" [PSiCC2]The QP-<strong>nano</strong> framework can manage up to 8 concurrently executinghierarchical state machines and requires only 1-2KB of code (ROM)and just several bytes of RAM. As shown in Figure 2, QP-<strong>nano</strong>consists of a universal UML-compliant event processor (QEP-<strong>nano</strong>), ahigly portable event-driven framework (QF-<strong>nano</strong>), and a tiny run-tocompletionkernel (QK-<strong>nano</strong>).Figure 2: QP-<strong>nano</strong> components and their relationship with the target hardware, board supportpackage (BSP), and the application comprised of state machinesStateMachineStateMachineStateMachineStateMachineApplication(Your code)QEP-<strong>nano</strong> UML-CompliantEvent ProcessorQF-<strong>nano</strong> Event-DrivenFrameworkBSPQK-<strong>nano</strong> Preemptive Kernel,Cooperative Kernel,or other OS/RTOSTargetCopyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.2 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr1.2 About QMQM (QP Modeler) is a free, cross-platform, graphical UML modeling tool fordesigning and implementing real-time embedded applications based on theQP state machine frameworks. QM is available for Windows, Linux, andMac OS X. QM provides intuitive diagramming environment for creating goodlooking hierarchical state machine diagrams and hierarchical outline of yourentire application. QM eliminates coding errors by automatic generation ofcompact C or C++ code that is 100% traceable from your design. Please visitstate-machine.com/qm for more information about QM.1.3 What’s Included in the <strong>QDK</strong>-<strong>nano</strong>?This <strong>QDK</strong>-<strong>nano</strong> provides the QP-<strong>nano</strong> port to <strong>AVR</strong> with the <strong>GNU</strong> compiler, the Board Support Package(BSP) and two versions of the PEdestrian LIght CONtrolled (PELICAN) crossing example applicationdescribed in the Application Note “PELICAN Crossing Example” [QL AN-PELICAN 08], for cooperativeand preemptive kernels, respectively.Figure 3: The example model opened in the QM modeling toolNOTE: The entire source code included with this <strong>QDK</strong> can be edited manually in a traditional codeeditor. However, significant parts of the code have been generated automatically by the QMCopyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.3 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avrmodeling tool from the pelican.qm model file included in the <strong>QDK</strong>. The preferred way of developingQP applications is to make all the changes in the model and generate the code automatically..1.4 Licensing QP-<strong>nano</strong>The Generally Available (GA) distribution of QP-<strong>nano</strong> available for download from the www.statemachine.com/downloadswebsite is offered with the following two licensing options:• The <strong>GNU</strong> General Public License version 2 (GPL) as published by the FreeSoftware Foundation and appearing in the file GPL.TXT included in the packaging ofevery <strong>Quantum</strong> <strong>Leaps</strong> software distribution. The GPL open source license allowsyou to use the software at no charge under the condition that if you redistribute theoriginal software or applications derived from it, the complete source code for yourapplication must be also available under the conditions of the GPL (GPL Section2[b]).• One of several <strong>Quantum</strong> <strong>Leaps</strong> commercial licenses, which are designed forcustomers who wish to retain the proprietary status of their code and therefore cannotuse the <strong>GNU</strong> General Public License. The customers who license <strong>Quantum</strong> <strong>Leaps</strong>software under the commercial licenses do not use the software under the GPL andtherefore are not subject to any of its terms.For more information, please visit the licensing section of our website at: www.statemachine.com/licensing.1.5 Licensing QMThe QM graphical modeling tool available for download from the www.statemachine.com/downloadswebsite is free to use, but is not open source. During theinstallation you will need to accept a basic End-User License Agreement (EULA),which legally protects <strong>Quantum</strong> <strong>Leaps</strong> from any warranty claims, prohibits removingany copyright notices from QM, selling it, and creating similar competitive products.Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.4 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr2 Getting StartedThis section describes how to install, build, and use <strong>QDK</strong>-<strong>nano</strong>-<strong>AVR</strong>-<strong>GNU</strong> based on two examples.NOTE: Every <strong>QDK</strong>-<strong>nano</strong> contains only example(s) pertaining to the specific MCU and compiler, butdoes not include the platform-independent baseline code of QP-<strong>nano</strong>, which is available for aseparate download. It is strongly recommended that you read Chapter 12 in [PSiCC2] before youstart with this <strong>QDK</strong>-<strong>nano</strong>.2.1 InstallationThe <strong>QDK</strong>-<strong>nano</strong> code is distributed in a ZIP archive (qdkn_<strong>AVR</strong>-<strong>GNU</strong>.zip. You should uncompress thearchive into the same directory in which you’ve installed QP-<strong>nano</strong>. The QP-<strong>nano</strong> installation will bereferred henceforth as QP-<strong>nano</strong> Root Directory qpn.Listing 1: Directories and files after installing QP-<strong>nano</strong> baseline code and the <strong>QDK</strong>-<strong>nano</strong>-<strong>AVR</strong>-<strong>GNU</strong>distribution. The highlighted directories and files are provided in the <strong>QDK</strong>-<strong>nano</strong>-<strong>AVR</strong>-<strong>GNU</strong> ZIP file.qpn\- QP-<strong>nano</strong> Root Directory|+-examples\- QP-<strong>nano</strong> examples| +-avr\ - examples for <strong>AVR</strong>| | +-gnu\ - examples compiled with the <strong>GNU</strong> (Win<strong>AVR</strong>) compiler| | | +-pelican-stk600-atmega2560/ - PELICAN example for <strong>AVR</strong> STK600-ATMEGA2560| | | | +-dbg\ - directory containing the debug build| | | | +-rel\ - directory containing the release build| | | | +-pelican-stk600-atmega2560.cproj – Atmel Studio 6 project| | | | +-pelican-stk600-atmega2560.atsln – Atmel Studio 6 solution| | | | +-pelican.qm - QM model for the PELICAN application| | | | +-bsp.h - Board Support Package include file| | | | +-bsp.c - Board Support Package implementation| | | | +-pelican.h| | | | +-main.c| | | | +-pelican.c| | | | +-ped.c| | | | +-qpn_port.h – QP-<strong>nano</strong> port| | | || | | +-pelican-qk-stk600-atmega2560/ - PELICAN example for <strong>AVR</strong> STK600-ATMEGA2560| | | | +-dbg\ - directory containing the debug build| | | | +-rel\ - directory containing the release build| | | | +-pelican-qk-stk600-atmega2560.cproj – Atmel Studio 6 project| | | | +-pelican-qk-stk600-atmega2560.atsln – Atmel Studio 6 solution| | | | +-pelican.qm - QM model for the PELICAN application| | | | +-bsp.h - Board Support Package include file| | | | +-bsp.c - Board Support Package implementation| | | | +-pelican.h| | | | +-main.c| | | | +-pelican.c| | | | +-ped.c| | | | +-qpn_port.h – QP-<strong>nano</strong> port|+-include\- subdirectory containing the QP-<strong>nano</strong> public interface| +-qassert.h - embedded-systems-friendly assertions used in QP-<strong>nano</strong>| +-qepn.h - The platform-independent QEP-<strong>nano</strong> header fileCopyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.5 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr| +-qfn.h - The platform-independent QF-<strong>nano</strong> header file| +-qkn.h - The platform-independent QK-<strong>nano</strong> header file|+-source/- QP-<strong>nano</strong> source files| +-qepn.c - QEP-<strong>nano</strong>| +-qfn.c - QF-<strong>nano</strong>| +-qkn.c - QK-<strong>nano</strong> (required only in QK-<strong>nano</strong> configuration)2.2 Building the ExamplesThe <strong>QDK</strong>-<strong>nano</strong> contains the Atmel Studio solution located in \examples\avr\gnu\pelicanstk600-atmega2560\pelican-stk600-atmega2560.avrslnfor the “vanilla” version, and in \-examples\avr\gnu\pelican-qk-stk600-atmega2560\pelican-qk-stk600-atmega2560.avrsln forthe QK-<strong>nano</strong> version, respectively.Figure 4: The PELICAN example project opened in Atmel Studio 6.Select buildconfigurationCopyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.6 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr3 Non-Preemptive Configuration of QP-<strong>nano</strong>The example of using QP-<strong>nano</strong> with the cooperative “Vanilla” kernel is located in the directory: \-examples\arm\gnu\pelican-stk600-atmega2560\. This section describes the generic QP-<strong>nano</strong>configuration, which consist of the qpn_port.h header file. The board-specific elements are common forboth the non-preemptive and preemptive (QK-<strong>nano</strong>) configuration and will be covered in Section 5.You configure and customize QP-<strong>nano</strong> through the header file qpn_port.h, which is included by the QP<strong>nano</strong>source files (qepn.c and qfn.c) as well as in all your application C modules.NOTE: The QP-<strong>nano</strong> port to the cooperative “Vanilla” kernel qpn_port.h is generic and should notneed to change (except for the QF_MAX_ACTIVE definition) for other <strong>AVR</strong> projects.Listing 2: qpn_port.h header file for the non-preemptive QF-<strong>nano</strong> configuration and <strong>GNU</strong> compiler#ifndef qpn_port_h#define qpn_port_h(1) #define Q_ROM PROGMEM(2) #define Q_ROM_BYTE(rom_var_) pgm_read_byte_near(&(rom_var_))(3) #define Q_ROM_PTR(rom_var_) pgm_read_word_near(&(rom_var_))(4) #define Q_NFSM(5) #define Q_PARAM_SIZE 1(6) #define QF_TIMEEVT_CTR_SIZE 2/* maximum # active objects--must match EXACTLY the QF_active[] definition */(7) #define QF_MAX_ACTIVE 2/* interrupt disabling policy for <strong>GNU</strong> compiler */(8) #define QF_INT_DISABLE() cli()(9) #define QF_INT_ENABLE() sei()/* interrupt disabling policy for interrupt level */(10) /* #define QF_ISR_NEST */ /* nesting of ISRs not allowed */(11) #include #include /* cli()/sei() */#include /* accessing data in the program memory (PROGMEM) */(12) #include /* Exact-width integer types. WG14/N843 C99 Standard */(13) #include "qepn.h" /* QEP-<strong>nano</strong> platform-independent public interface */(14) #include "qfn.h" /* QF-<strong>nano</strong> platform-independent public interface */#endif /* qpn_port_h */(1) The macro Q_ROM allows enforcing placing the constant objects, such as lookup tables, constantstrings, etc. in ROM, rather than in the precious RAM. On CPUs with the Harvard architecture (suchas Atmel <strong>AVR</strong> or 8051), the code and data spaces are separate and are accessed through differentCPU instructions. Various compilers often provide specific extended keywords to designate code ordata space, such as the “PROGMEM” macro in the <strong>GNU</strong>-<strong>AVR</strong> compiler.Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.8 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr(2) The macro Q_ROM_BYTE() encapsulates a custom mechanism of retrieving a data byte from thegiven ROM address. <strong>GNU</strong>-<strong>AVR</strong> cannot generate code for accessing data allocated in the programspace (ROM), even though the compiler can allocate constants in ROM. The workaround for <strong>GNU</strong>-<strong>AVR</strong> is to explicitly add custom assembly code to access data allocated in the program space.(3) The macro Q_ROM_PTR() encapsulates a custom mechanism of retrieving a data pointer from thegiven ROM address. <strong>GNU</strong>-<strong>AVR</strong> cannot generate code for accessing data allocated in the programspace (ROM), even though the compiler can allocate constants in ROM. The workaround for <strong>GNU</strong>-<strong>AVR</strong> is to explicitly add custom assembly code to access data allocated in the program space.(4) Defining the macro Q_NFSM eliminates the code for the simple non-hierarchical FSMs.(5) The macro Q_PARAM_SIZE defines the size (in bytes) of the scalar event parameter. The allowedvalues are 0 (no parameter), 1, 2, or 4 bytes. If you don’t define this macro in qpn_port.h, thedefault of 0 (no parameter) will be assumed.(6) The macro QF_TIMEEVT_CTR_SIZE defines the size (in bytes) of the time event down-counter. Theallowed values are 0 (no time events), 1, 2, or 4 bytes. If you don’t define this macro in qpn_port.h,the default of 0 (no time events) will be assumed.(7) You must define the QF_MAX_ACTIVE macro as the exact number of active objects used in theapplication. The provided value must be between 1 and 8 and must be consistent with the definitionof the QF_active[] array in main.c.(8-9) The macros QF_INT_DISABLE/QF_INT_ENABLE define the task-level interrupt disabling policy forQP-<strong>nano</strong> (see Section 12.3.2 in Chapter 12 in [PSiCC2]).(10) This QP-<strong>nano</strong> port to <strong>AVR</strong> does not allow nesting of interrupts.<strong>AVR</strong> does not provide any support for prioritizing interrupts in hardware. Therefore, enabling interruptsinside ISRs (the <strong>AVR</strong> hardware automatically disables interrupts upon entry to an ISR) is not advisable.Allowing interrupts to nest can lead to all sorts of priority inversions, including the pathological case of aninterrupt preempting itself.NOTE: This QP-<strong>nano</strong> port assumes that you never enable interrupts inside ISRs.(11) These header files are necessary for supporting interrupts in C an well as accessing the PROGMEMspace.(12) The <strong>GNU</strong> compiler provides the C99-standard exact-width integer types are defined in the standard header file.(13) The qpn_port.h must include the QEP-<strong>nano</strong> event processor interface qepn.h.(14) The qpn_port.h must include the QF-<strong>nano</strong> real-time framework interface qfn.h.3.1 ISRs in the Non-preemptive “Vanilla” ConfigurationThe <strong>GNU</strong>-<strong>AVR</strong> compiler supports writing interrupts in C. In the “vanilla” port, the ISRs are identical as inthe simplest of all “superloop” (main+ISRs), and there is nothing QP-specific in the structure of the ISRs.The only QP-specific requirement is that you provide a periodic time-tick ISR and you invoke QF_tick()in it.Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.9 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avrListing 3: Time tick interrupt calling QF_tick() function to manage armed time events.(1) ISR(TIMER2_COMPA_vect) {/* No need to clear the interrupt source since the Timer0 compare* interrupt is automatically cleard in hardware when the ISR runs.*/(2) QF_tick();}(1) The definition of the interrupt function must begin with the ISR() macro.(2) The time-tick ISR must invoke QF_tick(), and can also perform other actions, if necessary. Thefunction QF_tick() cannot be reentered, that is, it necessarily must run to completion and returnbefore it can be called again. This requirement is automatically fulfilled, because here interrupts aredisabled throughout the interrupt processing.3.2 QP Idle Loop Customization in QF_onIdle()The cooperative “vanilla” kernel can very easily detect the situation when no events are available, inwhich case QF_run() calls the QF_onIdle() callback. You can use QF_onIdle() to suspended the CPUto save power, if your CPU supports such a power-saving mode. Please note that QF_onIdle() is calledrepetitively from the event loop whenever the event loop has no more events to process, in which caseonly an interrupt can provide new events. The QF_onIdle() callback is called with interrupts disableded,because the determination of the idle condition might change by any interrupt posting an event.<strong>AVR</strong> supports several power-saving levels (consult the <strong>AVR</strong> data sheet for details). The following piece ofcode shows the QF_onIdle() callback that puts <strong>AVR</strong> into the idle power-saving mode. Please note that<strong>AVR</strong> architecture allows for very atomic setting the low-power mode and enabling interrupts at the sametime.Listing 4: QF_onIdle() for the non-preemptive (“vanilla”) QP-<strong>nano</strong> port to <strong>AVR</strong>.(1) void QF_onIdle(void) { /* entered with interrupts DISABLED, see NOTE01 */(2) LED_ON(7);LED_OFF(7);/* toggle the LED number 7 on and then off, see NOTE02 */#ifdef NDEBUG(3) SMCR = (0


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr(2) The LED[7] is turned on and off to visualize the idle loop activity. Note that the LED is toggled withinterrupts locked, to the period of the LED turned on is constant and does not include any time spentin the ISRs.(3) The SMCR register is loaded with the desired sleep mode (idle mode in this case) and the SleepEnable (SE) bit is set. Please note that the sleep mode is not active until the SLEEP command.(4) The interrupts are unlocked with the SEI instruction.(5) The sleep mode is activated with the SLEEP instruction.NOTE: The <strong>AVR</strong> datasheet is very specific about the behavior of the SEI-SLEEP instruction pair. Dueto pipelining of the <strong>AVR</strong> core, the SLEEP instruction is guaranteed to execute before entering anypotentially pending interrupt. This means that enabling interrupts and activating the sleep mode isatomic, as it should be to avoid non-deterministic sleep.(6) As recommended in the <strong>AVR</strong> datasheet, the SMCR register should be explicitly cleared upon the exitfrom the sleep mode.(7) In the DEBUG configuration the interrupts are simply unlocked.NOTE: Every path through QF_onIdle() callback function must ultimately unlock interrupts.Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.11 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr4 Preemptive Configuration with QK-<strong>nano</strong>The QP port with the preemptive kernel (QK) is remarkably simple and very similar to the “vanilla” port. Inparticular, the interrupt locking/unlocking policy is the same, and the BSP is identical, except some smalladditions to the ISRs. The PELICAN example for the QK port is provided in the directory\examples\avr\gnu\pelican-qk-stk600-atmega2560.You configure and customize QP-<strong>nano</strong> through the header file qpn_port.h, which is included by the QP<strong>nano</strong>source files (qepn.c, qfn.c, and qkn.c) as well as in all your application C modules. The followingListing 5 shows the qpn_port.h header file for the QK-<strong>nano</strong> port. Except for the highlighted fragments,the listing is identical as in the non-preemptive case (Listing 2)Listing 5: qpn_port.h header file for the preemptive QK-<strong>nano</strong> configuration#define Q_ROM#define Q_ROM_BYTE(rom_var_)#define Q_ROM_PTR(rom_var_)#define Q_NFSM#define Q_PARAM_SIZE 1#define QF_TIMEEVT_CTR_SIZE 2PROGMEMpgm_read_byte_near(&(rom_var_))pgm_read_word_near(&(rom_var_))/* maximum # active objects--must match EXACTLY the QF_active[] definition */#define QF_MAX_ACTIVE 2#define QF_INT_DISABLE()#define QF_INT_ENABLE()/* interrupt disabling policy for <strong>GNU</strong> compiler */cli()sei()/* interrupt disabling policy for interrupt level *//* #define QF_ISR_NEST */ /* nesting of ISRs not allowed */(1) #define QK_ISR_ENTRY() ((void)0)(2) #define QK_ISR_EXIT() do { \uint8_t p = QK_schedPrio_(); \if (p != (uint8_t)0) { \QK_sched_(p); \} \} while (0)/* interrupt entry/exit for QK-<strong>nano</strong> */#include #include /* cli()/sei() */#include /* accessing data in the program memory (PROGMEM) */#include /* Exact-width integer types. WG14/N843 C99 Standard */#include "qepn.h" /* QEP-<strong>nano</strong> platform-independent public interface */#include "qfn.h" /* QF-<strong>nano</strong> platform-independent public interface */(3) #include "qkn.h" /* QK-<strong>nano</strong> platform-independent public interface */(1-2) The interrupt entry and exit macro for QK-<strong>nano</strong> are defined consistently with the interrupt nestingpolicy, which does not allow interrupt nesting.(3) The preemptive configuration of QP-<strong>nano</strong> is selected by including the qkn.h header file.Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.12 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avrWhen interrupt nesting is not allowed (the macro QF_ISR_NEST is not defined in qpn_port.h), QK-<strong>nano</strong>allows for a simpler interrupt handling compared to the full-version QK. Specifically, when interruptscannot nest you don’t need to increment the interrupt nesting counter (QK_intNest_) upon the ISRentry, and you don’t need to decrement it upon the ISR exit. In fact, when the macro QF_ISR_NEST notdefined, the QK_intNest_ counter is not even available. This simplification is possible, because QP<strong>nano</strong>uses special ISR-version of the event posting function QActive_postISR(), which does not callthe QK-<strong>nano</strong> scheduler. Consequently, there is no need to prevent the synchronous preemption withinISRs.4.1 ISRs in the Preemptive Configuration with QK-<strong>nano</strong>As all preemptive kernels, QK-<strong>nano</strong> must be notified about interrupt entry and exit. You achieve this bymeans of the QK-<strong>nano</strong> macros QK_ISR_ENTRY() and QK_ISR_EXIT(), as shown in Listing 6.Listing 6: Time tick interrupt calling QF_tick() function to manage armed time events and QK-<strong>nano</strong>ISR entry/exit macros.ISR(TIMER2_COMPA_vect) {/* No need to clear the interrupt source since the Timer0 compare* interrupt is automatically cleard in hardware when the ISR runs.*/QK_ISR_ENTRY(); /* inform QK about entering the ISR */QF_tick();}QK_ISR_EXIT(); /* inform QK about exiting the ISR */NOTE: This QP-<strong>nano</strong> port assumes that you never enable interrupts inside ISRs.4.2 Idle Loop Customization in the QK PortAs described in Chapter 10 of [PSiCC2], the QK idle loop executes only when there are no events toprocess. The QK allows you to customize the idle loop processing by means of the callbackQK_onIdle(), which is invoked by every pass through the QK idle loop. You can define the platformspecificcallback function QK_onIdle() to save CPU power, or perform any other “idle” processing (suchas <strong>Quantum</strong> Spy software trace output).NOTE: The idle callback QK_onIdle() is invoked with interrupts unlocked (which is in contrast toQF_onIdle() that is invoked with interrupts dissabled, see Section 3.2).Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.13 of 16


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr5 BSP for <strong>AVR</strong>The Board Support Package (BSP) for <strong>AVR</strong> is very simple. However, there are some important detailsthat you need to pay attention to.5.1 Board Initialization and the Timer TickThe BSP is minimal, but generic for most <strong>AVR</strong> devices. The most important step is initialization of Timer 0to deliver the time tick interrupt at the desired rate (BSP_TICKS_PER_SEC):void BSP_init(void) {DDRD = 0xFF; /* All PORTD pins are outputs for LEDs */LED_OFF_ALL(); /* trun off all LEDs */}5.2 Starting Interrupts in QF_onStartup()QP-<strong>nano</strong> invokes the QF_onStartup() callback just before starting the event loop inside QF_run(). TheQF_onStartup() function must start the interrupts configured earlier. In this BSP only the timer tickinterrupt is started.Listing 7: Configuring and enabling interrupts in the QF_onStartup() callback.void QF_onStartup(void) {/* set Timer2 in CTC mode, 1/1024 prescaler, start the timer ticking */TCCR2A = ((1


<strong>QDK</strong>-<strong>nano</strong><strong>AVR</strong>-<strong>GNU</strong>www.state-machine.com/avr7 Contact Information<strong>Quantum</strong> <strong>Leaps</strong>, LLC103 Cobble Ridge DriveChapel Hill, NC 27516USA+1 866 450 LEAP (toll free, USA only)+1 919 869-2998 (FAX)e-mail: info@quantum-leaps.comWEB : http://www.quantum-leaps.comhttp://www.state-machine.com“Practical UMLStatecharts inC/C++, SecondEdition: EventDrivenProgramming forEmbeddedSystems”,by Miro Samek,Newnes, 2008Copyright © <strong>Quantum</strong> <strong>Leaps</strong>, LLC. All Rights Reserved.16 of 16

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!