Un poco tarde para la discusión, pero para cualquiera que lo lea después de una búsqueda ...
Algo que no vi mencionado, que es absolutamente crítico cuando se programan chips SPI Flash es el control del pin Chip Select (CS_). El pin Chip Select se usa para puntuar comandos en el SPI Flash. En particular, una transición de CS_ high a CS_ low debe preceder inmediatamente a la emisión de cualquier código operativo de operación de escritura (WREN, BE, SE, PP). Si hay actividad entre la transición CS_ (es decir, después de que CS_ ha bajado) y antes de que se transmita el código operativo de escritura, el código operativo de escritura generalmente se ignorará.
Además, lo que no se explica comúnmente en las hojas de datos SPI Flash, porque es una parte inherente del protocolo SPI, que también es crítico, es que por cada byte que se transmite en el bus SPI, uno recibe un byte a cambio. Además, no se pueden recibir bytes, a menos que se transmita un byte.
Típicamente, el SPI Master que el usuario está ordenando, tiene un Buffer de transmisión, que envía bytes en la línea MOSI del bus SPI y un Buffer de recepción, que recibe bytes desde la línea MISO del bus SPI.
Para que los datos aparezcan en el búfer de recepción, algunos datos deben haberse enviado al búfer de transmisión. Del mismo modo, cada vez que se envían datos desde el búfer de transmisión, los datos aparecerán en el búfer de recepción.
Si uno no tiene cuidado al equilibrar las transmisiones de escritura y las lecturas de recepción, no sabrá qué esperar en el búfer de recepción. Si el búfer de recepción se desborda, los datos generalmente se derraman y se pierden.
Entonces, cuando uno envía un comando de lectura, que es un código operativo de un byte y tres bytes de dirección, primero recibirá cuatro bytes de "basura" en el búfer de recepción maestro SPI. Estos cuatro bytes de basura corresponden al código operativo y tres bytes de dirección. Mientras se transmiten, Flash aún no sabe qué leer, por lo que solo devuelve cuatro palabras basura.
Después de que se devuelvan esas cuatro palabras de basura, para obtener cualquier otra cosa en el búfer de recepción, debe transmitir una cantidad de datos igual a la cantidad que desea leer. Después del código de operación y la dirección, no importa lo que transmita, es solo relleno para empujar el DAta de lectura desde el SPI Flash al búfer de recepción.
Si no realizó un seguimiento cuidadoso de esas primeras cuatro palabras basura devueltas, podría pensar que una o más de ellas son parte de sus Datos leídos devueltos.
Entonces, para saber lo que realmente está obteniendo del búfer de recepción, es importante saber el tamaño de su búfer, saber cómo saber si está vacío o lleno (generalmente hay un bit de estado de registro para informar esto) y realizar un seguimiento de cómo muchas cosas que has transmitido y cuánto has recibido.
Antes de comenzar cualquier operación de SPI Flash, es una buena idea "drenar" el FIFO de recepción. Esto significa verificar el estado del búfer de recepción y vaciarlo (por lo general, realizando una 'lectura' del búfer de recepción) si aún no está vacío. Por lo general, vaciar (leer) un búfer de recepción ya vacío no hace daño.
La siguiente información está disponible en los diagramas de tiempos en las hojas de datos de los flashes SPI, pero a veces la gente pasa por alto los bits. Todos los comandos y datos se emiten al flash SPI utilizando el bus SPI. La secuencia para leer un SPI Flash es:
1) Start with CS_ high.
2) Bring CS_ low.
3) Issue "Read" op code to SPI Flash.
4) Issue three address bytes to SPI Flash.
5) "Receive" four garbage words in Receive Buffer.
6) Transmit as many arbitrary bytes (don't cares) as you wish to receive.
Number of transmitted bytes after address equals size of desired read.
7) Receive read data in the Receive Buffer.
8) When you've read the desired amount of data, set CS_ high to end the Read command.
If you skip this step, any additional transmissions will be interpreted as
request for more data from (a continuation of) this Read.
Tenga en cuenta que los pasos 6 y 7 deben ser intercalados y repetidos según el tamaño de la lectura y el tamaño de sus Buffers de recepción y transmisión. Si transmite una cantidad mayor de palabras de una vez, de lo que puede contener su búfer de recepción, derramará algunos datos.
Para preformar un programa de página o un comando de escritura, realice estos pasos. El tamaño de página (típicamente 256 bytes) y el tamaño de sector (típicamente 64K) y los límites asociados son propiedades del SPI Flash que está utilizando. Esta información debe estar en la hoja de datos de Flash. Omitiré los detalles de equilibrar los búferes Transmitir y Recibir.
1) Start with CS_ high.
2) Change CS_ to low.
3) Transmit the Write Enable (WREN) op code.
4) Switch CS_ to high for at least one SPI Bus clock cycle. This may be tens or
hundreds of host clock cycles. All write operations do not start until CS_ goes high.
The preceding two notes apply to all the following 'CS_ to high' steps.
5) Switch CS_ to low.
6) Gadfly loop: Transmit the 'Read from Status Register' (RDSR) op code and
one more byte. Receive two bytes. First byte is garbage. Second byte is status.
Check status byte. If 'Write in Progress' (WIP) bit is set, repeat loop.
(NOTE: May also check 'Write Enable Latch' bit is set (WEL) after WIP is clear.)
7) Switch CS_ to high.
8) Switch CS_ to low.
9) Transmit Sector Erase (SE) or Bulk Erase (BE) op code. If sending SE, then follow
it with three byte address.
10) Switch CS_ to high.
11) Switch CS_ to low.
12) Gadfly loop: Spin on WIP in Status Register as above in step 6. WEL will
be unset at end.
13) Switch CS_ to high.
14) Switch CS_ to low.
15) Transmit Write Enable op code (again).
16) Switch CS_ to high.
17) Switch CS_ to low.
18) Gadfly loop: Wait on WIP bit in Status Register to clear. (WEL will be set.)
19) Transmit Page Program (PP = Write) op code followed by three address bytes.
20) Transmit up to Page Size (typically 256 bytes) of data to write. (You may allow
Receive data to simply spill over during this operation, unless your host hardware
has a problem with that.)
21) Switch CS_ to high.
22) SWitch CS_ to low.
23) Gadfly loop: Spin on WIP in the Status Register.
24) Drain Receive FIFO so that it's ready for the next user.
25) Optional: Repeat steps 13 to 24 as needed to write additional pages or
page segments.
Finalmente, si su dirección de escritura no está en un límite de página (generalmente un múltiplo de 256 bytes) y escribe suficientes datos para cruzar el siguiente límite de página, los datos que deberían cruzar el límite se escribirán al comienzo de la página en la que la dirección de su programa cae. Entonces, si intenta escribir tres bytes para la dirección 0x0FE. Los primeros dos bytes se escribirán en 0x0fe y 0x0ff. El tercer byte se escribirá en la dirección 0x000.
Si transmite una cantidad de bytes de datos mayor que el tamaño de una página, los bytes anteriores se descartarán y solo se usarán los 256 bytes finales (o tamaño de página) para programar la página.
Como siempre, no somos responsables de las consecuencias de los errores, errores tipográficos, descuidos o alteraciones en lo anterior, ni de cómo lo pones en uso.