¿Cómo escribo en la memoria flash SPI?

9

Estoy trabajando en una aplicación de audio donde, en lugar de almacenar datos de audio en una tarjeta SD ( Waveshield en Arduino), la estoy almacenando en un IC de memoria flash SPI y estoy rodando mi propia placa con MCU, DAC y amplificador.

Estoy usando un Winbond W25Q80BVSSIG .

Estoy bastante familiarizado con la programación de AVR utilizando el AVRISP mkII o el USBTiny , ¿escribir datos en flash se realiza con el mismo programador? No he podido encontrar nada cuando busqué específicamente a los programadores de memoria flash SPI.

Esta pregunta es un seguimiento de esta .

JYelton
fuente
No sé si existe un programador que específicamente pueda hacer esto fácilmente por usted, desde una PC o algo así, pero si hay un CPLD involucrado en su circuito, puede configurarlo para escribir datos en la memoria flash.
deed02392
Creo que los módulos spi flash están diseñados hoy en día para almacenar firmware / bios que la CPU usa en la mayoría de las PC. No es para dispositivos de almacenamiento robustos.
Artesanía Mariscal

Respuestas:

12

Si simplemente está buscando una forma de programar el flash Winbond SPI con datos "precargados" que su microcontrolador leería para usarlos cuando esté funcionando, entonces lo que querrá buscar es un programador que pueda hacer programación en circuito del chip SPI Flash. Esto también se conoce como programación en el sistema (ISP).

Una opción es el programador de DediProg. Este dispositivo conectado por USB puede programarse en circuito si diseña su placa correctamente. Incluso venden un clip adaptador que se puede conectar al paquete SOW-16 sin tener que diseñar un encabezado de programación separado en su placa. DediProg tiene boletines de información de aplicaciones disponibles para ayudar con el diseño correcto para el uso en circuito. La estrategia principal para el diseño es encontrar una manera simple de aislar los controladores de interfaz SPI en su sistema MCU para que no interfieran con los controladores en el pod de programación SPI. La forma más sencilla de hacer esto es colocar resistencias en serie en las líneas controladas por MCU entre MCU y SPI Flash. El programador se conectaría en el lado del flash SPI de las resistencias en serie. Los métodos alternativos podrían incluir agregar un MUX o conmutadores analógicos en las líneas de interfaz activadas. Un esquema aún más inteligente es agregar un "

ingrese la descripción de la imagen aquí

Una segunda opción a considerar también es el programador USB de ASIX . El Presto puede hacer varios tipos de dispositivos SPI e I 2 C, incluidos los dispositivos SPI Flash. Tengo uno de estos dispositivos específicamente para programar Atmel MCU y varios tipos de dispositivos SPI Flash. Es una solución más rentable que la unidad anterior pero no tan flexible. Su dispositivo más caro llamado Forte puede hacer más cosas porque tiene más pines de interfaz de destino.

ingrese la descripción de la imagen aquí

A veces puede ser beneficioso poder conectar un programador a una placa de destino sin tener que agregar un encabezado de programación. Una buena solución para esto es colocar un pequeño conjunto de almohadillas en una huella especial definida por una compañía llamada TagConnect . Fabrican y venden una serie de cables de programación de conexión rápida que tienen pines pogo que se dedican a la huella especial en el tablero. Hay versiones de 6 pines, 10 pines y 14 pines del cable disponibles para adaptarse a una variedad de aplicaciones. El costo de los cables es muy razonable.

ingrese la descripción de la imagen aquí

Michael Karas
fuente
Esto es muy útil. Estoy planeando programar la memoria flash antes de soldarla a la PCB final. Hasta ahora he hecho esto para MCU y ha funcionado bien. No sé si proporcionar pines ISP en la PCB es una buena idea o no, ya que se supone que no deben reprogramarse una vez completados.
JYelton
1
@JYelton: en mi experiencia, es una buena idea planificar para ISP por varias razones. Las ECO (órdenes de cambio de ingeniería) son una realidad en el ciclo del producto. Alguien o algo exigirá un cambio en el contenido Flash una vez que entre en producción. Los chips flash a veces son susceptibles a perturbaciones de ruido inesperadas en el circuito y terminan comprometiendo su contenido. Otra razón para proporcionar ISP.
Michael Karas
1
¿Existe un encabezado "estándar" que sea compatible con la mayoría de estos programadores al menos a través de cables adaptadores incluidos? He visto encabezados de pin 2x4 y 2x5 con un montón de pinouts diferentes. También vea flashrom.org/Supported_hardware
kert el
Todos tienen su propia idea de lo razonable. Los cables Tag-connect cuestan entre $ 35 y $ 40.
markrages
1
@markrages: pero para un laboratorio de desarrollo o una estación de programación de fábrica dada, solo necesita comprar un cable. No necesita uno para cada producto. Además, estos cables son mucho más baratos que tratar de enrollar su propio accesorio de pines para permitir que el ISP no tenga un conector.
Michael Karas el
8

Apuesto a que podría hacerlo con un Bus Pirate sin pasar por su MCU ... que le permite realizar interacciones en serie algo arbitrarias directamente a un chip utilizando la comunicación SPI, I2C o UART. Puede tomar un poco de trabajo "escribirlo", pero probablemente le permita hacer el trabajo.

También he visto herramientas especializadas para cargar EEPROM sobre I2C directamente, pero no flash y no SPI específicamente.

vicatcu
fuente
Estoy empezando a preguntarme si mi selección de SPI flash es buena, dado lo (aparentemente) oscuros que son los métodos para escribir en las cosas arruinadas.
JYelton
1
Eso requeriría una secuencia de comandos seria, pero una buena idea de todos modos. Un poco demasiado complicado para mi gusto. ¿Quizás deberías considerar una tarjeta SD? Entonces solo necesita preocuparse por la lectura, escribirle con una computadora
chwi
El prototipo actual usa un Arduino y Waveshield (que tiene un lector de tarjetas SD). Quiero alejarme de la tarjeta SD porque creo que el costo será menor (sin lector ni tarjeta) y también más a prueba de manipulaciones.
JYelton
7

Nunca he oído hablar de ninguna otra herramienta que comunique SPI directamente a dicho chip, y creo que es imposible ya que "todos" los chips requieren diferentes llamadas para diferentes operaciones.

El chip necesita llamadas SPI para escritura, lectura, cambio de sector, tamaño de datos, etc. En el capítulo 7.2 Instrucciones de la hoja de datos puede ver todos los comandos SPI que puede enviarle. Por lo tanto, dado que todas las memorias flash externas no tienen el mismo conjunto de instrucciones, debe escribir una aplicación personalizada para esta.

EDITAR: Siendo un seguimiento, realmente recomendaría una de las memorias flash SPI de Atmels, ya que la mayoría de ellas ya ha escrito un código abierto disponible para ellas. Al mirar esta publicación de AVRFreaks, se le proporcionará un código para algunos de los chips flash serie AT45xxxx de Atmels.

chwi
fuente
Si te entiendo correctamente, ¿debo escribir un programa para mi MCU que luego escriba los datos en la memoria flash? El problema es que el MCU tiene menos memoria que el flash externo, por lo que estoy algo perdido.
JYelton
Si. Puede enviar datos desde la línea en serie de su computadora con UART que usted escribe en la memoria flash. Además, puede escribir varios programas para la MCU, programando el flash algunos bloques a la vez. Puede ser un poco lento, pero funciona ya que el flash externo no se borran todo el tiempo que mantener un registro de los sectores que cambian correctamente
CHWI
2
Esta es la respuesta correcta. Por lo tanto, necesitará un programa en su PC para descargar fragmentos a la MCU que luego los escribe en flash. Ayuda si hay una comprobación de errores y no tiene que escribir un nuevo programa en la PC; así que le sugiero que encuentre algún código para XMODEM o similar.
pjc50
@ pjc50 ... no tan rápido al declarar la 'respuesta correcta' :)
vicatcu
En realidad, muchos programadores pueden programar memorias flash; y uno de los esquemas de programación comunes usados ​​con los micros atmel está bastante cerca de SPI para empezar.
Chris Stratton
4

Compré un programador " FlashCAT " de Embedded Computers por alrededor de $ 30 US. Fue sorprendentemente fácil conectarse a la PC a través de USB y escribir archivos en la memoria flash de Winbond. Los métodos y programadores en otras respuestas son probablemente igual de buenos, algunos más caros o de bricolaje, pero esta es una forma barata y simple que se ajusta a lo que estaba buscando.

Aquí hay una foto de la configuración:

Programación con FlashCAT

El programador FlashCAT está a la izquierda, conectado a USB. Está ejecutando el firmware de programación SPI (a diferencia de JTAG) y suministra energía a la memoria flash. La potencia suministrada es seleccionable (3.3V o 5V) con un puente.

Tengo un zócalo SOIC a DIP en la placa para facilitar la programación de múltiples chips. (También puede ver otro IC de memoria flash en el tablero).

Software FlashCAT

Todavía no he convertido mi archivo de audio al formato binario adecuado, pero escribí un archivo WAV de 211 KB en la memoria solo para probarlo, como se muestra arriba. Luego lo leí y lo guardé como un archivo nuevo, lo renombré a .wav y se reproduce correctamente en la PC.

El siguiente paso será codificar correctamente el archivo y escribir el software AVR para leer los datos y enviarlos a través de un DAC.

Descargo de responsabilidad: no estoy afiliado a las computadoras integradas, solo soy un cliente que eligió algo barato y estoy compartiendo información sobre la experiencia con el producto.

JYelton
fuente
4

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.

Jeff Walther
fuente
"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 (generalmente haciendo una 'lectura' del búfer de recepción) si no está ya vacío. Por lo general, vaciar (leer) un búfer de recepción ya vacío no hace daño ". ¿Qué pasos debo seguir para leer el estado del búfer de recepción y vaciar el búfer de recepción?
3

Contrariamente a algunas de las declaraciones aquí, si bien hay algunas SPM PROM extravagantes, también hay algunas instrucciones estándar utilizadas por una gran variedad de SPI PROM, incluida la que ha elegido.

Como vicatcu ya mencionó, hay buenos cables 'bit-bash' disponibles que pueden programar directamente SPI. En cuanto a la señal, SPI se parece mucho a JTAG, por lo que cualquier tipo de cable bit-bash debe poder utilizarse siempre que la interfaz sea de código abierto. El protocolo interno del flash es bastante simple.

Utilizamos el hermano mayor de la parte que está buscando para arrancar nuestras placas FPGA (256M - 2G). El direccionamiento tiene un byte adicional para manejar el volumen de almacenamiento, pero por lo demás los comandos son básicamente idénticos.

El tipo de PROM que está utilizando debe borrarse por sector y luego programarse por página. La lectura es significativamente más rápida que la escritura (en el caso de los que usamos, la programación puede tomar media hora, pero la lectura de toda la PROM toma menos de un segundo a 108MHz).

Ahora para los comandos: Hay manera más comandos disponibles en estos dispositivos que realmente se necesitan para programarlos. En realidad solo necesitas lo siguiente:

  • RDID (ID de lectura): solo para verificar la PROM y la señalización antes de hacer algo más complejo.
  • WREN (escritura habilitada): necesaria antes de cada escritura.
  • PP (0x02 - programa de página): necesario para programar una página.
  • SE (0x20 - borrado de sector): devuelve bits en el sector a '1'.
  • RDSR (0x05 - registro de estado de lectura) - necesario para monitorear el ciclo de borrado / escritura.
  • FREAD (0x0B - lectura rápida) - lee los datos de PROM y verifica la escritura.

Si desea obtener más información, consulte las notas de respuesta sobre la programación SPI para FPGA Xilinx en su sitio web (http://www.xilinx.com). Implementan un subconjunto reducido de comandos para que sus FPGA puedan arrancar desde estos dispositivos.

Diseñé mi propio programador para hacer esto en función de lo que tengo disponible y escribí un script de programador en Python, pero puedes hacer lo mismo con un cable. En su caso, consideraría seriamente hacer todo indirectamente a través del MCU como sugiere Michael Karas. No necesita programar toda la PROM desde la MCU de una sola vez; puede hacerlo por sector.

Jxj
fuente
2

Debería poder reutilizar el USBtiny para programar una memoria flash en lugar de un MCU de destino si se siente cómodo cambiando su programación. Sin embargo, es posible que no haya suficiente memoria para que sea lo suficientemente versátil como para programar tanto la MCU como el flash.

En algún lugar tengo una placa de un proyecto que tiene un flash ATTINY y un SPI, y usa como Arduino como un "programador" fácilmente disponible. Se utiliza una ligera modificación del boceto del ISP para programar la MCU con avrdude, luego una utilidad personalizada envía una secuencia que coloca el boceto en un modo especial y escribe bloques de datos en el flash SPI.

Chris Stratton
fuente