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.

Boot loader question

Other Parts Discussed in Thread: CONTROLSUITE

I have an application that I am writing that will live in sectors E and D of FLASH on the 28335 chip.  I am writing a separate application that resides in sector A that will act as a boot loader.  I have tested the boot loader application and it appears to do everything that I want except jump to the application in sector E.  These applications are completely independent and share no code.

 

From what I have read, the answer must lie somewhere in the cmd file and/or the boot.asm file.  My boot.asm file calls a function loader_main() that does everything I want the boot loader to do.  When it exits I want the code to jump to my main application in sector E.  I do not know assembly well enough.  I would appreciate help and example code if possible.  Thanks.

  • I am ending up in ITRAP.  I know that my boot loader is executing and exiting loader_main().  My main application has codestart set at 0x318000 in its cmd file. 

    My boot loader boot.asm file looks like this:

    ***********************************************************************
    * Function: Boot section
    *
    * Description: Bootup starts here. If the application space is valid,
    *              launch. Otherwise revert to a reporgramming mode.
    ***********************************************************************

        .sect "bootvector"

    boot_vector:
        LB boot_process       ;Branch to watchdog disable code

        .sect "bootme"

    boot_process:    
        SETC OBJMODE        ;Set OBJMODE for 28x object code
        EALLOW              ;Enable EALLOW protected register access
        MOVZ DP, #7029h>>6  ;Set data page for WDCR register
        MOV @7029h, #0068h  ;Set WDDIS bit in WDCR to disable WD
        EDIS                ;Disable EALLOW protected register access

    copy_secureramfuncs:
        MOVL XAR5,#_secureRamFuncs_size        ; Store section size in XAR5
        MOVL ACC, @XAR5                ; Move section size to ACC
        MOVL XAR6,#_secureRamFuncs_loadstart    ; Store load starting address in XAR6
        MOVL XAR7,#_secureRamFuncs_runstart    ; Store run address in XAR7

        B copy_FlashAPI,EQ                ; Return if the ACC is zero (No section to copy)
        RPT AL                    ; Copy section from load address to
        || PWRITE *XAR7,*XAR6++    ; run address

    copy_FlashAPI:
        MOVL XAR5,#_Flash28_API_Size        ; Store section size in XAR5
        MOVL ACC, @XAR5                ; Move section size to ACC
        MOVL XAR6,#_Flash28_API_LoadStart    ; Store load starting address in XAR6
        MOVL XAR7,#_Flash28_API_RunStart    ; Store run address in XAR7

        B finish,EQ                ; Return if the ACC is zero (No section to copy)
        RPT AL                    ; Copy section from load address to
        || PWRITE *XAR7,*XAR6++    ; run address

    finish:
        LCR _loader_main    ;run the boot loader
        SETC INTM;
        ZAPA;
        MOV @SP,#0;
        PUSH ACC;
        PUSH AL;
        MOV AL, #0x0a08;
        PUSH AL;
        MOVL XAR7, #0x318000;
        PUSH XAR7;
        POP RPC;
        POP ST1;
        POP ST0;
        POP IER;
        POP DBGIER;
        LRETR; 
        .end

  • Christopher Taylor said:
    copy_secureramfuncs:
        MOVL XAR5,#_secureRamFuncs_size        ; Store section size in XAR5
        MOVL ACC, @XAR5                ; Move section size to ACC

     

    Christopher Taylor said:

    copy_FlashAPI:
        MOVL XAR5,#_Flash28_API_Size        ; Store section size in XAR5
        MOVL ACC, @XAR5                ; Move section size to ACC

    Christoper

    One thing I noticed is XAR5 is being used for both the size of the secure RAM functions and also the flash API - but I don't see anything that sets the value in XAR5 or changes it between the two copies?  

    If you endup in an itrap then my hunch is one of the copies is not working correctly.  When the function is called an invalid opcode is found and you go to an ITRAP.   You can look at the stack or return from the ITRAP to reason out how you got there.

    Some information on itrap here that may be useful:  http://processors.wiki.ti.com/index.php/Interrupt_FAQ_for_C2000#The_ITRAP_Interrupt

    Cheers,

    Lori

  • Thanks Lori.  I will look into this.  This code does appear to be working because my loader_main function is running and working as expected.  It is after the function ends that I have the issue.  This same code snippet is used in other applications with no issue.  That being said, I am not very literate when it comes to assembly so I need to do my research first and make sure that the code is doing what I was told that it is doing.  The intent of that section of code is to replace using memcpy in the c code.  Thanks.

  • Christopher Taylor said:
       SETC INTM;
        ZAPA;
        MOV @SP,#0;
        PUSH ACC;
        PUSH AL;
        MOV AL, #0x0a08;
        PUSH AL;
        MOVL XAR7, #0x318000;
        PUSH XAR7;
        POP RPC;
        POP ST1;
        POP ST0;
        POP IER;
        POP DBGIER;
        LRETR; 

    I'm a bit confused about this code snippet.

    I would double check that the stack was even aligned before this - otherwise the mixing of 32-bit and 16 bit push can cause issues.

    I understand 0x318000 is going into RPC.  0x0a08 into ST1.  

    My question is what is ACC before this routine?   Since I don't see anything loaded into ACC I'm not sure what values are going into ST0, IER and DBGIER.

    Here is the exit routine that we use in the boot ROM - where it transfers control to the main application.  The address of the place we want to jump to is in ACC before this is called - ie your case you would call it with  ExitBoot(0x318000)

     

    ;-----------------------------------------------
    ; _ExitBoot
    ;-----------------------------------------------
    ;-----------------------------------------------
    ;This module cleans up after the boot loader
    ;
    ; 1) Make sure the stack is deallocated.
    ;    SP = 0x400 after exiting the boot
    ;    loader
    ; 2) Push 0 onto the stack so RPC will be
    ;    0 after using LRETR to jump to the
    ;    entry point
    ; 2) Load RPC with the entry point
    ; 3) Clear all XARn registers
    ; 4) Clear ACC, P and XT registers
    ; 5) LRETR - this will also clear the RPC
    ;    register since 0 was on the stack
    ;-----------------------------------------------

    _ExitBoot:

    ;-----------------------------------------------
    ;   Insure that the stack is deallocated
    ;-----------------------------------------------

        MOV SP,#__stack

    ;-----------------------------------------------
    ; Clear the bottom of the stack.  This will endup
    ; in RPC when we are finished
    ;-----------------------------------------------

        MOV  *SP++,#0
        MOV  *SP++,#0

    ;-----------------------------------------------
    ; Load RPC with the entry point as determined
    ; by the boot mode.  This address will be returned
    ; in the ACC register.
    ;-----------------------------------------------

        PUSH ACC
        POP  RPC

    ;-----------------------------------------------
    ; Put registers back in their reset state.
    ;
    ; Clear all the XARn, ACC, XT, and P and DP
    ; registers
    ;
    ; NOTE: Leave the device in C28x operating mode
    ;       (OBJMODE = 1, AMODE = 0)
    ;-----------------------------------------------
        ZAPA
        MOVL  XT,ACC
        MOVZ  AR0,AL
        MOVZ  AR1,AL
        MOVZ  AR2,AL
        MOVZ  AR3,AL
        MOVZ  AR4,AL
        MOVZ  AR5,AL
        MOVZ  AR6,AL
        MOVZ  AR7,AL
        MOVW  DP, #0

    ;------------------------------------------------
    ;   Restore ST0 and ST1.  Note OBJMODE is
    ;   the only bit not restored to its reset state.
    ;   OBJMODE is left set for C28x object operating
    ;   mode.
    ;
    ;  ST0 = 0x0000     ST1 = 0x0A0B
    ;  15:10 OVC = 0    15:13      ARP = 0
    ;   9: 7  PM = 0       12       XF = 0
    ;      6   V = 0       11  M0M1MAP = 1
    ;      5   N = 0       10  reserved
    ;      4   Z = 0        9  OBJMODE = 1
    ;      3   C = 0        8    AMODE = 0
    ;      2  TC = 0        7 IDLESTAT = 0
    ;      1 OVM = 0        6   EALLOW = 0
    ;      0 SXM = 0        5     LOOP = 0
    ;                       4      SPA = 0
    ;                       3     VMAP = 1
    ;                       2    PAGE0 = 0
    ;                       1     DBGM = 1
    ;                       0     INTM = 1
    ;-----------------------------------------------

        MOV  *SP++,#0
        MOV  *SP++,#0x0A0B
        POP  ST1
        POP  ST0

    ;------------------------------------------------
    ;   Jump to the EntryAddr as defined by the
    ;   boot mode selected and continue execution
    ;-----------------------------------------------

        LRETR

    ;eof ----------

  • One other thought.  In the restore of ST0 I notice the INTM and DBGM bits are clear.  This means interrupts are enabled.  This may well be intended but if it was not, then perhaps an unintended interrupt is being called.

    -Lori

  • Thanks Lori.  I now see my boot loader jumping to 0x318000.  It appears now that even though I set the tcf file for the code start of my main application to be 0x318000 the code start is not there.  There is code in memory.  How can I determine where the actual code start is?

  • Christopher Taylor said:
    Thanks Lori.  I now see my boot loader jumping to 0x318000.  It appears now that even though I set the tcf file for the code start of my main application to be 0x318000 the code start is not there.  There is code in memory.  How can I determine where the actual code start is?

    The compiler generates a file with a .map extension.  It is typically in the Debug directory.  This file has all of the symbols and where they resolved to.  Inspecting this file can tell you where everything is located.

    You can fix the location of a particular section by assigning it to a named section (using the CODE_SECTION pragma if in C www.ti.com/lti/spru514) and placing that section in the linker command file (www.ti.com/spru513).

    Cheers,

    Lori

  • Thanks Lori.  Let me know if this makes sense:

     

    1.  Boot loader app will reside at 0x300000.  It will be written by the JTAG once and then never touched.  The boot loader will receive a new application and burn it to FLASH or load the existing application on FLASH.

    2.  The main application will reside at 0x318000 with codestart set at APP_ENTRY (0x318000 size 0x000002) and application data at 0x318002.

    3.  Both of the applications are completely independent applications built in separate workspaces.

     

    The only thing I saw in the .map file for the main application was the address of c_int00.  Is this what I am supposed to be using?  Is there a vector table I am missing?

     

  • I think a big part of my problem is that the two projects are completely independent of each other.  Every example that I have seen shows the boot loader as being compiles as part of the same project as the main application.  is there any example code available to do what I want to do?

  • Christopher Taylor said:

    I think a big part of my problem is that the two projects are completely independent of each other.  Every example that I have seen shows the boot loader as being compiles as part of the same project as the main application.  is there any example code available to do what I want to do?

    The TI boot ROM code is an example of this.  You can find the code in controlSUITE (www.ti.com/controlsuite).   C:\TI\controlSUITE\libs\utilities\boot_rom is the default install location. 

    The boot ROM always jumps to a specific location in the flash. 

    The user is required to program a branch instruction at that location to redirect the code flow to their own application.   The goal is to get to the c initialization of the user's application.   

    boot exit -> flash entry address (fixed) -> branch to any custom assembly for boot (disable watchdog for example) -> branch to the c-startup (cinit00 you mentioned before).

    The branches we added are not required, but we wanted to make it easy to have one clear entry point into flash so we chose to do it in this manner.   Most, if not all, of our examples have a assembly file called codestartbranch that includes the redirection branch.  This is linked into the BEGIN section in the linker command file.

    In the Delfino workshop - chapter 4 there is a reset flow that shows how the boot ROM exits to flash.  This may help.

    http://processors.wiki.ti.com/index.php/C2000_Delfino_Multi-Day_Workshop

    Regards,

    Lori

     

     

  • hello, Christopher Taylor

    I'm doing the same things as you. but i'm not familiar with assembly language. and how does you organize your project?

    could you please shared or explain some of your code?

    thanks very very  much!

  • The main is pretty much normal.  There is a function at the end to look at.  We have a message come over the CANBUS to tell us to either update firmware or start the application.

    void

    main(void)

    {

    // if the reset was due to a watchdog reset then clear the watchdog

    if ((SysCtrlRegs.WDCR & 0x0080) != 0)

    {

    EALLOW;

    SysCtrlRegs.WDCR |= 0x00A8;

    EDIS;

    }

    // due to errata on the chip in regards to XINTF we need to perform a watchdog reset on a

    // cold boot

    else

    {

    EALLOW;

    SysCtrlRegs.WDCR= 0x0040;

    EDIS;

    }

    MemCopy(&Flash28_API_LoadStart, &Flash28_API_LoadEnd, &Flash28_API_RunStart);

    // Initialize System Control:

    // PLL, WatchDog, enable Peripheral Clocks

    // This example function is found in the DSP2833x_SysCtrl.c file.

    InitSysCtrl();

    // Initialize the on-chip flash registers

    InitFlash();

    // Initialize the on-chip GPIOs

    InitializeGPIO();

    // initialize the external RAM

    InitXintf();

    // initialize the canbus and start comms

    PF239ServerInit();

    PF239ClientInit();

    PF255ServerInit();

    g_exitBootLoader = FALSE;

    CANInit();

    // Clear all interrupts and initialize PIE vector table:

    // Disable CPU interrupts

    DINT;

    // Initialize the PIE control registers to their default state.

    // The default state is all PIE interrupts disabled and flags

    // are cleared.

    // This function is found in the DSP2833x_PieCtrl.c file.

    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:

    IER = 0x0000;

    IFR = 0x0000;

    // Initialize the PIE vector table with pointers to the shell Interrupt

    // Service Routines (ISR).

    // This will populate the entire table, even if the interrupt

    // is not used in this example. This is useful for debug purposes.

    // The shell ISR routines are found in DSP2833x_DefaultIsr.c.

    // This function is found in DSP2833x_PieVect.c.

    InitPieVectTable();

    // Interrupts that are used in this example are re-mapped to

    // ISR functions found within this file.

    EALLOW;

    // This is needed to write to EALLOW protected registers

    PieVectTable.TINT0 = &cpu_timer0_isr;

    PieVectTable.ECAN1INTB = &CANRx_ISR;

    EDIS;

    // This is needed to disable write to EALLOW protected registers

    // Initialize the Device Peripheral. This function can be

    // found in DSP2833x_CpuTimers.c

    InitCpuTimers();

    // For this example, only initialize the Cpu Timers

    // Configure CPU-Timer 0, 1, and 2 to interrupt every 01. micro second:

    // 150MHz CPU Freq, 100 Period (in uSeconds)

    ConfigCpuTimer(&CpuTimer0, 150, 100);

    // To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any

    // of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in DSP2833x_CpuTimers.h), the

    // below settings must also be updated.

    CpuTimer0Regs.TCR.all = 0x4001;

    // Use write-only instruction to set TSS bit = 0

    // Enable CPU int1 which is connected to CPU-Timer 0

    IER |= M_INT1;

    // Enable TINT0 in the PIE: Group 1 interrupt 7

    PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

    /* CAN Recieve Interrupt config -start */

    PieCtrlRegs.PIEIER9.bit.INTx8 = 1;

    // Enable CPU interrupt for the CANBUS

    IER |= 0x0100;

    // Enable global Interrupts and higher priority real-time debug events:

    EINT;

    // Enable Global interrupt INTM

    ERTM;

    // Enable Global realtime interrupt DBGM

    SetupFlashAPI();

    // Validate the image

    if (ChecksumVerify(FLASH_SECTOR_C,FLASH_SECTOR_F)!= STATUS_SUCCESS)

    {

    g_firmwareValid = FALSE;

    g_firmwareVersion = BOOT_MODE | 0xffffff;

    }

    else

    {

    g_firmwareValid = TRUE;

    g_firmwareVersion = BOOT_MODE | FIRMWARE_VALID | 0xffffff;

    }

    // IDLE loop. Just sit and wait

    while(g_exitBootLoader == FALSE);

    jumpApp();

    }

    static

    void jumpApp(void)

    {

    InitPieCtrl();

    //zero all the core IERs

    IER = 0;

    IFR = 0;

    entryAddress = (Uint32*)ENTRY_ADDRESS;

    entry_point = (

    void(*)(void))*entryAddress;

    entry_point();

    }

  • thank you very much! Christopher Taylor

     i still have some problem, because i just strat studying on this;

    the only difference between your whole project and my project is the way of transmit(your:CAN / MY:SCI )

    1. I don't know what's the detailed function of the assembly code! could you explain it for me? why not just let the boot  procedure as:  _c_int00—> boot_main()?  but : asm_code—>_c_int00—> boot_main()

    2. what is the whole procedure of our project?  and what's every parts function in your project?

    3. I want to put bootloader in sectorA(0x338000), and My Application in SectorB(0x330000), can I just write

    asm("   LB 0x330000")  to jump to My Application program?

    4. and when my app receive the SCI instruction for update firmware, how to jump to my bootloader?

    a bit more problem ah? I know you are familiar this,  Thanks a lot !