ambiente de desenvolvimento arm
TRANSCRIPT
Ambiente de Desenvolvimento para Microcontrolador ARM
Relatório submetido à Universidade Federal de Santa Catarina
como requisito para a aprovação na disciplina
DAS 5501: Estágio em Controle e Automação Industrial
Marcelo Sousa Menegol
Florianópolis, Junho de 2013
Ambiente de Desenvolvimento para Microcontrolador ARM
Marcelo Sousa Menegol
Orientadores:
Jonatan Vieira, Engenheiro de Software
______________________________Assinatura do Orientador
Prof. Werner Kraus Jr.
_______________________Assinatura do Orientador
Este relatório foi julgado no contexto da disciplina DAS5501: Estágio e Controle e Automação Industrial
e aprovado na sua forma final peloCurso de Engenharia de Controle e Automação
2
Resumo
A Arvus Tecnologia é a única empresa nacional fabricante de equipamentos
para Agricultura e Silvicultura de Precisão. Um dos principais equipamentos
desenvolvidos por esta empresa é um computador de bordo que é instalado em
máquinas agrícolas. Este computador é responsável por controlar vários atuadores
da máquina e também por coletar dados sobre as operações realizadas. Este
computador de bordo tem um processador da arquitetura ARM que é o coração de
todo o sistema.
Como é essencial que uma empresa de tecnologia acompanhe as novas
tendências do mercado tecnológico, é do interesse da empresa modernizar o
hardware que é oferecido a seus clientes. Portanto, comçou-se a estudar um novo
processador mais moderno que atendesse melhor as demandas deste sistema que
é aprimorado com frequência. O processador escolhido foi um ARM de dois núcleos
da empresa NXP: o LPC4350.
O trabalho principal desenvolvido durante o estágio foi o de estudar esse
processador e de encontrar uma forma de se desenvolver nesta plataforma. Além
disso, a plataforma de desenvolvimento deveria ser configurada em um computador
com um sistema operacional baseado em sistema Unix. No caso, utilizou-se um
computador com o sistema operacional Ubuntu (12.04), e testou-se o processador
em uma palca de desenvolvimento: LPC-4350-DB1, da empresa Diolan.
3
Abstract
Arvus Technology is the only brazilian company that manufactures equipment
for Precision Agriculture and Forestry. One of the main equipments developed by this
company is a on-board computer that goes embedded in agricultural machinery. This
computer is responsible for controling several actuators and collecting data about the
operations performed. It has an ARM processor that is the heart of all the system.
Since it is essential for an engineering enterprise to keep up with the new
technological trends, it is of their interest to update the hardware that they offer to
their customers. Therefore, the search for newer processor that could better meet the
needs of this system that is frequently improved has begun. And the chosen
processor was one of the ARM architecture with two cores, developed by NXP: the
LPC4350.
The main task developed during this internship was studying this new
processor and finding a way of developing in this platform. Besides that, the
developing environment should be configured on a computer running a Unix-based
operational system. In this case, a computer running Ubuntu (12.04) was used, and
the processor was tested on a development board: LPC-4350-DB1, by Diolan.
4
Sumário
Capítulo 1: Introdução...................................................................................................6
Capítulo 2: Entendendo o Problema.............................................................................8
2.1 O microcontrolador e a placa............................................................................8
2.2 O sistema........................................................................................................10
Capítulo 3: O ambiente de desenvolvimento..............................................................12
3.1 Eclipse CDT: Ambiente de programação........................................................12
3.2 GNU ARM Eclipse: Ferramenta de gerenciamento de projetos.....................12
3.3 Sourcery G++ Lite : Toolchain........................................................................13
3.4 Zylin Embedded CDT: ferramenta de depuração...........................................14
3.5 OpenOCD.......................................................................................................15
Capítulo 4: Configuração do ambiente........................................................................16
4.1 OpenOCD.......................................................................................................16
4.2 Criação de um projeto novo............................................................................17
4.3 Configurações de Depuração.........................................................................20
Capítulo 5: Executando o Código................................................................................22
Capítulo 6: Conclusões e Perspectivas......................................................................25
Anexo 1: Script Vinculador..........................................................................................27
Anexo 2: Arquivos de Inicialização..............................................................................31
5
Capítulo 1: Introdução
O computador de bordo desenvolvido pela empresa Arvus Tecnologia controla
um sistema multi-tarefa: controla várias válvulas e motores da máquina agrícola e
recebe dados de vários sensores diferentes. Portanto, ao se escolher um novo
microcontrolador para este sistema, optou-se por um que tivesse mais de um núcleo
de processamento para se lançar mão das vantagen que isso traz a um sistema
deste tipo.
O desafio a ser abordado é o de se estudar o processador e descobrir como
se utilizar suas várias funcionalidades do novo microcontrolador de forma que ao se
alterar o firmware para esta nova plataforma, ela possa ser executada de maneira
mais eficiente. Além disso, deve-se encontrar uma forma de se desenvolver nesta
nova plataforma: trocando-se o microcontrolador, é necessário um novo conjunto de
softwares (compiladores, vinculadores, etc) para se trabalhar. E todo o ambiente de
desenvolvimento deveria ser criado com softwares gratuitos que funcionem no
sistema operacional Ubuntu (utilizado na empresa).
O problema é de grande relevância para o Curso de Eng. de Controle a
Automação atualmente. A grande maioria dos sistemas de controle são executados
em sistemas computacionais. E o grande avanço tecnologico atual permite que um
único computador controle vários sistemas diferentes ao mesmo tempo, o que
muitas vezes força o sistema computacional a ser multi-tarefa.
Para aumentar a eficiência desses sistemas o mercado já desenvolveu várias
soluções, como os microcontroladores de mais de um núcleo de processamento.
Porém, desenvolver nestes novos sitemas nem sempre é trivial, nem barato. Para
permitir que as novas tecnologias sejam utilizadas, é importante que alguém
desenvolva o know-how sobre como utilizá-las. E as ferramentas devem ser,
preferencialmente, gratuitas.
O desafio abstrato de se encontrar e configurar uma plataforma de
desenvolvimento foi resumido e simplificado nos seguintes objetivos:
6
- Compilar e executar códigos de exemplos na placa de desenvolvimento
LPC-4350-DB1;
- O processo deve ser feito inteiramente com software gratuito.
A metodologia empregada no desenvolvimento do trabalho consiste em
pesquisa e estudo em bibliografia variada, principalmente pela internet. Além, é
claro, de testes frequentes e eventuais correção de erros durante o processo. Cada
software empregado no processo também foi testado sequencialmente, de forma a
tentar garantir que qualquer problema a ser encontrado não fosse consequência de
uma operação executada anteriormente (que o problema estivesse de alguma forma
no último software instaladoe não no anterior, por exemplo).
Dentre as alternativas para solução deste problema, muitas definidas pela
atual situação da empresa: o sistema operacional no qual o ambiente deveria ser
executado e o ambiente de programação (Ubuntu e Eclipse) forma escolhidos por
serem aqueles que já são utilizados na empresa, os funcionários que posteriormente
utilizarão o ambiente já estão acostumados a estes sistemas.
Outras soluções foram escolhidas por serem as que aparentam ter mais
material disponível na rede ou por serem já amplamente utilizadas por outras
pessoas. Esta foi a justificativa de se utilizar, por exemplo, a "toolchain"
CodeSourcery Sourcery G++ Lite.
Nos capítulos subsequentes, serão apresentados de maneira mais detalhada
o microprocessador, o sistema e os programas escolhidos para se configurar o
ambiente de desenvolvimento. Também serão apresentados como cada um deve ser
configurado, quais os procedimentos necessários apra se instalar cada componente,
etc. No final, pretende-se que este relatório funcione também como um guia para
qualquer desenvolvedor que esteja em situação semelhante que queira programar
no microcontrolador aqui apresentado ou em outros semelhantes.
7
Capítulo 2: Entendendo o Problema
Inicialmente, é necessário se estudar um pouco o microcontrolador com o
qual estamos lidando e, depois, ter em mente quais são os atuais recursos que
teremos que usar para programá-lo.
2.1 O microcontrolador e a placa
Os processadores da arquitetura ARM são muito conhecidos atualmente no
mercado por terem um alto desempenho para sistemas embarcados. Logo, o
processador escolhido para integrar o novo computador de bordo foi desta
arquitetura. Além disso, tendo em vista que temos um sistema multi-tarefa em mãos,
torna-se interessante se utilizar microcontroladores com mais de um núcleo de
processamento. Tais necessidades justificam a escolha do LPC4350 [1] como
substituto.
O processador LPC4350 é um microcontrolador de 32 bits para aplicações
embarcadas baseado em ARM Cortex-M4, que incui um coprocessador ARM
Cortex-M0. Tem internamente 264 kB de memória SRAM para o uso de dados e
código e 64 kB de memória ROM para inicialização e alguns "drivers" em software.
O núcleo Cortex-M4 tem uma arquitetura Harvard, com locais separados para
intruções e dados, bem como um terceiro barramento para periféricos. O núcleo
Cortex-M0 utiliza a arquitetura von-Neumann. A comunicação entre os dois
processadores é feita em uma área de memória SRAM compartilhada que atua
como caixa de correio e com um núcelo ativando interrupções do outro. Por
exemplo, quando um núcleo envia uma mensagem ao outro, ele ativa uma
interrupção deste, que por sua vez, deverá ativar uma interrupção daquele para
avisar que a mensagem foi devidamente recebida.
Para se testar este microcontrolador, utilizou-se a placa de desenvolvimento LPC-
4350-DB1. Esta placa, além do microcontroaldor, tem uma série de outros recursos,
dentre eles:
- Conector mini USB tipo B;
8
- Conector JTAG;
- 16 MB de memória FLASH externa;
- 5 Leds controlados pelo usuário;
- “Jumpers” seletores de inicialização.
Segue abaixo o mapa de memória da SRAM do microcontrolador, que é a área de
memória a ser utilizada posteriormente.
9
Figura 1: LPC-4350-DB1 B por Diolan
2.2 O sistema
Por ser a linguagem de programação já utilizada na empresa para o
desenvolvimento dos atuais produtos, as soluções aqui propostas são para C/C++.
A solução foi pensada para um máquina com um sistema operacional baseado em
Unix. Mais especificamente, um computador com Ubuntu 12.04, 64bits. O
computador precisa ter uma conexão com a internet para facilitar a instalação das
ferramentas demonstradas a seguir. Parte-se do presuposto que o usuário tem a
ferramenta Aptitude instalada no computador. Para instalá-la, basta executar as
seguintes linhas de código no terminal:10
Figura 2: Mapa de Memória LPC 4350
sudo apt-get -y install aptitude
sudo aptitude update
Parte-se também do presuposto de que o computador tem a ferrmenta Java
Runtime Environment. Por ser uma ferramenta recorrente, seu processo de
instalação não será explanado aqui.
Não existe muitos requisitos de hardware para a solução encontrada, logo as
especificações técnicas da máquina são serão descritas aqui.
Para o comunicação entre o computador e a placa, são utilizados os seguintes
conectores:
-Conector USB (Macho A / Macho B 5 pinos) para a alimentação da placa;
-Adaptador Olimex ARM-USB-TINY para as funções de gravação e “debug”;
11
Figura 3: Olimex ARM-USB Tiny
Capítulo 3: O ambiente de desenvolvimento
3.1 Eclipse CDT: Ambiente de programação
Talvez a parte mais importante de um ambiente de desenvolvimento seja o
ambiente de programação. É nesta ferramentas que o programador irá
conceber e desenvolver seu código, sua aplicação. É onde tudo começa.
Para o caso, decidiu-se escolher o ambiente Eclipse CDT. Optou-se por
ele pelo simples fato de já ser utilizado dentro da empresa. Além disso, a
ferramenta se integra facilmente com outras ferramentas. Assim, o
processo de se escrever o código, compilá-lo, gravá-lo do chip e depurá-lo
se torna muito mais simples, podendo todo ser feito por uma mesma
interface.
3.1.1. Processo de instalação
Executar o seguinte comando no terminal:
sudo aptitude install eclipse-cdt
3.2 GNU ARM Eclipse: Ferramenta de gerenciamento de projetos
Esta ferramenta não é completamente imprescindível para o
desenvolvimento, porém auxilia o desenvolvedor no gerenciamento de
projetos para processadores ARM. Seu nome é GNU ARM Eclipse, é um
plugin para o Eclipse. É um projeto “Open-Source”.
3.2.1. Processo de instalação
Abra a ferramenta Eclipse e, no menu superior, vá em Help>Install
New Software...
Em “Work With:”, escreva:
GNU ARM Eclipse - http://gnuarmeclipse.sourceforge.net/updates
Instale o pacote.
12
3.3 Sourcery G++ Lite : Toolchain
Depois de escrito qualquer código a ser gravado no processador, é
necessário que se tenha um compilador adequado para o compilá-lo.
Precisamos de um compilador que seja executado em Linux, mas que
gere um código para ser executado em um processador ARM.
Compiladores comuns não são capazes de fazer isso. Para tal,
precisamos de um “cross-compiler”, um “compilador cruzado”. O mesmo
ocorre para o depurador, o vinculador, e outras ferramentas.
Atualmente existem pacotes, conhecidos como “toolchain”, que agrupam
todas essas ferramentas. Para este caso, é necessário uma toolchain que
possa interpretar programas em C, executar em GNU e gerar um
programa para ser executado no ARM. Optou-se por usar a Sourcery G++
Lite. Uma “toolchain” desenvolvida pela empresa CodeSourcery (atual
Mentor). Ela inclui:
- Compiladores GNU C e C++;
- Assembler e vinculador GNU;
-Bibliotecas C e C++;
-Depurador GNU.
3.3.1. Processo de Instalação
Faça download do pacote no site:
http://sourcery.mentor.com/public/gnu_toolchain/arm-none-linux-
gnueabi-i686-pc-linux-gnu/arm-2012.09-64-arm-none-linux-gnueabi-
i686-pc-linux-gnu.tar.bz2
Crie um diretório em /opt (ex.: /opt/codesourcery);
Descompacte o pacote dentro do diretorio criado;
Esta “toolchain” precisa que o computador tenha bibliotecas 32bits
instaladas. No caso de máquinas 64bits, basta rodar o seguinte código
no terminal:
13
sudo apt-get install ia32-libs
Depois, é importante garantir que o sistema operacional identificará as
entradas para a “toolchain”. No terminal:
PATH=[Diretório de onde foi extraído o pacote]:$PATH
(Ex.: PATH=/opt/codesourcery/arm-2012.09/bin:$PATH )
export PATH
Agora, já deve ser possível compilar um arquivo .c e gerar um arquivos
.elf (que será utilizado para se gravar o seu programa no
microcontrolador).
3.4 Zylin Embedded CDT: ferramenta de depuração
Apesar de já termos um depurador (que foi instalado junto com a
“toolchain” anteriormente), há um plugin “Open-Source” para a ferramenta
Eclipse que facilita o trabalho de configuração do depurador para este e
outros projetos. Seu nome é Zylin Embedded CDT, da empresa Zylin.
3.4.1. Processo de Instalação
Abra a ferramenta Eclipse e, no menu superior, vá em Help>Install
New Software...
Em “Work With:”, escreva:
http://opensource.zylin.com/zylincdt
Instale o pacote.
14
3.5 OpenOCD
OpenOCD (“Open On-Chip Debugger”) é uma ferramenta de depuração
que permite se verificar o código enquanto ele é executado no
microcontrolador. Ela é um projeto Open-Source criada por Dominic Rath.
3.5.1. Processo de Instalação
No terminal, execute:
sudo aptitude install openocd
15
Capítulo 4: Configuração do ambiente
Agora que todos os programas e ferramentas estão devidamente instaladas
no computador, é necessário se realizar algumas configurações [2] para que todas
funcionem em conjunto.
4.1 OpenOCD
Mesmo que a ferramenta esteja instalada no computador, é necessário se
configurar o Ecilpse IDE para que ele a reconheça como uma ferramenta.
Em “Run>External Tool>External Tool Configurations...” selecione
“Program” na aba do lado esquerdo e clique em “New launch
configuration” acima.
Em “Location”, insira a localização do executável. Em “Working Directory”,
insira o diretório do local de trabalho sendo utilizado pelo Eclipse no
momento. Em argumentos, insira:
- Os arquivos de configuração de interface da ferramenta com o chip. No
caso, a interface é feita por JTAG.
- Os arquivos de configuração para o alvo de gravação e depuração. No
caso, LPC4350
- Comandos de configuração que se deseja que sejam executado quando
a ferramenta for executada.
Mais detalhes sobre estes argumentos e sobre como configurar a
ferramenta podem ser encontrados na sua documentação [3].
16
Nota: o arquivo de configuração de alvo (“target”) possivelmente não está
presente no computador até o presente momento. O arquivo utilizado
pode ser encontrado em:
https://github.com/shyul/openocd/blob/master/tcl/target/lpc4350.cfg
4.2 Criação de um projeto novo
Sempre que um projeto novo for criado, o “Plugin” GNU ARM ECLIPSE
mostra-se útil. Em “File>New>C++ Project”, pode-se escolher a opção de
um novo projeto para ARM, bem como já se definir qual será a “toolchain”
(neste caso “Sourcery G++ Lite”). Desta forma não será necessário se
definir manualmente qual “toolchain” deverá ser utilizada, e a geração de
um “Makefile” (arquivo necessário para que se vincule e compile o código)
será automática.
17
Figura 4: Exemplo de Configuração - OpenOCD
Em um projeto para ARM, existem dois arquivos muito importantes além
do programa em si (arquivos em .c) e de outras bibliotecas e cabeçalhos:
os arquivos de inicialização(.s, .S, .c ou .cpp) e o script vinculador (.ld). Em
seguida, dar-se-a uma atenção especial a eles, apesar de serem
específicos para cada projeto criado.
18
Figura 5: Tela de Criação de Novo Projeto
4.2.1. Script Vinculador (.ld)
O script vinculador [5] liga vários objetos e arquivos, realoca seus
dados e amarra as referências de símbolos. Outra forma de enxergá-lo
é como um arquivo que define as áreas de memória que serão usada
dos sistema microcontrolado, bem como em que partes da memória
cada sessão do programa ficará (“main”, pilha, vetor de interrupções, e
entre outros).
Estes arquivos normalmente são escritos de acordo com a linguagem
“Linker Command Language”. Segue no Anexo 1 um exemplo de script
vinculador, o que foi usado para se executar o exemplo neste caso. O
que ele éxecuta é, basicamente:
-Define o ponto de entrada no código como sendo o procedimento de
“reset”;
-Define as áreas de memória que serão utilizadas;
-Mapeia todo o código e os dados na memória RAM.
Mais a respeito da sintaxe utilizada e da estrutura do arquivo pode ser
encontrado na documentação.
4.2.2. Arquivos de Inicialização
Esse arquivos são utilizados para se definir a sequência de
inicialização do ARM, bem como alguns símbolos, vetor de
interrupções, e entre outros.
Comumente, eles são escritos em assembly [6] (.s ou .S), mas
eventualmente podem ser escritos em linguagem C ou C++ (.c ou
.cpp). O Anexo 2 é um arquivo de inicialização escrito em assembly.
Dentre suas definições mais notáveis estão:
-O tamanho da pilha;
-O vetor de interrupções;
-O procedimento de reinicialização.
19
4.3 Configurações de Depuração
Em seguida, é necessário se configurar quais serão os procedimentos a
serem executados pelo depurador. Esta configuração é específica para
cada projeto criado. Ou seja, precisa ser feita novamente para cada novo
projeto. No caso, outilizou-se os exemplos de software providenciados
pelos próprios fabricantes da placa de desenvolvimento, que pode ser
encontrados em:
http://www.lpc4350.com/software-examples
Para o teste do ambiente, o exemplo utilizado se chama “Buttons Leds
Simple”. Por ser muito específico do exemplo em questão, as
configurações do projeto (como, por exemplo, referenciamento de
bibliotecas necessárias) não serão abordadas aqui.
Pode-se criar uma configuração de depuração em “Run>Debug
Configurations...”. Seleciona-se “Zylin Embedded Debug (Native)” e clica-
se em “New launch configuration”.
Em “C/C++ Application”, na primeira aba, deve constar o diretório do
arquivo .elf gerado pela compilação. Na aba “Debugger”, em “GDB-
debugger”, deve-se inserir o executável do depurador. No caso: “arm-
none-eabi-gdb”. Em seguida, na aba “Commands”, deve-se inserir os
comandos que se deseja que sejam executaos para que a depuração seja
feita. Mais detalhes sobre estes comandos e o que cada um representa
podem ser encontrados da documentação relacionada [4].
20
Para o caso aqui tratado, optou-se pela seguinte sequência de comandos:
target remote localhost:3333
monitor reset
monitor soft_reset_halt
load
monitor halt
continue
Que basicamente fazem o seguinte:
Inicia a sessão de depuração;
Reinicia o sistema por hardware;
Reinicia o sistema por software;
Carrega o programa na memória do microcontrolador;
Faz uma parada logo após;
Continua e executa o programa gravado.
21
Capítulo 5: Executando o Código
Após todo o ambiente estar devidamente configurado e o código que se
deseja executar no microcontrolador escrito, resta apenas gravá-lo e validá-lo.
Optou-se por um código simples de exemplo da placa de desenvolvimento, que
pode ser encontrado no site do fabricante. O Anexo 3 é o procedimento principal
(“main”) do código. Ele deve apenas verificar se os botões S1 a S4 estão
pressionados e, para cada um respectivamente, acender os LEDs D3 a D6 caso
estejam.
Para executar o código e depurá-lo:
-Compilá-lo (“Build”, no Eclipse);
-Executar a configuração criada da ferramenta OpenOCD;
-Executar a configuração criada do depurador;
Segue abaixo uma imagem de uma sessão de depuração, com o
proceidmento principal aberto e o código em assembly de cada intrução ao lado,
para que o usuário possa, se quiser, ir depurando o código passo-a-passo.
22
23
Figura 6: Exemplo de Sessão de Depuração
Figura 7: LPC-4350-DB1 executando código recém gravado
Apesar deste ser um exemplo muito simples, as outras funcionalidades
devem poder ser utilizadas facilmente (agora que todo o ambiente está configurado).
Muitas das outras funcionalidades (como, por exemplo, integração do LPC4350 com
displays LCD ou a comunicação entre os núcleos) já estão disponíveis em
bibliotecas, criadas as vezes pelo próprio fabricante.
Há um pacote de bibliotecas chamado CMSIS (“Cortex Microcontroller
Software Interface Standard”, algo como: Padrão de Intrface de Software de
Microcontroladores Cortex), disponível gratuitamente no site www.arm.com (ou em
sites de outrso forncedores). Este pacote oferece uma interface para o programador,
como uma camada a mais entre ele e o processador, de forma a simplificar e facilitar
o trabalho.
Portanto, para que outras aplicações possam ser criadas utilizando-se este
ambiente de desenvolvimento aqui apesentado, basta que o programador:
-Identifique as bibliotecas necessárias para o novo projeto (ou, em casos mais
extremos, crie a sua própria);
-Redefina os arquivos de inicialização e o script vinculador;
-Redefina os comandos a serem executados pelo depurador (se necessário);
-Redefina as configurações para estabelecer a conexão entre o computador e
o processador (se necessário).
24
Capítulo 6: Conclusões e Perspectivas
Para se desenvover aplicações e projetos em sistemas embarcado, é
necessário ter-se um ambiente de desenvolvimento. E, principalmente quando se
trata de lidar com novas tecnologias, criar este ambiente se mostra uma tarefa
complicada. Para isto, é necessário se compreender bem o hardware que irá
executar a aplicação, bem como os meios de comunicá-lo com o a plataforma na
qual o software será desenvolvido (na maioria dos casos, um computador comum).
No fim das contas, o criador do ambiente de desenvolvimento tem de
compreender bem estes aspectos para que o desenvolvedor do aplicativo não
precise se preocupar tanto. Trata-se de criar uma espécie de interface entre o
usuário (programador) e hardware (microcontrolador).
O desafio de criar este ambiente aumenta quando se inclui a necessidade de
que ele seja gratuito. Assim que o hardware é lançado no mercado, lança-se
também uma forma de se utilizá-lo. Porém, estes métodos costumam ser pagos, o
que dificulta sua utilização por parte de empresas mas, principalmente, de
programadores amadores.
O trabalho desenvolvido aqui deverá ser útil não apenas para a empresa
Arvus Tecnologia, que deverá aproveitar estes resultados para o desenvolvimento de
produtos futuros, mas também para desenvolvedores amadores que queiram
trabalhar com novas tecnologias. Contribui, portanto, para o aparecimento de mais e
melhores tecnologias no mercado brasileiro.
25
Bibliografia:
[1] NXP Semiconductors, “LPC4350/30/20/10 – Product Datasheet”, Rev. 4,
Março de 2013, Disponível em:
<http://www.nxp.com/documents/data_sheet/LPC4350_30_20_10.pdf>.
[2] J. P. Lynch, “ARM Cross Development with Eclipse”, Disponível em:
<https://www.sparkfun.com/tutorial/ARM/ARM_Cross_Development_with_Eclipse.pdf
>.
[3] The Open OCD Project, S. Oliver, O. Harboe, D. Ellis e D. Brownell,
“OpenOCD User's Guide”, 16 de Junho de 2013, Disponível em:
<http://openocd.sourceforge.net/doc/html/index.html>.
[4] Free Software Foundation, “Debugging with gdb: the gnu Source-Level
Debugger”, 2013, Disponível em:
<http://sourceware.org/gdb/current/onlinedocs/gdb/>.
[5] S. Chamberlain e I. L. Taylor, ”Using LD, the GNU linker”, Versão 2.14,
2003, Disponível em: <http://www.gnuarm.com/pdf/ld.pdf>.
[6] Free Software Foundation, Z. Juric, S. Reichelt e K. Kofler, “The GNU
Assembler”, 2003, Disponível em: <http://tigcc.ticalc.org/doc/gnuasm.html>.
26
Anexo 1 – Script Vinculador
/* Linker script for Cortex-M3 * * Version:CodeSourcery Sourcery G++ Lite 2007q3-53 * BugURL:https://support.codesourcery.com/GNUToolchain/ * * Copyright 2007 CodeSourcery. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose,provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. */
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")ENTRY(__cs3_reset_cortex_m)SEARCH_DIR(.)GROUP(-lgcc -lc -lcs3 -lcs3unhosted -lcs3micro)
MEMORY{ rom (rx) : ORIGIN = 0x1C000000, LENGTH = 0x400000 ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x20000 ram1(rwx) : ORIGIN = 0x10080000, LENGTH = 0x10000}
/* These force the linker to search for particular symbols from * the start of the link process and thus ensure the user's * overrides are picked up */EXTERN(__cs3_reset_cortex_m)EXTERN(__cs3_interrupt_vector_cortex_m)EXTERN(__cs3_start_c main __cs3_stack __cs3_stack_size __cs3_heap_end)
PROVIDE(__cs3_stack = __cs3_region_start_ram + __cs3_region_size_ram);PROVIDE(__cs3_stack_size = __cs3_region_start_ram + __cs3_region_size_ram - _end);PROVIDE(__cs3_heap_start = _end);PROVIDE(__cs3_heap_end = __cs3_region_start_ram + __cs3_region_size_ram);
SECTIONS{ .text : { CREATE_OBJECT_SYMBOLS __cs3_region_start_ram = .; *(.cs3.region-head.ram)/* __cs3_region_start_rom = .;*//* *(.cs3.region-head.rom)*/ __cs3_interrupt_vector = __cs3_interrupt_vector_cortex_m; *(.cs3.interrupt_vector)
27
/* Make sure we pulled in an interrupt vector. */ ASSERT (. != __cs3_interrupt_vector_cortex_m, "No interrupt vector");/* *(.rom) *(.rom.b)*/ *(.ram)
__cs3_reset = __cs3_reset_cortex_m; *(.cs3.reset) /* Make sure we pulled in some reset code. */ ASSERT (. != __cs3_reset, "No reset code");
*(.text .text.* .gnu.linkonce.t.*) *(.plt) *(.gnu.warning) *(.glue_7t) *(.glue_7) *(.vfp11_veneer)
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*) *(.gcc_except_table) *(.eh_frame_hdr) *(.eh_frame)
. = ALIGN(4); KEEP(*(.init))
. = ALIGN(4); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .;
. = ALIGN(4); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .;
. = ALIGN(0x4); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*crtend.o(.ctors))
. = ALIGN(4); KEEP(*(.fini))
. = ALIGN(4); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) __fini_array_end = .;
KEEP (*crtbegin.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*crtend.o(.dtors))
. = ALIGN(4); __cs3_regions = .;
28
LONG (0) LONG (__cs3_region_init_ram) LONG (__cs3_region_start_ram) LONG (__cs3_region_init_size_ram) LONG (__cs3_region_zero_size_ram) }>ram
/* .ARM.exidx is sorted, so has to go in its own output section. */ __exidx_start = .; .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >ram __exidx_end = .; .text.align : { . = ALIGN(8); _etext = .; } >ram/* __cs3_region_size_rom = LENGTH(rom); __cs3_region_num = 1;*/
.data : {/* __cs3_region_start_ram = .; *(.cs3.region-head.ram)*/ _sdata = .; KEEP(*(.jcr)) *(.got.plt) *(.got) *(.shdata) *(.data .data.* .gnu.linkonce.d.*) *(.ram.d) . = ALIGN (8); _edata = .; } >ram /*AT>rom*/ .bss (NOLOAD): { . = ALIGN (4); __bss_start__ = .; *(.shbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)
__bss_end__ = .; *(.ram.b) . = ALIGN (4); _end = .; __end = .; } >ram1 .heap (NOLOAD): { *(.heap) } >ram .stack (__cs3_stack - __cs3_stack_size) (NOLOAD): { *(.stack) _estack = .; PROVIDE(estack = .); } >ram __cs3_region_init_ram = LOADADDR (.data);
29
/* __cs3_region_init_ram = LOADADDR (.text);*//* __cs3_region_init_size_ram = _edata - __cs3_region_start_ram;*/ __cs3_region_init_size_ram = _edata - _sdata; __cs3_region_zero_size_ram = _end - _edata; __cs3_region_size_ram = LENGTH(ram); __cs3_region_num = 1;
.stab 0 (NOLOAD) : { *(.stab) } .stabstr 0 (NOLOAD) : { *(.stabstr) } /* DWARF debug sections. * Symbols in the DWARF debugging sections are relative to the beginning * of the section so we begin them at 0. */ /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } /* DWARF 2 */ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } /* SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) }
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) } /DISCARD/ : { *(.note.GNU-stack) }}
30
Anexo 2 – Arquivo de Inicialização
Disponível em:
<http://www.lpc4350.com/lpc43xx/Core/Device/NXP/LPC43xx/Source/Templates/GC
C/startup_LPC18xx.s?peg=41>.
/*************************************************************************//* startup_LPC18xx.s: Startup file for LPC18xx device series *//*************************************************************************//* Version: CodeSourcery Sourcery G++ Lite (with CS3) *//*************************************************************************/
/*// <h> Stack Configuration// <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>// </h>*/
.equ Stack_Size, 0x00000100 .equ Sign_Value, 0x5A5A5A5A .section ".stack", "w" .align 3 .globl __cs3_stack_mem .globl __cs3_stack_size__cs3_stack_mem: .if Stack_Size .space Stack_Size .endif .size __cs3_stack_mem, . - __cs3_stack_mem .set __cs3_stack_size, . - __cs3_stack_mem
/*// <h> Heap Configuration// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>// </h>*/
.equ Heap_Size, 0x00001000
.section ".heap", "w" .align 3 .globl __cs3_heap_start .globl __cs3_heap_end__cs3_heap_start: .if Heap_Size .space Heap_Size .endif__cs3_heap_end:
/* Vector Table */
.section ".cs3.interrupt_vector" .global __cs3_interrupt_vector_cortex_m .type __cs3_interrupt_vector_cortex_m, %object
31
__cs3_interrupt_vector_cortex_m: .long __cs3_stack /* Top of Stack */ .long __cs3_reset /* Reset Handler */ .long NMI_Handler /* NMI Handler */ .long HardFault_Handler /* Hard Fault Handler */ .long MemManage_Handler /* MPU Fault Handler */ .long BusFault_Handler /* Bus Fault Handler */ .long UsageFault_Handler /* Usage Fault Handler */ .long Sign_Value /* Reserved */ .long 0 /* Reserved */ .long 0 /* Reserved */ .long 0 /* Reserved */ .long SVC_Handler /* SVCall Handler */ .long DebugMon_Handler /* Debug Monitor Handler */ .long 0 /* Reserved */ .long PendSV_Handler /* PendSV Handler */ .long SysTick_Handler /* SysTick Handler */
/* External Interrupts */ .long DAC_IRQHandler /* 16 D/A Converter */
.long 0 /* 17 Event Router */
.long DMA_IRQHandler /* 18 General Purpose DMA */
.long 0 /* 19 Reserved */
.long 0 /* 20 Reserved */
.long ETH_IRQHandler /* 21 Ethernet */
.long SDIO_IRQHandler /* 22 SD/MMC */
.long LCD_IRQHandler /* 23 LCD */
.long USB0_IRQHandler /* 24 USB0*/
.long USB1_IRQHandler /* 25 USB1*/
.long SCT_IRQHandler /* 26 State Configurable Timer*/
.long RIT_IRQHandler /* 27 Repetitive Interrupt Timer*/
.long TIMER0_IRQHandler /* 28 Timer0*/
.long TIMER1_IRQHandler /* 29 Timer1*/
.long TIMER2_IRQHandler /* 30 Timer2*/
.long TIMER3_IRQHandler /* 31 Timer3*/
.long MCPWM_IRQHandler /* 32 Motor Control PWM*/
.long ADC0_IRQHandler /* 33 A/D Converter 0*/
.long I2C0_IRQHandler /* 34 I2C0*/
.long I2C1_IRQHandler /* 35 I2C1*/
.long 0 /* 36 Reserved*/
.long ADC1_IRQHandler /* 37 A/D Converter 1*/
.long SSP0_IRQHandler /* 38 SSP0*/
.long SSP1_IRQHandler /* 39 SSP1*/
.long UART0_IRQHandler /* 40 UART0*/
.long UART1_IRQHandler /* 41 UART1*/
.long UART2_IRQHandler /* 42 UART2*/
.long UART3_IRQHandler /* 43 UART3*/
.long I2S0_IRQHandler /* 44 I2S*/
.long I2S1_IRQHandler /* 45 AES Engine*/
.long SPIFI_IRQHandler /* 46 SPI Flash Interface*/
.long SGPIO_IRQHandler /* 47 SGPIO*/
.long GPIO0_IRQHandler /* 48 GPIO0*/
.long GPIO1_IRQHandler /* 49 GPIO1*/
.long GPIO2_IRQHandler /* 50 GPIO2*/
.long GPIO3_IRQHandler /* 51 GPIO3*/
.long GPIO4_IRQHandler /* 52 GPIO4*/
.long GPIO5_IRQHandler /* 53 GPIO5*/
.long GPIO6_IRQHandler /* 54 GPIO6*/
32
.long GPIO7_IRQHandler /* 55 GPIO7*/
.long GINT0_IRQHandler /* 56 GINT0*/
.long GINT1_IRQHandler /* 57 GINT1*/
.long EVRT_IRQHandler /* 58 Event Router*/
.long CAN1_IRQHandler /* 59 C_CAN1*/
.long 0 /* 60 Reserved*/
.long VADC_IRQHandler /* 61 VADC*/
.long ATIMER_IRQHandler /* 62 ATIMER*/
.long RTC_IRQHandler /* 63 RTC*/
.long 0 /* 64 Reserved*/
.long WDT_IRQHandler /* 65 WDT*/
.long 0 /* 66 M0s*/
.long CAN0_IRQHandler /* 67 C_CAN0*/
.long QEI_IRQHandler /* 68 QEI*/
.size __cs3_interrupt_vector_cortex_m, . - __cs3_interrupt_vector_cortex_m
.thumb
/* Reset Handler */
.section .cs3.reset,"x",%progbits .thumb_func .globl __cs3_reset_cortex_m .type __cs3_reset_cortex_m, %function__cs3_reset_cortex_m: .fnstart.if (RAM_MODE)/* Clear .bss section (Zero init) */
MOV R0, #0LDR R1, =__bss_start__LDR R2, =__bss_end__CMP R1,R2BEQ BSSIsEmpty
LoopZI:CMP R1, R2BHS BSSIsEmptySTR R0, [R1]ADD R1, #4BLO LoopZI
BSSIsEmpty: LDR R0,=main BX R0.else
LDR R0,=_start BX R0.endif .pool .cantunwind .fnend .size __cs3_reset_cortex_m,.-__cs3_reset_cortex_m
.section ".text"
/* Exception Handlers */
33
.weak NMI_Handler .type NMI_Handler, %functionNMI_Handler: B . .size NMI_Handler, . - NMI_Handler
.weak HardFault_Handler .type HardFault_Handler, %functionHardFault_Handler: B . .size HardFault_Handler, . - HardFault_Handler
.weak MemManage_Handler .type MemManage_Handler, %functionMemManage_Handler: B . .size MemManage_Handler, . - MemManage_Handler
.weak BusFault_Handler .type BusFault_Handler, %functionBusFault_Handler: B . .size BusFault_Handler, . - BusFault_Handler
.weak UsageFault_Handler .type UsageFault_Handler, %functionUsageFault_Handler: B . .size UsageFault_Handler, . - UsageFault_Handler
.weak SVC_Handler .type SVC_Handler, %functionSVC_Handler: B . .size SVC_Handler, . - SVC_Handler
.weak DebugMon_Handler .type DebugMon_Handler, %functionDebugMon_Handler: B . .size DebugMon_Handler, . - DebugMon_Handler
.weak PendSV_Handler .type PendSV_Handler, %functionPendSV_Handler: B . .size PendSV_Handler, . - PendSV_Handler
.weak SysTick_Handler .type SysTick_Handler, %functionSysTick_Handler: B . .size SysTick_Handler, . - SysTick_Handler
/* IRQ Handlers */
.globl Default_Handler .type Default_Handler, %function
34
Default_Handler: B . .size Default_Handler, . - Default_Handler
.macro IRQ handler .weak \handler .set \handler, Default_Handler .endm
IRQ DAC_IRQHandlerIRQ DMA_IRQHandlerIRQ ETH_IRQHandlerIRQ SDIO_IRQHandlerIRQ LCD_IRQHandlerIRQ USB0_IRQHandlerIRQ USB1_IRQHandlerIRQ SCT_IRQHandlerIRQ RIT_IRQHandlerIRQ TIMER0_IRQHandlerIRQ TIMER1_IRQHandlerIRQ TIMER2_IRQHandlerIRQ TIMER3_IRQHandlerIRQ MCPWM_IRQHandlerIRQ ADC0_IRQHandlerIRQ I2C0_IRQHandlerIRQ I2C1_IRQHandlerIRQ ADC1_IRQHandlerIRQ SSP0_IRQHandlerIRQ SSP1_IRQHandlerIRQ UART0_IRQHandlerIRQ UART1_IRQHandlerIRQ UART2_IRQHandlerIRQ UART3_IRQHandlerIRQ I2S0_IRQHandlerIRQ I2S1_IRQHandlerIRQ SPIFI_IRQHandlerIRQ SGPIO_IRQHandlerIRQ GPIO0_IRQHandlerIRQ GPIO1_IRQHandlerIRQ GPIO2_IRQHandlerIRQ GPIO3_IRQHandlerIRQ GPIO4_IRQHandlerIRQ GPIO5_IRQHandlerIRQ GPIO6_IRQHandlerIRQ GPIO7_IRQHandlerIRQ GINT0_IRQHandlerIRQ GINT1_IRQHandlerIRQ EVRT_IRQHandlerIRQ CAN1_IRQHandlerIRQ VADC_IRQHandlerIRQ ATIMER_IRQHandlerIRQ RTC_IRQHandlerIRQ WDT_IRQHandlerIRQ CAN0_IRQHandlerIRQ QEI_IRQHandler
.end
35