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.

Flash programming,when one "flash segment" program the "another".

Other Parts Discussed in Thread: MSP430F2618

Hi Brandon,

It's an answer for your reply about my "flash programming" request.You understand my question well,but your answer doesn't help me.I'll explain.

I'm working with MSP430F2618 and IAR IDE. For flash programming,UART flash monitor example of TI doesn't help me. I'll explain:

Flash monitor program resides at the end of Flash memory of Demonstration application program.The flash monitor activates in case in RX UART of demonstration application receives=3,the PC moves to flash monitor program.From now the flash monitor program (not an apllication program) works with UART for flash updating. Flash updating starts from address,where demonstration application runs.So flash monitor reprogram flash of application program.Is it TRUE?

I need something else.I couldn't stop the regular work of my 1st application program,while the 2nd application program doesn't completed.The 2nd application program i'll receive by RF in small packets and back to regular work of 1st application.I couldn't rewrite all functionality of 1st image in something like "flash monitor" program and rewrite the flash of 1st application with the new receiving one.

MSP430F2618 has lower and higher memory for CODE and DATA_20,but CSTART,CSTACK,DATA_16 and etc.. should be in lower memory.So i need to build something like "two different" linker files and one START point,or something else????

Please help me to solve the scenario with a full explanation of how i could "JUMP" to higher memory code with CSTACK,CSTART of lower memory...

  • Since both programs, the new and the old, require their intterrupt functions pointed to in the vector table, and interrupt vectors always point into the lower 64k, there's no way around stopping 'normal' function for a short time.

    What you can do to minimize the process is:

    1) compile your code normally

    2) download the new code into area 0x10000-0x1ffff

    3) after all has been received, 'stop the machine', erase bank 0 (the 'minor mass erase' of only one 64k flash bank), then copy the data from bank 1 to bank 0. If it was successful, reset and restart.

    To minimize the risk of failure, you can add soem code that will be flashed first after bank erase and which contains the reset vector and the flash copying code. this will be either replaced as soon as everything else has been rewritten, or you make it part of your program code (check whether 0x10000 is empty, if not, copy and erase it at the end), so it is always there and never changed, even if everything else changes.

     

  • I was very happy to read your answer,because i solve the "flash" problem exactly in the way as you wrote.But i did it before i red your answer.So it make more guaranty in my implementation.

    Another questions:

    1) In order to write to flash starting from address 0x10000,i need to open form "configuration project" the data Model:large with 20 bit data types.Is it be a problem for my old code,because i don't want to take a risk of bugs due to open data model:large option?

    2) Could you explain more about your last sentence? Why for minimize the risk of failure,it isn't enough to check the "checksum" at the end of flashing copy to bank 1.And "flasing copy" code of bank 1 to bank 0,it's an always code of bank 0 and bank 1(part of my program code)?

    3) ".txt" format of "new code" has a control characters like "@" or "q". Is it my code should make just simple "copy" between segments(bank 1 to bank 0) or make a read an address after "@" and dispatch the code into this specify address after "@"? For e.g. "@3500 31 40 ...." Is it a should make a code that takes all after 3500 and dispatch "31 40.."  into the address " 3500" ?

     

    Thanks again

  • I cannot tell for sure for the different compilers, but switching to data model large means that data can be stored in the full 20 bit address space. This implies that every time a register is saved on stack, it has to be saved in 20 bit mode, This adds an additional cycle per push/pop operation as well as two additional bytes of stack usage.

    This might also affect already compiled code such as libraries. If the precompiled code isn't aware of that, problems might arise when registers lose their upper bits during a function call (since the called function does only save and restore 16 bit). Also, if passing pointers, the precompiled code might interpret them as 16 bit only and access the wrong memory location (e.g. for printf format strings).

    The 'risk of failure' I was talking about is based on the fact that there is a small time window where the processor is in an instable state. You need to update the vector table so it will match your new program version. To do so, you'll have to erase the 0xfe00 flash segment. As long as you haven't written the new vector table (and the flash code which should reside in the same 512 bytes), any interruption of the processor due to power shortage, ESD or so will leave the device in an unstable state.

    One solution would be to implement an ISR forwarding mechanism at a fixed location in flash that will forward any interrupt to the proper function (such as a secondary vector table or -better- a jump list. So you'll never erase the real vector table and therefore your flash routine (pointed to by the reset vector) will always stay in flash.

    You'll have to manually maintain and place the vector table and the jump table as there is no support for that in the usual compiler structures. Also, you cannot use bank erase for deleting the code flash (only for erasing the buffer flash after copying the data) as this would erase the last segment too. This makes the actual flash process take much longer (about 2.5 seconds more for full 40k). But your flash code might be smart enough to only erase and flash the actually used areas.

    Example:

    0x1d00 jmp #isr1
    0x1d04 jmp #isr2
    ...
    0x1e00 flashfunction:
    ...
    0x1f80 .dw 0x1d00
    0x1f82 .dw 0x1d04
    ...
    0x1ffe .dw flashfunction

    This way you'll never have to erase the last segment in lower 4k with the vector table and your flashcode and the device will always be in working condition: the flash code will after a reset detect whether the last update was successful (upper memory empty), unsuccessful (upper memory not empty but valid CRC) or reception of the update data was incomplete (upper memory checksum failure)

    Whether you store the binary values in the upper flash buffer or the transmitted textual file depends on the overhead you have. Binary is shortest and will finish the flash operation in the shortest time (for maximum flash usage). It will also allow the flash function (which in the above described approach may not be longer than 384 bytes) to be simple.

    Storing the source data, however, has advantages when your code is much smaller than the available flash. Then you'll have to update only the really used portion of the flash. You can combine both by just writing to the upper memory based on the commands you got and when copying to the lower memory, skip the areas that contain still ff for the whole segment. After all, you must reserve space for a full 40K flash update anyway (worst case), so you don't waste flash.

     

  • Hi All

    I just got some Texas Instruments eZ430-RF2500T Devices and install the Code Composer Essential and try to run a program which says that the Device is not RF20x1, so what device should i select from the list please.

    Thanks in advance.

    Fazlullah Khan

  • 1)Data model large option i'll check separetly.Thank you.

    2)"Risk of failure" problem.

        I'm writing code in C and using IAR linker to create/or not  my segments.I have an understanding problem,how i could create my

        small "flash copy=bootloader" function,that will be residing in a specific place in flash code,that willn't be erazed during a flash copy process from bank 1 to bank 0.

       Could you explain me,that i need to do in IAR linker file and in my C code to locate my "small flashing copy" function in unerased memory location?

       As i understand,the problem is with segment 0 of low memory(0xFE00 - 0xFFFF) with "INTVEC and RESET" code for a short time of coping by my "bootloader flashing" 

       copy function.Is it right? If i will reside my flash copy function at the end of high memory(for e.g. 0x1FDFF - 0x1FFFF)(how to do it in C,please help me),

       my flashing function only should do:   1)erase low memory(0x3500-0xFFBD);  2) copy the new image code(0x10000 - 0x1FDFF)(that will be resides there before)  to low  

        memory. 3)erasing high memory(0x10000-0x1fdff).Is it right? 

         I an understand that will be a short time ,where 0xFE00 will be erased and new interrupt vector willn't be write yet.

         But i have no experience like you in MSP430 and i want to write my  code as simple as i could. It's very difficult to me  to understand about "ISR forwarding process" or    "manual" managing of interrupt vector with assembly code).I don't understand,when i should write it and in where it should be resides(which file ,where in memory). Please answer me with simple suggestions.Please remember,i work with C and IAR linker.Thank you.

    3)"TXT format via Binary image format" question.

        I don't understand your answer.I've compiled new image in ".txt" format. Is it mean,that after residing the new image in ".txt" format in high memory (0x10000-0x1FDFF),i should simple call my flashing function(See my flashing function should do)? Or maybe i should write my flash code function with dispatching the new image functionality according to "@" address in ".TXT" file?  I work only with ".TXT" format.

     I don't understand your sentence:  "As long as you haven't written the new vector table (and the flash code which should reside in the same 512 bytes)". Which flash code,is it "my flashing=bootloader" code?Why it should reside in same 512 bytes? I could reside the "flash code" in high memory for e.g.: 0x1FDFF - 0x1FFFF. Is it right?

    Thank you.And please help me.  

  • First of all, I'm not useing IAR or CCE. I'm mspgcc user (inherited for the one working on out projects before, and I'm quite happy with it as it offers much functionality and the toolchain allows automatisation of the production process).

    So I cannot tell you how to exactly do the necessary tweaks for IAR. I can only give general hints. I have never really dealt with linker configuration before too (just a few peeks into it), so even on mspgcc I had to do some research myself.

    Based on this...

    2)  indeed, you got the problem and the concept of the my solution proposal. Only that the flash copy code should reside in the same segment as teh (static) vector table, so it can be called ofter a reset. All vectors can only point into the lower 64k, so the flash copy code needs to be there too. Since teh vector tabel is only 128 bytes, the flash segment it sits in 8and tehrefore may not be erased) is 512 bytes, there's plenty of space for the copy code.

    Writing your own bootloader is a rather complex task, especially if you want to make it failsafe. The MSP has its own bootloader, but it requires a special entry sequence and there is no way to make it come up without external influence. So even on systems with a reprogrammable bootloader section, it is not suitable for updates from different data sources (such as RF module, USB, I2C, SPI etc.) even if one writes a bootloader that handles this. The need for toggling some lines to enter the bootloader after a reset makes all attempts void. (If the bootloader would automatically always come up if the reset vector points to FFFF, this would be an alternative option to my approach.)

    Basically you'll need to define two additional segments. One that starts at 0xfe00 to the beginning of the vector table. This will hold the code that is called at reset and will then check for a necessary copy operation. This is because the area 0xfe00-0xffff is in a single flash segment and can only be erased whole or not. Since you want your system operational all the time, this segment will contain the boot/flash copy code and a static vector table and will never be erased again. The flash copy code needs to fit into these 384 bytes and if it is smaller, the rest will remain unused.

    The next segment is one with 256 bytes size which holds a jump table. It must be always at the same location (therefore a separate segment) and contains jumps to the 'real' interrupt functions. The last 4 bytes of this would be a jump to the real reset function of your program so if the segment is loacted at e.g. 0xfd00, the last operation of your flash copy code (if nothing is to do or copying was successful) would be a jump at 0xfdfc where a (compilation dependent) jump to the reset function resides. As these jumps depend on the actual program version, they need to be refreshed with each new firmware version.

    It might be necessary to also catch the NMI vector into your flash copy function sgement, so if an NMI happens while copying, it can be eliminated.

    The main drawback of all this is the addition of some additional clock cycles on each and every interrupt. But it will be failsafe then.

    How to accomplish all this, well, I cannot tell for the IAR/CCE. Even on the mspgcc it isn't easy. The normal definition of an ISR with Pragma etc. won't work. On MSPGCC, one would define all real interrupt functions as of type NOVECTOR and then set up the dummy list in the jumptable segment by using the available function attributes and inline assembly:

    interrupt(NOVECTOR) timerahandler(void){...} // the real interrupt handler, placed anywhere in the lower 64k

    void __attribute__((interrupt (TIMER1_A0_VECTOR))) __attribute__((naked)) __attribute((segment(jumptable))) timera1entry(void) { __asm__ ("bra #timerahandler"::);} // the entry in the jumptable which will forward to the real handler.

    How to do this on IAR/CCE I don't know. One side effect: if you design your jumptable for 20 bit jumps, you can place your interrupt functions anywhere in the whole address range.

    Of course teh jump table needs to cover ALL vectors, since the automatic assignment of a dummy ISR for unused vectors will not work and if you add newer functions later, you already need the forwarfins (since the vector table stays unaltered)

     

    3)  you have two options. Either you just receive and store the unaltered .TXT file into flash and interpret it while copying, or you interpret it while receiving (just adding 0x10000 to all addresses) and make later just a 1:1 copy of the high memory content. It's up to you which way to go. But keep in mind that the plain TXT file might be much larger than the actual binary content while the interpteted data always matches the flash area in lower memory. In both cases you need to omit the 0xfe00-0xffff area, which will be included in yout .txt file (stupid file extension for something that is no human-readable content) but may not be written.

    Since interpreting teh .txt file takes more code than a plain copy, I would opt for your application receiving and interpreting the .txt file before writing the extracted content to 0x1xxxx (instead of 0x0xxxx as the @ address tells).

    The otehr question is already answered above: teh reset vector can only jump to an address in the lower 64k. So your flash copy function needs to be there (or at least a long jump to it). So why not placing it already there in the same 512 byte segment as the vector table? There are 384 bytes you cannot delete and flash without deleting the vector table too. So make use of them by placing your flash copy code there. 384 bytes are plenty for this job. After all, it is not complex and straightforward.

    p.s.: don't forget the WDT. It is enabled after a reset and you'll need to set it to something different than the default (but don't disable it! you want a reset in case something goes wrong) because erasing segments takes 32ms and this is in the range of the WDT timeout.

  • First of all,thank you again for your help.I still have a questions:

    1) As we've discussed above i need:

                              1) Reside "flash copy code" in low memory,for e.g. at 0x3100(for failsafe),because according to linker the main program code starts from 0x3500,therefore i have 0x3500 - 0x3100 = 1024bytes of free flash segments. Could i do it? Is it right?

                              2) Compile a current program code regulary in lower memory space(0x3500-0xFFBD); Is it right ?

                              2)Receiving(via UART/RF) new program code and  1:1 copy  the new code to high memory 0x10000-... Is it right?

                              3)When the new program code like this("@3500 31 40 00 31 B0 13 BE") is completed at high memory current program code could activate the reset by WDT; 

                              4)At reset code,will always activates "flash copy code" (0x3100 -0x3500). The "flash copy code" will check if high memory isn't EMPTY(not 0xFF).If high memory has a code,that starts like "@3500.....",the "flash copy code"  will read the data from high memory  and write the code to low memory according "@xxx" policy. The "flash copy code" will write to low memory until segment=0(FFC0-FFFF) with interrupt vector and reset vector.Therefore the segment=0(FFC0-FFFF) will never be erased. Please answer,i could do it???? So i don't need to resides a "jump" table with address of real ISR and reset functions. Or maybe i don't understand something.Because i didn't see,why i need to reside jump interrupt table.

    2) I think the code ".TXT" format should go to high memory AS IS.Why i need to change all addresses to 0x10... instead of 0x00 as in "@xxx". I willn't activate the code from high memory. High memory works as "new code container". Is it right? do you agree with me?

    Thanks,

     

     

  • 1.1 yes, you could do it. Provided you never overwrite 0x3100-0x3500, by restricting the linkers .text segment to 0x3500... you can place your flash copy code there. (it's not enough to just make an .org 0x3500 to place the code there. The linker must know that the usable flash area is limited or code could flow over and you'll not notice at compile time) But...

    1.2 no, you can only use 0x3500-0xfdff. 0xfe00-0xffff is a single flash segment. You can only erase it in a whole. All flash memory can only deleted in whole segments, the segment sizes are 128 bytes for the info flash and 512 bytes for the code flash. And it must be deleted before writing anything new to it. If you want to write something to 0xfe00, you'll need to erase the whole 0xfe00-0xffff area before, and with it the vector table. This is why I suggested placing the copy flash code in these 384 bytes, as you cannot use them otherwise. If you cannot fit the copy flash code into 384 bytes, enlarge its (linker) segment by another (flash) segment of 512 to 896 bytes and limit the normal (linker) .text segment to the 0x3100-0xfbff area.

    1.3 Yes, you can. But see 2). You can either initiate a reset, or directly call it (with a BRA #0x3100 or BRA #0xFE00 command, depending of the location you finally chose). You can also make a BRA &FFFE which should jump to the reset vector (will take the word value at address 0xfffe, the reset vector, and use it as destination for the jump)

    1.4 that's not exactly true.
    First (as explained in 1.2) the area that may not be deleted is 0xfe00-0xffff, as it can only be erased as a whole and must be erased before parts of it can be rewritten.
    Then, it is NOT sufficient to just check whether high memory is empty. What if receiving of the update was interrupted in the middle? Then high memory isn't empty but also invalid as it contains an incomplete update. You'll need to at least set a marker that tells that the transmission was complete and verified.
    You'll need the jump table at a fixed (never changing) address since it is unlikely that on every compilaton run the addresses of all of your ISRs don't change. To keep the vector table constant, so it doesn't need to be erased and rewritten (which is what we want to make the thing failsafe), its entries must point to a constant place. And since your ISRs will surely move over time with every new feature or bugfix (why else providing updates at all?), you'll need this jumptable as fixed entry point.
    The table will always be at the same place, but will be rewritten on each program update, so its entries point to the updated locations of your ISRs. The only entries of the vector table which do not point into this jumptable will be the reset vector (pointing to the also fixed flash copy code) and maybe the NMI vector (pointing to a dummy handler or so), as these are the only interrupts being possibly happen while the program memory is erased. All others can be disabled using DINT().

    2. You can do it as you want. Of course, if you store the .txt file 'as is', you don't need to change the addresses. I was talking about what to do if you interpret it at reception and store binary values in high memory. If doing so, a @3500 command should result in writing the binary data following it to 0x13500 and not 0x03500. That is what I meant. No need to alter the addresses in the original format. :)
    You should, however, consider, that storing the .txt in its original format requires more than thrice the space. Each byte in the final program code is represented by three bytes (2 digits and a space). Plus linefeeds/CRs and the @ commands.
    So storing a .txt file for a program that uses the full 50k of lower flash would require >150k of upper flash to be stored. Plus it takes a bit of additional time (albeit small, compared to the time to flash the code), to decode the file after reset, wehn the device is not operating normally but busy updating.

    So my suggestion is to interpret the incoming .txt file as it streams in, following its commands, but adding 0x10000 to the destination, so after the complete file has been received, allis in 0x1xxxx as it should be later in 0x0xxxx. If all is received, then, for example, go and write #0 to 0x1fffe. This will never happen accidentally in a compilateion (the reset vector which will be there after receiving the update) will never point to 0x0000 on an MSP) and IF, after reset, your flash copy code detects it containing #0, it knows that the update data has been received completely and properly. If it is something else, it is invalid and the old firmware should be started for a new attempt.

    Just for clarification:
    Above I said that flash needs to be erased in whole segments before you can write to it. That's not exactly true. You can only write '0' bits into flash. ever. So if a flash memory bit contans a '1', you can change it to a '0'. But you cannot write a '1' to a cell that already contains a '0'. Therefore you can always change 0x1fffe to #0, no matter what it was before (you will not copy this part of the update anyways, as it should be the same vector table that is already in lower mem). There is a limit how often you can do a write to any memory location inside a flash sector before you MUST erase it (or it will deliver unreliable data). It depends on writing algorithm (byte/word/dword or block write). Actually, a certain 'programming time' since the last erase may not be exceeded for all bytes in a segment together. But it is safe to 'overwrite' a few bytes of a segment after they have been already programmed once. Only that you cannot overwrite them with '1'-bits. You can only set a bit from 0 back to 1 by erasing the whole flash segment where it resides in.

     

**Attention** This is a public forum