Skip navigation
Home > All Places > ModusToolbox > Blog > Authors MarkS_11
1 2 3 Previous Next

ModusToolbox

35 Posts authored by: MarkS_11

If you have been following along with my TFT blogs you may have tried to use the debugger to figure out what was causing the crescent shapes bug. But, because I added FreeRTOS to the project, you’d have seen these warnings when starting the debugger.

 

Error: FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around

 

All this means is that the OCD connection software is looking for a symbol that is no longer part of the FreeRTOS code base. The actual debugging still works but you get no information about tasks, which is really handy when you  have 6 tasks running the same C code.

There is a workaround to the problem that is easy to implement. You just define and use that variable. If you read my last blog you’ll know that I have something of an aversion to using global variables but this is a case where you simply have to. So I’ll suck it up and get on with it. Add this line at the top of the file, outside of any function.

 

int uxTopUsedPriority;                              // FreeRTOS/OCD debug workaround

 

Then, in main(), add a line that just sets it to the lowest priority.

 

uxTopUsedPriority = configMAX_PRIORITIES - 1;                  // FreeRTOS/OCD debug workaround

 

That’s all you need to do. It gets rid of the warning and turns on task-aware debugging. Cool, but what’s that? Well, start the debugger and put a breakpoint in your bounce() function, on the vTaskDelay() call is a good place. Then run the code until the breakpoint is hit. Look in the debugger view – you can see the 6 bounce tasks, plus a Timer Service and IDLE tasks.

Here are screenshots of the debugger view from before the OS starts (note the “No RTOS thread” message) and after hitting the breakpoint a couple of times. In the second picture you see all the threads and can work out where the code is when the task was stopped. In my picture b1 is suspended in the vTaskDelay() call and b2 has just hit the breakpoint.

Handy!

Another cool thing to do with breakpoints is to make them task-specific. Go to the breakpoints view and locate the breakpoint in bounce(). Right-click to open the Breakpoint Properties window. Click on Filter and you’ll see a list of tasks with checkboxes. Unset all but one task and apply. Now run the code again and it will only break in the task you chose.

 

This can be really handy because you make the tools figure out whether you have stopped in the context you are actually interested in. But there is a price. It’s slow. This is because the breakpoint is still hit and the target register set and some memory has to be sent up to the debugger every time.

It’s what I call Heisenberg debugging. You can use the debugger to look at what’s happening, but the act of looking somewhat alters the behavior. When you are waiting for mission-critical events, like BLE connection events, this is a real problem. But when you are debugging a system with no such concerns, like our’s, it’s a useful tool. And fun too… put the breakpoint in your slowest-running task and watch the balls all crawl slowly along while your task is asleep.

Everyone who sees my screen when I am working on these blogs says I am re-creating “pong”. Well, that was not my plan… but why not? Maybe I should add a movable paddle and a score board!

Did you find my bug? Make these changes to your program and it’s really obvious. First change the background color to GUI_BLACK in the GUI_Init_Task() function (as I suggested in my last post). Then create a bunch of bouncing balls. I have six of them and some are bouncing at near full speed.

 

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

    GUI_Init();

    GUI_SetBkColor( GUI_BLACK );

    GUI_Clear();

 

    /* Define the ball initial conditions */

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

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

    static ball_t b3 = { GUI_GREEN,   4, 47, -1 /*LEFT*/,  +1 /*DOWN*/ };

    static ball_t b4 = { GUI_CYAN,    6, 10, -2 /*LEFT*/,  -1 /*UP*/   };

    static ball_t b5 = { GUI_YELLOW,  7, 50, -1 /*LEFT*/,  +1 /*DOWN*/ };

    static ball_t b6 = { GUI_MAGENTA, 7, 50, +1 /*RIGHT*/, -1 /*UP*/   };

 

    /* Create ball tasks */

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

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

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

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

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

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

 

Having six balls bouncing is cool but, if you run them too fast then you can get ball clippings left on the screen. Every now and again you see little crescents appearing. Grrrrr…..

The issue manifests itself very clearly when you have balls running at speed == 50. This is because there is no delay in the loop and the OS is more likely to time slice that task at some other part of the loop (during the delays in the TFT library). The result is a jumbled order of screen updates causing balls to be drawn and cleared in other ball’s colors.

Note that the problem is not just because of speed. It is just more common at high speed. The lazy boy fix is to not allow the delay to be zero. That would greatly reduce the occurrence of crescents… but the defect is still there and GOSH DARN I am going to fix it!

What we need to do is make sure that task switching only happens during the vTaskDelay() call. What we need is a simple binary semaphore. One of those bad boys will let me implement a resource protection scheme that ensures the OS will not stop my tasks in the middle of a screen update.

I will have just one semaphore and six tasks will be giving and taking it. The lazy boy solution to that is to create a global variable for the semaphore. But globals make me a little itchy. They are not baaaaad. But they are not gooood either. I just only want to use them when I really have to. And, today, I do not. Cue my friend the “static” keyword. Inside bounce() I use it to create a single instance of the semaphore in static memory, not on the stack.

 

       static SemaphoreHandle_t screen = NULL;

 

This is now a shared variable but it is protected from being messed with by another function (it is a “static automatic” if you want to get all fancy pants about it… but we don’t) and I’m not itchy any longer. But I have a new problem – how to initialize the variable once and only once? I need to make sure the semaphore is initialized before any task uses it but not reinitialized by every task. The trick is to check it is NULL and, if so, initialize it. Otherwise just continue into the drawing loop.

 

       if( NULL == screen )

             { screen = xSemaphoreCreateBinary(); }

 

I do not know which task the OS will run first but I do not care. Whichever one runs will create the mutex and the rest will not.

All we need now is to wrap the call to vTaskDelay() with calls to give and then take the semaphore. When a task owns the semaphore it will prevent the others from running, so the ball gets moved properly before the next one starts to move.

 

    xSemaphoreGive( screen );

    vTaskDelay( speed );

    xSemaphoreTake( screen, portMAX_DELAY );

 

Ready to go now? Nearly. Usually, when I write these how-to articles, I start by telling you to include the header file. But forgetting to add header files is just something engineers do! So I thought I’d wait until the end and tell you about it. Tell the compiler about semaphores by adding this line after the includes for FreeRTOS.h and task.h.

 

#include "semphr.h"

 

I do not know why the file name is abbreviated… maybe semphr is easier to type than semphaore, semapahore, shampemore, semifour…oh yeah, it is!

Anyway, program that and you should be fully rid of crescent shapes on your screen!

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

#define configUSE_RECURSIVE_MUTEXES 1

#define configHEAP_ALLOCATION_SCHEME (HEAP_ALLOCATION_TYPE2)

 

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 README.md 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:

 

COMPONENTS=EMWIN_OSNTS FREERTOS

 

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 );

    pri--;

 

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

    GUI_Init();

    GUI_SetBkColor( GUI_GRAY );

    GUI_Clear();

 

    /* 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 );

    __enable_irq();

 

    initRandomNumber( P10_7 );

 

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

 

    vTaskStartScheduler();

}

 

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…

MarkS_11

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_RIGHT    (SCREEN_WIDTH-1)

#define SCREEN_TOP      (0)

#define SCREEN_BOTTOM   (SCREEN_HEIGHT-1)

 

/* Define the box in which to bounce */

#define BOX_HMARGIN     (10)

#define BOX_VMARGIN     (10)

#define BOX_LEFT        (SCREEN_LEFT+BOX_HMARGIN)

#define BOX_RIGHT       (SCREEN_RIGHT-BOX_HMARGIN)

#define BOX_TOP         (SCREEN_TOP+BOX_VMARGIN)

#define BOX_BOTTOM      (SCREEN_BOTTOM-BOX_VMARGIN)

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 */

    for(;;)

        {

        /* 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_Init();

    GUI_SetBkColor( GUI_GRAY );

    GUI_Clear();

 

    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!!!

 

bounce1.jpg

MarkS_11

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.

project-explorer.png

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 README.md 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.

lib-mgr.png

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.

 

COMPONENTS=EMWIN_NOSNTS

 

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_Init();

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.

MarkS_11

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.

quick-panel.png

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.

new-project.png

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

starter.png

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:

debug-buttons150.png
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.

MarkS_11

Managing GitHub Libraries

Posted by MarkS_11 Dec 29, 2019

In my last blog, Using the retarget-io library to enable printf(), I assuaged some of my guilt over not bothering to explain where the pin and baud rate defines come from in Extending and Re-Targeting My Second ModusToolbox Project. Now it is time to explain the library shenanigans! Actually, there are precisely zero shenanigans involved... it is all clean and above board... but I just wanted to say "shenanigans". I think it is out of my system now.

When you add a library from the command line using git clone, as I have been doing in my last few blogs, then you get all the firmware and a .git folder, where all the GitHub information is maintained. If you are good at using git (I am not!!!) then this is all you need to be able to update the firmware to new releases and all that good stuff. If you are not a git maven (like me) or are a bit lazy (a lot like me) then Library Manager can really help you out.

When you add a library using the manager then it creates a cunning extra file with the extension .lib. This lib file records where the library came from and its version. It contains just a single line, like this example for retarget-io:

 

https://github.com/cypresssemiconductorco/retarget-io/#latest-v1.X

 

Simple huh? There really is no shenanigans here - just the GitHub address and the version (after the #).

When you run the Library Manager it reads this file to figure out what libraries are included in the project and marks them with a checkbox. In this image the manager is showing that the retarget-io library is included. Also, if you click in the Version column you will see all the available versions. If you select a different version and press Apply the manager will replace the firmware for you.

The "Latest_v1.X" version is special. It means that the manager will update to the newest available v1 implementation. If we release a new version, the manager (or "make getlibs") will update your project without any extra effort on your part. Good eh? Of course, when you are deep into a project you will probably want to lock down the version. It's easy, just use the pull-down to choose a specific version, like "1.0.0 release" in our example, and press Apply. That will get the right software and only update it if you go back and request it explicitly.

This is probably my last blog of 2019. I hope you found some of this year's content helpful! I'll be back in January with some more descriptions of cool ModusToolbox features and examples of how to leverage them to make fabulous applications. And maybe some more shenanigans!

Last week I slid in a call to cy_retarget_io_init() in my application without explaining it. I felt a bit naughty about that and so promised to explain it to you. Here goes!

The Cypress retarget-io library implements low-level character I/O functions expected by the Arm and GNU C compilers. These functions are called from the printf() and scanf() functions that come from the STDIO C-language run-time library. The actual names of the functions depend on the compiler you are using, but the library is written so that the right implementations are enabled for you automatically. Here is some code to remind you how it works (this code works on all supported compilers).

Start by adding these two header files to tell the compiler about the low-level functions and printf(), respectively.

#include "cy_retarget_io.h"

#include <stdio.h>

In the main() function you need to just initialize the UART, check it worked correctly, and start printing with wild abandon.

    result = cy_retarget_io_init( CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE );

    CY_ASSERT( result == CY_RSLT_SUCCESS );

    printf( "Program started...\r\n" );

Note that the CY_ASSERT() call just halts the application if the expression equates to false, which is probably a little simplistic in a real application but makes the point here. About the only reasons why this call would fail, though, are that you have a) passed in a pin that is not accessible from any of the PSoC SCB blocks, or b) requested a baud rate that cannot be achieved, or c) have already initialized the UART.

So, this is all fine and dandy but the arguments to cy_retarget_io_init() need a little explanation. The function just sets up the UART for the pins defined by the first two arguments - CYBSP_DEBUG_UART_TX and CYBSP_DEBUG_UART_RX. The prefix to those macros is a hint as to where they are defined - the BSP. Take a look in your project folder and jump down into the libs folder - this is where the Library Manager saves the content you select. There are folders with the prefix "TARGET", which are the kit BSPs. Looking in TARGET_CY8CKIT-062-WIFI-BT you will see a useful little file called cybsp_types.h. Here's a snippet from that file.

/** Pin: UART RX */

#define CYBSP_DEBUG_UART_RX         (P5_0)

/** Pin: UART TX */

#define CYBSP_DEBUG_UART_TX         (P5_1)

The author of the BSP has helpfully defined the pins that connect to the KitProg device. This means that, regardless of the kit you have, those macros will help you set up I/O across the KitProg bridge (to your computer). When you call cy_retarget_io_init() with those macros as the first two arguments, the library code figures out which SCB they are connected to and initializes it as a UART. If you wish to redirect the I/O then just change the arguments of the desired pins, such as P6_0 and P6_1.

The other argument in our function call is CY_RETARGET_IO_BAUDRATE, which is obviously the baud rate, but where is it defined. This is not a BSP macro. Rather, it is a retarget-io library define which helps all Cypress examples run UARTs at the same speed. Look in libs/retarget-io and you will see cy_retarget_io.h, the file that we included at the top of this blog. The following define is easy to find in that file.

/** UART baud rate */

#define CY_RETARGET_IO_BAUDRATE         (115200)

As you can see, if you want to run your UART at a different speed, just use a different number, such as 9600, like this:

    cy_retarget_io_init( P6_1, P6_0, 9600 );

Hopefully this explains what is going on with the library and explains how to make simple changes in your code to modify the printf() speed and hardware. I feel better for honoring my commitment from last week... next time I shall explain how the Library Manager works its magic!

 

In My Second ModusToolbox 2.0 Project I wrote about the project-creator tool and built a TCPWMSquareWave project for the CY8CKIT-062-WIFI-BT kit. Today I am going to add a library to the project and enable printf() through a device UART. Wooooooo! First, let's take a look at the libraries we already have (which came in with the code example project that I cloned last week).

lib-mgr-1.png

There are two TARGET_* folders, which are the kit BSPs. Then there are things like capsense and psoc6pdl. Each folder contains a library and we are going to add a new one. I do this by starting the library-manager from my shell.

 

yfs@YFS-T550 ~/TCPWMSquareWave

$ ~/ModusToolbox/tools_2.0/library-manager/library-manager.exe &

[1] 2258

yfs@YFS-T550 ~/TCPWMSquareWave

 

After a short while the tool pops up and shows the BSPs that you can use. It also lists more that you can add, if you like.

lib-mgr-2.png

Switching to the "Libraries" tab I can see the ones that are already on disk. Check the "retarget-io" box and press "Apply" to add that library.

lib-mgr-3.png

A quick look at the folders shows that the manager has added the new folder and a .lib file (more on that next time).

lib-mgr-4.png

Now that we have added the library, let's write a bit of code to try it out. Start by adding these two include files. These bring in the function definitions for the retarget-io library and also the C run-time printf() function, which is pretty much the raison d'etre of this blog.

 

#include "cy_retarget_io.h"

#include <stdio.h>

 

Note that I am using the angley bracketty thingies around stdio.h, also known as the less than and greater than signs, and probably a more mature and professional name as well. That is just because I am grabbing the header from a system rather than user path. It turns out that you can just use the regular quotes in ModusToolbox projects if you want but, if you set up your compiler paths using -J instead of -I, then angley thingies it must be!

Now we need to tell printf() where to print. Here is the code to do that - put it in main() somewhere after the call to cybsp_init() and before the PWM code. The cy_retarget_io_init() function sets up the UART that gets used when printf() has formatted the string and is sending out the characters via __write(), which is in libs/retarget-io/cy_retarget_io.c. Note that __write() is the function used by the GNU compiler printf() implementation. If you build with the Arm Compiler then the library automatically sets up fputc() instead - so you can change compilers and continue to print without torture!

 

    result = cy_retarget_io_init( CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE );

    CY_ASSERT( result == CY_RSLT_SUCCESS );

    printf( "TCPWM Square Wave started...\r\n" );

 

To check this works just run "make program" and connect up a terminal emulator.

lib-mgr-5.png

Woo hoo! Looks like I got it right. Now I am going to make another change with the library manager - switching to a new target board. I have touched on this before but switching hardware is really easy in ModusToolbox. The only essential change is to edit the "TARGET" rule in the Makefile. That works for command line builds but, as we saw in the comments for Re-Targeting My ModusToolbox 2.0 project, it does not regenerate the launch configurations for the IDE. So, to avoid confusion it is probably best to use the library-manager. There is a handy drop-down menu for that and so I have made it a habit to use that to change the BSP. Just choose the board, as shown here, then press "Apply" to safely switch the default BSP for your project.

lib-mgr-6.png

As before, all I need to do now is "make program" (and remember to connect the new board to my laptop!). It works like a charm!

Now I have to admit that I kinda glossed over two things today. Firstly, I talked about the libraries but did not explain how the manager knows where to get them and how to update them, so I'll fix that soon. I also told you about the cy_retarget_io_init() function and completely glossed over where the arguments come from! I do not like the idea of you guys blindly copying the code and not understanding it fully - that makes me feel itchy - so I'll explain that too. Honest. I promise... next time!

With any luck, my last two blogs - My First ModusToolbox Project and Re-Targeting My ModusToolbox 2.0 Project - gave you some insight into the anatomy of ModusToolbox projects. The most important learning from them was not really to get used to the git clone and make commands, rather to understand where the files in a project come from and how to manage them. That said, I have to admit, it's a lot to keep in your brain. Let's face it, we've all got more important things to dedicate memory cells to!

Let's look at some easier methods of creating projects. In your ~/ModusToolbox/tools_2.0/project-creator folder there are two executables which automate the process for you.

 

project-creator-cli.exe

As you might have guessed, this is the command-line tool. I am going to pretend to be a real engineer for a moment and advise you to start by running the command with the "--help" option to get started. Obviously, being lazy and obstinate, I did not do this, but it would have saved me some time so I'll ask you practice what I preach, not what I do! It will tell you about the --board-id, --app-id and --user-app-name options, which I'll use in a moment. But there is also the fiendishly clever --list-apps option which tells you all the GitHub-hosted projects that are compatible with a kit. Here are the options for the WIFI-BT kit.

 

$ ~/ModusToolbox/tools_2.0/project-creator/project-creator-cli.exe --list-apps CY8CKIT-062-WIFI-BT

Getting manifest...

super-manifest: https://github.com/cypresssemiconductorco/mtb-super-manifest/raw/v2.X/mtb-super-manifest.xml

Successfully acquired BSP/Application information from remote server.

List of template applications supported by the board "CY8CKIT-062-WIFI-BT":

mtb-example-psoc6-capsense-buttons-slider

mtb-example-psoc6-capsense-buttons-slider-freertos

mtb-example-psoc6-crypto-aes

mtb-example-psoc6-crypto-sha

mtb-example-psoc6-crypto-trng

mtb-example-psoc6-empty-app

mtb-example-psoc6-emulated-eeprom

mtb-example-psoc6-emwin-eink

mtb-example-psoc6-emwin-oled

mtb-example-psoc6-fault-handling

mtb-example-psoc6-gpio-interrupt

mtb-example-psoc6-hello-world

mtb-example-psoc6-i2c-master

mtb-example-psoc6-i2c-master-ezi2c-slave

mtb-example-psoc6-i2c-slave-callback

mtb-example-psoc6-i2s

mtb-example-psoc6-mcwdt

mtb-example-psoc6-pdm-pcm

mtb-example-psoc6-pdm-to-i2s

mtb-example-psoc6-qspi-readwrite

mtb-example-psoc6-qspi-readwrite-sfdp

mtb-example-psoc6-rtc-basics

mtb-example-psoc6-smartio-ramping-led

mtb-example-psoc6-spi-master

mtb-example-psoc6-spi-master-dma

mtb-example-psoc6-switching-power-modes

mtb-example-psoc6-tcpwm-square-wave

mtb-example-psoc6-uart-transmit-receive

mtb-example-psoc6-uart-transmit-receive-dma

mtb-example-psoc6-usb-hid

mtb-example-psoc6-wdt

 

Nice! This is a convenient way to see the examples without trawling around https://github.com/cypresssemiconductorco. I am going to try the tcpwm-square-wave example. I shall call my project "square-wave" and put it into the folder called "square" using those options we saw in the help output. Here goes...

 

$ ~/ModusToolbox/tools_2.0/project-creator/project-creator-cli.exe --board-id CY8CKIT-062-WIFI-BT --app-id mtb-example-psoc6-tcpwm-square-wave --user-app-name square_wave

Getting manifest...

super-manifest: https://github.com/cypresssemiconductorco/mtb-super-manifest/raw/v2.X/mtb-super-manifest.xml

Successfully acquired BSP/Application information from remote server.

 

 

==============================================================================

= Cloning 'mtb-example-psoc6-tcpwm-square-wave' =

==============================================================================

Cloning https://github.com/cypresssemiconductorco/mtb-example-psoc6-tcpwm-square-wave into C:/Users/yfs directory...

Cloning into 'square_wave'...

remote: Enumerating objects: 13, done.

remote: Counting objects: 100% (13/13), done.

remote: Compressing objects: 100% (10/10), done.

remote: Total 13 (delta 0), reused 10 (delta 0), pack-reused 0

Unpacking objects: 100% (13/13), done.

 

 

Cheking out latest-v1.X...

Note: checking out 'latest-v1.X'.

 

 

You are in 'detached HEAD' state. You can look around, make experimental

changes and commit them, and you can discard any commits you make in this

state without impacting any branches by performing another checkout.

 

 

If you want to create a new branch to retain commits you create, you may

do so (now or later) by using -b with the checkout command again. Example:

 

 

  git checkout -b <new-branch-name>

 

 

HEAD is now at 17f92ae Upload mtb-example-psoc6-tcpwm-square-wave 1.0.0.55

 

 

==============================================================================

= Creating 'TARGET_CY8CKIT-062-WIFI-BT.lib' file(s) =

==============================================================================

 

 

==============================================================================

= Updating Makefile for 'square_wave' =

==============================================================================

Tools Directory: C:/Users/yfs/ModusToolbox/tools_2.0

 

 

Initializing import: mtb-example-psoc6-tcpwm-square-wave

 

 

==============================================================================

= Importing libraries =

==============================================================================

Git is git version 2.17.0, found at /usr/bin/git

 

 

Searching application directories...

Application directories search complete.

 

 

Searching libs directory...

Found 2 file(s)

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT.lib

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CPROTO-062-4343W.lib

Libraries were processed. Re-evaluating libs directory...

Found 14 file(s)

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/capsense.lib

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/core-lib.lib

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/psoc6cm0p.lib

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/psoc6hal.lib

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/psoc6make.lib

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/psoc6pdl.lib

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CPROTO-062-4343W/libs/capsense.lib

        Library "capsense.lib" was already processed at C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/capsense.lib.

        Skipping current reference...

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CPROTO-062-4343W/libs/core-lib.lib

        Library "core-lib.lib" was already processed at C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/core-lib.lib.

        Skipping current reference...

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CPROTO-062-4343W/libs/psoc6cm0p.lib

        Library "psoc6cm0p.lib" was already processed at C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/psoc6cm0p.lib.

        Skipping current reference...

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CPROTO-062-4343W/libs/psoc6hal.lib

        Library "psoc6hal.lib" was already processed at C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/psoc6hal.lib.

        Skipping current reference...

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CPROTO-062-4343W/libs/psoc6make.lib

        Library "psoc6make.lib" was already processed at C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/psoc6make.lib.

        Skipping current reference...

    Processing file C:/Users/yfs/square_wave/libs/TARGET_CY8CPROTO-062-4343W/libs/psoc6pdl.lib

        Library "psoc6pdl.lib" was already processed at C:/Users/yfs/square_wave/libs/TARGET_CY8CKIT-062-WIFI-BT/libs/psoc6pdl.lib.

        Skipping current reference...

Libraries were processed. Re-evaluating libs directory...

Found 14 file(s)

libs directory search complete.

 

 

==============================================================================

= Import complete =

==============================================================================

 

 

Successfully created "square_wave" application.

 

In one command I have created a new project, added a BSP, set it as the default for build and program, and pulled in all firmware libraries needed to build the application. Just plugging in the kit and running "make program" is all it takes to build and program the board.

 

project-creator.exe

 

If the above is still too much typing then run the non-CLI executable - ~/ModusToolbox/tools_2.0/project-creator/project-creator.exe. You can start it from Windows Explorer or launch from the command line with "~/ModusToolbox/tools_2.0/project-creator/project-creator.exe &". Note that I do it in the background with the ampersand at the end of the line, so I can still use the shell.

 

The GUI tool (why is it not spelled "gooey"?) starts by grabbing a bunch of information from the mtb-super-manifest.xml file on GitHub (I'll write more about this file, and creating your own manifests, in a future blog).

project-creator-1.png

Just press "Next>" to get to the good stuff.

project-creator-2.png

Now pick your kit.

project-creator-3.png

Choose the application and give it a name and a sensible location.

project-creator-4.png

You then get a summary of what you ordered. Press "Create" and let the tool assemble all the parts. You'll recognize all the GitHub and make output in the dialog. Once it is all done you just "make program" in the shell to get the application onto the kit (you may want to edit main.c to change the value of PWM_FREQUENCY to make sure your new program is actually running rather than the old one!).

 

Next time, I shall show you how to add BSPs and firmware libraries to a project using another helpful tool, the library-manager.

Last time out we got hello world running on the PROTO-062-4343W kit. That was a lot of fun for me… because I have that kit! Actually, I have about 20 of them because they arrived too late for the training event last week. But most of you don’t have 20 kits so, today, I am going to show you how to re-target an application to another kit.

 

All ModusToolbox applications have a BSP. It is the thing that defines the PSoC device, the memory layout, the connection to the Wi-Fi device over SDIO, the CapSense buttons and sliders, the I2C and UART peripherals, and the mechanical buttons and LEDs. We give these things standard names, like CYBSP_USER_LED, so that applications using those names can run on just about any kit even if the physical pins connected to the LED are different. So, to re-target our application we only have to do two things; add a new BSP to the project and tell the build tools to use it instead of the original BSP. Some examples actually include more than one BSP, for convenience, so you can often skip the first step!

 

I’ve been writing about CY8CPROTO-063-BLE kit recently (github.com/cypresssemiconductorco/TARGET_CY8CPROTO-063-BLE) so let’s switch our program to that one. You can read about the BSP on the GitHub site or you can just get on with it and download the thing (as you can tell, I’m a type-first, read-later guy). Just jump into the libs folder and clone the BSP.

 

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world

$ cd libs

 

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world/libs

$ git clone https://github.com/cypresssemiconductorco/TARGET_CY8CPROTO-063-BLE

Cloning into 'TARGET_CY8CPROTO-063-BLE'...

remote: Enumerating objects: 156, done.

remote: Counting objects: 100% (156/156), done.

remote: Compressing objects: 100% (106/106), done.

Receiving objectsremote: Total 156 (delta 43), reused 153 (delta 43), pack-reused 0:   % (85/

Receiving objects: 100% (156/156), 391.77 KiB | 1.42 MiB/s, done.

Resolving deltas: 100% (43/43), done.

Checking out files: 100% (135/135), done.

 

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world/libs

$ ls -la

total 34

drwxr-xr-x 1 yfs 1049089  0 Nov 4 09:24 .

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:24 ..

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:12 capsense

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:12 core-lib

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:12 psoc6cm0p

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:13 psoc6hal

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:13 psoc6make

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:14 psoc6pdl

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:12 retarget-io

-rw-r--r-- 1 yfs 1049089 67 Nov  1 15:40 retarget-io.lib

drwxr-xr-x 1 yfs 1049089  0 Nov 1 16:12 TARGET_CY8CPROTO-062-4343W

-rw-r--r-- 1 yfs 1049089 82 Nov  1 15:40 TARGET_CY8CPROTO-062-4343W.lib

drwxr-xr-x 1 yfs 1049089  0 Nov 4 09:24 TARGET_CY8CPROTO-063-BLE

 

As you can see, you have added a new TARGET folder. Great, now let’s build for it. I can almost feel you gearing up for a stream of edit-this and move-that with a little bit of delete-the-other and a frustrating time. Not exactly, just add the name of the target to the build command.

 

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world/libs

$ cd ..

 

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world

$ make build TARGET=CY8CPROTO-063-BLE

Tools Directory: C:/Users/yfs/ModusToolbox/tools_2.0

 

Initializing build: mtb-example-psoc6-hello-world Debug CY8CPROTO-063-BLE GCC_ARM

    Stale device files detected. Running device configurator to regenerate files...

 

Auto-discovery in progress...

-> Found 158 .c file(s)

-> Found 36 .S file(s)

-> Found 18 .s file(s)

-> Found 0 .cpp file(s)

-> Found 0 .o file(s)

-> Found 4 .a file(s)

-> Found 377 .h file(s)

-> Found 0 .hpp file(s)

-> Found 0 resource file(s)

Applying filters...

Auto-discovery complete

 

==============================================================================

= Building application =

==============================================================================

Building 142 file(s)

    Compiling app file startup_psoc6_01_cm4.S

    Compiling app file cy_syslib_gcc.S

    Compiling app file cycfg.c

    Compiling app file cycfg_clocks.c

    Compiling app file cycfg_peripherals.c

    Compiling app file cycfg_pins.c

    Compiling app file cycfg_routing.c

    Compiling app file cycfg_system.c

    Compiling app file cybsp.c

    Compiling app file system_psoc6_cm4.c

    Compiling app file cy_capsense_centroid.c

    Compiling app file cy_capsense_control.c

    Compiling app file cy_capsense_csd.c

    Compiling app file cy_capsense_csx.c

    Compiling app file cy_capsense_filter.c

    Compiling app file cy_capsense_processing.c

    Compiling app file cy_capsense_sensing.c

    Compiling app file cy_capsense_structure.c

    Compiling app file cy_capsense_tuner.c

    Compiling app file psoc6_01_cm0p_sleep.c

    Compiling app file psoc6_02_cm0p_sleep.c

    Compiling app file psoc6_03_cm0p_sleep.c

    Compiling app file cyhal_adc.c

    Compiling app file cyhal_analog_common.c

    Compiling app file cyhal_crc.c

    Compiling app file cyhal_crypto_common.c

    Compiling app file cyhal_dac.c

    Compiling app file cyhal_flash.c

    Compiling app file cyhal_gpio.c

    Compiling app file cyhal_hwmgr.c

    Compiling app file cyhal_i2c.c

    Compiling app file cyhal_interconnect.c

    Compiling app file cyhal_lptimer.c

    Compiling app file cyhal_not_implemented.c

    Compiling app file cyhal_pwm.c

    Compiling app file cyhal_qspi.c

    Compiling app file cyhal_rtc.c

    Compiling app file cyhal_scb_common.c

    Compiling app file cyhal_sdhc.c

    Compiling app file cyhal_spi.c

    Compiling app file cyhal_system.c

    Compiling app file cyhal_tcpwm_common.c

    Compiling app file cyhal_timer.c

    Compiling app file cyhal_trng.c

    Compiling app file cyhal_uart.c

    Compiling app file cyhal_udb_sdio.c

    Compiling app file cyhal_usb_dev.c

    Compiling app file cyhal_utils.c

    Compiling app file cyhal_wdt.c

    Compiling app file cyhal_psoc6_01_104_m_csp_ble.c

    Compiling app file cyhal_psoc6_01_104_m_csp_ble_usb.c

    Compiling app file cyhal_psoc6_01_116_bga_ble.c

    Compiling app file cyhal_psoc6_01_116_bga_usb.c

    Compiling app file cyhal_psoc6_01_124_bga.c

    Compiling app file cyhal_psoc6_01_124_bga_sip.c

    Compiling app file cyhal_psoc6_01_43_smt.c

    Compiling app file cyhal_psoc6_01_68_qfn_ble.c

    Compiling app file cyhal_psoc6_01_80_wlcsp.c

    Compiling app file cyhal_psoc6_02_100_wlcsp.c

    Compiling app file cyhal_psoc6_02_124_bga.c

    Compiling app file cyhal_psoc6_02_128_tqfp.c

    Compiling app file cyhal_psoc6_02_68_qfn.c

    Compiling app file cyhal_psoc6_03_100_tqfp.c

    Compiling app file cyhal_psoc6_03_49_wlcsp.c

    Compiling app file cyhal_psoc6_03_68_qfn.c

    Compiling app file cy_ble_clk.c

    Compiling app file cy_canfd.c

    Compiling app file cy_crypto.c

    Compiling app file cy_crypto_core_aes_v1.c

    Compiling app file cy_crypto_core_aes_v2.c

    Compiling app file cy_crypto_core_cmac_v1.c

    Compiling app file cy_crypto_core_cmac_v2.c

    Compiling app file cy_crypto_core_crc_v1.c

    Compiling app file cy_crypto_core_crc_v2.c

    Compiling app file cy_crypto_core_des_v1.c

    Compiling app file cy_crypto_core_des_v2.c

    Compiling app file cy_crypto_core_ecc_domain_params.c

    Compiling app file cy_crypto_core_ecc_ecdsa.c

    Compiling app file cy_crypto_core_ecc_key_gen.c

    Compiling app file cy_crypto_core_ecc_nist_p.c

    Compiling app file cy_crypto_core_hmac_v1.c

    Compiling app file cy_crypto_core_hmac_v2.c

    Compiling app file cy_crypto_core_hw.c

    Compiling app file cy_crypto_core_hw_v1.c

    Compiling app file cy_crypto_core_mem_v1.c

    Compiling app file cy_crypto_core_mem_v2.c

    Compiling app file cy_crypto_core_prng_v1.c

    Compiling app file cy_crypto_core_prng_v2.c

    Compiling app file cy_crypto_core_rsa.c

    Compiling app file cy_crypto_core_sha_v1.c

    Compiling app file cy_crypto_core_sha_v2.c

    Compiling app file cy_crypto_core_trng_v1.c

    Compiling app file cy_crypto_core_trng_v2.c

    Compiling app file cy_crypto_core_vu.c

    Compiling app file cy_crypto_server.c

    Compiling app file cy_csd.c

    Compiling app file cy_ctb.c

    Compiling app file cy_ctdac.c

    Compiling app file cy_device.c

    Compiling app file cy_dma.c

    Compiling app file cy_dmac.c

    Compiling app file cy_efuse.c

    Compiling app file cy_flash.c

    Compiling app file cy_gpio.c

    Compiling app file cy_i2s.c

    Compiling app file cy_ipc_drv.c

    Compiling app file cy_ipc_pipe.c

    Compiling app file cy_ipc_sema.c

    Compiling app file cy_lpcomp.c

    Compiling app file cy_lvd.c

    Compiling app file cy_mcwdt.c

    Compiling app file cy_pdm_pcm.c

    Compiling app file cy_profile.c

    Compiling app file cy_prot.c

    Compiling app file cy_rtc.c

    Compiling app file cy_sar.c

    Compiling app file cy_scb_common.c

    Compiling app file cy_scb_ezi2c.c

    Compiling app file cy_scb_i2c.c

    Compiling app file cy_scb_spi.c

    Compiling app file cy_scb_uart.c

    Compiling app file cy_sd_host.c

    Compiling app file cy_seglcd.c

    Compiling app file cy_smartio.c

    Compiling app file cy_smif.c

    Compiling app file cy_smif_memslot.c

    Compiling app file cy_sysanalog.c

    Compiling app file cy_sysclk.c

    Compiling app file cy_sysint.c

    Compiling app file cy_syslib.c

    Compiling app file cy_syspm.c

    Compiling app file cy_systick.c

    Compiling app file cy_tcpwm_counter.c

    Compiling app file cy_tcpwm_pwm.c

    Compiling app file cy_tcpwm_quaddec.c

    Compiling app file cy_trigmux.c

    Compiling app file cy_usbfs_dev_drv.c

    Compiling app file cy_usbfs_dev_drv_io.c

    Compiling app file cy_usbfs_dev_drv_io_dma.c

    Compiling app file cy_wdt.c

    Compiling app file cy_retarget_io.c

    Compiling app file main.c

    Linking output file mtb-example-psoc6-hello-world.elf

==============================================================================

= Build complete =

==============================================================================

 

Calculating memory consumption: CYBLE-416045-02 GCC_ARM -Og

 

   --------------------------------------------------

  | Section Name         |  Address |  Size     |

--------------------------------------------------

  | .cy_m0p_image        |  0x10000000 |  5328     |

  | .text                |  0x10002000 |  36180    |

  | .ARM.exidx           |  0x1000ad54 |  8        |

  | .copy.table          |  0x1000ad5c |  24       |

  | .zero.table          |  0x1000ad74 |  8        |

  | .data                |  0x0800228c |  1892     |

  | .cy_sharedmem        |  0x080029f0 |  12       |

  | .noinit              |  0x08002a00 |  148      |

  | .bss                 |  0x08002a94 |  976      |

  | .heap                |  0x08002e68 |  276888   |

--------------------------------------------------

 

  Total Internal Flash (Available) 1048576

  Total Internal Flash (Utilized)           46324

 

  Total Internal SRAM (Available) 292864

  Total Internal SRAM (Utilized) 279916

 

Now you can just run ”make qprogram” and hello world will run just the same way as it did on the original kit. That was cool, let’s do it again!

 

When you type as haphazardly as I do, that extra text at the end of the command is just asking for a typo. So I need a more permanent solution. It’s easy to do… just open the Makefile in a text editor, look for the line “TARGET=CY8CPROTO-062-4343W” and change the name of the board to CY8CPROTO-063-BLE, like this.

 

################################################################################

# Basic Configuration

################################################################################

 

# Target board/hardware

# TARGET=CY8CPROTO-062-4343W

TARGET=CY8CPROTO-063-BLE

 

Now you can build and program your kit in one step with the almost-impossible-to-mistype command “make program”. You’ll never guess how to go back to the other kit!

OK, that’s enough typing for me. Next time I’ll show off the new GUI tools we have created to automate all this make shenanigans.

Well, I did not get a visit from any of the VPs I was being rude about yesterday, so I can start showing you some of the ways to do cool projects with ModusToolbox. I usually dive straight into the IDE for things like this but I have lots of options with ModusToolbox so I will start with a simple command-line example instead. This will demonstrate the four fundamental steps involved in making a program.

  1. Clone a starter project from GitHub
  2. Pull down all the required libraries - startup code, board support, CapSense and so on
  3. Build
  4. Program

If you have installed ModusToolbox 2.0 already, then you can follow all these steps (only step 4 requires a kit). If you have not installed ModusToolbox… what the heck are you waiting for???

ModusToolbox includes a convenient "modus-shell", which is just a cygwin DLL with the path set up for the make and compiler executables. I start that by running cygwin.bat from the ModusToolbox\tools_2.0\modus-shell folder. That launches the shell in your home directory.

Clone a Project

All the ModusToolbox firmware is distributed as libraries in the cypresssemiconductorco repo on GitHub (yes, there are three consecutive 's' in there!). To get started you just have to clone an example from that site. As is traditional, I picked "hello world", and it takes just a few seconds to download.

yfs@YFS-T550 ~

$ mkdir MyFirstProject

 

yfs@YFS-T550 ~

$ cd MyFirstProject

 

yfs@YFS-T550 ~/MyFirstProject

$ git clone https://github.com/cypresssemiconductorco/mtb-example-psoc6-hello-world

Cloning into 'mtb-example-psoc6-hello-world'...

remote: Enumerating objects: 15, done.

remote: Counting objects: 100% (15/15), done.

remote: Compressing objects: 100% (13/13), done.

remote: Total 15 (delta 0), reused 12 (delta 0), pack-reused 0

Unpacking objects: 100% (15/15), done.

 

yfs@YFS-T550 ~/MyFirstProject

$ cd mtb-example-psoc6-hello-world

 

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world

$ ls -la

total 64

drwxr-xr-x 1 yfs 1049089     0 Nov 1 15:40 .

drwxr-xr-x 1 yfs 1049089     0 Nov 1 15:40 ..

drwxr-xr-x 1 yfs 1049089     0 Nov 1 15:40 .git

drwxr-xr-x 1 yfs 1049089     0 Nov 1 15:40 images

drwxr-xr-x 1 yfs 1049089     0 Nov 1 15:40 libs

-rw-r--r-- 1 yfs 1049089 12443 Nov  1 15:40 LICENSE

-rw-r--r-- 1 yfs 1049089 10161 Nov  1 15:40 main.c

-rw-r--r-- 1 yfs 1049089  5207 Nov 1 15:40 Makefile

-rw-r--r-- 1 yfs 1049089 17480 Nov  1 15:40 README.md

 

What do you get? Well, there’s main.c and a Makefile, which is pretty much the whole application for “hello world”! Then there is README.md, which is a markdown file that tells you all about the application. You can read that file as plain text or open it in a markdown viewer. When you do that the document is nicely formatted and includes the pictures in the “images” folder. Then is also a LICENSE file, of course, and a “.git” folder, which contains all the clever stuff to support updating and pushing and pulling and cloning and tickling and tweaking and, oh you know, all that git stuff.

Pull in Libraries

The most interesting folder, though, is “libs”. Take a peak in there and you’ll see two files with the extension “.lib” (in this example). These files contain a hash of the GitHub repos and branch for all the extra firmware needed by the application. We use a make rule “getlibs” to pull in those libraries.

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world

$ ls -la libs

total 6

drwxr-xr-x 1 yfs 1049089 0 Nov  1 15:40 .

drwxr-xr-x 1 yfs 1049089 0 Nov  1 15:40 ..

-rw-r--r-- 1 yfs 1049089 67 Nov 1 15:40 retarget-io.lib

-rw-r--r-- 1 yfs 1049089 82 Nov 1 15:40 TARGET_CY8CPROTO-062-4343W.lib

 

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world

$ make getlibs

Tools Directory: C:/Users/yfs/ModusToolbox/tools_2.0

 

Initializing import: mtb-example-psoc6-hello-world

 

==============================================================================

= Importing libraries =

==============================================================================

Git is git version 2.17.0, found at /usr/bin/git

 

Searching application directories...

Application directories search complete.

 

Searching libs directory...

Found 2 file(s)

    Processing file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/libs/retarget-io.lib

    Processing file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/libs/TARGET_CY8CPROTO-062-4343W.lib

Libraries were processed. Re-evaluating libs directory...

Found 8 file(s)

    Processing file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/libs/TARGET_CY8CPROTO-062-4343W/libs/capsense.lib

    Processing file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/libs/TARGET_CY8CPROTO-062-4343W/libs/core-lib.lib

    Processing file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/libs/TARGET_CY8CPROTO-062-4343W/libs/psoc6cm0p.lib

    Processing file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/libs/TARGET_CY8CPROTO-062-4343W/libs/psoc6hal.lib

    Processing file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/libs/TARGET_CY8CPROTO-062-4343W/libs/psoc6make.lib

    Processing file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/libs/TARGET_CY8CPROTO-062-4343W/libs/psoc6pdl.lib

Libraries were processed. Re-evaluating libs directory...

Found 8 file(s)

libs directory search complete.

 

==============================================================================

= Import complete =

==============================================================================

 

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world

$ ls -la libs

total 46

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:13 .

drwxr-xr-x 1 yfs 1049089 0 Nov  1 15:40 ..

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:12 capsense

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:12 core-lib

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:12 psoc6cm0p

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:13 psoc6hal

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:13 psoc6make

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:14 psoc6pdl

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:12 retarget-io

-rw-r--r-- 1 yfs 1049089 67 Nov 1 15:40 retarget-io.lib

drwxr-xr-x 1 yfs 1049089 0 Nov  1 16:12 TARGET_CY8CPROTO-062-4343W

-rw-r--r-- 1 yfs 1049089 82 Nov 1 15:40 TARGET_CY8CPROTO-062-4343W.lib

 

When you look at the libs folder now you have all the Board and Chip support firmware in TARGET_CY8CPROTO-062-4343W and the retarget-io library to enable STDIO output to printf(). Note that the TARGET library, which is known as the BSP, automatically pulls in other libraries that it depends up; core-lib, psoc6hal, psoc6pdl and so on.

Build

So now we have used make to complete the application. The cool part is that we can also use make to update the library versions, or add more, or remove one that you no longer want. The next step is to see if it works… it’s really complicated. Not really, just type “make build”.

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world

$ make build

Tools Directory: C:/Users/yfs/ModusToolbox/tools_2.0

 

Initializing build: mtb-example-psoc6-hello-world Debug CY8CPROTO-062-4343W GCC_ARM

 

Auto-discovery in progress...

-> Found 150 .c file(s)

-> Found 34 .S file(s)

-> Found 16 .s file(s)

-> Found 0 .cpp file(s)

-> Found 0 .o file(s)

-> Found 4 .a file(s)

-> Found 367 .h file(s)

-> Found 0 .hpp file(s)

-> Found 0 resource file(s)

Applying filters...

Auto-discovery complete

 

==============================================================================

= Building application =

==============================================================================

Building 144 file(s)

    Compiling app file startup_psoc6_02_cm4.S

    Compiling app file cy_syslib_gcc.S

    Compiling app file cycfg.c

    Compiling app file cycfg_capsense.c

    Compiling app file cycfg_clocks.c

    Compiling app file cycfg_peripherals.c

    Compiling app file cycfg_pins.c

    Compiling app file cycfg_qspi_memslot.c

    Compiling app file cycfg_routing.c

    Compiling app file cycfg_system.c

    Compiling app file cybsp.c

    Compiling app file system_psoc6_cm4.c

    Compiling app file cy_capsense_centroid.c

    Compiling app file cy_capsense_control.c

    Compiling app file cy_capsense_csd.c

    Compiling app file cy_capsense_csx.c

    Compiling app file cy_capsense_filter.c

    Compiling app file cy_capsense_processing.c

    Compiling app file cy_capsense_sensing.c

    Compiling app file cy_capsense_structure.c

    Compiling app file cy_capsense_tuner.c

    Compiling app file psoc6_01_cm0p_sleep.c

    Compiling app file psoc6_02_cm0p_sleep.c

    Compiling app file psoc6_03_cm0p_sleep.c

    Compiling app file cyhal_adc.c

    Compiling app file cyhal_analog_common.c

    Compiling app file cyhal_crc.c

    Compiling app file cyhal_crypto_common.c

    Compiling app file cyhal_dac.c

    Compiling app file cyhal_flash.c

    Compiling app file cyhal_gpio.c

    Compiling app file cyhal_hwmgr.c

    Compiling app file cyhal_i2c.c

    Compiling app file cyhal_interconnect.c

    Compiling app file cyhal_lptimer.c

    Compiling app file cyhal_not_implemented.c

    Compiling app file cyhal_pwm.c

    Compiling app file cyhal_qspi.c

    Compiling app file cyhal_rtc.c

    Compiling app file cyhal_scb_common.c

    Compiling app file cyhal_sdhc.c

    Compiling app file cyhal_spi.c

    Compiling app file cyhal_system.c

    Compiling app file cyhal_tcpwm_common.c

    Compiling app file cyhal_timer.c

    Compiling app file cyhal_trng.c

    Compiling app file cyhal_uart.c

    Compiling app file cyhal_udb_sdio.c

    Compiling app file cyhal_usb_dev.c

    Compiling app file cyhal_utils.c

    Compiling app file cyhal_wdt.c

    Compiling app file cyhal_psoc6_01_104_m_csp_ble.c

    Compiling app file cyhal_psoc6_01_104_m_csp_ble_usb.c

    Compiling app file cyhal_psoc6_01_116_bga_ble.c

    Compiling app file cyhal_psoc6_01_116_bga_usb.c

    Compiling app file cyhal_psoc6_01_124_bga.c

    Compiling app file cyhal_psoc6_01_124_bga_sip.c

    Compiling app file cyhal_psoc6_01_43_smt.c

    Compiling app file cyhal_psoc6_01_68_qfn_ble.c

    Compiling app file cyhal_psoc6_01_80_wlcsp.c

    Compiling app file cyhal_psoc6_02_100_wlcsp.c

    Compiling app file cyhal_psoc6_02_124_bga.c

    Compiling app file cyhal_psoc6_02_128_tqfp.c

    Compiling app file cyhal_psoc6_02_68_qfn.c

    Compiling app file cyhal_psoc6_03_100_tqfp.c

    Compiling app file cyhal_psoc6_03_49_wlcsp.c

    Compiling app file cyhal_psoc6_03_68_qfn.c

    Compiling app file cy_ble_clk.c

    Compiling app file cy_canfd.c

    Compiling app file cy_crypto.c

    Compiling app file cy_crypto_core_aes_v1.c

    Compiling app file cy_crypto_core_aes_v2.c

    Compiling app file cy_crypto_core_cmac_v1.c

    Compiling app file cy_crypto_core_cmac_v2.c

    Compiling app file cy_crypto_core_crc_v1.c

    Compiling app file cy_crypto_core_crc_v2.c

    Compiling app file cy_crypto_core_des_v1.c

    Compiling app file cy_crypto_core_des_v2.c

    Compiling app file cy_crypto_core_ecc_domain_params.c

    Compiling app file cy_crypto_core_ecc_ecdsa.c

    Compiling app file cy_crypto_core_ecc_key_gen.c

    Compiling app file cy_crypto_core_ecc_nist_p.c

    Compiling app file cy_crypto_core_hmac_v1.c

    Compiling app file cy_crypto_core_hmac_v2.c

    Compiling app file cy_crypto_core_hw.c

    Compiling app file cy_crypto_core_hw_v1.c

    Compiling app file cy_crypto_core_mem_v1.c

    Compiling app file cy_crypto_core_mem_v2.c

    Compiling app file cy_crypto_core_prng_v1.c

    Compiling app file cy_crypto_core_prng_v2.c

    Compiling app file cy_crypto_core_rsa.c

    Compiling app file cy_crypto_core_sha_v1.c

    Compiling app file cy_crypto_core_sha_v2.c

    Compiling app file cy_crypto_core_trng_v1.c

    Compiling app file cy_crypto_core_trng_v2.c

    Compiling app file cy_crypto_core_vu.c

    Compiling app file cy_crypto_server.c

    Compiling app file cy_csd.c

    Compiling app file cy_ctb.c

    Compiling app file cy_ctdac.c

    Compiling app file cy_device.c

    Compiling app file cy_dma.c

    Compiling app file cy_dmac.c

    Compiling app file cy_efuse.c

    Compiling app file cy_flash.c

    Compiling app file cy_gpio.c

    Compiling app file cy_i2s.c

    Compiling app file cy_ipc_drv.c

    Compiling app file cy_ipc_pipe.c

    Compiling app file cy_ipc_sema.c

    Compiling app file cy_lpcomp.c

    Compiling app file cy_lvd.c

    Compiling app file cy_mcwdt.c

    Compiling app file cy_pdm_pcm.c

    Compiling app file cy_profile.c

    Compiling app file cy_prot.c

    Compiling app file cy_rtc.c

    Compiling app file cy_sar.c

    Compiling app file cy_scb_common.c

    Compiling app file cy_scb_ezi2c.c

    Compiling app file cy_scb_i2c.c

    Compiling app file cy_scb_spi.c

    Compiling app file cy_scb_uart.c

    Compiling app file cy_sd_host.c

    Compiling app file cy_seglcd.c

    Compiling app file cy_smartio.c

    Compiling app file cy_smif.c

    Compiling app file cy_smif_memslot.c

    Compiling app file cy_sysanalog.c

    Compiling app file cy_sysclk.c

    Compiling app file cy_sysint.c

    Compiling app file cy_syslib.c

    Compiling app file cy_syspm.c

    Compiling app file cy_systick.c

    Compiling app file cy_tcpwm_counter.c

    Compiling app file cy_tcpwm_pwm.c

    Compiling app file cy_tcpwm_quaddec.c

    Compiling app file cy_trigmux.c

    Compiling app file cy_usbfs_dev_drv.c

    Compiling app file cy_usbfs_dev_drv_io.c

    Compiling app file cy_usbfs_dev_drv_io_dma.c

    Compiling app file cy_wdt.c

    Compiling app file cy_retarget_io.c

    Compiling app file main.c

    Linking output file mtb-example-psoc6-hello-world.elf

==============================================================================

= Build complete =

==============================================================================

 

Calculating memory consumption: CY8C624ABZI-D44 GCC_ARM -Og

 

--------------------------------------------------

  | Section Name         |  Address |  Size     |

--------------------------------------------------

  | .cy_m0p_image        |  0x10000000 |  5068     |

  | .text                |  0x10002000 |  37276    |

  | .ARM.exidx           |  0x1000b19c |  8        |

  | .copy.table          |  0x1000b1a4 |  24       |

  | .zero.table          |  0x1000b1bc |  8        |

  | .data                |  0x080022e0 |  1888     |

  | .cy_sharedmem        | 0x08002a40   |  8 |

  | .noinit              |  0x08002a48 |  148      |

  | .bss                 |  0x08002adc |  996      |

  | .heap                |  0x08002ec0 |  1030464  |

--------------------------------------------------

 

  Total Internal Flash (Available) 2097152

  Total Internal Flash (Utilized)           47412

 

  Total Internal SRAM (Available) 1046528

  Total Internal SRAM (Utilized) 1033504

 

Program

The last step is obviously to program the kit. Plug a CY8CPROTO-062-4343W kit into the USB port and give your computer a few moments to install the drivers for it. Then open a serial terminal like PuTTY or TeraTerm and set them up for the “KitProg3 USB-UART COMxx” port in the Windows Device Manager. The baud rate is 115200.

If you do not have that kit… don’t worry, next time I’ll show you how easy it is to switch applications onto different kits.

To program the kit just type “make program”. This will check that the build is up to date (and build again if necessary) and then download the program using the CMSIS-DAP protocol to the board. If you are super impatient, like me, then you can use “make qprogram” instead and that is quicker (hence the ‘q’) because it skips the build check.

yfs@YFS-T550 ~/MyFirstProject/mtb-example-psoc6-hello-world

$ make program

Tools Directory: C:/Users/yfs/ModusToolbox/tools_2.0

 

Initializing build: mtb-example-psoc6-hello-world Debug CY8CPROTO-062-4343W GCC_ARM

 

Auto-discovery in progress...

-> Found 150 .c file(s)

-> Found 34 .S file(s)

-> Found 16 .s file(s)

-> Found 0 .cpp file(s)

-> Found 0 .o file(s)

-> Found 4 .a file(s)

-> Found 367 .h file(s)

-> Found 0 .hpp file(s)

-> Found 0 resource file(s)

Applying filters...

Auto-discovery complete

 

==============================================================================

= Building application =

==============================================================================

Building 144 file(s)

==============================================================================

= Build complete =

==============================================================================

 

Calculating memory consumption: CY8C624ABZI-D44 GCC_ARM -Og

 

--------------------------------------------------

  | Section Name         |  Address |  Size     |

   --------------------------------------------------

  | .cy_m0p_image        |  0x10000000 |  5068     |

  | .text                |  0x10002000 |  37276    |

  | .ARM.exidx           |  0x1000b19c |  8        |

  | .copy.table          |  0x1000b1a4 |  24       |

  | .zero.table          |  0x1000b1bc |  8        |

  | .data                |  0x080022e0 |  1888     |

  | .cy_sharedmem        |  0x08002a40 |  8        |

  | .noinit              |  0x08002a48 |  148      |

  | .bss                 |  0x08002adc |  996      |

  | .heap                |  0x08002ec0 |  1030464  |

--------------------------------------------------

 

  Total Internal Flash (Available) 2097152

  Total Internal Flash (Utilized)           47412

 

  Total Internal SRAM (Available) 1046528

  Total Internal SRAM (Utilized) 1033504

 

Programming target device...

Open On-Chip Debugger 0.10.0+dev-2.2.0.249 (2019-09-10-10:57)

Licensed under GNU GPL v2

For bug reports, read

http://openocd.org/doc/doxygen/bugs.html

adapter speed: 1500 kHz

adapter speed: 1000 kHz

** Auto-acquire enabled, use "set ENABLE_ACQUIRE 0" to disable

cortex_m reset_config sysresetreq

cortex_m reset_config vectreset

Info : Using CMSIS loader 'CY8C6xxA_SMIF' for bank 'psoc6_smif0_cm0' (footprint 6105 bytes)

Warn : SFlash programming allowed for regions: USER, TOC, KEY

Info : CMSIS-DAP: SWD  Supported

Info : CMSIS-DAP: FW Version = 2.0.0

Info : CMSIS-DAP: Interface Initialised (SWD)

Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1

Info : CMSIS-DAP: Interface ready

Info : VTarget = 3.332 V

Info : kitprog3: acquiring PSoC device...

Info : clock speed 1000 kHz

Info : SWD DPIDR 0x6ba02477

Info : psoc6.cpu.cm0: hardware has 4 breakpoints, 2 watchpoints

Info : psoc6.cpu.cm0: external reset detected

***************************************

** Silicon: 0xE402, Family: 0x102, Rev.: 0x11 (A0)

** Detected Device: CY8C624ABZI-S2D44A0

** Detected Main Flash size, kb: 2048

** Flash Boot version 3.1.0.45

** Chip Protection: NORMAL

***************************************

Info : psoc6.cpu.cm4: hardware has 6 breakpoints, 4 watchpoints

Info : psoc6.cpu.cm4: external reset detected

Info : Listening on port 3333 for gdb connections

Info : Listening on port 3334 for gdb connections

Warn : Only resetting the Cortex-M core, use a reset-init event handler to reset any peripherals or configure hardware srst support.

Info : kitprog3: acquiring PSoC device...

target halted due to debug-request, current mode: Thread

xPSR: 0x41000000 pc: 0x00000190 msp: 0x080ff800

** Device acquired successfully

** psoc6.cpu.cm4: Ran after reset and before halt...

target halted due to debug-request, current mode: Thread

xPSR: 0x01000000 pc: 0x0000012a msp: 0x080ff800

** Programming Started **

auto erase enabled

Info : Flash write discontinued at 0x100013cc, next section at 0x10002000

Info : Padding image section 0 at 0x100013cc with 52 bytes (bank write end alignment)

[100%] [################################] [ Erasing     ]

[100%] [################################] [ Programming ]

Info : Padding image section 1 at 0x1000b92c with 212 bytes (bank write end alignment)

[100%] [################################] [ Erasing     ]

[100%] [################################] [ Programming ]

wrote 44544 bytes from file C:/Users/yfs/MyFirstProject/mtb-example-psoc6-hello-world/build/CY8CPROTO-062-4343W/Debug/mtb-example-psoc6-hello-world.hex in 5.370537s (8.100 KiB/s)

** Programming Finished **

** Verify Started **

verified 44280 bytes in 0.267027s (161.939 KiB/s)

** Verified OK **

** Resetting Target **

Warn : Only resetting the Cortex-M core, use a reset-init event handler to reset any peripherals or configure hardware srst support.

shutdown command invoked

 

You should see the red LED blinking at about 1Hz. That’s just way too slow for me and it drives me nuts - I always open main.c in an editor and speed that up! In the terminal emulator you should see this. You can turn the LED blinking on and off by pressing the Enter key.

My First ModusToolbox 2_0 Design PuTTY.png

 

Congratulations! If you followed along then you just created, built, and programmed your first ModusToolbox application.

Oh my stars, it has been a week since we released ModusToolbox 2.0! I thought I'd be getting some down time after the release but, as usual, things did not really go that way. Instead of taking a break we decided to give all the San Jose vice presidents a crash course in all things ModusToolbox. This was a group of sales guys, marketeers, and business unit managers, with not a single engineer among them... what could possibly go wrong?

Alan Hawse (who else!) was hosting the day but he missed his plane from Kentucky. We had no course materials. The kits we wanted to use for lab sessions arrived two days late. And, worst of all, we found that all VPs share one common skill - the ability to mess up software installations. It was a hectic day but, by the end of it all, these guys...

ModusToolbox training SJ.jpeg

... got our motley collection of non-programmers writing programs using every customer development flow that we could think of...

  • Mbed CLI
  • Mbed Online Compiler
  • Mbed Studio
  • ModusToolbox IDE
  • Visual Studio Code
  • And from the command-line

And we were not just building blinky. When you get a group of VPs at your mercy... it would be wrong not to torture them with a little C and C++ programming ("I wrote Pascal in college and waaa waaa waaa"). So we had them writing to TFT displays, connecting to Wi-Fi networks, polling NTP servers, and pulling all that together to create a PSoC-based alarm clock. In one day.

I think this is a testament to the design goal of ModusToolbox. We wanted to create a set of tools and libraries that are so flexible and interchangeable that we can support bare metal or RTOS-based applications; running in our own ecosystems or partner platforms like Mbed and Amazon FreeRTOS; using our IDE, a partner IDE, or no IDE at all; and building with the compiler of your choice. I think we crushed that objective, so 'Chapeau' to all the 226 engineers that have worked on the project!

Another good thing to come from that crazy day was that I now have a good set of starter projects and use cases that I can blog about and get everyone excited and up to speed with the new tools. Watch this space...