2008-12-26 02:44 PM
Need some help creating an IAP app
#iap #bootloader #upsd32532011-05-17 03:04 AM
I cannot quite grasp the IAP fucntionality yet. I'm a newbie working with the DK3200. I am familiar with the general mapping of an IAP program as follows:
Boot to secondary flash which contains the IAP program. The IAP program can perform various validity checks on primary flash sectors to determine good/bad status of main program. The IAP can then modify the VM and page register and ''jump'' to the page of the main program. Can someone please give some specifics on the VM and page register modifications. :-[2011-05-17 03:04 AM
IAP can be tricky. Before I even get started, do you plan to use this with an ICE (in-circuit emulator). Neither the one made by Nohau or by Manley support the most efficient means of performing IAP since it involves ''swapping out'' the entire code space. Let me know that and I'll be able to answer your question more effectively.
2011-05-17 03:04 AM
No emulators. simply using the DK3200.
2011-05-17 03:04 AM
Alright... here's the way to do it that I found most accomodating:
1. Create a memory map that has one page with secondary flash mapped in the lower 32kB of code memory and main flash mapped into the upper 32kB (or whatever) of data memory (with your RAM and the like in the lower 32kB of data memory). This map should have another page with main flash mapped into the lower 32kB of code memory and secondary flash not mapped anywhere. 2. Create a project for some compiler (I use Keil) to contain your IAP routines. Make sure to copy and include the STARTUP.A51 code from Keil if that's what you're using. In this project, write the various routines for programming the main flash, etc. 3. Create another project to contain your main application. Find an open block of fixed code memory and define some constants there that are all FF's, like so: const unsigned int code statusbytes = 0xFFFF; 4. Modify the STARTUP.A51 file for BOTH projects to be IDENTICAL. This assembly code should, at startup, check the status bytes of the main application and if they're equal to some predetermined value (OTHER than FF), run the application. Otherwise, it should just run the IAP routines. The way the code runs the application is by changing the VM register to let it fetch code from EITHER main or secondary flash, THEN swapping to a page which places main flash in the space previously held by secondary flash. A final note is that you have to tell the linker to place this startup code (in Keil, the routine is C_C51STARTUP) at the EXACT same memory address. Just look at the memory map and pick someplace that looks convenient. Notes: - When you finish programming the main flash application, you should set the status bytes to whatever value you want to be your ''good'' indicator. For examples, I use 0xFE - Your startup assembly code also needs to check if you're trying to switch into IAP mode. I do this by writing a long key sequence into RAM from the main application when IAP is initiated and then letting the watchdog reset the processor. I have my startup code check this BEFORE seeing if the application is valid, and if it's there I run the IAP routines. Make sure it's a long enough key sequence that random RAM contents at startup couldn't accidentally prevent you from running the application. - When you start reprogramming flash, the very FIRST thing you should do is program your status bytes to 0x0000, that way if anything goes wrong, your startup code will know NOT to try and run a corrupted application. There are some other nifty things you could do. With as much memory as the DK3200 has, it's possible to have multiple application images and have the startup code just run whichever one is valid. This way, you avoid ever having no application to run after a failed download. Hopefully some of that will help. It took me quite a while to wrap my head around what's involved in doing all this manual paging.2011-05-17 03:04 AM
Wow! Lots of work ahead of me.
Thanks for taking the time to explain that to me. It has been a real help. I'm sure that I'll have followup Q's eventually, but until then, good day sir.2011-05-17 03:04 AM
I ask hesitantly as I do not want to bite the hand that feeds me.
Could you possibly attach/paste an example of the startup.a51 routine which provides the following functionality: checks main flash validity, looks for the IAP key pattern in RAM, and jumps to either main or IAP routines? An example would put me further along the path of comprehension much faster. I will understand if you choose not to disclose such information.2011-05-17 03:04 AM
Sure, I can post some code that will give you a basic idea without divulging anything that I shouldn't. Also, the basic methodology I use here is from an app note I found somewhere on either this forum or another ST site. Finally, there will be no mocking my hideously inefficient assembly code. I'm normally a C-only guy.
MOV DPTR, VMREG MOV A, (VM_REG_RD_MAIN_FLASH OR VM_REG_PSEN_MAIN_FLASH OR VM_REG_PSEN_BOOT_FLASH) MOVX @DPTR, A CHECKPAGE: MOV DPTR, pageval MOVX A, @DPTR JNZ RUNAPP ;If pageval doesn't point to bootloader, check and run app MOV DPTR, PAGEREG MOV A, BOOTLOADER_PAGE MOVX @DPTR, A ;If we're here, the pageval appears to point to the bootloader. We check the checkcode ;in RAM against the key value to make sure that it's not just a random occurrence on ;startup. If they match, we run the bootloader. CHECKRAM: MOV R0, KEY_LENGTH - 1 ;R0 = Loop index CHECKLOOP: MOV DPTR, key MOV A, R0 MOVC A, @A+DPTR MOV R1, A ;Store next byte from key in R1 MOV A, LOW(checkcode) ;Add R0 to location of checkcode and load ADD A, R0 ;into DPTR MOV DPL, A MOV A, HIGH(checkcode) ADDC A, 00H MOV DPH, A MOVX A, @DPTR ;Fetch next byte of check code MOV R2, A MOV A, 'x' MOVX @DPTR, A ;Wipe checkcode as we process it so we can get back to app MOV A, R2 XRL A, R1 ;XOR with key byte in R1 JNZ RUNAPP ;If bytes don't match, check and run application DJNZ R0, CHECKLOOP ;Otherwise, decrement loopcounter and jump JMP RUNBOOT ;pageval =0 and key sequence good, so run bootloader RUNAPP: MOV DPTR, (08000H + APPBITS) MOVX A, @DPTR CJNE A, 0FEH, RUNBOOT ;Make sure we don't run an invalid application MOV DPTR, VMREG MOV A, (VM_REG_PSEN_MAIN_FLASH OR VM_REG_PSEN_BOOT_FLASH) MOVX @DPTR, A MOV DPTR, PAGEREG MOV A, APPLICATION_PAGE MOVX @DPTR, A MOV DPTR, VMREG MOV A, VM_REG_PSEN_MAIN_FLASH MOVX @DPTR, A JMP DONE RUNBOOT: MOV DPTR, VMREG MOV A, (VM_REG_PSEN_BOOT_FLASH OR VM_REG_PSEN_MAIN_FLASH) MOVX @DPTR, A MOV DPTR, PAGEREG MOV A, BOOTLOADER_PAGE MOVX @DPTR, A MOV DPTR, VMREG MOV A, (VM_REG_PSEN_BOOT_FLASH OR VM_REG_RD_MAIN_FLASH) MOVX @DPTR, A DONE: Hope some of that helps... let me know if anything's unclear, but I think it's lack of efficiency makes it pretty easy to understand.2011-05-17 03:04 AM
Thank you. I am also primarily a C-guy, so please don't appologize for knowing more Assembly than me. ;)
I've got a meeting w/ GE this morning so I won't be able to perform any tests until afternoon'ish. But I'm sure your example code will answer many of my questions. Thanks again!2011-05-17 03:04 AM
Your example startup.a51 has helped tremendously. I have some questions though that I was hoping that you could answer before I get myself into trouble.
----------------------------------------------- 1:How do I locate the main app's statusbytes (0xFFFF) once defined? Do I simply open the .hex file in a hex viewer and look for it's location? ----------------------------------------------- Previously, you had written: Modify the STARTUP.A51 file for BOTH projects to be IDENTICAL. 2:Can you explain your reasoning behind using identical startup.a51's for both programs. ----------------------------------------------- Previously, you had written: The way the code runs the application is by changing the VM register to let it fetch code from EITHER main or secondary flash, THEN swapping to a page which places main flash in the space previously held by secondary flash. 3.I can see this in your startup.a51 example. There is a VM change,Page change,and then VM change again. Could you explain each change in a bit more detail? 4.What pages are you using for #APPLICATION_PAGE & #BOOTLOADER_PAGE ? ----------------------------------------------- Previously, you had written: A final note is that you have to tell the linker to place this startup code (in Keil, the routine is C_C51STARTUP) at the EXACT same memory address. Just look at the memory map and pick someplace that looks convenient. 5.Is this why the same startup.a51 is used for both app's?; So that address of C_C51STARTUP is the same in both pages? 6.How exaclty do I 'tell' the linker to place startup code at a specific mem address? ----------------------------------------------- 7.My main application will take up more than 32k code space. I am familiar with banking as I have successfully created a bank-switching app which calls routines in all 8 banks. What concerns and/or modifications should I make to allow this multi-page mapping to my main application, without disrupting the IAP architecture? ----------------------------------------------- 8.Could you provide a sample key sequence used to switch to IAP mode from main app? Im not sure that I understand your CHECKLOOP. ----------------------------------------------- FYI: I too am using Keil. Wow, thats alot of Q's. I have been reading up on the uPSD for well over 2 weeks now. It really helps having someone with experience who can fill in the blanks for me. Especially with IAP development which has been the hardest to find help on. Thanks for all of your help