This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Code Loader Issues

All,
We are designing a "loader" for field firmware updates. Unfortunately we do not have the code space (P89C668) to have two sets of code in on-chip flash. Therefore we will use a scheme where we have the loader code located in sector one and all the ISRs in sector zero as the loader will use interrupts. The rest of the application will be in sectors 2 and up.

The loader will erase the upper sectors and program the new code there. It will then erase sector zero and reprogram the vector table and the ISRs. Block one, the loader, will remain unchanged.

Questions:
I think I can locate the code in sector one and the ISRs in sector zero using user classes. I have done this with some ARM code in uVision. How can I be sure that the loader will have all the run-time modules it needs in sector zero? In other words, I cannot have the loader calling code in sectors that have been erased. It will have to be completely self contained except for the ISRs.

Is this a reasonable plan? Anyone have a better way to do this?

Rich

  • DO visualize wha will happen with your scheme if power fail at any time during the process.

    I have seen more dead chips due to this than anything else.

    If you decide to go ahead with a scheme where such can happen, at least socket your processor.

    Erik

  • Without the space to duplcate the code there is not much option.

  • then why not use NoTouch and the ISP

    Erik

  • The units are potted and on a 485 bus.

  • ,i>The units are potted and on a 485 bus.
    on all such bopards, I have a connector to a "remote" MAX232equivalent just for ISP.

    Erik

  • When installed, the units are not accessible.

  • But the connectot I suggest will be

  • But the connector I suggest will be

  • Erik, are you helping? ;-) Actually I appreciate the replies. The plan du jour is to have the loader in one sector which does not use interrupts or libaries. When the loader starts the BV is changed to the loader entry, that way, if power should fail etc, we end up back in the loader. Once the loader has downloaded and verified all code we reprogram the BV to FC in case we need ISP in the future. Then we let the WDT timeout. The units are not acessible at all, only the network is.

    Rich

  • We have the same problem in a number of products. Our solution is to put the boot loader and the interrupt vectors in the first part of memory ... in our case the first 4k.

    We have the application start at 0x1000, while the Boot starts at 0x100, the interrupt vector processing is the only code at 0. Do this by relocating the interrupt vectors (see C51 TAB in uVision) and changing the StartUp.A51. We reserve an unused interrupt vector block in the application to keep a checksum that is generated by the Boot after successful download.

    The actual interrupt code uses the same scheme that RTX uses ... ie. we set a bit (RTX uses F0) to indicate that we are in the boot. If an interrupt occurs while in the boot, we use an AJMP to 0x103 + (8*Int#). If an application interrupt occurs we do a LJMP to 0x1003 + (8*Int#). The two jumps and the JNB InBootBit all fit in the standard 8 byte interrupt vector slot.

    When the processor is reset, the Boot executes first and jumps to 0x1000 if the application checksum is valid. If not it simply waits for download.

    In this manner, the boot is really simple and handles the TxEnable and any other special stuff.

  • that way, if power should fail etc, we end up back in the loader

    As long as you have that the rest should be easy.

    This is THE most important loader feature.

    Erik

  • Do this by relocating the interrupt vectors (see C51 TAB in uVision) and changing the StartUp.A51.

    A "window" for failure.

    The "relocating" consist of storing LJMPs in the page zero slots and if power fail during that process, you are screwed.

    Erik

  • No it doesn't. The vectors are constants that are never overwritten. Only the application code is erased ... thus invalidating the application checksum.

  • Do this by relocating the interrupt vectors ....
    A "window" for failure. "relocating" consist of storing LJMPs in the page zero slots and if power fail during that process, you are screwed. ....
    No it doesn't. The vectors are constants that are never overwritten.



    In order to have a "different interrupt vector" or "ISR location" you MUST write to e.g. address 3 or somewhere that is addressed by whatever it vectors to.

    There is NO WAY you can change the processing of an interrupt from "loader" to "application" without writing something affecting the interrupt path to code memory. And even the best engineered such change can fail with power loss.

    You can not change interrupts between the loader and the app without risking access loss.

    Erik

  • Sometimes code is worth a thousand words.

    We use three modules:
    1) FakeInts ... shown below
    2) The boot loader
    3) The application

    The boot loader has it's interrupt vectors starting at 0x100. The application has it's starting at 0x1000.

    After initial programming of FakeInts and BootLoad, they are "never" changed.

    The FakeInts source is shown below:

    ;------------------------------------------------------------------------------
    ;  FakeInts.a - Dummy Interrupt vectors for the Universal DownLoad Program
    ;------------------------------------------------------------------------------
    ;  To translate this file use A51 with the following invocation:
    ;
    ;     A51 FakeInts.A
    
    
    DnlBase Equ     0100H           ; DownLoader base address
    AppBase Equ     1000H           ; Application base address
    
            CSEG    AT 0
            Ljmp    DnlBase         ; Start application
    
    
    IntVect Macro   Num
            CSEG    AT 8*Num+3
            Jnb     F0,$+5
            Ajmp    DnlBase+(8*Num+3)
            Ljmp    AppBase+(8*Num+3)
            Endm
    
            IntVect 0               ; INT0 - External Interrupt
            IntVect 1               ; T0 - Timer 0 Interrupt
    
            IntVect 2               ; INT1 - External Interrupt
            IntVect 3               ; T1 - Timer 1 Interrupt
    
            IntVect 4               ; SP - Serial Port Interrupt
            IntVect 5               ; T2 - Timer 2 Interrupt
    
    ;   Modify from here on as needed for your microprocessor specific interrupts
    
    
            IntVect 6               ; PCA - Programmable Capture Array Interrupt
    
            End