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.

Compiler/TMS320F28035: Custom Exit Routine Not Being Executed In boot28.asm

Part Number: TMS320F28035

Tool/software: TI C/C++ Compiler

I am trying to write a CAN bootloader routine. The CAN bootloader is finished, it accepts memory and flashes fine. I am basing my switch to application code on the f2803x_flash_kernel code where on reset it will check for data at the application code entry and if there is anything there will return the code entry address from main. My issue is after main() returns, my exit function (same as the ExitBoot in f2803x_flash_kernel) is not being called. It skips over my exit routine and calls the standard exit which ends on an infinite loop. The boot28.asm is from the c2000_16.9.2 compiler code. I added the assembly "BF _exit_boot,UNC" with the .global and .asg defined. Any idea why my function is being skipped? I have included my code below. Thanks.

;******************************************************************************
;* BOOT  v16.9.2
;* 
;* Copyright (c) 2000-2017 Texas Instruments Incorporated
;* http://www.ti.com/ 
;* 
;*  Redistribution and  use in source  and binary forms, with  or without
;*  modification,  are permitted provided  that the  following conditions
;*  are met:
;* 
;*     Redistributions  of source  code must  retain the  above copyright
;*     notice, this list of conditions and the following disclaimer.
;* 
;*     Redistributions in binary form  must reproduce the above copyright
;*     notice, this  list of conditions  and the following  disclaimer in
;*     the  documentation  and/or   other  materials  provided  with  the
;*     distribution.
;* 
;*     Neither the  name of Texas Instruments Incorporated  nor the names
;*     of its  contributors may  be used to  endorse or  promote products
;*     derived  from   this  software  without   specific  prior  written
;*     permission.
;* 
;*  THIS SOFTWARE  IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS
;*  "AS IS"  AND ANY  EXPRESS OR IMPLIED  WARRANTIES, INCLUDING,  BUT NOT
;*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
;*  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
;*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
;*  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL  DAMAGES  (INCLUDING, BUT  NOT
;*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
;*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;*  THEORY OF  LIABILITY, WHETHER IN CONTRACT, STRICT  LIABILITY, OR TORT
;*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;* 
;******************************************************************************

;****************************************************************************
;* BOOT.ASM
;*
;* THIS IS THE INITAL BOOT ROUTINE FOR C28xx C++ PROGRAMS.
;* IT MUST BE LINKED AND LOADED WITH ALL C++ PROGRAMS.
;* 
;* THIS MODULE PERFORMS THE FOLLOWING ACTIONS:
;*   1) SET RESET VECTOR TO POINT AT _C_INT00
;*   2) ALLOCATES THE STACK AND INITIALIZES THE STACK POINTER
;*   3) SET UP PROPER STATUS
;*   4) PERFORMS AUTO-INITIALIZATION
;*   5) CALLS INITALIZATION ROUTINES FOR FILE SCOPE CONSTRUCTION
;*   6) CALLS THE FUNCTION MAIN TO START THE C++ PROGRAM
;*   7) CALLS THE STANDARD EXIT ROUTINE
;*
;* THIS MODULE DEFINES THE FOLLOWING GLOBAL SYMBOLS:
;*   1) __stack     STACK MEMORY AREA
;*   2) _c_int00    BOOT ROUTINE
;*
;****************************************************************************
CONST_COPY	.set 0
        .if __TI_EABI__
           .asg _args_main, __args_main
           .asg exit, _exit, _exit_boot
           .asg copy_in, _copy_in
           .asg _system_pre_init, __system_pre_init
           .asg _system_post_cinit, __system_post_cinit
           .global __TI_auto_init
        .endif

	.global  _c_int00, cinit, binit, pinit
	.global  __args_main, _exit, _copy_in, _exit_boot
        .global  __system_pre_init, __system_post_cinit
	.global  __stack

****************************************************************************
* Declare the stack.  Size is determined by the linker option -stack.  The *
* default value is 1K words.                                               *
****************************************************************************
__stack:	.usect	".stack",0

****************************************************************************
*  INITIALIZE RESET VECTOR TO POINT AT _c_int00                            *
****************************************************************************
	.sect .reset
	.long _c_int00

	.text
****************************************************************************
* FUNCTION DEF : _c_int00                                                  *
*                                                                          *
****************************************************************************

_c_int00:	.asmfunc stack_usage(0)
****************************************************************************
*  INITIALIZE STACK POINTER.                                               *
****************************************************************************
	MOV  	SP,#__stack		; set to beginning of stack space

****************************************************************************
* INITIALIZE STATUS BIT FIELDS *NOT* INITIALIZED AT RESET                  *
****************************************************************************
	SPM	0			; set product shift to 0

****************************************************************************
* SET C28x MODES                                                           *
****************************************************************************
        C28OBJ                          ; select C28x object mode
        C28ADDR                         ; clear the addressing mode
        C28MAP                          ; set block M0 and M1 mode

        .if .TMS320C2800_FPU32
        SETFLG            RNDF32=1      ; Enable rounding in FPU32 mode.
        .endif
****************************************************************************
* SETTING THESE STATUS BITS/REGISTER TO RESET VALUES.  IF YOU RUN          *
* _c_int00 FROM RESET, YOU CAN REMOVE THIS CODE                            *
****************************************************************************
	CLRC    PAGE0			; use stack addressing mode
        MOVW    DP,#0			; initialize DP to point at low 64K
	CLRC    OVM         		; turn off overflow mode

	ASP				; ensure SP is aligned

****************************************************************************
*  IF _system_pre_init is 0, bypass C/C++ autoinitialization               *
****************************************************************************
	LCR	#__system_pre_init
	CMP	AL, #0
	B	BYPASS_AUTO_INIT, EQ ; Branch if _system_pre_init returns 0

        .if     __TI_EABI__
        LCR #__TI_auto_init
        .else

****************************************************************************
* SET THE EALLOW BIT BEFORE THE CINIT TABLE IS COPIED.                     *
****************************************************************************
	EALLOW

****************************************************************************
*  IF cinit IS NOT -1, PROCESS CINIT INITIALIZATION TABLE	           *
****************************************************************************
	MOV	AL,#cinit
	MOV	AH,#hi16(cinit)
	ADDB	ACC,#1
	B	DO_BINIT,EQ		; if cinit < 0 (-1) no init tables

****************************************************************************
*  PROCESS CINIT INITIALIZATION TABLE.  TABLE IS IN PROGRAM MEMORY IN THE  *
*  FOLLOWING FORMAT:                                                       *
*                                                                          *
*       .word  <length of init data in words>                              *
*       .word  or .long <address of variable to initialize>                *
*       .word  <init data>                                                 *
*       .word  ...                                                         *
*                                                                          *
*  If the variable's address is greater than 65535 (located in 'far'       *
*  memory), then the address field of the cinit record will be 32-bits     *
*  instead of the default 16-bits. The length value is negated to tag      *
*  cinit records for those variables located in far memory.                *
*                                                                          *
*  The init table is terminated with a zero length                         *
*                                                                          *
****************************************************************************
	MOVL	XAR7,#cinit		; point XAR7 at start of table	
	CLRC    TC		        ; reset TC bit used as far flag 
	B 	START, UNC		; jump to start processing
LOOP:
	MOVB    AH,#0		        ; zero out upper addr bits
	PREAD   AL,*XAR7		; load address of variable to be inited
	ADDB    XAR7,#1			; point to initialization data
       	B	GET_DATA,NTC	        ; get data if variable is not far 
	CLRC    TC		        ; reset TC bit used as far flag 
	PREAD   AH,*XAR7	        ; otherwise, get hi bits of 22-bit addr
	ADDB    XAR7,#1
GET_DATA:	
	MOVL	XAR6,ACC	        ; address
	RPT	AR1			; repeat length + 1 times
||	PREAD   *XAR6++,*XAR7		; copy data from table to memory
	
	MOVL	ACC,XAR7		; using ACC as temp, point XAR7 to 
	ADD  	ACC,AR1			; next cinit record since PREAD 
	ADDB	ACC,#1			; doesn't change value of XAR7. 
	MOVL	XAR7,ACC	
START:
	PREAD	AL,*XAR7		; load length
	B	GET_ADDR,GEQ	        ; a length < 0 denotes far data	 
        NEG     AL		        ; negate value to get real length	
	SETC    TC		        ; flag that the address field is 32-bits
GET_ADDR:	
	MOVZ	AR1,AL		        ; copy length value to loop register
        ADDB    XAR7,#1			; point to address field
	BANZ	LOOP,AR1--		; if (length-- != 0) continue 

****************************************************************************
*  IF binit IS NOT -1, PROCESS CINIT INITIALIZATION TABLE	           *
****************************************************************************
DO_BINIT:
	MOV	AL,#binit
	MOV	AH,#hi16(binit)
	ADDB	ACC,#1
	B	DO_PINIT,EQ		; if binit < 0 (-1) no init tables
	MOVL	XAR4,#binit
	LCR	#_copy_in

****************************************************************************
*  IF pinit IS NOT -1, PROCESS CONSTRUCTOR ROUTINES                        *
****************************************************************************
DO_PINIT:			

****************************************************************************
* CLEAR THE EALLOW BIT AFTER THE CINIT TABLE IS COPIED.                    *
****************************************************************************
	EDIS

****************************************************************************
* Call the startup hook function.                                          *
****************************************************************************
        LCR     #__system_post_cinit

	MOV	AL,#pinit
	MOV	AH,#hi16(pinit)
	ADDB	ACC,#1
	B	DONE_INIT,EQ		; if pinit < 0 (-1) no pinit table

****************************************************************************
*  PROCESS PINIT SECTION. TABLE CONSISTS OF CONSTRUCTOR ROUTINE ADDRESSES  *
*  THAT POINT TO C++ INITIALIZATION FUNCTIONS. THESE ROUTINES MUST EXECUTE *
*  BEFORE MAIN IS CALLED                                                   *
****************************************************************************
	MOVL    XAR7,#pinit	        ; set up pointer to initialization table
	B	START_PINIT, UNC        ; jump to start processing

LOOP_PINIT:	
	ADDB    XAR7,#1			; point to next table entry	
	PUSH	XAR7			; save off table entry address 
	MOVL	XAR7,ACC		; load constructor routine address
	LCR     *XAR7			; execute routine
	POP	XAR7			; reload table entry address 
	
START_PINIT:	
	PREAD   AL,*XAR7	        ; unpack constructor routine address 
	ADDB    XAR7,#1		
	PREAD   AH,*XAR7	
	TEST	ACC			; test for table end condition (zero)	
	B	LOOP_PINIT,NEQ		; process table entry if not zero
	
	
****************************************************************************
*  COPY CONSTANTS TO DATA MEMORY, IF NECESSARY                             *
****************************************************************************
DONE_INIT:
	.if CONST_COPY
        LCR	_const_init
	.endif

        .endif  ; __TI_EABI__
BYPASS_AUTO_INIT:
****************************************************************************
*  CALL USER'S PROGRAM                                                     *
****************************************************************************
	LCR     __args_main			; execute main()
	BF 		_exit_boot,UNC
	LCR  	_exit
	.endasmfunc

	.if CONST_COPY

****************************************************************************
* FUNCTION DEF : __const_init                                              *
*                                                                          *
*  COPY .CONST AND .ECONST SECTION FROM PROGRAM TO DATA MEMORY             *
*                                                                          *
*   The function depends on the following variables                        *
*   defined in the linker command file                                     *
*                                                                          *
*   __c_load         ; global var containing start                         *
*                      of .const in program memory                         *
*   __const_run      ; global var containing run                           *
*                      address in data memory                              *
*   __const_length   ; global var length of .const                         *
*                      section                                             *
*                                                                          *
*                                                                          *
*   Similarly for constants to be placed into extended memory (far):       *
*                                                                          *
*   __ec_load         ; global var containing start                        *
*                      of .econst in program memory                        *
*   __econst_run      ; global var containing run                          *
*                      address in data memory                              *
*   __econst_length   ; global var length of .econst                       *
*                      section                                             *
*                                                                          *
****************************************************************************
        .global __const_length,  __c_load,  __const_run
        .global __econst_length, __ec_load, __econst_run
 
        .sect ".c_mark"              ; establish LOAD adress of
        .label __c_load              ; .const section
 
        .sect ".ec_mark"              ; establish LOAD adress of
        .label __ec_load              ; .econst section
 
        .text
_const_init:	.asmfunc stack_usage(2)
 
        MOV     AL,#__const_length
        B       __econst_init,EQ
        DEC     AL
        MOVL    XAR6,#__const_run
        MOVL    XAR7,#__c_load
        RPT     AL
||      PREAD   *XAR6++,*XAR7
 
__econst_init:
        MOVL    XAR6, #__econst_length
        MOVL    ACC,XAR6
        B       __end_const,EQ
        MOVL    XAR6,#__econst_run
        MOVL    XAR7,#__ec_load
        DEC     AL
        B       __econst_loop,GEQ
        DEC     AH
__econst_loop:
        MOV     AR0,AH
        RPT     AL
||      PREAD   *XAR6++,*XAR7
        MOV     AH,#0
        ADDL    ACC,XAR7
        ADDB    ACC, #1
        MOVL    XAR7,ACC
        MOV     AL, #0xffff
        MOV     AH,AR0
        SUBB    AH,#1
        B       __econst_loop,GEQ
_exit_boot:
;-----------------------------------------------
;   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

******************************************************
*  AT END OF CONSTANT SECTIONS RETURN TO CALLER      *
******************************************************
__end_const:
        LRETR
	.endasmfunc
        .endif			;  if CONST_COPY

  • Casey

    You've observed this by stepping through the code? Are you using optimizations? Have you checked the .MAP file to ensure that routine is being pulled in?
    I'm not clear why you are referring to boot28.asm

    Best regards
    Chris
  • Yes I've observed this by stepping through the code. Optimizations are not enabled. The function is not being pulled in to the map file. I can see args_main and exit but not the _exit_boot routine I added to boot28.asm file (line 334). It seems like boot28.asm is precompiled into a library and the source is included as a reference which might be why my routine is not being called? I am trying to jump to application code when the bootloader detects data has been written at application code entry and it seems like boot28.asm would be the place to do it based on the control suite flash_kernel example.
  • Casey

    The boot28.asm is part of the RTS library and doesn't look to be using your copy. Having said that, you shouldn't be doing your modifications in that file. Like the flash_kernel example you reference, if there is something special you want to do in your exit routine, it should be modified in the exit_boot.asm that you find with that example.
    The general flow is call kernel main, return application address, run exit boot, call application address (which should point to c_int00), and c_int00 runs boot28.asm as part of its routine, and finally returns from there to your application main function.

    Best regards
    Chris
  • Thank you for your help. I have been looking into where else I could insert my code but the exit routine that is called is also part of the rts library and there is no exit_boot.asm in my project (exit.c is the file in the rts library). So all code before and after main() seems to be out of my control.
  • That's unfortunate. You can see if they have some form of code_start (see file DSP2803x_CodeStartBranch.asm) where c_int00 is called and you can put code before that. I recommend checking out the flash_f28035 example.

    Best regards
    Chris
  • So I got it working. I had to create my own boot.asm file which is nearly identical to the ExitBoot.asm from the flash_kernel example. I had to add the --entry_point=_myBootFunction command to the linker command. Then when I meet the criteria to switch from bootloader to application code I return the address of c_int00 of the application code. Thanks again for your help Chris

  • Sounds good, glad you figured out a solution!

    Best regards
    Chris