Using the retarget-io library to enable printf() | Cypress Semiconductor
Using the retarget-io library to enable printf()
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 BSP's. 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!