This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

High level FOTA upgrade doubts

Other Parts Discussed in Thread: CC430F5137

Hello folks,

I'm thinking about adding FOTA upgrades for my CC430F5137. Here are the two sources that I have been learning from:

  1. https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/272514
  2. http://www.ti.com/lit/an/slaa511a/slaa511a.pdf

So, here is what I understand and a few related questions:

  1. From 's response, the new firmware is received and stored in an unused part of the flash memory
  2. When the firmware is completely received, the MSP430 restarts and goes into the custom BSL. However, looking at the download package from (2), how is the BSL any different from other code? I don't see any additional decoration around the main() function (see below for what I mean). Or should I look at a different example?
  3. The BSL needs to run in RAM; this makes sense or else we'll be clobbering some parts of the BSL.
  4. Again, from 's response, the new firmware is copied to the location of the current firmware (I believe this starts at 0x8000 for the CC430F5137). Is there no way to do some kind of remapping of flash memory to avoid this copy?
Main function in the Core BSL:
//******************************************************************************
// @fn          main
// @brief       Starting point of the WBSL, calls the needed routines prior
//              to starting main program or entering WBSL
// @param       none
// @return      none
//******************************************************************************
void main()
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

  // Upon power-up, check whether to run the Boot Loader or the Main Program.
  init_buttons();                           // Enable S1 button of FRAM board

  __delay_cycles(1000);                     // Allow S1 to settle

  if (TI_CC_SW_PxIN & TI_CC_S1)             // Check S1 pin state
  {
    TI_CC_SW_PxREN &= ~TI_CC_S1;            // Restore default S1 port state
    startMainProgram();                     // Transfer execution
  }                                         // In case this fails, start WBSL, sleep
  else
  {
    TI_CC_SW_PxREN &= ~TI_CC_S1;            // Restore default P4 state
  }
  cbsl_init();                              // Enter the WBSL
}



  • Hello Kenny,

    I am currently trying to pull in the author of the app report mentioned to help answer your questions but I ask that you please be patient as he is out of the office through next week.

    Regards,
    Ryan
  • Cool, glad to know that these questions are on someone's radar. Rest of the folks on TI support forum, don't be shy :)

  • Hi Kenny,

    Overall the steps outlining your current understanding seem to be rather complete! I will try and clarify the topics related to the questions in steps 2 and 4.

    2. The primary function of the BSL being utilized in the application note is to check whether a new firmware image should be transferred OTA to the target MCU, and if not then start the application already in memory. The main function you quoted in your initial question is performing that primary function. In terms of any additional differences to BSL code versus main application code, there is not much that separates a BSL from a main application. The function it performs is different than the majority of other applications (handling firmware updates), and oftentimes special handling must take place in terms of placement within MCU memory (typically BSL memory segments on an MSP430), but otherwise a BSL is 'just' another application.

    4. Since the BSL being developed for OTA updates is already a custom application, you can modify it to meet your specific needs in multiple ways. The method Jens-Michael Gross outlines in his reply is one method, although it is not necessarily the only method (as you can tell by both his frequency of replies and quality of replies, more often than not his method/recommendation is absolutely one you should consider regardless of the topic!) which can be used for BSL and firmware updates. For instance, you could instead modify your custom BSL to call one of two application images; one image would reside in the first half of main memory and the other in the second half of main memory. A flag or bit indicating which half of memory contains the current, active application would be updated when new images are transferred to the target. This would allow you to copy the new firmware image OTA, set a bit/flag, reset, and have your BSL call the new application without any need for copying the new firmware image from one location of memory to another.

    Hope these details help you with your developments, and please let us know if you have any further questions!

    Mark-

  • @ Thanks for the response! As a follow up for (4), what is the correct way to call the main() function in the new firmware? It seems like one way to do it is to change the address at the reset vector at 0xfffe (from e2e.ti.com/.../72505). Is this correct? Or should the BSL just call some address in memory?
  • Hi Kenny,

    Either solution could certainly be implemented.

    I would lean more towards having the BSL call some address in memory, but I don't have many technical reasons for that preference other than it makes more sense in my head. If a power loss happens after erasing the segment of flash containing the reset vector before writing it you will have a part which will not do anything. With the BSL calling some address in memory, every time the device resets the BSL is called first and will handle checking which firmware image is valid and should be run or request/wait for a new firmware image if no valid images are found (which may happen in the power loss case described above).

    If instead you elected to rewrite the reset vector to point to the latest valid firmware image, your application would call the BSL (either as a result of a user request or each time the application starts). Other than the potential risk of rewriting your reset vector, the behavior would be quite similar. One thing to note is that typically more changes are made to the application instead of to the BSL during a product's life. This is another reason I would lean towards having the BSL utilize the reset vector, as it would minimize the need to rewrite the reset vector and allow for the more stable code to always run first.

    One reason you see the application note download a 'wireless BSL' is to give the BSL upgradeability. Having a very small BSL with limited functionality that is 'called' by the reset vector that then downloads a more full featured BSL as part of an upgrade process allows changes to be made to the larger BSL for future changes to the system which require changes to the BSL. This upgradeability feature could be added to either method.

    Mark-

  • Cool, thanks for the detailed explanations! I'll definitely have more low level questions when I begin to do the work.
  • Mark, thanks for the kind words :)
    The main problem with having two applications that can be alternatively called is the handling of the interrupt vectors. There is only one set. Interrupts go to the application that has its vectors written to 0x0FFxx. A possible workaround on 5x family would be to copy the interrupt vector table of the active application to end of ram, and switch the CPU to use this place instead of flash for fetching interrupt vectors. The BSL can do so when picking the application to run. However, each application needs to be linked in a way that it does not use this ram area (change of the linker script needed). And of course it needs to be linked for its final location. So you can't place an application anywhere in flash. If APP A is built for this and APP B is built for that location, you can't replace either of them with APP C, as APP C can only replace A or B depending on the location it was built for. Or you need an intelligent bootloader that does address relocation when a new APP is loaded. Sort of a 'just-in-time-linker'. Perhaps doable, but quite a task.
    An alternative (on other device families) would be to have the interrupt vectors pointing to fixed ISRs inside the BSL (not in BSL flash, as you can't jump there), where the current application is checked and jumped to the vector of the active one, fetched from their individual (not at 0x0ffxx) vector table. However, this adds quite some latency to any interrupt, preventing some applications where fast interrupt response is required.

    If you have the custom BSL in BSL area, it can have a modified BSL entry check function which always starts the BSL and then the active application. In this case, it doesn't matter whether the hardware interrupt vector table is populated or not. However, I'm not sure whether this function (and therefore any BSL code) is called on a soft reset (PUC), and I don't remember whether a PUC resets the table from ram to flash. In which case a PUC would crash the system.

    Kenny,
    if the app is a C program, then it does all the necessary initialization when you jump to the address in its reset vector. You may also make a call, instead of a jump, from which it never returns. (C doesn't know jumps but can perform indirect calls on an address using function pointer typecasting. So if your BSL was written in C...)
    It initializes the stack (voiding the stored return address in case you called it instead of jumping to it), initializes global variables and so on. The only thing that should be done is to reset all hardware to its power-on defaults (including clearing the GIE bit in SR), as the application might be written in a way that it chokes if anything isn't as expected after a clean power-on.
    That's the same prerequisite as required for calling the (default) BSL from within your app. Or when switching between apps.
    In any case, 0xFFFE should point to your BSL (if you have a BSL outside the BSL area).

**Attention** This is a public forum