Como fazer a transição de microcontroladores "básicos" para o ARM Cortex?


22

Tenho muitos anos de experiência com núcleos de 8 bits de vários fabricantes - 8051, PIC e AVR - e agora tenho um Cortex M0 para descobrir. Especificamente este , mas espero que possamos ser mais gerais do que isso.

Está se tornando um pouco mais do que eu esperava, com vários documentos que descrevem diferentes partes do sistema em vários níveis de detalhes e nenhum que eu realmente tenha visto para conectar tudo isso. Isso comparado a ter uma folha de dados que explica tudo. Eu entendo ter muito mais coisas para documentar em primeiro lugar, mas a mudança no formato está me dando uma volta.

O site acima tem um documento que é uma boa visão geral de cada subsistema e periférico isolado, e outro que descreve cada registro em detalhes, e eu tenho todo o código-fonte do SDK, incluindo arquivos de cabeçalho e alguns exemplos complexos, mas ainda vejo nada que descreva como tudo se conecta.

Existe uma explicação concisa da arquitetura Cortex que explica a função de coisas que os controladores menores simplesmente não têm - como várias camadas de barramentos da CPU aos periféricos, cada um com seu próprio timer de vigilância - e como todos eles se conectam?


Não sei do que você descreveu se você recebeu a folha de dados / manual do usuário do processador. Isso deve fornecer uma boa imagem e detalhes gerais. De uma das fotos no site que você vinculou, parece um processador NXP. Veja o número da peça do fabricante e procure a documentação do processador em seu site. Também há o site arm.com/products/processors/cortex-m/cortex-m0.php da ARM .
usar o seguinte

Desculpe pela demora em voltar a isso; Eu estive ocupado com outros projetos. Obrigado @ Adam pela voz da experiência.
AaronD

E obrigado @Richard pela visão geral de como pensar sobre isso e pela observação sobre a impressão da configuração dos pinos. Eu votei em vocês dois.
AaronD

Você nunca voltará, exceto se encontrar alguns requisitos extremos de preços. E, mesmo assim, você ficará tentado, já que existem muito pouco Cortex-M barato.
Ronan Paixão

Respostas:


40

Trabalhei em AVRs e em MCUs baseados em ARM Cortex-M3 / M4 / R4. Eu acho que posso oferecer alguns conselhos gerais. Isso assumirá que você está programando em C, não em assembly.

A CPU é realmente a parte mais fácil. Os tipos básicos de dados C terão tamanhos diferentes, mas você está usando o uint8 / 16 / 32_t, certo? :-) E agora todos os tipos de números inteiros devem ser razoavelmente rápidos, com 32 bits (int) sendo o mais rápido. Você provavelmente não possui uma FPU, portanto continue evitando flutuações e duplas.

Primeiro, trabalhe no seu entendimento da arquitetura no nível do sistema. Isso significa E / S, relógio, memória, redefinições e interrupções. Além disso, você precisa se acostumar com a ideia de periféricos mapeados na memória. No AVR, você pode evitar pensar nisso porque os registradores têm nomes exclusivos com variáveis ​​globais exclusivas definidas para eles. Em sistemas mais complexos, é comum consultar registros por um endereço base e um deslocamento. Tudo se resume à aritmética do ponteiro. Se você não estiver familiarizado com os ponteiros, comece a aprender agora.

Para E / S, descubra como o muxing periférico é tratado. Existe um controle central de mux para selecionar quais pinos são sinais periféricos e quais são GPIOs? Ou você define os pinos para o modo periférico usando os registros periféricos? E, é claro, você precisará saber como configurar os GPIOs como entradas e saídas e ativar o modo de dreno aberto e pull / ups / downs. As interrupções externas geralmente se enquadram nessa categoria também. Os GPIOs são bastante genéricos; portanto, sua experiência deve ser útil aqui.

O relógio se resume a algumas coisas. Você começa com uma fonte de relógio, normalmente um oscilador RC de cristal ou interno. Isso é usado para criar um ou mais domínios de relógio no nível do sistema. Os chips de maior velocidade usarão um PLL, que você pode considerar um multiplicador de frequência. Também haverá divisores de relógio em vários pontos. Eles consideram importantes o que deve ser a frequência do clock da CPU e as taxas de bits necessárias para os periféricos de comunicação. Geralmente isso é bastante flexível. Quando você se torna mais avançado, pode aprender sobre coisas como modos de baixo consumo de energia, que geralmente são baseados no clock gating.

Memória significa flash e RAM. Se você possui RAM suficiente, geralmente é mais rápido manter seu programa lá durante o desenvolvimento inicial, para que você não precise programar o flash repetidamente. O grande problema aqui é o gerenciamento de memória. Seu fornecedor deve fornecer scripts de vinculador de amostra, mas pode ser necessário alocar mais memória para código, constantes, variáveis ​​globais ou pilha, dependendo da natureza do seu programa. Os tópicos mais avançados incluem segurança de código e programação em flash em tempo de execução.

As redefinições são bem diretas. Normalmente, você só precisa observar o cronômetro do watchdog, que pode ser ativado por padrão. As redefinições são mais importantes durante a depuração, quando você executa o mesmo código repetidamente. É fácil perder um bug devido a problemas de sequenciamento dessa maneira.

Há duas coisas que você precisa saber sobre interrupções - como ativá-las e desativá-las e como configurar os vetores de interrupção. O AVR-GCC faz o último para você com as macros ISR (), mas em outras arquiteturas você pode precisar gravar um endereço de função em um registro manualmente.

Os periféricos do microcontrolador geralmente são independentes um do outro, para que você possa aprendê-los um de cada vez. Pode ser útil escolher um periférico e usá-lo para aprender parte das coisas no nível do sistema. Os periféricos de comunicação e os PWMs são bons para clock e E / S e os temporizadores são bons para interrupções.

Não se deixe intimidar pelo nível de complexidade. Esses microcontroladores "básicos" já ensinaram muito do que você precisa saber. Informe-me se precisar que eu esclareça alguma coisa.


4
Boa resposta. Outra coisa a observar são os periféricos DMA, que tendem a ter interfaces complicadas e sub-documentadas em minha experiência.
Doug McClean

3
"E agora todos os tipos inteiros devem ser igualmente rápidos." Na verdade, devido às regras de promoção de números inteiros em C, o uso de tipos de 8/16 bits pode resultar em muitas extensões de sinal / zero e pode ser um problema quando a memória Flash está baixa. Portanto, se houver RAM de sobra, pode valer a pena usar mais tipos de 32 bits ou pelo menos preferir int/ int_leastN_Ttipos para variáveis ​​de pilha.
user694733

Cometi um erro no meu comentário. Eu quis dizer; use int_fastN_ttipos, não int_leastN_ttipos.
user694733

@ user694733: Desejo que o padrão C permita que o código solicite um número inteiro que ocupa um determinado tamanho na memória e possa operar com valores dentro de um intervalo específico, mas com semântica pouco especificada ao ultrapassar esse intervalo. Em algo como o ARM, um int16_tgeralmente é tão rápido quanto int32_taos valores armazenados na memória, mas o Padrão exige que, em plataformas com int17 bits ou mais, int16_t x=32767; x+=2;seja definido xcomo -32767, frequentemente exigindo instruções de extensão de sinal, mesmo que o código seja necessário. nunca faça uso do comportamento de quebra automática.
Supercat 23/06

O padrão @supercat C requer comportamento de quebra automática apenas para tipos não assinados. Para tipos assinados, qualquer quebra é UB, devido a diferentes representações possíveis. Portanto x+=2, seria legal usar instruções para tipos de 16 bits, porque o compilador pode assumir que o valor não será quebrado e, portanto, usá-lo não mudaria o comportamento observável. Mas acho que o ARM não possui instrução ADD de 16 bits, o que tornaria isso possível. (Eu posso estar errado, meu conhecimento sobre ARM conjunto de instruções que não é bom.)
user694733

8

É útil lembrar que o ARM possui a propriedade intelectual do microprocessador, mas na verdade não faz peças. Em vez disso, os fabricantes licenciam as várias versões do processador ARM e produzem suas próprias peças únicas com combinações individuais de recursos e periféricos.

Com isso dito, se você é novo na arquitetura, provavelmente faria sentido começar com a documentação da ARM, que é, essencialmente, a documentação de linha de base para todos esses microprocessadores.

Por exemplo, o Cortex-M0 é descrito no site da ARM .

Há também uma lista de livros relacionados ao ARM que atendem a uma ampla variedade de necessidades e interesses.

Finalmente, existem as folhas de dados do fabricante específico. Para o M0, Cypress, NXP e STMicroelectronics são apenas três dos muitos fabricantes de peças reais baseadas no Cortex-M0.

(E não, eu não trabalho para a ARM e nunca trabalhei.)


1
Essa é uma resposta bastante genérica que não faz muito mais que um link para alguns documentos do Cortex-M0, que tenho certeza que o OP pode encontrar por conta própria.
Jay Carlson

1
Ele aborda diretamente a pergunta que solicitou ajuda para encontrar a documentação geral. Essa resposta responde diretamente a essa necessidade e explica por que as coisas são como são.
22416 Edward Edward

8

Uma grande diferença é o uso de bibliotecas fornecidas pelo fornecedor. Para os PICs, Atmels, etc, as bibliotecas básicas (para gpio, timers, adc, etc) não foram muito usadas pela maioria dos desenvolvedores. Na minha experiência, as pessoas (no máximo) as usariam como guias ao escrever seu próprio código.

No entanto, com o ARM, as bibliotecas são quase sempre usadas. Existe um padrão, "CMSIS", que os fabricantes devem seguir. A maioria faz. Ajuda na portabilidade de código (entre diferentes ARMs e entre fabricantes) e fornece um método "padronizado" para estruturar seu código. As pessoas se acostumam a ver e entender as funções da biblioteca.

Claro, existem alguns desenvolvedores que acessam os registros diretamente, mas eles são os outliers :)

Para responder sua pergunta, achei muito útil ler a documentação da Biblioteca. O ST possui um código bem desenvolvido, com um grande arquivo de ajuda criado por Doxygen. Você pode ver quais são todas as opções para cada módulo de hardware.

Para usar o GPIO como exemplo, a função de inicialização lida com:

  • Direção (Entrada ou Saída)
  • pullups / pulldowns
  • coletor aberto / push-pull
  • taxa de variação
  • etc.

Observando as opções, você pode ver o que é possível. E, é claro, você aprenderá como passar essas opções para a função Init!

OK, agora que eu disse isso, vejo que seu ARM específico não possui bibliotecas compatíveis com CMSIS. Em vez disso, eles têm seu SDK proprietário disponível para download. Eu começaria a procurar pelos documentos do SDK.

Se você não é casado com este produto específico, recomendamos que você encontre um fornecedor diferente com bibliotecas mais compatíveis. Você vai escalar uma curva de aprendizado de qualquer maneira, para tornar seu investimento mais portátil ...

BRAÇOS são divertidos! Eu não olhei para trás.


"Para os PICs, Atmels, etc, as bibliotecas não foram muito usadas pela maioria dos desenvolvedores." Não tenho certeza de onde isso vem. Eu usei apenas PICs, não o AVR, mas certamente não gostaria de escrever minha própria biblioteca, por exemplo, para a interface host USB, pilha TCP ou sistema de arquivos de cartão SD. As bibliotecas da Microchip para todas elas parecem bastante adequadas.
tcrosley

Ah, @tcrosley, você está definitivamente correto. Eu só estava tentando para se referir à funcionalidade coberta pelos periféricos básicos: GPIO, temporizadores, a ADC, etc.
bitsmack

Concordo, normalmente acesso GPIO, temporizadores, relógios e UART R / W diretamente. Às vezes, eu uso suas chamadas de biblioteca para configuração de I2C, SPI, ADC e UART, mas nem sempre. Muitos registros, esteja você falando do PIC (e, em particular, do PIC32) ou do ARM.
tcrosley

Eu acho que essa resposta é a mais pragmática listada para esta pergunta, mesmo que não se aplique ao controlador específico do OP. Eu acho que você pode fazer um pouco de boa engenharia incorporada sem entender o AHB ou o NVIC.
Jay Carlson

@JayCarlson Thanks! Sua edição desta resposta foi rejeitada porque não devemos alterar as postagens de outras pessoas de maneira tão significativa. Mas foi realmente uma boa informação! Eu sugiro que você publicá-la como sua própria resposta, por isso vai ajudar as pessoas e também se upvoted :)
bitsmack

5

Boa hora para se mudar; os 8 bits estão morrendo rapidamente; quando você pode comprar uma placa de US $ 5 com (por exemplo) um STM32F103, que é um microcontrolador ARM de 32 bits bastante capaz (com USB incluso!), não há dúvida de que os tempos mudaram.

Você já teve ótimas respostas, mas principalmente eu diria "esqueça a montagem" e quase "esqueça de se preocupar com o funcionamento da CPU em um nível baixo" - um dia haverá um caso em que você precisará cavar (uma otimização específica ou para depuração), mas os núcleos do ARM executam o código C excepcionalmente bem (por design) e você varia raramente precisa se aventurar profundamente no interior.

Isso significa que você gastará uma certa quantidade de tempo enfrentando problemas com compiladores (e especialmente vinculadores e makefiles) exibindo erros obscuros para você, mas todos são superáveis.

As tripas de como os ARMs funcionam (ou seja, os livros da CPU do ARM) são densas e pouco interessantes até o dia em que você realmente precisa otimizar (e você ficará surpreso com a pouca frequência disso quando você tem registros de 32 bits e seu PLL ' d O relógio da CPU está na região de 100 mhz).

O conjunto de instruções ARM "old skool" é muito mais fácil de ler uma desmontagem do que o muito mais recente "Thumb2" - que é o que você encontra nos ARMs mais modernos (Cortex) em nível de microcontrolador - mas, novamente, as entranhas das instruções em linguagem de montagem desbotam principalmente em segundo plano; se você possui o conjunto de ferramentas certo (especialmente um depurador no nível da fonte decente com pontos de interrupção / etapa única etc), você simplesmente não se importa muito com o fato de ser ARM.

Quando você estiver no mundo dos registros de 32 bits e das larguras de barramento de dados de 32 bits e tudo o que você sempre quis disponível no chip, nunca mais desejará voltar a uma CPU de 8 bits; basicamente, geralmente não há penalidade por "ficar com calma" e escrever código para ser legível mais do que eficiente.

No entanto ... periféricos ... sim e tem o problema.

Você com certeza tem uma tonelada de coisas para tocar nos MCUs modernos, e muitas delas são bem bonitas; você costuma encontrar um mundo de sofisticação muito, muito além dos periféricos on-chip AVR, PIC e 8051.

Um temporizador programável? Nah, tenho oito! DMA? Que tal 12 canais com prioridade programável e modo burst, modo encadeado e recarregamento automático e .. e .. e ...

I2C? I2S? Dezenas de opções de muxing de pinos? Quinze maneiras diferentes de reprogramar o flash no chip? Certo!

Muitas vezes parece que você passou da fome para o banquete com os periféricos e é comum que existam pedaços inteiros de um chip que você admira, mas que mal usa (daí o relógio).

Atualmente, a quantidade de hardware no chip (e as variações na linha de chips de apenas um fornecedor) é hoje bastante impressionante. É claro que um fornecedor de chips tende a reutilizar os blocos de IP; assim, quando você se familiariza com uma determinada marca, fica mais fácil, mas "a merda está ficando louca hoje em dia".

Se alguma coisa, os periféricos e suas interações (e DMA e interrupções e alocação de barramento e e e ...) são tão complexos (e, ocasionalmente, não exatamente como descrito nas planilhas de dados) que os engenheiros freqüentemente têm um intervalo favorito de MCUs e ARM tendem a querer ficar com ela simplesmente porque estão familiarizados com os periféricos e as ferramentas de desenvolvimento.

Boas bibliotecas e ferramentas de desenvolvimento (ou seja, ciclo rápido de compilação + depuração com um depurador adequado) e um grande conjunto de projetos de código de exemplo em funcionamento são absolutamente cruciais para a sua escolha do ARM MCU atualmente. Parece que muitos fornecedores agora têm quadros de avaliação extremamente baratos (

Como tenho certeza de que você notou, uma vez que você ultrapassa o nível do microcontrolador com os ARMs e entra no nível do SOC (por exemplo, SOCs no estilo Raspberry Pi / etc), as regras mudam completamente e é sobre o tipo de Linux que você vai para correr, porque - com poucas exceções - você estaria louco para tentar qualquer outra coisa.

Basicamente; independentemente da CPU que (pode) ter sido pré-selecionada para você neste show, compre um punhado de placas de avaliação baseadas em Cortex super baratas de alguns fornecedores diferentes (TI, STM, Freescale e mais): hackear com o código de exemplo fornecido.

Conselho final; depois de encontrar a página ou três na folha de dados que descreve as opções de agrupamento de pinos para o chip exato do número de peça com o qual você está trabalhando, convém imprimi-lo e colá-lo na parede. Descobrir no final de um projeto que uma certa combinação de periféricos é impossível por causa do muxing de pinos não é divertido, e às vezes essas informações são tão escondidas que você jura que estão tentando escondê-las :-)


um adendo rápido - se o seu projeto é muito mais do que o controlador mais simplista, pense em usar um RTOS - há uma espécie de curva de aprendizado com o que você escolher, mas mesmo os menores ARMs têm bastante poder hoje em dia para executar um sistema operacional multithread. Pessoalmente, descobri que o ChibiOS é uma ótima combinação de capacidade enxuta, mas capaz (especialmente em execução no STM32, onde ele vem com uma boa biblioteca periférica), mas há várias opções.
Richard Aplin

4

Eu também vim do AVR e agora geralmente uso o STM32 (Cortex-M). Aqui está o que eu recomendo para iniciantes e reflete minhas próprias dificuldades quando comecei:

  1. Obtenha uma placa com um depurador, ou pelo menos um conector JTAG (e compre um depurador JTAG). Existem muitos baratos por aí, e você economizará muito tempo usando-o.

  2. Obtenha um bom IDE com tudo incluído. Eu costumava recomendar o CooCox CoIDE há muito tempo. Desde então, ele parou e reiniciou o desenvolvimento, então não tenho certeza de como está agora. "Um bom IDE" permite que você pisque rapidamente o LED básico Hello World.

  3. "Um bom IDE" deve configurar os cabeçalhos CMSIS do fabricante. Estes são basicamente os mapas de registro que permitem a gravação mais fácil de programas C / C ++, com nomes de variáveis ​​em vez de números simples e ponteiros.

  4. Tente usar as bibliotecas periféricas do fabricante, se você não precisar do melhor desempenho absoluto. Você realmente não faz agora, já que está aprendendo. Se mais tarde você achar que precisa espremer mais, consulte o código da biblioteca para ver como ele faz o quê. O bom das bibliotecas também é que elas geralmente permitem que você use muitos chips diferentes do mesmo fabricante com o mesmo código.

  5. Diferentemente do AVR, os chips ARM começam com os periféricos desativados. Você precisa habilitá-los primeiro. Uma boa biblioteca de periféricos terá exemplos de como usar os periféricos corretamente e você poderá obter mais informações na folha de dados do dispositivo. Portanto, lembre-se de ativar os relógios e os periféricos antes de usá-los. Sim, até as portas de E / S são consideradas periféricas.

  6. Codifique conforme você aprende. Não tente grudar tudo de uma vez, pois é realmente bastante complexo. Eu começaria aprendendo a árvore do relógio (APB, AHB, etc.) e como os relógios e os divisores de relógio interagem. Depois, veria onde o IDE armazena os scripts do vinculador e o código de inicialização do seu dispositivo. O script do vinculador é basicamente como você organiza a memória (onde estão RAM, flash, tabela de vetores ISR etc.). O script de inicialização configura seu programa (como copiar inicializadores de variáveis ​​globais do flash para a RAM). Alguns IDEs têm scripts de inicialização no ASM e outros no C. Às vezes você pode procurar no Google por outro, no idioma que preferir.

  7. Obter o depurador indo o mais rápido possível. É bastante comum cometer um erro no começo, fazendo algumas coisas (geralmente inicialização de hardware) em uma ordem diferente da que você deveria. Às vezes, isso desencadeia uma exceção ISR que fornece while(1);um loop infinito (implementação padrão para esse ISR) que interrompe seu programa e é difícil rastrear até mesmo com um depurador. Imagine sem um depurador.

  8. Falando sobre um depurador, tente fazer o UART funcionar também e use um adaptador USB serial para ler isso. printf()a depuração é sempre útil :-)


3

Não trabalho muito em 8051, AVR ou PIC. Mas recentemente comecei a olhar para a linha de processadores ARM Cortex MX. Portanto, não posso falar muito sobre a transição do 8051, AVR ou PIC, mas principalmente do ponto de vista de um iniciante.

O processador ARM®Cortex ™ -M4 é baseado na arquitetura de Harvard, portanto possui barramentos de dados e instruções separados. Abaixo está uma imagem de alto nível.

insira a descrição da imagem aqui

Nesta semana, representantes da NXP visitarão nossas instalações. Vou verificar com eles todos os recursos do NXP ARM-Cortex Mx e publicá-los aqui. A Freescale possui um microcontrolador de 32 bits (MCUs) Kinetis Low Power baseado nos núcleos ARM® Cortex®-M , eu entendo que eles também têm guias semelhantes para aprender os processadores ARM. Infelizmente eu não os pesquisei.


Referências:

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.