2

I am working on Cortex-M3. I want to add a function (or ISR) to an existing firmware image without updating the whole program. Can I compile and build a function without main and write into the flash? If I know the address where this function is written, Can I call this function using a function pointer?

We have code in single thread and no OS. The underlying problem is how will we create an environment to install and use an application in this case.

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • no we are not trying to patch some one else binary .we have a code in single thread and we have no OS and the problem is how will create the environment to install and use that application in such a case. – user1884725 Sep 22 '13 at 15:36
  • Most of your issues are elegantly solved with a *linker*. Look at the documentation for your toolkit. For example, [Gnu Ld](http://sourceware.org/binutils/docs/ld/) with the `gcc` tools. You may extract symbols from one module and call them *without* function pointers. Even though you can do this in plain C without linker tricks, your code will usually be *limited*. If you really have no-OS, then I would guess you already have a custom linker script. – artless noise Sep 23 '13 at 01:24
  • Yes you can. What you will be able to do will depend entirely on how you implement it. Infact, you can implement a Reset Vector and even give it a new Vector Table so that you can upload a small bootloader somewhere in memory. – nonsensickle Sep 23 '13 at 01:38
  • If you explain more about what you're after I might be able to help. Right now I'm writing a bootloader for a Cortex-M3 and I've already done something similar to this. – nonsensickle Sep 23 '13 at 01:38
  • 1
    This question is 100% appropriate, on-topic, and complete. A main challenge to keep in mind is that any library routines you use (even unawares, from compiler built-ins) will either have to be duplicated, or else you will have to manually inform the build system where they are located in memory in the existing image. But ISRs should generally be kept quite lean, so you may not have an issue there. Finally, if the system is running with the vector table in flash, you will have to reflash that block with a new version that has a vector pointing to your ISR. – Chris Stratton Sep 23 '13 at 14:26

2 Answers2

0

Yes you can.

There are 3 files that you will need to understand before you can be sure that you know how to solve this:

  1. The SAM3N4C Startup Code
  2. The DeviceVectors definition
  3. The SAM3N4C Linker Memory Region Definitions
  4. The SAM3N4C Linker Script

I've given you the links to the SAM3N4C chip because I'm familiar with it. The code can be made to suit your chip that you're using.

To make it work for what you are asking you will need a vector table that has a pointer to your function. You will need to place this vector table at a known address and you will use it to get your function pointer. Your function will be placed in the memory immediately following this vector table.

Brief explanation:

It seems that you're still unfamiliar with how things work on a Cortex-M3 so I'll try and explain a little.

main is not special. It is just a function and it isn't even the first thing that executes. The first function that runs on a Cortex-M3 is your Reset Vector interrupt service routine. This function then sets up all of your memory and then calls main (see The SAM3N4C Startup Code).

On a Cortex-M3 there is a pointer to this special function at a known offset from the start of your memory (0x00000004) and that is what your hardware uses to boot/start. The Reset_Handler() function from The SAM3N4C Startup Code is placed at that address. This is done in the DeviceVectors exception_table struct that you can see being initialized in the code given in The SAM3N4C Startup Code. This struct contains all the function pointers and for the reset vector to be located at an offset of 0x00000004 from the start of memory, the exception_table needs to be placed at a the very start of memory. This is done by using the __attribute__ ((section(".vectors"))) flag to place the exception_table in the .vectors section (see The GNU attribute syntax). This is then used in The SAM3N4C Linker Script, which includes the memory region definitions given in The SAM3N4C Linker Memory Region Definitions, to place it at the very beginning of memory (using the KEEP(*(.vectors .vectors.*)) line, which is put into memory first).

I recommend investigating your existing linker scripts for how they work because they will give you a clue as to how you can do this. Reading more about the GNU linker will help you with this.

Also, the solution you are after would, in my opinion, replicate this behavior but you would use a smaller 'vector table' since you only need one function...

nonsensickle
  • 4,438
  • 2
  • 34
  • 61
0

If you compile your code using "Position Independent Code", then your function can be relocated anywhere in ROM (Flash) or RAM.

Writing code that is relocated in memory is still not trivial and you should be sure to understand the ARM architecture and at least not be scared of the ARM machine instruction set. The trick is to first understand how this happens at the instruction level, then try to do the same thing with C. There are complications, of course. Before main runs, there is behind-the-scenes work in the initialization procedures, which set up zero and non-zero initialized variables. It depends on your compiler on how this actually proceeds. It is useful to run a dummy program, and step through all the execution BEFORE you get to main.

See this related question: Trying to load position independent code on cortex-m3

Community
  • 1
  • 1
Mark Lakata
  • 19,989
  • 5
  • 106
  • 123