C28系列数据总线为32位,如果在后台循环中为一个long long 或 long double型的64位变量赋值,是否可认为这不是一个原子操作。
即写完32位后,未写剩余的32位时,可能被高优先级任务或中断打断。不做临界区处理的话,在中断或高优先级任务中读取此值有概率是不正确的。
不知道是不是我问题没有表达清楚,补充测试如下:
main函数主循环代码如下:
uint64_t test; if(i==0) { test = 0x1111111122222222; } else { test = 0x2222222211111111; }
20k频率中断中代码如下:
if( (test != 0x1111111122222222) && (test != 0x2222222211111111) ) { GvUtility_TestData_U[0]++; }
测试结果:变量值GvUtility_TestData_U[0]不断增加
在测试1基础上,将test数据类型由uint64_t 变更为uint32_t,对应值更改为0x11112222,0x22221111;
测试结果:GvUtility_TestData_U[0]始终为0
在测试1基础上,操作变量前后增加临界区保护ENTER_CRITICAL_SECTION();/EXIT_CRITICAL_SECTION()
测试结果:GvUtility_TestData_U[0]始终为0
您好,
您关注在这里是有效的。由于总线宽度为 32 位,因此 64 位写入如果中断,可能会导致不正确的值。
要使其具有原子性,您可以使用 DINT 后跟 EINT,或者使用软件解决方法(如 UPDATE_STATUS = START、UPDATE_STATUS = END - 并在 ISR 中或访问该变量的任何地方进行检查)。