Estudando Projetos do SDK 10 para nRF5x com Eclipse Oxygen (Portuguese)

The purpose of this tutorial is to expound my notes on the studies I have done on the use of nRF51, but also serve for the nRF52, and thus share with the beginner as I of the Portuguese language. This tutorial is continuity in the [previous tutorial] (https://devzone.nordicsemi.com/blogs/1193/configuring-the-eclipse-oxygen-for-development/).

The SDK 10 is chosen because there is still the S110 version of SoftDevice for the nRF51.

If you find any errors, be sure to let me know, because they are annotations made as I am learning to program for these modules, so I can initially mislead some information.


O objetivo deste tutorial é expor minhas anotações dos estudos que tenho feito sobre o uso do nRF51, mas também servem para o nRF52, e assim compartilhar com o iniciantes como eu da língua portuguesa. Este tutorial é continuidade no tutorial anterior.

A escolha do SDK 10 se dá porque nele ainda há a versão S110 do SoftDevice para o nRF51.

Caso identifique algum erro, não deixe de me informar, pois são anotações feitas conforme estou aprendendo a programar para estes módulos, portanto posso inicialmente me enganar em alguma informação.

Testando o projeto pela Linha de Comando

Antes de partimos para o Eclipse certifique-se que consegue compilar sem erros seu projeto através da linha de comando.

Caso seja a primeira vez que está tentando compilar um projeto, ou se não teve sucesso ainda, é importante que você tenha uma estrutura de diretório nova e original, sem nenhuma alteração. Sendo assim baixe o SDK 10 se preciso e descompacte em um diretório que poderá trabalhar sem preocupação. Eu uso normalmente o diretório workspace dentro do diretório do usuário que me logo no computador.

No meu ambiente de trabalho meu diretório fica assim:

image description

Portanto a raiz do sdk será sempre referenciado como C:\Users\Admin\workspace\Nordic\nRF5_SDK\10.x.x, assim não será mais citado este caminho, em seu caso o caminho pode ser completamente outro, mas deste ponto a estrutura deve ser idêntica, com a pena de seu projeto não funcionar com as instruções apresentadas. Deste ponto usaremos sempre referências relativas aos diretórios do projeto e de pastas auxiliares.

Confirme as instalações das ferramentas feitas conforme no post anterior, abaixo estão os diretórios no qual tenho as ferramentas instaladas, para confirmar use o comando wherepor exemplo where arm-none-eabi-gcc e where make: C:\Users\Admin\workspace\Nordic\nRF5_SDK\10.x.x\examples\peripheral\blinky\pca10028\s110\armgcc>where arm-none-eabi-gcc C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q2-update\bin\arm-none-eabi-gcc.exe

C:\Users\Admin\workspace\Nordic\nRF5_SDK\10.x.x\examples\peripheral\blinky\pca10028\s110\armgcc>where make
C:\Program Files\GNU MCU Eclipse\Build Tools\2.9-20170629-1013\bin\bin\make.exe 

Em meu ambiente tenho diversas versões do gcc e make no path, evite tal prática no início, pode lhe trazer problemas que irão dificultar os primeiros passos.

Usarei os diretórios acima para parametrizar o SDK. Para isso, é preciso editar o arquivo Makefile.windows, se estiver usando o Linux ou Mac, edite o arquivo Makefile.posix. Este arquivo srá encontrado na pasta components\toolchain\gcc\ dentro da pasta raiz de seu SDK.

No caso do windows o arquivo tem o conteúdo similar a baixo:

GNU_INSTALL_ROOT := C:/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q3
GNU_VERSION := 4.9.3
GNU_PREFIX := arm-none-eabi

Se você não tiver esta versão do GCC instalado neste caminho irá ter problemas, e considerando que você está começando agora com sua instalação e seguiu o tutorial anterior acredito que terá a versão 6.3.1 ou superior, então o arquivo deverá representar tal instalação, no caso da 6.3.1 no dia que eu fiz este tutorial ficou assim:

GNU_INSTALL_ROOT := C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q2-update
GNU_VERSION := 6.3.1
GNU_PREFIX := arm-none-eabi

Considerando que tudo está como foi apresentado em ambos os tutoriais, ao executar o comando make em um projeto como por exemplo o blink, ele irá compilar com sucesso, veja abaixo:

C:\Users\Admin\workspace\Nordic\nRF5_SDK\10.x.x\examples\peripheral\blinky\pca10028\s110\armgcc>make
rm -rf _build
echo  Makefile
Makefile
mkdir _build
Compiling file: system_nrf51.c
Compiling file: main.c
Compiling file: nrf_delay.c
Compiling file: gcc_startup_nrf51.s
Linking target: nrf51422_xxac_s110.out
make[1]: Entering directory 'C:/Users/Admin/workspace/Nordic/nRF5_SDK/10.x.x/examples/peripheral/blinky/pca10028/s110/armgcc'
Preparing: nrf51422_xxac_s110.bin
Preparing: nrf51422_xxac_s110.hex

   text    data     bss     dec     hex filename
   1300     104      28    1432     598 _build/nrf51422_xxac_s110.out

make[1]: Leaving directory 'C:/Users/Admin/workspace/Nordic/nRF5_SDK/10.x.x/examples/peripheral/blinky/pca10028/s110/armgcc'

Se vc tiver um resultado como este está pronto para dar o próximo passo para usar o Eclipse.

Importanto o projeto para o Eclipse.

Como testamos anteriormente e tudo deu certo pela linha de comando, vamos agora importar o projeto no Eclipse.

Alguns conceitos importantes antes de continuarmos

Caso seja a primeira vez que esteja trabalhando com a linha nRF5x é preciso que compreenda alguns conceitos importantes.

Quando formos trabalhar com os projetos podemos ter que identificar qual módulo estamos usando e qual versão, para isso usamos o conceito chamado PCA que significa Printed Circuit Assembly, como Montagem do Circuito Impresso, PCA ajuda a identificar a versão da montagem do módulo, normalmente são identificados como pca10028, pca20006.

Além da versão do módulo podemos adotar uma base para nosso firmware, conhecido como SoftDevice, é uma API, quase um sistema operacional que define uma API para acesso transparente aos recursos do módulo e de forma padronizada e também oferece o stack para cada protocolo suportado pelos módulos.

Abaixo apresento o diagrama de blocos da arquitetura da linha nRF5x e onde o software encaixa:

Aquiretura do SoC nRF

Para obter mais informações sobre SoftDevices visite o link: http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.softdevices51%2Fdita%2Fnrf51%2Fsoftdevices.html

Compreendendo a estrutura de um projeto no SDK nRF

A estrutura do SDK da série nRF foi criado exatamente para evitar redundância de arquivos e facilitar o reaproveitamento quando necessário. Vamos antes compreender um pouco como está distribuída estes arquivos.

Já vimos duas pastas a do projeto quando compilando com o ARM GCC da versão correspondente ao SoftDevice que será usado e pasta components\toolchain\gcc vejamos o que representa cada pasta.

A pasta do exemplo

Estamos usando o exemplo Blink, este exemplo pode ser compilado para o módulo nRF51422 nRF51822, ele está dentro da pasta peripheral porque é um dos diversos exemplos que demonstra como usar os módulos como periféricos no Bluetooth LE.

Nesta pasta como pode ser visto abaixo na imagem é composta por uma estrutura que representa tanto as possíveis versões do Hardware (PCA - Printed Circuit Assembly) como também as versões do Firmware (SoftDevice), além da ferramenta para compilação do código.

vamos então importar o projeto no Eclipse, como estamos usando o ARM GCC iremos usar a pasta armgcc que se encontra exemplates\peripheral\blink\pca10028\s110\armgcc, se quiser arriscar seguir seus próprios passos, pode escolher outro exemplo até mais complexo, mas lembre-se que só poderei ajudar neste nível seguindo exatamente meus passos, e não se esqueça que para o Eclipse e o ARM GCC é necessário usar a pasta armgcc.

Se você entrar nesta pasta com o explorer verá que nela há dois arquivos apenas, um descrição do uso da memória do MCU (blinky_gcc_nrf51.ld) e o Makefile. Portanto nosso projeto deve ser exportado como sendo um projeto baseado em Makefile.

Conteudo da Pasta armgcc

Os demais arquivos específicos do projeto exemplo "Blink" são encontrados nas pastas anteriores, e podem inclusive aproveitar de outros projetos como você irá ver logo a frente, já os arquivos comuns a este tipo de uso, estão espalhados pelas pastas do SDK conforme sua aplicação.

Pasta Componente

A Pasta Components possui o framework propriamente e todos os fontes de código e cabeçalhos que definem os símbolos usados na programação para o nRF5x, veja que a pasta é dividida em grupos de subpastas como listado e explicado abaixo:

  • ant -> API da pilha de protocolo ANT
  • ble -> API da pilha de protocolo Bluetooth LE
  • device -> API para acesso ao hardware do dispositivo conforme a linha nRF51 ou nRF52
  • drivers_ext-> API para acesso a dispositivos externos ao nRF51 como o nRF6350 (um display) e de terceiros como J-Link, DS1624 Termometro Digital da Maxim, etc.
  • drivers_nrf -> API para acesso a dispositivos internos e protocolos do nRF5x como UART, TWI, I2C, pinagens, timers, etc.
  • libraries -> Biblioteca de funções e recursos uteis ao desenvolvimento adaptadas adequadamente para uso com o nRF5x.
  • proprietary_rf -> API para uso de protocolos de ocmunicação RF propriétários como o Gazzelle.
  • softdevice -> API para uso dos SoftDevices como o próprio nome diz.
  • toolchain -> Biblioteca de apoio e simbolos especificos para cada Toolchain usado, ARM GCC, Keil e IAR.

É importante conhecer bem a estrutura das pastas e o que contém cada uma para facilitar seu trabalho ao criar um novo projeto.

Mas vamos então fazer a importação.

Importando o Projeto

Entre no Eclipse, escolha o workspace que deseja trabalhar com estes projetos.

Agora abra o menu "File", em seguida "Import", irá então ver a janela abaixo e na arvore de opções de importação abra o braço "C/C++" e selecione "Existent Code as Makefile Projet", você pode usar o campo de texto para pesquisar as opções, digite apenas "make" e ele irá listar as opções relativas a palavra make.

Importando projeto baseado em Makefile

Na próxima tela digite o nome do projeto que deseja usar, eu usarei "Exemplo Blink - PCA10028 - S110", escolha a pasta onde está o arquivo Makefile, como citei o SDK e os projetos de exemplos está na pasta workspace onde criei outra pasta para conter os projetos relativos a este trabalho chamada `nordic\nRF{versão do sdk}', sendo assim veja na imagem abaixo como ficou na estrutura que eu uso.

Lembre-se também de escolher o Toolchain que será usado, no nosso caso "ARM Cross GCC":

Dando o Nome ao Projeto, Selecionando a pasta do Makefile e escolhendo o Toolchain

Siga em frente, sem mudar outras opções, finalizando esta etapa.

O resultado será o seguinte:

Se você listar o diretório pela linha de comando verá que apenas os arquivos do Eclipse foram adicionados:

C:\Users\Admin\workspace\Nordic\nRF5_SDK\10.x.x\examples\peripheral\blinky\pca10028\s110\armgcc>dir
 Volume in drive C has no label.
 Volume Serial Number is 648F-BA64

 Directory of C:\Users\Admin\workspace\Nordic\nRF5_SDK\10.x.x\examples\peripheral\blinky\pca10028\s110\armgcc

11/11/2017  02:36 PM    <DIR>          .
11/11/2017  02:36 PM    <DIR>          ..
11/11/2017  02:36 PM            22,942 .cproject
11/11/2017  03:09 PM             4,807 .project
11/11/2017  02:36 PM    <DIR>          .settings
11/08/2017  10:18 AM               391 blinky_gcc_nrf51.ld
11/10/2017  12:54 PM             7,242 Makefile
               4 File(s)         35,382 bytes
               3 Dir(s)  243,739,619,328 bytes free

Sugestão: Apesar que, apenas os arquivos de configuração do Eclipse para o projeto serão criados nesta pasta, você pode não querer que isso aconteça, então você pode optar por copiar a pasta armgcc para outra pasta no mesmo nível da estrutura com o nome sugestivo de eclipse, mas lembre-se de manter o mesmo nível da pasta original, assim você não irá quebrar as referências, e não deixe copiar a pasta armgcc com todos os arquivos. Desta forma você pode editar a pasta como desejar e se cometer algum erro não irá interferir na pasta original. E todos os arquivos que criar com seus testes ficaram separados.

Bem, você deve estar se perguntando como eu já me perguntei a primeira vez que usei um projeto assim no Eclipse, e ai, onde estão meus fontes, meus "headers" e tudo mais que constrói meu projeto?

Os arquivos estão relativos a este diretório e não podem ser visto no Eclipse, para isso é preciso criar pastas virtuais que irão fazer referência a esta estrutura de forma que ela apareça dentro do projeto e assim você possa estuda-la.

Trazendo os outros arquivos do projeto para se tornarem visíveis no projeto

Para que possamos trazer de forma a tornar visíveis os outros arquivos do projeto é adequado criarmos pastas para mantermos o projeto organizado, mas não queremos duplicar todos os arquivos, queremos apenas torná-los visíveis.

*Sugestão" você pode optar também em usar "Linked Folder" assim ao invés de criar um "Folder Virtual" e importar arquivos desejados para seu projeto, você pode linkar virtualmente todos os Folders que achar necessário ao seu projeto, mantendo a estrutura dos subfolders. Este formado é mais interessante para projetos muito complexos que demandam uma maior quantidade de arquivos. Não usaremos ele neste tutorial. Mas poderá se deparar com ele sem prévio aviso em tutoriais futuros.

Criando Pastas Virtuais

As "Pastas Virtuais" (Virtual Folders) existem apenas internamente no Eclipse, se você voltar ao projeto pelo explorer elas não serão visíveis e assim não irá interferir em seu projeto original.

Além disso a grande vantagem de se usar Pastas Virtuais, é que ao se criar um arquivo internamente, não interfere nas pastas ao qual elas fazem alusão.

Continuando nossa importação, vamos agora então criar as pastas virtuais para manter os espelhos (links) para os arquivos de apoio do projeto, eu optei em usar uma estrutura levemente diferente, não se preocupe isso não irá atrapalhar em nada nem dificultar nada, apenas irá ajudar a identificar onde estão os arquivos então segue a descrição de cada pasta virtual:

  • toolchain = Arquivos auxiliares de parametrização do projeto com ARM GCC, Makefiles de apoio conforme plataforma, e outros headers específicos do ARM GCC.
  • config = Caso o projeto o uso conterá as configurações do projeto, no blink não é necessário.
  • softdevice = Arquivos relativos a API SoftDevice
  • device = Arquivos relativos aos dispositivos usados
  • drivers_nrf = Arquivos especificos dos drivers do nRF
  • main = Arquivos principais do projeto

Para criar tais pastas virtuais, siga o seguintes passos para cada uma delas:

Clique com o botão direito sobre o nome do projeto, selecione "New", e então "Folder":

Selecionando o menu new folder

Na janela que surgir, certifique-se que seu projeto está selecionado na caixa que listas os projetos, no campo de texto "Folder Name" digite em cada vez um dos nomes acima, em seguida clique no botão "Advanced", selecione a opção "Folder is not located in the File System (Virtual Folder)"

Criando Virtual Folder

Bem depois de repetido este passo para cada folder sugerido acima, vamos iniciar a importação dos arquivos.

Importando os arquivos e pastas como Links para as pastas virtuais

Agora iremos criar os links para os arquivos e pastas já existentes, como podem ver serão links, assim os aquivos não serão duplicados, o que evitará ter arquivos desatualizados caso atualize o SDK, mas há o risco de você fazer alteração em um arquivo comum a todos os outros projetos prejudicando-os assim, cuidado, o uso deste recurso é indicado apenas para evitar duplicação de arquivos, se pretende altera-los use a opção para copiá-los para a pasta.

As seguintes pastas e arquivos deverão ser linkados nas respectivas pastas virtuais:

  • toolchain:
    • ../../../../../../components/toolchain/
  • main
    • ../../../main.c
    • ../../../../../bsp/boards.h
  • drivers_nrf
    • ../../../../../../components/drivers_nrf/
  • config
    • Não há arquivos a serem linkados;
  • softdevice
    • ../../../../../../components/softdevice/s110/headers
  • device
    • ../../../../../../components/device
  • libraries
    • `../../../../../../components/libraries\

Vejamos então como fazer com o arquivo boards.h, este deve estar na pasta main:

Para começar, clique com o botão direito sobre o nome da pasta que pretende usar para importar, selecione "import":

Na janela que se abrir, use a opção "File System" que se encontra na pasta "General":

Importando File System

Clique em "next" e então encontre as pasta que deseja importar, veja que este procedimento deberá ser seguido para cada pasta citada acima para a pasta virtual sugerida, tal seleção é meramente para manter o projeto organizado e facilitar encontrar cada arquivo.

Atenção o caminhos estão apresentados como referência com relação a pasta armgcc, ou se você optou em copiar a pasta para eclipseesta deve estar no mesmo nível e mantendo as referências. Mas nas imagens abaixo serão apresentados de forma absoluta conforme minha instalação.

Como na imagem abaixo, uma vez selecionado o diretório, você deve marcar apenas os arquivos que deseja importar, nada mais, evite importar arquivos desnecessários principalmente nesta fase, você poderá importar novos arquivos sempre que quiser, portanto pode ir importando aos poucos conforme demanda, neste caso importaremos apenas como foi citado acima, arquivos e pastas quando for conveniente para encurtar, mesmo que a pasta tenha mais do que precisamos.

Importando o arquivos boards.h

O resultado está na imagem abaixo, veja que o Eclipse já analisou o conteúdo do arquivo e já o processou para facilitar o tratamento do mesmo. Se você clicar em um dos símbolos definidos neste arquivo header, ele irá abrir o arquivo e exibir a linha onde ele está definido.

Arquivo boards.h processado

Vamos repetir o processo para a pasta toolchain, ela tem uma peculiaridade que irá se repetir em outras importações, faça o mesmo procedimento para importar arquivos e encontre a pasta no SDK. Veja a imagem:

Importando a pasta toolchain e subpastas importantes

Como você pode ver a pasta toolchain além de ter arquivos tem subdiretórios, e eu não quero importar todos os subdiretórios apenas os que fazem referência ao toolchain do ARM GCC, sendo assim ao selecionar a pasta, eu desmarco os demais diretórios que não desejo. É mais fácil marcar a pasta principal, e ir desmarcando todas as subpastas que não me interessa, e depois se for o caso os arquivos que não me interessam.

Esta seleção também é util quando se quer selecionar uma subpasta para uma pasta virtual e outra pasta pai para outra pasta virtual, algo como comuns, isso poderá acontecer em projetos mais complexos.

Faça agora você mesmo a importação da pasta softdevice, device e drivers_nrf, libraries.

Alguns ajustes no Makefile para Indexação no Eclipse

Para a perfeita indexação dos arquivos e o eclipse conseguir linkar os símbolos referenciados com suas declarações é preciso fazer uma pequena mudança no arquivo Makefiledo projeto.

Lembre-se Foi por isso que sugeri criar uma pasta eclipse com a copia do conteúdo da pastaarmgccassim você pode fazer alterações nos arquivos de definição do projeto sem problemas e riscos. Mas vamos continuar como estamos indo, e deixe tal prática como exercício.

Na linha 75, na variável CFLAG está apenas o parametro -O3 que optimiza o código, como pretendemos futuramente depurar este código, vamos reduzir a optimização para nenhuma então passe este parâmetro para -O0, e adicione também o parâmetro -g3 para depuração.

Na linha 67, você encontra o parâmetro -D definindo uma MACRO de compilação de nome BOARD_PCA10028, guarde o nome desta variável. Você poderá usar as demais se desejar.

Salve as alterações feitas, o arquivo ficará assim:

Arquivo Makefile alterado

Ajustando o Eclipse para identificar os Simbolos e Paths de inclusão

O Eclipse é capaz de interpretar a compilação pelo make e assim indexar todos os símbolos e arquivos onde os mesmos estão declarados, mas para isso é preciso dois passos cruciais. Veja que no primeiro registramos apenas uma variável, podendo ser registradas as demais informadas no Makefile para se obter uma maior precisão da indexação.

Parametrizando a interpretação dos arquivos

O primeiro passo para ajustar o Eclipse para que ele identifique corretamente os simbolos e os paths de inclusão é desativar a resolução heurística dos includes para isso, vá nas propriedades do projeto, e siga na arvore por "C/C++ General", "Index", na janela que abrir, desmarque a opção "Allow heuristic resolution of includes".

Este recurso tem causado falhas na interpretação dos dados para indexação.

Automatizando a Inclusão de Paths e Indexação dos Símbolos

Agora vamos ensinar ao Eclipse como interpretar a compilação e resultados da indexação dos símbolos, são dois passos muito simples.

Abra novamente a janela de propriedades do projeto, vá na árvore seguindo o caminho de parametrização até a janela "C/C++ Build", nesta janela desmarque a opção "Use default build command", clique na caixa de texto, certifique-se que depois de {cross_make} haja um espaço, então escreva VERBOSE=1. Isso fará com que o Make apresente todas as informações relativas a compilação, ajudando o eclipse a encontrar os arquivos que são incluídos na compilação de seu código. Veja a imagem:

image description

Agora vamos mostrar ao Eclipse como interpretar a saída do Make, vá na opção de configuração, "C/C++ General", "Preprocessor Include Paths, Macros etc.", na janela que se abre, selecione a aba "Providers", então seleciona na lista "CDT GCC Build Output Parser", certifique-se apenas de seleciona-lo não desmarcando nenhuma opção da lista.

Abaixo procure a caixa de texto "Compiler Command Parser", apague seu conteúdo e escreva: (.*gcc)|(.*[gc]\+\+)

Clique então no botão "Apply and Close", o Eclipse dará início a reindexação de seu projeto. A primeira vista nada mudou, mas se observar bem na arvore do projeto, surgiu uma nova pasta includes nesta pasta estão os arquivos que o eclipse identificou como sendo necessários para um projeto de sucesso.

Conclusão

O Resultado final deste tutorial é você poder compilar qualquer projeto de exemplo e navegar por seus arquivos inclusos com a diretiva #includeou mesmo clicando em algum simbolo com o botão esquerdo enquanto seguro a tecla [CTRL] e assim ter acesso a sua declaração, seja uma Macro, Variável ou Função.

No próximo tutorial irei mostrar como usar um dos exemplos como referência para criar um novo projeto com o Eclipse.

Próximos Tutoriais

  • Criando um projeto Original do Zero com o Eclipse e ARM GCC

Tutoriais Anteriores