Hay Stm32l052 con EEPROM incorporado (2k). Se utilizan 4 canales ADC, los datos se recogen por el gatillo cada 40 microsegundos. Los datos del ADC se procesa en la interrupción (determinado por la salida de los valores más allá de los límites). Por lo tanto, el uso de las bibliotecas estándar Hal durante la grabación en EEPROM puntos se pierden (3 milisegundos velocidad de escritura estándar en los datos de EEPROM), incluso si se escribe un byte de la memoria intermedia del anillo. ¿Hay alguna forma de conseguir que el controlador escriba en la EEPROM de forma asíncrona sin bloquear las interrupciones del ADC?
Respuesta
¿Demasiados anuncios?STM32L052
parece tener un controlador NVM de un solo banco, por lo que un acceso de escritura a cualquier dirección EEPROM bloquearía las lecturas y recuperaciones de datos de la flash.
Sólo funcionaría si puedes reubicar todo el código relevante, excepto la inicialización, pero incluyendo la tabla de vectores, en la RAM. Sería todo un reto hacerlo en 8 kbytes, pero podría funcionar. Olvídate de HAL, tiene demasiada sobrecarga y complejidad.
Yo recomendaría hacerlo así:
- Reubicar el NVIC en la RAM
- El manejador de la interrupción del ADC en la RAM, pone los datos en el buffer del anillo, invoca PendSV (
SCB->ICSR=SCB_ICSR_PENDSVSET
). - El gestor de fallos PendSV en la RAM, mientras haya datos que escribir, pone una sola palabra de 32 bits† en la EEPROM, y espera hasta que la escritura se complete. No regresa mientras la NVM sigue ocupada.
- El manipulador ADC debería tener mayor prioridad que PendSV.
- El resto del código puede dejarse en flash siempre que el retraso sea aceptable. Los manejadores de interrupción en flash deben tener prioridades más bajas que PendSV.
Este arreglo evitaría que cualquier código en la flash se ejecute mientras una escritura en la EEPROM esté en progreso, pero permite que los manejadores de mayor prioridad se ejecuten siempre y cuando no toquen la memoria no volátil.
Para reubicar una función en la RAM
Con gcc, utilice __attribute__((section(".data")))
en la declaración de la función. Hágalo recursivamente a cada función que llame. Utilice -ffreestanding
para evitar que gcc genere llamadas a funciones de biblioteca de forma inesperada. El .data
se copiará de la flash a la RAM después del reinicio, junto con las variables inicializadas, por el código de inicio.
Para reubicar la tabla de vectores
La tabla de vectores del STM32L052
tiene 192 bytes (Manual de referencia 12.3 Vectores de interrupción y excepción). Yo simplemente movería el inicio de la RAM hacia arriba 192 bytes en el linker script
RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 8000 /* 8192 - 192 */
copiar la tabla de vectores allí, y establecer el puntero de la tabla de vectores
memcpy((void*)0x20000000, (void*)0x08000000, 192);
SCB->VTOR = 0x20000000;
antes de que se active cualquier interrupción.
Utilizando STM32L072
en cambio, 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 se interferirían entre sí. Por supuesto, todavía tomaría 3 ms (o 6 ms si no está vacía) para escribir una palabra de 32 bits† en la EEPROM, intentar escribir más datos antes de que la primera escritura se complete todavía bloquearía la ejecución del programa hasta que la primera se complete. Consulta el manual de referencia para ver la disposición de los bancos (3.3.1 Organización de la NVM)
† Según tengo entendido, los datos de la EEPROM se escriben en unidades de 32 bits, escribir 1 o 2 bytes a la vez lleva el mismo tiempo que escribir una palabra completa de 4 bytes.