STMCU小助手
发布时间:2022-3-2 22:24
|
前言 本文章主要介绍多任务系统中的的不可重入函数的用法和如何避免出错。 1. 可重入函数与不可重入函数的区别 在多任务环境中,可重入函数可以由多于一个的任务并发使用,而不用担心数据错误。这个函数可以在执行的任何时刻中断它。 不可重入函数由于使用了一些系统资源,比如全局变量等,不能被很多任务所共享,除非能确保函数的互斥性。 1)可重入函数: 不返回指向静态数据的指针。 使用本地数据。 如果必须访问全局变量,记住利用互斥信号量来保护全局变量。 绝不调用任何不可重入函数。 2)不可重入函数: 函数中使用了静态变量。 函数返回静态变量。 函数中调用了不可重入函数。 函数体内使用了静态的数据结构; 函数体内调用了 malloc()或者 free()函数; 函数体内调用了其他标准 I/O 函数。 总的来说,如果一个函数在重入条件下使用了未受保护的共享的资源,那么它是不可重入的。 2. 不可重入函数的一次错误应用示例,造成 I2C Master 端收到的数据无法正确解析。 这个产品使用的 MCU 为 STM32F411,是作为 Sensor hub 使用的,做为 I2C 的 Master 端,总线上挂了好几个传感器,如加速度、陀螺仪、光感应等。并且同时采用定时方式和中断方式通过 I2C 总线读取 sensor 上数据的。
客户产品功能是在实时操作系统上实现的,属于多任务系统。在中断处理函数中会调用 I2C_Read(…)函数,而I2C_Read(…)函数中又调用了 HAL_I2C_Master_Receive_IT(…)函数。 函数代码在示例程序中的位置如下: …\stm32cubef4\STM32Cube_FW_F4_V1.6.0\Drivers\STM32F4xx_HAL_Driver\Src 的 stm32f4xx_hal_i2c.c stm32f4xx_hal_i2c.c 文件中有一段 I2C slave 接收程序,具体代码如下:
上面程序中通过下面指令对硬件端口进行加锁: __HAL_LOCK(hi2c); __HAL_UNLOCK(hi2c); 初步看来多任务系统中好像是安全的,但实际应用中并非如此(客户的不可重入函数调用了这个 I2C 函数),下面用图例来说明:
上图中”t”为时间轴,”T1”时间发生 sensor 1 中断并调用 I2C_Read(…),在 I2C_Read(…)函数中会调用HAL_I2C_Master_Receive_IT(…)函数,在调用 HAL_I2C_Master_Receive_IT(…)函数之前已经进行了传参,即:Addr=0x1A0,Size=3,Buf 指向 buffer1 的地址。 当程序运行到”T2”时又来了一个 sensor 2 中断,调用 I2C_Read(…)函数,在调用 HAL_I2C_Master_Receive_IT(…)函数之前已经传参完成。此时的 I2C 地址,Size 等的值如下: Addr=0x1B0,Size=5,Buf 指向 buffer1 的地址。 由于 HAL_I2C_Master_Receive_IT(…)程序有加锁,和判断 busy 状况,当程序判断到总线 busy 时或是有加锁时跳出HAL_I2C_Master_Receive_IT(…)函数;但此时的 I2C 地址,buffer 地址, Size 都已经是 Sensor2 对应的值了。然后程序进入 ”T3“。 Sensor2 中断返回时会把 sensor2 的 Size 值 5 赋给 hi2c->XferSize,因此后面的 I2C 通讯中的值如下: Addr=0x1A0(sensor1 value) Buf 指向 buffer1(sensor1 value) Size=5(sensor2 value) 因此程序处理中会出错。 3.上面的问题解决方法: 上面多任务系统的 I2C 处理程序中出现了不可重入函数的多次调用问题,主要是 I2C_Read(…)为不可重入函数,但对它进行了多次调用,使变量更改。 下面的办法可以解决多次调用问题,既对调用 I2C_Read(…)的动作加锁,使第二个 I2C 中断发生后不进行传参动作,如下图所示:
也可以使用信号量方式处理。如下图:
4. 程序占用资源后要防止死锁发生 上面 I2C 程序处理中要注意不要发生死锁,假设在 I2C_Read(…) 函数里有一条指令是对 I2C 端口的状态进行判断,如 busy状态,如果程序一直在等待中,就很容易发生死锁,下面图示是程序发生死锁的情况:
在上面程序中需要增加超时跳出机制来防止死锁。 5.总结 在多任务系统中,在使用函数时要了解函数的可重入性,对待有信号量或是加互斥锁的函数要防止死锁的发生。通讯程序比如 I2C, UART 等最好增加超时跳出机制。 |
【经验分享】STM32 HAL库移植FreeModbus详细步骤
【逢7发帖赢大礼】STM32开发之IC门禁卡UID读取方法!
实战经验 | Keil工程使用NEAI库的异常问题
经验分享 | FDCAN数据段波特率增加后发送失败的问题分析
STM32几种流行开发环境的优缺点
好用软件推荐-TouchGFX Designer
OpenSTLinux 6.1发布:M33-TD加持+安全升级,STM32MPU开发效率翻倍!
【经验分享】STM32CubeIDE汉化
手把手教你VSCode搭建STM32开发环境
RTOS在STM32中的应用
微信公众号
手机版