Realmente no quería involucrarme en la optimización del código y al mismo tiempo agregar problemas para encontrar nuevos errores. Por lo tanto, se recordó oportunamente que esta versión del microcontrolador tiene un segmento RAM adicional de 64K (CCM SRAM) a bordo, que no se ha utilizado de ninguna manera ahora. Eureka - ¡aquí está, la solución!
Pero, lamentablemente, todo resultó no ser tan sencillo.
Resultados de búsqueda de una solución lista para usar
La documentación oficial de CCMRAM proporciona ejemplos para colocar código ejecutable, una pila o variables individuales en él.
La búsqueda en los foros arrojó varios enlaces a diferentes formas de usar CCMRAM, pero desafortunadamente, todas eran variaciones diferentes de las formas que se describen en la documentación oficial. Y todos ellos requirieron revisar el código fuente para agregar atributos al declarar cada función o variable.
Para GCC, en mi caso, algo como esto:
__attribute__((section(".ccmram")));
Además, algunas variables tienen un valor predeterminado, que requiere modificar el cargador de arranque para que cuando se inicie el firmware, dichas variables se copien en un área separada para las variables inicializadas o puestas a cero.
Bueno, la dificultad final fueron las limitaciones de CCMRAM en sí. Se cuelga de un bus separado al que DMA no tiene acceso, y se planeó utilizar el acceso directo a la memoria de manera muy activa.
En otras palabras, al resolver un problema, uno podría agregar accidentalmente un montón de otros y profundizar en la depuración para encontrar los errores introducidos.
Afortunadamente, logramos encontrar una solución simple por parte de FreeRTOS.
El tamaño del montón era menor que el tamaño del segmento RAM de CCM y la decisión fue evidente: mover el montón a esta partición.
Y logramos hacer esto con cambios mínimos en el código.
- Se agrega una nueva sección al archivo ld (en mi caso STM32F407VGTX_FLASH.ld):
.ccmram : { . = ALIGN(8); . = . + _Min_Heap_Size; . = ALIGN(8); } >CCMRAM
- En la sección "._user_heap_stack" se comenta o elimina una línea
/* . = . + _Min_Heap_Size; */
Las líneas con _Min_Heap_Size son necesarias para que el vinculador emita advertencias en caso de que el tamaño de RAM sea insuficiente. - Se agrega una sola variable al cuerpo del programa.
uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__((section(".ccmram")));
- Y al construir un proyecto, se agrega una definición de preprocesador
configAPPLICATION_ALLOCATED_HEAP=1
Como resultado, ¡un montón de FreeRTOS en CCM SRAM con un número mínimo de ediciones en el código fuente!