Gab*_*les 2 c++ avr atomic arduino interrupt
我只是失去了几天,从字面上看,大约25个小时的工作,因为我试图调试我的代码而不是我不知道的简单.
事实证明,在C++中减少单字节数组的元素,在AVR上,ATmega328 8位微控制器(Arduino)不是原子操作,需要原子访问保护(即关闭中断).为什么是这样???此外,在Atmel AVR微控制器上确保原子访问变量的所有C技术是什么?
这是我所做的一个愚蠢的版本:
//global vars:
const uint8_t NUM_INPUT_PORTS = 3;
volatile uint8_t numElementsInBuf[NUM_INPUT_PORTS];
ISR(PCINT0_vect) //external pin change interrupt service routine on input port 0
{
//do stuff here
for (uint8_t i=0; i<NUM_INPUT_PORTS; i++)
numElementsInBuf[i]++;
}
loop()
{
for (uint8_t i=0; i<NUM_INPUT_PORTS; i++)
{
//do stuff here
numElementsInBuf[i]--; //<--THIS CAUSES ERRORS!!!!! THE COUNTER GETS CORRUPTED.
}
}
Run Code Online (Sandbox Code Playgroud)
这是循环的版本,没关系:
loop()
{
for (uint8_t i=0; i<NUM_INPUT_PORTS; i++)
{
//do stuff here
noInterrupts(); //globally disable interrupts
numElementsInBuf[i]--; //now it's ok...30 hrs of debugging....
interrupts(); //globally re-enable interrupts
}
}
Run Code Online (Sandbox Code Playgroud)
注意"原子访问保护",即:在递减之前禁用中断,然后在之后重新启用它们.
由于我在这里处理单个字节,我不知道我需要原子访问保护.为什么在这种情况下我需要它们?这是典型的行为吗?我知道如果这是一个2字节值的数组,我需要它们,但为什么1字节值???? 通常对于1字节值,此处不需要原子访问保护......
所以我们知道在AVR 8位mcus上读取或写入任何单字节变量都是原子操作,但STM32 32位mcus呢?哪些变量在STM32上具有自动原子读写?答案是:STM32微控制器上哪些变量类型/大小是原子的?.
该ATmega328数据表表示:
ALU支持寄存器之间或常量和寄存器之间的算术和逻辑运算
它没有提到ALU能够直接在内存位置上运行.因此,为了减少值,这意味着处理器必须执行多个操作:
因此,减量操作不是原子操作,除非你做一些特殊操作使其成为原子,例如禁用中断.这种读/修改/写入要求可能比更新内存更常见.
如何使操作成为原子的细节取决于平台.较新版本的C和C++标准明确支持原子操作; 我不知道ATmega的工具链是否支持这些新标准.
归档时间: |
|
查看次数: |
847 次 |
最近记录: |