Estoy trabajando en un proyecto ARM7TDMI usando GCC 4.3 y tengo dificultades para decirle al compilador que use llamadas largas en ciertos casos pero no en otros.long_calls entre secciones RAM y ROM en bare metal ARM con gcc
El proceso de construcción se ejecuta arm-eabi-gcc
para generar ficheros objeto ELF reubicable para cada archivo de origen .c (CFLAGS más relevantes incluyen -Os -ffunction-sections -fdata-sections -mthumb -mthumb-interwork
), luego todos los enlaces en un archivo ejecutable ELF (la mayoría de LDFLAGS relevantes incluyen -Wl,--gc-sections -Wl,-static -Wl,-n -nostdlib
, y una secuencia de comandos personalizada enlazador) . A continuación, ese archivo ELF se convierte en un ejecutable sin procesar con arm-eabi-objcopy -O binary
, y un gestor de arranque personalizado lo copia de ROM a RAM (una sola SRAM con código y datos) al inicio. Entonces, todo se ejecuta desde RAM, .rodata
está presente en la RAM, y todo avanza rápidamente, ignorando completamente la ROM después del arranque.
Estoy tratando de cambiar eso, de modo que ciertas piezas seleccionadas de datos de RO y el texto de las funciones de selección solo puedan vivir en ROM y se pueda acceder durante el tiempo de ejecución según sea necesario. Modifiqué la secuencia de comandos del enlazador para conocer dos secciones nuevas, ".flashdata"
y ".flashtext"
, y ambas deben colocarse en una dirección fija de la ROM. También rocié __attribute__((__section__(".flashdata")))
y __attribute__((__section__(".flashtext"),__long_call__))
en todo el código C, según corresponda, y rejigué el proceso de compilación para que el viejo objcopy ahora agregue -R .flashdata -R .flashtext
, y hago un segundo objcopy con -j
para cada una de esas secciones, luego combino el dos archivos de salida para que el gestor de arranque pueda hacer lo correcto y las secciones ROM aparecen en la ubicación asignada de memoria esperada.
Todo esto funciona bien - puedo printf cadenas etiquetados en la sección .flashdata
, y puedo llamar a una función .flashtext
de código que se ejecuta sin memoria RAM (que sabe utilizar una llamada de larga duración debido al atributo __long_call__
junto al atributo __section__(".flashtext")
) Esa función basada en ROM puede, afortunadamente, llamar brevemente a otras funciones basadas en ROM, y puede regresar a su llamador basado en RAM.
El problema consiste en intentar llamar desde una función basada en ROM a una basada en RAM, que también debe ser una llamada larga. No quiero utilizar llamadas largas en todas partes, así que no quiero -mlong_calls en mi CFLAGS. Si agrupo todas las funciones para vivir en ROM en un solo rom.c
, puedo construir ese archivo con -mlong-calls
y todo funciona. Sin embargo, prefiero evitar eso, y mantener las funciones agrupadas generalmente por propósito, simplemente etiquetando algunas aquí y allá según sea apropiado para ejecutar desde ROM.
Por cierto, esto no era suficiente en gcc 3.4. El uso de -mlong-calls
hizo que el compilador pensara lo correcto, pero no pudo seguir porque solo estaba dispuesto a realizar saltos largos con sus ayudantes _call_via_rX
... todos vivían en la RAM y solo se podía acceder mediante una llamada larga. This was fixed in the linker in gcc 4.0, but not backported to anything in the 3.x tree.
Así que es maravilloso que ahora pueda volver a llamar a RAM, ya que estoy usando gcc 4.3. Sería aún mejor si pudiera etiquetar el código de alguna manera en las funciones basadas en ROM para forzarlo a usar llamadas largas. Hay un #pragma long_calls
, pero solo afecta a las declaraciones, por lo que podría usarlo en lugar de __attribute__((__long_call__))
. Por desgracia, no obliga mágicamente al compilador a utilizar llamadas largas para todas las llamadas a funciones que se producen mientras está en vigor.
Organizacionalmente, simplemente no es lo correcto hacer agrupar todo el código de ejecución lenta en un solo archivo, fuera de contexto y separado de otro código en su categoría general. Por favor dime que hay una opción que aún no he considerado. ¿Por qué las secciones de no-función o simplemente el hecho de que el código está en diferentes secciones (.text
versus .flashtext
) solucionando automáticamente mi problema?
Por cierto, el error de salida del engarce cuando se da cuenta de que el compilador usó una llamada corta que no dejó suficiente espacio para gestionar la reubicación es: relocation truncated to fit: R_ARM_THM_CALL against symbol
foo 'definido en la sección .text.foo en objs/foo.o (and the section
.text.foo is used instead of
.text because of
-ffunction-sections` en CFLAGS).