Summary

In my work life, I am working on some systems that will require more complicated firmware architectures built using real time operating systems.  As I need to get more familiar with RTOSs, I thought that I would go ahead and start using them in my PSoC 4 projects.  The logical one to start with is FreeRTOS.  In this article I will take you through the steps to create a PSoC4 FreeRTOS port.

  1. Introduce FreeRTOS
  2. Execute a PSoC4 FreeRTOS Port
  3. Create a PSoC4 FreeRTOS Test Project (the blinking LED)

FreeRTOS Background

FreeRTOS is a light weight, open-source, real time operating systems for embedded systems that was developed by RealTime Engineers.  Their basic business plan is to sell consulting and support services to semiconductor companies their customers.  All of the source code is available (mostly in plain C) and easy to use.  In addition there are ports to 35 MCUs (including all of the Cypress ARM chips).  FreeRTOS is frequently cited as the most popular embedded RTOS which is easy to understand as I have found it easy to use and very stable.

Execute a PSoC4 FreeRTOS Port

The port of FreeRTOS to PSoC4 is actually pretty trivial, once you figure it out.  But I suppose that is how things often go.  FreeRTOS comes preconfigured with a GCC version of an ARM Cortex-M0 port.  All that needs to be done is to hook the basic port to the correct PSoC4 systems.  There are generic porting instruction on the FreeRTOS site but these are my PSoC specific steps:

    1. Download FreeRTOS V9.0.0
    2. Add the include directories “FreeRTOS/Source/include” and “FreeRTOS/Source/portable/GCC/ARM_CM0” to your project by right clicking on the project and editing “Build Settings…”  You should add those directories to the “Additional Include Directories”Configuring the PSoC 4 FreeRTOS build settings
    3. Right click on the project and “Add Existing Item” so that you can add the .c & .h files from FreeRTOS/Source/portable/GCC/ARM_CM0  to your projectAdd the PSoC4 FreeRTOS Files to Project
    4. Add the .c files from FreeRTOS/Source/ to your project
    5. Add the .h files from FreeRTOS/Source/include to your project
    6. Add “heap_1.c” (or which ever memory manager you want) from FreeRTOS/Source/portable/MemMang
    7. Create the “setupFreeRTOS” function to install the Interrupt Service vectors required by FreeRTOS.
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 );
}

8. Create the FreeRTOSConfig.h First, add a new file called FreeRTOSConfig.h file to the project (right click on the project and “add new item”.  This file contains a bunch of CPP macros to setup FreeRTOS.  You can get this file by copy/pasting from the the linked website into your blank FreeRTOSConfig.h file.
9. Modify FreeRTOSConfig.h I made the following changes to the default configuration file:

// Add the PSOC Creator Macros for the PSoC4 Registers 
#include "project.h"
// PSoC Creator creates a #define macro for the clock settings from the DWR
#define configCPU_CLOCK_HZ ( ( unsigned long ) CYDEV_BCLK__SYSCLK__HZ )
// SysTick Defaults to 1ms
#define configTICK_RATE_HZ                      1000
#define configSUPPORT_STATIC_ALLOCATION   0
#define configSUPPORT_DYNAMIC_ALLOCATION  1
#define configTOTAL_HEAP_SIZE               10240
#define configAPPLICATION_ALLOCATED_HEAP 0
// During an assert just put into a busy wait
#define configASSERT ( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

Create a PSoC4 FreeRTOS Test Project

The example project is a simple blinked LED.  It starts with a “Task” function which I call LED_Task.  This just reads the current value of the RED Led pin, inverts it, and writes it back.  Then it does and RTOS delay of 500 ms.  The main look just turns on the interrupt system, initializes the RTOS, Creates the LED Task, then starts the scheduler.  The Scheduler will never return.

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 control the intensity of the LEDs */
    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();
}

Recommended Posts

20 Comments

  1. Very useful, it would be great to have a official FreeRTOS component in Creator 🙂

    • Yes I agree. I did a partial implementation of a component… but it isn’t really good enough to release so I haven’t.

      Cypress is planning on supporting FreeRTOS much better in PSoC6.

  2. Yep, the FreeRTOS support on P6 seems great, i asked about that on the P6 forum, hope one day in the future see that on PSoC 5LP and 4 devices 🙂

    • Not in the cards… but it is easy enough to do…

  3. i just ported it to PSoC 4 AL following your post. worked like a charm on the kit.

  4. HI.Tankyou for your helping.it is very useful.i make new project as said but it has many error.why it is happening?

    • I have no idea. You are going to have to give me more information.

      • I will send my project and ask a question in your email(alan_hawse@cypress.com).ok?

        • It seems like I got your questions answered. Is everything OK?

  5. This seems to work quite well. Thank you for the example and pointing me toward the sources. A couple of notes – With a heap size of 10240 it is too large for a PSOC 4200, I had to reduce that down to about 2000 because the chip in the CY8CKIT-049-4200 only has 4k of RAM. It’s ok for the 4200M with 16k of RAM on the chip for the CY8CKIT-043 board. The part of the code that blinks the LED, RED_Write(~RED_Read());, was not understood during compilation, so I changed that to using a control register, Control_Reg_1_Write(~Control_Reg_1_Read());. It gave me a chance to understand the control register a bit better. Other than that, it was fairly simple and easy to setup and test. Thanks again!

    • You are welcome. Figuring out the right stack size is something that I always wish that i had a better answer for.

  6. Hello Sir
    I have one doubt.
    Where should I write “setupFreeRTOS” function ? Is it need to write in main.c ? Or some other C files?

    • That function was at the top of the file and all it does is hook up the interrupt vectors for the FreeRTOS

  7. Hello, I am trying to follow these steps to port it to a PSOC 5LP (CY8C5888LT*-LP097) prototyping kit, and I am having some issues with build errors with the file includes. Would this work for the the M3 chip? I did make some modifications which I will list below, but then everything else was followed to the letter.

    “FreeRTOS/Source/portable/GCC/ARM_CM0” WAS CHANGED TO “FreeRTOS/Source/portable/GCC/ARM_CM3”

    • It will for sure work. Yes there are a few small things that you need to change for the CM3.

      I haven’t personally tried it… but I know that people have.

      Did you figure it out?

      Alan

  8. Hello,
    Thank you for this awesome tutorial. Works like a charm.
    Not sure if this is the right place to ask this question, but I don’t know where you post this.

    I am working with PSOC 4 BLE and I’ve created a task that calls CyBle_ProcessEvents() in a loop. As i don’t want this task to run all the time (only when there in an event throught ble), I wan’t to block this thread using a semaphore or a queue. The problem is that I don’t know where to give that semaphore or add data to the queue when I want to wake this task. Normally, you do this kind of stuff in an ISR, but in this case i can’t find the ISR for BLESS

    • On PSoC6 we added a callback that is called when the event loop needs to be called. You can see in some/most of the P6 examples I give a semaphore from ISR in the callback. We have not yet added this to PSoC4BLE.. but I for sure want to. Cypress is committed to RTOS support everywhere and I have been driving people to add this mechanism to many places… e.g. CapSense so that you dont have to poll it.

  9. Hi Alan,

    I tried all the steps that you have mentioned in the above article on CY8CKIT-044 PSoc4 , but some how my freeRTOS port seems to be incorrect . My LED is not blinking . I tried the regular UART code without FreeRTOS , it worked perfectly well. However, the same code when written using FreeRTOS did not work. If possible can you help in this ?

    • You are going to have to give me more information… what is happening?


Add a Comment

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