MCU RAM: ¿Por qué el acceso a la RAM a través del límite causa una falla del bus?

3

Mi pregunta se explica mejor con un ejemplo. Hay un kit de evaluación de Infineon que utiliza ARM Cortex-M4 y tiene ), el tamaño máximo de RAM es inferior a 20 kB. ¿Cuál podría ser la causa de tal comportamiento?] Después de una investigación adicional, el problema parece ser que la memoria RAM asignada para los datos del programa pasa el límite entre las dos regiones, y lo hace de forma desalineada. Esto puede causar problemas incluso si el tamaño del código está muy por debajo del tamaño de RAM.

Para darle un poco de contexto al problema, aquí está la salida de arm-none-eabi-size con la opción SysV habilitada:

section               size        addr
.text                 5628   134217728
Stack                 2048   536854528
.data                  116   536856576
.bss                 16386   536856692
USB_RAM                  2   536873078
.no_init                32   536936384
.debug_aranges        2208           0
.debug_info          43565           0
.debug_abbrev         3389           0
.debug_line          11094           0
.debug_frame          9968           0
.debug_str           30489           0
.debug_loc           21316           0
.debug_ranges         2064           0
.build_attributes      472           0
Total               148777

A menos que me equivoque, las únicas partes que entran en la RAM son .bss , .data (como va tanto en RAM como en Flash ). La sección del mapa del enlazador relevante es la siguiente (es decir, muestra exactamente el punto donde la sección .bss sale de sus límites):

.bss            0x1fffc874     0x4009 load address 0x0c0016a8
                0x1fffc874                . = ALIGN (0x4)
                0x1fffc874                __bss_start = .
 *(.bss)
 *(.bss*)
 .bss.resultsArray
                0x1fffc874     0x4000 ./main.o
                0x1fffc874                resultsArray
 .bss.resultsArrayIndex
                0x20000874        0x2 ./main.o
                0x20000874                resultsArrayIndex
 *fill*         0x20000876        0x2 
 .bss.oversamplingResult
                0x20000878        0x4 ./main.o
                0x20000878                oversamplingResult
 .bss.numberOfOversamplingSamplesCollected
                0x2000087c        0x1 ./main.o
                0x2000087c                numberOfOversamplingSamplesCollected

Tenga en cuenta que, según el manual del usuario, el PSRAM termina en 0x1FFFFFFF y el DSRAM comienza en 0x20000000 . La ejecución de este programa genera un error de bus cuando la secuencia de inicio alcanza 0x1FFFFFFD . Reducir el tamaño para que quepa en PSRAM hace que el programa se compile y ejecute sin fallas. La pregunta no es tanto sobre este programa en particular; en cambio, tengo curiosidad por saber por qué hay tan poca RAM disponible para las variables reales del programa y los datos sin inicializar y todo lo demás que se incluye en la RAM.

A continuación se muestra la captura de pantalla del manual de referencia que describe la organización de la memoria en el límite.

    
pregunta andrey

2 respuestas

5
  

La ejecución de este programa genera un error de bus cuando la secuencia de inicio alcanza 0x1FFFFFFD

Las rutinas de inicio habituales escriben palabras de 4 bytes, pero su dirección es no de 4 bytes alineada. Es probable que la secuencia de comandos de tu vinculador pierda una declaración ALIGN(4) (o similar si no es LD).

Ahora, el Cortex M4 en teoría debería dividir la escritura no alineada en dos, pero el tuyo envolvería más de dos segmentos de memoria en diferentes buses de memoria. Es posible que este caso en particular no se maneje correctamente en el hardware, lo que hace que la dirección se invierta en 0x00000000 en lugar de 0x20000000 . Por lo tanto, intenta escribir en flash en 0x00 = > Falla del bus. La alineación correcta de sus datos debería solucionar este problema.

    
respondido por el Turbo J
5
Es muy probable que la respuesta de

Turbo J sea correcta, pero quería aclarar qué sucede con las RAM y mostrarle cómo encontrar esta información en la documentación.

Hay tres bloques de RAM en tu MCU. El primero es el programa RAM (PSRAM). Como se indica en la sección XMC4000 MCU manual de referencia / sección / sección / artículo >

  

RAM de código (PSRAM)

     

El código RAM está diseñado para el código de usuario o el almacenamiento de datos del sistema operativo. los   se accede a la memoria a través de la matriz de bus y proporciona acceso de estado de espera cero para la CPU para la ejecución de código o acceso a datos.

Por lo tanto, la RAM está "destinada" para el código del programa, y (según la sección 25.2.5) hay una opción especial para iniciar desde PSRAM, pero puedes usarlo para lo que quieras.

De la introducción otra vez:

  

RAM del sistema (DSRAM1)

     

La RAM del sistema está diseñada para el almacenamiento general de datos del usuario. La RAM del sistema es   se accede a través de Bus Matrix y proporciona acceso de estado de espera cero para datos.

     

RAM de comunicación (DSRAM2)

     

La memoria RAM de comunicación está diseñada para ser utilizada por unidades de interfaz de comunicación como los módulos USB y Ethernet.

Nuevamente, dice "destinado", pero en otras partes el documento sugiere que los bloques de RAM son intercambiables en su mayoría. La sección 2.3.3 dice:

  

Las regiones Code, SRAM y RAM externa pueden contener programas. Sin embargo lo és   Se recomienda que los programas utilicen siempre la región del Código. Esto se debe a que el procesador tiene buses separados que permiten la obtención simultánea de instrucciones y el acceso a los datos.

Se trata de las interfaces ARM ICode y DCode. Lamentablemente, no soy un experto en eso, pero básicamente es una arquitectura de Harvard.

ARM ha publicado el Cortex-M4 TRM en línea. Explica una propiedad útil del bus DCode :

  

La lógica de control en esta interfaz convierte los datos no alineados y los accesos de depuración en dos o tres accesos alineados, dependiendo del tamaño y la alineación del acceso no alineado. Esto detiene cualquier acceso posterior de datos o depuración hasta que se complete el acceso no alineado.

Según otra página ARM TRM , esto viene con limitaciones:

  

Los accesos no alineados que cruzan los límites del mapa de memoria son impredecibles arquitectónicamente. El comportamiento del procesador es dependiente de los límites, como sigue:

     
  • DCode accede a la envoltura dentro de la región. Por ejemplo, la interfaz DCode convierte un acceso de halfword no alineado al último byte del espacio de código (0x1FFFFFFF) en un acceso de byte a 0x1FFFFFFF seguido de un acceso de byte a 0x00000000. ...
  •   

Ahora, volvamos al manual de referencia de MCU una vez más para ver qué regiones de memoria hay en esta implementación en particular:

  

¡SealineaperfectamenteconelejemploARM!(Esoesbastantecomún,enrealidad).Porlotanto,unaccesonoalineadoen0x1ffffffd/eseajustaríaa0x00000000.¿Quéhayenesadirección?ElmapadememoriadelmanualdereferenciadeMCUvienealrescate:

  

¡Es la ROM de arranque! Si tuviera que adivinar, diría que las escrituras en el espacio de direcciones de la ROM de inicio probablemente generen un error. (La Sección 7.4 del manual sugiere que es un error de Modo de acceso no admitido). Puede experimentar y averiguar si lo desea. De todos modos, la moraleja de esta historia es: ¡no hagas que las secciones de tu vinculador atraviesen regiones de memoria! (Idealmente, póngalos en la memoria RAM para la que están destinados).

Este tema sobre accesos no alineados y regiones de memoria no es tan sencillo como a uno le gustaría, pero este es el tipo de cosas con las que debe lidiar cuando usa un microcontrolador de alta gama. En caso de duda, lo mejor es seguir las recomendaciones del fabricante para saber qué pasa en la memoria.

    
respondido por el Adam Haun

Lea otras preguntas en las etiquetas