Summary
This weekend I found myself down a rabbit hole, beating my head on the wall trying to make a USB driver work properly inside of Parallels & Windows 10 on my Mac (which I still don’t have quite right). While going through that excruciating process I ended up creating 3-4-5 different FreeRTOS PSoC projects, which although not difficult, is still a bit of a pain as it requires 1/2 dozen step. After reflecting on it a while I decided that I needed something easier. The obvious thing to do was to build a FreeRTOS PSoC Component, which I did, but eventually abandoned (Ill talk about that process in the next section). After the component idea was abandoned I decided to just make a template project that could be used to start a FreeRTOS PSoC Project (the next Article).
In this article I will show you:
- An example project using a clever FreeRTOS PSoC Component that I found on GitHub built by E2ForLife
- A discussion of the implementation details of that FreeRTOS PSoC Component
- A discussion of problems with that implementation which lead me to build a template project.
FreeRTOS PSoC Component Example Project
When I first started looking at FreeRTOS I wasn’t totally sure where to start. When I googled FreeRTOS PSoC, one of the first hits was this repo which contains a PSoC Component that was built by “E2ForLife”. I really liked the idea of a component based FreeRTOS implementation, as all you would need to do is place the components… and then away you go. The more that I looked at the component the more that I liked what E2ForLife had done. When I cloned his repo, there was “nothing” in it, but it turns out there is another branch called “Implement-PSoC5” which makes me think that he was partially done (he hasn’t been changed since August 2015)
First, his example project. When you look at the schematic you see a nice looking FreeRTOS PSoC Symbol (obviously E2ForLife draws way better than me).
When you double click the component you see all of the stuff that is normally in FreeRTOSConfig.h which you can set using the GUI instead of the FreeRTOSConfig.h
When you “Generate Application” you can see that he setup all of the FreeRTOS files to come into the Generated Source automatically (though with different names)
And his FreeRTOS PSoC Component example project is straight forward
#include <project.h>
xTaskHandle redTask;
xTaskHandle blueTask;
xTaskHandle greenTask;
void vRedTask( void* pvParameters);
void vGreenTask( void* pvParameters);
void vBlueTask( void* pvParameters);
int main()
{
CyGlobalIntEnable; /* Enable global interrupts. */
xTaskCreate(vRedTask,"red",80,NULL,3,&redTask);
xTaskCreate(vGreenTask,"green",80,NULL,3,&greenTask);
FreeRTOS_Start();
for(;;);
}
void vRedTask( void* pvParameters)
{
for(;;) {
vTaskDelay( 125/portTICK_RATE_MS );
RED_Write( ~RED_Read() );
}
}
void vGreenTask( void* pvParameters)
{
for(;;) {
vTaskDelay( 219/portTICK_RATE_MS );
GREEN_Write( ~GREEN_Read() );
}
}
He built a function called “FreeRTOS_Start()” which installs the interrupt vectors then starts up the scheduler.
uint8 FreeRTOS_initVar = 0;
/* ------------------------------------------------------------------------ */
void FreeRTOS_Init( void )
{
/* 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 );
FreeRTOS_initVar = 1;
}
/* ------------------------------------------------------------------------ */
void FreeRTOS_Enable( void )
{
/* start the scheduler so the tasks will start executing */
vTaskStartScheduler();
}
/* ------------------------------------------------------------------------ */
void FreeRTOS_Start( void )
{
if (FreeRTOS_initVar == 0) {
FreeRTOS_Init();
}
FreeRTOS_Enable();
/*
* After the scheduler starts in Enable(), the code should never get to
* this location.
*/
for (;;);
}
And when you run the FreeRTOS PSoC Component project you get the nice blinking LED (Red and Green)
FreeRTOS PSoC Component
After downloading the project, then opening it I first wanted to look at the components. You can do this by clicking the “Components” tab in the workspace explorer. It looks like he created (or was planning to create) several other components in addition to the “FreeRTOS”.
When you double click on the “FreeRTOS_v8_2.cysym” you will get an editable view of the symbol.
When you right click on the blank part of the canvas, PSoC Creator will bring up this menu.
On the properties menu you can configure which tab the component belongs to in the Component Catalog. In this case he created a tab called “Community” which looks like this in the actual Component Catalog.
To make that happen he setup the “Doc.CatalogPlacement” to be “Community/Operating System/FreeRTOS” (on the properties menu)
The next thing that he did was add a whole bunch of Symbol Parameters which will let the user change the setup of FreeRTOS. Each of these parameters show up as an editable field on the component customers (in the schematic).
In the picture above you can see that he created two new “enumerated” datatypes called “FreeRTOS_CheckStackOverFlowType” “FreeRTOS_MemMangType”. In the picture below you can see the legal values for that type. This lets him restrict the things that the user of the component can select when he places it in his schematic.
Here is what the component looks like when the user actually uses it. You can see the legal fields (from above) and the legal values for those fields (from above)
The next thing that he did was copy all of the FreeRTOS files into component API.
If you remember each FreeRTOS project needs to have a file called “FreeRTOSConfig.h”. But, that file doesn’t appear to exist in the list above. How is that? Remember that when PSoC Creator builds a project it copies the API into your generated source directory, but it renames each of the files to be INSTANCE_NAME_filename. In this example, “Config.h” will become “FreeRTOS_Config.h” (FreeRTOS is the instance name in the schematic)
In FreeRTOS each of the features of the RTOS turn into a #define that is 0 or 1. When the component was created he modified “Config.h” so that each of the parameters on the component set values for the #defines in the “Config.h” file. And there is a bunch of them so that must have taken a good bit of work. Here is an example of a section of his “Config.h”. Each place you see the back-tick $parameter back-tick PSoC Creator will substitute the value of the parameter (I am typing back-tick because WordPress interprets the actual symbol to mean something special and I don’t know how to get it into the text)
#if CY_PSOC4
/* Port-dependent settings - not user-editable */
#define configCPU_CLOCK_HZ ( ( unsigned long ) CYDEV_BCLK__SYSCLK__HZ )
/* Application settings - user editable */
#define configMAX_PRIORITIES ( `$MAX_PRIORITIES` )
#define configTOTAL_HEAP_SIZE ( `$TOTAL_HEAP_SIZE` )
#elif CY_PSOC5
/* Device settings - not user-editable */
#define configCPU_CLOCK_HZ ( ( unsigned long ) BCLK__BUS_CLK__HZ )
/* Application settings - user editable */
#define configMAX_PRIORITIES ( `$MAX_PRIORITIES` )
#define configTOTAL_HEAP_SIZE ( `$TOTAL_HEAP_SIZE` )
#else
#error "This FreeRTOSConfig.h file is for PSoC 4 and PSoC 5LP devices only"
#endif
#define configUSE_PREEMPTION `$USE_PREEMPTION`
#define configUSE_IDLE_HOOK `$USE_IDLE_HOOK`
#define configUSE_TICK_HOOK `$USE_TICK_HOOK`
#define configTICK_RATE_HZ ( ( portTickType ) `$TICK_RATE_HZ` )
Because each filename changes name, he had to go fix all of the #includes to look like this example from croutine.c (this was a bunch of work)
/* PSoC Component Customizations */
#include "`$INSTANCE_NAME`.h"
#include "`$INSTANCE_NAME`_task.h"
#include "`$INSTANCE_NAME`_croutine.h"
He also wanted to be able to have all of the FreeRTOS memory management schemes included in the project at one time. To solve this problem he put an #if around all of the code in heap_1, heap_2 … that adds and removes the appropriate memory manager.
#if (`$MemManager` == 2)
.
.
.
.
.
#endif
A FreeRTOS PSoC Template Project
When I started working on FreeRTOS I knew that I wanted to use V9.0. But the component was setup for V8.2. So I launched into the process of converting the component. This turned out to be a colossal pain in the ass because of the massive number of “small” changes. In addition I didn’t really like having to change the names of key files (even the stupidly named semphr.h). Moreover, the source code as a component debate was raging wildly inside of Cypress and in general is on the way out. So I decided to implement this as a template project instead of a component.
All that being said, what E2ForLife did I continue to think was really clever.