2021-05-10 12:23 PM
Looking for some clarification about printf and SWV ITM using an STM32F4-Discovery board (STM32F407VGT). Let's just assume we're working with boards/processors that support the function. What I have configured works but I'd like to understand this a bit better. I've done an online tutorial that begins with an empty STM32 project, then, in order for the SWV ITM Data Console to display the printf info, code was provided to be pasted into the syscalls.c file (not shown) with the associated 'write' function modified with the entry of 'ITM_SendChar()', as shown below:
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
// __io_putchar(*ptr++);
ITM_SendChar(*ptr++);
}
return len;
}
This works as the custom ITM_SendChar() function is defined with the syscalls.c code addition. No problem so far, this with the empty CubeMX generated code.
Now, using the (assumed) recommended process of including the necessary code into a new project to be able to use the SWV ITM printf type function, I select 'sys' in CubeMX and choose 'Serial Wire' or 'Trace Asynchronous sw', then generate the new code with either of those two choices. I modify only the 'write' function with the new 'ITM_SendChar() function entry (shown above), with no additional code added to the syscalls.c file, and it works. No problem, again. Apparently, the ITM_SendChar() function in core_cm4.h is now available to the project/app.
Here's the part that's unclear. Most of the information I've found indicates that the choice of 'sys/serial wire' or 'sys/trace asynchronous sw' is required to get the SWV ITM Data Console to display the printf data, but if I don't select either debug choice, the code is still generated, the functions are available and modifying only the 'write' function makes debugging with printf work. After all the searching and post reading about the SWV and printf not working can it be that simple that the necessary code is generated and made available (using CubeMX) by default and is ready to go no matter the sys/debug choices or is it something else that causes that code to be generated and available?
TJM
2021-05-10 02:31 PM
An empty C project will still include basic functions such as _write.
The SWD pins are initialized by default on reset, so selecting them inside CubeMX isn't strictly necessary, but it certainly makes things more clear.
2021-05-11 08:47 AM
Thanks for the info. I would think that setup using CubeMX would then make the initialization more consistent no matter the reset method.
TJM
2021-05-11 08:57 AM
2021-05-11 09:49 AM
Correct me if I'm wrong, but what I get from the reference manual is that a power off reset would configure and enable SWD mode by default just like you say. But if the configuration was changed by the app for some reason, and I don't know why, maybe advanced debugging or a code error?, then a power on reset would keep the changes where a power off reset would restore the default. But if the initial configuration was made with CubeMX and deliberately coded in, then the configuration would be the same no matter the reset method? What I meant by consistency is the config remains the same whether you reset by unplugging or pushing the boards reset button.
I can make the printf debug method work and I now know where to look if it doesn't, but it's just become an exercise in how to interpret the reference manual, I think.
TJM
2021-05-11 09:55 AM
2021-05-11 01:40 PM
ITM_SendChar is not a function that a user should define.
It is a CMSIS defined API to send a char to ITM port 0.
It is automatically available if you include all proper CMSIS .h files; Cube generator does this for you.
So, do not redefine ITM_SendChar. Redefine __io_putchar or _write, etc., and make them call ITM_SendChar.
Now, initialization of ITM is a different matter. Many debuggers do it themselves via the debugger interface, so the code running on STM32 does not have to.
In this case all that the program should do is let the SWD pins alone and don't touch them.
--pa
2021-05-11 11:13 PM
Thanks for all the info here in this thread. I now understand how to make use of printf for debugging. The problem arose while working through a tutorial where the demonstration application was built with CubeMX but with an empty configuration. The author of that tutorial provided a custom ITM_SendChar() function written specifically for that tutorial apparently so it would work without the added definitions that are normally provided during a full CubeMX normal code generation. Before I realized that I was missing a piece of the tutorial, I did try to cut and paste the function from a CMSIS file that belonged to an existing application obviously without success because of the lack of the support definitions for the function. Anyway, it appears to be a relatively simple matter to either modify or replace the 'write' function to enable the printf debugging, especially during a normal CubeMX code generation.
Thanks,
TJM