Skip navigation
Home > All Places > ModusToolbox > Blog > 2020 > January

As promised, I am going to add FreeRTOS to the bouncing ball application. Why? So I can explain how to do it and create multiple bouncy ball tasks! Also, I get to leave you guys with a teaser question for next time!

Start by opening the Library Manager and adding both the freertos and abstraction-rtos libraries, as shown. You need the abstraction because the Segger emWin port (in the CY8CKIT-028-TFT library) is built to be able to run on any supported kernel, such as FreeRTOS and RTX (inside Mbed OS).

That's easy enough. Now we need to configure the RTOS. Start by copying the example FreeRTOSConfig.h file from libs/freertos/Source/portable to your top-level folder. If you do not make a copy then the build system will pick up the default version, which is fine in many cases, but I need to make a few changes. In your copy of the file hunt down these definitions and check/change them to the values below.


#define configUSE_MUTEXES               1




The mutex choices are an emWin requirement when using FreeRTOS. If you forget to set those values the application will fail to build because the abstraction-rtos requires them (the error is "cyabs_rtos_freertos.c:280: undefined reference to `xSemaphoreCreateRecursiveMutex'").

The heap choice is a means of choosing how memory is allocated and freed when you create and delete resources like tasks and semaphores. The default is type 1, which does not support freeing at all. That sounds a little dumb but, in reality, many applications just grab the memory and never free it so this is a memory optimization. My application is going to create and delete a task and so I chose a slightly more sophisticated scheme.

To complete the RTOS configuration, delete this line so you do not get swamped with warnings.


#warning This is a template. Copy this file to your project and remove this line. Refer to FreeRTOS for usage details.


That's sorted out the RTOS. Now let's tell emWin to use it. Open the Makefile and find the COMPONENTS line. Change the EMWIN to use OS mode, instead of NOS, and tell the abstraction-rtos to support FreeRTOS. it should look like this:




Now open main.c so we can turn the bounce() function into a task. Add two include files for the OS near the top of the file.


#include "FreeRTOS.h"

#include "task.h"


Now scroll down and change the bounce() function argument to match the FreeRTOS definition of TaskFunction_t, which is a void function accepting a void* argument. The original looks like this:


void bounce( ball_t* ball )


It already returns a void and so, to make it a FreeRTOS task, just change the argument like this:


void bounce( void* arg )


When I create the task I shall pass in a pointer to the ball configuration as an argument and so the first line of the new function should create a new ball pointer variable.


    ball_t* ball = (ball_t*) arg;


The last change to my task is to use the FreeRTOS delay function, which does not hog the CPU like Cy_SysLib_Delay(). The good news is that the FreeRTOS configuration uses a 1ms tick, so the speed calculation does not change, only the function name.


    vTaskDelay( speed );


Still with me? I hope so, but the final main.c file is attached, just in case.

When used in OS mode the emWin REQUIRES all calls to come from a task (i.e. after the OS is started) so we need to create a new task to initialize the GUI and start the bouncing ball tasks. You will not have a good time if you try to call GUI_Init() from main(). Create a new function above main() – I called mine GUI_Init_Task() because it is a task that initializes the GUI. I can be quite literal sometimes!


void GUI_Init_Task( void* arg )


    TaskHandle_t thisTask = xTaskGetCurrentTaskHandle();

    unsigned int pri = uxTaskPriorityGet( thisTask );



    /* Turn on the OLED and set the background color */


    GUI_SetBkColor( GUI_GRAY );



    /* Define the ball initial conditions */

    static ball_t b1 = { GUI_RED, 3, 45, +1 /*RIGHT*/, -3 /*UP*/ };


    xTaskCreate( bounce, "b1", configMINIMAL_STACK_SIZE*2, &b1, pri, NULL );


    vTaskDelete( thisTask );



What is going on here? First of all I am getting the task handle from the OS, then I am using it to get the priority of the task (which will get set when I create it in a moment). Then I decrement that value because I want to create a lot of bounce tasks at a lower priority than this task. This means GUI_Init_Task() will create them all but not let them run until it is good and ready!

Then, I initialize the GUI with three lines code ( GUI_* calls) that I just moved from main().

Also stolen from main() is the ball definition from main(). Instead of calling the bounce function directly, though, I create a task.


    xTaskCreate( bounce, "b1", configMINIMAL_STACK_SIZE*2, &b1, pri, NULL );


Let’s go through all those arguments for creating the task. The first one is the bounce() function. Second is the name, which can prove handy when debugging. Next is the amount of heap I want to get allocated for the bounce function stack – I chose 2x the absolute minimum (that's not a lot but this is a pretty simple task). The fourth argument is the cool part - I am passing in a pointer to the ball, which will get passed into the bounce() function when it starts. Then I specify the priority that was calculated above. The last argument is a pointer to get the task handle but I just pass in NULL because I do not need it.

So now I have a new task waiting to run. How to "release the hound"? I just delete the current task and the new one will automatically get scheduled.


    vTaskDelete( thisTask );


The vTaskdelete() call frees the memory allocated to GUI_Init_Task and so his is why I needed the upgraded heap option in the config file.

We're close now... just need to create our temporary task and start the OS. Here is the code for that (note that it still sets up the random number seed with the ADC):


int main( void )


    CY_ASSERT( cybsp_init() == CY_RSLT_SUCCESS );



    initRandomNumber( P10_7 );


    xTaskCreate( GUI_Init_Task, "GUI", configMINIMAL_STACK_SIZE*2, NULL, 5, NULL );





Cool, now build and program the board. It's... just the same as the non-OS version! So, before you start making effigies of me and sticking pins into my eyes for wasting your time, let's do something that would have been difficult before... add another ball or two or three.

In the GUI_Init_Task() function all you have to do is copy the ball variable (b1), rename it to b2, and change some of the arguments. Then copy the task creation line to start the task. Just change the name of the task to "b2" and the task argument from &b1 to &b2.


    static ball_t b1 = { GUI_RED,  3, 45, +1 /*RIGHT*/, -3 /*UP*/   };

    static ball_t b2 = { GUI_BLUE, 5, 35, -2 /*LEFT*/,  +1 /*DOWN*/ };


    xTaskCreate( bounce, "b1", configMINIMAL_STACK_SIZE*2, &b1, pri, NULL );

    xTaskCreate( bounce, "b2", configMINIMAL_STACK_SIZE*2, &b2, pri, NULL );


Build and program the kit and you have two balls starting at different positions, of different sizes, speeds, and directions (depending upon what you changed in the variable definition).

I think this is a lot of fun. You can now create half a dozen balls if you wish. It's a nice way of using the same task function multiple times, on different data, with just two extra lines of code.

Go on, have a play with the speed and radius of the balls. I left a defect in the application that I am going to fix next time. Can you find it? You should see it with lots of fast balls bouncing around (Hint: change the background color of the screen in GUI_Init_Task() to BLACK so it is easier to see what happens when the balls cross paths).

I don’t know about you, but I quickly got bored of always starting the ball in the same place. I’ve added some code to make that position random. The PSoC 6 device has an on-board true random number generator but, I’ll be honest, I’ve not looked up how to use it yet! So I shall use the poor-man’s option – read the noise on a pin with the ADC. Maybe I’ll circle back to this in the future and do it right!

The ADC on the PSoC 6 connects to port 10 and, after a quick scan of the kit silk screen I found that P10.7 has nothing connected to it (other than a solder hole). OK, that’s a lie. It was not quick and I did not find it. It’s been years since I could read a silk screen with my clapped-out old peepers. I had to go find a teenager and bribe him to read it for me. Why am I so honest with you on this blog???

Anyway, this pin will have enough noise to be a good random number seed. Note that I will not use the noise itself as the random number because it does not have a wide range of values. I’d just get a varying number in a small area of the screen. Instead I am going to use a pair of C stdlib run-time library functions. Start by including the header file.

#include <stdlib.h>

Write this simple function to get a random number from the library rand() function and constrain it to a desired range.

uint32_t getRandomInRange( uint32_t lo, uint32_t hi )


    uint32_t num = rand();


    num %= ( hi - lo );

    num += lo;


    return num;


Then change the bounce() function to call this function instead of hard-coding the values.

    uint16_t xPos = getRandomInRange( BOX_LEFT + radius, BOX_RIGHT  - radius );

    uint16_t yPos = getRandomInRange( BOX_TOP  + radius, BOX_BOTTOM - radius );

The last job is to get the random number and use it as a seed. I did this in a function with a pin as argument so I could experiment with different pins and verify that P10.7 is a good choice. The function initializes the ADC and selects a channel for the desired pin, then it reads the voltage at the pin and passes that value to srand() as the seed argument. Then it dutifully deinitializes the ADC like a good function should.

void initRandomNumber( cyhal_gpio_t noisy_pin )


    cyhal_adc_t adc;

    cyhal_adc_channel_t channel;

    uint16_t seed;


    /* Turn on the ADC for the specified pin */

    cyhal_adc_init( &adc, noisy_pin, (cyhal_clock_divider_t*)NULL );

    cyhal_adc_channel_init( &channel, &adc, noisy_pin );


    /* Read the noise (random) and use it as the seed */

    seed = cyhal_adc_read_u16( &channel );

    srand( seed );


    /* Turn off the ADC */

    cyhal_adc_channel_free( &channel );

    cyhal_adc_free( &adc );


Call this function from main(), with the argument “P10_7”, which is defined in the BSP, before you call bounce().

    initRandomNumber( P10_7 );

Program the kit with the new program and you’ll see that it (probably) does not start the ball in the center of the box. Good eh? Try resetting the kit a few times and the start point should change every time.

bounce_random_1.jpg     bounce_random_3.jpg

As before I have attached a copy of the main.c source file for your reference. I think we have had as much fun as you can have with just one ball now. Next time, I am going to add an RTOS to my project and spawn multiple ball-bouncing tasks…


Fun with the TFT

Posted by MarkS_11 Jan 20, 2020

I have never used the TFT to do anything other than draw some shapes and print text. Of course, that’s not too surprising really... since that’s what they are designed to do! But I am going to make some simple animated applications now and that should force me to dig a little deeper into what the screen can do and how emWin works. Should be fun!

I am going to use the function void GUI_FillCircle(int x0, int y0, int r) to draw a ball and move it around the screen. I’ll be doing this from the TFT_Play project I created last time so I do not need to bother adding the libraries and setting the COMPONENT in the Makefile again. I’ll start by defining the screen dimensions and a box inside that. The idea is that the ball shall bounce around inside the box so the following allows me to define a box of any shape and position.

#define SCREEN_WIDTH    (320)

#define SCREEN_HEIGHT   (240)


#define SCREEN_LEFT     (0)


#define SCREEN_TOP      (0)



/* Define the box in which to bounce */

#define BOX_HMARGIN     (10)

#define BOX_VMARGIN     (10)





The FillCircle function takes a radius as the third argument and so whenever the ball is drawn such that its edge touches a side, we should bounce. Here are some handy functions that figure out if the ball is touching

inline int isBallTouchingLeft(   int x, int radius) { return ( x <= ( BOX_LEFT   + radius ) ); }

inline int isBallTouchingRightint x, int radius) { return ( x >= ( BOX_RIGHT  - radius ) ); }

inline int isBallTouchingTop(    int y, int radius) { return ( y <= ( BOX_TOP    + radius ) ); }

inline int isBallTouchingBottom( int y, int radius) { return ( y >= ( BOX_BOTTOM - radius ) ); }

Next, here is a type for the ball. It may seem unnecessary to create this right now but, in my next blogs, I intend to create multiple balls and bounce them all at the same time.

typedef struct


    GUI_COLOR   color;

    uint8_t    radius;

    uint8_t    speed;

    int8_t     xDir;

    int8_t        yDir;

} ball_t;

The color and radius should be pretty self-explanatory. The speed is going to control the time between moves and has a range between 0 and 50 (#define MAX_SPEED (50)). A speed of 0 is the slowest (boring) and a speed of 50 hurtles around the screen with wild abandon! The direction arguments indicate the number of pixels to move every time, which provides a lot of freedom to alter the angle of travel. Note that they are signed quantities so you can start the ball in either a left/right or north/south.

The meat of the program is going to be in the void bounce( ball_t* ball ) function, below. It takes a pointer to the ball as an argument. Again, this is a little overkill for a single ball, but it will be really useful in my next few blogs. It is good form to make local copies of the ball_t values because it is pointing to memory outside of the function. Making copies of the values helps avoid very bad results if you make the mistake of passing a pointer to local (non-static) data. You will see a little later that I explicitly define the ball in static memory but constrain its scope to the main() function. I could have just created a global but then I would be tempted to access it directly inside bounce(), which is lazy and would have to be re-written in my next blog anyway.

Once the color, speed, size and direction are set, the forever loop draws the ball (in red), delays a while based on the speed, then clears the ball (in black), changes the position, and repeats.  You can also see how those helper functions, above, are used to make the ball actually bounce of the edges.

void bounce( ball_t* ball )


    /* Set up local variables to control the ball */

    GUI_COLOR color = ball->color;

    uint32_t speed = ( MAX_SPEED < ball->speed ) ? 0 : MAX_SPEED - ball->speed;

    uint8_t radius = ball->radius;


    /* Extract the up/down and left/right increments */

    int8_t xDir = ball->xDir;

    int8_t yDir = ball->yDir;


    /* Start the ball at a fixed position */

    uint16_t xPos = BOX_LEFT + ( ( BOX_RIGHT - BOX_LEFT ) / 2 );

    uint16_t yPos = BOX_TOP + ( ( BOX_BOTTOM - BOX_TOP ) / 2 );


    /* Draw - wait - clear - move */



        /* Draw the ball */

        GUI_SetColor( color );

        GUI_FillCircle( xPos, yPos, radius );


        /* Moderate the speed of the ball */

        Cy_SysLib_Delay( speed );


        /* Clear the previously drawn ball */

        GUI_SetColor( GUI_BLACK );

        GUI_FillCircle( xPos, yPos, radius );


        /* If the ball touches an edge, change direction */

        if( isBallTouchingLeft( xPos, radius ) || isBallTouchingRight( xPos, radius ) )

            { xDir = -xDir; }

        if( isBallTouchingTop( yPos, radius ) || isBallTouchingBottom( yPos, radius ) )

            { yDir = -yDir; }


        /* Move the ball in both axes */

        xPos += xDir;

        yPos += yDir;



All that is needed now is to show you the code in main() that sets everything up. I created a small, speedy red ball (in permanent memory) that moves one pixel left-right and 3 pixels up-down on every cycle, then I turned on the display with a gray background, and finally called my bounce() function (which never returns).

    static ball_t b1 = { GUI_RED, 3, 45, +1 /*RIGHT*/, -3 /*UP*/ };



    GUI_SetBkColor( GUI_GRAY );



    bounce( &b1 );

I’ve attached a completed main.c file to this blog so, if you run into problems following my ramblings, you have a good reference. Try out a few different values in the ball_t struct and you’ll find out that making them too big and too fast creates display problems because you start pushing the limits of the OLED update rate. Or maybe it is my eyes???

Here is a picture of the screen after a few seconds. Notice how the background is gray and the ball is leaving a black trail behind it. I did that because I like the way it looks but you should be able to turn the effect off if you do not like it. Try out the program with a few different box sizes too – and let me know if you find a bug!!!




Adding TFT to my project

Posted by MarkS_11 Jan 13, 2020

Last time out I showed you how to create a new application in ModusToolbox IDE 2.0 Today, I am going to add TFT support and draw a few things on the screen. Before I launch into that, I think I should explain how eclipse presents your project, because it is a little different to what you've seen on the command-line. Here is the Project Explorer view.


Binaries is a virtual folder, not a real one on disk. It appears once you have successfully built the application and, in our case, just shows you the elf file(s) that have been built.


Archives is another virtual folder and it shows all the binary libraries in the project. If you look in there you will see the CapSense archives (.a and .ar files) for both hard and soft floating point on the three supported compilers (GNU, Arm and IAR).


Includes lists the include paths. Note that, because we are using a Make-based flow, PSoC applications only need the paths to the compiler run-time libraries in here, not all the ModusToolbox headers.


build is a real folder where all the generated object files are saved, in sub-folders for the kit and compiler configuration (e.g. CY8CKIT-062-WIFI-BT/Debug).


images comes from the starter example project (empty app) and it contains the pictures and diagrams that are displayed in the file.

libs is the folder you've seen before, where the ModusToolbox Library Manager saves lib files and sources.

Hopefully you are now a little more comfortable with Eclipse so let's add that TFT code. Open the Library Manager from the Tools section of the Quick Panel or by right-clicking on the project name in the Project Explorer and opening the ModusToolbox menu. Switch to the Libraries tab and select two libraries.

  • PSoC 6 Middleware / emwin
  • Board Utils / CY8CKIT-028-TFT

The first library is the emWin library from Segger. It's a really easy-to-use and popular graphics package for embedded devices like PSoC. The second is the Cypress shield support package, which enables emWin to run on the PSoC and interface to the shield pins. The library name comes from the separately-purchasable TFT shield, which is included in the 062-WIFI-BT kit.


Apply the changes in the manager and wait until you get the "Successfully updated the project" message. Back in the IDE, you will see the new files in the libs folder.
The emWin software is designed to run in various configurations, as follows.

  • EMWIN_NOSNTS - No multitasking and no touch support
  • EMWIN_NOSTS - No multitasking support, touch support
  • EMWIN_OSNTS - Multitasking support, no touch support
  • EMWIN_OSTS - Multitasking and touch support

We are going to start with the simplest (for us) method, which is to run with no RTOS and no touch screen. Open the Makefile and change line 69 to this.




This will cause the build system to include the right support files for running with no RTOS and to leave out the touch support (the screen does not support it). Finally, it is time to write a little code... three whole lines of it. Include the header file for emWin.


#include "GUI.h"


Then add these two lines in main(), before the infinite loop.



GUI_DispString( "Hello!" );


Press the TFT_Play Program (KitProg3) to build download the program. The string should appear in the top left corner of the screen. That's how easy it is to write to the TFT!

So, now you have a start point for creating cool programs with the TFT. Try moving the text to another location on screen (hint: GUI_DispStringAt) and changing the fore- and background colors. Next time I shall start drawing more stuff and show you how to use the screen with an RTOS. For some light bed-time reading I have attached the Segger emWin documentation to this post. Well worth a look.


ModusToolbox IDE 2.0

Posted by MarkS_11 Jan 11, 2020

In most of my previous blogs I have written about working on the command line and using the project-creator and library-manager utilities. Now I am going to introduce you to the IDE and start a sequence of articles to show off the TFT display integration.

ModusToolbox IDE is just Eclipse with a Cypress twist to make a few things easier to do. There is nothing fancy going on, just a new perspective called ModusToolbox. If you are an Eclipse master and do not like our idea if what's easy, just switch to the regular C/C++ perspective and you'll be grand.
The ModusToolbox perspective is actually intended to save you the chore of repeatedly switching between C/C++ and Debug. It merges the editing views, like Project Explorer, Outline, and Console, with the Breakpoints, Registers, Variables (and so on) debugging views into a single screen. We think it's nifty. We have also grouped some of the most common actions into a super-handy-dandy "Quick Panel" that gives you one-click access to project creation, library management, building, cleaning, configuring, programming, debugging, cooking, bathing, exercising, and calling your mom on the weekend.
In this picture you can see these options for a TFT project that I am about to walk you through.


New Application launches the same GUI that I wrote about in My Second ModusToolbox 2.0 Project. I strongly recommend using this button (or "File->New->ModusToolbox IDE Application" if you're a menu-centric guy) to create projects because this GUI ensures that your files, settings, paths, and launch configurations are all set up correctly. Again, if you know Eclipse and Make inside out (and backwards and ideally sideways) then you could just create an Eclipse C/C++ project and set all that up manually. You could also build a microwave out of chewing gum and after shave but I do not recommend that either.




Search Online for Code Examples just points your browser to our GitHub examples page.




Build and Clean, youll be shocked to learn, build and clean the project by running Make with the appropriate options.




Launches are shortcuts to pre-built launch configurations that program and/or Debug the kit with the application. Configurations exist for Segger J-Link the Cypress KitProg3 (which also supports MiniProg4) hardware.




Tools is a collection of ModusToolbox utilities like the configurators, CapSense tuner, firmware updater (updates KitProg3) and so on. I'll write about those in some detail in future blogs.




Documentation gather together some device and kit information along with links to the documentation for all the libraries included in your project.

OK, that's the Quick Panel. Like it? Good. Let's go make something. I want to show off the TFT display integration that my friends Misha and Oleksandr wrote. So I will use the CY8CKIT-062-WIFI-BT kit that includes a plug-in shield with a 2.4" TFT screen.
Press the New Application button in the Quick Panel and choose the kit.


Choose the "Empty PSoC6 App" template and give your project a name (I chose "TFT_Play").


When you complete the wizard it pulls in all the firmware you need from GitHub and updates the libraries to make sure you are ready to go. The Quick Panel should look like the image above.

Press Build TFT_Play Application to verify that the project will compile and give you HEX and ELF files in the build/CY8CKIT-062-WIFI-BT/Debug folder. If the Console view contains this text then, be happy!

  Total Internal Flash (Available)       1048576   
  Total Internal Flash (Utilized)          21000   

  Total Internal SRAM (Available)      292864    
  Total Internal SRAM (Utilized)         279920  

09:44:19 Build Finished. 0 errors, 0 warnings. (took 59s.752ms)

Plug your kit into a USB port and press TFT_Play Program (KitProg3) to download the program. If your Console view contains this text then, be more happy!

** Program operation completed successfully **
srst_only separate srst_gates_jtag srst_open_drain connect_deassert_srst
Info : SWD DPIDR 0x6ba02477
Info : psoc6.cpu.cm0: external reset detected
Info : psoc6.cpu.cm4: external reset detected
shutdown command invoked

The program does not actually do anything yet. But press the TFT_Play Debug (KitProg3) button to start the debugger. You should be able to step through the BSP setup code. The debugger starts and runs the code up to the start of the main() function. Use the F5 (Step Into) and F6 (Step Over) buttons to get a feel for the debugger. Here is a picture of the debugger buttons providing, in order:

Resume                  Execute code
Suspend                 Pause code execution
Terminate               Close the debugger
Disconnect             (Not enabled by KitProg3)
Step Into                Step into a function call
Step Over              Step over a function call (stay in the calling function)
Step Return           Execute up one level of the stack
Drop to Frame       (Not enabled)
Use Step Filters     (Not enabled)
Restart                   Start the program from the beginning

So now you know how to create a new application inside the IDE. It is remarkably like the command-line and project-creator tools methods isn't it? That's because we're creating a framework that lets you choose the way you work, what IDE you like, what debugger you use, what editor, and so on. Tomorrow I'll write a little bit more about the project and show you how easy it is to get started with the TFT.

I am excited to announce the release of our Wi-Fi Host Driver (WHD), along with TCP/IP and TLS libraries in the PSoC 6 SDK. It's a first step toward the creation of a flexible, cloud-agnostic wireless development flow within ModusToolbox. We'll be adding plenty of new features and protocols to round out the offering over the next few releases.


WHD is already well-proven in the Arm Mbed and Amazon FreeRTOS ecosystems, enabling high-performance Wi-Fi support for the Cypress CYW43012 and CYW4343W devices. We have combined WHD with the popular and trusted lwIP networking stack and the industry-standard Mbed TLS implementation to create a robust and secure solution that is remarkably easy to use.

To add Wi-Fi to your project, simply add the required libraries; WHD, lwIP, wifi-mw-core and mbedTLS (optional) using the ModusToolbox Library Manager (which I have discussed in several previous posts - most notably Extending and Re-Targeting My Second ModusToolbox Project and Managing GitHub Libraries).


Adding the Wi-Fi Host driver, lwIP TCP/IP stack, Mbed TLS and Wi-Fi middleware core libraries to a ModusToolbox project.


Supporting the new libraries are some informative starter projects that you can use to evaluate and learn, then launch your next wireless product. The examples all start with the string "Connectivity" so they are easy to find in the Project Creator and they show you how to make secure (using Mbed TLS)_and non-secure client-server applications.


Choosing a Connectivity starter application in the ModusToolbox Project Creator


I am confident that you'll be able to jump start your next wireless application with these new libraries because they leverage all the ModusToolbox features I have been writing about recently. This makes it easy to quickly pull everything you need into your project, and nothing that you do not. I know I am really excited to try them out - so look out for some new blogs with some tips, tricks and fun examples.


Availability Notice: For about 24 hours after making this post the new examples and libraries were not accessible within ModusToolbox IDE. The New Application wizard was unable to create a Wi-Fi application. This problem is now resolved and application development is fully enabled within the IDE.