Application and Firmware Separation in Cortex M4 - c

I'm busy with a massive project where I need write software for a control system for an automotive vehicle. Here's what I am using:
I'm using an STM32F4 for the micro
I am writing the Application (Control app) in Matlab Simulink. I then generate Cortex M4 optimised code from Matlab which I simply Include in my Keil uVision Project. (Works like a charm)
I manually write software for the driver layer and to interface to the Hardware abstraction Layer.
I would like to maintain separation between my Simulink Generated Code and my 'firmware' hand written code. Essentially, I want to be able to change the firmware without affecting my control application.
I would like to use a configuration file to map the variables that Matlab Simulink generates with my Hardware Registers (for GPIO, for instance). I would like to do this via a configuration file (e.g. via an xml file).
Has anyone ever done something like this and is it even possible. I'm looking for an elegant solution that does not consume a lot of RAM.
Thanks so much!
PS: Is it possible to declare variables in your code based on variables names that are stored in say an .xml or .txt file.
So if in the .txt file I have "Pressure_Sensor = 0", is it possible, perhaps using a Macro Definition, to declare a variable in the code: Pressure_Sensor = 0;

If you want to include variables into your c project build from syntax in another type of file whether it be .xml or .txt files there's a couple ways to do it. If you are going to be keeping variables in c compatible declaration style like:
int Pressure_Sensor = 0;
and no other invalid semantics will be in that file you can always just include that file into one of your compilation units. The extensions of the file do not matter. The #include directive literally just inserts that file into place.
If you are going to be doing something along the lines of a non c compatible language such as XML, a standard way to generate and include those variables into your build is to have a script that runs are a pre-build action that parses that .xml file and then generates a c compatible include file that you include into one of your compilation units. One of the most common things to use this for that you could find many examples of is for generating version/build info into the build.

You can do this:
Simplified Problem Statement is:
You want to modify a CPU port register through your code, but you don't know the address of that port register(Port address may change externally).
Solution is:
I)In your code:
Let your program assume that the address of the port register is at at fix location say 0x1000.
Someone/something will letter put address of port register at 0x1000(Your program don't care how)
So to change pin K1 you have to change value of address present at 0x1000.
But Wait ,
You want to only change a single port pin and you don't know which so,
Assume pin bit pattern is at 0x1004
To make pin ON write:
Value of the address present at 0x1000 |= Value at 0x1002
To make pin OFF write:
Value of the address present at 0x1000 &= ~Value at 0x1002
Most Imp:
Reserve these locations in your program somehow so that compiler dont write code there.
II)Outside the code:
Assumptions for explanation: Port1 address : 0xF000
Port2 address : 0xF001
Now have a Excel macro or something to do following:
Suppose you wants port2's 8th pin for contactor K1 then that macro should generate a simple text file as: "F00180".
Now use bin2hex or bin2mot (based) on your compilers output format and convert this notepad file into .hex or .mot(S-record) format.
You have to specify address location as 0x1000 as one of the input to these utilities.
Now remove header ,footer lines from generated .hex file and merge remaining data to your program.hex file.
You are done here,burn the .hex file into target by suitable flash programmer.

Related

Using pointer functions - 2 separate applications on 1 device

I asked some time ago this question How can I use one function from main application and bootloader? (embedded) and started to implement proposed solution but ran into a few problems.
On my cortex M4 I, have 2 separate applications - bootloader and user application. Now I had some (many) functions which were the same for both apps. So I compiled them only for bootloader, then created an array of function pointers at specified address, which is known for user application. So in application, I didn't compile the files with those functions again, but I use those pointers whenever needed.
This is example of code I tried to make common for both applications:
static uint8_t m_var_1;
// Sends events to the application.
static void send_event(fs_op_t const * const p_op, fs_ret_t result)
{
uint8_t var_2;
[...]
}
My application ends in Hardfault, which happens e.g. when dividing by zero or using pointer to function with NULL value. I am not sure why yet, but I started wondering what happens with those variables. var_2 will most surely be located on stack so this is no problem. But what about m_var_1? In the map file, it has a specified place in RAM. But I don't have seperate RAM sections for app and bootloader. I am not sure, but I have a feeling that this variable may use the same RAM location as when created for bootloader. Is this possible? Maybe some other issues?
Yes you are right, the code will attempt to access the global variable at the same location as it is linked for loader. This is because linking involves replacing all occurrences of identifiers (including function names and variable names) by the addresses determined after compiling.
In your application, the variable, even if it does exist there too, is likely to be at a different address.
The calling of the functions happens to work, because they are located in ROM and cannot be different for application and loader. Calling them via const pointers, which are also stored in ROM, bypasses the problem.
The solution is using a file system simulator, if you can find one for your hardware.
Otherwise you will hate having to do the following.
Part 1, setup:
introduce a special linker section with all the variables accessed by both system paprts (application and loader)
let one linker fill it
set it up for the other linker as don't-tocuh
be careful with the initialisation
preferrably do not assume any intialisation value
if you need initialisation, e.g. "bss" (init to 0) or "data" (init to specified value),
do so explicitly at the start of the system part which is not associated to the linker you let setup the variables
for safety, it is recommended to do the init the same way in both system parts
"data" init uses a special non-volatile linker section with a copy of the to-be-initialised variables, accessing that is possible
Part 2, access:
option 1)
store const pointers to those variables, like you did for the functions
option 2)
get the second linker (the other one, which did not do the actual setup of the common variable section) to create an identically structured and identically located section as the one from first linker; more studying of your linker needed here
Part 3, resuing values stored by other system part
(e.g. you want to leave some kind of message from loader, to be read my application)
design which system part initisalises which variable, the other one only reads them
separate the common variables in four sections,
written and read by both system parts, initialised by both
written and read by x, only read by y, initialised by x
written and read by y, only read by x, initialised by y
written by both system parts, not initialised, uses checksums and plausibility cehcks,
if a variable has not been initialised, init to default
init each section only in the corresponding writer system part
setup as "no init" in the other linker
setup as "no init" in both linkers for the fourth case
use getters and setters with checksum update and plausibility for the fourth case
To do all that, intense study of your linker features and syntax is needed.
So I recommend not to try, if you can get around it. Consider using an existing file system simulator; because that is basically what above means.

Having .c source file storing .txt information at compile-time

I'm using C to make some RTEMS application for a given target (a LEON processor more specifically).
When doing the various tutorials I noticed that since it isn't possible to load the simulation .txt files, the solution is to have .c source files (let's call them inputs.c) keeping the various 512x512 global input matrices and have them referenced as extern within the main file.
I'm trying to find information about this procedure but I haven't found it.
My question: In the documentation of the example they state that at some point they are going to transfer the global matrices in the inputs.c from the PC to the target via UART. Isn't the inputs.c file loaded into the LEON processor as well as all the other .c files?
I think there is some information missing to completely understand which is your environment ...
But it could be that the data into the input.c is linked into a separated section (you should check the RTEMS linker file cmdlnk).
This way it won't be loaded by grmon but it will be loaded on specific command.
Or probably you do actually upload the data exactly at the same time of the executable code by doing the "load" in grmon.

MpLab, ASM, C, Building To accommodate both

I have a large and substantial ASM project for a PIC24 chip. (The specific chip is the PIC24FJ256GB210)
I now have some other routines in C.
I want to incorporate these into my project.
The C routines are in a project of 5 or so files, one of which contains the int main(void) statement as the starting point. This was for the purpose of testing them and giving us the confidence that they work. We are now ready to move that code and incorporate it into the larger existing system.
The assembly language stuff starts with the __reset: instruction.
How do I arrange the project and build options so that I can do these next three things ?
Keep starting with my __reset instruction
(Or at least make sure that my existing __reset and the int main(void) at least cooperate with each other)
Call his routines from the ASM code
Use the same data buffers that the C code sets up
Interestingly enough, Microchip's User forums and sample code sections seem to miss this idea (or, more likely, I haven't figured out how to find them).
I would think this question has been asked a lot, and I hope I'm not duplicating a previous question, but I don't see it here nor on MicroChip's site. Links to helpful websites on this topic are welcome.
If I just need to learn how to search this and other sites better, that will be a useful and workable answer in and of itself. Again, hope I'm not asking a duplicate question.
I recommend you to read DS51284H ("MPLAB® C COMPILER FOR PIC24 MCUs AND dsPIC® DSCs USER’S GUIDE") (PDF).
In particular see section 4.4 STARTUP AND INITIALIZATION
"Two C run-time startup modules are included in the libpic30.a archive/library. The
entry point for both startup modules is __reset. The linker scripts construct a GOTO
__reset instruction at location 0 in program memory, which transfers control upon
device reset.
....
5. The function main is called with no parameters."
Your __reset label and the one in the CRT (C run-time) would appear to conflict. If you have the source for the CRT you could change that by renaming the __reset label in the CRT to something else so that your own __reset always is called first.
Another point is that it sounds like you want to take a stand-alone program and use it as a library from within your own program. Since stand-alone programs often are designed to perform one or more specific tasks and exit once that task is finished you might want to refactor your C code a bit to make it more library-ish (like getting rid of the main() function and perhaps replace it with some sort of init() function).
And section 4.11 FUNCTION CALL CONVENTIONS.
"The first eight working registers (W0-W7) are used for function parameters. Parameters
are allocated to registers in left-to-right order, and a parameter is assigned to the first
available register that is suitably aligned.
....
Function return values are returned in W0 for 8- or 16-bit scalars, W1:W0 for 32-bit
scalars, and W3:W2:W1:W0 for 64-bit scalars."
Michael gave you a good answer. The only thing I would like to add is that you should make the project in C and cut the assembly functions within it.
This way you keep the speedy and functional asm code and can mantain the project in C, which is much easier.
It is not in your interest to convert the C code into assembly and have a large assembly code to mantain, its the other way around.
Once you read the docs you will see it is not so hard to use an assembly function in C, but to get you started, you can take a look at this:
C:\ ...bla bla... \Microchip\MPLAB C30\src\dsp\include\dsp.h
contains function declaration in C for the actual assembly functions located in this folder:
C:\ ...bla bla... \Microchip\MPLAB C30\src\dsp\asm
You can begin with the function _VectorAdd: Vector Addition, file "vadd.s"
Note that the assembly function _VectorAdd is defined as VectorAdd in the header file.
This example files are for the dsp engine in the DSPIC, something the PIC24 does not feature. But it is still ilustrative enough to extract the principle.

Arm Rom.ld ,Ram.ld ,scatterfile ,startup.s ,what all these files do?

I have programmed avr microcontroller , but new to arm.I just looked a sample code for sam7s64 that comes with winarm.I am confused about these files rom.ld , ram.ld , scatter file , cstartup.s file. I never saw these kind of files when i programmed avr .Please clarify my doubts what each of them file do.
I have even more samples for you to ponder over http://github.com/dwelch67
Assume you have a toolchain that supports a specific instruction set. Tools often try to support different implementations. You might have a microcontroller with X amount of flash and Y amount of ram. One chip might have the ram at a different place than another, etc. The instruction set may be the same (or itself may have subtle changes) in order for the toolchain to encode some of the instructions it eventually wants to know what your memory layout is. It is possible to write code for some processors that is purely position independent, in general though that is not necessarily a goal as it has a cost. tools also tend to have a unix approach to things. From source language to object file, which doesnt know the memory layout yet, it leaves some holes to be filled in later. You can get from different languages depending on the toolchain and instruction set, maybe mixing ada and C and other languages that compile to object. Then the linker needs to combine all of those things. You as the programmer can and sometimes have to control what goes where. You want the vector table to be at the right place, you want your entry code perhaps to be at a certain place, you definitely want .data in ram ultimately and .text in flash.
For the gnu tools you tell the linker where things go using a linker script, other toolchains may have other methods. With gnu ld you can also use the ld command line...the .ld files you are seeing are there to control this. Now sometimes this is buried in the bowels of the toolchain install, there is a default place where the default linker script will be found, if that is fine then you dont need to craft a linker script and carry it around with the project. Depending on the tools you were using on the avr, you either didnt need to mess with it (were using assembly, avra or something where you control this with .org or other similar statements) or the toolchain/sandbox took care of it for you, it was buried (for example with the arduino sandbox). For example if you write a hello world program
#include <stdio.h>
int main ( void )
{
printf("Hello World!\n");
return(0);
}
and compile that on your desktop/laptop
gcc hello.c -o hello
there was a linker script involved, likely a nasty, scary, ugly one. But since you are content with the default linker script and layout for your operating system, you dont need to mess with it it just works. For these microcontrollers where one toolchain can support a vast array of chips and vendors, you start to have to deal with this. It is a good idea to keep the linker script with the project as you dont know from one machine or person to the next what exact gnu cross compiler they have, it is not difficult to create projects that work on many gnu cross compiler installs if you keep a few things with the project rather than force them into the toolchain.
The other half of this, in particular with the gnu tools an intimate relationship with the linker script is the startup code. Before your C program is called there are some expectations. for example the .data is in place and .bss has been zeroed. For a microcontroller you want .data saved in non volatile memory so it is there when you start your C program, so it needs to be in flash, but it cant run from there as .data is read/write, so before the entry point of the C code is called you need to copy .data from flash to the proper place in ram. The linker script describes both where in flash to keep .data and where in ram to copy it. The startup code, which you can name whatever you want startup.s, start.s, crt0.s, etc, gets variables filled in during the link stage so that code can copy .data to ram, can zero out .bss, can set the stack pointer so you have a stack (another item you need for C to work), then that code calls the C entry point. This is true for any other high level language as well, if nothing else everyone needs a stack pointer so you need some startup code.
If you look at some of my examples you will see me doing linker scripts and startup code for avr processors as well.
It's hard to know exactly what the content of each of the files (rom.ld , ram.ld , scatter file , cstartup.s) are in your specific case. However assuming their names are descriptive enough I will give you an idea of what they are intended to do:
1- rom.ld/ram.ld: by the files extensions these are "linker scripts". These files tell the linker how where to put each of the memory sections of the object files (see GNU LD to learn all about linker scripts and their syntax)
2- cstartup.s: Again, from the extension of this file. It appears to be code written in assembly. Generally in this file the software developer will initialize that microcontroller before passing control to the your main application. Examples of actions performed by this file are:
Setup the ARM vectors
Configure the oscillator frequency
Initialize volatile memory
Call main()
3- Scatter : Personally I have never used this file. However it appears to be a file used to control the memory layout of your application and how that is laid out in your micro (see reference). This appears to be a Keil specific file no different from any other linker script.

Two different programs in Flash

Is it possible to RUN 2 different C programs(ie 2 main()), stored in Flash(micro controller), one at a time?
I have a bootloader code which is a separate program and resides in separate protected section of ROM. Then I have my application program which resides in separate ROM section. Although, residing in memory is not an issue, but how will linker interpret this? How can I switch between 2 programs. Is this possible?
For example:
Once I am done with bootloader, I can make it jump to Application function, but how will linker know this function?
Just to add, I am using Freescale HCS08 series and IDE is Codewarrior.
Further, here are the sequence of steps:
I load a Bootloader code in ROM. Then this bootloader code is required to load my application code. And then my application code should take over.
Bootloader Code:
Program Application Area ROM
Start Application Program
Application Code:
Check if to run Bootloader code or application itself.
Main is just a function. You may rename it and write another main which call either of them.
If you do not want rename main in the source you may mangle its name by define or compiler key:
cc -Dmain=main1 ...
(for first program), and
cc -Dmain=main2 ...
(for the second). Selector main:
int main(void) {
if(x) return main1();
else return main2();
}
Then link all together and download to your controller.
But there's problem with ISR's: you cannot assign two routines to single irq vector. If vectors are hardcoded to some flash location (like in most 8-bit controllers) you cannot switch ISR's. You will have to write ISR wrapper, recognizing which program is run and calling appropriate ISR.
UPD
Second issue is that statically linked variables from first and second program will be in RAM simultaneously while only one set of them is used. This may exhaust RAM (small amount of which often exists in microcontroller) too early.
UPD2
Oh, now I really understand. If you want to link and download them separately, you should deal with linker maps. In this case same symbol names (such as many main's) s not an issue. In linker map you should define known entry point [set it to absolute address], from which either application code starts. Startup code (commonly it is assemble code) should be linked from this address. From selector you should decide and jump to defined location directly. (Do this only for bootloader if your app is also a selector).
Entry point provided by linker may be accessible by program as extern function:
int app2_start(void);
{
.... /* condition check */
app2_start(); /* this symbol defined in linker map, not in any source */
}
But this is not the address of it's main(), because C RTL have do make many initialisations (stack, initialised variables, heap, IO, etc.) before main() can start.
There's more common way that the bootloader decides, should it run itself or application, because if application code fails, boodloader may became inaccessible.
The way I've seen this done is to stick the entry point into a header for the application. Then have the boot loader pull that entry point out and jump to it with an appropriate inline assembly instruction. You may need a linker script to get the entry point itself from the application. Gnu ld uses ENTRY.

Resources