(solved) 25F80 EEPROM: Deaf to Page Write, but can Erase,Read,Read Status etc - Page 1
Forum section: electronics / general

author: Salome2
author_rank: Regular Contributor
timestamp: November 30, 2022, 05:13:02 pm
content: Help! I think I rechecked everything very carefully, but my SEEPROM will not burn data.Running MCU at 5V 40MHz (100nS instr cycle), .1uf film bypass cap Vcc-Vss, using level converters for MCU<--> 3.0V Vcc SEEPROM,all functions except pp write workperfectly. Scope shows clean +3V Vcc on EEPROM and 5V Vcc on MCU.Using MCU: PIC18F452 to burn data into EON25F80 8Mbit SEEPROM. Note: all other code works perfect, tested, verifiedNOTE:#WP write protection pin and #HOLD. both wired to +3V Vcc on EEPROMBefore attempting to program 25F80, I can read the entire chip. I have some pre-pgmed (salvaged PC BIOS chips ). No Problem. see all data. (Verified on 4-chan 200MHz scope)After running my Bulkerase() I can read (rd() routine) all of the EEPROM and all 8MBit Dout bits are 1.(Verified on 4-chan 200MHz scope)in pgmit(), after executing wren() to set WEL instruction, I can call my ReadStatusReg() and see only WEL (write enable bit) has been set (scope verified)No write protection bits are seen set.In my code below,I give the EEPROM >max pgm wait time to write a page to the EEPROMThe EEPROM is given at least .2-sec to warm up before calling pgmit()I have also tried a second EON25F80 and Winbond 25x80 EEPROM with code below with exactly same results.In other words, I can do anything else with the 25F80 except burn data into it!What am I possibly doing wrong!!!But after writing to a test portion of the entire 8Mbits, and examining on scope Dout in my Rd(), I see nothing but ones. NO Write!Code:void pgmit() // PP cmd=02 page program 256 bytes{ static signed char j;static unsigned char U=0,M=0,L=0; //starting page address Upper-Mid-Lostatic unsigned int b,k;//nCS active low chip select of SEEPROM, must go lo before any instruction and stay low. nCS-->1 to start burn after page filled//PP cmd=02// Sequence: wren(), nCS-->lo pp cmd Page Start Address UUUUUUUU MMMMMMMM 00000000 then byte0 byte1..byte 255//256 data bytes follow LoAddr to fill EEPROM write buffer//nCS-->1 starts programming, typ wait time 2.3mSec/page write, for test I exceed max spec'd wait for pp to finishStats(); //just a Serial debug routine that shows var vals to view on PC//--------------------------------- begin pp --------------------------------------------------nCS=1;for(k=0;k<2048;k++) //page ctr 2048 to test (32768 total pages x 256 bits/page=8388608 bits){ wren(); //Sets WEL write enable bit correctly (verifed by scope)//All other Control Register bits are 0(verified)//wren() exits setting nCS=1;FilBuf(); // dummy data 256 bytes of incrementing bytes 0-255.Bufnum++; //Can see this on my Stats() serial out to PC, just to watch progress of programmingnCS=0; //Active low Chip Select (nCS must hi-->lo to do any cmd) Sent to EEPROM b4 pp program page commandfor(j=7;j>-1;j--) //pp cmd 0000 0010 //cmd 02 PP program page{ if(j==1){ Din=1;}else{ Din=0;}Clock=1;Clock=0;Clock=1;}for(j=7;j>-1;j--) //send upper 8 bit of 24-bit write starting addr{ Din=(U>>j) & 1;Clock=1;Clock=0;Clock=1;}for(j=7;j>-1;j--) //send Middle 8-bit starting Addr{ Din=(M>>j) & 1;Clock=1;Clock=0;Clock=1;}for(j=7;j>-1;j--) /send Lower 8-bit //always 0 for 256 byte buffer fill{ Din=0;Clock=1;Clock=0;Clock=1;}for(b=0;b<256;b++) //Write Data to EEPROM internal 256 byte buffer{ for(j=7;j>-1;j--){ Din=(wbuf>>j) & 1;Clock=1;Clock=0;Clock=1;}}nCS=1; //page write starts when nCS-->1mSec1=0;w4Write:if(Sec & 1){ if(didit1==0){ Stats();}}else didit1=0;if(mSec1<7)goto w4Write; //2.3mS EON25F80 typical pgm time, max=6mSecM++;if(M==0){ U++;}}} //-------------- end of PageWrite PP 8Mbitvoid FilBuf(){ unsigned int k;for(k=0;k<256;k++) //dummy data for testing{ wbuf=k;}}//--------------------------void wren(){ static signed char j=0;//Cmd 06 7654 3210// 0000 0110nCS=1;Din=0;Clock=1;h=0;m=0;l=0;nCS=0;Sd();for(j=7;j>-1;j--){if(j==2){ Din=1;}else if(j==1){ Din=1;}else Din=0;Clock=1;Clock=0;Clock=1;}nCS=1; //nCS must 0-->1 to for WREN to set WELDin=0;} //---------------------------void Sd() //small delay used mostly to parse waveforms on scope{ NOP();}

author: ggchab
author_rank: Frequent Contributor
timestamp: November 30, 2022, 05:33:58 pm
content: Is the level of the "WP" pin correct in your circuit ?

author: Salome2
author_rank: Regular Contributor
timestamp: November 30, 2022, 05:38:14 pm
content: Yes, thanks for reminding me of not posting this..#WP pin is wired directly to Vcc

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 30, 2022, 06:11:16 pm
content: Please fix your code tags

author: Salome2
author_rank: Regular Contributor
timestamp: November 30, 2022, 06:21:20 pm
content: Ok..fixed code tags. Didn't know at first how to use them!

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 30, 2022, 06:54:13 pm
content: Huh what a terrible codingProbably the main issue is the clock, it's wrong everywhere:Code:Din=whatever; // <-- Update DinClock=1; // <-- This clock sends current DinClock=0;Clock=1; // <-- This creates another clock pulse before Din is updatedShould be:Code:Din=whatever; // <-- Update DinClock=1; // <-- This clock sends current DinClock=0;Some tidying:Code:void spi_send(unsigned char d) {unsigned char i=0;do {Din = ((d & 0x80) == 0x80); // Set ouput dataClock = 1; // Clock highd <<= 1; // Shift input data for next clockClock=0; // Clock low} while(++i < 8);}void pgmit() // PP cmd=02 page program 256 bytes{static unsigned char U=0,M=0,L=0; //starting page address Upper-Mid-Lostatic unsigned int b, p;Stats(); //just a Serial debug routine that shows var vals to view on PC//--------------------------------- begin pp --------------------------------------------------nCS=1;FilBuf(); // dummy data 256 bytes of incrementing bytes 0-255.for(p=0;p<2048;p++) { // page ctr 2048 to test (32768 total pages x 256 bits/page=8388608 bits)wren(); // Sets WEL write enable bit correctly (verifed by scope)// All other Control Register bits are 0(verified)// wren() exits setting nCS=1;Bufnum++; // Can see this on my Stats() serial out to PC, just to watch progress of programmingnCS=0; // Active low Chip Select (nCS must hi-->lo to do any cmd) Sent to EEPROM b4 pp program page commandspi_send(0x02); // pp cmd 0000 0010 //cmd 02 PP program pagespi_send(U); // send Upper 8 bit of 24-bit write starting addrspi_send(M); // send Middle 8-bit starting Addrspi_send(L); // send Lower 8-bit //always 0 for 256 byte buffer fillfor(b=0;b<256;b++) { // Write Data to EEPROM internal 256 byte bufferspi_send(wbuf);}nCS=1; //page write starts when nCS-->1mSec1=0;do {if(Sec & 1) {if(didit1==0) {Stats();}}elsedidit1=0;} while (mSec1<7); //2.3mS EON25F80 typical pgm time, max=6mSecif(++M==0) { // Increase Middle addressU++; // Increase High address}}}void FilBuf(void) {unsigned int i;for(i=0;i<256;i++) { //dummy data for testingwbuf=i;}}void wren() {nCS=0;Sd();spi_send(0x06);nCS=1;}Anyways, remember you can't simply write the memory, flash must be erased first:Code:void chip_erase(void) {nCS=0;wren(); // Write enablenCS=1;nCS=0;spi_send(0xC7); // Chip erase (Whole flash becomes 0xFF)nCS=1;// <<----- // WAIT 20 seconds for completion!}After running chip_erase, all the memory contents should be read FF.

author: Salome2
author_rank: Regular Contributor
timestamp: November 30, 2022, 07:07:16 pm
content: Holy Cow! Thanks a million. What a simple mistake.I C my error now, thousand thanks for cleaning up my code and now I can see the problem clearly.My problem code was not incrementing the page start middle address because i was inc H(a not used var) instead of M.(I corrected this in my code posting)I was using SPI Mode 3 (which should work since the rising edge of the last Clock=1 in my clocking sequence clocks in Din correctly).I wrote my code this way to use SPI mode 3 to set Clock hi each time after clocking in anything/Din).Of course to use this method, I must set Clock-->hi before any beginning a cmd sequence with nCS-->lo for my code to clock correctly.Din clocks in with a lo-->hi transition, Dout clocks out with hi-->lo transition.But the final result is:I now see Dout.I don't quite yet see any other problems with my code other than excess c-verbiage, but I am still looking!

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 30, 2022, 07:19:01 pm
content: Also that one, yeah.I corrected several errors that would cause other issues, but the worst one was the clock messing everything up.

author: Salome2
author_rank: Regular Contributor
timestamp: November 30, 2022, 07:51:06 pm
content: I still don't get it why my clocking sequence would not work correctly.I was using SPI Mode 3 (which should work since the rising edge of the last Clock=1 in my clocking sequence clocks in Din correctly).I wrote my code this way to use SPI mode 3 to set Clock hi each time after clocking in anything/Din).Of course to use this method, I must set Clock-->hi before any nCS-->lo (start of an active cmd sequence) for my code to clock correctly.=====15-mins later!I now also see that the first Clock-->1 is the wrong way to start since I can only clock in Din with a 0-->1 clock transition and there is the possibility of double clocking when I start out with Clock=1 in my sequence, that is, if any previous clocking code left clock lo.Also, it is certain my code adds an extra line of code that has a possibility of creating big problems.

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 30, 2022, 08:00:46 pm
content: Ah,I see. It was a bit confusing. Then:Code:void spi_send(unsigned char d) {unsigned char i=0;do {Clock=0; // Clock lowDin = ((d & 0x80) == 0x80); // Set ouput dataClock = 1; // Clock highd <<= 1; // Shift input data for next clock} while(++i < 8);}Or your version:Code:for(j=7; j>-1; j--) {Clock=0;Din=whatever;Clock=1;}

author: Salome2
author_rank: Regular Contributor
timestamp: November 30, 2022, 08:15:45 pm
content: Thanks DavidAlfa,I always think the easiest to read code is the best code.Your last clocking solution(which you attribute to me!) is so simple to read but incorrect.(It fails to serialize each byte's Din bit values)Code easiest to read and understand is ALWAYS best, while your above code clock coding was both correct, yet too elegant.

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 30, 2022, 08:19:54 pm
content: Anyways, when you get it working, use the hardware SPI module, will be much faster

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 30, 2022, 08:40:46 pm
content: If you really want to get it nice, use some enums.And make proper functions instead repeating the same code again and againEdit: Remove HW SPI due the errata.Code:typedef enum{en25_status_wr = 0x01,en25_page_prog = 0x02,en25_read = 0x03,en25_write_dis = 0x04,en25_status_rd = 0x05,en25_write_en = 0x06,en25_fast_read = 0x0B,en25_sect_erase = 0x20,en25_blk_erase = 0x52,en25_chip_erase = 0x60,en25_sleep = 0xB9,en25_wake = 0xAB,} en25_cmds;void spi_write(unsigned char d) {unsigned char i=0;do {Clock=0; // Clock lowDin = ((d & 0x80) == 0x80); // Set ouput dataClock = 1; // Clock highd <<= 1; // Shift input data for next clock} while(++i < 8);}unsigned char spi_read(void) {unsigned char i=0, d=0;do {Clock=0; // Clock lowd <<= 1; // Shift input data for next clockClock = 1; // Clock highd |= (Dout && 1); // Sample input data} while(++i < 8);return d;}void spi_cmd(unsigned char c){nCS=0;spi_write(c);nCS=1;}void pgmit(void) {// ...spi_cmd(en25_write_en);Bufnum++; // Can see this on my Stats() serial out to PC, just to watch progress of programmingnCS=0;spi_write(en25_page_prog);spi_write(U); // send Upper 8 bit of 24-bit write starting addrspi_write(M); // send Middle 8-bit starting Addrspi_write(L); // send Lower 8-bit //always 0 for 256 byte buffer fill// ...nCS=1;}

author: Salome2
author_rank: Regular Contributor
timestamp: November 30, 2022, 09:23:49 pm
content: Errata18F452Using the fast SPI HW machine may add new flies to the soup:Module: MSSP (All I2C™ andSPI™ Modes)The Buffer Full (BF) flag bit of the SSPSTATregister (SSPSTAT<0>) may be inadvertentlycleared even when the SSPBUF register has notbeen read. This will occur only when the followingtwo conditions occur simultaneously:• The four Least Significant bits of the BSRregister are equal to 0Fh (BSR<3:0> = 1111)and• Any instruction that contains C9h in its 8 LeastSignificant bits (i.e., register file addresses,literal data, address offsets, etc.) is executed.

author: DavidAlfa
author_rank: Super Contributor
timestamp: November 30, 2022, 09:45:42 pm
content: Ouch, the erratas.Is it a C0 revision?

author: Salome2
author_rank: Regular Contributor
timestamp: November 30, 2022, 10:45:15 pm
content: Yes, it appears to be a C0 rev. What strange conditions to cause a SPI fault!