Start address different from zero

Status
Not open for further replies.

beubeu

Member
Hi,

I have used a bootloader to send my program through serial port.
This bootloader is a t address 0x000000. In consequence, I stated my program at address 0x8080.
The blink example works at this address but my program doesn't.
The solution has been tested with the board TWR-K20D72M (http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=TWR-K20D72M#prettyPhoto) and it works.

It seems that the problem comes from the teensy board.
It seems to appear when using the serial port (UART). In deed the example Communication\MultiSerialMega does not work when the address is changed.

Do you have any idea why it does not work?

regards,

Benoit
 
I just tested Communication / MultiSerialMega, using a Teensy 3.1 and a FTDI cable with the seyon terminal emulator.

It seems to work perfectly:

screen.png
(click for full size)
 
yes it works when we launch it address 0x00000.
My problem is that I used utasker bootloader and I changed the linker script to write start address at 0x8080.
It seems to work well on TWR-K20D72M but not on teensy 3.1.
That's weird because it is the same proc. I don't see what could be the particularity of teensy 3.1 that causes the problem.

regards,

Benoit
 
I speak already with him^^
He advised me to ask in teensy forum to see if someone would have an answer about the difference between teensy and the other board.

regards,

Benoit
 
I really can't comment on hardware differences. Both schematics are published, so if you want to dig into the hardware, you certainly can. I just can't spend time on that.

Teensy is designed to give your code complete control over the CPU. There's no bootloader burned into any part of the K20 chip. Your code is running directly, without anything like uTasker's bootloader, just as it would be if you bought blank chips from Freescale and programmed your code onto them with a programmer, like the ones P&E Micro sells.

I can't help you with custom linker scripts, or utasker, or non-Teensy hardware. I can and do spend a lot of time digging into details of problems, but this is simply outside what I can support for Teensy.
 
Hi,

ok I understand. but do you know if there is anything in the code that has a fixed address and so make it not relocatable?

regards,

Benoit
 
Hi

I will chime in now since things are getting quite serious. I have myself spend many hours trying to debug what is taking place but not being able to do real source code debugging it is proving to be like trying to find a needle in haystack.

First some details:
1. It is not a problem with the boot loader itself since simply adding a couple of lines of code to jump to an offset program address causes some programs to fail.
2. The issue is on the Teensy board (but not due to its hardware) and is essentially the same on any other HW with the same chip (the other HW is used as cross-reference since assembler level debugging is then possible and basicalyl [with some potential randomness thrown in] the issue is the same on all).
3. There has been one change to the code to allow it to essentially work when the start address is not 0. This is to set the vector offset value to the same address (rather than 0), which allows interrupts to work.
4. It is not that the code doesn't operate since the USB "Teensy serial" enumerates (we test various standard Arduino / Teensy codes like the blink and MultiSerialMega). Blink works with and without the offset but MultierialMega doesn't (works fully without offset and partially with). It doesn't crash since the USB enumerates but its UART doesn't operate (although it is configured)
5. In addition, it has been seen that using C++ "new" fails to allocate dynamic memory (correctly) when linked to an offset.

State of the investigation:
- originally it was thought that something was crashing (was true initially since interrupts wouldn't work due to the fixed vector offset of 0x00000000 but that was obvious and quickly adapted) but it is in fact more subtle since the code is in fact spinning in the main loop and the USB part is OK. Just some parts stop working.
- the thinking is that maybe some variable initialisation is not being completed since there seems to almost be a random nature about the issue.
-since the programs are all correct when linked to 0x000000 but shows the unexpected behaviour only when inked to an offset it is quite sure that the offset is causing some difficulties.
- therefore the present question is whether there is any code that is known to not support relocation. Examples of such would be fixed code that relies on something in flash being at a defined address. I noticed that there are some sections declared in the linker script which are put between the interrupt vectors and the flash coniguration area; probably to insert small pieces of code there to use up the space but could it be that some of this code expects thing to be at fixed addresses there? Note that the onyl change in teh linker script is to modify the start address from 0x00000000 to 0x00008080

I believe that there must be a small details that can't be seen at the momet due to lack of debugging capabilities on the Teensy and if this coud be resolved there is more or less a complete solution ready. If it can't be resolved it may cause more major problems because it could prove to be necessary to port a complete (working) project to a different environment to overcome this limitation that hasn't been able to be located.

An idea or two may help to focus in on parts of code that may potentially have relocation restrictions.

Thanks

Mark
 
Hi Paul

After another day of work I have defined a simple way to show that the "MultiSerialMega" fails (doesn't operate as normal) if the code is set at an offset.
This doesn't involve installing an boot loaders and can be reproduced by the following steps.


1. Normally build and load the MultiSerialMega project and verify that each character typed into the USB serial port is sent out on the UART output.

2. Now modified the linker script at one location:
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
to
FLASH (rx) : ORIGIN = 0x00008080, LENGTH = 256K

This shifts the code to start at 0x8080.

3. In mk20dx28.c comment out the watchdog unlock sequence (but not the wathdog disable).

/*
WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
asm volatile ("nop");
asm volatile ("nop");*/

and change

SCB_VTOR = 0x0; // use vector table in flash
to
SCB_VTOR = 0x8080; // use vector table in flash

This means that the new interrupt vector location operates correctly. The reason for the watchdog unlock disable is explained below.

4. Build the project but don't load it to the Teensy yet (it can't run yet since it has no reset code at 0x00000000).
Now edit the hex file by adding these line at the very beginning (before the original code)

:10000000008000200900000044f205004fea004093
:1000100040f400504cf220524df62811c281c181ab
:1000200048f28000d0f800d0d0f804f0350000008d
:10040000FFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFD

This is a new reset vector that jumps to 0x00000008. At this address the code does the following:

asm("movw r0, #16389");
asm("lsl r0, r0, #16");
asm("orr r0, r0, #8192");
asm("movw r2, #50464");
asm("movw r1, #55592");
asm("strh R2, [r0, #14]");
asm("strh R1, [r0, #14]");
asm("movw r0, #32896");
asm("ldr sp, [r0]");
asm("ldr pc, [r0, #4]");

That is, it writes the watchdog unlock sequence and jumps to the code at 0x8080. [Also the flash config line is inserted into the HEX file so that the chip is left unsecured].
This is the minimum code needed to do this and it tests the offset without needing a boot loader installed. I found that I had to do the watchdog unlock here because the code would otherwise fail in the application, but the application is still disabling it (since it is unlocked and it has time to do it). The unlock sequence in the application seems otherwise to be too late and causes an immediate reset (there are a limited number of clock cycles after the reset in which it can be done).

With these simple modifications any Teensy project can be converted to a version that is offset and starts at the new offset.


5. Load the HEX file manually to the Teensy3.1 and test the project again and it will be seen that the USB enumerates correctly. The first character typed in also appears at the UART output.
The difference is however than no further characters are sent after that first one.


If the same is done with the blink project it is found that both HEX files work the same (with no offset of with the 0x8080 offset).
There is a definite behavioural difference with the MultiSerialMega project though.
This is quite consistent with results from production projects where everything looks fine until a certain change is made any then the behaviour deviates depending on the link address.

Therefore the question is still open as to why there is this behaviour with the Teensy/Arduino project code whereas it has never been experienced with a number of other projects used at offset addresses?

Regards

Mark
 
Hi

For completeness I have attached the blink and serial HEX files that have already been prepared (the one with "0" in the name is the standard one without an offset). These can be easily loaded ad the difference in case of the serial project seen.

Regards

Mark
 

Attachments

  • TEST_HEX_FILES.zip
    58.6 KB · Views: 108
Teensyduino 1.20 changed from a fixed, flash-based vector table to a RAM-based vector table.

Maybe that matters, somehow? I really do not know, and offsetting from the standard 0 location is not something I can put any time into supporting. This will be my 5th and probably last reply on this thread. I just can't put time into supporting this.
 
Shouldn't the LENGTH be 224K not 256K after offsetting ORIGIN? Not sure if that is a significant change.

Edit: nevermind, it seems to make no difference.
 
Last edited:
@uTasker I followed your instructions and got the blink example working and it blinks with the flash offset of 0x8080 as you said. I then added Serial1.begin() to setup(), Serial1.write('a') to loop(), and I get a single 'a' in my terminal and no blinking. If I remove the code in fault_isr(), I get no 'a' and no blinking.

My guess is there's something wrong with the vector table, and ISRs are not being properly called by interrupts.

Hope this helps.
 
Turns out the fix is really easy: don't change the SCB_VTOR line. I changed the line back to SCB_VTOR = (uint32_t)_VectorsRam; and MultiSerialMega works as it should.
 
@embedded-creations
Thank you, we weren't using a version with interrupts in SRAM, but moving them there does solve the issue.

It has been possible to identify the actual cause in that the UART0 interrupt arrives as a DMA channel 13 interrupt when the VTOR offset is set to 0x8080. This results in the undefined interrupt handler being called, which allows USB to continue operating (this was the most misleading part in fact because without a debugger it initially looked like everything was OK, with exception of certain smaller parts, like the UART not sending more data after the first byte which had caused the exception).

Furthermore it was found that offsetting to 0x8000 works as expected but when offsetting to 08100 the UART interrupt then operates correctly but the USB interrupt fires as DMA channel 9 interrupt instead.

According to the ARMv7-M Architecture Reference Manual the VTOR has a resolution of 0x80 (and the VTOR test in the K20D72 also returns this result - one writes 0xffffffff and reads back 0xffffff80, showing the implemented bits). The K20D72 Users manuals and data sheets don't reference any restrictions specifically for this device but it is now known that VTOR offsets of XXX80, XX100 and XX180 cause the interrupt vectors to be 'corrupted' XX200 is the smallest step possible for this processor.

The case has been reported at the Freescale forum https://community.freescale.com/thread/337498 to see whether this is an errata or an implementation details that I not imposed by ARM (or even expected). My feeling is that Freescale has implemented the VTOR as an OR with the vectors rather than an ADD (which would give this effect) but I don't know yet whether this is an 'error' as such.

Regards

Mark
 
Isn't this documentated behavior? http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/Ciheijba.html

"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 of your device."

Teensy 3.1 has 95+16 interrupts (Teensy 3.0 46+16), each vector need 4 bytes, so we have 4*(95+16) = 444 bytes. the next power of 2 is 512 (0x200), which gives the alignment. Nothing wrong with it (?!)
Or, am i wrong ?
 
Last edited:
Isn't this documentated behavior? http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/Ciheijba.html
Teensy 3.1 has 95+16 interrupts (Teensy 3.0 46+16), each vector need 4 bytes, so we have 4*(95+16) = 444 bytes. the next power of 2 is 512 (0x200), which gives the alignment. Nothing wrong with it (?!)
Or, am i wrong ?

Frank

Thank you for the clarification. I have been using the "ARM®v7-M Architecture Reference Manual" where this detail is not mentioned.

Now it is clear that the 0x200 boundary, as found from experimentation, is the expected limitation for this device (due to its number of interrupts) and that it changes depending on the number of interrupts available.

Also the reference states "See your vendor documentation for the alignment details of your device", but this detail was not found there either.

In future I will use the on-line reference which looks to be superior.

Regards

Mark
 
Flash protected ?

Hi,

i'm planning to use the flash too, but not for a bootloader.
I want to read files from a sd-card (in a "sketch") and burn it to the remaining free flash.
But before i start coding, i have a question. Are there any lockbits set, do i have to deal with them ?
Does anybody have any useful hints for me ?

thank you :)
Frank
 
Last edited:
Are there any lockbits set, do i have to deal with them ?

Frank

Lock bits are controlled in the flash configuration area (0x400..0x40f). Since you have full control over these and the Teensy project sets them per default with 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xfe 0xff 0xff 0xff (the single 0xfe is to remove security) there is nothing locked.

There is a thread about flash programming at https://community.freescale.com/message/395090#395090

If any code is missing you can get all necessary components from the uTasker serial loader project since it contains the Flash programming interface and SD card support so will copy SD card data to internal flash (as well as USB-MSD/USB-HID or UART data to internal Flash). It does this normally to load applications but doesn't need to be used for this purpose. The SD card data can can be encrypted or plain text and is matched either by full name or by wild-card name matches.

Regards

Mark
 
Is your ecode-example in the thread @ freescale ok for K20 too ?

Frank

The code in the thread is suitable for any K processor which uses long-word programming (including K20-72 as on the Teensy).
There are a few differences for K parts using phrase programming (essentially parts including floating point unit (FPU)) and for KL and KE tyes, but the version on the uTasker download page [http://www.utasker.com/forum/index.php?topic=1721.msg6697#msg6697] is a generic one which can be used for all of these (adapts itself accordingly).

Regards

Mark
 
Frank

The code in the thread is suitable for any K processor which uses long-word programming (including K20-72 as on the Teensy).
There are a few differences for K parts using phrase programming (essentially parts including floating point unit (FPU)) and for KL and KE tyes, but the version on the uTasker download page [http://www.utasker.com/forum/index.php?topic=1721.msg6697#msg6697] is a generic one which can be used for all of these (adapts itself accordingly).

Regards

Mark

Great, thank you for the useful information.

Regards, Frank.
 
Status
Not open for further replies.
Back
Top