sprintf在具有中断的32位MCU中重新进入64位操作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sprintf在具有中断的32位MCU中重新进入64位操作相关的知识,希望对你有一定的参考价值。

参考SO问题:52164135

设置: 我有一个函数可以将许多double值转换为预定义的字符串。输入是一个array of struct,我们将两个double值连接成一个字符串。双倍大小为8字节或64位,我的操作MCU是STM32,一个32位ARM微控制器。 interrupt也在并行运行。

数据应如下所示:

[[12.11111111,12.11111111],[12.22222222,12.22222222],...]

但我得到(很少):

[[12.11111111,12.11111111],[55.01[12.33333333,12.33333333],...]

注意:我错过了[12.22222222,12.22222222]

sprintf不可重入: 根据这个discussion,关于AVRFreaks,sprintf is not re-entrant.(讨论是在启用中断的硬件环境中使用sprintf。)这意味着如果在sprintf操作之间发生中断,则堆栈无法继续它正在进行的操作。

由于我的MCU是32位,因此要执行64位操作,需要两个时钟周期。如果我们假设在sprintf操作之间发生中断,根据上面的讨论,sprintf应该失败。

题 1.如果sprintf中断,它会失败吗?

这是字符串函数,中断例程也在后台运行,处理其他传感器数据(本地和全局)

/* @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
}

中断例程中发生了什么

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();
}
答案

qazxsw poi只会在中断期间失败,如果在该中断期间再次调用它(假设它使用了重用的全局变量;它是否只使用堆栈变量,那么它是可重入的)。

因此,如果您的中断处理程序正在调用sprintf,并且在该调用期间发生新的,相同或更高优先级的中断,那么它可能会失败。但是,在处理中断期间,通常会禁用中断,因此不能(不应该!)是发生相同类型的另一个中断。

但为什么在中断处理期间转换此原始数据?为什么不通过缓冲区将这些数据存储/传递给用户级例程并使该功能转换原始数据?这与中断处理程序应该尽可能短(快)的想法是一致的。

以上是关于sprintf在具有中断的32位MCU中重新进入64位操作的主要内容,如果未能解决你的问题,请参考以下文章

STM32/MM32/GD32 IAP跳转到APP后无法进中断

在 STM32 上使用 FreeRTOS 处理多个中断

FreeRtos 进入bootloader 串口无法接收数据,如何解决???????

STM32 软件复位并模拟USB拔插

STM32串口之空闲中断

stm32中外部中断进入中断以后,把中断线挂起位清0以后,在检测还有意义吗,不是已经clear了吗