Semihosting printf call corrupts uxSchedulerSuspended variable

rayq wrote on Tuesday, December 12, 2017:

I’m linking a semihosting library using the ‘–specs=rdimon.specs’ flag. I put a watch on the ‘uxScheduleSuspended’ variable and saw that the first call to swrite() corrupts the ‘uxScheduleSuspended’ variable which later on causes issues in assertions and halts my program execution.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x080024a6 in xTaskResumeAll () at /home/rahman/stm32f405-workspace/FreeRTOS/Source/tasks.c:2035
2035 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
(gdb) c
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x0800ac04 in __swrite ()
(gdb) p uxSchedulerSuspended
$10 = 536889224

rayq wrote on Tuesday, December 12, 2017:

Hi everyone: I didn’t allocate enough stack space. Also, I added the following line to prevent hardfaults although I don’t know the details of why the hard fault occurs.

#define printf(format, …) portDISABLE_INTERRUPTS();printf(format, \##VA_ARGS);portENABLE_INTERRUPTS();

davidbrown wrote on Tuesday, December 12, 2017:

On 12/12/17 08:00, Abdurrahman Qureshi wrote:

Hi everyone: I didn’t allocate enough stack space. Also, I added the
following line to prevent hardfaults although I don’t know the
details of why the hard fault occurs.

#define printf(format, …) portDISABLE_INTERRUPTS();printf(format,
##VA_ARGS);portENABLE_INTERRUPTS();

I don’t know why you are having problems, but disabling interrupts
around a printf call seems to me to be a /very/ bad idea. printf can
take quite a bit of time to run - you certainly don’t want to disable
interrupts for a long and unpredictable time.

Try splitting it into a “snprintf” call to put the formatted output into
a buffer, then “puts” to send out the output. Then at least you should
be able to identify which half of “printf” is causing you problems.

heinbali01 wrote on Tuesday, December 12, 2017:

Hi Abdurrahman,

Here I rewrote your macro:

#define safe_printf(format, ...) \
    portDISABLE_INTERRUPTS();    \
    printf(format, ##VA_ARGS);   \
    portENABLE_INTERRUPTS();

portENABLE_INTERRUPTS() just enables the interrupts, not matter whether they were enabled before calling your safe_printf() macro. Maybe it will end a critical section too soon.

For this reason, you can better use these couples:

#define safe_printf(format, ...) \
    taskENTER_CRITICAL();        \
    printf(format, ##VA_ARGS);   \
    taskEXIT_CRITICAL();

These macros ( functions ) use a global variable ulCriticalNesting. Only when it becomes zero, interrupts are allowed again.

I would recommend not to use printf() from within an ISR.

I didn’t allocate enough stack space. Also, I added the following line to prevent hardfaults
although I don’t know the details of why the hard fault occurs.

I don’t know who implemented your printf(). Does it come from the C-library? What does it do, does it send the bytes to a serial port? If so, why don’t you just call the UART routine?

heinbali01 wrote on Tuesday, December 12, 2017:

David Brown ( he was quicker than me ), is very right of course, printf() executes far too much ( unknown ) code to be called from within a critical section. Critical sections should be kept as short as possible.

See what you can do with the sprintf() routines, e.g. :

void safe_printf( const char *pcFormat, ... )
{
char pcBuffer[ 129 ];
size_t xLength;
va_list xArgs;

    va_start( xArgs, pcFormat );
    xLength = vsnprintf( pcBuffer, sizeof pcBuffer, pcFormat, xArgs );
    va_end( xArgs );
    uart_send( pcBuffer, xLength );
}

rayq wrote on Tuesday, December 12, 2017:

Thanks for the reply!
Excuse my ignorance if I make a mistake in the explanation below.

I believe printf is implemented by newlib but the syscall is typically user-implemented. However you can link one of two pre-compiled (by ARM?) syscalls via the flags ‘–specs=rdimon.specs’ and ‘–specs=nosys.specs’. The latter are dummy calls so in production I get rid of printf statements.

During debugging I link the former. Those syscalls somehow communicate with the JTAG debugger to print straight to my console via OpenOCD. You are right that most syscall implementations I read online print via UART. I do not call a UART routine because I do not want to have to connect a second wire and USB cable to my computer.

rayq wrote on Tuesday, December 12, 2017:

Thanks for all the help! As I replied above the ARM compiler is just linking some implementation of stdlib - I believe it is newlib - and I am linking some pre-compiled syscalls. I didn’t look too much into the details because I just wanted it to work and continue on my development.

That being said, if this comes up as an issue again (printf is long and I can conceive that can cause some timing issues), I will go ahead and follow your suggestion.

Thanks!

rayq wrote on Tuesday, December 12, 2017:

Thanks for the reply! I’ve posted some explanations below, but tldr I can’t edit printf but if more issues arise I will do so.

rtel wrote on Tuesday, December 12, 2017:

Depending on the device you are using you may find that semihosting is simply incomaptible with FreeRTOS, or any other system that uses the same interrupts that use semihosting uses.