Es un poco tarde para la discusión, pero para cualquiera que lo lea después de una búsqueda ...
Una cosa que no vi mencionada, que es absolutamente crítica cuando se programan chips SPI Flash es el control del pin Chip Select (CS_). El pin de selección de chip se usa para puntuar los comandos al SPI Flash. En particular, una transición de CS_ high a CS_ low debe preceder inmediatamente a la emisión de cualquier código de operación de escritura (WREN, BE, SE, PP). Si hay actividad entre la transición CS_ (es decir, después de que CS_ se haya agotado) y antes de que se transmita el código de operación de escritura, el código de operación de escritura generalmente se ignorará.
Además, lo que no se explica comúnmente en las hojas de datos de SPI Flash, porque es una parte inherente del protocolo SPI, que también es fundamental, es que por cada byte que se transmite en el bus SPI, se recibe un byte a cambio. Además, uno no puede recibir bytes, a menos que uno transmita un byte.
Normalmente, el SPI Master que el usuario está ordenando, tiene un búfer de transmisión, que envía bytes a la línea MOSI del bus SPI y un búfer de recepción, que recibe bytes desde la línea MISO del bus SPI. / p>
Para que los datos aparezcan en el búfer de recepción, algunos datos deben enviarse al búfer de transmisión. De manera similar, cada vez que uno envía datos fuera del búfer de transmisión, los datos aparecerán en el búfer de recepción.
Si uno no tiene cuidado al equilibrar las escrituras de transmisión y las lecturas de recepción, no sabrá qué esperar en el búfer de recepción. Si se recibe el desbordamiento del búfer, los datos generalmente se derraman y se pierden.
Entonces, cuando uno envía un comando de lectura, que es un código de operación de un byte y tres bytes de dirección, uno recibirá primero cuatro bytes de "basura" en el búfer de recepción maestro de SPI. Estos cuatro bytes de basura corresponden al código de operación y tres bytes de dirección. Mientras se transmiten, el Flash aún no sabe qué leer, por lo que solo devuelve cuatro palabras de basura.
Después de que se devuelvan esas cuatro palabras de basura, para obtener algo más 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, solo es un relleno empujar el DAta de lectura desde el SPI Flash al Buffer de Recepción.
Si no realizó un seguimiento cuidadoso de las primeras cuatro palabras de basura devueltas, podría pensar que una o más de ellas forman parte de los datos de lectura devueltos.
Por lo tanto, para saber qué obtiene realmente del búfer de recepción, es importante conocer el tamaño de su búfer, saber cómo está vacío o lleno (generalmente hay un bit de estado de registro para informar de esto) y mantener realizar un seguimiento de la cantidad de cosas que ha transmitido y la cantidad que ha recibido.
Antes de iniciar cualquier operación de SPI Flash, es una buena idea "drenar" el FIFO de recepción. Esto significa que debe verificar el estado del búfer de recepción y vaciarlo (por lo general, se realiza una 'lectura' del Búfer de recepción) si aún no está vacío. Por lo general, vaciar (leer) un Buffer de recepción ya vacío no hace daño.
La siguiente información está disponible en los diagramas de tiempo en las hojas de datos de SPI Flashes, pero a veces la gente pasa por alto los bits. Todos los comandos y datos se envían 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 se deben intercalar y repetir según el tamaño de la lectura y el tamaño de sus búferes de recepción y transmisión. Si transmite un número mayor de palabras de una vez, de lo que puede contener su búfer de recepción, podrá derramar algunos datos.
Para realizar un programa de página o comando de escritura, realice estos pasos. El tamaño de página (normalmente 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 de transmisión y recepción.
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 deben cruzar el límite se escribirán al comienzo del Página en la que cae su dirección de programa. Por lo tanto, si intenta escribir tres bytes en 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 más grande que el tamaño de una página, los bytes iniciales se descartarán y solo se utilizarán los 256 bytes finales (o tamaño de página) para programar la página.
Como siempre, no es responsable de las consecuencias de los errores, errores tipográficos, descuidos o desajustes en lo que antecede, ni en la forma en que lo utiliza.