¿Método o función para determinar si el puntero se debe direccionar en flash o RAM?

7

Estoy trabajando con un microcontrolador ARM Cortex M4 que tiene un DMA o un controlador DMA periférico. Un requisito del DMA es que no puede acceder a los punteros a las direcciones que existen en flash, sino a los punteros a direcciones que están en la memoria RAM. ¿Hay una manera de determinar si un puntero en particular apunta a flash o RAM?

Si no, creo que necesito inicializar realmente un búfer en la RAM, luego strcpy o algo así para transferir lo que hay en flash a la RAM para que el DMA pueda leerlo. ¿Alguien sabe de una mejor manera de hacerlo para no perder tiempo de CPU si no hay forma de saber si el puntero apunta a flash o RAM?

Esto está en un Atmel SAM4S.

    
pregunta Pugz

4 respuestas

5

Usted conoce el mapa de memoria de su microcontrolador, por lo que simplemente puede probar su puntero con las direcciones RAM de inicio y fin. En la mayoría de los casos, su linkerscript proporcionará estas direcciones, por lo que no necesita escribirlas usted mismo (los detalles dependerán de su linkerscript). Tenga en cuenta que cuando utilice el linkerscript, los valores no se conocerán en el momento de la compilación, por lo que el compilador no puede optimizar las comparaciones con los punteros conocidos.

    
respondido por el Wouter van Ooijen
5

El principal problema con la verificación de si un puntero está en un rango específico es, desafortunadamente, el estándar C. La aritmética de punteros tiene un comportamiento definido solo si se realiza en punteros del mismo tipo dentro del rango de memoria del mismo objeto (es decir, dentro del mismo rango de matriz asignado). A los operadores de comparación se definen como operaciones aritméticas, esta restricción también se aplica a ellos. Una solución para este problema sería convertir los punteros al tipo uintptr_t definido en stdint.h , que es un tipo de número entero garantizado para mantener un valor de puntero. Y luego realice sus comparaciones.

Ahora a la parte de obtener los límites correctos. Normalmente, un proyecto de C contendría algún tipo de script de vinculador que definiera las regiones de memoria de la arquitectura específica. Comúnmente incluirá líneas similares a las siguientes:

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x40000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x8000
}

luego, en el mismo script se pueden agregar las siguientes definiciones:

  _flash_start = ORIGIN(FLASH);
  _flash_end = ORIGIN(FLASH) + LENGTH(FLASH);

Y luego en el código C se puede acceder a estos símbolos usando:

extern int _flash_start ;  
extern int _flash_end;

Y luego una parte difícil: la dirección de _flash_start corresponderá a la dirección de inicio de flash, y la dirección de _flash_end corresponderá al final de flash dirección. Es decir. &_flash_start y &_flash_end le dan el rango deseado.

    
respondido por el Eugene Sh.
5

Si su MCU sigue las convenciones de ARM Cortex, puede ver el mejor lugar de la dirección en cuestión:

int
inflash_p(void *addr)
{
    uintptr_t addr_int = addr;
    unsigned int addrtype = addr_int >> 28;

    // 0 = flash, 1,2 = ram, 4 = periph, e = system
    return (addrtype == 0);
}
    
respondido por el corecode
2

Puede convertir el puntero en un entero, luego comparar su valor con el espacio de direcciones flash definido en el mapa de memoria de su MCU. Por ejemplo, si su memoria flash está en las direcciones 0x10000000 - 0x1001ffff, podría hacer:

void DMA_Function(uint8_t *ptr)
{
    uint32_t ptrAddress = (uint32_t)ptr;

    if (ptrAddress >= 0x10000000 && ptrAddress < 0x10020000)
        //The address is in flash
    else
        //The address is not in flash

    ...
}

Por supuesto, en el código real es mejor usar constantes en lugar de direcciones codificadas, FLASH_START_ADDR y FLASH_END_ADDR, por ejemplo. Si desea ser más flexible, puede definir variables de enlace para las direcciones flash, lo que mantiene las direcciones fuera de su código fuente por completo.

    
respondido por el Adam Haun

Lea otras preguntas en las etiquetas