¿Cómo pasar de microcontroladores "básicos" a ARM Cortex?


22

Tengo muchos años de experiencia con núcleos de 8 bits de varios fabricantes, a saber, 8051, PIC y AVR, y ahora tengo que descifrar un Cortex M0. Específicamente este , pero espero que podamos ser más generales que eso.

Está resultando ser un poco más de lo que esperaba, con múltiples documentos que describen diferentes partes del sistema en diferentes niveles de detalle y ninguno realmente que haya visto para conectarlo todo. Esto se compara con tener una hoja de datos que explica todo. Entiendo que tengo muchas más cosas que documentar en primer lugar, pero el cambio de formato me está dando vueltas.

El sitio web anterior tiene un documento que es una buena descripción general de cada subsistema y periférico de forma aislada, y otro que describe cada registro en detalle, y tengo todo el código fuente de su SDK, incluidos los archivos de encabezado y algunos ejemplos complejos, pero aún veo nada que describa cómo todo se conecta entre sí.

¿Existe un recorrido conciso de la arquitectura Cortex que explica la función de las cosas que los controladores más pequeños simplemente no tienen, como múltiples capas de buses desde la CPU a los periféricos, cada uno con su propio temporizador de vigilancia, y cómo se conectan todos juntos?


No puedo decir por lo que describió si obtuvo la hoja de datos real / manual de usuario para el procesador del fabricante. Eso debería darle una buena imagen general y detalles. De una de las imágenes en el sitio que ha vinculado, parece un procesador NXP. Mire el número de pieza del fabricante y busque la documentación del procesador en su sitio. También está el sitio de ARM arm.com/products/processors/cortex-m/cortex-m0.php .
DigitalNinja

Perdón por la demora en volver a esto; He estado ocupado con otros proyectos. Gracias @ Adam por la voz de la experiencia.
AaronD

Y gracias @Richard por la descripción general de cómo pensarlo y la nota sobre cómo imprimir la configuración del pin. Les he votado a los dos.
AaronD

Nunca volverá, excepto si encuentra algunos requisitos de precios extremos . E incluso entonces se sentirá tentado, ya que hay bastantes Cortex-M muy baratos.
Ronan Paixão

Respuestas:


40

He trabajado en AVR y en MCU basados ​​en ARM Cortex-M3 / M4 / R4. Creo que puedo ofrecer algunos consejos generales. Esto supondrá que está programando en C, no en ensamblado.

La CPU es en realidad la parte fácil. Los tipos de datos básicos de C serán de diferentes tamaños, pero de todos modos está utilizando uint8 / 16 / 32_t, ¿verdad? :-) Y ahora todos los tipos enteros deberían ser razonablemente rápidos, con 32 bits (int) como el más rápido. Probablemente no tenga una FPU, así que continúe evitando flotadores y dobles.

Primero, trabaje en su comprensión de la arquitectura a nivel de sistema. Esto significa IOs, cronometraje, memoria, reinicios e interrupciones. Además, debe acostumbrarse a la idea de los periféricos mapeados en memoria. En AVR puede evitar pensar en eso porque los registros tienen nombres únicos con variables globales únicas definidas para ellos. En sistemas más complejos, es común referirse a los registros por una dirección base y un desplazamiento. Todo se reduce a la aritmética del puntero. Si no te sientes cómodo con los punteros, comienza a aprender ahora.

Para las E / S, descubra cómo se maneja el muxing periférico. ¿Existe un control central de mux para seleccionar qué pines son señales periféricas y cuáles son GPIO? ¿O configura los pines en modo periférico usando los registros periféricos? Y, por supuesto, necesitará saber cómo configurar GPIO como entradas y salidas, y habilitar el modo de drenaje abierto y pull-ups / down. Las interrupciones externas generalmente también entran en esta categoría. Los GPIO son bastante genéricos, por lo que su experiencia debería servirle bien aquí.

El reloj se reduce a unas pocas cosas. Comienza con una fuente de reloj, generalmente un cristal o un oscilador RC interno. Esto se utiliza para crear uno o más dominios de reloj a nivel de sistema. Los chips de mayor velocidad usarán un PLL, que puedes considerar como un multiplicador de frecuencia. También habrá divisores de reloj en varios puntos. Los aspectos clave a tener en cuenta son la frecuencia de reloj de su CPU y las velocidades de bits que necesita para sus periféricos de comunicación. Por lo general, esto es bastante flexible. Cuando avanzas más, puedes aprender cosas como los modos de bajo consumo, que generalmente se basan en la activación del reloj.

Memoria significa flash y RAM. Si tiene suficiente RAM, a menudo es más rápido mantener su programa allí durante el desarrollo inicial para que no tenga que programar el flash una y otra vez. El gran problema aquí es la gestión de la memoria. Su proveedor debe proporcionar scripts de enlazador de muestra, pero es posible que deba asignar más memoria al código, las constantes, las variables globales o la pila, según la naturaleza de su programa. Los temas más avanzados incluyen seguridad de código y programación flash en tiempo de ejecución.

Los reinicios son bastante sencillos. Por lo general, solo tiene que estar atento al temporizador de vigilancia, que puede habilitarse de manera predeterminada. Los reinicios son más importantes durante la depuración cuando ejecuta el mismo código una y otra vez. Es fácil perderse un error debido a problemas de secuencia de esa manera.

Hay dos cosas que debe saber sobre las interrupciones: cómo las habilita y deshabilita, y cómo configura los vectores de interrupción. AVR-GCC hace esto último por usted con las macros ISR (), pero en otras arquitecturas puede que tenga que escribir una dirección de función en un registro manualmente.

Los periféricos de microcontroladores generalmente son independientes entre sí, por lo que puede aprenderlos uno a la vez. Puede ser útil elegir un periférico y usarlo para aprender parte del material a nivel de sistema. Los periféricos de comunicación y los PWM son buenos para la sincronización y las E / S, y los temporizadores son buenos para las interrupciones.

No se deje intimidar por el nivel de complejidad. Esos microcontroladores "básicos" ya le han enseñado mucho de lo que necesita saber. Avísame si necesitas que te aclare algo.


44
Buena respuesta. Otra cosa a tener en cuenta son los periféricos DMA, que en mi experiencia tienden a tener interfaces complicadas y poco documentadas.
Doug McClean

3
"Y ahora todos los tipos enteros deberían ser igualmente rápidos". En realidad, debido a las reglas de promoción de enteros en C, el uso de tipos de 8/16 bits puede resultar en una gran extensión de signo / cero, y puede ser un problema cuando la memoria Flash es baja. Entonces, si hay RAM de sobra, podría ser útil usar más tipos de 32 bits o al menos preferir int/ int_leastN_Ttipos para las variables de la pila.
user694733

Cometí un error en mi comentario. Quise decir; use int_fastN_ttipos, no int_leastN_ttipos.
user694733

@ user694733: desearía que el estándar C permitiera que el código solicite un número entero que ocupe un tamaño determinado en la memoria y pueda operar en valores dentro de un rango particular, pero con una semántica poco especificada cuando va más allá de ese rango. En algo como el ARM, int16_ta menudo será tan rápido como int32_tpara los valores almacenados en la memoria, pero el Estándar requiere que en plataformas donde intsea ​​de 17 bits o más, int16_t x=32767; x+=2;debe establecerse xen -32767, requiriendo frecuentemente instrucciones de extensión de signo incluso si el código fuera nunca haga uso del comportamiento de envoltura.
supercat

@supercat C estándar requiere un comportamiento de ajuste solo para tipos sin signo. Para los tipos con signo, cualquier ajuste es UB, debido a diferentes representaciones posibles. Por lo tanto x+=2, sería legal usar instrucciones para tipos de 16 bits, porque el compilador puede asumir que el valor no se ajustará y, por lo tanto, usarlo no cambiaría el comportamiento observable. Pero creo que ARM no tiene una instrucción ADD de 16 bits que lo haría posible. (Podría estar equivocado, mis conocimientos sobre el conjunto de instrucciones ARM no es tan bueno.)
user694733

8

Es útil recordar que ARM posee la propiedad intelectual del microprocesador, pero en realidad no hace partes. En cambio, los fabricantes licencian las diversas versiones de procesadores ARM y producen sus propias piezas únicas con mezclas individuales de características y periféricos.

Dicho esto, si eres nuevo en la arquitectura, probablemente tendría sentido comenzar con la documentación de ARM, que es, esencialmente, la documentación de referencia para todos esos microprocesadores.

Por ejemplo, el Cortex-M0 se describe en el sitio web de ARM .

También hay una lista de libros relacionados con ARM que atiende a una amplia variedad de necesidades e intereses.

Finalmente, están las hojas de datos específicas del fabricante. Para el M0, Cypress, NXP y STMicroelectronics son solo tres de los muchos fabricantes de piezas reales basadas en el Cortex-M0.

(Y no, no trabajo para ARM y nunca lo he hecho).


1
Esta es una respuesta bastante genérica que no hace mucho más que un enlace a algunos documentos de Cortex-M0, que estoy seguro de que el OP puede encontrar por sí mismo.
Jay Carlson

1
Aborda directamente la pregunta que solicita ayuda para encontrar la documentación general. Esta respuesta responde directamente a esa necesidad y explica por qué las cosas son como son.
Edward

8

Una gran diferencia es el uso de bibliotecas proporcionadas por el proveedor. Para los PIC, Atmels, etc., la mayoría de los desarrolladores no utilizaron mucho las bibliotecas básicas (para gpio, temporizadores, adc, etc.). En mi experiencia, la gente (a lo sumo) los usaría como guías al escribir su propio código.

Sin embargo, con ARM, las bibliotecas casi siempre se usan. Existe un estándar, "CMSIS", que los fabricantes recomiendan seguir. Debe hacerse. Ayuda en la portabilidad del código (entre diferentes ARM y entre fabricantes) y ofrece un método "estandarizado" para estructurar su código. La gente se acostumbra a ver y comprender las funciones de la biblioteca.

Claro que hay algunos desarrolladores que acceden a los registros directamente, pero son los valores atípicos :)

Para responder a su pregunta, me pareció muy útil leer la documentación de la Biblioteca. ST tiene un código bien desarrollado, con un gran archivo de ayuda creado por Doxygen. Puede ver cuáles son todas las opciones para cada módulo de hardware.

Para usar GPIO como ejemplo, la función de inicialización maneja:

  • Dirección (dentro o fuera)
  • pullups / pulldowns
  • colector abierto / push-pull
  • velocidad de subida
  • etc.

Al mirar las opciones, puede ver lo que es posible. ¡Y, por supuesto, aprenderá cómo pasar estas opciones a la función Init!

Bien, ahora que he dicho eso, veo que su ARM específico no tiene bibliotecas compatibles con CMSIS. En cambio, tienen su SDK patentado disponible para descargar. Empezaría a buscar sus documentos SDK.

Si no está casado con este producto específico, podría recomendarle que busque un proveedor diferente con bibliotecas más compatibles. Vas a subir una curva de aprendizaje de todos modos, así que también podrías hacer que tu inversión sea más portátil ...

¡Los BRAZOS son divertidos! No he mirado hacia atrás.


"Para los PIC, Atmels, etc., la mayoría de los desarrolladores no usaban mucho las bibliotecas". No estoy seguro de dónde viene eso. Solo he usado PIC, no AVR, pero ciertamente no quisiera escribir mi propia biblioteca, por ejemplo, para la interfaz de host USB, la pila TCP o el sistema de archivos de la tarjeta SD. Las bibliotecas de Microchip para todos estos parecen bastante adecuadas.
tcrosley

Ah, @tcrosley, tienes toda la razón. Solo estaba tratando de referirme a la funcionalidad cubierta por los periféricos básicos: gpio, temporizadores, adc, etc.
bitsmack

Estoy de acuerdo, generalmente accedo a GPIO, temporizadores, relojes y UART R / W directamente. A veces uso sus llamadas de biblioteca para la configuración de I2C, SPI, ADC y UART, pero no siempre. Muchos registros, ya sea que esté hablando PIC (y en particular PIC32) o ARM.
tcrosley

Creo que esta respuesta es la más pragmática de esta pregunta, aunque no se aplica al controlador específico del OP. Creo que puedes hacer una buena ingeniería integrada sin entender el AHB o el NVIC.
Jay Carlson

@JayCarlson Gracias! Su edición de esta respuesta fue rechazada porque se supone que no debemos cambiar las publicaciones de otras personas de manera tan significativa. Pero fue muy buena información! Sugiero que publique como su propia respuesta, por lo que ayudará a la gente y también obtener upvoted :)
Bitsmack

5

Buen momento para moverse; los 8 bits están muriendo rápidamente; cuando puede comprar una placa de $ 5 con (por ejemplo) un STM32F103 que es un microcontrolador ARM de 32 bits bastante capaz (¡incluso con USB!), no hay duda de que los tiempos han cambiado.

Ya has tenido algunas respuestas excelentes, pero principalmente diría "olvida el ensamblaje" y casi "olvídate de cómo funciona la CPU en un nivel bajo": un día habrá un caso de esquina en el que debes profundizar (una optimización específica o para la depuración), pero los núcleos ARM ejecutan el código C excepcionalmente bien (por diseño) y rara vez es necesario aventurarse en las entrañas.

Esto significa que pasarás una cierta cantidad de tiempo golpeándote la cabeza contra problemas con los compiladores (y especialmente los enlazadores y los archivos MAKE) que te arrojan errores oscuros, pero todos son superables.

Las agallas de cómo funcionan los ARM (es decir, los libros de CPU ARM) son densas y no muy interesantes hasta el día en que realmente necesita optimizar (y se sorprenderá de lo poco frecuente que es cuando tiene registros de 32 bits y su PLL ' d El reloj de la CPU está en la región de 100 mhz).

El conjunto de instrucciones ARM "old skool" es mucho más fácil de leer que un desmontaje mucho más reciente que "Thumb2", que es lo que se encuentra en la mayoría de los ARM modernos de nivel de microcontrolador (Cortex), pero nuevamente las entrañas de las instrucciones en lenguaje ensamblador en su mayoría se desvanecen en el fondo; si tiene el conjunto de herramientas adecuado (especialmente un depurador de nivel de origen decente con puntos de interrupción / paso único, etc.) simplemente no le importa demasiado que sea ARM.

Una vez que esté en el mundo de los registros de 32 bits y los anchos del bus de datos de 32 bits y todo lo que siempre quiso disponible en el chip, nunca querrá volver a una CPU de 8 bits nuevamente; básicamente, a menudo no hay penalización por "tomarlo con calma" y escribir código para ser legible más que eficiente.

Sin embargo ... periféricos ... sí, y ahí está el problema.

Seguro que obtienes un montón de cosas para jugar en los MCU modernos, y muchas de ellas son cosas muy elegantes; a menudo encuentra un mundo de sofisticación mucho más allá de AVR, PIC y periféricos en chip 8051.

¿Un temporizador programable? Nah, ten ocho! DMA? ¿Qué tal 12 canales con prioridad programable y modo ráfaga y modo encadenado y recarga automática y ... y ... y ...

I2C? I2S? ¿Docenas de opciones de muxing de pin? ¿Quince formas diferentes de reprogramar el flash en chip? ¡Seguro!

A menudo se siente como si hubieras pasado de la hambruna a un festín con los periféricos y es común que haya trozos enteros de un chip que admirarás pero que apenas usarás (por lo tanto, sincronización de reloj).

La cantidad de hardware en chip (y las variaciones en eso en la línea de chips de un solo proveedor) es hoy en día bastante alucinante. Un proveedor de chips, por supuesto, tenderá a reutilizar los bloques de IP, por lo que una vez que se familiarice con una determinada marca, será más fácil, pero "la mierda se volvió loca hoy en día".

En todo caso, los periféricos y sus interacciones (y DMA e interrupciones y asignación de bus yy ...) son TAN complejos (y, en ocasiones, no exactamente como se describe en las hojas de datos) que los ingenieros con frecuencia tienen un rango favorito de MCU ARM y tienden a querer quedarse con él simplemente porque están familiarizados con los periféricos y las herramientas de desarrollo.

Buenas bibliotecas y herramientas de desarrollo (es decir, compilación rápida + ciclo de depuración con un depurador adecuado) y un gran conjunto de proyectos de código de ejemplo de trabajo son absolutamente cruciales para su elección de ARM MCU hoy en día. Parece que la mayoría de los vendedores ahora tienen tableros de evaluación extremadamente baratos (

Como estoy seguro de que has notado, una vez que superas el nivel de microcontrolador con ARM y entras en el nivel de SOC (por ejemplo, SOC de estilo Raspberry Pi / etc.), las reglas cambian por completo y se trata de qué tipo de Linux vas a utilizar. correr, porque, con muy pocas excepciones, te volverías loco intentando cualquier otra cosa.

Básicamente; independientemente de la CPU que (puede) haber sido preseleccionada para ti en este concierto, cómprate un puñado de placas de evaluación basadas en Cortex súper baratas de algunos proveedores diferentes (TI, STM, Freescale y más vienen a tu mente) y tener un truco con el código de muestra proporcionado.

Último consejo; una vez que encuentre la página o tres en la hoja de datos que describe las opciones de cambio de pines para el chip de número de pieza exacto con el que está trabajando, puede imprimirlo y pegarlo en la pared. Descubrir tarde en un proyecto que una cierta combinación de periféricos es imposible debido a la modificación del pin no es divertido, y a veces esa información está tan oculta que juraría que están tratando de ocultarla :-)


un apéndice rápido: si su proyecto es mucho más que el controlador más simplista, piense en usar un RTOS: hay algo de una curva de aprendizaje con lo que elija, pero incluso los ARM más pequeños tienen mucho empuje hoy en día para ejecutar un sistema operativo multiproceso. Personalmente, he encontrado que ChibiOS es una gran combinación de esbelto pero capaz (especialmente en STM32, donde viene con una buena biblioteca periférica), pero hay varias opciones.
Richard Aplin

4

También vengo de AVR y ahora generalmente me quedo con STM32 (Cortex-M). Esto es lo que recomiendo para empezar, y refleja mis propias dificultades cuando comencé:

  1. Obtenga una placa con un depurador, o al menos un conector JTAG (y luego compre un depurador JTAG). Hay muchos baratos, y ahorrará mucho tiempo al usarlo.

  2. Obtén un buen IDE con todo incluido. Solía ​​recomendar el CooCox CoIDE hace mucho tiempo. Desde entonces se ha detenido y reiniciado el desarrollo, por lo que no estoy seguro de cómo es ahora. "Un buen IDE" le permite obtener el LED básico Hello World parpadeando en poco tiempo.

  3. "Un buen IDE" debería configurar los encabezados CMSIS del fabricante. Básicamente, estos son los mapas de registro que permiten una escritura más fácil de los programas C / C ++, con nombres de variables en lugar de números simples y punteros.

  4. Intente utilizar las bibliotecas periféricas del fabricante, si no necesita el mejor rendimiento absoluto. En realidad no lo haces por ahora, ya que estás aprendiendo. Si luego encuentra que necesita exprimir más, mire el código de la biblioteca para ver cómo hace qué. Lo bueno de las bibliotecas también es que generalmente le permiten usar muchos chips diferentes del mismo fabricante con el mismo código.

  5. A diferencia de AVR, los chips ARM comienzan con periféricos deshabilitados. Necesita habilitarlos primero. Una buena biblioteca de periféricos tendrá ejemplos sobre cómo usar los periféricos correctamente, y puede obtener más información de la hoja de datos del dispositivo. Por lo tanto, recuerde habilitar los relojes y periféricos antes de usarlos. Sí, incluso los puertos de E / S se consideran periféricos.

  6. Codifique a medida que aprende. No intentes asimilar todo de una vez, ya que realmente es bastante complejo. Comenzaría aprendiendo el árbol del reloj (autobuses APB, AHB, etc.) y cómo interactúan los relojes y los divisores de reloj. Luego miraría dónde el IDE almacena los scripts del enlazador y el código de inicio para su dispositivo. La secuencia de comandos del vinculador es más o menos cómo organizar la memoria (dónde está la RAM, la memoria flash, la tabla de vectores ISR, etc.). El script de inicio configura su programa (cosas como copiar inicializadores de variables globales de flash a RAM). Algunos IDE tienen scripts de inicio en ASM y otros tienen en C. A veces puede buscar en Google otro, en el idioma que prefiera.

  7. Haga que el depurador funcione lo antes posible. Es bastante común cometer un error al principio, al hacer algunas cosas (generalmente la inicialización del hardware) en un orden diferente al que debería. Esto a veces desencadena una excepción ISR que lo coloca en while(1);un bucle infinito (implementación predeterminada para ese ISR) que detiene su programa y es difícil de rastrear incluso con un depurador. Imagínese sin un depurador.

  8. Hablando de un depurador, intente poner en marcha el UART también, luego use un adaptador USB serie para leer eso. printf()la depuración siempre es útil :-)


3

No he trabajado mucho en 8051, AVR o PIC. Pero recientemente comencé a mirar la línea de procesadores ARM Cortex MX. Por lo tanto, no puedo decirle mucho sobre la transición desde 8051, AVR o PIC, sino principalmente desde el punto de vista de un principiante.

El procesador ARM®Cortex ™ -M4 se basa en la arquitectura de Harvard, por lo que tiene buses de datos e instrucciones separados. A continuación se muestra una imagen de alto nivel.

ingrese la descripción de la imagen aquí

Esta semana los representantes de NXP visitarán nuestras instalaciones. Comprobaré con ellos los recursos de NXP ARM-Cortex Mx y los publicaré aquí. Freescale tiene un microcontrolador Kinetis Low Power de 32 bits (MCU) basado en núcleos ARM® Cortex®-M , entiendo que también tienen guías similares para aprender procesadores ARM. Lamentablemente no los he investigado.


Referencias

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.