Author Topic: Trouble when bit banging SST39SF040A  (Read 929 times)

0 Members and 1 Guest are viewing this topic.

Offline NivagSwerdnaTopic starter

  • Super Contributor
  • ***
  • Posts: 2507
  • Country: gb
Trouble when bit banging SST39SF040A
« on: August 18, 2020, 10:59:02 am »
I have a SST39SF040A (512K x 8 ) flash which I am trying to program and it is misbehaving.... some bytes seem to stick whereas other ones don't work out...

If I program...

I intended to program...

Code: [Select]
00004000 : 1D C7 48 C6 35 CC EF C7 C5 CA DF CA 70 CF 23 CB 9C C8 9C C7 74 C7 1F C8 0C C7 7F C7 C9 C7 32 C8 
00004020 : 1B C7 42 C8 01 D7 D4 FF D7 FF DA FF 94 D2 F8 D6 7E C9 9E C9 44 C7 A7 C5 6F C7 84 C9 DD FF BF FF
00004040 : C2 FF 9E CA 50 C5 0B DB 9E DB 2A DB 00 00 64 D2 85 D2 24 DE 45 DF BF D8 A0 DE 9E DF A5 DF EE DF
00004060 : 48 E0 E6 D6 54 D6 49 D3 85 D6 63 D6 C4 D5 D8 D5 04 D6 0F D6 79 3E D7 79 27 D7 7B FF D8 7B E3 D9
00004080 : 7F 2D DE 50 D8 CE 46 D5 CE 7D 66 DE 5A E7 CD 64 05 CF 45 4E C4 46 4F D2 4E 45 58 D4 44 41 54 C1
...

then when verifying (* means mismatch)

Code: [Select]
00004000 : 00*C7 40*C6 15*CC EF C7 84*CA C0*CA 60*CF 02*CB 8C*C8 8C*C7 04*C7 0F*C8 0C C7 0F*C7 C9 C7 02*C8 
00004020 : 1A*C7 42 C8 01 D7 D4 FF D7 FF DA FF 84*D2 00*D6 0A*C9 8A*C9 40*C7 A4*C5 66*C5*80*C9 DD FF BF FF
00004040 : C2 FF 1C*CA 50 C5 01*DB 98*DB 20*DB 00 00 40*D2 00*D2 04*DE 45 DF B6*D8 80*DE 98*DF 85*DF 28*C0*
00004060 : 08*E0 E0*D6 54 D6 09*D3 85 D6 61*D6 C4 D5 D8 D5 04 D6 01*D6 79 34*D7 79 25*D7 7B 36*D8 7B 01*D8*
00004080 : 7F 25*DE 50 C8*CE 46 C5*CE 7D 20*DE 5A C6*CD 64 05 CE*45 4E C4 46 4F D2 4E 45 58 D4 44 41 54 C1

So some bytes are correct... in fact some runs of bytes are correct... but some are not!

My current code, with some defensive delays, is...
Code: [Select]
void flashProgramByte2(ADDRESS_T address, uint8_t data) {
   
    // Check FLASH is very off
    nOE_Set();
    nCE_Set();
    nWE_Set();
    setDataForWrite();

    setAddress(0x5555);   
    writeData(0xAA);
   
    nWE_Clear();
    nCE_Clear();
   
    // TWP       40ns 
    SysTick_Wait1us();
   
    nWE_Set();
    nCE_Set();   
   
    // TWPH
    SysTick_Wait1us();
       
    setAddress(0x2AAA);   
    writeData(0x55);
    nWE_Clear();
    nCE_Clear();

    // TWP       
    SysTick_Wait1us();

    nWE_Set();
    nCE_Set();

    // TWPH    40ns
    SysTick_Wait1us();
   
    setAddress(0x5555);   
    writeData(0xA0);
    nWE_Clear();
    nCE_Clear();

    // TWP       
    SysTick_Wait1us();

    nWE_Set();
    nCE_Set();

    // TWPH
    SysTick_Wait1us();
   
    setAddress(address);   
    writeData(data);
    nWE_Clear();
    nCE_Clear();

    // TWP       
    SysTick_Wait1us();

    nWE_Set();
    nCE_Set();
   
    // TBP  20us

    for (int i=0; i<20; i++) SysTick_Wait1us();
}

The wait at the end should be sufficient (matches datasheet) and in reality my program then does some serial IO for the next byte so there is a huge delay between calls.  This is running at 48MHz on a ATSAMC21G18A and 1/f gives 20.8ns per instruction if it were one cycle... so nothing can happen faster than that.

Very confused.

Thanks in advance
« Last Edit: August 18, 2020, 11:25:31 am by NivagSwerdna »
 

Offline rhodges

  • Frequent Contributor
  • **
  • Posts: 354
  • Country: us
  • Available for embedded projects.
    • My public libraries, code samples, and projects for STM8.
Re: Trouble when bit banging SST39SF040A
« Reply #1 on: August 18, 2020, 02:18:51 pm »
It looks like your flash is wearing out. If you write 0xff to an area, you will probably see a lot of zero bits.

Second guess is maybe a problem with the voltage for the flash charge pump?
Currently developing embedded RISC-V. Recently STM32 and STM8. All are excellent choices. Past includes 6809, Z80, 8086, PIC, MIPS, PNX1302, and some 8748 and 6805. Check out my public code on github. https://github.com/unfrozen
 
The following users thanked this post: NivagSwerdna

Offline NivagSwerdnaTopic starter

  • Super Contributor
  • ***
  • Posts: 2507
  • Country: gb
Re: Trouble when bit banging SST39SF040A
« Reply #2 on: August 18, 2020, 05:33:36 pm »
Surprisingly I managed to get to work by changing the code to...

Code: [Select]
void flashProgramByte2(ADDRESS_T address, uint8_t data) {
   
    // Check FLASH is very off
    nOE_Set();
    nCE_Set();
    nWE_Set();
    setDataForWrite();

    setAddress(0x5555);   
    writeData(0xAA);
   
    nWE_Clear();
    nCE_Clear();
   
    // TWP       40ns 
    nCE_Clear();
    nCE_Clear();
   
    nWE_Set();
    nCE_Set();   
   
    // TWPH
    nCE_Set();   
    nCE_Set();   
       
    setAddress(0x2AAA);   
    writeData(0x55);
    nWE_Clear();
    nCE_Clear();

    // TWP       
    nCE_Clear();
    nCE_Clear();

    nWE_Set();
    nCE_Set();

    // TWPH    40ns
    nCE_Set();
    nCE_Set();
   
    setAddress(0x5555);   
    writeData(0xA0);
    nWE_Clear();
    nCE_Clear();

    // TWP       
    nCE_Clear();
    nCE_Clear();

    nWE_Set();
    nCE_Set();

    // TWPH
    nCE_Set();
    nCE_Set();
   
    setAddress(address);   
    writeData(data);
    nWE_Clear();
    nCE_Clear();

    // TWP       
    nCE_Clear();
    nCE_Clear();

    nWE_Set();
    nCE_Set();
   
    // TBP  20us - Super Long Time!
    for (int i=0; i<20; i++) SysTick_Wait1us();
}

There must be some constraint which is not documented in the datasheet since it says TWPH Min 30ns with no maximum; however looks like 1us is too long.  2 instructions worth seems to work.

Mysterious.
 

Offline bson

  • Supporter
  • ****
  • Posts: 2497
  • Country: us
Re: Trouble when bit banging SST39SF040A
« Reply #3 on: August 20, 2020, 12:53:31 am »
Surprisingly I managed to get to work by changing the code to...

Code: [Select]
void flashProgramByte2(ADDRESS_T address, uint8_t data) {
   
    // Check FLASH is very off
    nOE_Set();
    nCE_Set();
    nWE_Set();
    setDataForWrite();

    setAddress(0x5555);   
    writeData(0xAA);
   
    nWE_Clear();
    nCE_Clear();
Try using WE to strobe the data, something like:

Code: [Select]
   nOE_Set();

    nCE_Clear();
    nWE_Set();
    setDataForWrite();

    setAddress(0x5555);

    nWE_Clear();
    writeData(0xAA);
    nWE_Set();
   
    // ... more ...
 
     nCE_Set();

Here's code I have to write the same flash.  Obviously a very different library.  It polls for the write to finish at the end (using SysTimer to time out to avoid getting stuck).

Code: [Select]
bool Writer::WriteByte(uint32_t addr, uint8_t byte) {
    // Deassert CE#, OE#, WE#
    Pin_OEn::set(true);
    Pin_CEn::set(true);
    Pin_WEn::set(true);

    Pin_CEn::set(false);

    // Unlock and write byte
    Port_DB::P_DIR = 0xff;  // Make port output

    SetAddr(0x5555);
    Pin_WEn::set(false);
    Port_DB::P_OUT = 0xaa;
    Pin_WEn::set(true);

    SetAddr(0x2aaa);
    Pin_WEn::set(false);
    Port_DB::P_OUT = 0x55;
    Pin_WEn::set(true);

    SetAddr(0x5555);
    Pin_WEn::set(false);
    Port_DB::P_OUT = 0xa0;
    Pin_WEn::set(true);

    SetAddr(addr);
    Pin_WEn::set(false);
    Port_DB::P_OUT = byte;
    Pin_WEn::set(true);

    // Wait for write to finish by repeatedly reading the byte until BIT7 isn't inverted.
    const SysTimer::Future deadline = SysTimer::future(TIMER_USEC(200));
    const uint8_t bit7 = byte & BIT7;

    Pin_CEn::set(true);
    Pin_OEn::set(true);

    Port_DB::P_DIR = 0x00;  // Make port input
    //SetAddr(addr);

    uint8_t data;
    do {
        Pin_CEn::set(false);
        Pin_OEn::set(false);
        data = Port_DB::P_IN;
        Pin_CEn::set(true);
        Pin_OEn::set(true);
    } while ((data & BIT7) != bit7 && !SysTimer::due(deadline));

    return (data & BIT7) == bit7;
}
 
The following users thanked this post: NivagSwerdna

Offline bson

  • Supporter
  • ****
  • Posts: 2497
  • Country: us
Re: Trouble when bit banging SST39SF040A
« Reply #4 on: August 20, 2020, 01:35:05 am »
By the way, I think the Cypress S29GL064S80TFIV10 is a better part.  It's significantly bigger (8M * 8 or 4M * 16) and more importantly MUCH faster to program.  It has both an "unlock bypass" mode where you unlock it once then keep writing without having to unlock it for each byte, and a "buffered write" where you tell it how many bytes to write (up to 128) and then just clock them out and wait for it to finish.  This is MUCH faster when bit banging.  As in, like 6-10x faster.  With a lot of µC's it can also be done with a timer feeding a write strobe (WE#) pin and triggering a DMA controller.  Super nice when you have to be responsive to things like USB bus enumeration or suspend/resume at any arbitrary time (including in the middle of a USB-driven write).
« Last Edit: August 20, 2020, 01:36:49 am by bson »
 
The following users thanked this post: NivagSwerdna

Offline NivagSwerdnaTopic starter

  • Super Contributor
  • ***
  • Posts: 2507
  • Country: gb
Re: Trouble when bit banging SST39SF040A
« Reply #5 on: August 20, 2020, 09:13:51 am »
It has both an "unlock bypass" mode where you unlock it once then keep writing without having to unlock it for each byte, and a "buffered write" where you tell it how many bytes to write (up to 128) and then just clock them out and wait for it to finish.  This is MUCH faster when bit banging.
That sounds perfect for my application.  Will check that out for the next rev. :-+
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf