I would like to write an IAR application that lives solely in RAM. I have a bootloader that will load the code via USB at runtime but I don't know how to setup the linker script. Does anyone have an example? Just a linker script would be nice but a whole project would be fantastic.
IAR Execute in RAM after copying from Flash or ROM
IAR Download and run whole application in RAM (Cortex-M3)
I'm trying to follow these examples but IAR doesn't work that way anymore (big surprise). I took the gpio_led_output I found in the CMSIS pack examples but it tells me I can only edit the linker in the text editor. Honestly I didn't even know the "edit" button would bring up another menu, I always assumed it just open the file in an editor.
I am able to force the entry point to a given address as long as the function is named __low_level_init. If I rename this function startup (its not really the __low_level_init function in the compiler sense) the compiler tosses it out because it's not actually called from my program. What must I do to prevent the compiler from removing this "unused" function?
I apologize for my "shotgun" approach to asking questions...
I'm not sure if this is right but I added a call to main at the bottom of my __low_level_init function and I've got some blinking lights now.
I've got one more piece of the puzzle figured out. I added this
place at address mem:__ICFEDIT_region_ROM_start__ { readonly section .init };
to the linker file and then added
#pragma location=".init"
above my __low_level_init function. I can see that the __low_level_init function is now at 0x20000000 but I still dont ever see the code jumping to main.
Mark,
When you say you are loading and operating in SRAM, what exactly are you loading? Is this some code that exists as a standalone IAR project (meaning it includes the low level init stuff). The only thing I've done is update the linker script to put everything in RAM and then override the low_level_init.c code with my own where I update the SCB_VTOR
SCB_VTOR = (unsigned int) & __vector_table;
I jump to the code like so...
typedef void(*jumpFunc)(void);
uint8_t BootJump(uint32_t address)
{
/* Jump to whatever address user specifies */
jumpFunc jump = (jumpFunc)(address | 0x1);
jump();
//EnableInterrupts
return TRUE;
}
with address = 0x20000000
the contents of that address is the new stack pointer and when I jump to that address I get a hardfault. I want to use the upper SRAM to hold my ramcode and the lower SRAM is for my stack and heap with the stack pointer starting at 0x20000000.
Essentially what im trying to do is create a project i can use to build ramcode modules I can load and run at runtime. When I do this with the older processor expert (not sure if im saying this right, before KSDK I used codewarrior and a GNU compiler) code my startup function looks like this
__attribute__ ((section (".init"))) void startup(void)
{
extern unsigned int __vector_table[];
extern char __START_BSS[];
extern char __END_BSS[];
char * ptr = __START_BSS;
__DI();
/* Copy interrupts from flash to allow RAM code to install it's own handlers */
memcpy(__vector_table, (unsigned char *)ROM_VECTOR_LOCATION, VECTOR_TABLE_SIZE);
SCB_VTOR = (uint32_t)__vector_table; /* Set the interrupt vector table position */
// zero-fill the .bss section
while(ptr != __END_BSS)
{
*ptr++ = 0x00;
}
/* Enter main with interrupts disabled */
main();
/* Reset interrupt vectors to ROM */
SCB_VTOR = (uint32_t)ROM_VECTOR_LOCATION;
/* Return to bootloader */
}
IAR has hidden most of the startup code from me so I can't figure out where I need to initialize things.
Does any of this make sense? I'm having a hard time explaining what I'm trying to do.
Ryan
You don't want to jump to the stack pointer - you want to jump to the entry point - this is at 0x20000004 and not at 0x20000000.
You need to load the content of the first address to the SP and then the second to the PC (or jump to it as you have done).
You don't need to "or" the address with 1 since if it is valid code it will already be an odd (Thumb) address.
Regards
Mark
P.S. I use only the IAR variable initialisation code (which one can't really avoid) and nothing else from the IAR startup.
P.P.S. I understand what you are doing since I have done the same in various product developments with Cortex parts
Mark,
Would you be willing to take a look at my code if I shared it with you? I would like to force the entry point to be 0x20000000 (it needs to be to be backwards compatible with my code warrior bootloader). I was able to move the vector table to 0x2007000 but the disassembly I see at 0x20000000 does not look like an entry point. From the map file I see it placed "packbits_init_single" at 0x20000000.
What exactly should my entry point be considering the bootloader as already initialized the processor? I tried to force it to be _low_level_init in the linker settings but that doesn't appear to do anything. I also tried to change the assembly in the reset handler to jump to __low_level_init instead of __iar_program_start but the linker complains that its missing __iar_data_init3. I don't think I want the reset handler to be the entry point anyways.
Mark,
What I’m really trying to do is move the vector table to 0x2007000 so 0x20000000 would be the entry point.
Then at ramcode startup I will copy the bootloader’s vector table to the new location so I can install my own handlers.
Thank you,
Ryan
(sent from mobile device)