eldarkg / emdr1986x-std-per-lib

Milandr MCU 1986x Standard Peripherals Library. Mirror:
https://code.launchpad.net/~eldar/emdr1986x-std-per-lib/+git/emdr1986x-std-per-lib
46 stars 29 forks source link

Various src compiled code that works with EEPROM enter MCU to the Hard Fault #18

Open eldarkg opened 7 years ago

eldarkg commented 7 years ago

Affected code with EEPROM_*() functions calls. The code compiled in GCC 5.x. P.S. Bug is strange and I didn't find why it appears. I'll try to find it.

eldarkg commented 7 years ago

This issue linked with #2 I think. Commit bae2538 gives wrong solution of this issue.

eldarkg commented 6 years ago

Check the CMSIS issue in future. Maybe the current issue is related with this one.

eldarkg commented 6 years ago

The bug appears yet in gcc 7-2017-q4-major.

eldarkg commented 6 years ago

Opinion: maybe it is need to add ProgramDelay after MDR_EEPROM->CMD = Command; MDR_EEPROM->KEY = 0; (before exit from EEPROM_* functions)

AndreySV commented 6 years ago

I think, I've experienced similar problem.

Here is my test code

static void __attribute__((__noinline__)) test_call(void) {
    static volatile int x=0;
    x++;
}

/* void __is_ramfunc __attribute__((__noinline__)) init(void) */
void init(void)
{
    __disable_irq();
    mcu_clk_init();

    volatile uint32_t val = 0;
    RST_CLK_PCLKcmd(RST_CLK_PCLK_EEPROM,ENABLE);
    val = EEPROM_ReadWord(START_USR_EEPROM_ADDR, EEPROM_Main_Bank_Select);
    /* test_call(); */
    EEPROM_ErasePage(START_USR_EEPROM_ADDR, EEPROM_Main_Bank_Select);
    EEPROM_ProgramWord(START_USR_EEPROM_ADDR, EEPROM_Main_Bank_Select, val + 1);
    for(;;) {
        val = val;
        nop();
    }
        ....
}

After returning from EEPROM_ErasePage problem is happening on first/second instruction. In I step through instrustion in gdb, then I saw the PC changed to some wrong value after executing first/second instruction after EEPROM_ErasePage call. Then MCu executes random places in MCU until it finds some invalid instruction and then HardFault happens.

If EEPROM_ErasePage is called from function in RAM, than all is good. if uncomment 'test_call()', then code is working as well (this is similar to use 'short_call' instead of 'long_call', because shortcall introduces intermediate functions for every `EEPROM*` function. Looks like something related to pipeline/flash accelerator flushing.

I tried to add ProgramDelay after MDR_EEPROM->CMD = Command; MDR_EEPROM->KEY = 0; (before exit from EEPROM_* functions) as you recommended nothing changed. And e CMSIS issue most likely is not the proble (at least in my case), because I've experience this problem on Cortex-M3 and there is no code dealing with MSR in my test example.

Settings different flashing latencies changes nothing, Using slow CPU clocks doesn't help either. Different compiler were tried 4.9.3, 5.2, 6.3.1 on GNU/Linux.

eldarkg commented 6 years ago

@AndreySV I forgot to write that for me helped calling EEPROM_* functions from code in RAM as you said.

AndreySV commented 5 years ago

@eldarkg, why do you think that commit bae2538 gives wrong solution of this issue?

eldarkg commented 5 years ago

@AndreySV Because the issue repeated after this fix too.

AndreySV commented 5 years ago

Interesting. Do you remember were intermediate functions for EEPROM_* generated by the compiler and used when the issue happened?

eldarkg commented 5 years ago

@AndreySV Sorry, I dont remember.