MC9S12XEP100 Flash burner question MC9S12XEP100. Code Warrior 5.9.0, single chip, absolute assembler. I have a program, similar to the one I wrote using the MC9S12C64, but larger and more complex. I couldn't figure out the flash burner process for that one until I posted the question and Ladislav was able to explain it to me with his C64-FLASH-ASM test program. Using that I was able to get my program to work just fine. Now I am having the same issue using the MC9S12XEP100 processor. I was hoping there would be enough similarities in the process that I could adapt what I learned, but I'm having some difficulties. Is there a test program similar to the C64-FLASH-ASM, but specific to the MC9S12XEP100 in single chip, absolute assembler that I could study and see if I could get that to work? I'm attaching a basic test code that I am using to troubleshoot. Regards, Robert Re: MC9S12XEP100 Flash burner question Hi Ladislav, Thanks so much for your detailed response. There are still a few minor errors in your comments, but no matter, I'm quite sure I know what you are doing and they really helped. Your screen shots of the memory window were a big revelation to me. I didn't know about the l, g and r suffix. That explains a lot. The spread sheet that compares the equivalent addresses also really helped in my education. I now feel I have a good understanding of what you have done and a better understanding of what the debugger can do. As a result of my new found knowledge I am realizing that I should be using EEPROM emulation. I have some questions about that in a separate thread. Thanks once more for all your help and patience. Regards, Robert Re: MC9S12XEP100 Flash burner question Hi,
I have found my notes contain copy/paste mistakes.
I am not sure what are you looking at so more detailed comments. Moreover, I suppose the DFLASH is in erased status before it is written.
Moreover, the question is how the RAM content is refreshed in your memory window. You should also check the setup lime it is done for DFLASH.
The address 0x2100 is selected by compiler so the array is placed:
Buffer[0] is at address 0x2100,0x2101 of a local address space
Buffer[1] is at address 0x2102,0x2103
Buffer[2] is at address 0x2104,0x2105
Buffer[3] is at address 0x2106,0x2106
Finally, it is good to understand local and global address space. The RAM 0x2100 is in local address space 0x2100 and in the global address space 0x0F_E100. Si memory map in attachment.
... and be careful when you show address space ... extension 'G or 'L. For example 0FE100'G and 2100'L represents the same address from different views.
.... does no exist
.... the variable "buffer" in a local address space
... the variable "buffer" in a global address space
better comments of the original asm code..
;---------------------------
;err = DFLASH_Program(0x0000, &buffer[0], 4); //write 4 words to D Flash address 0x10_0000
; GPAGE (0x10_.... ) is not used in the Addr variable because it is directly used in the DFLASH_Program routine
MOVW #$0000,Addr ; address to be written 0x(10)0000~0x(10)0007
MOVB #4,Cnt ; number of words to be written
;for example data to be written into DFLASH are 0x0123, 0x4567, 0x89AB, 0xCDEF
; written global DFLASH address is 0x10_0000’G … for data visualization in a debugger memory
; window“ ’G ” must be added into memory address
LDX #Buffer ; Load the base address of the array into X register, the base address
; is selected by compiler if you do not set exact address
LDD #$0123 ; Load the hexadecimal value 0x0123 into D register
STD 0,X ; Store the value at the 0th position of the array; Buffer[0] = 0x0123
LDD #$4567 ; Load the value 0x4567 into D register
STD 2,X ; Store the value at the 1st position of the array; Buffer[1] = 0x4567
LDD #$89AB ; Load the value 0x89AB into D register
STD 4,X ; Store the value at the 2nd position of the array; Buffer[2] = 0x89AB
LDD #$CDEF ; Load the value 0xCDEF into D register
STD 6,X ; Store the value at the 3rd position of the array; Buffer[3] = 0xCDEF
CALL DFLASH_Program ; note there is a status of verification in the Err variable after execution of this command
;---------------------------
;err = DFLASH_Program(0x0008, &buffer[0], 4); //write 4 words to eeprom address 0x0000
;… at this place you should check whether Err value is OK to be sure entire write process has
; finished correctly. I am not doing it in this example.
;---------------------------
; write another set of data to a 8 bites higher address of the DFLASH
; written global DFLASH address is 0x10_0008’G
MOVW #$0008,Addr ; address to be written 0x(10)0008~0x(10)000F
MOVB #4,Cnt ; number of words to be written
;for example data to be written into DFLASH are 0xDEAD,0xBEEF,0xC0DE,0xCAFE
LDX #Buffer ; Load the base address of the array into X register, the base address
; is selected by compiler if you do not set exact address
LDD #$DEAD ; Load the hexadecimal value 0xDEAD into D register
STD 0,X ; Store the value at the 0th position of the array; Buffer[0] = 0x0123
LDD #$BEEF ; Load the value 0xBEEF into D register
STD 2,X ; Store the value at the 1st position of the array; Buffer[1] = 0x4567
LDD #$C0DE ; Load the value 0XC0DE into D register
STD 4,X ; Store the value at the 2nd position of the array; Buffer[2] = 0x89AB
LDD #$CAFE ; Load the value 0xCAFE into D register
STD 6,X ; Store the value at the 3rd position of the array; Buffer[3] = 0xCDEF
CALL DFLASH_Program ; note there is a status of verifiction in the Err variable after execution of this command
;---------------------------
;err = DFLASH_Program(0x0008, &buffer[0], 4); //write 4 words to eeprom address 0x0000
;… at this place you should check whether Err value is OK to be sure entire write process has
; finished correctly. I am not doing it in this example.
;---------------------------
Best regards,
Ladislav Re: MC9S12XEP100 Flash burner question Hi Daniel, Freescale USBDM (from China). I use it successfully to load programs. Does that answer your question? Regards, Robert Re: MC9S12XEP100 Flash burner question Hi Robert,
I mean debugger like PE Micro Multilink (with revision), USBDM, ... Re: MC9S12XEP100 Flash burner question Hi Daniel, Code Warrior IDE V5.9.0 Build 5294 Special Edition. Regards, Robert Re: MC9S12XEP100 Flash burner question Hello @roberthiebert,
What debugger do you use?
The debugger can interpret the data as 0xCAFE because of ECC, for example.
Regards,
Daniel
Re: MC9S12XEP100 Flash burner question I've spent a lot of time stepping through this code and recording all the variable and register states on each step. I think I have a pretty good understanding of what is happening here, but one thing in particular still has me puzzled. In this section of code: LDX #Buffer ; Load the base address of the array into X register LDD #$0123 ; Load the value 0123 into A register STD 0,X ; Store the value at the 0th position of the array X is loaded with $2100, the address of "Buffer" in RAM D is loaded with decimal 0123 Decimal 0123 is copied into the first two bytes of the "Buffer" array at address $2100 in RAM. Now, when I use the debugger to check the contents of RAM address $2100 I see $CA, $FE in the first two bytes, and they never change. Why is this and where are the example words stored? Regards, Robert Re: MC9S12XEP100 Flash burner question Hi,
The topic has already been processes...
https://community.nxp.com/t5/S12-MagniV-Microcontrollers/S12-X-MCU-Security/ta-p/1111118
https://community.nxp.com/t5/S12-MagniV-Microcontrollers/Unsecuring-MC9S12XEP100MAG/m-p/617603
Best regards,
Ladislav Re: MC9S12XEP100 Flash burner question Hi Ladislav, One more thing. I did some more research and I understand that in order for CW to be able to read the D-Flash the FSEC register needs to be set to $FE. I see that your code has done this, but I can't find out where and how you did it. Could you explain how I can do that in my code please? Regards, Robert Re: MC9S12XEP100 Flash burner question Hi Ladislav, I have made some progress. To make a long story short, I discovered that my controller was secured. I don't know how that happened, but I was able to unsecure it and now your program is working the way you have shown in your last post. Now I am able to study your ASM code to make sure I understand it fully before I try to adapt it it work in my code. I have one thing that is puzzling me though. If I am understanding you r code correctly, you have placed your test data to be burned to D-Flash, in RAM memory starting at Buffer: (address $2100). But when I look at that address all I ever see is $CA,$FE, repeat. Why is this? Regards, Robert Re: MC9S12XEP100 Flash burner question I have the memory set to refresh on halt, but no matter what I do, the memory never changes. I've tried setting breakpoints where I see you have highlighted, but nothing. I tired running the program and halting it at random points. No change. What am I doing wrong? Re: MC9S12XEP100 Flash burner question Hi,
Do not step memory functions if the part of memory is displayed in the memory window of the debugger.
Set refresh memory when halting
First loop
Second loop … after erase sector
Second loop after writing data
Second loop reading the data
Moreover, it is always suitable to disable possible interrupts to do not change registers.
Create critical section which is not interrupted using CLI, SEI.
Best regards,
Ladislav
Re: MC9S12XEP100 Flash burner question Hi again Ladislav, After stepping through the program again several times I noticed some other peculiar things. After running the FLASH_ERASE_VERIFY subroutine the returned "err" was $01. Which was expected. However, after any FLASH_PROGRAM subroutine "returned "err" was $40. The FLASH_READ subroutine seems to work but it doesn't return the var_Data values I expected. It returns $FA, $CF first. $4 second. $BB $B6 third. $46 $46 forth. The values at address $100000 are $FA, $CF, $00,$04,$BB, $B6, $46, $46. These are not the values that should have been burned to this address if I am understanding the program correctly. The values at address $2100 are $CA,$FE,$CA,$FE,$CA,$FE,$CA,$FE and they don't change. Something seems odd here. Regards, Robert Re: MC9S12XEP100 Flash burner question Hi Ladislav, Thank you for that excellent attachment. It was just what I was looking for. It runs just fine on my controller, except for one thing. I can't seem to get the debugger to update the memory window, either for the RAM or the D-Flash. I when I single step through the program I expected to see the RAM addresses from $2100 to $2110 update with the appropriate steps. I'm not seeing this. I also expected to see the D-Flash addresses from $10000 to $100010 update as I step through, but I'm not seeing that either. Also, if I run the program and halt it, the memory locations are not updated. Are there some settings in the de-bugger that I don't have set right? Regards, Robert Re: MC9S12XEP100 Flash burner question I am very sorry but I see no issue to rebuilt C to ASM. C shows you principle and this C code is not a object oriented programming. It is simple Ansi C. Here you can see programming of D-Flash. (Not P-Flash, it is a little bit different but in principle very similar)
;************************************************************** ;* This stationery serves as the framework for a * ;* user application. For a more comprehensive program that * ;* demonstrates the more advanced functionality of this * ;* processor, please see the demonstration applications * ;* located in the examples subdirectory of the * ;* Freescale CodeWarrior for the HC12 Program directory * ;************************************************************** ; Include derivative-specific definitions INCLUDE 'derivative.inc'
; export symbols XDEF Entry, _Startup, main ; we use export 'Entry' as symbol. This allows us to ; reference 'Entry' either in the linker .prm file ; or from C/C++ later on
XREF __SEG_END_SSTACK ; symbol defined by the linker for the end of the stack
;********************************************************************* OK EQU 0 ERASED EQU 1 NON_ERASED EQU 2 LENGTH_OUT_OF_RANGE EQU 3 ;*********************************************************************
; variable/data section MY_EXTENDED_RAM: SECTION
; Insert here your data definition.
Buffer ds.w 4; Err ds.b 1; Addr ds.w 1; Cnt ds.b 1; var_i ds.b 1; var_j ds.b 1; var_Data ds.w 1; ;*********************************************************************
; code section MyCode: SECTION main: _Startup: Entry: ;--------------------------- LDS #__SEG_END_SSTACK ; initialize the stack pointer CLI ; enable interrupts ;--------------------------- EndlessLoop: ;--------------------------- ;EE_Init ... 0x0F //oscillator 16MHz -> divide by 0x0F to achieve FCLK 800kHz - 1.05MHz ;while(FSTAT_CCIF == 0); //wait if command in progress BRCLR FSTAT,#128,*+0 ;abs = 0001 ;FCLKDIV = fdiv; //osc = 16MHz LDAB #$0F STAB FCLKDIV ;--------------------------- ;DFLASH_Erase_Sector(0x0000); //erase first sector (256 bytes) MOVW #$0000,Addr CALL DFLASH_Erase_Sector ;--------------------------- ;err = DFLASH_Erase_Verify(0x0000, 16); //check if 16 words are erased - we will receive ERASED message MOVW #$0000,Addr MOVB #16,Cnt CALL DFLASH_Erase_Verify ; note there is a status of verification in the Err variable after execution of this command ;--------------------------- ;err = DFLASH_Program(0x0000, &buffer[0], 4); //write 4 words to D Flash address 0x0000
MOVW #$0000,Addr ; address to be written MOVB #4,Cnt ; number of words to be written ;for example data to be written into DFLASH are 0123, 4567, 89AB, CDEF LDX #Buffer ; Load the base address of the array into X register LDD #$0123 ; Load the value 0123 into A register STD 0,X ; Store the value at the 0th position of the array LDD #$4567 ; Load the value 4567 into A register STD 2,X ; Store the value at the 1st position of the array LDD #$89AB ; Load the value 89SB into A register STD 4,X ; Store the value at the 2nd position of the array LDD #$CDEF ; Load the value CDEF into A register STD 6,X ; Store the value at the 3rd position of the array
CALL DFLASH_Program ; note there is a status of verifiction in the Err variable after execution of this command ;--------------------------- ;err = DFLASH_Program(0x0008, &buffer[0], 4); //write 4 words to eeprom address 0x0000
MOVW #$0008,Addr ; address to be written MOVB #4,Cnt ; number of words to be written ;for example data to be written into DFLASH are 0123, 4567, 89AB, CDEF LDX #Buffer ; Load the base address of the array into X register LDD #$DEAD ; Load the value 0123 into A register STD 0,X ; Store the value at the 0th position of the array LDD #$BEEF ; Load the value 4567 into A register STD 2,X ; Store the value at the 1st position of the array LDD #$C0DE ; Load the value 89SB into A register STD 4,X ; Store the value at the 2nd position of the array LDD #$CAFE ; Load the value CDEF into A register STD 6,X ; Store the value at the 3rd position of the array
CALL DFLASH_Program ; note there is a status of verifiction in the Err variable after execution of this command ;--------------------------- ; get written data ;--------------------------- MOVW #$0000,Addr CALL DFLASH_Read STD var_Data
MOVW #$0002,Addr CALL DFLASH_Read STD var_Data
MOVW #$0004,Addr CALL DFLASH_Read STD var_Data
MOVW #$0006,Addr CALL DFLASH_Read STD var_Data ;--------------------------- JMP EndlessLoop ; restart. ;--------------------------- ;********************************************************************* ;DFLASH_Read ;********************************************************************* DFLASH_Read: MOVB #$10, GPAGE LDX Addr GLDD X RTC
;********************************************************************* ;DFLASH_Program ;********************************************************************* DFLASH_Program: ;if((Cnt < 1) || (Cnt > 4)) LDAB Cnt CMPB #1 BCS LBL_DP1 CMPB #4 BLS LBL_DP2 ;return LENGTH_OUT_OF_RANGE; LBL_DP1: MOVB #LENGTH_OUT_OF_RANGE,Err RTC LBL_DP2: ;while(FSTAT_CCIF == 0); //wait if command in progress BRCLR FSTAT,#128,*+0 ;abs = 000e ;FSTAT = 0x30; //clear ACCERR and PVIOL MOVB #$30, FSTAT ;FCCOBIX = 0x00; CLR FCCOBIX ;FCCOB = 0x1110; MOVW #$1110,FCCOB ;FCCOBIX = 0x01; MOVB #$1,FCCOBIX ;FCCOB = address; MOVW Addr,FCCOB ;for(i=2; i<=Cnt+1; i++) //fill appropriate number of words to FCCOB CLRA LDX #Buffer LDAB Cnt INCB STAB var_j ; end variable of cycle LDAA #$2 ; start value of cycle
LBL_DP3: ;FCCOBIX = A = 2 to {3,4,5}; STAA FCCOBIX ;FCCOB = *ptr; LDD 2,X+ STD FCCOB LDAA FCCOBIX INCA CMPA var_j BLS LBL_DP3 ;FSTAT_CCIF = 1; //launch command BSET FSTAT,#128 ;while(FSTAT_CCIF == 0); //wait for done BRCLR FSTAT,#128,*+0 ;abs = 004b ;return OK; MOVB OK,Err RTC
;********************************************************************* ;DFLASH_Erase_Verify ;********************************************************************* DFLASH_Erase_Verify: ;while(FSTAT_CCIF == 0); //wait if command in progress BRCLR FSTAT,#128,*+0 ;abs = 0001 ;FSTAT = 0x30; //clear ACCERR and PVIOL MOVB #$30,FSTAT ;FCCOBIX = 0x00; CLR FCCOBIX ;FCCOB = 0x1010; MOVW #$1010, FCCOB ;FCCOBIX = 0x01; MOVB #$1, FCCOBIX ;FCCOB = address; MOVW Addr, FCCOB ;FCCOBIX = 0x02; MOVB #$2, FCCOBIX ;FCCOB = number_of_bytes; MOVB Cnt,FCCOB ;FSTAT_CCIF = 1; //launch command BSET FSTAT,#128 ;while(FSTAT_CCIF == 0); //wait for done BRCLR FSTAT,#128,*+0 ;abs = 002b ;if(FSTAT_MGSTAT == 0) BRCLR FSTAT,#3,*+7 ;abs = 0037 BRA lbl_nonerased ;return ERASED; MOVB #ERASED, Err RTC lbl_nonerased: ;return NON_ERASED; MOVB #NON_ERASED, Err RTC
;********************************************************************* ;void DFLASH_Erase_Sector(unsigned int address) ;********************************************************************* DFLASH_Erase_Sector: ;while(FSTAT_CCIF == 0); //wait if command in progress BRCLR FSTAT,#128,*+0 ;abs = 0001 ;FSTAT = 0x30; //clear ACCERR and PVIOL MOVB #$30, FSTAT ;FCCOBIX = 0x00; CLR FCCOBIX ;FCCOB = 0x1210; MOVW #$1210, FCCOB ;FCCOBIX = 0x01; MOVB #$1, FCCOBIX ;FCCOB = address; MOVW Addr,FCCOB ;FSTAT_CCIF = 1; //launch command BSET FSTAT,#128 ;while(FSTAT_CCIF == 0); //wait for done BRCLR FSTAT,#128,*+0 ;abs = 0022 RTC ;********************************************************************* ;********************************************************************* ;********************************************************************* ;********************************************************************* ;*********************************************************************
Re: MC9S12XEP100 Flash burner question I'm still working hard at trying to figure this "C" code out but getting nowhere. The code runs and says that the first 256 bytes in D Flash have been erased at $10_0000, but I don't see that. Then it says that buffer[0] has been written into $0_0000, $10_0008 and $10_0010, But I don't see that either. What am I missing here? Regards, Robert Re: MC9S12XEP100 Flash burner question I'm still not getting anywhere with this. I've tried to figure out the ASM by stepping through the code, but I really have to be able to understand what the program is doing in "C" first. I believe that it partitions the DFlash then erases it all. Then it writes 16 bytes that it had written into RAM into D FLash. I can find the bytes in RAM, but in no place in D Flash can I find where it has written them in. Any suggestions would be greatly appreciated. Regards, Robert Re: MC9S12XEP100 Flash burner question Hi Ladislav, This is not easy stuff for me, but I was able to load your XEP100-DFLASH-CW47 program into my controller using a USBDM. I believe the program is running correctly. I expected to see the D-Flash address from $10_0000 loaded with $12, $34, $56, $78 $9A, $BC, $DE, $F0, but nothing is there. I also expected to see each of the remainder of the 256 byte sector loaded with $FF. Perhaps my understanding of how the program is supposed to work is flawed? Regards, Robert Re: MC9S12XEP100 Flash burner question Hi Ladislav, Thanks again for your prompt reply and the files. I am not a "C" engineer and only have a basic knowledge of the language so the disassembly process will be challenging, but I'll give it my best shot. Regards, Robert Re: MC9S12XEP100 Flash burner question Hi,
there are no similarities. It is 2 levels higher MCU with different memory organization. In this case I suggest to use DFLASH for data storage. There is no ASM code available but I believe it is not any problem to do it by disassembling C code. If you are C coding engineer it must be easy for you to rebuilt it to asm.
Here is a C code and the project is attached. You can go/step through the ASM code in debugger to see how it works.
I have also attached C code for PFLASH programming. Nothing easier but it does not require to perform partitioning of this memory. There are some similarities in addresses but global address must be used for data E/W. Short (4000-7FFF) and PPAGE_Offset addresses are used for program execution.
In the case of the MCU it will require more effort to understand how flash is organized and how it works.
Moreover, to go from relocatable assembly of the single file project to the absolute assembly is easy. Directive EQU is used for data placement into RAM and ORG is used to place code in given PFLASH space.
What is necessary to be understand is that for reading and writing DFLASH the global address must be used. However in the case of this memory it is solved easily because it has higher word (DPAFE ) always 0x10 so it is enough to send to the routine only offset in the range 0000-7FFF and full address is created in routine, for example DFLASH_Program..
I am sorry we do not have any empty space, resources or responsibility for such complex projects … plus in assembler.
Best regards,
Ladislav Re: MC9S12XEP100 Flash burner question Oops. I forgot to mention that when I try to erase the sectors I get an Access Error code. Regards, Robert Re: MC9S12XEP100 Flash burner question I'll try the attachment again
View full article