我正在尝试修复在富士通 MB90F543 的成熟程序中发现的错误。该程序至今运行了近10年,但发现在某些特殊情况下,它一开始就没有做两件事。其中之一至关重要。
在低电平和高电平初始化(端口、引脚、外设、IRQ 处理程序)之后,通过 SPI 从 EEPROM 读取配置数据,并且状态 LED 会打开片刻(要打开它们,数据会通过 SPI 发送到 LED 驱动器)。当这些特殊情况首先发生并且只有第一个函数调用几个 EEPROM 读取失败并且另外一些应该不打开的 LED 时。
该程序用 C 语言编写并使用 Softune v30L32 编译。令人惊讶的是,在低级硬件初始化中添加单个 __asm(" NOP ") 就足以使程序在上述情况下按预期工作。在优化设置中关闭“指针别名的控制优化”就足够了。在不同的地方添加几行代码也有帮助。
我已经比较了编译程序的(DIFFed)ASM 列表,用于具有和不具有 __asm(" NOP ") 的版本以及上述两种优化器设置,它们看起来都很好。
在编译过程中,Softune 编译器多年来一直打印的唯一警告如下:
*** W1372L:该部分位于 RAM 区域或 I/O 区域之外 (IOXTND)
我确实意识到这是一个相当笼统的问题,但也许有更大图景的人能够指出可能的原因。
你知道什么可能导致这种奇怪的行为吗?如何找到错误并修复它?
在初始化期间,使用了几个长(大约 20 毫秒)的延迟循环。尽管它们从大约 2 毫秒开始增加,但它们没有帮助,但硬件初始化函数的任何行中的单个 NOP 甚至在函数之前或之后都有帮助。
两个等待循环都有效。我已经用示波器检查过了。(我在之前和之后添加了 LED 开启)。
我通过将 SPI 时钟从 1MHz 降低到 500kHz 来检查时序假设。它不会改变任何东西。减慢到 250kHz 会使看门狗复位,因为代码的某些部分执行时间过长(>25ms)。
还有一件事。我观察到在任何源文件中添加局部变量有时会使问题消失或重新出现。同样涉及初始化未初始化的局部变量。在任何文件中添加几行额外的代码有助于或揭示问题。
void main(void)
{
watchdog_init();
// waiting for power supply to stabilize
wait; // about 45ms
hardware_init();
clear_watchdog();
application_init();
clear_watchdog();
wait; // about 20ms
test_LED();
{...}
}
void hardware_init (void)
{
__asm("NOP"); // how it comes it helps? - it may be in any line of the function
io_init(); // ports initialization
clk_init();
timer_init();
adc_init();
spi_init();
LED_init();
spi_start();
key_driver_init();
can_init();
irq_init(); // set IRQ priorities and global IRQ enable
}