PIC18F67K22 can't write EEPROM - Page 1
Forum section: electronics / general

author: firstcolle
author_rank: Regular Contributor
timestamp: April 22, 2017, 02:14:43 pm
content: Hi, I'm having some troubles with writing the EEPROM memory of a 18F67K22. some detail- 3.3v with external regulator (this mean ENVREG tied to GND)- clock internal osc with PLL enabled (64Mhz, but the issue remain also at lower speed)- i use my on routine but is identical with the one created with MCC, the same routine works on PIC18F26K22 and 18F46K22 and much more.it seems that the byte can't be written in EEPROM. during debug the PC skip the EECON2 = 0x55 and 0xAA instruction and i can't understand why.. is there some sort of enamblig method on this PIC?here is the wrtite routine..Code:unsigned char GIEBitValue = INTCONbits.GIE;EEADR = (data_address & 0xFF);EEDATA = data_byte;EECON1bits.EEPGD = 0;EECON1bits.CFGS = 0;EECON1bits.WREN = 1;INTCONbits.GIE = 0; // Disable interruptsEECON2 = 0x55;EECON2 = 0xAA;EECON1bits.WR = 1;// Wait for write to completewhile (EECON1bits.WR){}EECON1bits.WREN = 0;INTCONbits.GIE = GIEBitValue; // Restore interrupt enablemany thanks

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: April 22, 2017, 06:44:06 pm
content: Quote from: firstcolle on April 22, 2017, 02:14:43 pmHere's what the datasheet says about how to enable writes:-Code:MOVLW 0x55 ;Required MOVWF EECON2 ; Write 55hSequence MOVLW 0xAA ;MOVWF EECON2 ; Write 0AAhBSF EECON1, WR ; Set WR bit to begin writeBTFSC EECON1, WR ; Wait for write to completeGOTO $-2The datasheet's explanation is a bit ambiguous, but I suspect the instructions have to be executed in sequence without anything else happening in between. So the debugger 'skips over' those instructions because they have to be executed in real-time.

author: Ian.M
author_rank: Super Contributor
timestamp: April 22, 2017, 07:32:02 pm
content: IIRC, from the hardware's point of view, the critical sequence is:Tcycle Operation1 Write 0x55 to EECON22 - don't care -3 Write 0xAA to EECON24 EECON1.WR bit is unlocked for this instruction only.The write of 0x55 to EECON2 'starts the clock'. If the write of 0xAA doesn't happen two instructions later, the WR bit unlock for the next instruction cycle is cancelled. Anything more complex would require the EEPROM access controller to sniff the CPU core state which would require more interconnects, wasting die area and tightly coupling the EEPROM module to the core design.

author: jolshefsky
author_rank: Regular Contributor
timestamp: April 22, 2017, 07:49:46 pm
content: I have been wrestling with the PIC internal EEPROM for a while. I still don't have a proper solution to my problem (occasional, specific writes of 0x02 when not expected) which I documentedhere.What I do know, though, is that the "magic sequence" must be followed exactly:Code:MOVLW 0x55MOVWF EECON2MOVLW 0xAAMOVWF EECON2Two things can be a problem: interrupts, and compilers. You already have the bit to turn off interrupts, but you may have the issue that some compilers will redundantly set the RAM page bit resulting in a problem, so your snippetCode:EECON2 = 0x55;EECON2 = 0xAA;might actually result in something like:Code:MOVLW 0x55BSF STATUS.RP0MOVWF EECON2MOVLW 0xAABSF STATUS.RP0MOVWF EECON2which does not work and the processor ignores it (no EEPROM write). You may need to add an assembly snippet in your routine to ensure this doesn't happen.

author: cv007
author_rank: Frequent Contributor
timestamp: April 23, 2017, 07:47:02 am
content: QuoteWatch out for this as EEADR is defined as an unsigned char even though it would seem that should address the whole register pair (it would seem they did this to match the datasheet naming). There is only EEADR and EEADRH. The EEADRH is supposed to be 00 on reset, so unless you are setting either of those bits somewhere else, it should not matter. If you are touching those bits somewhere else, then it would matter as the EEADRH is not set in your code you have shown. Since you are and'ing the data_address with 0xFF, I assume you are working with a 16bit data_address, and possibly assuming EEADR is also 16bits. In any case I would set EEADRH-EEADR = data_address;EEADRH = data_address >> 8;

author: firstcolle
author_rank: Regular Contributor
timestamp: April 23, 2017, 08:27:37 am
content: the problem was the compiler.. infact the ASM code was generated without theCode:MOVLW 0x55MOVWF EECON2MOVLW 0xAAMOVWF EECON2i solved the problem usingCode:asm("MOVLW 0x55");asm("MOVWF EECON2");asm("MOVLW 0xAA");asm("MOVWF EECON2");

author: JPortici
author_rank: Super Contributor
timestamp: April 23, 2017, 08:37:45 am
content: which compiler? XC8 doesn't skip those instructions, infact on some of the newer pic16/18 datasheets the code is given out in C directly.

author: Ian.M
author_rank: Super Contributor
timestamp: April 23, 2017, 08:45:52 am
content: That doesn't guarantee the problem will stay solved if you add code to the program, change optimisation level or upgrade the compiler. If you haveCode:asm("MOVLW 0x55");asm("MOVWF EECON2");asm("MOVLW 0xAA");asm("MOVWF EECON2");EECON1bits.WR = 1;the compiler may choose to insert instructions between the last asm() statement and setting the WR bit in C. To make sure it stays fixed, you *MUST* set the WR bit using an assembler BSF instruction.@JPortici: There's a known issue with some versions of the compiler - at high optimisation levels, if you have more than one EEPROM unlock sequence in the program, the optimiser may recognise the code duplication and replace all copies with a subroutine call to a single copy. Unfortunately, the optimiser sometimes isn't aggressive enough and fails to put the following BSF EECON1,1 in the subroutine, which causes the subroutine RETURN to break the critical unlock sequence.

author: cv007
author_rank: Frequent Contributor
timestamp: April 23, 2017, 04:59:38 pm
content: QuoteSeems odd ANY compiler would optimize away writing to volatile defined registers. You write to a volatile, the compiler will be writing to that register- maybe not in the required time frame, but it will write to it. If not, then we are all in big trouble.The OP's code posted will compile correctly (required time frame) in XC8/v1.41/Free, it will also work for 16F.Procedural abstraction in XC8 only works in PRO mode, but even if that is happening here (PRO mode user asking questions here?), the OP surely could see the call taking place to that code if that is what happened. We are missing some information it seems.