本文探讨了编程中子函数在被中断函数与主函数同时调用时可能出现的问题及解决方案。通过实例分析,帮助读者理解不同场景下的调用机制及其影响。
在单片机系统中,中断函数与主函数可能会同时调用同一个子函数,这可能导致一些问题。
这些问题的根源在于该子函数可能是不可重新进入(reentrant)的。这意味着当此函数正在执行时,另一个ISR(Interrupt Service Routine, 中断服务程序)可能试图调用它。这种情况下结果是不确定性的,并且有可能导致参数错误等问题出现。
例如,在某些代码中,`WRITE_GMVLX1_REG` 函数被多个地方所引用:既有中断服务程序也有主函数中的其他部分会使用到这个功能。如果该子函数不可重新进入,则可能会在同一时间点上执行两次,从而引发问题。
解决这些问题的方法包括:
- 如果可以确定两个调用不会同时发生,并且此函数仅依赖寄存器而不访问内存时,你可以忽略这些警告。
- 对于需要使用内存的函数,请利用`OVERLAY` 指令来排除该函数被覆盖分析的可能性。例如:
```
OVERLAY (?PR?_WRITE_GMVLX1_REG?D_GMVLX1 ! *)
```
如果这个子程序在执行期间可以被调用,那么解决起来会更加复杂:
- 当从主程序中调用此函数时关闭中断。
- 使用`#pragma disable`来禁止对其他地方的函数进行覆盖分析。
- 将该子程序排除于overlay analysis之外。
此外还可以通过以下方式处理:
- 创造两个独立版本,分别用于ISR和main部分;
- 修改代码使其可重新进入。例如使用这样的定义:
```
void myfunc(void) reentrant { ... }
```
这种方法会生成一个用来存储参数及局部变量的栈,并且需要在`STARTUP.A51` 中配置该重入式堆栈,这将消耗更多RAM并减缓可重新进入函数的速度。