UCD3138064: bootloader to app question

Part Number: UCD3138064
Other Parts Discussed in Thread: UCD3138, UCD3138128

Tool/software:

Dear Sirs,

I have a question to ask: Due to CRPS2.0 requirements, I need to develop a bootloader. Currently, the firmware download and Flash write operations are functioning properly, and the application (APP) can run independently. However, after the bootloader disables interrupts and jumps to the APP (located at Flash partition 0x2000-0xFFFF, while the bootloader occupies 0x0000-0x1FFF), the APP fails to work correctly. ​What critical steps should the bootloader perform before handing control to the APP?

The code of bootload was show as blew:

void main()
{

MiscAnalogRegs.CLKTRIM.bit.HFO_LN_FILTER_EN = 0;
read_dflash_Modelname_message();
read_dflash_upload_message();
volatile Uint32 check_sum=*(volatile Uint32 *)0x0000fffc;
if((BootLoaderStructRam.UpdateMode==0)&&(check_sum==(calculate_checksum(0,0xfffc))))
{

JumpToApp(FLASHPROGRAMBASE); //0x2000
}
else
{
FirmwareUpdate_Handler();

}

}

typedef void (*AppEntry)(void);

void JumpToApp(Uint32 app_address)
{
disable_interrupt();
disable_fast_interrupt();


AppEntry app_entry = (AppEntry)(*(volatile Uint32*)app_address);


app_entry();
}

  • Hello Rex,

    I would not handle something like your bootloader in the main function. We have a dedicated software interrupt handler for code accesses sensitive registers, such as the data flash. Try implementing this feature within the software_interrupt.c file.

    See this E2E post for more explanation on the software interrupts: https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1495205/ucd3138128-program-flash-erase-issue 

    As a sidenote, you can enter C code into E2E by clicking on Insert --> Code and select C in the dropdown menu. Below is a snippet of the software_interrupt.c in the on-the-fly update firmware.

    #include "function_definitions.h"
    #include "software_interrupts.h"
    #include "pmbus_common.h"
    
    extern Uint32 zero_out_integrity_word_1_start[32];
    extern Uint32 zero_out_integrity_word_2_start[32];
    extern Uint32 clear_program_flash_1_start[32];
    extern Uint32 clear_program_flash_2_start[32];
    extern Uint32 block_switch_at_startup_start[32];
    
    
    #pragma INTERRUPT(software_interrupt,SWI)
    void software_interrupt(Uint32 arg1, Uint32 arg2, Uint32 arg3, Uint8 swi_number)
    //void software_interrupt(Uint32 *address, Uint32 data, Uint32 more_data, Uint8 swi_number)
    {
    	//make sure interrupts are disabled
    
    	 asm(" STMFD SP!, {R4} "); //Store R4
    
    	 asm(" MRS r4, cpsr "); // get psr
    
    	 asm(" ORR r4, r4, #0xc0 "); // set interrupt disables
    
    	 asm(" MSR cpsr_cf, r4"); // restore psr
    
    	 asm(" LDMFD SP!, {R4} "); //Restore R4
    
    
    	switch (swi_number) //handle flash write/erase and ROM backdoor first
    	{
    		case 0: 
    	//--------------------------------------------------------------------------------------
    	// SWI ALIAS: erase_data_flash_segment()
    	// 	Erases one segment of Data Flash and wait for erase to complete.
    	//--------------------------------------------------------------------------------------
    		case 1: 	
    	//--------------------------------------------------------------------------------------
    	// SWI ALIAS: erase_dflash_segment_no_delay()
    	// 	Erase one segment of Data Flash and return without waiting for completion.
    	//--------------------------------------------------------------------------------------
    		{
    
    	        union DFLASHCTRL_REG dflashctrl_shadow;	// Shadow copy of control register
    			
    			if (arg1 >= DATA_FLASH_NUM_SEGMENTS)	
    			{
    				return;		// Invalid segment number
    			}
    			while(DecRegs.DFLASHCTRL.bit.BUSY != 0)
    			{
    				; //wait in case it's already programming
    			}
    			DecRegs.FLASHILOCK.all = 0x42DC157E; //unlock flash write;
      			// Set the bits in the Data Flash Control Register to erase the indicated segment
    			dflashctrl_shadow.all = DecRegs.DFLASHCTRL.all;	// Read the hardware register
    			dflashctrl_shadow.bit.PAGE_ERASE = 1; 			// Erase one segment
    			dflashctrl_shadow.bit.PAGE_SEL = arg1;		// Segment number
    			DecRegs.DFLASHCTRL.all = dflashctrl_shadow.all;	// Write the hardware register
    			if (swi_number == 1)	// 0= Wait for erase to complete, 1= return immediately
    		    {
    			  return;
    		    }
    
    			return;
    		
    		}

    Regards,

    Jonathan Wong

  • Hi Jonathan,

    I appreciate your quick response!

    Okay, I roughly understand your point about performing the jump under a software interrupt. I've written the JumpToAPP function within the software interrupt handler. Perhaps I didn’t explain my issue clearly earlier. My main question is: ​Does the code below actually achieve the jump functionality? Additionally, the APP size is ​53KB, which seems too large for on-the-fly updates. Could you review this?

    #include "cyclone_device.h"
    //#include "user_define.h"
    #include "system_defines.h"
    #include "pmbus_commands.h"
    #include "pmbus_common.h"
    #include "variables.h"
    #include "function_definitions.h"
    #include "software_interrupts.h"
    
    
    extern Uint32 zero_out_integrity_word_start[32];
    extern Uint32 clear_program_flash_1_start[32];
    extern Uint32 write_word_1st_pflash_block_start[32];
    extern void zero_out_integrity_word(void);
    #pragma DATA_SECTION(program_area, ".ram_for_program_area")
    Uint32 program_area[32]; // small RAM area for storing programs which modify program flashes
    
    
    
    
    
    #pragma INTERRUPT(undefined_instruction_exception,UDEF)
    void undefined_instruction_exception(void)
    {
    }
    
    #pragma INTERRUPT(software_interrupt,SWI)
    void software_interrupt(Uint32 arg1, Uint32 arg2, Uint32 arg3, Uint8 swi_number)
     //void software_interrupt(Uint32 *address, Uint32 data, Uint32 more_data, Uint8 swi_number)
    {
    	//make sure interrupts are disabled
    	asm(" STMFD   SP!, {R4} "); //Store R4
        asm(" MRS     r4, cpsr "); 		// get psr
        asm(" ORR     r4, r4, #0xc0 "); // set interrupt disables
        asm(" MSR     cpsr_cf, r4"); 	// restore psr
        asm(" LDMFD   SP!, {R4}  ");    //Restore R4 
    
    	switch (swi_number) //handle flash write/erase and ROM backdoor first
    	{
    	case 0: 
    		//--------------------------------------------------------------------------------------
    		// SWI ALIAS: erase_data_flash_segment()
    		// 	Erases one segment of Data Flash and wait for erase to complete.
    		//--------------------------------------------------------------------------------------
    	case 1: 	
    		//--------------------------------------------------------------------------------------
    		// SWI ALIAS: erase_dflash_segment_no_delay()
    		// 	Erase one segment of Data Flash and return without waiting for completion.
    		//--------------------------------------------------------------------------------------
    		{
    			union DFLASHCTRL_REG dflashctrl_shadow;	// Shadow copy of control register
    
    			if (arg1 >= DATA_FLASH_NUM_SEGMENTS)	
    			{
    				return;		// Invalid segment number
    			}
    			DecRegs.FLASHILOCK.all = DFlash_Lock_Key;//0x42DC157E; //unlock flash write;
    			// Set the bits in the Data Flash Control Register to erase the indicated segment
    			dflashctrl_shadow.all = DecRegs.DFLASHCTRL.all;	// Read the hardware register
    			dflashctrl_shadow.bit.PAGE_ERASE = 1; 			// Erase one segment
    			dflashctrl_shadow.bit.PAGE_SEL = arg1;		// Segment number
    			DecRegs.DFLASHCTRL.all = dflashctrl_shadow.all;	// Write the hardware register
    			if (swi_number == 1)	// 0= Wait for erase to complete, 1= return immediately
    			{
    				return;
    			}
    			while(DecRegs.DFLASHCTRL.bit.BUSY != 0)
    			{
    				; //do nothing while it programs
    			}
    			return;
    
    		}
    	case 3: //write word to data flash
    	{
    		union  MFBALRX_REG mfbalr_shadow;
    
    		if(((arg1) < DATA_FLASH_START_ADDRESS) ||
    			((arg1) > DATA_FLASH_END_ADDRESS))
    		{//if out of data flash range
    			return;
    		}
    
    		//this clears read only bit to permit writes to data flash.
    		DecRegs.FLASHILOCK.all = DFlash_Lock_Key;//0x42DC157E; //unlock flash write
    
    		// Clear read-only bit to allow writes to Data Flash.
    		mfbalr_shadow.all = DecRegs.MFBALR2.all;
    		mfbalr_shadow.bit.BLOCK_SIZE =2;
    		mfbalr_shadow.bit.ADDRESS = 0x22;
    		mfbalr_shadow.bit.RONLY = 0;
    	    DecRegs.MFBALR2.all = mfbalr_shadow.all; //enable program flash write
    
    
    		//put data in word.
    		*(Uint32 *)(arg1 & 0xfffffffc) = arg2 ;
    
    		//Set RONLY bit to protect dataflash
    		mfbalr_shadow.all = DecRegs.MFBALR2.all;
    		mfbalr_shadow.bit.RONLY = 1;
    	    DecRegs.MFBALR2.all = mfbalr_shadow.all; //enable program flash write
    
    		while(DecRegs.DFLASHCTRL.bit.BUSY != 0)
    		{
    			; //do nothing while it programs
    		}
    		return;
    	}
    
    		//handle interrupt enables/disables next
    	case 4: //enable fiq
    		asm(" MRS     r0, spsr "); //get saved psr
    		asm(" BIC     r0, r0, #0x40 "); // clear fiq disable
    		asm(" MSR     spsr, r0"); //restore saved psr
    		return;
    	case 5: //disable fiq
    		asm(" MRS     r0, spsr "); //get saved psr
    		asm(" ORR     r0, r0, #0x40 "); // set fiq disable
    		asm(" MSR     spsr, r0"); //restore saved psr
    		return;
    	case 6: //enable irq
    		asm(" MRS     r0, spsr "); //get saved psr
    		asm(" BIC     r0, r0, #0x80 "); // clear irq disable
    		asm(" MSR     spsr, r0"); //restore saved psr
    		return;
    	case 7: //disable irq
    		asm(" MRS     r0, spsr "); //get saved psr
    		asm(" ORR     r0, r0, #0x80 "); // set irq disable
    		asm(" MSR     spsr, r0"); //restore saved psr
    		return;
    	case 8: //write to fiq/irq program_control_register
    		CimRegs.FIRQPR.all = arg1;
    		return;
    	case 9: //write to fiq/irq program_control_register
    		CimRegs.REQMASK.all = arg1;
    		return;
    	case 10: // switch to supervisor mode
    		asm(" MRS     r0, spsr "); //get saved psr
    		asm(" BIC	  r0, r0, #0x1F "); // clear 5 lsbs.
    		asm(" ORR     r0, r0, #0x13 "); // set mode bits to 13.
    		asm(" MSR     spsr, r0"); //restore saved psr
    		return;
    	case 11: // switch to user mode
    		asm(" MRS     r0, spsr "); //get saved psr
    		asm(" BIC	  r0, r0, #0x1F "); // clear 5 lsbs.
    		asm(" ORR     r0, r0, #0x10 "); // set mode bits to 10.
    		asm(" MSR     spsr, r0"); //restore saved psr
    		return;
    	case 12: // clear integrity word.
    		{
    		    register  Uint32  *  program_index  =  (Uint32  *)  program_area;
    		                //store destination address for program
                register  Uint32  *  source_index  =  (Uint32  *) zero_out_integrity_word_start;  //Used  for  source  address  of PFLASH;
                register Uint32 counter;
    
                union  MFBALRX_REG mfbalr_shadow;
                mfbalr_shadow.all = DecRegs.MFBALR17.all;
                mfbalr_shadow.bit.RONLY = 0;
                DecRegs.MFBALR17.all = mfbalr_shadow.all; //enable program flash write
    
                for(counter=0;  counter  <  84;  counter++)  //Copy  program  from PFLASH to RAM
                {
                    *(program_index++)=*(source_index++);
                }
    
                zero_out_integrity_word();
    		                return;
    		}
    	case 13: //write block to data flash
    		//--------------------------------------------------------------------------------------
    		// SWI ALIAS: write_data_flash_block()
    		// 	Copies a block of data from a source (typically RAM) to a destination in Data Flash.
    		// Handles locking and unlocking the read-only bit.
    		// Includes necessary delays while writing.
    		// Assumptions:  
    		//	Destination address is in Data Flash.
    		//	Destination addresses start and end on word boundary.
    		//	Source addresses start and end on word boundaries.
    		//--------------------------------------------------------------------------------------
    		{
    			volatile Uint32* dest_ptr = (volatile Uint32*)(arg1 & 0xfffffffc);
    			Uint32*	src_ptr =  (Uint32*)(arg2);
    			int32	byte_counter = (int32)arg3;	// Use int instead of Uint in case count is not a multiple of 4
    
    			union  MFBALRX_REG mfbalr_shadow;
    
    			// Validate that destination address is in Data Flash
    			if(  ((arg1) < DATA_FLASH_START_ADDRESS)
    				||((arg1) > DATA_FLASH_END_ADDRESS)  )
    			{//if out of data flash range
    				flash_write_status = FLASH_INVALID_ADDRESS;
    				return;	// Return without writing to DFlash
    			}
    
    			// Clear read-only bit to allow writes to Data Flash.
    			mfbalr_shadow.all = DecRegs.MFBALR2.all;
    			mfbalr_shadow.bit.RONLY = 0;
    		    DecRegs.MFBALR2.all = mfbalr_shadow.all; //enable program flash write
    
    			// Copy a block of RAM to DFlash						     
    			while (byte_counter > 0)
    			{
    				Uint32	temp_word = *src_ptr++;
    				DecRegs.FLASHILOCK.all = DFlash_Lock_Key;//0x42DC157E; //unlock flash write
    				// Write the temp word to DFlash.
    				*dest_ptr = temp_word;
    
    				// *** Should add value to checksum.
    				// checksum += temp.word;
    
    				// Wait for any previous writes to complete.
    				while(DecRegs.DFLASHCTRL.bit.BUSY != 0)
    				{
    					; //do nothing while it programs
    				}
    
    				// Read back value from DFlash. Abort if it does not match intended value.
    				if (*dest_ptr != temp_word)
    				{
    					// Set an error flag to indicate write failure.
    					flash_write_status = FLASH_MISCOMPARE;
    					return;	
    				}
    
    				dest_ptr++;
    				byte_counter -= 4;
    			}
    
    			// Set read-only bit to protect Data Flash
    			mfbalr_shadow.all = DecRegs.MFBALR2.all;
    			mfbalr_shadow.bit.RONLY = 1;
    		    DecRegs.MFBALR2.all = mfbalr_shadow.all; 
    			flash_write_status = FLASH_SUCCESS;
    			return;
    		}
    	case 14: // erase entire Program Flash
    		{
    		   register  Uint32  *  program_index  =  (Uint32  *)  program_area;
    		                           //store destination address for program
               register  Uint32  *  source_index  =  (Uint32  *) clear_program_flash_1_start;  //Used  for  source  address  of PFLASH;
               register Uint32 counter;
    
               union  MFBALRX_REG mfbalr_shadow;
               mfbalr_shadow.all = DecRegs.MFBALR17.all;
               mfbalr_shadow.bit.RONLY = 0;
               DecRegs.MFBALR17.all = mfbalr_shadow.all; //enable program flash write
    
               for(counter=0;  counter  <  84;  counter++)  //Copy  program  from PFLASH to RAM
               {
                   *(program_index++)=*(source_index++);
               }
    
    			clear_program_flash_1();
    
    			return;
    		}
    	case 15:
    	   {   Uint8 j;
    	       for(j=0;j<(FWdataCnt-1);)
                {
    
                 pflash_write_data.uc[0]=FWupdata[j++];
                 pflash_write_data.uc[1]=FWupdata[j++];
                 pflash_write_data.uc[2]=FWupdata[j++];
                 pflash_write_data.uc[3]=FWupdata[j++];
    
    
    	         if(FlashDestAdress<0x00008000)
    	          {
    	            register  Uint32  *  program_index  =  (Uint32  *)  program_area;
    	                                      //store destination address for program
                    register  Uint32  *  source_index  =  (Uint32  *) write_word_1st_pflash_block_start;  //Used  for  source  address  of PFLASH;
                    register Uint32 counter;
    
                    union  MFBALRX_REG mfbalr_shadow;
                    mfbalr_shadow.all = DecRegs.MFBALR17.all;
                    mfbalr_shadow.bit.RONLY = 0;
                    DecRegs.MFBALR17.all = mfbalr_shadow.all; //enable program flash write
    
                    for(counter=0;  counter  <  52;  counter++)  //Copy  program  from PFLASH to RAM
                     {
                      *(program_index++)=*(source_index++);
                     }
    
    	            write_word_1st_pflash_block();
    	          }
    	        else if(FlashDestAdress<0x0000fffC)
    	         {
    	           DecRegs.FLASHILOCK.all =  PROGRAM_FLASH2_INTERLOCK_KEY;
    	           *((volatile unsigned long *)FlashDestAdress) = pflash_write_data.ul;
    	           while((DecRegs.PFLASHCTRL2.bit.BUSY != 0))
    	                  {
    	                                ; //do nothing while it programs
    	                  }
    
    	          }
    	       FlashDestAdress+=4;
    
                }
    	       return;
    
    	   }
    
    		case 99:
    		{
    		    typedef void (*AppEntry)(void);
    		    AppEntry app_entry = (AppEntry)(*(volatile Uint32*)FLASHPROGRAMBASE);
    
    		    //jump to app
    		    app_entry();
    
    		}
    		/*****************************************************************************************************/
    	default:
    		break;
    	}
    }
    #pragma INTERRUPT(abort_prefetch_exception,PABT)
    void abort_prefetch_exception(void)
    {
    }
    
    #pragma INTERRUPT(abort_data_fetch_exception,DABT)
    void abort_data_fetch_exception(void)
    {
    }
    
    
    #pragma INTERRUPT(fast_interrupt,FIQ)
    void fast_interrupt(void)
    {
    }
    
    
    
    

  • Hello Rex,

    I will provide a response by the end of the week.

    Regards,

    Jonathan Wong

  • Hello Rex,

    Have you see our On-the-fly update example for UCD3138064? Below is an article by Ian Bower that demonstrates the steps. If you are interested in the code, then let me know.

    On-the-fly power supply firmware upgrades.docx

    The UCD3138064 only has 64kB of program flash. If my understanding is correct, then you are not switching between two programs, but just going from boot ROM to the APP?

    Regards,

    Jonathan Wong

  • Hello Jonathan,

    Yes, due to capacity constraints, I don’t need on-the-fly functionality. My current issue is that the bootloader fails to work properly after jumping to the APP. So, my question is: Is my jump code correct? If convenient, you can share your on-the-fly code with me, as it includes the jump logic. This will help me deepen my understanding of the UCD3138 jump mechanism!Thank you!

  • Hello Rex,

    Please accept the friend request so I can share the on-the-fly update firmware with you. 

    I do not think the jump code is correct. I think more will be required. I found this article that highlights how to implement a bootloader on a Cortex-M0 processor: https://interrupt.memfault.com/blog/how-to-write-a-bootloader-from-scratch 

    (UCD3138064 is the older Arm7TDMI-S core. See https://en.wikipedia.org/wiki/List_of_ARM_processors for details).

    From my understanding, your main() function is below:

    void main()
    {
        MiscAnalogRegs.CLKTRIM.bit.HFO_LN_FILTER_EN = 0;
        read_dflash_Modelname_message();
        read_dflash_upload_message();
        volatile Uint32 check_sum=*(volatile Uint32 *)0x0000fffc;
        if((BootLoaderStructRam.UpdateMode==0)&&(check_sum==(calculate_checksum(0,0xfffc))))
        {
            JumpToApp(FLASHPROGRAMBASE); //0x2000
        }
        else
        {
            FirmwareUpdate_Handler();
        }
    }

    Your JumpToApp() function is below

    typedef void (*AppEntry)(void);
    
    void JumpToApp(Uint32 app_address)
    {
        disable_interrupt();
        disable_fast_interrupt();
    
        AppEntry app_entry = (AppEntry)(*(volatile Uint32*)app_address);
        app_entry();
    }

    I do think that you need to place this bootloader into your software interrupts handler. Accessing sensitive locations such as the data flash and program flash are best handled within the software interrupts. See this E2E on ARM mode vs. Thumb mode: https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1495205/ucd3138128-program-flash-erase-issue 

    I am also not sure if your checksums are calculated correctly. The default program flash checksum setup is split by 32kB blocks. Since you are using 53kB, which is split between 2 blocks, then your checksum may be calculating for the full 64kB even though the 64kB includes the bootloader as well.

    Program Flash Address Program Flash Content Size
    0x0000 Bootloader Start
    0x1fff Bootloader End ~8kB
    0x2000 APP Start
    0xF400 APP End ~53kB
    0xFFFF

    In the example above, let's say you have a 8kB bootloader and start the APP at address 0x2000. Instead of just calculating a checksum for the 53kB range, the checksum may be calculating for the entire 64kB block, including the checksum + bootloader.

    Here are a few questions:

    • What is the app_address that you are inputting into your bootloader?
    • What is the AppEntry type? Is this just casting app_entry as a pointer to the app address location?
    • What is the app_entry() function?

    Regards,

    Jonathan Wong

  • Hello Rex,

    I have sent you the on-the-fly update firmware via direct message. 

    I have a few more questions and thoughts for you regarding the UCD3138064 bootloader:

    1. What line is this code failing at? Does the line 
          if((BootLoaderStructRam.UpdateMode==0)&&(check_sum==(calculate_checksum(0,0xfffc))))
      work? This seems to be the likeliest code to fail.
    2. Your JumpToApp() function looks ok. Try running your bootloader code without the if statement and see if the JumpToApp() function executes. If it does, then I think your issue is your checksum calculation
    3. Why did you calculate the checksum from 0 - 0xfffc
    4. What does the FirmwareUpdate_Handler() function do?
    5. Where are you storing your APP firmware? 
      1. You can find the default location your program is stored by looking at your linker file. Below is the section for the cyclone_64.cmd linker file for the UCD3138064. The .text section specifies your program location. You can set this to 0x2000 to ensure the APP code starts at 0x2000. Then, you can view the .map file after compiling to double check the address is correct.
      2. /*==========================================================================================
        // cyclone.cmd  Linker command file for Cyclone
        //
        // In addtion to the memory sections specified here, functions existing in the ROM
        // are specified by RomFuncs.cmd which is automatically generated in the ROM build
        // process.
        //
        //    Available Cyclone memory:
        //    ---------------------------------
        //    P-Flash   32K   0x0000  - 0xFFFF
        //    ROM       8K    0xA000  - 0xBFFF	 
        //    D-Flash   2K    0x18800 - 0x18FFF
        //    RAM       4K    0x19000 - 0x19FFF
        //
        // Copyright (C) 2008 Texas Instruments Incorporated.
        //========================================================================================*/
        
        MEMORY
        {
        
            VECS           : org = 0x00000000, len = 0x00000020    /* Vector table                */
            /*------------------------------------------------------------------------------------*/
            /* ROM       8K    0xA000 - 0xBFFF                                                    */
            /*------------------------------------------------------------------------------------*/
            ROM     : org = 0x00020020   len = 0x00000FE0  /* SYSTEM ROM    */
        	SINE	: org = 0x00021000   len = 0x00000282  /*sine table in ROM */
        	EXP	: org = 0x00021282   len = 0x0000007A  /*exponent table in ROM */
        
            /*------------------------------------------------------------------------------------*/
            /* P-Flash   32K   0x0  - 0x7FFF                                                   */
            /*------------------------------------------------------------------------------------*/
            PFLASH    (RX) : org = 0x00000020, len = 0x00007F38    /* PFlash Main Program         */
            DEVICEID  (RX) : org = 0x00007F58, len = 0x00000020    /* Fixed Location for DEVICE_ID*/
            FIXTFA    (RX) : org = 0x00007F78, len = 0x00000004    /* Fixed Step Size for TFA     */
            FIXCONST  (RX) : org = 0x00007F7C, len = 0x00000080    /* Fixed-location Constants    */
            FLASHSUM  (RX) : org = 0x00007FFC, len = 0x00000004    /* Flash Checksum              */
        
        
            /*------------------------------------------------------------------------------------*/
            /* D-Flash   2K    0x18800 - 0x18FFF                                                  */
            /*------------------------------------------------------------------------------------*/
            DFLASH    (RX) : org = 0x00068800, len = 0x00000800
        
            /*------------------------------------------------------------------------------------*/
            /* RAM       4K    0x19000 - 0x19FFF                                                  */
            /*                                                                                    */
            /*    Partition RAM into four parts:                                                  */
            /*     1. Fixed at the start of RAM are tester variables.                             */
            /*        that can not move without breaking the tester.                              */
            /*     2. General variables.                                                          */
            /*     3. Stacks for the various operating modes.                                     */
            /*        NOTE!!  Stack size must be specified in build options too!!!                */
            /*     4. The interlock used to prevent rom from returing to flash - rom_flash_lock.  */
            /*------------------------------------------------------------------------------------*/
            RAM       (RW) : org = 0x00069000, len = 0x00001000
        }
        
        SECTIONS
        {
            /*------------------------------------------------------------------------------------*/
            /* P-Flash   32K   0x0  - 0x7FFF                                                   */
            /*                                                                                    */
            /*   Most of these sections are unused for the ROM build.                             */
            /*------------------------------------------------------------------------------------*/ 
        
            .fiq            : {} > 0x001C                    /* Fast Interrupt Handler            */
            .text           : {} > (PFLASH align(16))        /* Code                              */
            .const          : {} > (PFLASH align(16))        /* Constant data                     */
            .cinit          : {} > (PFLASH align(16))        /* Initialization tables             */
             FixedDeviceID  : {} > (DEVICEID)                /* Fixed location for Device ID      */
             FixedTfaStep   : {} > FIXTFA                    /* Fixed location TFA Step Size      */
             FixedConstants : {} > FIXCONST                  /* Fixed location constants          */ 
            .flashi         : {} > FLASHSUM                  /* PFlash Integrity Word             */
        
            /*------------------------------------------------------------------------------------*/
            /* ROM (8kB   0xA000 - 0xBFFF                                                         */
            /*------------------------------------------------------------------------------------*/
            .vectors        : {} > VECS
            .sine           : {} > SINE
        
            /*------------------------------------------------------------------------------------*/
            /* D-Flash   2K    0x18800 - 0x18FFF                                                  */
            /*------------------------------------------------------------------------------------*/
             .dflash   : {} > (DFLASH align(32))
        		//data flash
        	.CONFIG    : {} > (DFLASH align(32))
            .CONFIG_A  : {} > (DFLASH align(32))
            .CONFIG_B  : {} > (DFLASH align(32))
        	.PASSW     : {} > (DFLASH align(32))
            /*------------------------------------------------------------------------------------*/
            /* RAM       4K    0x19000 - 0x19FFF                                                  */
            /*------------------------------------------------------------------------------------*/
            .bss            : {} > RAM                       /* Global & Static vars              */
        
        }
    6. We have an unreleased guide on how to use the UART as a bootloader: BootFlash_001.docx
      1. See section 3 and 4 for code examples
      2. load.asm changes
        1.     .global rom_main
              .global _boot_upload_fw_vec
          rom_main .equ 0xffffa4dc
          ; these three lines are added for ti_uart_boot_loader option
              .sect ".bvectors"
              ; boot vectors - mostly go to vectors in main program flash.
              .state32
          _boot_upload_fw_vec
              .sect ".vectors"
              .state32
                  B c_int00
      3. cyclone.cmd changes (this is the linker for UCD3138)
      4. main.c changes

    Regards,

    Jonathan Wong

  • Hello Rex,

    Since your issue is still persistent, here is another suggestion to help with your code.

    We have a UART Bootloader for UCD3138064 and UCD3138128 example code. Here is a tentative app note on UART BootFlash. I have sent you the example code directly.

    BootFlash_001.pdf

    Regards,

    Jonathan Wong

  • Thanks for your help, I have cloesed this issue.