February 27, 2007
In this issue:
  • Understanding ARM Cortex-M3
  • Quantum Kernel (QK) Supports Generic Co-processors
  • Quantum Kernel (QK) Supports Thread-Local Storage (TLS)
  • QP integrated with emWin from SEGGER and µC/GUI from Micrium
  • Quantum Platform™ (QP) Released on SourceForge.net

Understanding ARM Cortex-M3

Cortex

The new ARM Cortex-M3 architecture is getting lately a lot of attention. (Check for instance the IAR white paper "Choosing an ARM processor ARM7 vs Cortex-M3", or just google up "Cortex-M3").

While most of the writings about the new ARM architecture present a high-level overview of features and perhaps some comparisons and market forecasts, you will be much better informed if you look at actual implementations of everyday tasks with Cortex. For instance, how do you do preemptive mutlitasking with Cortex? How do you use the Wait-For-Interrupt sleep mode? How do you implement system clock tick, or software trace dump with Cortex?

All of these questions and more are answered in the new Quantum Development Kits (QDKs) for Cortex-M3. Quantum Leaps has recently released QDKs for QP/C, QP/C++, as well as QDKs-nano for QP-nano, each in two versions: for RealView and the IAR ARM compiler. All these QDKs come with detailed manuals in PDF and all have been validated with the EKC-LM3S811 evaluation kit from Luminary Micro -- the first silicon vendor of Cortex-M3 devices.

EKC-LM3S811

Perhaps the most interesting part of the QDKs for Cortex-M3 is the implementation of the QK preemptive kernel. As you'll see, a single-stack, preemptive kernel implements in software exactly the same prioritization algorithm as the new Nested Vectored Interrupt Controller (NVIC) integrated into ARMv7 architecture. In other words, QK extends to the task level the NVIC prioritization scheme used for nested interrupts.

NOTE: The QDKs-nano for Cortex-M3 provide the world's smallest implementation of preemptive mutlitasking for Cortex-M3, and are particularly suitable for the low-end, $1-apiece Stellaris LM3S1xx devices.

Download QDKs for Cortex-M3 »


Quantum Kernel (QK) Supports Generic Co-processors

QK

Starting from version 3.2.04, QK supports a generic extended context switch for various co-processors, such as hardware floating point co-processors or other hardware accelerators.

C/C++ compilers typically support various co-processors, such as FPUs, in that they generate instructions for these hardware accelerators. However, the compiler typically assumes that any interrupt necessarily returns to the exact point of preemption and therefore the C/C++ compiler generally does NOT perform the co-processor context saving and restoring in the interrupts.

NOTE: The C/C++ compiler typically assumes that the co-processor is NOT used in the interrupt context. This assumption is still maintained in the QK extended context switch implemenation. Please note that the interrupt duration is defined in QK from the entry to the ISR till the call to the QK_ISR_EXIT() macro.

Being a preemptive kernel, QK in general does not return to the original interrupted task, but rather performs asynchronous preemption if a higher-priority task becomes ready to run as a result of the interrupt. This obviously violates the assumption of the C/C++ compiler, and therefore requires special care to save and restore the co-processor context upon asynchronus preemption.

For best performance, maximum flexibility, and minimal stack usage, the implementation of the extended context switch is divided in two parts. The first part is handled in the interrupt exit (typically the QK_ISR_EXIT() macro).

The following listing shows the QK_ISR_EXIT() macro for the x86 processor with the x87 math co-processor (FPU). The interrupt exit sequence begins with disabling all interrupts (1), which is immediately followed by writing the EOI instruction to the interrupt controller (2). The QK priority is restored from the temporary stack variable pin_ (passed as the argument to the macro). The rest of the exit sequence is only executed only if the interrupt has preempted a task (e.g., the saved priority pin_ is less than QF_MAX_ACTIVE). If additionally, the preempted task is using the co-processor (which is stored in the bitmask os_Object__ for this task) the extended QK scheduler is invoked. Otherwise the regular QK scheduler is called.

    #define QK_ISR_EXIT(pin_) do { \
(1)     disable(); \
(2)     outportb(0x20, 0x20); \
        QK_currPrio_ = (pin_); \
        if ((pin_) <= QF_MAX_ACTIVE) { \
            if ((QF_active_[pin_]->osObject__ & QK_FPU_THREAD) != 0) { \
(3)             QK_scheduleExt_(); \
            } \
            else { \
(4)             QK_schedule_(); \
            } \
         } \
    } while (0)

The extended scheduler QK_schedExt_() performs the co-processor context saving and restoring before launching any task that would asynchronously preempt the interrupted task (3). To do this, QK_schedExt_() allocates the co-processor context on the stack, so the extended scheduler call uses MORE of the stack than the regular scheduler. However, if the co-processor is not used by a particular task, the extended context switch is not necessary, and the regular QK scheduler is adequate (4). In this case the extended co-processor context switch is not performed and the co-processor context does not even need to be allocated on the stack.

The QK implementation of the extended context switch is much more efficient than it can be done in any traditional multi-stack kernel. In QK, you only pay of the extended context in asynchronous preemptions. The synchronous task-to-task preemptions are regular C-function calls, which don't need any extra attention from the kernel. In contrast, in a traditional kernel you pay the full price of the extended context switch every time. Additionally, QK allows you to be selective and perform the extended context switch only for tasks that actually use the co-processor, rather than for all tasks.

NOTE: The QK port to 80x86 included in the standard QK distribution demonstrates the extended context switch for the 80x87 math co-processor.

QK is described in Section 4 in the "QP Programmer's Manual »
Download QP with the QK extended context switch for the x87 FPU »


Quantum Kernel (QK) Supports Thread-Local Storage (TLS)

QK

Starting from version 3.2.04, QK supports "Thead-Local-Storage" (TLS), which is used for example in the Newlib C-runtime library.

The concept of "Thead-Local-Storage" (TLS), as it is used in the Newlib's reentrancy model, might not be quite obvious at first glance, so here is a short description how it works (see ESD article "Embedding with GNU: Newlib" ). Once you know the details, it will be clear how to make sure you set it up properly in your system.

Newlib declares one _reent structure and aims the global _impure_ptr pointer at it during initialization, so everything starts out correctly for situations where only one thread of execution is in the library at a time. To facilitate multiple contexts, you must take two additional steps: you must pro-vide one _reent structure for each execution thread (active object in QF), and you must move _impure_ptr between these structures during context switches.

QK supports the TLS concept and provides a context-switch hook QK_TLS(), which is invoked every time a different task priority is processed. The following code fragment from QK port to the Altera Nios II processor defines the macro QK_TLS() for re-assigning the Newlib's _impure_ptr during context switches:

#define QK_TLS(tls_)        \
    if ((tls_) != (void *)0) { \
        _impure_ptr = (struct _reent *)(tls_); \
    } else ((void)0)

While the QK_TLS() macro will move the _impure_ptr, you are responsible for allocating the _reent structure in each active object that actually uses the Newlib facilities. In other words, you have the option of not allocating the _reent structure and not performing the _impure_ptr re-assignment for those active objects that don't use the Newlib.

The QDPP sample application for Nios II processor provides an example of using the TLS selectively for Philosopher active objects, but not for the Table active object. The Philosopher active objects use the TLS as follows (see file \examples\nios2\qk\gcc\qdpp_std_2C35\philo.cpp). First the struct _reent tls_ is declared as data member of the Philo class:

class Philosopher : public QActive {
private:
    struct _reent tls_;               // thread-local storage (TLS) for NewLib

    uint8_t num_;                                // number of this philosopher
    QTimeEvt timeEvt_;                        // to timeout thinking or eating

    . . .
};

Next, the pointer to the TLS storage is passed to the framework during the invocation of the QAc-tivre::start() function:

void philosopherStart(uint8_t n, uint8_t prio,
                      QEvent const *qSto[], uint32_t qLen)
{
    Q_REQUIRE(n < N);

    _impure_ptr = &l_philo[n].tls_;           // initialize the TLS for NewLib
    _REENT_INIT_PTR(_impure_ptr);

    TableEvt ie;                                       // initialization event
    ie.philNum = n;
    l_philo[n].start(prio,
                     qSto, qLen,
                     &l_philo[n].tls_,                   // pointer to the TLS
                     0,
                     (QEvent *)&ie);
}

In contrast, the Table active object does not use the TLS, and simply passes the NULL pointer to the QActive::start() method (see \examples\nios2\qk\gcc\qdpp_std_2C35\table.cpp).

Nios II-Cyclone II Dev Kit
Download QDK-Nios2 demonstrating how to use TLS »


QP integrated with emWin from SEGGER
and µC/GUI from Micrium

QP-emWin QP-emWin

Many embedded systems today come with a graphic LCD and sophisticated Graphical User Interfaces (GUIs). The popular embedded GUI libraries, such as emWin from SEGGER, µC/GUI from Micrium, PEG from Swell Software, and many others, provide anything from low-level LCD drivers, through drawing primitives, assortments of widgets, all the way to sophisticated window managers.

One thing, however, that these software packages do NOT provide is the high-level "screen logic" to control the overall behavior of the GUI. As it turns out, Quantum Platform™ (QP) beautifully complements the GUI libraries by exactly providing the high-level structure to the GUI system. This is, of course, hardly surprising because GUIs are exemplary event-driven systems, which QP is exactly designed to handle.

This new Quantum Leaps Application Note "QP and emWin Embedded GUI" describes how to use QP with the emWin™ Embedded GUI from SEGGER and also µC/GUI from Micrium, which technically are the same products. The Application note describes how to use emWin with and without the Windows Manager and comes with the executable examples running in the SEGGER's emWin simulator for Windows.

Download the QP-emWin integration demo »

Quantum Platform™ (QP) Released on SourceForge.net

SourceForge.net

Quantum Leaps, LLC released its Quantum Platform (QP) family of frameworks to SourceForge.net. The Generally Available (GA) distributions of QP/C, QP/C++, and QP-nano are available for download from this most popular open source repository.

Visit the QP project on SourceForge.net »

Latest Development Kits

Quantum Platform
Quantum Platform
Quantum Spy
Quantum Spy software trace
Quantum Platform-nano
Quantum Platform-nano
Quantum Kernel-nano
Quantum Kernel-nano
C 3.3.00
(25-Jan-07)
Dual License Release
3.3.00
(25-Jan-07)
Commercial Only Release
1.5.06
(25-Jan-07)
Dual License Release
1.5.06
(25-Jan-07)
Commercial Only Release
C++ 3.3.00
(25-Jan-07)
Dual License Release
3.3.00
(25-Jan-07)
Commercial Only Release
N/A N/A

SUBSCRIPTION INFORMATION: You have received this emal because you have contacted Quantum Leaps or specifically elected to receive news from Quantum Leaps. To make sure you continue to receive this Newsletter in your e-mail inbox, and that it is not sent to bulk or junk folders, please add news@quantum-leaps.com to your address book.

If you no longer wish to receive e-mail from Quantum Leaps, please unsubscribe at: quantum-leaps.com/news or reply to this e-mail with the word "unsubscribe" in the subject or body of the message.

If you have been forwarded this newsletter and would like to receive it directly, please also visit quantum-leaps.com/news to subscribe.