我正在尝试修复Fujitsu MB90F543成熟程序中发现的错误。到目前为止,该计划已有近10年的历史,但有人发现,在某些特殊情况下,它在一开始就没有做两件事。其中之一是至关重要的。
在低电平和高电平初始化(端口,引脚,外设,IRQ处理程序)之后,通过SPI从EEPROM读取配置数据,并且状态LED打开一会儿(将数据通过SPI发送到LED驱动器)。 当这些特殊情况首先发生时,只有几个EEPROM调用的第一个功能失败,另外还有一些LED应该不能打开。
程序用C语言编写,使用Softune v30L32编译。 令人惊讶的是,在低级硬件init中添加单个__asm(" NOP")就足以使程序在上述情况下按预期工作。关闭“控制指针别名优化”就足够了。在优化设置中。在不同的地方添加几行代码也有帮助。
我已经比较了(DIFFed)已编译程序的ASM列表,包含和不带__asm的版本(" NOP")以及上述两种优化器设置,它们看起来都很好。
Softune编译器在编译期间多年来一直打印的唯一警告如下:
*** W1372L:该部分位于RAM区域或I / O区域(IOXTND)之外
我确实意识到这是一个相当普遍的问题,但也许有更大局面的人可以指出可能的原因。
您是否了解可能导致这种奇怪行为的原因?如何找到错误并修复它?
在初始化期间,使用了几个长(约20ms)的延迟循环。他们没有帮助,虽然它们从大约2ms开始增加,但在硬件初始化功能的任何一行中都是单个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
}
答案 0 :(得分:0)
可能是许多事情中的一个,但有两个想到。
时序。
也许等待时间不够长,电源不能稳定,而且并非一切都与时钟同步。 NOP让一切恢复正常。
对齐。
也许NOP会使您的指令在硬件预期的32或64位边界上对齐。 (我们曾经在大型机汇编程序上做了很多这样的事情,因为IO操作通常期望事物在双字边界上。)
答案 1 :(得分:0)
问题解决了。这是由一个微不足道的错误造成的。
EEPROM的nHOLD和nCS信号在MCU复位后没有立即初始化,但在第一次使用EEPROM之前没有初始化。结果他们是0岁,非常活跃。 这意味着选择了EEPROM,但等待保持。同时使用SPI启动其他传输。在8个CLK脉冲中的6个之后,EEPROM的nHOLD I / O引脚被初始化并变为高电平。 EEPROM不再处于保持状态,因此它为另一个外设的最后两位数据提供时钟。 EEPROM上的每个后续操作都发现它没有同步CLK和MOSI。
当我添加NOP或其他任何其他时刻nHOLD 0-> 1时,边沿被移位到最后一个CLK脉冲之后。现在CLK-MOSI同步了。
我所要做的就是初始化所有EEPROM的SPI线路 在MCU复位后,特别是nHOLD和nCS。