Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending initial vector table to avoid checksum address on LPC4337 #17

Closed
martinmarcos opened this issue Jun 10, 2017 · 4 comments
Closed

Comments

@martinmarcos
Copy link

As I mentioned on Issue #16 we have been working on the porting of the embedded runtime to the EDU-CIAA-NXP board. At the end of last week we had a runtime that would build but no example to test it on. At the start of this week we finished a simple blinky example, we loaded it to the board and unfortunately it didn't work. Thankfully we were able to debug the board.

The runtime seemed to initialize correctly but when it got to the example code, at an specific line of code, we would get sent to the hard fault trap. If we modified the code we would still get a hard fault but at different line. The first thing that gave us a clue of what was going on was the assembly. We would debug line by line and inspect the assembly. We observed that the disassembler was indicating an undefined instruction at the line at which execution would be sent to the hard fault trap, obviously we were getting a hard fault because of the undefined instruction. When we would modify the example the line of source code at which the exception would get thrown changed but in the assembly the address stayed the same, it was very specific. An offset of 0x001C. We dumped the contents of the executable that we were flashing to the board and there was no undefined instruction at that specific address. So the first thing we thought was that we had a bad flash chip. We tried it on another board and same result. So now we were thinking that it had something to do with the MCU and its internal flash. We started looking through the user manual for a clue and voilà! Textually from the user manual:

The reserved Cortex-M4 exception vector location 7 (offset 0x 001C in the vector table)
should contain the 2’s complement of the check-sum of table entries 0 through 6. This
causes the checksum of the first 8 table entries to be 0. The boot loader code checksums
the first 8 locations in sector 0 of the flash. If the result is 0, then execution control is
transferred to the user code.

We did the math with the values and it checked out. So now we knew why, but we still didn't know how the code was getting corrupted. We knew it had to be done by the MCU itself or during the flash process. We continued to review the MCU's user manual but found nothing.

The board gets flashed through an FTDI USB JTAG adapter compatible with OpenOCD. To flash and debug the board with GPS we would launch OpenOCD with a configuration script we borrowed from the official CIAA developing environment and then launch gdb from GPS. Browsing through the script we realized it was using the lpc2000 flash driver with the option "calc_checksum" and from the OpenOCD documentation we found this:

calc_checksum: optional (but you probably want to provide this!), telling the driver to calculate a valid checksum for the exception vector table. Note: If you don’t provide calc_checksum when you’re writing the vector table, the boot ROM will almost certainly ignore your flash image. However, if you do provide it, with most tool chains verify_image will fail.

Anyway, to fix it we extended the initial vector table defined in start-rom.S and start-ram.S to include all the Cortex-M4 fault exceptions, that is up the Systick handler, so as to force the linker to avoid putting executable code at that specific address. We flashed the example and it worked. Success!

You can checkout the runtime code here, the example we used here. and the commit that fixed everything here.

Sorry for the lengthy preamble, but it also serves the purpose of documenting the process.

So what we wanted to ask was: What you consider would be the best solution to this problem? We think that maybe our fix is a dirty fix.

Rewards.

@Fabien-Chouteau
Copy link
Member

Great investigation!

Do you know if this behavior is specific to NXP's Cortex-Ms or all Cortex-Ms? Because we never saw this on the STM32F4/7.

@martinmarcos
Copy link
Author

martinmarcos commented Jun 13, 2017

Fabien,
I think the user code checksum that uses the 7th reserved entry of the initial vector table is specific to some of NXP's Cortex-Ms, not even all of them.

In OpenOCD's documentation the only flash driver that has a "calc_checksum" parameter is the lpc2000 driver. It even mentions the MCUs it's compatible with:

This is the driver to support internal flash of all members of the LPC11(x)00 and LPC1300 microcontroller families and most members of the LPC800, LPC1500, LPC1700, LPC1800, LPC2000, LPC4000 and LPC54100 microcontroller families from NXP. Note: There are LPC2000 devices which are not supported by the lpc2000 driver: The LPC2888 is supported by the lpc288x driver. The PC29xx family is supported by the lpc2900 driver.

I haven't found what the Cortex-M4 TRM dictates about how much of the initial vector table should be respected. What I did find on the TRM is that all Cortex-Ms' VTOR register should have a reset value of 0x00000000. Which means all of them expect the initial vector table to be at the beginning of the flash or whatever memory it's booting off.

Maybe it's all NXP's fault for not respecting what ARM wants to be left reserved.

@Fabien-Chouteau
Copy link
Member

OK so it's not something we need to fix in our run-times.

I think your solution is good. I would recommend a more detailed comment to explain why this .word hang /* 7 reserved. */ should never be removed.

Regards,

@martinmarcos
Copy link
Author

I think your solution is good. I would recommend a more detailed comment to explain why this .word hang /* 7 reserved. */ should never be removed.

Will do.
Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants