4

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:

  • UsageFault_Handler
  • BusFault_Handler
  • etc.

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.

artless noise
  • 21,212
  • 6
  • 68
  • 105
Traummaennlein
  • 474
  • 5
  • 12
  • 1
    Have you relocated the vector table to the start of your main application? – Colin May 17 '17 at 08:59
  • In fact 0x1594 IS divisible by 4 (but not by 8)! – Realtime Rik May 17 '17 at 14:35
  • yes, but not 0x1596. I had it right in the error message, but messed it up in the sentence below ;-( fixed it - thanks – Traummaennlein May 17 '17 at 14:41
  • I have set the address of the vector table: SCB->VTOR = address; – Traummaennlein May 17 '17 at 14:43
  • I also set the main stack pointer: __set_MSP(*ptr); where ptr is the pointer to 'address' – Traummaennlein May 17 '17 at 14:48
  • I got an example running by removing a lot of stuff. I prepared the USART0 but did not start and USART interrupt yet. I connected a switch which triggers the TX-ready interrupt and I immediately get an BusErrorInterrupt. SysTickInterrupt Worms fine. – Traummaennlein May 20 '17 at 19:19
  • @old_timer adding 1 moves the pointer to the next uint32_t, cause ptr first points to the address containing the stack pointer address and (ptr+1) points to the address containing the reset handler address. – Traummaennlein May 22 '17 at 07:01
  • Is your stack 8byte aligned when you jump to the program? Its required by the eabi, and a compiler could store 8byte chunks to it, assuming its aligned – Norbert Lange May 22 '17 at 07:02
  • ahh yes, thought you were using that to set the lsbit. How are you setting the lsbit (assuming it is set in the vector table is fine/good). Anding the VTOR with a mask is not good enough, if the address is not aligned properly then the vector table wont work so it should be a test and fail rather than an and with mask. – old_timer May 22 '17 at 13:09
  • sorry didnt see you had already figured this out yourself... – old_timer May 23 '17 at 00:54
  • Thanks to all of you. You where a creat help!! – Traummaennlein May 24 '17 at 06:21

1 Answers1

2

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).

Traummaennlein
  • 474
  • 5
  • 12