how to update only some portion or APIs of code in avr

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using atxmega256a3bu microcontroller for my project, I want to make a program architecture like I have compiled and programmed the code and now only some APIs can be changed and reprogrammed into the board other portion of flash should not be changed and newly compiled APIs can work with rest of the code that was already programmed in the flash.

for example, I have made all the code and downloaded it into the board, which has a API function named

todo_callback()
{
printf("nothing to do");
}

Now if I want to change the function as below:

todo_callback()
{
printf("updated to do");
}

then how can I update this function only whithout changing the whole flash code.

Regards, shreyas.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

only some APIs can be changed and reprogrammed into the board other portion of flash should not be changed

For that bit you'll want to use a bootloader.

For the other you need what's almost a form of dynamic linking. Normally when main() calls foo() the linker can just change a CALL 0x0000 to CALL 0x1234 because it knows foo() is at 0x1234 once it's seen all the files to be linked and has placed them into the memory map.

But now there's a potential for you to have a situation where the code in main() cannot know the address of foo() as its supplied in an update and on this build it's now at a different address.

The way to resolve this would probably be to have a fixed table to JMPs to things like foo() that you place at a known location each time the block of new API()s is delivered. When you rebuild the APIs and foo() changes location all that changes is its entry in the table. Something like:

int main(void) {
  foo();
}
===================
.section jmp_table
foo: jmp newfoo
===================
__attribute__((section(".new_apis")))) void newfoo(void) {
  // stuff
}

-Wl,-section-start=.jmp_table=0x10000
-Wl,-section-start=.new_apis=0x10100

Build this in two halves with .jmp_table in both.

Or something along these lines anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course, the most typical way to make a change like this would be to simply upload a completely new program that is compiled with the changes. Is there a specific reason that that can't be done in this case? Also, the change you showed had nothing to do with functionality, it was only a change of data, so that could be pushed out to EEPROM and the change made there ( also doable with a bootloader or even from the program code itself ).

Questions like this often run-afoul of the fact that they are not connected with an application. The question is, why do you think you need this. The AVR is not suited to the dynamic linking required to upload and replace functions at run-time. Though, of course, for every thing, there is a time and place.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mckeemj wrote:

Questions like this often run-afoul of the fact that they are not connected with an application. The question is, why do you think you need this. The AVR is not suited to the dynamic linking required to upload and replace functions at run-time. Though, of course, for every thing, there is a time and place.

Martin Jay McKee

of course there is a reason, I need the application like dynamic linking because I want to give base code in a stack form and user can compile and download only their application in some APIs above that stack.
that printf statement is just for example here.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

only some APIs can be changed and reprogrammed into the board other portion of flash should not be changed

For that bit you'll want to use a bootloader.

For the other you need what's almost a form of dynamic linking. Normally when main() calls foo() the linker can just change a CALL 0x0000 to CALL 0x1234 because it knows foo() is at 0x1234 once it's seen all the files to be linked and has placed them into the memory map.

But now there's a potential for you to have a situation where the code in main() cannot know the address of foo() as its supplied in an update and on this build it's now at a different address.

The way to resolve this would probably be to have a fixed table to JMPs to things like foo() that you place at a known location each time the block of new API()s is delivered. When you rebuild the APIs and foo() changes location all that changes is its entry in the table. Something like:

int main(void) {
  foo();
}
===================
.section jmp_table
foo: jmp newfoo
===================
__attribute__((section(".new_apis")))) void newfoo(void) {
  // stuff
}

-Wl,-section-start=.jmp_table=0x10000
-Wl,-section-start=.new_apis=0x10100

Build this in two halves with .jmp_table in both.

Or something along these lines anyway.

hi clawson, thank you so much for understanding, I got your idea but I am using IAR and in that I could not find __attribute__((section(".new_apis")))). I need to search for it how to implement it in IAR. do you have any suggestion for that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I got the way for attribute in IAR,
its like:

void f(void) @ "MY_FUNCTIONS";

I will update more when I complete the aim of updating the functions using jump table as per clawson.

thank you.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There remains the question as to why dynamic linking is the "right" way to do this. It would be easy enough to supply everything in source form to just allow recompilation, or the stack itself in an object library with headers ( so that the source is hidden ), or to build the stack into the bootloader ( assuming it is small enough ), so that what is actually downloaded is an application that uses the stack. Many ways to solve this sort of problem that do not require the difficulties of absolute positioning of sections.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shreyas,

You have completely missed the point if you think you need this or that it's a good idea for AVR.

On a PC ask yourself why both static and dynamic linking exist and why it is you often choose to use dynamic linking.

Now contemplate how that decision has any bearing on a Harvard architecture AVR that can only make opcode fetches from flash.

It simply does not make sense.

You mentioned printf as a library function that might be used by more than one program. Yeah so you build program 1 and statically link in a copy of printf and then squirt the entire program into the flash. Then you build program 2 that statically links to printf then squirt that into flash. How does it actually help to leave a copy of printf on the flash then only deliver the other bits of 1/2?

Is this all about saving flash download time?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Let's just see if we (or only I?) got the idea right:

You want to "deliver" an AVR with preloaded code supplying an API. The "customer" then writes his application code, builds it and loads this into the rest of the flash and those two combined form the final executable?

Correct?

Is this about trying to stop the "customer" from getting control over the API code?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If that were really the case what's to stop the user putting a ROM hex dump app into the AVR and simply dumping out the "hidden" code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Let's just see if we (or only I?) got the idea right:

You want to "deliver" an AVR with preloaded code supplying an API. The "customer" then writes his application code, builds it and loads this into the rest of the flash and those two combined form the final executable?

Correct?

Is this about trying to stop the "customer" from getting control over the API code?

yes, exactly! I need that kind of feature/requirement. If there is any other way then it is also acceptable.

Thank you,

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As Cliff said: The user can simply write a small app that dumps the complete flash out on e.g. the UART and pick it up using an attached PC.

If I where you I'd give upon this idea - IMO it is not worth it.Instead trust that the user can make little use of the binary code anyway. So you just ship a binary library to him, let him build the app and link with your library and program the complete application to flash himself.

If the code actually is something that will transform the future for all of humanity, with a possible value of gazillions of dollars, then anyone could buy a preloaded AVR of you and for a few hundred ot thousand bucks just let a chinese firm crack the AVR and extract the binary right out of flash. Regardless of how many obstacles you set up in some software scheme, it is no secret that AVRs can have their flash ontents read out for a dollar sum with less than 5 figures. AVRs are simply not that safe.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Because there's no memory protection in an AVR CPU the user will always be able to read out your code. True there are lockbits but as I say they can just deliver an app to dump out the entire ROM anyway. So you might as well just provided the code as statically linked binaries on the PC. If written in C then that's often protection enough anyway as disassembled C code without debug symbols tends to be a bit of a "one way encryption" anyway.

Another idea might be to put two micros on the board. One locked with your "hidden" code and one unlocked to accept the user code. There'd be some comms. mechanism by which the user micro could ask the system micro for some services. For years there used to be an ancilliary micro you could buy that would do floating point functions as a service to your own code. I think it was really just something like a Z80 (or Z8 MCU?) under the hood but it effectively worked like a "black box".

Now a few years ago I'd have had no problem remembering what that thing was called but age is the onset of the grim reaper and he appears to have already taken that brain cell :-(

EDIT: phew - thank goodness Google makes up for lost brain cells:

https://www.sparkfun.com/product...

(I note that URL includes the word "retired").

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Because there's no memory protection in an AVR CPU the user will always be able to read out your code.

JohanEkdahl wrote:
So you just ship a binary library to him, let him build the app and link with your library and program the complete application to flash himself.

Actually my idea for updating particular APIs is not for code protection from theft, I want to give stack to the user in such a way that he does not need to think about whole stack, he is familiar with those APIs only those he can update as his application. The idea of binary library was good option I thought.
But I want to give facility of firmware update over the air which also use my stack which is larger in size and would not fit in boot loader section of 8k.
Now if I give facility to update particular location then I can achieve my goal.
But still, in this case also, I don't know how to build image for that particular APIs only.

Thank you all..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I want to give stack to the user in such a way that he does not need to think about whole stack,

So provide it as a .a file. Think about printf() or strcpy(). You happily use those but you've never seen the source.
Quote:

But I want to give facility of firmware update over the air which also use my stack which is larger in size and would not fit in boot loader section of 8k.
Now if I give facility to update particular location then I can achieve my goal.

If the user is going to have to do some kind of code update process anyway then why not just send them a new libstack.a and get them to compile then download the complete code image they generate?

All you are trying to do here is delay the linking process but in doing so you make the system far more complex for very little gain.