sprintf 重新进入具有中断的 32 位 MCU 中的 64 位操作 [英] sprintf re-entry into 64bit operation in 32 bit MCU with interrupts

查看:30
本文介绍了sprintf 重新进入具有中断的 32 位 MCU 中的 64 位操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参考 SO 问题:52164135

In reference to SO question: 52164135

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

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.

数据应如下所示:

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

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

但我得到(很少):

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

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

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

sprintf 不会重新进入t:
根据此讨论,在 AVRFreaks 上,sprintf 不会重新(讨论的是在启用中断的硬件环境中使用 sprintf.)这意味着如果在 sprintf 操作之间发生中断,堆栈将无法继续它正在执行的操作.

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.

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

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.

问题
1.sprintf被打断会失败吗?

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

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

推荐答案

sprintf 如果在中断期间再次调用,则在中断期间只会失败(假设它使用了重复使用的全局变量); 会不会只使用堆栈变量,那么它是可重入的).

sprintf will ony fail during an interrupt if it is called again during that interrupt (assuming it uses global variables that are re-used; would it use only stack variables, then it is re-entrant).

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

So if your interrupt handler is calling sprintf and during that call a new, same or higher priority interrupt occurs then it can fail. However, during the processing of an interrupt, interrupts are normally disabled so there can't (shouldn't!) be another interupt of the same type occurring.

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

But why convert this raw data during interrupt handling? Why not store/pass this data to the user-level routine via a buffer and have that functionality convert the raw data? That would be consistent with the idea that an interrupt handler should be as short (fast) as possible.

这篇关于sprintf 重新进入具有中断的 32 位 MCU 中的 64 位操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆