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.

UCD3138128: Program Flash erase issue

Part Number: UCD3138128
Other Parts Discussed in Thread: UCD3138A

Tool/software:

Hello again.

I am just now getting back to this issue. My immediate problem is that I can't seem to simply erase a block of Pflash memory.

I am running out of block 0 and want to erase block 2. 

It seems when I execute the software_interrupt to clear prorgam flash block 2, I get a memory fault or something causing a reset.

(This is CASE 14 in the function: software_interrupt().)

The program It is attempting to run from a RAM copy of clear_program_flash_2 at that time.

Is there something special I need to do to allow the program to run from ram?

Here is the snippet: (it fails down around line 131)


        case 14: // erase entire Program Flash
	    //--------------------------------------------------------------------------------------
	    // SWI ALIAS: Pflash_EraseBlock
	    // variables: Uint32 arg1, Uint32 arg2, Uint32 arg3, Uint8 swi_number
	    //--------------------------------------------------------------------------------------
             {
                 register Uint32 * program_index = (Uint32 *) program_area; //store destination address for program
                 register Uint32 * source_index; //Used for source address of PFLASH;

                 register Uint32 counter;

                 if(arg1 == 0) //0 means first block by address, not flash block
                 {
                     if((DecRegs.MFBALR1.bit.ADDRESS == 0) && (DecRegs.MFBAHR1.bit.ADDRESS == 0)) //here if flash block 0 is at 0
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH0_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_0;
                     }
                     else if((DecRegs.MFBALR17.bit.ADDRESS == 0) && (DecRegs.MFBAHR17.bit.ADDRESS == 0))//if it's program flash 1;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH1_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_1;
                     }
                     else if((DecRegs.MFBALR18.bit.ADDRESS == 0) && (DecRegs.MFBAHR18.bit.ADDRESS == 0))//if it's program flash 2;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH2_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_2;
                     }
                     else if((DecRegs.MFBALR19.bit.ADDRESS == 0) && (DecRegs.MFBAHR19.bit.ADDRESS == 0))//if it's program flash 3;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH3_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_3;
                     }
                     else
                     {
                         return;
                     }
                 }
                 else if(arg1 == 1) //1 means second block by address;
                 {
                     if((DecRegs.MFBALR1.bit.ADDRESS == 0x20) && (DecRegs.MFBAHR1.bit.ADDRESS == 0)) //here if flash block 0 is at 0x8000
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH0_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_0;
                     }
                     else if((DecRegs.MFBALR17.bit.ADDRESS == 0x20) && (DecRegs.MFBAHR17.bit.ADDRESS == 0))//if it's program flash 1;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH1_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_1;
                     }
                     else if((DecRegs.MFBALR18.bit.ADDRESS == 0x20) && (DecRegs.MFBAHR18.bit.ADDRESS == 0))//if it's program flash 2;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH2_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_2;
                     }
                     else if((DecRegs.MFBALR19.bit.ADDRESS == 0x20) && (DecRegs.MFBAHR19.bit.ADDRESS == 0))//if it's program flash 3;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH3_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_3;
                     }
                     else
                     {
                         return;
                     }
                 }
                 else if(arg1 == 2) //2 means third block by address;
                 {
                     if((DecRegs.MFBALR1.bit.ADDRESS == 0) && (DecRegs.MFBAHR1.bit.ADDRESS == 1)) //here if flash block 0 is at 0x10000
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH0_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_0;
                     }
                     else if((DecRegs.MFBALR17.bit.ADDRESS == 0) && (DecRegs.MFBAHR17.bit.ADDRESS == 1))//if it's program flash 1;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH1_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_1;
                     }
                     else if((DecRegs.MFBALR18.bit.ADDRESS == 0) && (DecRegs.MFBAHR18.bit.ADDRESS == 1))//if it's program flash 2;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH2_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_2;
                     }
                     else if((DecRegs.MFBALR19.bit.ADDRESS == 0) && (DecRegs.MFBAHR19.bit.ADDRESS == 1))//if it's program flash 3;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH3_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_3;
                     }
                     else
                     {
                         return;
                     }
                 }
                 else if(arg1 == 3) //3 means fourth block by address;
                 {
                     if((DecRegs.MFBALR1.bit.ADDRESS == 0x20) && (DecRegs.MFBAHR1.bit.ADDRESS == 1)) //here if flash block 0 is at 0x18000
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH0_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_0;
                     }
                     else if((DecRegs.MFBALR17.bit.ADDRESS == 0x20) && (DecRegs.MFBAHR17.bit.ADDRESS == 1))//if it's program flash 1;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH1_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_1;
                     }
                     else if((DecRegs.MFBALR18.bit.ADDRESS == 0x20) && (DecRegs.MFBAHR18.bit.ADDRESS == 1))//if it's program flash 2;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH2_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_2;
                     }
                     else if((DecRegs.MFBALR19.bit.ADDRESS == 0x20) && (DecRegs.MFBAHR19.bit.ADDRESS == 1))//if it's program flash 3;
                     {
                         DecRegs.FLASHILOCK.all = PROGRAM_FLASH3_INTERLOCK_KEY;
                         source_index = (Uint32 *)clear_program_flash_3;
                     }
                     else
                     {
                         return;
                     }
                 }
                 else
                 {
                     return; //ditch any invalid arg1s
                 }

                 for(counter=0; counter < 32; counter++) //Copy program from PFLASH to RAM
                 {
                     *(program_index++)=*(source_index++);
                 }

                 {
                     register FUNC_PTR func_ptr;
                     func_ptr=(FUNC_PTR)program_area;     //Set function to program area
                     func_ptr();
                 }
             }
         break;


		default:
			break;
	}
}

  • I'm not sure what I am supposed to write to DecRegs.MFBALRx.all  registers? Maybe that is the problem? It isn't evident in the examples and is difficult to understand from the documentation to say the least!

  • FYI...

    I was able to get the erase feature to work. 

    I had to add the following statement in the functions that get copied to RAM:

    #pragma CODE_STATE(clear_program_flash_2, 32) // this will ensure that this code builds in ARM mode
    void clear_program_flash_2(void)
    { ...}

    My issue is that I don't understand what that statement actuall does.

    CAn you point me to a resource that could explain that? Does ARM mode mean Relative Address mode? 

    Thank you for any help in this matter.

  • Hello BatMan,

    Thank you for the update. The only thing you added was the line of code in red? Where did you find this line of code? I will look into how it works.

    Regards,

    Jonathan Wong

  • My guess is that it causes the included function to be compiled in relative addressing mode (why they call ARM mode is misleading since the processor type is "ARM").  Relative addressing compilation would allow it to be copied to another location (such as RAM as in this case) and run properly. I found that line of code in various examples but never explained anywhere.

  • Hello BatMan,

    Thanks for the explanation. I will provide a response at the end of the week.

    Regards,

    Jonathan Wong

  • FYI, I found the definition (and other PRAGMA definitions) here:ARM Optimizing C/C++ Compiler v20.2.0.LTS User's Guide (Rev. W)

    Please see my other posts about switching between apps and how to properly calculate checksums!! thank for your help in these matters. 

  • Hello BatMan,

    I wanted to follow up to clarify this issue for you and for anyone else on this forum.

    The UCD3138A Arm7 core has two instruction sets: Arm Mode (32-bit) and Thumb Mode (16-bit). Section 14.4.2 page 476 in the UCD31xx Technical Reference Manual highlights the advantages of the Thumb instruction set, including higher performance and code density. Thus, Thumb Mode is the preferred mode for as much UCD3138A code as possible. For example, in the UCD3138128 Bidirectional DC/DC firmwaremain.c is set to Thumb Mode in the file properties. 

    However, certain code must be configured in ARM mode, not Thumb Mode. Table 14-1 on page 472 shows a table between privileged (ARM mode) and non-priviliged (Thumb mode) code. For example, interrupts must be configured in ARM mode and not Thumb mode. If you check the standard_interrupt.c properties, then you can see that the file is set up for ARM mode.

    The line of code 

    #pragma CODE_STATE(clear_program_flash_2, 32) // this will ensure that this code builds in ARM mode
     ensures that the following code will be built in ARM mode and not Thumb mode. Since the clear_program_flash_2() function comes from the clear_program_flash_2.c file, then your file may have incorrectly built the function in Thumb mode. Thus, adding the #pragma directive ensured the function was built properly. 

    The software interrupts are all in a single handler (Ex. 14 different cases) so that the UCD3138A will never be locked up in performing two different software interrupt routines at the same time. Since the software interrupts handle sensitive operations, such as accessing data flash, the routines must be handled one at a time within the software interrupt, and must be accessed in supervisor mode. 

    More information about User Mode vs. Supervisor Mode can be found on section 14.3 and 16.1.10. 

    Regards,

    Jonathan Wong

  • Thank you for the detailed clarification and I hope this helps others as well.