Accediendo a los registros stm32 a través de estructuras en GCC

2

Estoy tratando de enrollar mi propio dispositivo USB usando una pastilla azul STM32F103 en C con el compilador GCC arm-none-eabi, pero me he encontrado con un comportamiento extraño que estoy tratando de entender.

He creado una estructura que modela las tablas de descriptores de búfer de punto final asociadas con el periférico USB:

typedef struct _EP_BUF_DSCR {
    uint32_t ADDR_TX;
    uint32_t COUNT_TX;
    uint32_t ADDR_RX;
    uint32_t COUNT_RX;
} EP_BUF_DSCR;

Y he creado un puntero a una de estas estructuras y lo he configurado para que aborde el inicio del área de memoria de paquetes USB de la MCU:

EP_BUF_DSCR *EP0_DSCR = (EP_BUF_DSCR *) 0x40006000;

Así que ahora puedo configurar los campos ADDR_TX y ADDR_RX simplemente eliminando la referencia de los campos apropiados y asignándoles valores. Sin embargo, cuando intento hacer esto con el campo COUNT_RX, parece que no tiene ningún efecto:

// debugger memory view shows register as set to 0 after running this:
EP0_DSCR->COUNT_RX = 0x8400;  

Pero puedo cambiar el valor en este registro creando un puntero directamente a él y eliminándolo:

// debugger memory view shows register set to correct value after running:
*((uint32_t *)(0x40006000 + 12)) = 0x8400;  

¿Podría alguien proporcionar alguna idea de por qué sucede esto? ¿He hecho algo sin sentido, o confío involuntariamente en el comportamiento del compilador no documentado?

    
pregunta user3513491

2 respuestas

3

Normalmente, los registros de funciones especiales de hardware asignados en la memoria se deben declarar volatile para que el hardware sepa que algo puede necesitar o alterar su estado más allá del hilo de ejecución local. o dejar de computar incluso los que no están en uso.

En el STM32, ciertos SFR también pueden estar restringidos a un ancho de acceso particular.

Si lo que está intentando hacer es legítimo, es probable que ya exista una definición adecuada dentro del controlador del proveedor (o alternativo) o de los archivos HAL. E incluso si no lo hay, puedes aprender mucho leyéndolos para ver cómo se declara algo tan simple como un bloque GPIO.

Por supuesto, también es posible que exista algún error específico en la operación en particular que está intentando realizar, por ejemplo, es posible que no se pueda escribir, o que solo se pueda escribir de manera significativa cuando el hardware está en un estado particular, que el depurador Se esfuerza por lograrlo, mientras que tu programa generalmente no lo hace.

    
respondido por el Chris Stratton
0

Hay un par de cosas que podrían estar ocurriendo aquí:

  1. Como lo señaló Chris Stratton, debe declarar EP0_DSCR (y cualquier otro puntero a registros de hardware) como volatile .

  2. ¿Tiene APB1 y el periférico USB encendido y cronometrado apropiadamente? Es posible que los registros no respondan correctamente si los periféricos no se están ejecutando. En particular, el periférico USB debe estar sincronizado a 48 MHz, y el APB1 debe estar sincronizado a ≥8 MHz.

  3. ¿Tiene el periférico CAN habilitado? Tanto CAN como USB comparten un búfer de memoria, por lo que no puede usar ambos al mismo tiempo.

respondido por el duskwuff

Lea otras preguntas en las etiquetas