QP/C  6.6.0

The DPP example for TI-RTOS on EK-TM4C123GXL board is located directory examples/ti-rtos/arm-cm/dpp_ek-tm4c123gxl.

EK-TM4C123GXL board
The TI-RTOS requires its own tooling (XDCTOOLS) and is too big to fit into the 3rd_party/ directory in the QP/C++ distribution. Therefore, you need to download and install TI-RTOS on your machine before you can build any examples (preferably in the default location C:/TI). Please refer to the TI Application Note "TI-RTOS for TivaC Getting Started Guide" (Literature Number: SPRUHU5D) for more information.

The sub-directory ccs contains the project files that you can import into the TI CCS IDE.

The sub-directory iar contains the workspace and project file that you can open in IAR EWARM IDE.

After you load the DPP example into the EK-TM4C123GXL board, the application should start blinking the on-board three-color LED (located below the Reset button). You can press the SW1 button (lower-left corner) to PAUSE the philosophers for as long as the button is depressed. The philosophers resume dining when you release the User button. (In the PAUSED state the Table active object stops granting permissions to eat, so eventually all philosophers end in the "hungry" state.)

main.c for TI-RTOS

The main.c for TI-RTOS is actually identical as for the built-in QV/QK/QXK kernels. In particular, you do not need to provide stack space to active objects, because they execute in the context of lightweight TI-RTOS Swis (Software Interrupts), which don't need private stacks.

int main() {
static QEvt const *tableQueueSto[N_PHILO];
static QEvt const *philoQueueSto[N_PHILO][N_PHILO];
static QSubscrList subscrSto[MAX_PUB_SIG];
static QF_MPOOL_EL(TableEvt) smlPoolSto[2*N_PHILO]; /* small pool */
Philo_ctor(); /* instantiate all Philosopher active objects */
Table_ctor(); /* instantiate the Table active object */
QF_init(); /* initialize the framework and the underlying RT kernel */
BSP_init(); /* initialize the Board Support Package */
/* initialize publish-subscribe... */
QF_psInit(subscrSto, Q_DIM(subscrSto));
/* initialize event pools... */
QF_poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0]));
/* start the active objects... */
for (n = 0U; n < N_PHILO; ++n) {
AO_Philo[n], /* AO to start */
(uint_fast8_t)(n + 1), /* QP priority of the AO */
philoQueueSto[n], /* event queue storage */
Q_DIM(philoQueueSto[n]), /* queue length [events] */
[1] (void *)0, /* stack storage (not used) */
[2] 0U, /* size of the stack [bytes] */
(QEvt *)0); /* initialization event */
AO_Table, /* AO to start */
(uint_fast8_t)(N_PHILO + 1), /* QP priority of the AO */
tableQueueSto, /* event queue storage */
Q_DIM(tableQueueSto), /* queue length [events] */
[3] (void *)0, /* stack storage (not used) */
[4] 0U, /* size of the stack [bytes] */
(QEvt *)0); /* initialization event */
return QF_run(); /* run the QF application */
  • 1-4 You don't provide the per-active object stack at startup;


TI-RTOS is configured specifically for the DPP application by means of the configuration file dpp.cfg, which is included in the ccs/ and iar/ directories. This file is processed in the custom build step for TI-RTOS.

The highlights of the Board Support Package (BSP) for TI-RTOS are explained below:

/* Clock function used in the application ==================================*/
[1] void clk0Fxn(UArg arg0) {
~ ~ ~
[2] QF_TICK_X(0U, &l_tickHook); /* process time events for rate 0 */
/* Perform the debouncing of buttons...
~ ~ ~
if (tmp != 0U) { /* debounced SW1 state changed? */
if (buttons.depressed == 0U) { /* is SW1 depressed? */
static QEvt const pauseEvt = { PAUSE_SIG, 0U, 0U};
[3] QF_PUBLISH(&pauseEvt, &l_tickHook);
else { /* the button is released */
static QEvt const serveEvt = { SERVE_SIG, 0U, 0U};
[4] QF_PUBLISH(&serveEvt, &l_tickHook);
[5] void myIdleFunc() { /* idle callback (see dpp.cfg) */
~ ~ ~
#ifdef NDEBUG
/* Put the CPU and peripherals to the low-power mode.
* you might need to customize the clock management for your application,
* see the datasheet for your particular Cortex-M3 MCU.
__asm (" WFI"); /* Wait-For-Interrupt */
/* QF callbacks ============================================================*/
[6] void QF_onStartup(void) {
[7] static Clock_Struct clk0Struct;
Clock_Params clkParams;
[8] Clock_Params_init(&clkParams);
[9] clkParams.startFlag = TRUE;
[10] clkParams.period = 1000U/BSP_TICKS_PER_SEC;
/* Construct a periodic Clock Instance */
[11] Clock_construct(&clk0Struct, &clk0Fxn, clkParams.period, &clkParams);
  • 1 The function clk0Fxn() provides the TI-RTOS clock service (configured later in step [11]);
  • 2 The TI-RTOS clock function calls the QF_TICK_X() service to process the QP time events;
  • 3-4 The TI-RTOS clock function might post or publish events to active objects;
  • 5 The TI-RTOS is configured (in the dpp.cfg file) to call the myIdle() function from the TI-RTOS idle loop; In the Release build configuration this function can put the CPU into a low-power sleep mode. In the Spy build configuration, the idle callback can perform QS software tracing output to the host.
  • 6 The QF_onStartup() function configures and starts interrupts. Here the function also configures and starts TI-RTOS clock service;
  • 7 The TI-RTOS Clock_Struct is allocated statically;
  • 8 The Clock Parameters are initialized to default;
  • 9 The Clock service is started;
  • 10 The Clock period is set to fire the desired number of times per second (BSP_TICKS_PER_SEC). NOTE: The system clock rate in microseconds is configured in the TI-RTOS configuration file dpp.cfg;
  • 11 The Clock service is constructed in the statically allocated memory;
Currently, the BSP does not demonstrate the QS (Q-SPY) tracing. Demonstrating the QS tracing for this example is planned in the future.

Next: uC/OS-II examples

unsigned char uint8_t
exact-width 8-bit unsigned int
Definition: stdint.h:29
void QF_onStartup(void)
Startup QF callback.
void QF_poolInit(void *const poolSto, uint_fast32_t const poolSize, uint_fast16_t const evtSize)
Event pool initialization for dynamic allocation of events.
Definition: qf_dyn.c:112
Define the type of the critical section status.
Definition: qk/qf_port.h:221
Event structure.
Definition: qep.h:153
int_t QF_run(void)
Transfers control to QF to run the application.
Definition: qutest.c:70
#define Q_DIM(array_)
Helper macro to calculate static dimension of a 1-dim array_.
Definition: qassert.h:331
void QF_psInit(QSubscrList *const subscrSto, enum_t const maxSignal)
Publish-subscribe initialization.
Definition: qf_ps.c:86
#define QACTIVE_START(me_, prio_, qSto_, qLen_, stkSto_, stkLen_, par_)
Polymorphically start an active object.
Definition: qf.h:215
void QF_init(void)
QF initialization.
Definition: qutest.c:55
unsigned int uint_fast8_t
fast at-least 8-bit unsigned int
Definition: stdint.h:36
#define QF_TICK_X(tickRate_, sender_)
Invoke the system clock tick processing QF_tickX_().
Definition: qf.h:625
#define QF_PUBLISH(e_, sender_)
Invoke the event publishing facility QF_publish_().
Definition: qf.h:582
#define QF_MPOOL_EL(evType_)
Memory pool element to allocate correctly aligned storage for QMPool class.
Definition: qmpool.h:165
Priority Set of up to 32 elements.
Definition: qpset.h:63