2022-04-27 06:41 AM
I have been using printf() to output to UART for many years on a STM32L052
All these projects still compile and printf() to UART, no problem.
I started a NEW project with CubeMX, but now printf() does NOT print to UART.
I use the same int fputc(int ch, FILE *f) as in ALL the other projects, but still no UART output. (Plese see attached code)
I looked at other solutions, but they seem to be doing similar int fputc(int ch, FILE *f)
Any help appreciated
2022-04-27 07:25 AM
Does HAL_UART_Transmit work if it's used directly within the main program?
If you put a breakpoint within fputc, does it get hit?
2022-04-27 07:58 AM
TDK,
YES - HAL_UART_Transmit(&huart1, (uint8_t *)message, string_lenght, 100);
NO - Does NOT break at fputc
2022-04-27 08:33 AM
TDK,
The app actually crashes at my printf("\r\nmyString\r\n");
Regards
2022-04-27 08:41 AM
2022-04-27 08:49 AM
Possibly:
STM32 provides two versions of libs used for for printf = with/without floating point.
Check your compile settings, maybe running out of memory due to overhead for floating point.
Try setting your projects compile options for "no floating point"
Paul
2022-04-27 01:19 PM
Paul,
I am still struggling to make it work.
If I put breakpoints, and step over, the app does NOT crash.
printf() still has NO output, but is does not crash, and the rest of the app continues.
If I remove the breakpoints, the app crashes, and I cannot figure out where / why.
Also., I am using IAR, and cannot find where the compile setting is for floating point.
I only see the FPU option under General Options > 32Bit, but FPU is grayed out
Regards
Rehards
2022-04-28 07:42 AM
Qualifier: We're not using IAR or the exact STM32 you are, but we are using many different STM32, with both UART and VCP for terminal diagnostics by printf, and UART for data communications.
Attached is a screen capture from our STM32 troubleshooting, it has several points that may help.
One more:
Paul
2022-04-28 07:56 AM
Also:
As TDK said check your heap.
I have no idea how IAR determines the heap size.
Quick test: make the heap as big as possible (and still compile).
Careful that increasing heap isn't hiding an actual bug!!
Recall my note about bad memory above? Just had a brain fart...
I've seen crashes like you mention when code references data in stacked/alloc'd variables that have been released (like temp internal variable in a function). Typically happens with pointers or alloc'd, but may happen in other scenarios. Somewhere a pointer is set, but the thing pointed to was a temporary stacked variable. Later you printf that item. Depending what has happened to stack or heap that data may or may not still be there. Enabling debugger changes how the memory is affected and may allow your code to survive longer, but not reliably.
Soln: tedious, but trace through your code tell you find the "released/orphaned" data and change how you handle that data.
Warn: The fault may not actually be in current printf, it could be in preceding code that uses the orphaned data and leaves stack corrupted so later code fails upon a "return".
Tracing/Debugging: What I do to catch these is just put a whole bunch of printf+waitempty in my code (I make a macro for the pair as I may be putting 20-50 of these in at a time). Basically it is a printf, followed by a function that loops till the UART is empty. That way you know that printf completed properly and any crash is truly for later code, or in code that called this code. I put the printf+waitempty between most every line, removing later as I determine it is before/after a particular printf+waitempty and crashing at a different printf+waitempty.
Paul
2022-06-15 10:10 AM
// The standard printf will consume too many resources. here is a light alternative:
// called xprintf)
static int inited = 0;
static char tmp[16];
static SemaphoreHandle_t BinSemHandle;
// This will do int, hex, str, float (%d %x %s %f) [pasted from working code]
int xprintf(const char *str, ...)
{
if(!inited)
{
inited = 1;
BinSemHandle = xSemaphoreCreateBinary(); xSemaphoreGive(BinSemHandle);
}
// So one can call it forn different threads (tasks)
xSemaphoreTake(BinSemHandle, portMAX_DELAY);
va_list ap;
va_start(ap, str);
int len = strlen(str);
for(int aa = 0; aa < len; aa++)
{
char chh = str[aa];
if(chh == '%')
{
if(str[aa+1] == 'd')
{
int vvv = va_arg(ap, int);
itoa(vvv, tmp, 10);
HAL_UART_Transmit(&huart2, (uint8_t *)tmp, strlen(tmp), HAL_MAX_DELAY);
}
else if(str[aa+1] == 'x')
{
int vvv = va_arg(ap, int);
itoa(vvv, tmp, 16);
HAL_UART_Transmit(&huart2, (uint8_t *)tmp, strlen(tmp), HAL_MAX_DELAY);
}
else if(str[aa+1] == 'f')
{
double vvv = va_arg(ap, double);
gcvt(vvv, 4, tmp);
HAL_UART_Transmit(&huart2, (uint8_t *)tmp, strlen(tmp), HAL_MAX_DELAY);
}
else if(str[aa+1] == 's')
{
char *sss = va_arg(ap, char*);
HAL_UART_Transmit(&huart2, (uint8_t *)sss, strlen(sss), HAL_MAX_DELAY);
}
else
{
HAL_UART_Transmit(&huart2, (uint8_t *)str[aa+1], 1, HAL_MAX_DELAY);
}
aa++;
}
else
{
HAL_UART_Transmit(&huart2, (uint8_t *)&str[aa], 1, HAL_MAX_DELAY);
}
}
xSemaphoreGive(BinSemHandle);
return len;
}