6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Mon Apr 29, 2024 3:40 pm

All times are UTC




Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Tue Jul 25, 2023 11:20 pm 
Offline
User avatar

Joined: Mon Mar 06, 2023 9:26 am
Posts: 84
Location: UK
I bought some SST39SF010 flash chips for my project and decided to build my own programmer for them. So far, I've got byte read and byte program working, but sector erase eludes me.

The current version of sector_erase is based on someone else's full-chip erase code, which is why it pulses WE# instead of clocking the address and data on the low and high edges respectively. The reason I didn't try to write it from scratch is because the timing diagram in the datasheet is pretty confusing and noticeably different from the byte program operation.

The code and datasheet screenshots are attached. Any help is very welcome.


Attachments:
File comment: sector erase timing diagram
2023-07-26_00-19.png
2023-07-26_00-19.png [ 53.45 KiB | Viewed 1812 times ]
File comment: byte program timing diagram
2023-07-26_00-18.png
2023-07-26_00-18.png [ 50.11 KiB | Viewed 1812 times ]
flash_programmer.c [2.73 KiB]
Downloaded 40 times

_________________
probably the youngest person on this forum
Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 26, 2023 12:59 am 
Offline
User avatar

Joined: Wed Feb 13, 2013 1:38 pm
Posts: 586
Location: Michigan, USA
I use the flash ROM chip select for each byte, though I'm not sure that would be a problem. Are you providing a 25-mS delay after the sector erase and the 20-uS delay after writing each byte?

Code:
  /******************************************************************************
   *  program 64K RAM image onto 64K 'A' or 'B' half of the 128K Flash ROM      *
   *                                                                            */
   void flash()                       // ****************************************
   { addr = 0x0000;                   // start address $0000                    *
     do                               //                                        *
     { if((addr & 0x0FFF) == 0)       // if 4K sector boundary                  *
       { wrROM(0x5555,0xAA);          // erase sector sequence                  *
         wrROM(0x2AAA,0x55);          //  "                                     *
         wrROM(0x5555,0x80);          //  "                                     *
         wrROM(0x5555,0xAA);          //  "                                     *
         wrROM(0x2AAA,0x55);          //  "                                     *
         wrROM(addr,0x30);            //  "                                     *
         _delay_ms(25);               // required delay                         *
         putSer('.');                 // indicate progress                      *
       }                              //                                        *
       wrROM(0x5555,0xAA);            // write byte 'unlock' sequence           *
       wrROM(0x2AAA,0x55);            //  "                                     *
       wrROM(0x5555,0xA0);            //  "                                     *
       wrROM(addr,rdMEM(ram));        // write byte                             *
       _delay_us(20);                 // required write delay                   *
     } while(addr);                   // until roll-over to 0 (full 64K image)  *
   }                                  // ****************************************


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 26, 2023 1:00 am 
Offline

Joined: Fri Dec 21, 2018 1:05 am
Posts: 1076
Location: Albuquerque NM USA
Addresses are latched on falling edge of write and data is latched on rising edge of write so addresses and data need to be stable at the specified edges. For most microprocessor interface, addresses and data are stable for the entire write operation which satisfy the SST39SF0x0 requirements. Another word, just write to flash aa-55-80-aa-55-30 with corresponding addresses of 5555-2aaa-5555-5555-2aaa-sect_addr and wait for 25ms to erase a sector.
Bill


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 26, 2023 11:29 am 
Offline
User avatar

Joined: Mon Mar 06, 2023 9:26 am
Posts: 84
Location: UK
The thing I'm confused about is that the timing diagram for a sector erase shows the data changing at the same time as the rising edge of WE#. I might be accidentally clocking the address and data during different bus cycles, because of how the code is set up.

_________________
probably the youngest person on this forum


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 27, 2023 2:26 pm 
Offline
User avatar

Joined: Mon Mar 06, 2023 9:26 am
Posts: 84
Location: UK
I fixed it! The problem was this line here:

Code:
uint32_t sax_masked = sax & (!0x0fff); // zero bits 0..=11


Specifically, the fact that `!` is a boolean operator, but there's no compiler warning if you use it on an integer value. This kinda thing is the reason I don't use c.

_________________
probably the youngest person on this forum


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 27, 2023 3:02 pm 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 745
Location: Germany
bools are integers so it makes sense that there would be no warning since there is no type conflict. honestly it would be pretty annoying if there was a warning since i often use the "boolean not" operator to check if an integer is 0.

example:
Code:
uint8_t test = someFunc();
if (!test){
    // test is equal to 0
}


that line is overall a bit strange, i would've just written the mask in full to avoid any potential compiler shenanigans:
Code:
uint32_t sax_masked = sax & 0xFFFFF000; // zero bits 0-11


C is not everyone's cup of tea. i personally like it, mainly because it's the only higher level language i know. :lol:


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 27, 2023 10:48 pm 
Offline

Joined: Fri Mar 18, 2022 6:33 pm
Posts: 435
I think you might be looking for the bitwise NOT operator (~) rather than the logical NOT operator (!). In C the logical operators (&&, ||, !) work on integers and test for TRUE (!=0) or FALSE (==0). The bitwise operators (&, |, ^, <<, >>, and ~) perform the expected bit-twiddling activities.

_________________
"The key is not to let the hardware sense any fear." - Radical Brad


Top
 Profile  
Reply with quote  
PostPosted: Thu Jul 27, 2023 11:47 pm 
Offline
User avatar

Joined: Mon Mar 06, 2023 9:26 am
Posts: 84
Location: UK
Quote:
i often use the "boolean not" operator to check if an integer is 0.


I prefer to use an equality check with zero, because that will no doubt compile to exactly the same thing and is much easier and faster to understand when you read someone else's code.

_________________
probably the youngest person on this forum


Top
 Profile  
Reply with quote  
PostPosted: Fri Jul 28, 2023 5:34 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 664
Location: Potsdam, DE
I have a vague memory that MISRA prefers
Code:
if (0 == variable)

over
Code:
if (!variable)

precisely to give this clarity to a subsequent reader of the code, though of course good naming of variables always helps anyway.
Code:
while (!finished)

It's been a few years though, so I could be mistaken. Certainly in my own code I have no qualms using the '!variable' form for boolean variables, but I'm always explicit for bitwise products.

Neil


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 01, 2023 3:24 pm 
Offline
User avatar

Joined: Mon Mar 06, 2023 9:26 am
Posts: 84
Location: UK
Update: I got it working! Byte read, byte write and sector erase can all be done over serial from a host computer. The control interface is pretty slow, but a) I'm not too concerned with speed and b) I can always add a faster interface later.

At present, it uses 4.4k of flash and 416 bytes of RAM (for globals), which means I can run it on an atmega88 and not bother with an entire Arduino board. The RAM usage is high because the Arduino I2C library allocates about 5 times as much memory as it needs to for buffers, and I can't make them smaller without changing the library code on my system, which isn't ideal. What I might do is get some serial-to-parallel shift registers and use those for driving the address, because that should use a lot less flash and RAM.

_________________
probably the youngest person on this forum


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 02, 2023 6:37 am 
Offline
User avatar

Joined: Tue Jul 17, 2018 9:58 am
Posts: 104
Location: Long Island, NY
What was the missing piece?


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 02, 2023 9:33 am 
Offline
User avatar

Joined: Mon Mar 06, 2023 9:26 am
Posts: 84
Location: UK
The reason sector erase wasn't working is because I got bitwise and boolean not mixed up. The reason it took until now to get it working was just cuz I didn't spend much time on it.

As a further update, I'm well on the way to having a host program, with the speed looking pretty decent for what it is (~20ms per byte program operation).

_________________
probably the youngest person on this forum


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 05, 2023 4:09 pm 
Offline
User avatar

Joined: Mon Mar 06, 2023 9:26 am
Posts: 84
Location: UK
Another update! I redid the serial interface completely an upped the baud rate by a lot, and now it gets ~12 seconds to overwrite a 4kb sector, and 4 seconds to read one, which I'm pretty proud of in all honesty.

_________________
probably the youngest person on this forum


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 38 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: