How to make MQX and MQX application position independent? so we can run the project from any address.
People have asked if it is possible to have the RTOS located in one area of memory and the application in another so that an application can be updated without the RTOS being updated. It probably is possible but impractical as with the current method the application is compiled and linked with the RTOS to form one binary. If an application were developed that wanted to use a resource that wasn't part of the RTOS ...well you can guess it wouldn't work.
With that said you can configure the code to be compiled with PIC/PID.
Example using ColdFire processor with CW10.1
Open the CW10.1 properties for the project, open the C/C++ Build, select Settings, then open the ColdFire Compiler, then click on Processor. Use the check box to enable and play with PIC/PIC settings.
Can you share what you are trying to do?
we want to have a bootloader in the default location zero, so each time the MK60 boot up, it will get in to the bootloader. and then the bootloader will load our application from Flash or run application from Flash.
We have 1 partition ( Not DOS FAT partition) it is our predefined partion which include enough information to decide to boot from one of the other two partition. So we have three partition: P1: information for P2 and P3, P2: our program, P3 : another version of the program. In this configration, we will alway have one partition (P2 or P3) is good program to run. When update come in action, the running program will write to another partition, and if upgrade succeeded, the program will jump to the new updated program.
By doing this, we are sure our MK60 will not blocked when upgrade failed. Although MK60 has the ability ( maybe all freescale devicd has the ability) to swap the two Flash partition, but we are not sure what will happen when system is powered off and on again, we don't know which partition will get run the program.
Base on this idea, we want to P2and P3 program be linked with identical linker script. If not, it will introduce confuse to manage the two programs.
So, if we want to run the program from Flash (not copied to RAM), we need to relocated the interrupt vector to RAM because the MK60 needs the IRQ vector predefined in Flash, and we write our program to a pre-known address, the reset vector is the base address for the program, so we can add this base address to interrupt vector while relocated the vectors. If all other portion of the program is referenced to this base address, then the program will run correctly.
I already tried to adjust the IRQ vector, and can jump to the correct location, but MQX use so many constant and function pointers that all referenced to location ROM_start, so we couldn't get the MQX run. All of these function pointers and constant addresses will need to add the base address. But this is a huge job, I couldn't patch it in a short time, so I quit.
To save MQX in a fixed location and all program linked to this position is not practicable. The system will get blocked if the OS changed.
By implement our idea, the Fresscale swap two partition is useless for us.
Thanks for the information.
I've worked with several bootloaders and generically the bootloader owns the vector table in flash. The bootlader will be what boots up and then makes determination to remain in bootloader mode or jump to an application. The application has its vector table in RAM and the code runs from flash (some address above where the bootloader sits).
If the application is going to be updated, then the application will re-enter the bootloader and let the bootloader download, erase and program the new application to flash. Since the bootloader is in flash, if the update process fails (say a brownout) the bootloader will just start up again and start the update process again. Once the bootloader validates the update it can jump to that new application.
So it wouldn't be too hard to also have the bootloader have more than one partitian.
I've had bootloader loading a MQX application without too much trouble.
MQX needs to be configured to have the vector table in RAM (place #define MQX_ROM_VECTORS 0 in the user_config.h). So during MQX boot up it loads vector table from flash space to RAM.
Hope this helps.
Your approach of down to bootloader when upgrade come in is not acceptable for us. because it needs human interaction, for example to push a button to get into bootloader mode.
Our application have the ability to do upgrade also.
I have tried to use RAM vector in the application and let the app run in Flash, but if I write the same application binary to different FlashX address, and they won't work.
For example : if the app is linked to ROM_START_ADDRESS of 0x20000, and I write one copy of the app to address 0x20000 and the other copy to 0x40000. The app in 0x20000 will run correctly, but the other one seems to run, but it calls a lot of funcitons and used a lot of variables in app of 0x20000. If I erase the app of 0x20000 in my 0x40000 application, then the 0x40000 app won't run.
The one thing about bootloaders that is interesting is not two bootloaders are designed the same way.
There are ways to get in and out of bootloader without users pushing button (i.e. from the application itself but must be careful to turn off resources app was using that might cause bootloader to crash) but your method of implementation is just fine too.
Can you send your project?
I have one bootloader ( actually it should be called golden app ), to load one of the two app to run in ram. My bootloader runs in Flash.
I patched MQX a little bit to get my project working.
I am not sure if our company allow me to public my project or not.
I played around with CW10.1, Tower K60, MQX3.7, and the mqx/examples/event project.
I used the Int Flash Debug target as starting point. So its partition is 0x00000-0x20000.
I then created a Int Flash 0x20000 target and its partition is 0x20000-40000. I updated the linker for this target to be intflash_0x20000.lcf.
I then created a Int Flash 0x40000 target and its partition is 0x40000-0x60000. I updated the linker for this target to be intflash_0x40000.lcf.
I first loaded and ran at 0x00000 and see it operate correctly.
I then loaded 0x40000 and it ran correctly (note still had image at 0x00000 in flash).
I then loaded the 0x60000 and it ran correctly (note still had images at 0x00000 and 0x20000 in flash).
I then erased all flash and tried to run from 0x40000. It craps out but I think that is because the 0x0 address space is blank.
I then loaded the vector table of 0x0 but not the rest of the application and the 0x40000 ran correctly. So I think the crapping out previsouly is more of a debugger issue than the vector table at 0 being used by the 0x40000 application. This also was the case for running the 0x20000 target.
In summary as long as I have the sector 0 configured correctly (by using vector table and flash configuration settings from a valid project) I was able to run the project at 0x0 or 0x20000 or 0x40000. Hopefully the example attached helps.
If your application uses interrupts, you need a boot software which has the interrupt vectors and jump-code for each interrupt.
Basic idea: When an interrupt occurs the bootloader reads the interrupt vector from the active application (0x20000, 0x40000, 0x6000, ...), adds the application base address and jumps to that address.
A bootloader running out of partition 0 (0x0000=0x20000 in the example) owns the vector table in flash. The bootloader may or may not actually use interrupt (i.e. many simple bootloaders operate in a polling mode only). Each application is indepenent of the other so they do not know anything about one another.
The applications I created to run out of partition 1 & 2 (0x20000-0x40000, 0x40000-0x60000 respectively) place their vector table in RAM after copying their table from flash. That's the secret sauce for these and other MCUs of having the ability to have the vector table in flash or SRAM.
Lastly is a bootloader using interrupts should disable all the resources it had configured prior to jumping to an application. I've been burned before that a bootloader interrupt is still active when an application boots up and crashes the system.
I took a look at your sample, the only difference is you add the constant 0x20000 or 0x40000 to the Memory::*rom portion.
I couldn't believe that : you erase the whole chip and programmed vector table from the 0x00000 application and program the 0x20000 or the 0x40000 application, the application could run.
The flash address 0x0 is contains the MSP and the __boot entrance address, for the 0x00000 application , it should points to address 0x410, for example. and the 0x20000 application table points to 0x20410, for the 0x40000 application, it points to 0x40410. This is why Mark said we need to add the constant 0x20000 or 0x40000 to the table. I think I also mentioned in my previous post.
Before today, I was using IAR6.10 to do the developemnt, and if I try to compile the MQX as position independent, it gave me lots of errors, so I had to patch the MQX, and finally I gave up.
By looking at your example, I am trying the CW10. Suprisingly, I get no error to compile MQX to be position independent. and Finally I got Virtual-Com application linked. But when I try to run it, it keeps reset. I debugged it, and find out the
kernel_data is located to 0x400210. There is no memory at this address. How do you solve this issue?
BTW, I set Position-Independent Code, Position-Independent Data and Place Read-Only Strings in .rodata Section in all the MQX projects and the Virtual Com project. The linker script is the default IntFlash.lcf
Let me clarify. When I have a vector table at 0x0 it is there only to let the debugger operate correctly and there is no application code associated with it. That way if my application code at 0x20000 or 0x40000 tries to access that vector table at 0x0 it would crash. I am not using the SP and PC to allow the system to boot and run. I'm using the debugger to get my 0x20000 or 0x40000 application to run. Note that for the application code at 0x20000 or 0x40000 the MQX was setup to use a RAM vector table. So when either of those applications starts to boot (via the debugger and not reset), it copies its vector table from Flash into RAM, and then starts to execute.
Hope this helps. If not ask more questions please.
Will your 0x20000 app run at 0x40000?
Yes the app will run at 0x40000.
In summary the one app can be configured to run at 0x or 0x20000 or 0x40000.
Have you compiled it as PIC/PID? I tried to compile virtual-com exmaple for twrK60, (both MQX libraries and the example code), but the mqx_init structure is aligned to 0x2, and kernel_data is located at 0x400210 (not 0x40210). so the program could never run.
Would you please share how you did it?
No I have not tried implementing PIC/PID.
Each application has its own linker file (all included in the project I posted) and therefore gets compiled to the desired run address of 0x0, or 0x20000, or 0x40000. I'm not using one binary to run at those address. I have three binaries.
Then, My boot loader implementation for is the only working solution for booting one of the two images.
Retrieving data ...