armcortex-mrelocation

ARM M3 relocate code -> faults


ARM Cortex M3 (LPC1519)

I have written a bootloader (which so far seems to work) which runs in flash and writes the program into the Flash (behind the bootloader). The programm gets written and starts to run properly (at least when debugging).

When I use the SEGGER Ozone debugger, I am able to set a breakpoint at 'main' and step through the firmware. However, when I run a larger reagion in code (to another breakpoint), I always get some unexpected interrupts:

This does not happen, when I step trough the code command by command. It seams that the interrupts will not work properly.

The program runs fine when I flash it to address 0x00000000. I changed the linker script so that the origin lies at the later offset (where the bootloader places the firmware).

Has someone experienced similar problems?

Thanks, Johann

PS: sorry I can't provide a minimal sample, cause I don't know where to start

Edit - Additional Information: I now downloaded a smaller project where I can find an error in debugger. There is a uint32_t variable in a struct which seems to trigger the error. It says:

Mis-alligned memory read: Address: 0x00001596, NumBytes: 8, Alignment: 4 (Word-aligned)

In fact 0x1596 is not devideable by 4 so the error is justified, but how can this be? Shouldn't the compiler take care of aligning variables in structs?

Edit - Additional Information: It seems that this error always occur when the USART0 IRQ is triggered (txReady). Might it be possible that I have a problem with interrupts? The ARM Cortex SysTick (SysTick_Handler) is running well!?

[[noreturn]]
inline void startFirmware(std::uint32_t address) noexcept
{
    //<removed checks for correct address>

    //pointer to the address
    const auto ptr = reinterpret_cast<std::uint32_t*>(address);

    // Set vector table offset
    SCB->VTOR = address & SCB_VTOR_TBLOFF_Msk;

    // Set top stack handler
    __set_MSP(*ptr);

    // Get address of reset handler
    const auto resetHandler = *(ptr + 1);

    // Jump to reset handler
    reinterpret_cast<internal::ResetHandlerFunction>(resetHandler)();
    while(true);
}

Edit - Additional Information: It seems that all Interrupts triggered by USART, CCTimer, etc. end up in exceptions, but I can not find out the reason why.


Solution

  • I found out why the Interrupts would not have worked.

    In the ARM Doku I found this sentence:

    When setting TBLOFF, you must align the offset to the number of exception entries in the vector table. The minimum alignment is 32 words, enough for up to 16 interrupts. For more interrupts, adjust the alignment by rounding up to the next power of two. For example, if you require 21 interrupts, the alignment must be on a 64-word boundary because the required table size is 37 words, and the next power of two is 64. See your vendor documentation for the alignment details for your device.

    This means, when you have more than 16 interrupts, you can't place your SCB->VTOR to addresses which are 32-word alligned (ending with 0x80), but only to 64 word aligned address (ending with 0x00). In my case 0x1100 instead of 0x1080 (I use the first 128byte for Information about the program, which the bootloader can verify).