0

我正在尝试修复在富士通 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
}
4

2 回答 2

0

可能是许多事情之一,但有两个浮现在脑海中。

定时。

也许等待时间不足以使电源稳定下来,并且并非所有内容都与时钟同步。NOP 让一切恢复同步。

结盟。

也许 NOP 让您的指令在硬件预期的 32 或 64 位边界上对齐。(我们过去常常在大型机汇编器上这样做,因为 IO 操作通常期望事情在双字边界上)。

于 2015-01-29T02:02:25.430 回答
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 同步了。

我所要做的就是在 MCU 复位后立即初始化所有 EEPROM 的 SPI 线,尤其是 nHOLD 和 nCS。

于 2015-06-20T21:30:12.580 回答