nopnop2002 / Raspberry-W25Q64

SPI Flash Memory W25Q64 Access Library for RaspberryPi

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

pageWrite doesn't work with W25Q64JV chips

Civil opened this issue · comments

It seems that bug is here https://github.com/nopnop2002/Raspberry-W25Q64/blob/master/W25Q64.c#L357

Datasheet: https://www.winbond.com/hq/support/documentation/levelOne.jsp?__locale=en&DocNo=DA00-W25Q64JV.1

Section 8.2.13:

The Page Program instruction allows from one byte to 256 bytes (a page) of data to be programmed at
previously erased (FFh) memory locations. A Write Enable instruction must be executed before the device
will accept the Page Program Instruction (Status Register bit WEL= 1). The instruction is initiated by driving
the /CS pin low then shifting the instruction code “02h” followed by a 24-bit address (A23-A0) and at least
one data byte, into the DI pin. The /CS pin must be held low for the entire length of the instruction while data
is being sent to the device. The Page Program instruction sequence is shown in Figure 29.
If an entire 256 byte page is to be programmed, the last address byte (the 8 least significant address bits)
should be set to 0. If the last address byte is not zero, and the number of clocks exceeds the remaining
page length, the addressing will wrap to the beginning of the page. In some cases, less than 256 bytes (a
partial page) can be programmed without having any effect on other bytes within the same page. One
condition to perform a partial page program is that the number of clocks cannot exceed the remaining page
length. If more than 256 bytes are sent to the device the addressing will wrap to the beginning of the page
and overwrite previously sent data.
As with the write and erase instructions, the /CS pin must be driven high after the eighth bit of the last byte
has been latched. If this is not done the Page Program instruction will not be executed. After /CS is driven
high, the self-timed Page Program instruction will commence for a time duration of tpp (See AC
Characteristics). While the Page Program cycle is in progress, the Read Status Register instruction may still
be accessed for checking the status of the BUSY bit. The BUSY bit is a 1 during the Page Program cycle
and becomes a 0 when the cycle is finished and the device is ready to accept other instructions again. After
the Page Program cycle has finished the Write Enable Latch (WEL) bit in the Status Register is cleared to
0. The Page Program instruction will not be executed if the addressed page is protected by the Block Protect
(CMP, SEC, TB, BP2, BP1, and BP0) bits or the Individual Block/Sector Locks. 

There is nothing about need of left shift by 12. If I remove that line (replacing it with sector_no * 256), everything works correctly, otherwise for sectors beyond approx. 20 it starts to overflow and overwrite first sectors (I guess before that overflow causes data to look like it should).

Overall I found API of sector writes instead of just plain address writes a bit counter intuitive. As well as I would've make it explicit that function accept not more than 256 bytes (even though in C it's not that strict).

Also that is something that is common for drivers for w25q on other platforms:
https://github.com/nimaltd/w25qxx/blob/master/w25qxx.c#L660-L673 - for STM32 driver
https://github.com/hepingood/w25qxx/blob/master/src/driver_w25qxx.c#L4733-L4738 - some other library (however something similar to your trick with lshift by 12 is required for w25q256)
https://github.com/iammingge/Driver_W25Qxx/blob/main/W25Qxx.c#L1340-L1373 - another driver for stm32
etc.

Same problem seems to be present in your driver for esp32: https://github.com/nopnop2002/esp-idf-w25q64/blob/master/components/w25q64/w25q64.c#L509

I'm not sure if that is something that has been changed in recent models of the flash (jedec id of my chip is ef-60-17) or something that was there from the beginning. I wouldn't be surprised if that was working well on older chips.

Hello

There is nothing about need of left shift by 12.

The opcode "02h" uses a 24-bit address (A23-A0).
For W25Q64 series, the address range is from 0x000000 to 0x7FFFFF.

W25QXX are 4K byte sectors.
See the [BLOCK DIAGRAM] chapter of the datasheet for more information.
As you can see, a 24-bit address is indicated by the sector number*4K + the address within the sector.

The pageWrite function specifies a sector number and an address within the sector.

uint16_t W25Q64_pageWrite(uint16_t sect_no, uint16_t inaddr, uint8_t* buf, uint16_t n)

24-bit address = (sector number << 12) + address within the sector.


W25Q256 uses 32-bit addresses and is not supported by this library.

In that case it is just a misleading API design that introduce a meaningless concept of a sector to a pageWrite operation that (as I've quoted DS) doesn't benefit from that. It only cares about 256 byte write granularity. However if you think that it is what it should be - feel free to close as that' technically not a bug, but rather design decision.

Could you please tell me in code what kind of problem this function is having?