MCU: at91sam7s256 toolchain: Yagarto (gcc-4.2.1) I'm developing a simple application: First image XXX bytes length is burnt on the flash at the very beginning, by address 0x100000; second image resides on the flash at the (0x100000 + XXX). First image prints a short debug message on DBGU port and then should jump to (0x100000 + XXX) and run the second one - but it never happens! Enclosed are the main source file and linker scripts. What did I miss, seems like some trouble with addresses, at which applications run. Thanks in advance for any hints!
As far as I guess, the first image should disable interrupts before transferring control to the 2nd image. Am I right? And perhaps similar actions should be done with peripherial used by the first image, may be reset is important. Any comments are welcome! Thanks.
Roman Mashak wrote: > As far as I guess, the first image should disable interrupts before > transferring control to the 2nd image. Am I right? > > And perhaps similar actions should be done with peripherial used by the > first image, may be reset is important. > > Any comments are welcome! Thanks. Hi Roman, There should not be a need to disable interrupts. You only do a jump to some other location, so an interrupt should not cause problems. What I would like to know is, does the first program work as expected ? How do you load the two parts into the flash ? How is the first part executed ? Why do you include the startup code in the second part. Let me explain why I would like the answer to especially the last two questions. As you probably know, any ARM7 processor starts executing code from address 0x0. Most ARM processors have an option to temporary map the flash into this area. (I don't know how the AT91 does this though, so I hope the part below also applies to you) Your startup code should take care of mapping the flash back to 0x100000 when done and map RAM memory in the 0x00 area. The boot code of course should resides in the flash. Mmmm, is difficult to explain. But in your case, the startup code runs from address 0x00, but is stored at 0x100000. So I would expect a line in your linker file where you specify that the bootloader code is running in address 0x00 but stored in the flash. Normally you make a special section for that like: SECTIONS { BOOT 0x00000000 : AT (0x100000) { *Cstartup.o (.text) } _boot_size = (. + 3) & ~ 3; .text (0x100000 + _boot_size) : { *(.text .text.*) .... Of course the startup code only runs after a reset and should call the main function of your first program part. The 2nd part does not need startup code, as it is simply called from the first part. Hope this helps, Cheers, Kees.
Hi, Kees Stoop wrote: > There should not be a need to disable interrupts. You only do a jump to > some other location, so an interrupt should not cause problems. On the another forum I read, that enabled interrupts may cause the application, one transfers control to, to get into unpredictable state. I'm actually trying to implement a simple bootloader, which can load new firmware via USB and burn into flash. > What I would like to know is, does the first program work as expected ? Yes, it works as it should. > How do you load the two parts into the flash ? I use SAM-BA, which allows to specify the load address. > How is the first part executed ? The first part prints a string in DBGU, and attempts to jump over the address the second image resides on: [snippet] typedef void (*funct)(void); //* external functions extern unsigned disableIRQ(); ... int main(void) { AT91F_DBGU_Init(); AT91F_DBGU_Printk("before jump\n\r"); disableIRQ(); *AT91C_RSTC_RCR = 0xa5000004; //Reset only peripherals //Run the application ((funct)0x10058c)(); // address of 2nd part } This is what 2nd part is supposed to do: //* external functions extern unsigned enableIRQ(); ... int main(void) { enableIRQ(); AT91F_DBGU_Init(); AT91F_DBGU_Printk("after jump\n\r"); while (1) { } } > Why do you include the startup code in the second part. Earlier http://en.mikrocontroller.net/topic/144666#new I've been explained that startup is needed. ...
Roman Mashak wrote: > Hi, > > Kees Stoop wrote: >> There should not be a need to disable interrupts. You only do a jump to >> some other location, so an interrupt should not cause problems. > > On the another forum I read, that enabled interrupts may cause the > application, one transfers control to, to get into unpredictable state. > I'm actually trying to implement a simple bootloader, which can load new > firmware via USB and burn into flash. > >> What I would like to know is, does the first program work as expected ? > Yes, it works as it should. > >> How do you load the two parts into the flash ? > I use SAM-BA, which allows to specify the load address. > >> How is the first part executed ? > The first part prints a string in DBGU, and attempts to jump over the > address the second image resides on: > > [snippet] > typedef void (*funct)(void); > > //* external functions > extern unsigned disableIRQ(); > > ... > > int main(void) > { > AT91F_DBGU_Init(); > AT91F_DBGU_Printk("before jump\n\r"); > > disableIRQ(); > *AT91C_RSTC_RCR = 0xa5000004; //Reset only peripherals > > //Run the application > ((funct)0x10058c)(); // address of 2nd part > > } > > This is what 2nd part is supposed to do: > > //* external functions > extern unsigned enableIRQ(); > ... > > int main(void) > { > enableIRQ(); > > AT91F_DBGU_Init(); > AT91F_DBGU_Printk("after jump\n\r"); > > while (1) > { > } > } > >> Why do you include the startup code in the second part. > Earlier http://en.mikrocontroller.net/topic/144666#new I've been > explained that startup is needed. > > ... Hi Roman, Ok, well, after a second look, I guess that the link files are correct after all. You do need your startup code when you want to intialize the bss and data sections, so to init. global variables. However, normally the startup code does a lot more then just clearing bss and init the data section. I guess that the AT91, like all ARM7's start at address 0x00 after a reset, so the startup code should remap the flash. It also should provide the interrupt vector table and provide dummy handlers for unused exceptions. I don't think that the 2nd startup code should re-do those parts. So I guess it is best to write some simple startup code for the second part, that only clears bss and copies etext to data, before calling main. The first program should then jump to the start of the second startup code. But still, I don't get it. You do a jump to address 0x10058c, but you load the second program at 0x001004f8 so maybe I am just missing something. Kees.
Hi Kees and thank you for your response. Hm.. I'm completely confused with what should I do. And I don't quite understand the concept of remapping, though I've read in Atmel's appnote and in your message - but it's still unclear :( Do you think, if I make two identical C-startups, it will somehow spoil the behavior of the processor after jump? Kees Stoop wrote: > You do need your startup code when you want to intialize the bss and > data sections, so to init. global variables. However, normally the > startup code does a lot more then just clearing bss and init the data > section. I guess that the AT91, like all ARM7's start at address 0x00 > after a reset, so the startup code should remap the flash. It also > should provide the interrupt vector table and provide dummy handlers for > unused exceptions. I don't think that the 2nd startup code should re-do > those parts. So I guess it is best to write some simple startup code for > the second part, that only clears bss and copies etext to data, before > calling main. The first program should then jump to the start of the > second startup code. >
The code attached to the first e-mail is not complete. Just some thoughts: - Read the map-file and maybe the disassembly to see where your code and data gets located by the linker - Even if not done for AT91 the code in this project might help to understand some the needed settings in makefile, linkerscript and startup: http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/index_str.html#str7_uart_boot Of cause the hardware-init and remapping of exception-vectors has to be handled differently for AT91 but the concept is the same.
Martin Thomas wrote: > The code attached to the first e-mail is not complete. Just some > thoughts: > - Read the map-file and maybe the disassembly to see where your code and > data gets located by the linker Herllo, Martin. I've made 'objdump' of both images and explored it. So far I didn't find anything suspicious, except there's a bunch of instructions past the main() function, I don't know for sure it's normal or not. Just in case I'm attaching the archive with dumps, they're quite small, perhaps someone may clarify the issue :)
Roman Mashak wrote: > Hi Kees and thank you for your response. > > Hm.. I'm completely confused with what should I do. > And I don't quite understand the concept of remapping, though I've read > in Atmel's appnote and in your message - but it's still unclear :( > > Do you think, if I make two identical C-startups, it will somehow spoil > the behavior of the processor after jump? > > Kees Stoop wrote: >> You do need your startup code when you want to intialize the bss and >> data sections, so to init. global variables. However, normally the >> startup code does a lot more then just clearing bss and init the data >> section. I guess that the AT91, like all ARM7's start at address 0x00 >> after a reset, so the startup code should remap the flash. It also >> should provide the interrupt vector table and provide dummy handlers for >> unused exceptions. I don't think that the 2nd startup code should re-do >> those parts. So I guess it is best to write some simple startup code for >> the second part, that only clears bss and copies etext to data, before >> calling main. The first program should then jump to the start of the >> second startup code. >> Hi Martin, Yes, I think that with two identical startups you will have a problem. The 2nd startup is not required, unless you need to have your global variables initialized. To explain the mapping concept is a little difficult and I guess that the people from Atmel are much better in this then I am, so I suggest to read the datasheet about this. For the 2nd startup file, I would simply make a 2nd c-file and make sure this is loaded first. Your first program should jump to the StartSecond function, so make sure that this is the first function in the file. This should init the bss and data sections and then jump to main. So something like this: void StartSecond(void) { InitBss(); InitData(); main(); } To init bss, you can use the linker variables that you specified in the .ld file. You can use something like this: extern unsigned long __bss_start__[]; extern unsigned long __bss_end__[]; unsigned long *ptr; ptr = _bss_start_; while(ptr < _bss_end_) *ptr++ = 0; to init data, you can use something like this: extern unsigned long _data[]; extern unsigned long _edata[]; extern unsigned long _etext[]; unsigned long *src, *dest; src = _etext; dest = _data; while(dest < _edata) { *dest = *src; dest++; src++; } This should work (I know this from experience) Have fun! Kees.
Roman Mashak wrote: > Martin Thomas wrote: >> The code attached to the first e-mail is not complete. Just some >> thoughts: >> - Read the map-file and maybe the disassembly to see where your code and >> data gets located by the linker > > Herllo, Martin. > > I've made 'objdump' of both images and explored it. So far I didn't find > anything suspicious, except there's a bunch of instructions past the > main() function, I don't know for sure it's normal or not. > > Just in case I'm attaching the archive with dumps, they're quite small, > perhaps someone may clarify the issue :) I have done this for a boot loader, You need to set of linker script. 1- your first program should have a starting based address of you flash at 0x100000. The second one you will have to modify you new address to 0x100000 + size of your choice. After that when you download you bin files, don't forget to remove the flash erease command. Change your download script to reflect the address of your both bin files. After that everything should work. Jonathan
Jonathan Dumaresq wrote: > You need to set of linker script. > > 1- your first program should have a starting based address of you flash > at 0x100000. > > The second one you will have to modify you new address to > > 0x100000 + size of your choice. > > After that when you download you bin files, don't forget to remove the > flash erease command. > > Change your download script to reflect the address of your both bin > files. > > After that everything should work. Hello Jonathan. I've already done all this, and it didn't work for me. I'm pretty sure linker scipt is correct, because I explored the MAP file, generated after build, and 'objdump -SD ..'. Addresses seem to be correct. I suspect problem is with C-startup somewhere. If you don't mind, can I mail you my linker script and startup files? Perhaps you could catch the error. Thanks.
Roman Mashak wrote: > Jonathan Dumaresq wrote: >> You need to set of linker script. >> >> 1- your first program should have a starting based address of you flash >> at 0x100000. >> >> The second one you will have to modify you new address to >> >> 0x100000 + size of your choice. >> >> After that when you download you bin files, don't forget to remove the >> flash erease command. >> >> Change your download script to reflect the address of your both bin >> files. >> >> After that everything should work. > > Hello Jonathan. > > I've already done all this, and it didn't work for me. I'm pretty sure > linker scipt is correct, because I explored the MAP file, generated > after build, and 'objdump -SD ..'. Addresses seem to be correct. > > I suspect problem is with C-startup somewhere. If you don't mind, can I > mail you my linker script and startup files? Perhaps you could catch the > error. > > Thanks. look here www.cimeq.qc.ca/AT91SAM7SERIALBOOT_s256.zip you should find what your are looking for Jonathan
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.