Summary: FreeRTOS PSoC Examples

Although in my last Article I said that I would get back to BLE Centrals this week, that turns out to not be the case because I have found myself down the FreeRTOS rabbit hole.  This week I will publish several FreeRTOS PSoC examples using PSoC 4 and PSoC 6.  I found myself here because I was working on BLE centrals on PSoC4, and I thought that I should try it on PSoC 6 to see how well it worked.  But, given the expansive capabilities of the chip, the reality is that PSoC 6 will almost certainly be programmed using an RTOS.  So, I decided to use FreeRTOS to try out the different features of PSoC 6.  But given that I don’t really know PSoC 6 yet … and I don’t really know FreeRTOS … I decided to experiment first on PSoC 4 examples first then once I understood what to with FreeRTOS, try the same things on PSoC 6.

Here is a video I took on Saturday in my office with three different PSoCs (PSoC 4 BLE, PSoC 4M, and PSoC 6) running FreeRTOS.  (yes my office looks like a tornado hit it).  The moral of the story is never underestimate the power of the blinking LED (to figure out what is going on).

In this article I will show FreeRTOS PSoC Examples:

  • Start with a single blinking LED Task
  • Add 2nd UART based command processor thread

In the upcoming articles I will add more FreeRTOS PSoC Examples:

  • Issue commands via a queue between the two threads
  • Interrupt processing & a Semaphore
  • Im not sure what else yet 🙂

Single Blinking LED

I start this process by following the instruction in my previous post to create a FreeRTOS example.  The project is straight forward, it does:

  • Installs the FreeRTOS vectors (lines 9-22)
  • Creates the LED Task (lines 41-48)
  • Starts the scheduler (line 50)
  • Runs the LED_Task until the end of time, blinking the LED (lines 25-33)
#include "project.h"
#include "FreeRTOS.h"
#include "timers.h"

extern void xPortPendSVHandler(void);
extern void xPortSysTickHandler(void);
extern void vPortSVCHandler(void);
#define CORTEX_INTERRUPT_BASE          (16)
void setupFreeRTOS()
{
    /* Handler for Cortex Supervisor Call (SVC, formerly SWI) - address 11 */
    CyIntSetSysVector( CORTEX_INTERRUPT_BASE + SVCall_IRQn,
        (cyisraddress)vPortSVCHandler );
    
    /* Handler for Cortex PendSV Call - address 14 */
	CyIntSetSysVector( CORTEX_INTERRUPT_BASE + PendSV_IRQn,
        (cyisraddress)xPortPendSVHandler );    
    
    /* Handler for Cortex SYSTICK - address 15 */
	CyIntSetSysVector( CORTEX_INTERRUPT_BASE + SysTick_IRQn,
        (cyisraddress)xPortSysTickHandler );
}


void LED_Task(void *arg)
{
    (void)arg;
    
	while(1) {
        RED_Write(~RED_Read());
        vTaskDelay(500);
	}
}

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    setupFreeRTOS();
  
    /* Create LED task, which will blink the LED */
    xTaskCreate(
        LED_Task,       /* Task function */
        "LED Blink",    /* Task name (string) */
        200,            /* Task stack, allocated from heap */
        0,              /* No param passed to task function */
        1,              /* Low priority */
        0 );            /* Not using the task handle */
      
    vTaskStartScheduler();
    while(1); // get rid of the stupid warning
}

You can see the blinking LED in the video from above.

UART Thread

Once you have the blinking LED working, that means you have all of the environment setup etc… for some reason this always feels like a big step.  I then copy the BlinkingLED project and give it the name “UART-Thread”.  Then add a debugging UART to the schematic:

FreeRTOS PSoC Examples - PSoC Schematic

Now you can add the UART Thread to your project.  It is pretty simple:

  • Starts the UART
  • Gets a key from the keyboard (line 47)
  • If it is an ‘a’ it prints out “Working” (line 51)
  • If it is a ‘t’ it calls the function vTaskList which makes a dump of the process currently running (more on this later) (lines 54-60)
#include "project.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "event_groups.h"
#include "timers.h"

extern void xPortPendSVHandler(void);
extern void xPortSysTickHandler(void);
extern void vPortSVCHandler(void);
#define CORTEX_INTERRUPT_BASE          (16)
void setupFreeRTOS()
{
    /* Handler for Cortex Supervisor Call (SVC, formerly SWI) - address 11 */
    CyIntSetSysVector( CORTEX_INTERRUPT_BASE + SVCall_IRQn,
        (cyisraddress)vPortSVCHandler );
    
    /* Handler for Cortex PendSV Call - address 14 */
	CyIntSetSysVector( CORTEX_INTERRUPT_BASE + PendSV_IRQn,
        (cyisraddress)xPortPendSVHandler );    
    
    /* Handler for Cortex SYSTICK - address 15 */
	CyIntSetSysVector( CORTEX_INTERRUPT_BASE + SysTick_IRQn,
        (cyisraddress)xPortSysTickHandler );
}


void LED_Task(void *arg)
{
    (void)arg;
    
	while(1) {
        RED_Write(~RED_Read());
        vTaskDelay(500);
	}
}

void UART_Task(void *arg)
{
    (void)arg;
    static char buff[500];
    UART_Start();
    UART_UartPutString("Started UART\n\r");
    char c;
    
	while(1) {
        c = UART_UartGetChar();
        switch(c)
        {
            case 'a':
            UART_UartPutString("Working\n\r");
            break;
            
            case 't':
                UART_UartPutString("********************************************\n\r");
                UART_UartPutString("Task          State   Prio    Stack    Num\n\r"); 
                UART_UartPutString("********************************************\n\r");
                vTaskList(buff);
                UART_UartPutString(buff);
                UART_UartPutString("*********************************************\n\r");
   
            break;
        }
        taskYIELD();
    }
}

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    setupFreeRTOS();
  
    /* Create LED task, which will blink the LED */
    xTaskCreate(
        LED_Task,       /* Task function */
        "LED Blink",    /* Task name (string) */
        200,            /* Task stack, allocated from heap */
        0,              /* No param passed to task function */
        1,              /* Low priority */
        0 );            /* Not using the task handle */
   
    
    /* Create UART Task which will control the serial port */
    xTaskCreate(
        UART_Task,       /* Task function */
        "UART",          /* Task name (string) */
        0x400,           /* Task stack, allocated from heap */
        0,               /* No param passed to task function */
        1,               /* Low priority */
        0 );             /* Not using the task handle */
   
    vTaskStartScheduler();
    while(1);
}

 

Testing the project

When I program the development kit, the LED starts blinking.  That is good.  Then I press ‘t’ which dumps out a table of the processes running.  The columns are

  • The name of the task
  • The state of the task (R-Running, B-Blocked, S-Suspended)
  • The priority (0-configMAX_PRIORITIES from FreeRTOSConfig.h)
  • The highwater mark of the stack usage of that thread.  In the UART thread I declared 0x400 (1024) so it appears I have used most of the RAM.
  • The task number

FreeRTOS PSoC Examples UART Serial Port

It is interesting that there are two tasks that I didnt create.  The FreeRTOS requires that there alway be some task, so it automatically creates an IDLE tasks which it runs when there is nothing else available to run.  It is possible to put the chip to sleep by adding to the IDLE task.  The other task is the Timer Service task which is what enables me to use the software delay (vTaskDelay).

If you have more FreeRTOS PSoC Examples that you are interested in please make a comment and maybe Ill create them.

As always, you can find the FreeRTOS PSoC Examples on the IoT Expert GitHub site or git@github.com:iotexpert/PSoC-FreeRTOS-Examples.git

Topic Description
FreeRTOS: A PSoC4 FreeRTOS Port An introduction to making FreeRTOS work on PSoC 4
FreeRTOS PSoC Examples Using multiple tasks in FreeRTOS
FreeRTOS Queue Example Using a queue to communicate between tasks
PSoC 6 FreeRTOS - The First Example Booting FreeRTOS on PSoC 6
FreeRTOS Binary Semaphore An first example of a binary semaphore
FreeRTOS Binary Semaphore (Part 2) Removing polling in the UART Task
FreeRTOS Counting Semaphore An example using a counting semaphore
PSoC FreeRTOS Reading I2C Sensors with a shared I2C Bus
PSoC FreeRTOS Task Notify A light weight scheme to replace Semaphores
PSoC FreeRTOS Task Notification Values A very light weight method to transfer one word of information into a task

Recommended Posts

6 Comments

    • Thank you… I will give a try and write about it.

  1. Hi,
    Maybe i ask for a lot but here’s a couple of projects i think might be interesting to see:
    * A project using the FreeRTOS tickless mode.
    * And i haven’t saw the FreeRTOS examples using multi-core microcontrollers, but, what use cases can require running FreeRTOS on both cores on the P6? i don’t know how the cores would “talk” to each other, using IPC or regular FreeRTOS semaphores and queues.

    • OK… for sure on Tickless

      As to the dual core P6…. that wasn’t really the intent of the chip as the 2nd core (the CM0+) was really put there as a security processor and a link-layer manager for the BLE. But I might try it.

  2. Tried this example on PSoc Creator 4.2 but apparently some of the names have changed and some functions seem to be missing. Example: CyIntSetSysVector() becomes Cy_SysInt_SetVector(). Unfortunately vTaskList() does not seem to exist at all.

    • The Cy_SysInt functions are for PSoC 6 not PSoC 4.
      To get vTaskList to be in your project you need to “configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must be defined as 1 in FreeRTOSConfig.” from the FreeRTOS documentation.

      Alan


Leave a Reply to Alan Hawse Cancel reply

Your email address will not be published. Required fields are marked *