STM32L052
parece tener un único controlador NVM de banco, por lo tanto, un acceso de escritura a cualquier dirección EEPROM bloquearía las lecturas de datos y las recuperaciones de flash.
Solo funcionaría si puedes reubicar todo el código relevante, excepto la inicialización, pero incluyendo la tabla de vectores, a la RAM. Sería un desafío hacerlo en 8 kbytes, pero podría funcionar . Olvídate 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 EEPROM, y espera hasta que finalice la escritura. No regrese mientras NVM aún esté ocupado.
- El controlador ADC debería tener una prioridad más alta como PendSV.
- El resto del código se puede dejar en el flash siempre que la demora sea aceptable. Los manejadores de interrupciones en flash deberían tener prioridades más bajas que PendSV.
Esta disposición evitaría que cualquier código en flash se ejecute siempre que una escritura EEPROM esté en curso, pero permite que los manejadores de mayor prioridad se ejecuten siempre que no toquen la memoria no volátil.
Para reubicar una función en la RAM
Con gcc, use __attribute__((section(".data")))
en la declaración de la función. Hazlo recursivamente a cada función que llame. Use -ffreestanding
para evitar que gcc genere llamadas a funciones de biblioteca de forma inesperada. La sección .data
se copiará de flash a RAM después del restablecimiento, junto con las variables inicializadas, mediante el código de inicio.
Para reubicar la tabla vectorial
La tabla de vectores de STM32L052
tiene 192 bytes de longitud (Manual de referencia 12.3 Vectores de interrupción y excepción). Acabo de mover el comienzo de la RAM hasta 192 bytes en el script del enlazador
RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 8000 /* 8192 - 192 */
copie la tabla de vectores allí y configure el puntero de la tabla de vectores
memcpy((void*)0x20000000, (void*)0x08000000, 192);
SCB->VTOR = 0x20000000;
antes de que se habilite cualquier interrupción.
En su lugar, utilizando STM32L072
, sería posible dejar que el programa se ejecute desde el Banco 1 y, al colocar los datos de la EEPROM en el Banco 2 , no interferirán entre sí. Por supuesto, aún tomaría 3 ms (o 6 ms si no está vacío) escribir una palabra † de 32 bits en la EEPROM, intentar escribir más datos antes de que se complete la primera escritura aún 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)
† Los datos de AFAIK EEPROM se escriben en unidades de 32 bits, escribir 1 o 2 bytes a la vez toma tanto tiempo como escribir una palabra completa de 4 bytes.