stm32 gpio a dma

Tengo algunas preguntas sobre el uso del DMA de la placa stm32f7 (nucleo F722ZE).

1) Entonces, para comenzar, explicaré lo que estoy haciendo:

Necesito leer datos de 2 pines GPIO (ADC) y tendré una señal de reloj alimentada al stm32f7 desde el dispositivo que suministra los datos. Planeo dejar que la señal del reloj active un temporizador de interrupción y cada vez que se active el temporizador quiero que el DMA haga una transferencia de memoria a periférico. La memoria será de 2 bits en el puerto GPIO con el periférico siendo una línea SPI acoplada a una tarjeta SD.

2) Acceso a los datos:

Me referí al manual de Arm Cortex 7 y encontré lo siguiente:

El puerto GPIOC se asigna a 0x40020800-0x40020BFF y los registros de datos de entrada se establecen en un desplazamiento de 0x14 .

Así que tomo el registro base asignado a la memoria (0x40020800 y le agrego 0x14). Por lo tanto, la dirección de origen que proporciono a la DMA será 0x40020814.

3) Hacer que el DMA desplace estos datos.

Este podría ser el problema más grande. Una vez que tenga los datos en los pines GPIO, esencialmente los recibiré bit por bit y los datos en realidad tienen una longitud de 24 bits, por pin. Entonces, en total, cada pin gpio recibirá paquetes de datos de 24 bits. Aunque cuando la señal externa active el temporizador, solo tendré un bit en cada uno de los GPIO.

¿Hay alguna manera de que el DMA pueda extraer los datos de forma selectiva poco a poco, hasta que tenga los 24 bits y luego enviarlos a través del SPI? ¿Usando algún tipo de transferencia de búfer y ráfaga? De lo contrario, parece que el DMA puede hacer una transferencia mínima de un byte, lo que requerirá que envíe cantidades masivas de bits basura por cada bit que transfiera.

Finalmente: para resumir, no estoy seguro de la ubicación de los datos GPIO, ¿es correcta la dirección que puse y no estoy completamente seguro de cómo hacer que el DMA transfiera estos datos?

¡Cualquier ayuda será apreciada!

Respuestas (3)

  1. GPIO no es el ADC. No entiendo lo que quieres decir. Si es un ADC externo, probablemente lo transfiera utilizando interfaces estándar como I2C o SPI. Si desea leer los datos analógicos que necesita usar, entonces el ADC interno
  2. Tiene todo definido en los encabezados de CMSIS. No es necesario pensar en las direcciones físicas. accederá a los registros GPIO de esta manera: GPIOA -> MODERpor ejemplo. Hay todas las definiciones de bits también en forma legible por humanos.
  3. DMA no transfiere bits, solo bytes, medias palabras o palabras. Pero debe considerar una forma más inteligente de leerlos que la idea inicial. Como no escribiste cuál es el dispositivo conectado, no puedo ayudarte más.
  4. Mi consejo: comience con algo más fácil: aprenda a usar CMSIS y los periféricos en su micro. Estoy 100% seguro de que puede usar uno de los estándar: I2C, SPI o U(S)ART sin lectura de bits del GPIO

1) Esto suena como SPI . ¿Tenemos un problema XY ?

2) Necesitaría el GPIO port input data register (GPIOx_IDR) (x = A..K), que está en el desplazamiento 0x10 del periférico GPIO base. La dirección base de cada periférico se encuentra en el encabezado stm32f7 o en la Tabla 1 del manual de referencia. (RM0385: Tabla 1) Puede acceder a los registros GPIO en modo palabra, media palabra o byte. (RM0385: 6.4) Nota: no puede acceder a todos los periféricos en todos los anchos.Tabla 1. Direcciones de límite de registro STM32F75xxx y STM32F74xxx (continuación)

3) No es la forma más eficiente con el DMA, la tasa de bits sería baja (kHz), pero se puede hacer.

  1. Haga que el DMA lea el byte activado en el búfer de memoria (circular). (o palabras si los gpio están muy separados)
  2. En DMA Complete/Half IRQ, ensamble la palabra del búfer DMA. Sería bueno si tuviera banda de bits, pero el Cortex M7 carece de esto.
  3. Procesa la palabra. Preferiblemente en otra función para mantener la capa de bitbanging separada del procesamiento de datos.

La salida de bits con DMA funciona igual, excepto que debe usar el GPIO port bit set/reset register (GPIOx_BSRR) (x = A..K)para no cambiar IO irrelevante.

El problema es que hay 2 bits entrantes a la vez, un solo controlador SPI no puede manejar eso.
@berendi ¿Tiene dos ADC sincronizados, sincronizados externamente, alimentando datos? Si es así, ¿por qué no usar dos spi, o tal vez DFSDM?

una línea SPI acoplada a una tarjeta SD

Tiene STM32F722ZEinterfaces SDMMC dedicadas que son significativamente más rápidas que SPI, especialmente si conecta los 4 pines de datos.

Así que tomo el registro base asignado a la memoria (0x40020800 y le agrego 0x14). Por lo tanto, la dirección de origen que proporciono a la DMA será 0x40020814.

Eso estaría bien si tuviera la dirección correcta ( IDRestá en desplazamiento 0x10), pero sería aún mejor usar las definiciones de los encabezados estándar

DMAx->SyPAR = (uint32_t)&(GPIOC->IDR);

y luego sería obvio para todos los que miran su código de qué se trata este fragmento de código. Además, ayuda a evitar errores en el cálculo de direcciones.

¿Hay alguna manera de que el DMA pueda extraer los datos de forma selectiva poco a poco, hasta que tenga los 24 bits y luego enviarlos a través del SPI?

Conecte cada línea de datos a un controlador SPI diferente (hay 5 de ellos), conecte la línea de reloj a ambos. Deje que cada uno llene un búfer de 256 bytes (con DMA), uno al lado del otro, para mantener contento al controlador SD con un tamaño de bloque de 512 bytes (2 * búferes de 2048 bytes pueden ser incluso mejores). Cuando los búferes están llenos, escriba el bloque completo en la tarjeta, mientras que los canales SPI DMA pueden cambiar automáticamente a búferes secundarios en una dirección diferente. Es posible que desee usar más de 2 búferes alternos para permitir las actualizaciones del sistema de archivos, si está usando alguno (FATFS puede ser terriblemente lento al actualizar la tabla FAT). Supongo que puede volver a ensamblar los bits más tarde, cuando realmente procese los datos.