Firmware Over the Air (FOTA)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Firmware Over the Air (FOTA)

4,295 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FernandoR on Sat May 10 12:50:23 MST 2014
Hey friends,

I have a few question that I hope some of you can give a help.
I'm working on a LPC1778 and now I'm finishing the firmware, I realized that I need to update firmware over the air, I have a secondary device which has GPRS connection, and this device will download the newest bin file and send it to me, and there is my problem, I'll store the data in an external flash memory, so I can rewrite as my new firmware later.

The point is : How can I put this firmware to run in my device after received??
I already read about IAP, that I'll need to use it to write in to the Device Internal Flash memory (512k) and all. But how to properly use it?
Which address should I start to Run my code  and write the firwmare that I received??

Anyone already did something like this??

I know its a lot of questions, but I'm desperate!!

Thank you in advance!!
Regards,
Fernando Augusto Rebêllo
Computer Science student
0 Kudos
Reply
14 Replies

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FernandoR on Wed May 21 10:49:02 MST 2014
I debuged, but no errors or faults happened.

I only think it's a little strange a thing in here, in my function

void execute_user_code(void)
{
void (*user_code_entry)(void);

unsigned *p;// used for loading address of reset handler from user flash

/* Change the Vector Table to the USER_FLASH_START
in case the user application uses interrupts */
__disable_irq();

NVIC->ICPR[0] = 0xFFFFFFFF;//Clear all pending interrupts
NVIC->ICPR[1] = 0x00000001;

SCB->VTOR = (USER_FLASH_START & 0x1FFFFF80);

// Load contents of second word of user flash - the reset handler address
// in the applications vector table
p = (unsigned *)USER_FLASH_START+4;

// Set user_code_entry to be the address contained in that second word
// of user flash
user_code_entry = (void *) *p;

__enable_irq();
// Jump to user application
    user_code_entry();
}

I set the value of VTOR = 0x00020000 // fine, it's my firmware base address
then I set the pointer p = (unsigned *)USER_FLASH_START+4; // why 4 bytes extra??

then I put my void (*user_code_entry)(void) = (void*) *p; // 0x200143 ??????

this function was copied from an SBL Example of NXP, but is normal to calculate that address (0x200143 ) ??

Thank you all in advance!

regards
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Wed May 21 08:17:15 MST 2014
So, time to debug your code then. If *you* don't know what is going on, how do you expect us to know?
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FernandoR on Wed May 21 07:41:24 MST 2014
TheFallGuy

I have these two firmwares in my internal flash ... the first one, is storedin 0x0 (Bootloader), the second one is stored in 0x20000 (User application Code), when I mean is not working, I mean that the software doesn't seem to run the user application Code, My Bootloader sets a GPIO pin from 1 to 0 10 times with 1 second of delay between the switch, before try to jump to the final firmware, so I can know I still in bootloader.

My final firmware set the GPIO pin from 1 to 0 with the half of the time, eternaly, so I can know the firmware is running, when I power on the board I hear the pin setting to 1 and 0 at booloader speed, but when the 10 times ends, the board doesn't seem to do nothing, like the bootloader didin't jump to my final firmware.

But I don't got any errors, and I didin't try to debug the bootloader yeat.

Thank you in advance
Regards!!
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Wed May 21 07:34:53 MST 2014
Maybe you can explain what you mean by "not working"? Are you getting errors? Have you stepped through the code? You haven't given us anything taht we can help you with...
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FernandoR on Wed May 21 07:07:56 MST 2014
whitecoe

I tried what you've done

my main code looks like this now:

void main(void)
{

 //void (*user_code_entry)(void);

uint32_t i;
GPIO_SetDir(1, 18, 1);
GPIOSetValue(1, 18, 1);
GPIOSetValue(1, 18, 0);

for(i = 0; i < 10; i++)
{
GPIOSetValue(1, 18, 1);
Delay_ms(700);
GPIOSetValue(1, 18, 0);
Delay_ms(750);
}


SCB->VTOR = USER_FLASH_START;
// set stack pointer to start address of second binary. The start address of a new binary contains the address of th  stack pointer
__set_MSP(*(uint32_t*) USER_FLASH_START);
// jump to the new binary
typedef void __attribute__((noreturn)) (*exec)();
uint32_t *start = (uint32_t*) (USER_FLASH_START + 4); // address of the reset vector for the new binary
((exec)(*start))();

}


but still not working

Regards
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by whitecoe on Wed May 21 06:46:49 MST 2014
Might be a stack pointer issue…
http://www.lpcware.com/content/forum/lpc1768-secondary-usb-bootloader-lock#comment-1133905

HTH!
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FernandoR on Wed May 21 06:36:03 MST 2014
TheFallGuy

I took a Look, but except for the part of USB and another detalis, i'm using the function in the example to try to run my firmware:

void execute_user_code(void)
{
void (*user_code_entry)(void);

unsigned *p;// used for loading address of reset handler from user flash

/* Change the Vector Table to the USER_FLASH_START
in case the user application uses interrupts */

SCB->VTOR = (USER_FLASH_START & 0x1FFFFF80);

// Load contents of second word of user flash - the reset handler address
// in the applications vector table
p = (unsigned *)(USER_FLASH_START+4);

// Set user_code_entry to be the address contained in that second word
// of user flash
user_code_entry = (void *) *p;

// Jump to user application
    user_code_entry();

}




Any idea of why is not working??

Thank you in advance
Regards
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Wed May 21 06:21:18 MST 2014
There is an example bootloader in the LPCXpresso examples for the LPC176x. Look in RDB1768cmsis2.zip and find the projects RDB1768cmsis2_usb_bootloader and RDB1768cmsis2_LedFlash_64k. This may give you some clues.
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FernandoR on Wed May 21 06:12:40 MST 2014
Guys,

Nevermind my last post, I gave up trying to run that function in RAM or SRAM.

Let me explain to you what I'm trying to do ...
I'm trying to make a BootLoader, so I tried to run from RAM the bootloader function (already discarded this idea), and now I'll burn a Firmware Bootloader at the address 0x00 and the User Application Code at 0x00020000, so I'll start my bootloader, do what I need to do and jump to the address of the UAC.

I tried to that with inline assembly (   __asm__ (" B 0x00020000 "); ), but didin't work, so I did more research about bootloader in Lpc's mcus and found somebody saying that is needed to reallocate the NVIC Sector Table to point to User Application Address before jumping to the address, so I took the function that person was using and tried to use it too, but it doesn't seem to work ...

First I set my bootloader project settings to run in address 0x0 (  Project -> Properties -> C/C++ Build -> MCU Settings -> Edit Flash ) and se size to 0x2000.

Then I set my User Application Firmware to rin in address 0x20000  (  Project -> Properties -> C/C++ Build -> MCU Settings -> Edit Flash ) and set the size to 0x60000.

Then I Flash the bin files into the MCU in the different flash areas and try to run, but my bootloader doesn't seem to jump to that address, even reallocating the NVIC Sector Table.

Heres my code:

/*
===============================================================================
 Name        : main.c
 Author      : $(author)
 Version     :
 Copyright   : $(copyright)
 Description : main definition
===============================================================================
*/

#include "LPC177x_8x.h"
#include "lpc177x_8x_gpio.h"

#include <cr_section_macros.h>

#define NVIC_VectTab_FLASH      (0x00000000)
#define USER_FLASH_START          0x00020000

#define PORT_DIR_OUTPUT 0

void Delay_ms(uint32_t dl)
{
uint32_t i;
for(i =0; i < (dl*8550); i++);
}

void execute_user_code(void)
{
void (*user_code_entry)(void);

unsigned *p;// used for loading address of reset handler from user flash

/* Change the Vector Table to the USER_FLASH_START
in case the user application uses interrupts */

SCB->VTOR = (USER_FLASH_START & 0x1FFFFF80);

// Load contents of second word of user flash - the reset handler address
// in the applications vector table
p = (unsigned *)(USER_FLASH_START +4);

// Set user_code_entry to be the address contained in that second word
// of user flash
user_code_entry = (void *) *p;

// Jump to user application
    user_code_entry();

}


void main(void)
{

 //void (*user_code_entry)(void);

uint32_t i;
GPIO_SetDir(1, 18, 1);
GPIOSetValue(1, 18, 1);
GPIOSetValue(1, 18, 0);

for(i = 0; i < 10; i++)
{
GPIOSetValue(1, 18, 1);
Delay_ms(700);
GPIOSetValue(1, 18, 0);
Delay_ms(750);
}

execute_user_code();
}


Do you guys can see what I'm doing wrong here??
And anyone knows why dr USER_FLASH_ADDR + 4 ???

Thank you in advance, I'm desperate, I need to solve this today.

Best Regards,

Fernando Augusto Rebello
Computer Science Student
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FernandoR on Mon May 19 13:11:23 MST 2014
I tried

But I do need to run a function in RAM, and this function will call iap_erase(0); iap_erase(1); iap_erase(2);
And when I try that, the software throws and "exception";

Am I doing anything wrong or forgetting about something??

regards
Fernando Augusto Rebêllo
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rocketdawg on Mon May 19 12:09:40 MST 2014
perhaps use these macros

http://www.lpcware.com/content/faq/lpcxpresso/placing-specific-functions-ram-blocks
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by FernandoR on Mon May 19 09:52:45 MST 2014
Hey guys,

Thank you for the support, but right now I have a bigger problem, how can I run a function in RAM or SRAM withou changing the  linker libraries?
I need to know that so I can erase my old firmware safely!!

Thank you in advance
Fernando Augusto Rebêllo
Computer Science student
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rocketdawg on Mon May 12 07:02:28 MST 2014
I would also add that you need to have two images available at all times, otherwise you risk a fail.
you do not want to do this in-place in flash since your bricking window is huge (the period of time where, if something goes wrong, reset, power spike, lost connection, ..., you end up with a brick)
so you have the current image and the next image.
if the next image is faulty then you can always revert to the current image.
if the next image executes fine, then erase the old current image and make the next image the current image.
you need image identifiers and checksums.
you probably want to save the image in external SPI flash because, as efiLabs says, you must be executing out of RAM to self program FLASH.

look at AN11257 which is an SPI boot loader
0 Kudos
Reply

3,974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by efiLabs on Sat May 10 22:49:36 MST 2014
hi Fernando :

i'm not quite sure if i follow all your details, but regardless of it, there are a few rules.

1) while writing the internal flash, regardless of the method and there is only one, IAP, the flash can not be used. period.

2) what this means is that the code fetching the image, wherever it comes from and the code making the IAP calls to write it, can not reside in the internal flash you are writing. also any constant data or whatever you use can not be in this internal flash.

3) options for the code space for handling the operation in item 2 will most likely be internal ram or other resources if the 1778 allows external memory execution access.

as long as you don't split your binary image into 2 parts i.e. boot loader and application program, the process of fetching the image (in small portions) and writing into flash can not be interrupted, otherwise you might need to re-image with ISP.

so what you do is, have the program portion which will execute in ram be placed in your flash image, have it compiled for the ram execution space, or in relocatable fashion if your compiler supports it ... and when you're ready to flash your new image, move this flash-loader from flash to ram and call it and once the flashing is done reset the cpu or jump to the reset vector. or wherever you want to jump (call) to in the new image.

have your interrupts disabled or the vector table access also relocated to a ram based ivect table

hopefully this short description helps ... think it over and envision, while writing, or erasing the internal flash you can not access it ... ergo execute the flash write portion, whatever it entails from a different memory address space ... where does this not flash resident portion of the code come from, most likely as an image embedded in the flash where you move it into ram before using (executing) it.

cheers, efiLabs
0 Kudos
Reply