2012-08-30 11:31 AM
ST's AN2557 app note explains In-Application Programming using a USART. Unfortunately, the example software that comes with the app note does not include a Crossworks implementation. Many good lessons have been learned in creating this one, with much help from Michael Johnson of Rowley Associates. I hope you can benefit from it.
Pertinent Items:
Properties - To set a property, right-click on the Project name (not Solution) and select Properties.
Load Offset - under Debugger
Load Offset Symbol Limit - under Debugger
Emit Relocations - under Linker
Additional Output Format - under Linker
Memory Map File - under Build
Section Placement File - under Build
Memory-Map file
This defines the SRAM and Flash segment addresses.
Default location is ''C:\Users\Albert\AppData\Local\Rowley Associates Limited\CrossWorks for ARM\packages\targets\ST_STM32F10x\ST_STM32F103VE_MemoryMap.xml''
You can make a copy of the default file in your project directory, edit it, and point to it with the Memory Map File property.
Section-Placement file
This defines what program sections (.text, .data, etc.) get put in what segments defined in the Memory-Map file.
Default location is ''C:\Program Files (x86)\Rowley Associates Limited\CrossWorks for ARM 2.1\targets\flash_placement.xml''
You should not need to edit this file but if you do, make a copy in your project folder and point to it with the Section Placement property.
Relocation. In order to implement a bootloader you will have to place the bootloader at a different memory location than the target app (that which the bootloader will load).
It's arbitrary weather the bootloader is below or above the target app in memory. But above seems better to me because then an existing app can be downloaded as is with the bootloader. Also, on power-up or reset you would usually want your target app to run. By default code location begins at 0x08000000, the bottom of flash, so a power-on or reset will go there and execute your target app instead of your bootloader.
To relocate code you have two options:
Option 1 (Preferred) - Edit the Memory-Map file, err... a copy of it. Use NotePad++ or similar to edit.
At the bottom of the file you will see: <MemorySegment size=''0x80000'' access=''ReadOnly'' name=''FLASH'' start=''0x08000000''/>
Change to: <MemorySegment size=''0x70000'' access=''ReadOnly'' name=''FLASH'' start=''0x08010000''/> if you want to relocate at 0x08010000. Note that ''start'' must be a multiple of 0x800 because that's the flash page size.
Note, you must reduce ''size'' by whatever you have added to ''start''.
This is the preferred method because it also puts the relocation info in the .bin output file which is the file that will get downloaded with the bootloader.
Option 2 - Set the Load Offset related properties
Set the Load Offset property to the desired load address offset, so if you want to load 0x10000 above beginning of flash, set it to 0x10000. Note that Load Offset must be a multiple of 0x800 because that's the flash page size.
Set the Load Offset Symbol Limit to 0x08080000, i.e., top of flash. This limits the offsetting to within flash. If you don't set this, the offsetting will also be applied to SRAM addresses which start at 0x20000000. With only 64K of SRAM an offset approaching 0x10000 will relocate SRAM accesses outside the 64K limit and a bus-fault / hard-fault will be generated.
Set Emit Relocations property to Yes. This tells the linker to pay attention to the Load Offset properties.
This is not the preferred method because the .bin file will not contain the relocation info. You can capture a .bin with the relocation info by loading the program area into a Memory window in Crossworks, the right-click Save to Binary. The size can be determined from the generated .bin file with HexEdit or similar.
Generating the target app.
Assuming your target app will be loaded into the bottom of flash, no project changes are needed other than to set the Additional Output Format property to bin.
If your target app will go into higher memory then certain things must be done:
Relocation of target app by one of the above methods.
ApplicationAddress in bootloader common.h will have to be changed from 0x08000000 to the higher place you want the target app loaded to.
ST's application note AN2557 also says you should relocate the vector table at the target app load address using the ''NVIC_SetVectorTable''function or the VECT_TAB_OFFSET definition inside the ''system_stm32f10x.c''. I have not found this to be necessary and don't understand enough to know why.
Examples
ETM IAP is the example bootloader.
ETM Base is the example target app. This target app jumps back to the bootloader after a few seconds so you can play around without continually resetting.
Notes
When the IAP code wants to jump to the downloaded target code, it must add 0x235 to the target's load address. The entry point is actually 0x234 from the beginning but only odd jump addresses are allowed in ARM so you must add one. It will resolve to 0x234 and jump correctly.
The simplest way is to allow your target app to load at the default zero offset (0x08000000), then you don't need to worry about relocating it. Now for the IAP bootloader, relocate it someplace well above the end of your target app (look at target app.bin to see how far it goes in flash).
If you load only the example IAP bootloader, then power-cycle or reset with no code down at 0x08000000 then nothing will happen. The bootloader will not run because the power-on/reset vector defaults to the bottom of flash. You must load some code at the bottom that will jump to the bootloader. Normally the target app would have some sort of Hyperterminal user interface that would allow the user to select Re-Flash, then the target would jump to the bootloader. Alternatively, you could use the state of a GPIO connected to a (pushbutton or jumper) in your target app to control whether it runs or jumps to bootloader on startup.
2012-08-30 12:27 PM
''It's arbitrary weather the bootloader is below or above the target app in memory. But above seems better to me because then an existing app can be downloaded as is with the bootloader. Also, on power-up or reset you would usually want your target app to run. By default code location begins at 0x08000000, the bottom of flash, so a power-on or reset will go there and execute your target app instead of your bootloader.''
Putting the boot loader on top increases the chances you'll brick your product. The front sectors are also smaller in the F2 and F4 designs, and lockable. It also allows the boot loader to validate the user application before blindly jumping into it. So I'm not convinced whether the choice is arbitrary.
2012-08-30 01:55 PM
I guess it depends on what your trying to do. I was trying to minimize changes to a target app that is mature, large, and complex. I don't want to move that pig. Plus I put the bootloader very high so I'm not worried about bricking the target app in. But I agree, a general-purpose bootloader might be better down low, just depends on your situation.
Long live the clive!2012-08-30 02:21 PM
Things must be simpler in Keil, you'd pretty much click a dialog and define the application region in ROM/RAM. I've been using the linker to handle the vector table symbol, and program the NVIC explicitly with that value. At that point it's agnostic to location, and RAM vs FLASH, provided you keep a 512 byte alignment.
There is the scatter file method too, or the linker script in GNU/GCC. The linker should resolved everything, if it doesn't you've got bigger problems to worry about. A power or process fail during the erase/flash phase of a front loaded application just scares me a lot. System_Init() extern void * __Vectors; NVIC_SetVectorTable((u32)(&__Vectors), 0x0); // Smart Base Location STARTUP.S ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY EXPORT __Vectors EXPORT __Vectors_End EXPORT __Vectors_Size __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler ...2012-08-30 04:02 PM
Fantastic summary by the way, I'd +1 the parent but the forum software assumes everything is a question, amongst it's other failures.
2012-09-17 08:47 AM
2012-09-17 09:25 AM
Wish I could edit my posts...
Turns out TIM4 ISR causes a problem too. So final solution was to __disable_irq(); //disables interrupts in target app just before jumping to IAP bootloater. Then, in IAP: NVIC_SystemReset(void); //force a reset, will execute target app loaded at 0x08000000