Escritura asíncrona en EEPROM

Hay Stm32l052 con EEPROM incorporado (2k). Se utilizan 4 canales ADC, el disparador recopila datos cada 40 microsegundos. Los datos del ADC se procesan en la interrupción (determinada por la salida de valores más allá de los límites). Por lo tanto, al usar las bibliotecas Hal estándar durante la grabación en EEPROM, se pierden puntos (velocidad de escritura estándar de 3 milisegundos en datos EEPROM), incluso si escribe un byte desde el búfer circular. ¿Hay alguna forma de hacer que el controlador escriba en la EEPROM de forma asíncrona sin bloquear las interrupciones del ADC?

¿Qué estás tratando de lograr aquí? Es poco probable que la EEPROM (independientemente de si es interna o externa) se ajuste a sus necesidades reales, a menos que sea un uso poco frecuente. Es posible que solo desee capturar los datos en la RAM, ya sea y luego escribirlos en la EEPROM, o mantenerlos solo en la RAM si es de corta duración. En general, debe pensar en la EEPROM interna como un bloc de notas para guardar pequeñas cantidades de información, no realmente como una memoria de desbordamiento o un lugar para almacenar datos dinámicos como los que obtendría de un ADC.
@ChrisStratton Un búfer de anillo en RAM está implícito en la pregunta. Según tengo entendido, solo los datos fuera de los límites deberían llegar al almacenamiento permanente, es decir, la eeprom se usa como un registro de errores, para almacenar eventos más o menos frecuentes.
Parece que la EEPROM es solo una parte particionada de FLASH, por lo que toda la memoria se detiene durante 4 mS mientras escribe. Me imagino que ese es el tema del que hablas. No es fácil de arreglar. Probablemente tendrá que reubicar la tabla ISR y el controlador en la RAM (asegurándose de no llamar a las rutinas de la biblioteca en FLASH, incluidas cosas como matemáticas de punto flotante). La mejor solución sería una EEPROM externa.

Respuestas (1)

STM32L052parece tener un controlador NVM de un solo banco, por lo tanto, un acceso de escritura a cualquier dirección EEPROM bloquearía las lecturas y recuperaciones de datos desde flash.

Funcionaría solo si puede reubicar todo el código relevante, excepto la inicialización, pero incluida la tabla de vectores, en la RAM. Sería todo un desafío hacerlo en 8 kbytes, pero podría funcionar. Olvídese de HAL, tiene demasiada sobrecarga y complejidad.

Recomiendo hacerlo de esta manera:

  • Reubicar NVIC a RAM
  • El controlador de interrupciones ADC en la RAM, coloca los datos en el búfer de anillo, invoca PendSV ( SCB->ICSR=SCB_ICSR_PENDSVSET).
  • El controlador de fallas PendSV en la RAM, siempre que haya datos para escribir, coloca una sola palabra de 32 bits† en la EEPROM y espera hasta que se complete la escritura. No regrese mientras NVM todavía esté ocupado.
  • El controlador ADC debe tener mayor prioridad que PendSV.
  • El resto del código se puede dejar en flash siempre que el retraso sea aceptable. Los controladores de interrupciones en flash deberían tener prioridades más bajas que PendSV.

Esta disposición evitaría que se ejecute cualquier código en flash mientras haya una escritura en EEPROM en curso, pero permite que los controladores de mayor prioridad se ejecuten siempre que no toquen la memoria no volátil.

Para reubicar una función en la RAM

Con gcc, utilícelo __attribute__((section(".data")))en la declaración de la función. Hágalo recursivamente a cada función que llama. Úselo -ffreestandingpara evitar que gcc genere llamadas a funciones de biblioteca de forma inesperada. La .datasección se copiará de la memoria flash a la RAM después del reinicio, junto con las variables inicializadas, mediante el código de inicio.

Para reubicar la tabla de vectores

La tabla de vectores del STM32L052tiene una longitud de 192 bytes (Manual de referencia 12.3 Vectores de interrupción y excepción). Simplemente movería el comienzo de la RAM 192 bytes hacia arriba en el script del enlazador

RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 8000 /* 8192 - 192 */

copie la tabla de vectores allí y establezca el puntero de la tabla de vectores

memcpy((void*)0x20000000, (void*)0x08000000, 192);
SCB->VTOR = 0x20000000;

antes de que se habilite cualquier interrupción.


Usando STM32L072en su lugar, sería posible dejar que el programa se ejecute desde el Banco 1, y colocar los datos de la EEPROM en el Banco 2 , no interferirían entre sí. Por supuesto, aún se necesitarían 3 ms (o 6 ms si no está vacío) para escribir una palabra de 32 bits† en la EEPROM, intentar escribir más datos antes de que se complete la primera escritura bloquearía la ejecución del programa hasta que se complete la primera. Consulte el manual de referencia para el diseño del banco (3.3.1 Organización NVM)


† AFAIK Los datos de la EEPROM se escriben en unidades de 32 bits, escribir 1 o 2 bytes a la vez lleva tanto tiempo como escribir una palabra completa de 4 bytes.