(Sorry for my English)
Hello,
I'm using a MC9S12DJ128 MCU and I want to write in the 2k EEPROM. By searching a lot on the internet, I managed to do what I wanted, but not the way I wanted... I'm currently writing in the EEPROM by using theses commands in codewarrior (found in the UNSECURE command file):
reset
wb 0x03c 0x00 //disable cop
wait 20
wb 0x110 0x09 // set ECLKDV clock to 2Mhz
wb 0x114 0xFF // EPROT all protection disabled
wb 0x115 0x30 // clear PVIOL and ACCERR in ESTAT register
wb 0x112 0x00 // clear the WRALL bit in FTSTMOD
wb 0x115 0x02
ww 0x118 0x002E // write to EADDR eeprom address register
ww 0x11A 0x0000 // write to EDATA eeprom data register
wb 0x116 0x60 // write SECTOR MODIFY command in ECMD register
wb 0x115 0x80 // clear CBEIF in ESTAT register to execute the command
wait 20
Now, I want to do the same thing WITHOUT using the BDM port. I will run the code in a bootloader, and it needs to be in assembly. This is what I've done so far, but it's not working:
MOVB #$00,$003C
MOVB #$09,$0110
MOVB #$FF,$0114
MOVB #$30,$0115
MOVB #$00,$0112
MOVB #$02,$0115
MOVW #$002E,$0118
MOVW #$0000,$011A
MOVB #$60,$0116
MOVB #$80,$0115
I don't know how to do a reset in assembly, maybe that's the problem... Or maybe the timings are wrong...? (I'm a complete beginner in assembly). Please help me !
Thanks
Solved! Go to Solution.
hi,
Following example is for DP512. The principle is the same. Just placement and sizes are different.
You can check also principle in the C code project- attached.
Best regards, Ladislav
;_______________________________________________________________________________
; - Example present erase sector and write word to the EEPROM
; - Before write it checks:
; * alignment (2B)
; * whether sector is erased
; - Before sector erase it checks:
; * alignment (4B)
; - Variable err_code is used as a error return code
;
;_______________________________________________________________________________
;The Answer to the Ultimate Question of Life, the Universe, and Everything is: 42
;(Douglas Adams - The Hitchhiker's Guide to the Galaxy)
;_______________________________________________________________________________
; export symbols
XDEF Entry ; export 'Entry' symbol
ABSENTRY Entry ; for absolute assembly: mark this as application entry point
; include derivative specific macros
INCLUDE 'derivative.inc'
;_______________________________________________________________________________
; definitions
;_______________________________________________________________________________
ROMStart EQU $C000 ; absolute address to place my code/constant data
ERR_OK: EQU $0 ; OK
ERR_RANGE: EQU $1 ; Parameter out of range. (not alligned sector 4B; data 2B))
ERR_BUSY: EQU $2 ; Device is busy.
ERR_NOTAVAIL: EQU $3 ; Requested value or method not available.
ERR_NOTERASED: EQU $4 ; Requested address is not erased
;_______________________________________________________________________________
; variable/data section
;_______________________________________________________________________________
ORG RAMStart
;_______________________________________________________________________________
EE_address DS.W 1 ; address for sector erase or data write
EE_data DS.W 1 ; data to be written
err_code DS.B 1 ; return value from flash erase/write functions
;_______________________________________________________________________________
; code section
;_______________________________________________________________________________
ORG ROMStart
;_______________________________________________________________________________
; main loop
;_______________________________________________________________________________
Entry:
;--- memory mapping ------------------
;- reset default memory mapping is: --
;INITRG = 0x00; Set the Reg map position 0x0000~0x03FF
;INITEE = 0x01; Set the EEPROM map position 0x0000~0x0FFF, EEON=1 => visible 0x0400~0x0FFF
;INITRM = 0x09; Set the RAM map position 0x0800~0x3FFF
MOVB #$01,INITRM ; INITRM = 0x01; Set the RAM map position 0x0800~0x3FFF
MOVB #$41,INITEE ; INITEE = 0x41; Set the EEPROM map position 0x4000~0x4FFF, EEON=1
MOVB #$0 ,INITRG ; INITRG = 0x00; Set the Reg map position 0x0000~0x03FF
NOP; ; recommended
;--- Initialize stack ----------------
LDS #$4000 ; initialize stack on the top of RAM
;--- EEPROM clock---------------------
; MOVB #$29,ECLKDIV ; ECLKDIV = 0x29, eeprom clock prescaler; OSCCLK = 8MHz BUSCLK=4MHz
MOVB #$4A,ECLKDIV ; ECLKDIV = 0x4A, eeprom clock prescaler; OSCCLK = 16MHz BUSCLK=8MHz
loop:
;--- Erase sector --------------------
MOVW #$4000,EE_address ; prepare address for write function
JSR EraseSector ; erase sector at address $4000
;--- Write word to eeprom ------------
MOVW #$4000,EE_address ; prepare address for write function
MOVW #$1234,EE_data ; prepre data for write function
JSR WriteWord ; write word to the eeprom without checking address and EEPROM erased
;--- check error code and written data
;...
;...
;...
;--- Write word to eeprom ------------
MOVW #$4002,EE_address ; prepare address for write function
MOVW #$5678,EE_data ; prepre data for write function
JSR WriteWord ; write word to the eeprom without checking address and EEPROM erased
;--- check error code and written data
;...
;...
;...
;--- loop forever---------------------
JMP loop ; endless loop
;_______________________________________________________________________________
; WriteWord
; inputs: EE_address
; EE_data
; output: err_code
;_______________________________________________________________________________
WriteWord:
PSHD
PSHX
LDD EE_address ; check alignment (4B)
LDX #$2
IDIV
CPD #$0 ; if != $0 => error
BEQ WriteWord_LBL6
MOVB #ERR_RANGE,err_code ;return ERR_RANGE;
BRA WriteWord_LBL2
WriteWord_LBL6: ; check whether word is errased
LDX EE_address ;*(volatile word *) AddrRow = Data16; // Array address and program data
LDD 0,X
CPD #$FFFF ; if != $FFFF => error
BEQ WriteWord_LBL5
MOVB #ERR_NOTERASED,err_code ;return ERR_BUSY; // If yes then error
BRA WriteWord_LBL2
WriteWord_LBL5:
BRSET ESTAT,#128,WriteWord_LBL1 ;if (ESTAT_CBEIF == 0) // Is command buffer full ?
MOVB #ERR_BUSY,err_code ;return ERR_BUSY; // If yes then error
BRA WriteWord_LBL2
WriteWord_LBL1:
MOVB #$30,ESTAT ;ESTAT = 0x30; // Clear error flags
LDX EE_address ;*(volatile word *) AddrRow = Data16; // Array address and program data
LDD EE_data
STD 0,X
MOVB #$20,ECMD ;ECMD = 0x20; // Word program command
BSET ESTAT,#$80 ;ESTAT_CBEIF = 1; // Clear flag command buffer empty
BRSET ESTAT,#$20,WriteWord_LBL3 ;if ((ESTAT_PVIOL == 1)||(ESTAT_ACCERR == 1)) // Is protection violation or acces error detected ?
BRCLR ESTAT,#$10,WriteWord_LBL4
WriteWord_LBL3:
MOVB #ERR_NOTAVAIL,err_code ;return ERR_NOTAVAIL; // If yes then error
BRA WriteWord_LBL2
WriteWord_LBL4:
LDAB ESTAT ;while (EEPROM_BUSY); // Wait for command completition
ANDB #192
CMPB #192
BNE WriteWord_LBL4
MOVB ERR_OK,err_code ;return ERR_OK;
WriteWord_LBL2:
PULX
PULD
RTS
;_______________________________________________________________________________
; EraseSector
; inputs: EE_address
; output: err_code
;_______________________________________________________________________________
EraseSector:
PSHD
PSHX
LDD EE_address ; check alignment (4B)
LDX #$4
IDIV
CPD #$0 ; if != $0 => error
BEQ EraseSector_LBL5
MOVB #ERR_RANGE,err_code ;return ERR_RANGE;
BRA EraseSector_LBL2
EraseSector_LBL5:
BRSET ESTAT,#128,EraseSector_LBL1;if (ESTAT_CBEIF == 0) // Is command buffer full ?
MOVB #ERR_BUSY,err_code ;return ERR_BUSY; // If yes then error
BRA EraseSector_LBL2
EraseSector_LBL1:
MOVB #$30,ESTAT ;ESTAT = 0x30; // Clear error flags
LDX EE_address ;*(volatile word *) AddrRow = Data16; // Array address and program data
LDD #$FFFF ; dummy data
STD 0,X
MOVB #$40,ECMD ;ECMD = 0x20; // Word program command
BSET ESTAT,#$80 ;ESTAT_CBEIF = 1; // Clear flag command buffer empty
BRSET ESTAT,#$20,EraseSector_LBL3 ;if ((ESTAT_PVIOL == 1)||(ESTAT_ACCERR == 1)) // Is protection violation or acces error detected ?
BRCLR ESTAT,#$10,EraseSector_LBL4
EraseSector_LBL3:
MOVB #ERR_NOTAVAIL,err_code ;return ERR_NOTAVAIL; // If yes then error
BRA EraseSector_LBL2
EraseSector_LBL4:
LDAB ESTAT ;while (EEPROM_BUSY); // Wait for command completition
ANDB #192
CMPB #192
BNE EraseSector_LBL4
MOVB ERR_OK,err_code ;return ERR_OK;
EraseSector_LBL2:
PULX
PULD
RTS
;_______________________________________________________________________________
;**************************************************************
;* Interrupt Vectors *
;**************************************************************
ORG $FFFE
DC.W Entry ; Reset Vector
Ok, I think I understand now. I have not tested it yet, but this is the code I've came up with by following your advices:
;SET MEMORY MAP
MOVB #$01,INITRM ;MAP RAM TO 0x0800~0x3FFF
MOVB #$0,INITRG ;MAP REG TO 0x0000~0x03FF
MOVB #$41,INITEE ;MAP EEPROM TO 0x4000~0x47FF
;SETUP
MOVB #$00,$003C ;DISABLE COP
MOVB #$09,$0110 ;SET ECLKDIV TO 2MHz
MOVB #$FF,$0114 ;EPROT ALL PROTECTION DISABLED
;ERASE SECTOR
MOVB #$30,$0115 ;CLEAR PVIOL AND ACCERR IN ESTAT
LDX #$405C ;EEPROM BASE ADDRESS (0x4000) + DATA LOCATION (0x005C)
LDD #$FFFF ;DUMMY DATA
STD 0,X ;WRITE DATA @ ADDRESS
MOVB #$40,ECMD ;SECTOR ERASE COMMAND IN ECMD
BSET ESTAT,#$80 ;LAUNCH COMMAND
;WRITE WORD
MOVB #$30,$0115 ;CLEAR PVIOL AND ACCERR IN ESTAT
LDX #$405C ;EEPROM BASE ADDRESS (0x4000) + DATA LOCATION (0x005C)
LDD #$0000 ;DATA HERE
STD 0,X ;WRITE DATA @ ADDRESS
MOVB #$20,ECMD ;WORD PROGRAM COMMAND IN ECMD
BSET ESTAT,#$80 ;LAUNCH COMMAND
Do you think I'm good with this ? I'm not quite sure about the ECLKDIV value I should use... =/
Thanks
I have just returned from vacation. Do you still need a help or you have already solved your issue?
Yes it is, I forgot to mark it solved. Thank you !
hi,
Following example is for DP512. The principle is the same. Just placement and sizes are different.
You can check also principle in the C code project- attached.
Best regards, Ladislav
;_______________________________________________________________________________
; - Example present erase sector and write word to the EEPROM
; - Before write it checks:
; * alignment (2B)
; * whether sector is erased
; - Before sector erase it checks:
; * alignment (4B)
; - Variable err_code is used as a error return code
;
;_______________________________________________________________________________
;The Answer to the Ultimate Question of Life, the Universe, and Everything is: 42
;(Douglas Adams - The Hitchhiker's Guide to the Galaxy)
;_______________________________________________________________________________
; export symbols
XDEF Entry ; export 'Entry' symbol
ABSENTRY Entry ; for absolute assembly: mark this as application entry point
; include derivative specific macros
INCLUDE 'derivative.inc'
;_______________________________________________________________________________
; definitions
;_______________________________________________________________________________
ROMStart EQU $C000 ; absolute address to place my code/constant data
ERR_OK: EQU $0 ; OK
ERR_RANGE: EQU $1 ; Parameter out of range. (not alligned sector 4B; data 2B))
ERR_BUSY: EQU $2 ; Device is busy.
ERR_NOTAVAIL: EQU $3 ; Requested value or method not available.
ERR_NOTERASED: EQU $4 ; Requested address is not erased
;_______________________________________________________________________________
; variable/data section
;_______________________________________________________________________________
ORG RAMStart
;_______________________________________________________________________________
EE_address DS.W 1 ; address for sector erase or data write
EE_data DS.W 1 ; data to be written
err_code DS.B 1 ; return value from flash erase/write functions
;_______________________________________________________________________________
; code section
;_______________________________________________________________________________
ORG ROMStart
;_______________________________________________________________________________
; main loop
;_______________________________________________________________________________
Entry:
;--- memory mapping ------------------
;- reset default memory mapping is: --
;INITRG = 0x00; Set the Reg map position 0x0000~0x03FF
;INITEE = 0x01; Set the EEPROM map position 0x0000~0x0FFF, EEON=1 => visible 0x0400~0x0FFF
;INITRM = 0x09; Set the RAM map position 0x0800~0x3FFF
MOVB #$01,INITRM ; INITRM = 0x01; Set the RAM map position 0x0800~0x3FFF
MOVB #$41,INITEE ; INITEE = 0x41; Set the EEPROM map position 0x4000~0x4FFF, EEON=1
MOVB #$0 ,INITRG ; INITRG = 0x00; Set the Reg map position 0x0000~0x03FF
NOP; ; recommended
;--- Initialize stack ----------------
LDS #$4000 ; initialize stack on the top of RAM
;--- EEPROM clock---------------------
; MOVB #$29,ECLKDIV ; ECLKDIV = 0x29, eeprom clock prescaler; OSCCLK = 8MHz BUSCLK=4MHz
MOVB #$4A,ECLKDIV ; ECLKDIV = 0x4A, eeprom clock prescaler; OSCCLK = 16MHz BUSCLK=8MHz
loop:
;--- Erase sector --------------------
MOVW #$4000,EE_address ; prepare address for write function
JSR EraseSector ; erase sector at address $4000
;--- Write word to eeprom ------------
MOVW #$4000,EE_address ; prepare address for write function
MOVW #$1234,EE_data ; prepre data for write function
JSR WriteWord ; write word to the eeprom without checking address and EEPROM erased
;--- check error code and written data
;...
;...
;...
;--- Write word to eeprom ------------
MOVW #$4002,EE_address ; prepare address for write function
MOVW #$5678,EE_data ; prepre data for write function
JSR WriteWord ; write word to the eeprom without checking address and EEPROM erased
;--- check error code and written data
;...
;...
;...
;--- loop forever---------------------
JMP loop ; endless loop
;_______________________________________________________________________________
; WriteWord
; inputs: EE_address
; EE_data
; output: err_code
;_______________________________________________________________________________
WriteWord:
PSHD
PSHX
LDD EE_address ; check alignment (4B)
LDX #$2
IDIV
CPD #$0 ; if != $0 => error
BEQ WriteWord_LBL6
MOVB #ERR_RANGE,err_code ;return ERR_RANGE;
BRA WriteWord_LBL2
WriteWord_LBL6: ; check whether word is errased
LDX EE_address ;*(volatile word *) AddrRow = Data16; // Array address and program data
LDD 0,X
CPD #$FFFF ; if != $FFFF => error
BEQ WriteWord_LBL5
MOVB #ERR_NOTERASED,err_code ;return ERR_BUSY; // If yes then error
BRA WriteWord_LBL2
WriteWord_LBL5:
BRSET ESTAT,#128,WriteWord_LBL1 ;if (ESTAT_CBEIF == 0) // Is command buffer full ?
MOVB #ERR_BUSY,err_code ;return ERR_BUSY; // If yes then error
BRA WriteWord_LBL2
WriteWord_LBL1:
MOVB #$30,ESTAT ;ESTAT = 0x30; // Clear error flags
LDX EE_address ;*(volatile word *) AddrRow = Data16; // Array address and program data
LDD EE_data
STD 0,X
MOVB #$20,ECMD ;ECMD = 0x20; // Word program command
BSET ESTAT,#$80 ;ESTAT_CBEIF = 1; // Clear flag command buffer empty
BRSET ESTAT,#$20,WriteWord_LBL3 ;if ((ESTAT_PVIOL == 1)||(ESTAT_ACCERR == 1)) // Is protection violation or acces error detected ?
BRCLR ESTAT,#$10,WriteWord_LBL4
WriteWord_LBL3:
MOVB #ERR_NOTAVAIL,err_code ;return ERR_NOTAVAIL; // If yes then error
BRA WriteWord_LBL2
WriteWord_LBL4:
LDAB ESTAT ;while (EEPROM_BUSY); // Wait for command completition
ANDB #192
CMPB #192
BNE WriteWord_LBL4
MOVB ERR_OK,err_code ;return ERR_OK;
WriteWord_LBL2:
PULX
PULD
RTS
;_______________________________________________________________________________
; EraseSector
; inputs: EE_address
; output: err_code
;_______________________________________________________________________________
EraseSector:
PSHD
PSHX
LDD EE_address ; check alignment (4B)
LDX #$4
IDIV
CPD #$0 ; if != $0 => error
BEQ EraseSector_LBL5
MOVB #ERR_RANGE,err_code ;return ERR_RANGE;
BRA EraseSector_LBL2
EraseSector_LBL5:
BRSET ESTAT,#128,EraseSector_LBL1;if (ESTAT_CBEIF == 0) // Is command buffer full ?
MOVB #ERR_BUSY,err_code ;return ERR_BUSY; // If yes then error
BRA EraseSector_LBL2
EraseSector_LBL1:
MOVB #$30,ESTAT ;ESTAT = 0x30; // Clear error flags
LDX EE_address ;*(volatile word *) AddrRow = Data16; // Array address and program data
LDD #$FFFF ; dummy data
STD 0,X
MOVB #$40,ECMD ;ECMD = 0x20; // Word program command
BSET ESTAT,#$80 ;ESTAT_CBEIF = 1; // Clear flag command buffer empty
BRSET ESTAT,#$20,EraseSector_LBL3 ;if ((ESTAT_PVIOL == 1)||(ESTAT_ACCERR == 1)) // Is protection violation or acces error detected ?
BRCLR ESTAT,#$10,EraseSector_LBL4
EraseSector_LBL3:
MOVB #ERR_NOTAVAIL,err_code ;return ERR_NOTAVAIL; // If yes then error
BRA EraseSector_LBL2
EraseSector_LBL4:
LDAB ESTAT ;while (EEPROM_BUSY); // Wait for command completition
ANDB #192
CMPB #192
BNE EraseSector_LBL4
MOVB ERR_OK,err_code ;return ERR_OK;
EraseSector_LBL2:
PULX
PULD
RTS
;_______________________________________________________________________________
;**************************************************************
;* Interrupt Vectors *
;**************************************************************
ORG $FFFE
DC.W Entry ; Reset Vector
Program algorithm used by CW is only usable in special modes, which are not usable without BDM. EADDR and EDATA registers (0x118, 0x11A) are not working in normal modes. Instead you need to write your data directly to EEPROM array, you need to replace
MOVW #$002E,$0118 <-- 2E is EEPROM word number
MOVW #$0000,$011A
with
;don't know where your EEPROM is mapped to in normal mode, say it is at 0x800, then
MOVW #$0000, $085C ; <-- 5c is 2E*2, byte offset from start of EEPROM array
Hi, thank you for your answer.
Do I need to keep all the MOVB instructions ? Also, according to the datasheet, my EEPROM is at 0x800 like you said, but is it normal I can't see the data in the Codewarior's Memory View tab at 0x800 ? Sometimes it appears at 0x2000 and 0x3000, but since it's RAM, I guess it's normal ? Thanks