Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
8 years, 7 months ago.
Is it possible re-flash the device with a downloaded binary?
Hi, I'm playing around with a FRDM-K64F trying to load binaries dynamicly. So far I've been reading up on IAP (In-Application Programming):
https://developer.mbed.org/users/okano/notebook/iap-in-application-programming-internal-flash-eras/ https://developer.mbed.org/users/okini3939/notebook/dynamicload/
What I'd like to do is : 1. Download a new binary from the device 2. Reboot the device
Q1: Is this possible? Q2: Is IAP the way to go? Q3: Are there any other good references part from the ones I referenced earlier?
Thank you!
1 Answer
8 years, 7 months ago.
Okano has done a really good job on his IAP library, there is just one small issue: It is for an NXP LPC1768 (and some similar ones), and not for your Freescale (okay also NXP now) K64F. They have a completely different method of using IAP.
So Q1: Yes this is possible. Q2: Yes IAP is your only option. Q3, with some shameless self promotion: https://developer.mbed.org/users/Sissors/code/FreescaleIAP/ and specifically: https://developer.mbed.org/users/Sissors/code/Bootloader_K64F/.
Note that while using the online compiler making a bootloader which references other libraries, such as USB for example if you would want to use that, is nearly impossible. Thats why in that example code I used a simple Serial bootloader that I could write all code for easily myself.
Thanks for an awesome answer Erik. It will take some time to digest, but thank you!
posted by 13 Apr 2016Took me a couple of days to read and understand. Although I don't consider myself a C programmer, the documentation was excelent and easy to understand. I've tried it out and it works! I'm humbled and overwhelmed of the opportunities it presents. - To sum it up, - it's exactly what I was looking for, even down to the device ;)
A few more questions (if you don't mind). So far we've offering an IoT infrastructure based on node.js, but the principle is the same. There are three pieces to the puzzel;
1. The Server Hub (provides updates and tells the Agent to download it).
2. The Agent (who talks to the hub using websockets, and downloads new versions of itself).
3. The Bootloader who installs the new agent versions and restarts the device.
Q1: I've added the FreescaleIAP reference to my program along with the bootloader.cpp file, but as my program is bigger than 60kB, what parameters part from the NUM_SECTORS (15) do I need to set? My program is 100kB so I tested setting it to 25, but it fails. Would I need to modify the attribute sections?
Q2: Given your article, I guess the easiest way would be to add an external memory chip to persist the downloaded binary. Would you happen to know of a memory chip you could recommend for the K64F?
Q3: When is the file persisted when I send the file using TeraTerm? Would I not be able use the same space for binaries downloaded from the Agent (I realize this is a stupid question)?
Q4: Just checking... would it be possible to convince you to help us out building the bootloader ;)
Many thanks for the article and the sample.
Mikael
posted by 17 Apr 2016Since contrary to some other MCUs, all sectors on a K64F are identical it should work with a larger number of sectors. However I was pretty lazy when making that program, and checking which sector was the last for the bootloader was apparantly too much effort for me :P. So the bootloader is located now at 65k (0x10000). And if you go to 100kB then it deletes its own bootloader, so it breaks.
Q2, that can be an easy solution yes, but if your binary is smaller than half the flash size of the K64F you can also use the second half of its flash for the same purpose. I don't have a memory chip to advice you :).
Q3: I don't understand your question. If you send it via TeraTerm it is placed first in a 16-byte RAM buffer, and once this is filled it is directly programmed. It is based on that it can program faster than Serial can write, so it stays ahead of the serial code by programming it faster.
Q4: Yes, but not for free ;). Also I know Freescale (NXP now) offers some kind of bootloader somewhere too, but I have no idea where and if it meets your requirements.
posted by 18 Apr 2016Hopefully the last question ;)
With the Bootloader running and sending a file (helloworld), it all works. The file gets uploaded and the device "reboots", - All good.
However, if I do the same thing, but uploads the binary of the same Bootloader program that is already running it fails. The new bootloader starts up, but it seams corrupted and won't continue to work.
Is this supposed to work? I can see how there could be a problem overriding the part of the program that is currently running. Perhaps I've misunderstood something. I was of the assumption that I could basically import the FreescaleIAP lib and add the bootloader to my existing program and ajust the attribute session (0x10000) to fit my program. And from that point forward I could always use the bootloader to update my binary.
Was I wrong?
posted by 18 Apr 2016There are some limitations on that example, since it does not set the clock setup itself (which would be easy enough to add), it relies on the mbed lib of the imported program to properly set the clock. In addition it uses stack variables, so a stack pointer needs to be set.
If you try to send the bootloader binary to it again I assume you are simply running out of space: since only the area in front of the bootloader can be use to program memory, but definition it is not possible to program the memory in front + the bootloader space itself. It will already fail because that area is not erased first. Also take note the bootloader example does not use the FreescaleIAP lib, it uses a modified version where all functions are also moved to the bootloader area!
But yes, if you do that the first time with any way you like to program it, you can get the bootloader on there, and the next times you can program something else with the bootloader. But the new programs should not include the bootloader, this will stay on there automatically.
posted by 18 Apr 2016The last sentence made it all clear. -Of course, the bootloader will always stay as long as the new program is smaller. But given that my helloworld program represents the Agent program that needs to call the Bootloader after it has downloaded the new binary, -How would the Agent call the bootloader if it's not part of the binary?
As I'm writing this question I realize this is turning out to become a "C for dummies course", which I never intended. I'm sorry about the that, but this is sooo much fun!
posted by 18 Apr 2016I haven't tried it myself (since in my example I use the NMI handler to get into the bootloader), but I think this should work:
void *(*bootloader)(void) = (void *(*)())0x10000;
Then you should be able to just call bootloader(). The first half is the standard way to define a pointer to a function taking no variables and returning no variables. The part in front of the 0x10000 is what the compiler error message told me to put there :P.
posted by 18 Apr 2016It didn't work, but I got plenty to look into. I'll let you know if I'm successful.
THANK YOU!
BTW, it compiles, but it doesn't start the bootloader :(
posted by 18 Apr 2016Ok i'm giving up, and turning to a professional (you)... What would it cost me to have you complete my code?
main.cpp // eg my agent int main () { write("Update device? (y/n)"); while(!(UART0->S1 & UART_S1_RDRF_MASK)); if (UART0->D == 'y'){ // download this binary from an internet location and persist it to flash download(); // call bootloader to override the current program with the one downloaded and restart the device bootloader(); } else{ printf("Whateva"); } }
In essens I should be able to run this over and over by just hitting "y", and every time it should download the new binary, flash the device and start up again.
You can reply to my email - wmmihaa at hotmail com
posted by 20 Apr 2016