In reference to SO question: 52164135
The setup:
I have a function which converts many double
values into a predefined string. The input is a array of struct
from which we concatenate two double values into a string. A double is of size 8 bytes or 64 bits and my MCU of operation is STM32, a 32 bit ARM micro-controller.
An interrupt
is also running parallelly.
The data should look like:
[[12.11111111,12.11111111],[12.22222222,12.22222222],...]
But I get (very rarely):
[[12.11111111,12.11111111],[55.01[12.33333333,12.33333333],...]
Note: I missed out [12.22222222,12.22222222]
sprintf is not re-entrant:
According to this discussion, on AVRFreaks, sprintf is not re-entrant.
(The discussion is on using sprintf in a interrupt enabled hardware environment.) Which means if an interrupt occurs in-between a sprintf
operation the stack fails to continue the operation it was doing.
Since my MCU is a 32 bit one, to perform a 64 bit operation it will take two clock cycles. And if we assume an interrupt occurred in between the sprintf operation according the the above discussion sprintf
should fail.
Question
1. Will sprintf
fail in case it is interrupted?
Here is the string function, an interrupt routine also runs in the background which deals with other sensor data (local and global)
/* @brief From the array of GPS structs we create a string of the format
* [[lat,long],[lat,long],..]
* @param input The input array of GPS structs
* @param output The output string which will contain lat, long
* @param sz Size left in the output buffer
* @return 0 Successfully completed operation
* 1 Failed / Error
*/
int get_gps60secString(GPS_periodic_t input[GPS_PERIODIC_ARRAY_SIZE],
char *output, size_t sz)
{
int cnt = snprintf(output, sz, "[");
if (cnt < 0 || cnt >= sz)
return 1;
output += cnt;
sz -= cnt;
int i = 0;
for (i = 0; i < GPS_PERIODIC_ARRAY_SIZE; i++) {
cnt = snprintf(output, sz, "[%0.8f,%0.8f]%s",
input[i].point.latitude, input[i].point.longitude,
i + 1 == GPS_PERIODIC_ARRAY_SIZE ? "" : ",");
if (cnt < 0 || cnt >= sz)
return 1;
output += cnt;
sz -= cnt;
}
cnt = snprintf(output, sz, "]");
if (cnt < 0 || cnt >= sz)
return 1;
return 0; // no error
}
What's happening inside the interrupt routine
void GPS_InterruptHandler(UART_HandleTypeDef *UartHandle)
{
gps_UART_RxInterrupt_Disable();
GPS_t l_sGpsInfo;
memset(&l_sGpsInfo,0,sizeof(GPS_t));
status=Validate_get_gpsInfo((char*)g_gps_readBuff,&l_sGpsInfo,100);
MEMS_interruptHandler(); //Inertial sensor ISR
gps_UART_RxInterrupt_Enable();
}
See Question&Answers more detail:
os