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

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

问题描述

关于SO问题: 52164135

In reference to SO question: 52164135

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

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:
根据关于A​​VRFreaks的讨论(该讨论正在进行中在启用中断的硬件环境中使用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如果被打扰会失败吗?

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

如果在中断期间再次调用

推荐答案

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天全站免登陆