This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
On my MSP430F5310, I have implemented an application which is based on a (also self-implemented) communication library, which handles the bus connection.
I would like to be able to reprogram the application part via the bus. Implementing a bootloader which also relies in the communication library is not a big thing, but currently, the linker happily mixes the objects from both library and application.This makes it impossible to replace only the application without touching the library.
It would be helpful to have each of them in separate flash segments. Is there a way to tell the linker to do this? I know how to do it for single objects, but I am not exactly eager to put a segment directive before each and every function and variable.
Any ideas?
Max
EDIT: I am using CCS5.
Leo,
thank you for anwering. I know about the approach (and have already implemented the ideas), but I do not yet see how I can separate my code the way I want to have it.
The BSL does not help me as the data transmission path is fixed. The main memory bootloader looks more promising, but I did not find an answer to my question there. Maybe I have overlooked it?
Max
Max,
i am not really sure where the problem is. If you want to have two separate flash areas for library and application, you need to create two projects with two different linker command files.
I would strongly suggest, that the bootloader+comm library reside in the memory area adjacent to the interrupt vector table since it is a "fixed" part. The application the resides in the lower part of the main flash memory and it shall be update-able. In order to enable application using the hardware interrupt, you need to create an intermediate table between the hardware interrupt vector and the real ISR function pointer in the application.
Leo,
I might have been unclear in the description of the problem, sorry about that. The files are in separate projects alright.
After some more looking around, I came across this (last post):
http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/42302.aspx
This is exactly what I had been looking for. Now the library code resides at the end of the flash, and the application at the beginning (as you had suggested).
Max
Maximilian Gauger said:Now the library code resides at the end of the flash, and the application at the beginning (as you had suggested).
How are you handling the the application calling the functions in the library (i.e. symbol mapping to entry addresses?)
The normal way MSP projects are done is by using static linking. This means, the library code is handled (almost) like all other project code. The result is a monolithic binary file that contains all together.
This is the way that gives most compact code, most efficient usage of flash and ram, and as well as causes least trouble.
What you want to do is more like dynamic linking. That means the application knows of the existence of the library and which functions it provides but the library code is completely outside the application.
With an OS that provides memory management and can assign separate address ranges for both, this is quite easy. On an MSP this is rather difficult.
For the code, the best is to have the library have a jumptable to all its functions. The table is located at a fixed memory location. The application then uses a header file that defines function pointers. This adds the overhead of a jump to each library call, but allows application and library to be completely independent except for the jumptable.
More difficult is the handling of the ram space. If the library requires static or global variables, the space required for them needs to be excluded from the application ram space.
Next step is the boot code. Of course the library (if written in C) needs some boot code for initializing the globals. Yet it has no main(). You need your own init code.
Best would be to make all globals uninitialized and write a lib_init function that has to be called by the application and which does the required init of the global vars. Makes the source code a bit less readable, but shouldn’t be a big problem. You can’t initialize local static vars this way, though.
The biggest chunk is if the library required interrupts and has ISRs. In this case, you’ll need to use some double-jump buffering, so all interrupt vectors point to the library area, and those which aren’t required by the library itself are routed to the application. This can be done by moving the app vector table to a different location, and then doing indirect jumps on this table when an interrupt is called. This increases interrupt latency by some clock cycles.
This way, the reset vector can point to the library init function, which at its end calls the application reset vector.
Well, it isn’t easy, but doable.
Jens-Michael,
thank you for pointing out the details of what else needs to be done. I was aware that calls from the library to the application are a problem to be solved, but I had not considered the other points you mentioned.
The library calls only a limited number of functions in the application directly, most is already being done with function pointers. I will need to come up with a solution that shifts the remaining calls to function pointers.
Most of the variable initialization is already being done in init functions, removing the remaining ones with runtime initialization should not be a big deal.
For the RAM assignment, it seems most reasonable to me to define a fixed split of the RAM between the library and the application. This means introducing a second .data section in the linker command file and assigning a fixed address range to it.
The library is meant to be platform-independent, so it does not directly handle interrupts. However, library code is called from interrupts, but this should not be a problem. All ISRs are defined in the application.
The idea to have the reset vector point first to library initialization, then back to application reset, sounds good. Thank you for the input.
Max
Jens-Michael did an excellent job of elaborating the steps to be done, which my question was trying to elicit if you understood how to do it.
Maximilian Gauger said:The idea to have the reset vector point first to library initialization, then back to application reset, sounds good.
That sounds like a reasonable plan.
Maximilian Gauger said:The library calls only a limited number of functions in the application directly, most is already being done with function pointers. I will need to come up with a solution that shifts the remaining calls to function pointers.
I think you need a (set of) library initialization routine(s) that your application calls before it starts actively using the library, whereby you pass the library any needed "callback" function pointers to your application code.
**Attention** This is a public forum