Sugerencias de administración de memoria Cortex M4: mejor ubicación de datos/código

Estoy tratando de implementar un sistema bastante complejo (¡al menos para mí!) en un mcu Cortex M4: LPC4370. Este tiene instrucciones ADC de alta velocidad (hasta 80 Msps), DMA y DSP (datos múltiples de instrucción única). Esto es lo que quiero hacer:

  • Deje que el ADC muestree de manera continua (al menos a 10 Msps)
  • Mover los datos a SRAM
  • Procéselos en tiempo real con cortex M4 DSP (filtrado de modelado de pulsos)

El reloj MCU es de 204 MHz y, por ahora, supongamos que ADC fs no es una especificación de diseño, pero idealmente me gustaría que fuera lo más alto posible. Así que necesito que el código sea lo más rápido posible. Aquí está la configuración de la memoria MCU.

ingrese la descripción de la imagen aquíY aquí la MATRIZ MULTICAPA AHB

ingrese la descripción de la imagen aquíA partir de ahora, estoy considerando más la arquitectura general del firmware y, específicamente, la gestión de la memoria. Algunas consideraciones:

  • No quiero que Core M4 y DMA luchen por la memoria: necesito que DMA pueda escribir datos mientras M4 realiza el procesamiento.
  • la mayor parte del código y todos los datos adquiridos deben estar en SRAM para una ejecución más rápida
  • La búsqueda de instrucciones no debe interferir con el almacenamiento de datos (DMA) y el procesamiento (M4)

En la guía del usuario de LPC4370 (cap. 2):

Para optimizar el rendimiento de la CPU, ARM Cortex-M4 tiene tres buses para acceso a Instrucción (código) (I), acceso a Datos (D) y acceso al Sistema (S). El espacio de memoria de acceso de I-bus y D-bus se encuentra debajo de 0x2000 0000, el S-bus accede al espacio de memoria desde 0x2000 0000. Cuando las instrucciones y los datos se mantienen en memorias separadas, los accesos a códigos y datos se pueden realizar en paralelo en un ciclo Cuando el código y los datos se mantienen en la misma memoria, las instrucciones que cargan o almacenan datos pueden tardar dos ciclos.

Mi idea en este momento es mantener los datos muestreados en dos búferes diferentes ubicados en dos áreas de memoria diferentes (como LocRam128 y LocRam72) y "ping pong" DMA y M4 entre estas dos áreas. El único problema es que estas son las dos áreas utilizadas para la instrucción (I). Por lo tanto, el código de invitado también debe colocarse aquí, y esto no es bueno para mí. Me pregunto cómo podría usar RAMAHB32 de manera efectiva ya que solo está conectado al bus del sistema M4 (S) y no a datos (D) ni instrucciones (I).

¿Alguna pista?

Para ser honesto, esta va a ser una pregunta difícil de responder. He escrito una rutina de "ADC de alta velocidad" para un M4. Pero alcanza un máximo de aproximadamente 1800kHZ de rendimiento total de la muestra. Estaba haciendo un montón de matemáticas en las muestras que realmente limitaban el rendimiento (sin mencionar otras tareas domésticas). Honestamente, debe comenzar esto con un requisito de frecuencia de muestreo real. Puede encontrar que está limitado por la CPU en lugar de estar limitado por la contención de la memoria.
Hola @pgvoorhees gracias por la respuesta. Entendí lo que quieres decir, y es por eso que no quiero establecer estrictamente la frecuencia de muestreo. ¿Sabes si hay alguna forma de usar el bus del sistema (S)?
Déjame reiterar: esta pregunta es imposible de responder sin saber qué vas a hacer con las muestras. Si no va a hacer nada con ellos, entonces 80Mhz es un objetivo muy alcanzable: simplemente asigne un búfer en la memoria y sobrescríbalo continuamente usando DMA y nunca deje que el procesador intervenga. Si desea hacer algo diferente a eso, debe especificar qué es porque la frecuencia de muestreo más alta posible y la estrategia para lograr esa frecuencia de muestreo cambian con la necesidad final.
Hola, @pgvoorhees, agregué información (no puedo describir el proyecto en detalle): necesito al menos 10 Mhz y quiero modelar el pulso en mis datos. Ya estoy tratando de escribir mi función de procesamiento de la mejor manera posible usando los intrínsecos de SIMD.
Creo que te estás perdiendo el punto que @pgvoorhees está tratando de hacer. Está preguntando sobre detalles sutiles de administración de memoria y DMA para un procesador muy específico, pero parece que el procesador en cuestión no es adecuado por otras razones. Entonces, ¿por qué perder el tiempo pensando en este procesador?
Hola, @ElliotAlderson, pido ideas generales, ya que sé que tengo que trabajar mucho para implementar tal cosa. Simplemente no quiero comenzar con fundamentos obviamente (para un ojo más entrenado) incorrectos. Además, como puedes ver en la matriz de memoria, esta unidad tiene 1 M4 y 2 M0: es bastante potente. (Me atengo a esto porque mi empresa necesita usar esto, de ninguna manera)
Para su información, si está muestreando a ~ 10 MSPS y el bus funciona a 204 MHz, entonces no me preocuparía demasiado por la contención de DMA frente a CPU. El M4 se basa en registros e incluso con el procesamiento de muestras más trivial, es poco probable que dedique más del 50 % del tiempo a operaciones de carga/almacenamiento. Probablemente me preocuparía más acerca de dónde coloca las constantes y los datos intermedios (por ejemplo, los coeficientes de filtro), ya que estos podrían competir fácilmente con las búsquedas de instrucciones. Como se ha señalado, debe definir mejor sus requisitos de procesamiento de señales antes de comenzar a intentar exprimir un rendimiento como este.
Todo esto parece que ha elegido el procesador equivocado. Además, nunca asuma que DMA es gratuito. Suponga que va a competir con él. Si cree que debe tener el código en la RAM antes de tener problemas de rendimiento, creo que este diseño ya es un fracaso. Tienes que hacer un prototipo y probar o tienes que comprar un producto que tiene muchos excesos y luego puedes hacer suposiciones y no preocuparte por nada de esto. Trabaje con cada bloque por separado (transferencias dma sin procesarlas realmente) (procesamiento sin transferencias dma), etc. ¿nxp tiene un i-cache como st?
la forma en que escribe su código jugará un papel importante en su rendimiento, sincronizar la parte lo más rápido posible no necesariamente le brinda el mejor rendimiento, a veces solo significa que el procesador está esperando a un ritmo de reloj más rápido lo mismo cantidad de tiempo y simplemente quemando mucha más energía. Tienes que hacer tu ingeniería de sistemas.

Respuestas (1)

Ok, ya que no puedes compartir más detalles. Te daré algunos puntos generales:

  1. la funcionalidad Scatter-gather en el módulo DMA le salvará el pellejo; Tómese el tiempo para entender cómo funciona y cómo usarlo.
  2. Si le preocupan los accesos a la memoria, siga adelante y coloque sus búferes de ping y pong en diferentes memorias. Scatter-gather ayudará a facilitar esto.
  3. Después de lo anterior, no se preocupe por la contención del autobús hasta que llegue allí. De manera realista: si, mientras usa memorias separadas, la contención del bus SIGUE siendo su cuello de botella, entonces tiene el chip equivocado. Puro y simple.
  4. Invierta en un j-trace de Segger e implemente el seguimiento de transmisión en su placa de depuración. Esto lo ayudará cuando necesite solucionar problemas de tiempo. Sí, es caro.
  5. Tómese el tiempo para experimentar con su ciclo de procesamiento, dimensione sus búferes de ping y pong en función del tiempo de procesamiento del ciclo. Es posible que también deba ser creativo al realizar cargas de trabajo parciales para cumplir con los plazos.
  6. Necesitaba reescribir algunas de las funciones de CMSIS DSP para que fuera más rápido.
  7. No tenga miedo de profundizar en las bibliotecas CMSIS, son muy legibles Y proporcionan un buen ejemplo de procesamiento SIMD.
  8. cuando estaba comparando mi código, descubrí que dejar mi sección de datos de firmware en flash no me dio un impacto de rendimiento supersignificativo sobre los datos ubicados en RAM. Eso me sorprendió.
  9. Use datos de punto fijo en todas partes, conviértalos a flotantes solo al final y solo si es necesario.

Espero que esto ayude.