Executing Code From SDRAM

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Executing Code From SDRAM

Jump to solution
3,984 Views
echris
Contributor III

Hi,

I am trying to execute code from the TWR-K65F180M external (SDRAM).  I actually CAN start to execute code in SDRAM (0x80000000), yet somehow, I seem to keep reverting back to execution from on-chip flash (0x0).  How do I make sure that I continue to execute code from SDRAM?

Details

- I created a raw image file from an elf file.  This raw image includes a vector table (located at 0x80000000) and code section (located at 0x80000410).

- I then flash an elf file to the board (KDS debugger).

- Next I copy the raw image file to SDRAM via a tftp client.

- Finally, I pause execution and manually set the PC register to 0x80000410.

- Sure enough, when I step through the assembly code I can see that we do start executing code from 0x80000410.

- I can execute and step through instructions for quite a while however eventually (and for no apparent reason) execution returns to 0x410 (flash).

Does anyone have any idea what I should try, next?

Thanks!

0 Kudos
1 Solution
2,958 Views
jimcarroll
Contributor II

Are you disabling the watchdog timer? If not, it will trigger a reset after some time. After a reset, registers will return to their default values. The default VTOR setting is 0.

View solution in original post

0 Kudos
13 Replies
2,959 Views
jimcarroll
Contributor II

Hi, Eric.

You will need to modify your linker script to place your code (text) in the external RAM region. However, before executing code there, you will need to initialize the DDR controller. When debugging, you can achieve this using a debugger macro. When running stand-alone, your bootloader will have to take care of this before loading and running the program.

Jim

0 Kudos
2,959 Views
echris
Contributor III

Thanks Jim,

I have already done most of this.  I have modified the linker script to start the code section at 0x80000410 (external SDRAM).  The vector table I have placed in internal SRAM at (0x1FFF0000).

Furthermore I have seen that I CAN execute the code at SDRAM.  I actually execute a couple dozen instructions.  But then some sort of fault (or something) occurs and execution returns internal flash (0x410) rather than SDRAM.  This surprises me because I do set SCB->VTOR = 0x1FFF0000 (where I set my new vector table to), so it seems to be ignoring the new vector table.

Also, after this reset SCB->VTOR is somehow reset back to it's default value of '0'.  Why did this happen?  Why do I end up going back to the PC listed in the flash vector table? Rather than the new one in SRAM?

Am I setting up SCB->VTOR wrong?  What am I missing?

Thanks,

Eric

0 Kudos
2,959 Views
jimcarroll
Contributor II

Are you disabling the watchdog timer? If not, it will trigger a reset after some time. After a reset, registers will return to their default values. The default VTOR setting is 0.

0 Kudos
2,959 Views
echris
Contributor III

Also, what is the point of the VTOR register, if not to tell where to resume execution after a reset?

0 Kudos
2,959 Views
mjbcswitzerland
Specialist V

Hi

The best place for core register details is at the ARM infocenter:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/Ciheijba.html

Beware that you must locate the interrupt vector table (when in RAM) on a 512 byte boundary to accomodate the number of interrupts that the K65 has. If not, some interrupts can start calling the wrong handlers!

Regards

Mark

0 Kudos
2,959 Views
jimcarroll
Contributor II

The VTOR contains the base address of the interrupt vector table (i.e., where the NVIC fetches vector address from). Like most other registers, it will be set to a default value (0x00000000) after reset.

0 Kudos
2,959 Views
echris
Contributor III

No I am not disabling the watchdog.  Why would the watchdog cause a reset when I am executing from SDRAM?

Is there anyway of telling exactly what caused the reset?  For example, is there a status register that states what may have caused the reset, or what type of fault generated the reset?

Eric

0 Kudos
2,959 Views
jimcarroll
Contributor II

You are probably switching execution to SDRAM before you disable the watchdog in your ROM code.

I think there are some status register for resets that you can check. You will have to look in the reference manual for your MCU.

-Jim

0 Kudos
2,959 Views
jasonaguayo
Contributor I

Eric,

This sounds a lot like a problem I had recently on a digital signal controller (DSC).  I would try to run code from RAM, but it would mysteriously start executing from the processor's flash memory.  I copied the routine from flash to RAM and executed it using a function pointer.  After investigating the assembly code, I found the processor was using JUMP instructions instead of BRANCH instructions.  JUMP's use absolute addresses, which BRANCH instructions use offsets.  In my C code, I was using switch() statements to run a state machine.  Switch() statements translate to JUMP instructions in assembly, so whenever the code changed states, it would jump back to flash memory (and still execute properly, since I didn't move the original routine in flash).  I switched to using if/else statements and the code always ran in RAM.

Hope this helps!

Jason

0 Kudos
2,959 Views
echris
Contributor III

Thanks for the tip.  I don't think that it is this however.  I am using BRANCH not jump. And execution switches back to flash on a strh instruction not a jump.  I wonder if perhaps the strh command somehow causes a fault of some kind.

0 Kudos
2,959 Views
jhmrd
Contributor III

If you build the code with the standard bsp, initialization code in the bsp_cm.c file reprograms the PLL in the MCG registers. Also in init_hw.c, the _bsp_ddr2_setup (or  _bsp_sdramc_setup) function reprograms the DDR controller. These cause access to the SDRAM to be blocked while the PLL and DDR controller are not ready. This causes the CPU to fail to fetch its instructions from the SDRAM. It could also cause the contents of the SDRAM to be corrupted. In either case, the CPU faults and fetches instructions from the FLASH. I modified the bsp startup code by adding a check to see if the PC counter is executing in FLASH. If not, it skips the PLL and DDR controller setup functions. This allows the code we run in SDRAM to not crash.

0 Kudos
2,959 Views
ndavies
Contributor V

Does your code reprogram the NVIC to know the interrupt service table is located at 0x80000000? If not, it will still use the ISR table located at 0x00000000. This will cause a jump back to the code located in flash when you get an interrupt.

0 Kudos
2,959 Views
echris
Contributor III

I tried changing VTOR.

SCB->VTOR = 0x80000000;

And if I print that value back out I can see that it DOES change the value.  But I am not totally sure if I am doing this in the correct spot in my program.  Or if there is other values I should change also?

Do you have any more information on what the proper way of doing this is?

Thanks so much.

0 Kudos