Hello World!

  1. Define Helpful Constants
  2. Create a Timer Task
  3. Start a Timer Task
  4. Hello World Function
  5. Full Code Example

In order to provide you with a better understanding of the concept of how the XDK is working, it is necessary to understand the core concepts of the FreeRTOS operating system it uses.

For the beginning, the basic principles of timer tasks are sufficient to build simple applications for the XDK.

In that regard, this article gives a very first impression about how to use a timer task to implement a periodic running application, which prints “Hello World” to the console of the XDK-Workbench.

Please note if the application requires more advanced handling of timer tasks or even more operating tasks, it is recommended to take a look at the corresponding article in the FreeRTOS section for a more detailed explanation about them.

Define Helpful Constants

Before we start with the implementation of the Hello World example, it is particularly advantageous to define some helpful constants in order to get a clearer understanding of the function implementations.

For that, as explained in the previous article all following implementation will take part in a XdkApplicationTemplate.

/* constant definitions */
#define TIMER_AUTORELOAD_ON pdTRUE
#define TIMER_AUTORELOAD_OFF pdFALSE
#define SECONDS(x) ((portTickType) (x * 1000) / portTICK_RATE_MS)

The definitions TIMER_AUTORELOAD_ON and TIMER_AUTORELOAD_OFF describes, if the timer should be automatically restarted or not. SECONDS defines the delay which the timer waits before it restarts itself.

Create a Timer Task

Timer tasks can run periodically without the need of manual implementations of any kind of loops. You can create a new timer task by using the function xTimerCreate(). This function creates a new software timer instance, allocates the storage required by the new timer, initializes the new timer’s internal state, and returns a handle by which the new timer can be referenced.

// Function that creates the Hello World timer task.
void createHelloWorldTimerTask(void){
  xTimerHandle xHandle;

  // Create the "Hello World" timer task running every second
  // Validated for portMAX_DELAY to assist the task to wait infinitely
  // Since ticks cannot be 0 in the FreeRTOS timer, ticks is assigned to 1
  xTaskCreate(helloWorld, (const char * const) "HelloWorldTimerTask", 256, &ucParameterToPass, 1, &xHandle);
  xHandle = xTimerCreate((char * const) "HelloWorldTimerTask", SECONDS(1), TIMER_AUTORELOAD_ON, NULL, helloWorld);

  [...]

}

Start a Timer Task

Once we created a timer sucessfully, we are now able to start the timer by using the function xTimerStart().

If you wish to stop, reset, delete or change the period of your timer, you can find the full timers.h file reference.

// Function that creates the Hello World timer task
void createHelloWorldTimerTask(void){

  [...]

  // Check whether timer was successfully created
  if( xHandle == NULL ){
    // The timer was not created
  }
  else{
    // Start the timer
    xTimerStart(xHandle, 0);
  }
}

Hello World Function

Second, we need to implement the function helloWorld() so the XDK does exactly what it should do: Say “Hello” to the world!

// Function that prints "Hello World" on the serial console.
void helloWorld(void * pvParameters ){
  // Task code goes here.
  printf("Hello world\r\n");
}

Afterwards, you can simply call the function createHelloWorldTimerTask() within the function appInitSystem() for XDK-Workbenches below 3.4.0. For XDK-Workbenches above 3.4.0 use the function AppControllerEnable() as shown in the following subchapter Full Code Example.

Full Code Example

Note: The full code example is intended for XDK-Workbench versions 3.4.0 and higher.

/*----------------------------------------------------------------------------*/

/* --------------------------------------------------------------------------- |
 * INCLUDES & DEFINES ******************************************************** |
 * -------------------------------------------------------------------------- */

/* own header files */
#include "XdkAppInfo.h"
#undef BCDS_MODULE_ID  /* Module ID define before including Basics package*/
#define BCDS_MODULE_ID XDK_APP_MODULE_ID_APP_CONTROLLER

/* system header files */
#include <stdio.h>

/* additional interface header files */
#include "BCDS_CmdProcessor.h"
#include "FreeRTOS.h"
#include "timers.h"

/* --------------------------------------------------------------------------- |
 * HANDLES ******************************************************************* |
 * -------------------------------------------------------------------------- */

static CmdProcessor_T * AppCmdProcessor;/**< Handle to store the main Command processor handle to be used by run-time event driven threads */

/* --------------------------------------------------------------------------- |
 * VARIABLES ***************************************************************** |
 * -------------------------------------------------------------------------- */

/* constant definitions */
#define TIMER_AUTORELOAD_ON pdTRUE
#define TIMER_AUTORELOAD_OFF pdFALSE
#define SECONDS(x) ((portTickType) (x * 1000) / portTICK_RATE_MS)

/* --------------------------------------------------------------------------- |
 * EXECUTING FUNCTIONS ******************************************************* |
 * -------------------------------------------------------------------------- */

// Function that prints "Hello World" on the serial console.
void helloWorld(void * pvParameters ){
  // Task code goes here.
  printf("Hello world \n\r");
}

// Function that creates the Hello World timer task.
void createHelloWorldTimerTask(void){
  xTimerHandle xHandle;

  // Create the "Hello World" timer task running every second
  // Validated for portMAX_DELAY to assist the task to wait infinitely
  // Since ticks cannot be 0 in the FreeRTOS timer, ticks is assigned to 1
  xHandle = xTimerCreate((char * const) "HelloWorldTimerTask", SECONDS(1), TIMER_AUTORELOAD_ON, NULL, helloWorld);

  // Check whether timer was successfully created
  if( xHandle == NULL ){
    // The timer was not created
  }
  else{
    // Start the timer
    xTimerStart(xHandle, 0);
  }
}

/* --------------------------------------------------------------------------- |
 * BOOTING- AND SETUP FUNCTIONS ********************************************** |
 * -------------------------------------------------------------------------- */

static void AppControllerEnable(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);

    /* Enable necessary modules for the application and check their return values */
    createHelloWorldTimerTask();
}

static void AppControllerSetup(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);
    Retcode_T retcode = RETCODE_OK;

    /* Setup the necessary modules required for the application */

    retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerEnable, NULL, UINT32_C(0));
    if (RETCODE_OK != retcode)
    {
        printf("AppControllerSetup : Failed \r\n");
        Retcode_RaiseError(retcode);
        assert(0); /* To provide LED indication for the user */
    }
}

void AppController_Init(void * cmdProcessorHandle, uint32_t param2)
{
    BCDS_UNUSED(param2);

    Retcode_T retcode = RETCODE_OK;

    if (cmdProcessorHandle == NULL)
    {
        printf("AppController_Init : Command processor handle is NULL \r\n");
        retcode = RETCODE(RETCODE_SEVERITY_ERROR, RETCODE_NULL_POINTER);
    }
    else
    {
        AppCmdProcessor = (CmdProcessor_T *) cmdProcessorHandle;
        retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerSetup, NULL, UINT32_C(0));
    }

    if (RETCODE_OK != retcode)
    {
        Retcode_RaiseError(retcode);
        assert(0); /* To provide LED indication for the user */
    }
}

/** ************************************************************************* */