Instruction manuals"> Fazer download", o google docs não abre o arquivo direito). Dentro do arquivo PDF estão anexados alguns arquivos de configuração citados ao longo do guia e os projetos de teste que foram criados.">
Nothing Special   »   [go: up one dir, main page]

Tutorial ARM

Fazer download em pdf ou txt
Fazer download em pdf ou txt
Você está na página 1de 92

UNIVERSIDADE TECNOLGICA FEDERAL DO PARAN

CPGEI

NIKOLAS LIBERT

CONFIGURANDO O ECLIPSE PARA DESENVOLVIMENTO EM


SISTEMAS EMBARCADOS: ARM LM3S8962, FREERTOS E LWIP

GUIA PRTICO, 1 VERSO

CURITIBA
2012

Dedico este guia a Don Ramn pelos bons


servios prestados vizinhana.

LISTA DE FIGURAS

Figura 1 Instalao do Sourcery CodeBench. Janela de incluso do software nas


variveis de ambiente do Windows. ............................................................................. 9
Figura 2 Seleo do Workspace onde se encontram os projetos. ............................. 10
Figura 3 Janela principal do Eclipse. ...................................................................... 11
Figura 4 Janela de instalao do plug-in GNU ARM. ............................................ 12
Figura 5 Instalao do plug-in GNU ARM, Security Warning. .............................. 12
Figura 6 Janela de instalao do plug-in GDB Hardware Debugging. ..................... 13
Figura 7 Criando um projeto no Eclipse. ................................................................ 14
Figura 8 Janela de novo projeto. ............................................................................ 15
Figura 9 Tela inicial do eclipse. .............................................................................. 16
Figura 10 Janela de propriedades do Eclipse. ......................................................... 16
Figura 11 Tela principal de opes do plug-in GNU ARM. .................................... 17
Figura 12 Configurao do GNU ARM. Definio do caminho dos arquivos de
cabealho utilizados. .................................................................................................. 18
Figura 13 Configurao do GNU ARM. Opes do linker. ..................................... 19
Figura 14 Configurao do GNU ARM. Definio das bibliotecas utilizadas. ......... 21
Figura 15 Configurao do GNU ARM. Definio do tipo de imagem gerada. ....... 22
Figura 16 Arquivos de cabealho do Eclipse. .......................................................... 22
Figura 17 Importando o arquivo de inicializao. ................................................... 24
Figura 18 Janela de seleo de tipo de arquivo a importar. .................................... 24
Figura 19 Janela de seleo do arquivo a importar. ................................................ 25
Figura 20 Criando um novo arquivo. ...................................................................... 26
Figura 21 Janela External Tools Configurations. Configurao para escrever na
flash. .......................................................................................................................... 28
Figura 22 Janela para adio do OpenOCD ao menu dos favoritos. ....................... 30
Figura 23 Tela com opo criada para gravar o microcontrolador.......................... 30
Figura 24 Erro tpico ao gravar memria flash. ...................................................... 31
Figura 25 Janela External Tools Configurations. Configurao para depurar......... 32

Figura 26 Janela de configurao do depurador. .................................................... 33


Figura 27 Janela de configurao do depurador com a aba Debugger selecionada. . 33
Figura 28 Janela de configurao do depurador com a aba Startup selecionada. .... 34
Figura 29 Janela com ferramentas externas abertas. .............................................. 35
Figura 30 Encerrando ferramenta externa. ............................................................. 36
Figura 31 Iniciando o Servidor GDB. .................................................................. 36
Figura 32 Console do OpenOCD configurado como servidor para o depurador. ..... 37
Figura 33 Iniciando o depurador............................................................................. 37
Figura 34 Caixa de dilogo de troca de perspectiva. .............................................. 37
Figura 35 Menu de perspectivas. ............................................................................ 38
Figura 36 Inserindo breakpoint. .............................................................................. 38
Figura 37 Abrindo o terminal do GDB Debugger. .................................................. 39
Figura 38 Boto resume no menu de depurao. ................................................ 39
Figura 39 Criando pasta virtual no Eclipse. ........................................................... 42
Figura 40 Opes da pasta virtual. ......................................................................... 43
Figura 41 Criando atalho para cdigo fonte no Eclipse. ......................................... 44
Figura 42 Configurando atalho para cdigo fonte. .................................................. 44
Figura 43 Adio de diretivas de pr-processador................................................... 48
Figura 44 Project Explorer aps incluso de arquivos. ........................................ 49
Figura 45 Criando atalho para pasta com arquivos do LwIP. ................................ 57

SUMRIO

1 INTRODUO ....................................................................................................6
2 CONFIGURAO DO ECLIPSE ........................................................................8
2.1 INSTALANDO O COMPILADOR ...................................................................8
2.2 INSTALANDO AS BIBLIOTECAS DO MICROCONTROLADOR ................9
2.3 INSTALANDO O ECLIPSE .............................................................................10
2.4 INSTALANDO O PLUG-IN GNU ARM ..........................................................10
2.5 INSTALANDO O PLUG-IN DO DEPURADOR..............................................13
2.6 PROGRAMA PARA PISCAR LED .................................................................14
2.6.1 Criando um projeto .........................................................................................15
2.6.2 Configurando o plug-in GNU ARM .................................................................17
2.6.3 Importando o arquivo de inicializao .............................................................23
2.6.4 Escrevendo o programa ...................................................................................25
2.6.5 Configurando o OpenOCD ..............................................................................27
2.6.6 Configurando o depurador...............................................................................31
2.7 PROGRAMA PARA ACESSAR A INTERFACE SERIAL .............................39
2.7.1 Criando o projeto ............................................................................................40
2.7.2 Escrevendo o programa ...................................................................................40
2.7.3 Criando pasta virtual e adicionando atalho para arquivo................................42
3 INSTALAO DO RTOS ....................................................................................45
3.1 ADICIONANDO O FREERTOS A UM PROJETO .....................................45
3.2 ESCREVENDO PROGRAMA DE TESTE COM O FREERTOS ................50
4 INSTALAO DA PILHA TCP/IP ....................................................................55
4.1 INSTALANDO E CRIANDO UM PROJETO DE EXEMPLO ........................55
REFERNCIAS ......................................................................................................69
APNDICE A - Listagem de cdigo do arquivo main.c criado no exemplo do
FreeRTOS .........................................................................................................70

APNDICE B - Listagem de cdigo do arquivo sys_arch.c utilizado na


configurao do LwIP .............................................................................................74
APNDICE C - Listagem de cdigo do arquivo sys_arch.h utilizado na
configurao do LwIP .............................................................................................83
APNDICE D - Listagem de cdigo do arquivo cc.h utilizado na configurao do
LwIP ......................................................................................................................86
APNDICE E - Listagem de cdigo do arquivo main.h utilizado no exemplo do
LwIP ......................................................................................................................89

1 INTRODUO

Eclipse uma plataforma de desenvolvimento livre, baseada em JAVA, com


flexibilidade para ser utilizada com diversas linguagens de programao. justamente
esta flexibilidade que pode tornar sua configurao demorada e complicada. Aps
perder um bom tempo aprendendo a configurar a interface Eclipse para programao
de um microcontrolador ARM, em linguagem C, e sabendo que logo os passos
seguidos sero esquecidos, foi escrito este guia.
Grande parte das informaes que sero apresentadas foram obtidas de
colegas (obrigado Ofuchi!), ou de sites como ODeV Idea e Out-of-Plane Labs.
Este guia voltado para o kit de desenvolvimento EK-LM3S8962 da Texas
Instruments, que dispe de um microcontrolador Stellaris ARM Cortex-M3
modelo LM3S8962.
Foi utilizada a verso Indigo CDT do Eclipse, configurada com o compilador
Sourcery CodeBench Lite EABI 2011.09-69 da Mentor Graphics e com o plug-in
GNU ARM, que automatiza a gerao dos make files. Para gravao dos arquivos
binrios no microcontrolador foi utilizado o OpenOCD verso 0.5.0. O OpenOCD
tambm foi configurado para se comunicar com o GDB Debugger, depurador interno
da interface Eclipse.
Este guia dividido em trs sees principais. Na seo Configurao do
Eclipse est descrito o processo de instalao e configurao do Eclipse. Nessa seo
tambm descrita a configurao do depurador do Eclipse e a escrita de um pequeno
programa de teste.

Na seo Instalao do RTOS apresentada a instalao de um sistema


operacional em tempo real utilizando o ambiente de desenvolvimento que foi descrito
na seo Configurao do Eclipse. O sistema operacional utilizado o FreeRTOS
verso 7.1.1.
Por fim, na seo Instalao da Pilha TCP/IP, apresentada a
configurao de uma pilha TCP/IP com o FreeRTOS. Foi utilizada a pilha lwIP
verso 1.4.0.
Ao longo do texto sero criados quatro projetos utilizando o Eclipse. Um
arquivo do workspace do Eclipse, com todos os projetos, est includo em anexo neste
arquivo PDF.

2 CONFIGURAO DO ECLIPSE

A seguir ser descrita a configurao da interface de desenvolvimento Eclipse.


Para isso sero necessrios os seguintes programas:

Eclipse IDE for C/C++ developers: Interface de desenvolvimento que

pode ser obtida no site do eclipse. Foi utilizada a verso Indigo.

Mentor Graphics Sourcery CodeBench Lite EABI: compilador

C/C++ para ARM, que inclui um maker e um linker, assim como as bibliotecas
padres de C/C++. Foi utilizada a verso 2011.09-69 lite, que pode ser obtida
gratuitamente do site da mentor.

StellarisWare EK-LM3S8962 Firmware Development Package: Conjunto

de bibliotecas com funes para acesso aos perifricos do kit de desenvolvimento EKLM3S8962. Pode ser obtido no site da texas instruments.

OpenOCD 0.5.0: Programa que chamado pelo Eclipse e capaz de se

comunicar com a interface JTag do microcontrolador para programao e depurao


do mesmo. Pode ser obtido neste site.

2.1 INSTALANDO O COMPILADOR

Inicialmente o compilador Sourcery CodeBench Lite EABI deve ser instalado.


A verso lite gratuita, no entanto no possui interface grfica, o que no chega a ser
um problema, j que o Eclipse ser utilizado como interface grfica.
Para que o compilador seja encontrado pelo Eclipse, o diretrio de instalao
do mesmo deve ser adicionado s variveis de ambiente do Windows. Isso pode ser

feito automaticamente durante o processo de instalao na janela representada pela


Figura 1.

Figura 1 Instalao do Sourcery CodeBench. Janela de incluso do software nas variveis de


ambiente do Windows.

2.2 INSTALANDO AS BIBLIOTECAS DO MICROCONTROLADOR

Aps a instalao do Sourcery CodeBench, as bibliotecas do pacote


StellarisWare podem ser instaladas. Essas bibliotecas so especficas para facilitar o
acesso aos perifricos do microcontrolador que est sendo utilizado (LM3S8962).
recomendvel que antes da instalao seja criado um diretrio na raiz do disco rgido,
sem espaos no nome, e as bibliotecas sejam instaladas em um novo subdiretrio
dentro deste diretrio. Eu criei um diretrio chamado Dev e instalei as bibliotecas
no diretrio Dev\StellarisWare. Os projetos sero salvos no diretrio Dev e isso
facilita o uso de caminhos relativos na incluso de arquivos.

10

2.3 INSTALANDO O ECLIPSE

Aps a instalao do Sourcery CodeBench

e das bibliotecas do

microcontrolador, ser feita a instalao do Eclipse. O mesmo no possui instalador.


Para instal-lo basta que o arquivo copiado do site seja descomprimido para alguma
pasta desejada. Foi criada uma pasta em Arquivos de Programas\Eclipse e
adicionado um atalho no menu iniciar.
Ao iniciar o Eclipse, a janela da Figura 2 dever aparecer, onde dever ser
escolhido um diretrio para salvar os projetos. Neste caso, foi criado o diretrio
Eclipse no mesmo local aonde se encontra o diretrio com as bibliotecas do pacote
StellarisWare.

Figura 2 Seleo do Workspace onde se encontram os projetos.

2.4 INSTALANDO O PLUG-IN GNU ARM

O plug-in GNU ARM permite a criao de projetos em C/C++ sem a


necessidade da gerao de make files manualmente. Ele pode ser instalado

11

diretamente de dentro do Eclipse. Para isso deve-se clicar em Help e em Install


New Software..., como mostrado na Figura 3.

Figura 3 Janela principal do Eclipse.

Ento a janela da Figura 4 se abrir. No campo Work with dever ser


inserido o endereo do repositrio que possui o plug-in GNU ARM. Nesse caso, o
endereo http://gnuarmeclipse.sourceforge.net/updates. Aps inserir o endereo e
pressionar Enter, o item CDT GNU Cross Development Tools dever aparecer na
lista. Ento o subitem GNU ARM C/C++ Development Support deve ser
selecionado. Prossiga at finalizar a instalao e aceite o aviso de segurana da Figura
5. Reinicie o Eclipse.

12

Figura 4 Janela de instalao do plug-in GNU ARM.

Figura 5 Instalao do plug-in GNU ARM, Security Warning.

Aps a instalao do plug-in, o Eclipse estar pronto para a compilao de


programas para o microcontrolador ARM. Antes de escrevermos um programa de
teste, iremos instalar mais um plug-in que ser utilizado para depurao em
hardware.

13

2.5 INSTALANDO O PLUG-IN DO DEPURADOR

A verso do Eclipse para C/C++ possui uma interface grfica que


integrada com o GDB Debugger e ser utilizada para depurao dos programas. No
entanto, necessria a instalao de um plug-in especfico para depurao em
hardware. Para a instalao, deve-se ir em Help e em Install New Software...,
como mostrado na Figura 3.

Figura 6 Janela de instalao do plug-in GDB Hardware Debugging.

Na janela que se abrir, deve-se especificar o endereo do repositrio onde se


encontra o plug-in a ser instalado. Ou seja, conforme ilustrado na Figura 6, no campo

14

Work with deve ser inserido o endereo http://download.eclipse.org/tools/cdt


/releases/indigo. Ento, deve-se selecionar o item C/C++ GDB Hardware
Debugging da categoria CDT Optional Features. Finalize a instalao e reinicie o
Eclipse.

2.6 PROGRAMA PARA PISCAR LED

Para verificar o funcionamento da integrao entre o Eclipse e o compilador,


ser escrito um programa de exemplo que far um LED do kit de desenvolvimento
piscar.

Figura 7 Criando um projeto no Eclipse.

15

2.6.1 Criando um projeto

Para iniciar, deve-se abrir o Eclipse e no menu File selecionar a opo


New -> C Project, como ilustrado na Figura 7. A janela mostrada na Figura 8
dever aparecer. Deve-se escolher um nome para o projeto. Neste caso o nome
escolhido foi Teste.
Caso a instalao do plug-in GNU ARM tenha ocorrido com sucesso, na lista
com os tipos de projeto dever haver a categoria ARM Cross Target Application.
Dentro desta categoria escolha a opo Empty Project. Na lista Toolchains,
dever ser selecionada a opo ARM Windows GCC (Sourcery G++ Lite). Aps
fazer estas opes, clique direto em Finish. Feche a tela de boas vindas caso ela
ainda esteja aberta, como na Figura 9.

Figura 8 Janela de novo projeto.

16

Figura 9 Tela inicial do eclipse.

Figura 10 Janela de propriedades do Eclipse.

17

2.6.2 Configurando o plug-in GNU ARM

Aps esta etapa, devem ser feitas as configuraes de compilao do projeto.


Estas so opes que normalmente estariam no make file, mas agora so selecionadas
pela interface grfica do plug-in GNU ARM. Deve-se clicar em Project e em
Properties. A Janela da Figura 10 se abrir.

Figura 11 Tela principal de opes do plug-in GNU ARM.

Na janela de propriedades deve ser selecionada, na lista de opes da


esquerda, a categoria C/C++ Build e a opo Settings. Ento as opes da

18

Figura 11 aparecero. Certifique-se primeiramente de que o processador selecionado


o correto (cortex-m3).
No item Debugging da tela de configurao do plug-in GNU ARM, podem
ser feitas opes relacionadas gerao de cdigo para depurao do programa na
compilao. No iremos alterar nada neste item. Para que a depurao seja possvel
necessria gerao de cdigos adicionais que relacionem as linhas do arquivo binrio
com as linhas de cdigo em linguagem C. As opes possveis para a gerao destes
cdigos pelo compilador esto no manual do mesmo, que includo com o Sourcery
CodeBench.

Figura 12 Configurao do GNU ARM. Definio do caminho dos arquivos de cabealho utilizados.

19

No item Additional Tools, existem opes para que seja gerada a imagem
que ser gravada na memria Flash e para a exibio de uma mensagem informando
o tamanho do cdigo gerado. Tambm no sero feitas alteraes neste item.
O item ARM Sourcery Windows GCC Assembler e seus subitens ficaro
como esto, uma vez que no ser programado em assembly.
Conforme mostrado na Figura 12, no subitem Directories da categoria
ARM Sourcery Windows GCC C Compiler, devem ser inseridos os caminhos para
os locais onde esto os arquivos de cabealho das bibliotecas que sero utilizadas. Isso
pode ser feito clicando-se sobre o smbolo que est marcado com um circulo vermelho
na Figura 12. Neste caso, ser necessrio adicionar apenas a pasta raiz da biblioteca
do pacote StellarisWare, j que nenhuma outra biblioteca ser utilizada.

Figura 13 Configurao do GNU ARM. Opes do linker.

20

O prximo passo efetuar as configuraes do linker, no item ARM


Sourcery Windows GCC C Linker. A descrio das opes disponveis pode ser vista
no manual do linker, que includo com o Sourcery CodeBench. No subitem
General, deve ser escolhido um arquivo de script para o linker. Este arquivo
contm informaes sobre as faixas de endereo do microcontrolador que podem ser
utilizadas para gravao do cdigo, de constantes, de variveis inicializadas e de
variveis no inicializadas. Ele pode ser copiado de algum dos projetos de exemplo da
pasta boards\ek-lm3s8962 do pacote StellarisWare. o arquivo que possui o
mesmo nome do projeto e extenso *.ld. Neste exemplo foi copiado o arquivo
boards\ek-lm3s8962\blinky.ld para a pasta base dos projetos do Eclipse. O mesmo
foi renomeado para linker.ld, como pode ser visto na Figura 13.
Na mesma tela, tambm foram selecionadas as opes Do not use standard
start files e Remove unused sections. A primeira opo foi escolhida, pois ser
utilizado um arquivo de inicializao prprio.
Posteriormente devem ser feitas alteraes no subitem Libraries. Embora
nas bibliotecas de drivers do pacote StellarisWare estejam inclusos os arquivos com os
cdigos fonte, estes arquivos no sero recompilados. Ao invs disso ser utilizado um
arquivo com os objetos j compilados. O arquivo se encontra no caminho
StellarisWare\driverlib\gcc-cm3\ e se chama libdriver-cm3.a. Como pode ser
visto na Figura 14, o caminho para o arquivo deve ser inserido na lista Library
search path e o nome da biblioteca em Libraries. Note que o nome da biblioteca
igual ao nome do arquivo sem o prefixo lib e o sufixo de tipo de arquivo. O nome
dos arquivos de biblioteca sempre deve iniciar com o prefixo lib.

21

Figura 14 Configurao do GNU ARM. Definio das bibliotecas utilizadas.

Por fim, deve ser feita uma alterao no subitem Output da seo ARM
Sourcery Windows GNU Create Flash Image. O campo Output file format deve
ser alterado para binary, como demonstrado na Figura 15. Clique em Apply para
salvar as alteraes.
Na Figura 16, pode ser vista a janela de configurao dos smbolos e
caminhos de arquivos utilizados pelo projeto do Eclipse. Caso o item GNU C seja
selecionado na lista Languages, o item C:\Dev\StellarisWare poder ser visto na
lista Include directories. Nenhuma alterao precisa ser feita.

22

Figura 15 Configurao do GNU ARM. Definio do tipo de imagem gerada.

Figura 16 Arquivos de cabealho do Eclipse.

23

No momento em que o caminho da biblioteca StellarisWare foi adicionado no


menu de configurao do GNU ARM, o plug-in fez as alteraes necessrias nos
caminhos do Eclipse. No entanto, conforme sejam feitas modificaes nos caminhos
dos arquivos de cabealho utilizados no projeto, pode acontecer das listas do plug-in
GNU ARM (Figura 12) e do Eclipse (Figura 16) ficarem desatualizadas, gerando
erros ou durante a compilao (caso o plug-in no fornea a lista correta de caminhos
para o maker), ou na hora da edio do cdigo (caso o analisador de cdigo no possa
encontrar nos caminhos do Eclipse algum arquivo includo). Nesses casos, correes
podem ser feitas manualmente.

2.6.3 Importando o arquivo de inicializao

Alm do arquivo com o programa principal, necessrio um arquivo de


inicializao. Esse arquivo deve conter o vetor de endereos das funes de
interrupo, uma funo de interrupo padro e as funes de erro e reset.
Utilizaremos o mesmo arquivo de inicializao utilizado nos exemplos do
pacote StellarisWare. Aqui foi utilizado o arquivo StellarisWare\boards\eklm3s8962\blinky\startup_gcc.c. Para importar o arquivo, clique com o boto direito
sobre o nome do projeto e selecione Import..., conforme mostrado na Figura 17.
Na janela da Figura 18, selecione a opo File System, da categoria
General. Ao clicar em Next, a janela da Figura 19 aparecer. Selecione ento o
diretrio onde se encontra o arquivo de inicializao que ser importado. Aps
selecionar o diretrio, selecione o arquivo e clique em Finish.

24

Figura 17 Importando o arquivo de inicializao.

Figura 18 Janela de seleo de tipo de arquivo a importar.

25

Figura 19 Janela de seleo do arquivo a importar.

2.6.4 Escrevendo o programa

Finalmente, o programa de teste pode ser escrito. Um novo arquivo deve ser
criado, clicando-se com o boto direito sobre o nome do projeto e selecionando-se
New -> Source File. Isso pode ser visto na Figura 20. Na janela que se abrir,
nomeie o arquivo como main.c e clique em Finish.
Abra o arquivo criado e escreva o seguinte cdigo:
main.c
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
int main(){
unsigned char flagLEDLigado = false;
unsigned long contador;
/* Configura Clock para 50 MHz. */
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_8MHZ);

26

/* Habilita drivers do GPIO. */


SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
/* Configura o port F0 como sada para o LED. */
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
while(1){
if (flagLEDLigado == false){
/* Liga LED. */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
flagLEDLigado = true;
} else {
/* Desliga LED. */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
flagLEDLigado = false;
}
/* Gera Atraso. */
for (contador=0; contador<5000000; contador++);
}
}

Figura 20 Criando um novo arquivo.

Salve o arquivo editado, v em Project e escolha a opo Build Project.


O projeto dever compilar sem problemas. Agora, necessrio gravar o arquivo
binrio gerado no microcontrolador. Para que isso seja feito o OpenOCD precisa ser
configurado para uso com o Eclipse.

27

2.6.5 Configurando o OpenOCD

Para instalar o OpenOCD, extraia o contedo do arquivo comprimido para


um subdiretrio no mesmo local onde foram salvos os arquivos do pacote
StellarisWare e os projetos do Eclipse (diretrio Dev\OpenOCD).
Inicialmente devem ser instalados os drivers da interface JTAG do kit de
desenvolvimento. Existem trs drivers a serem instalados, os drivers dos canais A e B
do kit e um driver de porta serial. Embora todos os drivers sejam fornecidos pela
Texas Instruments junto com o kit, o driver do canal A deve ser substitudo por uma
verso disponibilizada junto com o OpenOCD. sugerido que o primeiro driver a ser
instalado seja o fornecido com o OpenOCD. Ele se encontra no arquivo libusbwin32_ft2232_driver-110810.zip, localizado no diretrio OpenOCD\drivers. A
instalao pode ser feita pelo gerenciador de dispositivos do Windows.
Posteriormente, pode ser instalado o driver do canal B que foi fornecido junto
com o kit. Aps a instalao, ser detectada a existncia da porta serial e seu driver
tambm poder ser instalado. O controlador USB do kit emula uma porta que est
ligada na interface serial do microcontrolador.
A seguir, o OpenOCD poder ser integrado ao Eclipse clicando-se em Run > External Tools -> External Tools Configurations.... A janela da Figura 21 se
abrir. Clique no boto do canto superior esquerdo para criar uma nova configurao.
No campo Name escreva Grava Flash. Em Location deve ser inserido o
caminho para o executvel do OpenOCD. Neste caso, pode ser inserido o caminho
relativo

${workspace_loc:}/../OpenOCD/bin/openocd-0.5.0.exe,

onde

workspace_loc uma varivel de ambiente do Eclipse que contm o caminho para

28

a pasta raiz dos projetos. Em Working Directory deve ser inserido o caminho para
o diretrio base do OpenOCD, que neste caso ${workspace_loc:}/../OpenOCD/.
O texto contido no campo Arguments ser adicionado como parmetro na chamada
do OpenOCD pelo Eclipse e deve ser igual a -f .\board\ek-lm3s8962.cfg -c "init" -c
"reset

halt"

-c

"stellaris

mass_erase

0"

-c

"flash

write_bank

../Eclipse/${project_name}/Debug/${project_name}.hex 0" .

Figura 21 Janela External Tools Configurations. Configurao para escrever na flash.

O primeiro argumento, precedido pelo identificador -f, indica o local do


arquivo de configuraes do OpenOCD. Este arquivo contm informaes sobre o kit
de desenvolvimento e o microcontrolador para que a comunicao com a interface

29

JTag seja possvel. O arquivo ek-lm3s8962.cfg no est includo com o OpenOCD,


mas pode ser criado a partir do arquivo ek-lm3s6965.cfg. Aps duplicar o arquivo e
renome-lo,

algumas

alteraes

precisam

ser

feitas.

parmetro

WORKAREASIZE deve ser alterado de 0x5000 para 0x10000 e o parmetro


CHIPNAME deve ser alterado de lm3s6965 para lm3s8962. Na linha seguinte
deve ser inserido o texto set CPUTAPID 0x3ba00477.
Os demais argumentos, precedidos pelo identificador -c, so comandos que
obedecem a sintaxe utilizada pelo OpenOCD. O comando init informa ao
OpenOCD que as configuraes do JTag j foram feitas (neste caso pelo arquivo de
configurao) e iniciada a fase de execuo. O comando reset halt reinicializa o
microcontrolador e pausa sua execuo logo em seguida. O comando mass_erase
apaga a memria flash do microcontrolador e o comando write_bank grava a
mesma com o arquivo binrio fornecido. No caminho para o arquivo a ser gravado foi
utilizada a varivel de ambiente do Eclipse project_name, que ser substituda
automaticamente pelo nome do projeto ativo do Eclipse. Todos os comandos possveis
se encontram no manual do OpenOCD.
Aps estas configuraes, selecione a aba Common e na lista Display in
favorites menu, da janela da Figura 22, selecione a opo External Tools. Clique
em Apply e feche a janela.
Agora, para gravar o microcontrolador basta conectar o kit ao computador,
lig-lo, clicar sobre o boto representado na Figura 23 e selecionar a opo Grava
Flash.

30

Algumas vezes, a mensagem de erro da Figura 24 pode aparecer. Isto ocorre


quando nenhum projeto est selecionado, o que impossibilita o Eclipse de achar um
valor para a varivel de ambiente project_name. Para que isso no ocorra, basta
clicar com o cursor de texto em algum arquivo do projeto ou clicar sobre a pasta do
projeto, no Project Explorer, de forma que ela fique selecionada.

Figura 22 Janela para adio do OpenOCD ao menu dos favoritos.

Figura 23 Tela com opo criada para gravar o microcontrolador.

31

Figura 24 Erro tpico ao gravar memria flash.

2.6.6 Configurando o depurador

Embora o Eclipse j venha com o GDB Debugger integrado sua interface


grfica e o plug-in para depurao em sistemas embarcados j tenha sido instalado na
seo Instalando o plug-in do depurador, o GDB Debugger no tem acesso
interface JTag do kit de desenvolvimento. Para que o acesso interface JTag seja
possvel, necessria a integrao do sistema de depurao com o OpenOCD.
O OpenOCD dever se comunicar com a interface JTag e atender requisies
de controle do microcontrolador vindas do GDB Debugger. O OpenOCD se comunica
com o GDB por meio de uma conexo TCP/IP local na porta 3333. Logo, para que a
depurao seja possvel, primeiro necessrio que o OpenOCD esteja conectado com
a interface JTag e aguardando uma conexo do GDB.
Dever ser criada uma nova configurao para o OpenOCD, como a descrita
na seo Configurando o OpenOCD. No entanto, alteraes devem ser feitas para
que esta configurao no grave e apague a memria flash do microcontrolador.
Para facilitar, pode ser feita uma cpia da configurao Grava Flash. Abra
a janela External Tools Configuration em Run -> External Tools -> External
Tools Configurations.... Clique com o boto direito sobre a configurao Grava
Flash, que foi criada anteriormente, e selecione Duplicate. Agora altere o nome da

32

nova configurao para Servidor GDB. Alm disso, remova alguns parmetros da
caixa de texto Arguments at que seu contedo fique igual a -f .\board\eklm3s8962.cfg -c "init . O resultado final est mostrado na Figura 25. No se
esquea de clicar em Apply.

Figura 25 Janela External Tools Configurations. Configurao para depurar.

Agora devem ser feitas as configuraes do GDB Debugger. Para tanto, entre
em Run -> Debug Configurations.... Na janela da Figura 26, clique com o boto
direito sobre GDB Hardware Debugging e selecione a opo New. Posteriormente,
abra a aba Debugger e faa as modificaes da Figura 27. Altere o texto do campo
GDB Command para arm-none-eabi-gdb e o texto do campo Port number para
3333.

33

Figura 26 Janela de configurao do depurador.

Figura 27 Janela de configurao do depurador com a aba Debugger selecionada.

34

Na aba Startup, conforme mostrado na Figura 28, desmarque todas as


opes e na caixa de texto Initialization Commands escreva o cdigo a seguir.
monitor reset halt
file 'C:/Dev/Eclipse/Teste/Debug/Teste.elf'
monitor reset halt

Figura 28 Janela de configurao do depurador com a aba Startup selecionada.

Estes so comandos que sero executados quando o GDB Debugger for


iniciado. O comando monitor faz com que o GDB repasse a instruo subsequente
para o OpenOCD. Logo, a primeira e a ltima linha fazem com que o
microcontrolador seja reiniciado e pausado. J o comando file informa ao GDB
onde est o arquivo binrio que contm o cdigo que foi gravado na memria flash do
microcontrolador. Isso necessrio para que o depurador possa relacionar cada

35

endereo da memria flash do microcontrolador com as linhas de cdigo escritas em


C/C++.
A princpio, os comandos que foram escritos manualmente poderiam ser
executados pelas opes que foram desmarcadas na janela da Figura 28. No entanto,
por algum motivo desconhecido, as opes da interface grfica no esto funcionando
corretamente.
Aps estes passos, clique na aba Common e selecione o item Debug da
lista Display in favorites menu. Clique em Apply e feche a janela.

Figura 29 Janela com ferramentas externas abertas.

Antes de iniciar o depurador, certifique-se de que no h nenhuma instncia


do OpenOCD ou do GDB aberta. Como demonstrado na Figura 29, isso pode ser
verificado selecionando-se a aba Console da janela principal do Eclipse. Clicando

36

sobre a seta ao lado do cone com aparncia de computador aparecer uma lista com
os programas externos abertos. Caso haja algum item do OpenOCD ou do GDB,
clique sobre ele e encerre-o. Para encerrar a execuo, basta clicar sobre o quadrado
vermelho mostrado na Figura 30. Aps encerrar a execuo do programa externo, o
console do mesmo pode ser fechado clicando-se sobre o X ao lado do quadrado.

Figura 30 Encerrando ferramenta externa.

Figura 31 Iniciando o Servidor GDB.

Para iniciar a depurao, primeiro clique sobre a seta ao lado do item


demarcado na Figura 31 e selecione a opo Servidor GDB. Na janela da aba
Console, o texto da Figura 32 dever aparecer. Ento o GDB Debugger pode ser
iniciado. Para tanto, basta clicar sobre a seta ao lado do cone de inseto, apresentado
na Figura 33, e selecionar a opo Teste Debug. O GDB Debugger ir iniciar e

37

possivelmente a caixa de dilogo da Figura 34 aparecer. Clique em Yes para que a


perspectiva de depurao seja ativada, alterando o visual da interface grfica.

Figura 32 Console do OpenOCD configurado como servidor para o depurador.

Figura 33 Iniciando o depurador.

Figura 34 Caixa de dilogo de troca de perspectiva.

O Eclipse dispe de diversas perspectivas grficas, que possibilitam


mudanas na interface grfica de acordo com a atividade que est sendo realizada
pelo usurio. A comutao entre as perspectivas mais utilizadas pode ser feita por

38

meio do menu no canto superior direito da janela principal, que est destacado na
Figura 35.

Figura 35 Menu de perspectivas.

Figura 36 Inserindo breakpoint.

Ao iniciar o depurador, o programa iniciar possivelmente em algum ponto


desconhecido do cdigo. No se preocupe com isso, apenas abra o arquivo onde deseja
adicionar um breakpoint e d dois cliques na barra azul que fica do lado esquerdo do
editor de texto, na posio da linha desejada. Isso est exemplificado na Figura 36.
A seguir, o terminal do GDB deve ser aberto. Como destacado na Figura 37,
na parte inferior da janela principal selecione a aba Console, clique na seta ao lado

39

do cone de computador e selecione a opo Teste Debug [GDB Hardware


Debugging] gdb. Na tela do terminal digite monitor reset halt e pressione Enter.
O microcontrolador ir reiniciar. Ento pressione o boto resume, que se encontra na
barra de ferramentas de depurao e est destacado na Figura 38. A execuo dever
parar quando o breakpoint for atingido. Sempre que se desejar reiniciar o
microcontrolador o mesmo comando pode ser digitado no terminal.

Figura 37 Abrindo o terminal do GDB Debugger.

Figura 38 Boto resume no menu de depurao.

2.7 PROGRAMA PARA ACESSAR A INTERFACE SERIAL

A seguir sero feitas modificaes no projeto criado na seo Programa para


piscar LED para que sejam transmitidos dados pela interface serial. Este exemplo
interessante, pois para acessar a interface serial do microcontrolador sero

40

adicionados arquivos de cdigo fonte externos ao projeto. Isso no havia sido feito na
outra seo, onde haviam sido utilizados apenas arquivos de cabealho externos e
bibliotecas pr-compiladas.

2.7.1 Criando o projeto

O projeto ser criado com base no projeto de teste criado anteriormente.


Logo, abra o Eclipse e certifique-se de que o projeto Teste esteja aberto. Ento, no
Project Explorer, copie e cole o projeto Teste utilizando o menu do boto direito
do mouse. Na hora de colar o projeto, o Eclipse solicitar um nome para o mesmo.
Nomeie o projeto como Serial. Agora feche o projeto Teste. Para fech-lo clique
com o boto direito em cima do mesmo e selecione Close Project.
Quando um projeto copiado, por algum motivo desconhecido as
configuraes do depurador so perdidas. Logo, as configuraes da seo
Configurando o depurador, com exceo da parte referente ao OpenOCD (criao
da configurao GDB Server), precisam ser refeitas. No entanto, dessa vez o
caminho 'C:/Dev/Eclipse/Teste/Debug/Teste.elf' , que foi inserido nos comandos
de inicializao da janela representada pela Figura 28, deve ser substitudo por
'C:/Dev/Eclipse/Serial/Debug/Serial.elf' .

2.7.2 Escrevendo o programa

Agora, o cdigo do arquivo main.c pode ser substitudo por:

41

main.c
#include
#include
#include
#include
#include

"inc/hw_types.h"
"inc/hw_memmap.h"
"driverlib/sysctl.h"
"driverlib/gpio.h"
"utils/uartstdio.h"

int main(){
unsigned char flagLEDLigado = false;
unsigned long contador;
/* Configura Clock para 50 MHz. */
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_8MHZ);
/* Habilita drivers do GPIO F. */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
/* Configura o port F0 como sada para o LED. */
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
/* Habilita drivers do GPIO A (utilizado pela serial). */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
/* Configura ports F0 e F1 para uso com a serial. */
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
/* Inicializa a serial que ligada ao controlador USB. */
UARTStdioInit(0);
/* Lao infinito. */
while(1){
if (flagLEDLigado == false){
/* Liga LED. */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
UARTwrite("LED Ligado\n", 11);
flagLEDLigado = true;
} else {
/* Desliga LED. */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
UARTwrite("LED Desligado\n", 14);
flagLEDLigado = false;
}
/* Gera Atraso. */
for (contador=0; contador<5000000; contador++);
}
}

Este programa far com que toda vez que o estado do LED se altere, seja
transmitida uma mensagem pela interface serial. Neste exemplo foram utilizadas as
funes UARTStdioInit e UARTwrite, que esto declaradas no arquivo
uartstdio.c da pasta utils do pacote StellarisWare. A funo UARTStdioInit

42

inicializa a interface serial do microcontrolador com uma frequncia de 115200 Hz.


Para que o programa possa ser compilado, primeiro deve ser adicionado o arquivo
uartstdio.c.

2.7.3 Criando pasta virtual e adicionando atalho para arquivo

O arquivo uartstdio.c no ser copiado para a pasta do projeto. Ser criado


apenas um atalho para o arquivo, que ser armazenado em uma pasta virtual dentro
do projeto.
Primeiro a pasta virtual deve ser criada clicando-se com o boto direito sobre
o nome do projeto no Project Explorer e selecionando-se a opo New -> Folder,
como demonstrado na Figura 39.

Figura 39 Criando pasta virtual no Eclipse.

Na janela que se abrir, clique no boto Advanced e selecione a opo


Folder is not located in the file system (Virtual Folder). No campo Folder Name

43

digite o nome desejado. Para este exemplo, escolhi o nome utils. Estas
configuraes esto ilustradas na Figura 40.

Figura 40 Opes da pasta virtual.

Agora um atalho para o cdigo fonte precisa ser adicionado. Como mostrado
na Figura 41, clique com o boto direito sobre a pasta criada e selecione New ->
File. Na janela aberta, que est representada na Figura 42, clique em Advanced e
selecione a opo Link to file in the file system. Ento clique em Browse e
selecione o arquivo \StellarisWare\utils\uartstdio.c. Agora que o atalho foi
adicionado, o arquivo ser includo no processo de compilao pelo plug-in GNU
ARM. Caso se deseje excluir temporariamente algum arquivo do processo de
compilao, pode-se clicar com o boto direito sobre o mesmo e selecionar Resource

44

Configurations

->

Exclude

from

Build....

Compile

projeto,

microcontrolador e teste-o com algum programa para comunicao serial.

Figura 41 Criando atalho para cdigo fonte no Eclipse.

Figura 42 Configurando atalho para cdigo fonte.

grave-o

no

45

3 INSTALAO DO RTOS

Nesta seo ser feita a instalao de um sistema operacional em tempo real


no microcontrolador. Alm dos programas necessrios da seo anterior, ser
necessrio o sistema operacional FreeRTOS. O mesmo pode ser obtido
gratuitamente no site sourceforge. Para este guia foi utilizada a verso 7.1.1.
Para instalar o FreeRTOS basta extrair o arquivo obtido no diretrio base
onde est a pasta de projetos do Eclipse e a pasta com os arquivo do pacote
StellarisWare. No meu caso, os arquivos ficaram no diretrio \Dev\FreeRTOS.
O FreeRTOS inclui exemplos para o kit de desenvolvimento EKLM3S8962. No entanto, esta seo foi escrita, pois os exemplos esto meio
desatualizados e tambm no fazem uso do plug-in GNU ARM.

3.1 ADICIONANDO O FREERTOS A UM PROJETO

Inicialmente deve ser criado um novo projeto para este exemplo. Faa uma
cpia do projeto Teste da seo Programa para piscar LED. Nomeie o projeto
como RTOS.
O ncleo do FreeRTOS encontra-se basicamente nos seguintes arquivos:
list.c, queue.c e tasks.c, que esto no diretrio FreeRTOS\Source\. No
entanto para que o sistema operacional funcione, tambm necessrio um arquivo de
interface que especfico para cada famlia de microcontrolador. O arquivo de
interface utilizado com o ARM Cortex M3 est no diretrio FreeRTOS\Source\
portable\GCC\ARM_CM3\ e se chama port.c. Ainda necessrio um arquivo de

46

gerenciamento de memria. O FreeRTOS fornece trs opes de arquivo de


gerenciamento de memria. A descrio de cada um pode ser encontrada no site do
FreeRTOS. Para este exemplo utilizaremos o arquivo heap_2.c, que est no
diretrio FreeRTOS\Source\portable\MemMang\.
Um atalho para cada um destes cinco arquivos deve ser adicionado ao
projeto. A lista com o local e nome dos arquivos que devem ser adicionados est
apresentada abaixo. No projeto, crie uma pasta virtual chamada FreeRTOS e
adicione os atalhos a mesma. Em caso de dvida, leia a seo Criando pasta virtual
e adicionando atalho para arquivo.
-> \FreeRTOS\Source\
* list.c
* queue.c
* tasks.c
-> portable\
-> MemMang\
* heap_2.c
-> GCC\ARM_CM3\
* port.c

Tambm necessrio adicionar um arquivo de configurao4 do FreeRTOS


ao projeto. Ns iremos utilizar um arquivo do projeto de demonstrao que vem com
o FreeRTOS. Clique com o boto direito do mouse sobre o nome do projeto no
Project Explorer e selecione a opo Import. Na janela que aparecer escolha a
opo File System, da categoria General, e clique em Next. Escolha o diretrio
FreeRTOS\Demo\CORTEX_LM3Sxxxx_Eclipse\RTOSDemo

selecione

arquivo FreeRTOSConfig.h. Abra o arquivo importado e comente as trs


penltimas linhas. Da linha extern volatile unsigned long ulHighFrequencyTimer
Ticks; at a linha #define portGET_RUN_TIME_COUNTER_VALUE() ulHigh

47

FrequencyTimerTicks. Alm disso, no mesmo arquivo, mude o parmetro


configGENERATE_RUN_TIME_STATS de 1 para 0.
O pacote StellarisWare possui um arquivo com funes simplificadas para
manipulao de strings. Embora, no seja o caso neste exemplo, o FreeRTOS pode
fazer uso da funo sprintf. Logo, configuraremos o Eclipse para que caso esta
funo venha a ser utilizada algum dia, ela seja substituda pela funo usprintf,
presente no StellarisWare.
Primeiro um atalho para o arquivo StellarisWare\utils\ustdlib.c deve ser
adicionado

ao

projeto.

Eu

criei

atalho

dentro

das

pastas

virtuais

StellarisWare\utils\, que tambm adicionei ao projeto. Para que a funo


usprintf seja utilizada no lugar da funo printf, deve ser adicionada uma
diretiva de pr-compilador ao projeto. No menu do plug-in GNU ARM selecione o
item Preprocessor da categoria ARM Sourcery Windows GCC C Compiler.
Ento, na lista Defined symbols, adicione o item sprintf=usprintf, como na
Figura 43. Isso equivale a adicionar o texto #define sprintf=usprintf a todos os
arquivos do projeto.
Tambm devem ser includos ao projeto trs caminhos para os arquivos de
cabealho que sero utilizados. Isso feito por meio do menu de configurao do
GNU ARM, como descrito na seo Configurando o plug-in GNU ARM. Um
caminho para o diretrio FreeRTOS\Source\include, onde esto os arquivos de
cabealho

do

ncleo

do

sistema

operacional.

Outro

para

diretrio

FreeRTOS\Source\portable\GCC\ARM_CM3\, onde se encontra o arquivo de

48

cabealho de interface, e o ltimo para a pasta base do projeto, onde est o arquivo
de configurao que foi importado.

Figura 43 Adio de diretivas de pr-processador.

Aps a adio dos arquivos de cabealho e de cdigo fonte, a aparncia do


Project Explorer (com as pastas Includes, StellarisWare e FreeRTOS
expandidas) dever ficar como na Figura 44.
O FreeRTOS necessita de trs interrupes para funcionar. Logo, no
arquivo de inicializao startup_gcc.c devem ser feitas algumas modificaes.
Abaixo da linha onde est escrito "extern int main(void)", adicione os seguintes
prottipos de funes externas:
extern void xPortPendSVHandler(void);
extern void xPortSysTickHandler(void);
extern void vPortSVCHandler(void);

49

Figura 44 Project Explorer aps incluso de arquivos.

Estas funes esto definidas no arquivo de interface do FreeRTOS. Alm


disso, os ponteiros para estas funes devem ser inseridos na lista do vetor de
interrupes, ficando a mesma assim:
startup_gcc.c
(...)
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) =
{
(void (*)(void))((unsigned long)pulStack +
//
ResetISR,
//
(...)
0,
//
vPortSVCHandler,
//
IntDefaultHandler,
//
0,
//
xPortPendSVHandler,
//
xPortSysTickHandler,
//
IntDefaultHandler,
//
(...)
IntDefaultHandler
//
};
(...)

sizeof(pulStack)),
The initial stack pointer
The reset handler
Reserved
SVCall handler
Debug monitor handler
Reserved
The PendSV handler
The SysTick handler
GPIO Port A
Hibernate

50

Alm destas alteraes, o FreeRTOS requer que sejam adicionadas duas


funes ao projeto. Adicione o seguinte cdigo, com a definio das duas funes, ao
arquivo main.c.
void vApplicationTickHook( void )
{
}
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR
*pcTaskName )
{
for( ;; );
}

A funo vApplicationTickHook chamada a partir da interrupo do tick,


que tem sua frequncia definida no arquivo de configurao do FreeRTOS. A
funo vApplicationStackOverflowHook ser chamada caso seja detectado estouro
na pilha5 de alguma tarefa.
No se esquea tambm de incluir os seguintes cabealhos ao arquivo
main.c:
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "task.h"

Com estas alteraes, o projeto j dever compilar sem erros. No entanto,


ainda precisa ser escrito o cdigo que inicializa o FreeRTOS e cria as tarefas.

3.2 ESCREVENDO PROGRAMA DE TESTE COM O FREERTOS

Para testar o FreeRTOS ser escrito um programa que ter uma tarefa e
uma interrupo. A interrupo ser gerada por um timer, a cada segundo. A rotina

51

de interrupo enviar uma mensagem com o nmero de segundos decorridos para a


nica tarefa.
A tarefa ficar sempre em repouso, aguardando mensagens. Quando alguma
mensagem for recebida, a tarefa sair do repouso, enviar a mensagem recebida pela
interface serial e far o LED piscar.
Inicialmente deve ser criada a funo de interrupo do timer e o ponteiro
para a mesma deve ser adicionado ao vetor de interrupes do arquivo de
inicializao. A funo ser chamada de ISRTimer. Logo, no incio do arquivo
startup_gcc.c adicione o prottipo extern void ISRTimer (void);. Ainda no
mesmo arquivo, na tabela de vetores, na linha onde h o comentrio Timer 0
subtimer A, troque IntDefaultHandler, por ISRTimer,.
Agora, no arquivo main.c, adicione a seguinte varivel global:
xQueueHandle filaInterfaceSerial;

Esta varivel representa uma fila que ser usada para comunicao entre a
rotina de interrupo e a tarefa da serial. Para o uso de filas, o arquivo de cabealho
queue.h tambm deve ser includo.
Declare a funo ISRTimer adicionando o cdigo abaixo.
void ISRTimer(void){
/* Varivel para contagem dos segundos decorridos */
static unsigned long segundos=0;
/* Tarefa de prioridade mais alta foi desbloqueada? */
long tarefaPrioritariaDespertada;
/* Apaga interrupo do timer. Deve ser a primeira coisa a ser feita.*/
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
segundos++; /* Incrementa tempo */
/* Envia mensagem, informando tarefa da serial que se passou um segundo. */
xQueueSendToBackFromISR(filaInterfaceSerial, &segundos,
&tarefaPrioritariaDespertada);
}

52

A funo ISRTimer apenas incrementa uma varivel de tempo e transmite


seu valor atualizado para a fila filaInterfaceSerial. O efeito prtico da chamada da
funo TimerIntClear pode no ser instantneo, por isso a mesma deve ser
chamada no incio da rotina. As funes do timer requerem a incluso do cabealho
driverlib/timer.h.
Agora, deve ser criada a funo que representa a tarefa de controle da
interface serial. As funes de tarefa costumam ter um cdigo de inicializao que
executada uma nica vez e um cdigo que se repete indefinidamente. Crie a funo
transcrita a seguir:
void TarefaSerial(void *pvParameters){
unsigned short segundos;
unsigned char flagLEDLigado = false;
/* Habilita drivers do GPIO F (utilizado pelo LED). */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
/* Configura o port F0 como sada para o LED. */
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
/* Habilita drivers do GPIO A (utilizado pela serial). */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
/* Configura ports F0 e F1 para uso com a serial. */
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
/* Inicializa a serial que ligada ao controlador USB. */
UARTStdioInit(0);
/* Habilita timer */
TimerEnable(TIMER0_BASE, TIMER_A);
for( ;; ){
/* Aguarda mensagem da rotina de interrupo do timer. */
xQueueReceive( filaInterfaceSerial, &segundos, portMAX_DELAY );
/* Transmite tempo pela serial. */
UARTprintf("\%u segundos.\n", segundos);
/* Atualiza LED. */
if (flagLEDLigado == false){
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
flagLEDLigado = true;
} else {
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
flagLEDLigado = false;
}
}
}

53

No incio da funo feita a inicializao do pino ligado ao LED e da


interface serial. O timer iniciado aqui para termos certeza de que ele no provocar
interrupes antes do sistema estar rodando. Posteriormente, dentro do lao infinito
chamada

funo

xQueueReceive.

Caso

haja

algum

elemento

na

fila

filaInterfaceSerial, o mesmo ser lido e removido da fila. Caso contrrio, a tarefa


ir entrar em repouso at que a rotina de interrupo do timer adicione um novo
elemento fila.
O valor lido da fila ser transmitido pela interface serial e o estado do LED
ser atualizado. Foi utilizada a funo UARTprintf, que requer a adio de um
atalho para o cdigo fonte StelariWare\utils\uartstdio.c. Sugiro que o atalho seja
adicionado pasta virtual StellarisWare\utils. Em caso de dvidas, leia a seo
Criando

pasta

virtual

adicionando

atalho

para

arquivo.

cabealho

utils/uartstdio.h tambm deve ser adicionado no incio do arquivo main.h.


Finalmente, deve ser escrito o cdigo da funo main, para que o timer seja
configurado, a tarefa da interface serial seja criada, e o sistema operacional seja
inicializado.
int main(){
/* Configura Clock para 50 MHz. */
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_8MHZ);
/* Habilita drivers do Timer. */
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
/* Configura timer para modo peridico de 32 bits. */
TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
/* Configura timer para frequncia de 1 Hz. */
TimerLoadSet(TIMER0_BASE, TIMER_A, 50000000);
/* Configura prioridade da interrupo do timer. */
IntPrioritySet(INT_TIMER0A, configMAX_SYSCALL_INTERRUPT_PRIORITY);
/* Habilita interrupo do timer. */
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
IntEnable(INT_TIMER0A);
/* Inicializa fila da interface serial. */

54

filaInterfaceSerial = xQueueCreate( 2, sizeof( unsigned long ) );


/* Cria tarefa da interface serial. */
xTaskCreate( TarefaSerial, (signed portCHAR*)"UART",
configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
/* Inicia escalonador do FreeRTOS. */
vTaskStartScheduler();
/* No deve chegar aqui. */
while(1);
}

Como pode ser visto, inicialmente o timer configurado para uma frequncia
de 1 Hz e so habilitadas suas interrupes. muito importante que a prioridade da
interrupo do timer seja inferior ou igual (de nmero maior ou igual) a constante
configMAX_SYSCALL_INTERRUPT_PRIORITY, que est definida no arquivo
de configurao do FreeRTOS. Para que uma interrupo possa ter prioridade
maior, ela no deve utilizar as funes do sistema operacional. Para as funes de
configurao das interrupes so necessrios os cabealhos inc/hw_ints.h e
driverlib/interrupt.h.
Aps as configuraes do timer, inicializada a fila da interface serial, com
espao para no mximo dois elementos de tamanho unsigned long. A seguir criada
a

tarefa

da

interface

serial,

com

uma

pilha

de

tamanho

configMINIMAL_STACK_SIZE e com a menor prioridade possvel. Finalmente,


inicializado o escalonador, por meio da funo vTaskStartScheduler, que tambm se
encarrega de habilitar as interrupes globais.
O cdigo completo, aps todas as modificaes, pode ser encontrado no
APNDICE A.

55

4 INSTALAO DA PILHA TCP/IP

A seguir ser descrita a instalao da pilha TCP/IP LwIP em conjunto com o


sistema operacional FreeRTOS. Ser utilizada a instalao do sistema operacional
que foi apresentada na seo Instalao do RTOS.
Foi utilizada a verso 1.4.0 do LwIP, que pode ser obtida gratuitamente na
pgina do projeto.
Aps a configurao do LwIP ser escrito um pequeno programa de teste que
altera o estado do LED do kit de desenvolvimento quando o mesmo recebe uma
requisio http de um navegador conectado na mesma rede do microcontrolador.

4.1 INSTALANDO E CRIANDO UM PROJETO DE EXEMPLO

Inicialmente, extraia os arquivos do LwIP para a mesma pasta base onde


esto os arquivos do FreeRTOS e do StellarisWare, que no meu caso a pasta
\Dev\LWIP.
Para o funcionamento da pilha TCP/IP, so necessrios alguns arquivos de
interface com o FreeRTOS. Estes arquivos possibilitam que a pilha TCP/IP possa
criar semforos, pilhas e tarefas utilizando as funes do sistema operacional. Alm
disso, eles tambm definem os tipos de variveis reconhecidos e utilizados pelo
microcontrolador e pelo compilador. A descrio do que deve haver nestes arquivos6
est no guia do LwIP.
Tambm necessrio um arquivo de driver de dispositivo, responsvel pela
inicializao da interface ethernet no microcontrolador, assim como pelas possveis

56

leituras/escritas nos registradores do mesmo. Por sorte, este arquivo fornecido pelo
pacote StellarisWare e no precisa ser alterado. J os outros arquivos, embora
presentes no pacote StellarisWare, necessitaro de alteraes.
Aps extrair os arquivos do LwIP, copie a pasta ports (presente no
diretrio \Dev\StellarisWare\thir_party\lwip-1.3.2\) para a pasta do LwIP
(\Dev\LWIP). A estrutura do novo diretrio criado dever ficar assim:
-> \LWIP\ports\stellaris
* perf.c
* sys_arch.c
-> include\
-> arch\
* bpstruct.h
* cc.h
* epstruct.h
* perf.h
* sys_arch.h
-> netif\
* stellarisif.h
-> netif\
* stellarisif.c

Dos arquivos listados, os arquivos sys_arch.c, sys_arch.h e cc.h


necessitam de alteraes. Os mesmos foram reescritos com base nos arquivos originais
e nos arquivos do exemplo lwip_MCF5235_GCC, fornecido junto com o
FreeRTOS. As alteraes sero feitas aps a criao do projeto.
Abra o Eclipse e crie uma cpia do projeto FreeRTOS, que foi criado
anteriormente. Nomeie o novo projeto como Ethernet. No Project Explorer, crie
uma nova pasta chamada Ethernet (uma pasta real, no uma pasta virtual).
Dentro desta pasta crie uma pasta de atalho para os arquivos do LwIP. Para cria-la,
clique com o boto direito sobre a pasta Ethernet e selecione a opo New ->
Folder. No menu New Folder, como mostrado na Figura 45, clique no boto
Advanced e selecione a opo Link to alternate location (Linked Folder). Ento

57

selecione o caminho para a pasta com os arquivos do LwIP (\Dev\LWIP) e clique


em Finish.

Figura 45 Criando atalho para pasta com arquivos do LwIP.

Na pasta de atalho criada, alguns arquivos devem ser excludos do processo


de compilao. Clique com o boto direito sobre as pastas Ethernet\LWIP\doc e
Ethernet\LWIP\test e selecione a opo Resource Configurations -> Exclude from
Build.... No menu Exclude from Build clique em Select All e em OK. Exclua
tambm

as

pastas

Ethernet\LWIP\src\core\ipv6

Ethernet\LWIP\src\

include\ipv6.
Agora podem ser feitas as alteraes nos arquivos de interface sys_arch.c,
sys_arch.h e cc.h. Abra-os pelo Eclipse e substitua seus contedos pelos cdigos

58

do APNDICE B, APNDICE C e APNDICE D, respectivamente. Os arquivos


tambm esto includos como anexo neste documento, para evitar possveis problemas
de perda de formatao que podem ocorrer na cpia de textos em alguns leitores de
PDF.
Os caminhos para os arquivos de cabealho do LwIP devem ser adicionados
no menu do plug-in GNU ARM. Inclua os caminhos para os diretrios
/Ethernet/LWIP/ports/stellaris/include,
/Ethernet/LWIP/src/include/ipv4,

/Ethernet/LWIP/src/include

seguindo

procedimento

da

e
seo

Configurando o plug-in GNU ARM. Ainda no menu do plug-in, no item


Preprocessor da categoria ARM Sourcery Windows GCC C Compiler, adicione a
diretiva de pr-compilador snprintf=usnprintf.
O LwIP utiliza a interrupo da ethernet. Logo, so necessrias algumas
alteraes no arquivo de inicializao startup_gcc.c. Abra o arquivo e exclua o
prottipo da rotina de interrupo do timer, que havia sido includo na seo
Escrevendo programa de teste com o FreeRTOS e no ser mais utilizado.
Substitua o item ISRTimer por IntDefaultHandler, no vetor de interrupes. A
seguir, adicione o seguinte prottipo para a funo de interrupo da ethernet:
extern void EthernetISR(void);. Adicione o identificador EthernetISR ao vetor de
interrupes na posio referente a ethernet (penltima posio). Ainda no mesmo
arquivo, aumente o tamanho do vetor static unsigned long pulStack para 128.
necessria ainda um arquivo de configuraes do LwIP. Este arquivo, que
deve ser chamado de lwipopts.h, possui diversas definies que determinam o uso de
memria pela pilha TCP/IP, quais protocolos da pilha sero includos na compilao,

59

entre outros parmetros. H uma verso deste arquivo no exemplo enet_lwip do


pacote

StellarisWare

(no

diretrio

\Dev\StellarisWare\boards\ek-lm3s8962\

enet_lwip\), que deve ser importada para o projeto.


Aps importar o arquivo, comente as seguintes linhas:
linha
linha
linha
linha
linha
linha
linha
linha
at
linha
linha

041:
054:
138:
160:
161:
163:
291:
376:

#define HOST_TMR_INTERVAL 100


#define NO_SYS 1
#define LWIP_DHCP 1
#define LWIP_AUTOIP 1
#define LWIP_DHCP_AUTOIP_COOP ((LWIP_DHCP) && (LWIP_AUTOIP))
#define LWIP_DHCP_AUTOIP_COOP_TRIES 5
#define LWIP_NETCONN 0
#ifdef DEBUG

378: #endif
397: #define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE...

Alm disso, descomente e altere os textos das linhas a seguir, para:


linha
linha
linha
linha
linha
linha
linha
linha
linha

220:
268:
269:
270:
280:
281:
282:
283:
323:

#define
#define
#define
#define
#define
#define
#define
#define
#define

TCP_SND_QUEUELEN (4 * (TCP_SND_BUF/TCP_MSS))
TCPIP_THREAD_STACKSIZE 1024
TCPIP_THREAD_PRIO 3
TCPIP_MBOX_SIZE 6
DEFAULT_RAW_RECVMBOX_SIZE 6
DEFAULT_UDP_RECVMBOX_SIZE 6
DEFAULT_TCP_RECVMBOX_SIZE 6
DEFAULT_ACCEPTMBOX_SIZE 6
SYS_STATS 0

Por fim, adicione a definio a seguir no final do arquivo (antes da diretiva


#endif):
#define LWIP_COMPAT_MUTEX 1

A descrio dos parmetros de configurao do LwIP, assim como as


configuraes

padres,

podem

ser

vistas

no

arquivo

de

cabealho

\Dev\LWIP\src\include\lwip\opt.h.
Agora, crie dois novos arquivos de cdigo fonte e seus respectivos cabealhos
na pasta Ethernet. Nomeie-os como Ethernet.c, Ethernet.h, Servidor.c e
Servidor.h. Todos os arquivos esto anexados ao PDF.

60

Abra o arquivo Ethernet.c e insira o cdigo abaixo.


Ethernet.c
Este arquivo tambm foi includo como anexo no documento em PDF.
#include "Ethernet/Ethernet.h"
#include "Ethernet/Servidor.h"
/* StellarisWare includes */
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ethernet.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/ethernet.h"
#include "driverlib/flash.h"
/* FreeRTOS includes */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* LwIP includes */
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#include "ipv4/lwip/ip_addr.h"
#include "netif/stellarisif.h"
static void EthernetInitCallback(void * param);
static xSemaphoreHandle EthernetISRSemaphore;
/*
* Tarefa que l os pacotes do controlador ethernet e os transmite a tarefa
* que gerencia a pilha TCP/IP.
*/
void EthernetInterruptTask(void *pvArg) {
while(1){
/* Aguarda rotina de interrupo indicar que pacotes foram recebido. */
while(xSemaphoreTake(EthernetISRSemaphore, portMAX_DELAY) != pdPASS);
/* Processa pacotes pendentes. */
stellarisif_interrupt(pvArg);
/* Rehabilita interrupo. */
EthernetIntEnable(ETH_BASE, ETH_INT_RX | ETH_INT_TX);
}
}
/*
* Rotina de tratamento de interrupes da interface ethernet.
*/
void EthernetISR(void) {
long activeInterrupts, higherPriorityTaskWoken;
/* Apaga interrupo. */
activeInterrupts = EthernetIntStatus(ETH_BASE, false);
EthernetIntClear(ETH_BASE, activeInterrupts);
/* Informa tarefa de interrupo que dados foram recebidos. */

61

xSemaphoreGiveFromISR(EthernetISRSemaphore, &higherPriorityTaskWoken);
/* Desabilita temporariamente as interrupes da ethernet. Quando
* dados forem passados adiante pela tarefa de interrupo, as
* interrupes sero rehabilitadas. */
EthernetIntDisable(ETH_BASE, ETH_INT_RX | ETH_INT_TX);
/* Caso alguma tarefa tenha acordado com a liberao do semforo,
* executa chaveamento de tarefas. */
if (higherPriorityTaskWoken) vPortYieldFromISR();
}
/*
* Inicializa interface ethernet.
*/
void EthernetInicializa(void){
unsigned long UserRegister0, UserRegister1;
unsigned char MACAddress[8];
// Habilita e reseta o controlador Ethernet.
SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);
SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);
// Habilita LEDs para ETHERNET.
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3);
// Endeo MAC obtido do registrador do usurio.
FlashUserGet(&UserRegister0, &UserRegister1);
MACAddress[0] = ((UserRegister0 >> 0) & 0xff);
MACAddress[1] = ((UserRegister0 >> 8) & 0xff);
MACAddress[2] = ((UserRegister0 >> 16) & 0xff);
MACAddress[3] = ((UserRegister1 >> 0) & 0xff);
MACAddress[4] = ((UserRegister1 >> 8) & 0xff);
MACAddress[5] = ((UserRegister1 >> 16) & 0xff);
// Grava o endereo MAC no controlador Ethernet.
EthernetMACAddrSet(ETH_BASE, (unsigned char *)MACAddress);
/* Inicializa a pilha TCP, cria tarefa que gerencia a pilha e define
* callback para finalizao da inicializao da interface Ethernet.
* A funo de callback ser chamada de dentro do contexto da tarefa
* do LwIP quando o escalonador estiver rodando. */
tcpip_init(EthernetInitCallback, NULL);
/* Cria a tarefa que controlar o servidor TCP */
xTaskCreate(ServidorTask, ( signed portCHAR * ) "ServidorTCP",
SERVIDOR_STACK_SIZE, NULL, SERVIDOR_TASK_PRIORITY, NULL);
}
/*
* Termina a inicializao da interface Ethernet.
*/
static void EthernetInitCallback(void * param) {
struct ip_addr IPAddress, NetMask, GatewayAddress;
static struct netif NetworkInterfaceDescriptor;
extern err_t stellarisif_init(struct netif *netif);
/* Cria semforo para sincronismo do acesso ao controlador ethernet. */

62

sys_sem_new(&EthernetISRSemaphore, 1);
/* Cria tarefa que trata as interrupes da interface ethernet.
* Essa tarefa armazena os dados recebidos e os transmite para a
* tarefa que gerencia a pilha. */
xTaskCreate(EthernetInterruptTask, (signed portCHAR *)"eth_int",
ETHERNET_ISRTHREAD_STACKSIZE, &NetworkInterfaceDescriptor,
ETHERNET_ISRTHREAD_PRIO, 0);
/* Inicializa structs de endereo IP, Mscara de sub-rede e Gateway. */
IP4_ADDR(&IPAddress, ETHERNET_IPADDR0, ETHERNET_IPADDR1, ETHERNET_IPADDR2,
ETHERNET_IPADDR3);
IP4_ADDR(&GatewayAddress, ETHERNET_GATEWAY_ADDR0, ETHERNET_GATEWAY_ADDR1,
ETHERNET_GATEWAY_ADDR2, ETHERNET_GATEWAY_ADDR3);
IP4_ADDR(&NetMask, ETHERNET_NET_MASK0, ETHERNET_NET_MASK1,
ETHERNET_NET_MASK2, ETHERNET_NET_MASK3);
/* Inicializa interface de rede. */
netif_add(&NetworkInterfaceDescriptor, &IPAddress, &NetMask,
&GatewayAddress, NULL, stellarisif_init, tcpip_input);
/* Configura interface como padro. */
netif_set_default(&NetworkInterfaceDescriptor);
/* Inicia interface. */
netif_set_up(&NetworkInterfaceDescriptor);
}

Neste arquivo esto definidas quatro funes:


EthernetISR(): rotina de interrupo da interface ethernet. Esta funo fornece
um semforo para a tarefa de interrupo da ethernet, indicando que pacotes foram
recebidos pela interface.
EthernetInterruptTask(): tarefa de interrupo da ethernet. Esta tarefa fica
inativa at que a rotina de interrupo fornea um semforo. Quando isso ocorre, ela
esvazia os buffers da interface ethernet e envia os dados para a tarefa da pilha tcpip.
EthernetInicializa(): funo que inicializa a interface ethernet, a pilha tcpip e
cria a tarefa do servidor. Na chamada da funo tcpip_init(), criada a tarefa
principal da pilha tcpip. Nesse momento, tambm passado um ponteiro para a
funo EthernetInitCallback(), que ser chamada posteriormente de dentro do

63

contexto da tarefa tcpip. Na ltima linha da funo criada a tarefa que controla o
servidor, onde deve estar o cdigo do usurio, que efetivamente utilizar a interface
ethernet.
EthernetInitCallback(): Funo que ser chamada de dentro da tarefa principal
da pilha tcpip para finalizao das configuraes. Aqui ser criada a tarefa de
interrupo da ethernet, bem como o semforo utilizado nas interrupes.
No arquivo Ethernet.h, insira as seguintes definies:
Ethernet.h
Este arquivo tambm foi includo como anexo no documento em PDF.
/* Tamanho da pilha da tarefa que recebe os
* dados da ISR. */
#define ETHERNET_ISRTHREAD_STACKSIZE 256
/* Prioridade da tarefa que recebe os dados
* da ISR. */
#define ETHERNET_ISRTHREAD_PRIO 3
/* The IP address being used. */
#define ETHERNET_IPADDR0
#define ETHERNET_IPADDR1
#define ETHERNET_IPADDR2
#define ETHERNET_IPADDR3

172
17
5
150

/* The gateway address being used. */


#define ETHERNET_GATEWAY_ADDR0
#define ETHERNET_GATEWAY_ADDR1
#define ETHERNET_GATEWAY_ADDR2
#define ETHERNET_GATEWAY_ADDR3

172
17
5
194

/* The network mask being used. */


#define ETHERNET_NET_MASK0
#define ETHERNET_NET_MASK1
#define ETHERNET_NET_MASK2
#define ETHERNET_NET_MASK3

255
255
255
0

void EthernetInicializa(void);

Neste arquivo, no se esquea de inserir o gateway e a mscara da sua rede.


Estes endereos podem ser encontrados com o comando ipconfig, no terminal do
windows. Escolha tambm um endereo IP que esteja livre e faa parte da mesma

64

faixa de endereos da sua rede. No terminal do windows, certifique-se de que o IP est


livre por meio do comando ping.
No arquivo Servidor.c, ser escrito o cdigo da tarefa que far com que o
estado dos LEDs seja alterado sempre que algum browser tentar se conectar ao
microcontrolador. Copie os comandos a seguir:
Servidor.c
Este arquivo tambm foi includo como anexo no documento em PDF.
#include "Ethernet/Servidor.h"
/* StellarisWare includes */
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
/* FreeRTOS includes */
#include "FreeRTOS.h"
#include "task.h"
/* LwIP includes */
#include "lwip/api.h"
void ServidorTrataConexao(struct netconn *Conexao){
extern unsigned char ledLigado;
struct netbuf *NetconnBuffer;
char *DadosBufferRx;
unsigned short NumBytesRecebidos;
/* Recebe buffer de dados. */
netconn_recv(Conexao, &NetconnBuffer);
/* Caso haja sucesso na leitura do buffer de dados recebido: */
if (netbuf_data( NetconnBuffer, (void*)&DadosBufferRx, &NumBytesRecebidos)
== ERR_OK){
/* Atualiza LED. */
if (ledLigado){
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
ledLigado = false;
} else {
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
ledLigado = true;
}
}
/* Deleta buffer. */
netbuf_delete(NetconnBuffer);
/* Fecha conexo. */
netconn_close(Conexao);
}
/* Tarefa do servidor TCP */
void ServidorTask(void* Parametros){

65

struct netconn *Servidor, *Conexao;


/* Cria varivel que representa o servidor TCP/IP. */
Servidor = netconn_new(0x10);
/* Liga o servidor porta 3082 e ao IP da interface. */
netconn_bind(Servidor, NULL, SERVIDOR_PORTA);
/* Coloca servidor em modo de espera. */
netconn_listen( Servidor );
while(1){
/* Aguarda conexo. */
netconn_accept(Servidor, &Conexao);
if( Conexao != NULL ){
/* Trata conexo. */
ServidorTrataConexao(Conexao);
/* Deleta conexo. */
while( netconn_delete(Conexao) != ERR_OK ){
vTaskDelay(10);
}
}
}
}

Na funo ServidorTask(), inicialmente criado um servidor que fica


aguardando conexes. Ento, sempre que algum cliente se conecta ao servidor,
executada a funo ServidorTrataConexao(), que atualiza o estado dos LEDs. Aps
isso, a conexo fechada e aguardada uma nova conexo.
Caso se desejasse, na funo ServidorTrataConexao() poderiam ser
realizadas outras operaes, como ler algum dado enviado pelo cliente ou informar
alguma outra tarefa que uma conexo est aberta e dados podem ser enviados para o
cliente (uma tarefa que l e transmite dados de um AD, por exemplo).
Do modo como o programa est escrito apenas uma conexo tratada por
vez. Para tratamento de conexes simultneas seria necessria criao de uma nova
tarefa sempre que uma conexo aceita.
O arquivo Servidor.h tambm deve ser editado, com a adio do seguinte
texto:

66

Servidor.h
Este arquivo tambm foi includo como anexo no documento em PDF.
/* Tamanho da pilha da tarefa que controla o servidor TCP */
#define SERVIDOR_STACK_SIZE 256
/* Prioridade da tarefa que controla o servidor TCP */
#define SERVIDOR_TASK_PRIORITY 2
/* Porta utilizada pelo servidor TCP */
#define SERVIDOR_PORTA 80
/* Prottipos de funes. */
void ServidorTask(void* Parametros);

nesse arquivo de cabealho que foi definida a porta utilizada na conexo,


que nesse caso a porta 80.
Ainda so necessrias algumas alteraes no arquivo main.c. Comece por
excluir

varivel

global

xQueueHandle

filaInterfaceSerial

as

funes

ISRTimer() e TarefaSerial, que no sero mais utilizadas. A incluso do arquivo


de cabealho do timer tambm no mais necessria (#include driverlib/timer.h).
Agora,

no

incio

do

arquivo

adicione

diretiva

#include

Ethernet/Ethernet.h, para que a funo de inicializao da ethernet fique visvel.


Defina tambm a varivel global unsigned char ledLigado = true; e altere o cdigo
da funo main() para:
int main(){
/* Configura Clock para 50 MHz. */
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_8MHZ);
/* Configura LED */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
/* Inicializa a interface ethernet e cria tarefas da pilha TCP/IP.
* Sero criadas trs tarefas:
*
- tcpip_thread: Tarefa que controla a pilha TCP/IP.
*
- eth_int: Tarefa que recebe os dados e os envia para a
*
tarefa principal quando ocorrem interrupes da ethernet.
*
- ServidorTCP: Tarefa que atualiza os LEDs quando algum
*
cliente se conecta. */
EthernetInicializa();

67

/* Inicia escalonador do FreeRTOS. */


vTaskStartScheduler();
/* No deve chegar aqui. */
while(1);
}

Atualize tambm a funo vApplicationTickHook() com o cdigo a seguir:


void vApplicationTickHook( void )
{
static unsigned long Contador=0;
Contador++;
if(Contador == 3000){
if (ledLigado){
/* Desliga LED. */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
ledLigado = false;
} else {
/* Liga LED. */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
ledLigado = true;
}
Contador = 0;
}
}

Esta funo far com que o estado do LED se altere a cada trs segundos.
Assim, caso exista algum problema no programa e o sistema venha a travar, isso
ficar evidente para o usurio. Tanto a funo vApplicationTickHook() quanto a
funo de tratamento de conexes do servidor utilizam a varivel global ledLigado
para identificar o estado atual do LED. Isso no recomendado, pois as operaes
que acessam esta varivel, no servidor ethernet, no so atmicas. O ideal seria
proteger o acesso a varivel por meio de um semforo, o que no foi feito para
simplificar o cdigo.
A verso final do arquivo main.c se encontra no APNDICE E e tambm
foi includo como anexo a este PDF.

68

Agora compile o programa, grave o microcontrolador e pressione o boto de


reset. O estado do LED dever mudar a cada trs segundos. Abra um navegador e
tente acessar o endereo IP do microcontrolador. A cada tentativa o estado do LED
dever ser alterado, embora o navegador diga que a pgina no existe.

69

REFERNCIAS

1 THE ODEV IDEA. Disponvel em


<http://www.stf12.org/developers/ODeV.html>. Acesso em 09 jul. 2012.

2 OUT-OF-PLANE LABS. Disponvel em <http://outofplanelabs.com/tutorials>.


Acesso em 09 jul. 2012.

3 FREE RTOS. Memory Management. Disponvel em


<http://www.freertos.org/a00111.html>. Acesso em 09 jul. 2012.

4 FREE RTOS. Customisation. Disponvel em


<http://www.freertos.org/a00110.html>. Acesso em 09 jul. 2012.

5 FREE RTOS. Stack Overflow Protection. Disponvel em


<http://www.freertos.org/Stacks-and-stack-overflow-checking.html>. Acesso em 09
jul. 2012.

6 LWIP WIKI. Porting for an OS. Disponvel em


<http://lwip.wikia.com/wiki/Porting_for_an_OS >. Acesso em 09 jul. 2012.

70

APNDICE A - Listagem de cdigo do arquivo main.c criado no exemplo do


FreeRTOS

71

main.c
Este arquivo tambm foi includo como anexo no documento em PDF com o nome
FreeRTOSmain.c.
/*
* main.c
*
* Created on: 06/06/2012
*
Author: Mr. Burns
*/
/* Stellaris Includes */
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "utils/uartstdio.h"
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "task.h"
#include "queue.h"

xQueueHandle filaInterfaceSerial;
void ISRTimer(void){
/* Varivel para contagem dos segundos decorridos */
static unsigned long segundos=0;
/* Flag que informa se alguma tarefa de prioridade mais alta que aguardava
mensagens
* foi desbloqueada com o envio da mensagem. Neste caso, esta varivel no
ser
* utilizada, mas poderia ser til para execuo de um chaveamento de
tarefas. */
long tarefaPrioritariaDespertada;
/* Apaga interrupo do timer. O ideal que isso seja a primeira coisa a
ser feita.*/
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
segundos++; /* Incrementa tempo */
/* Envia mensagem, informando tarefa da serial que se passou um segundo. */
xQueueSendToBackFromISR(filaInterfaceSerial, &segundos,
&tarefaPrioritariaDespertada);
}
void TarefaSerial(void *pvParameters)
{
unsigned short segundos;
unsigned char flagLEDLigado = false;
/* Habilita drivers do GPIO F (utilizado pelo LED). */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

72

/* Configura o port F0 como sada para o LED. */


GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
/* Habilita drivers do GPIO A (utilizado pela serial). */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
/* Configura ports F0 e F1 para uso com a serial. */
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
/* Inicializa a serial que ligada ao controlador USB. */
UARTStdioInit(0);
/* Habilita timer */
TimerEnable(TIMER0_BASE, TIMER_A);
for( ;; )
{
/* Aguarda mensagem da rotina de interrupo do timer. */
xQueueReceive( filaInterfaceSerial, &segundos, portMAX_DELAY );
/* Transmite tempo pela serial. */
UARTprintf("\%u segundos.\n", segundos);
/* Atualiza LED. */
if (flagLEDLigado == false){
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
flagLEDLigado = true;
} else {
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
flagLEDLigado = false;
}
}
}
int main(){
/* Configura Clock para 50 MHz. */
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_8MHZ);
/* Habilita drivers do Timer. */
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
/* Configura timer para modo peridico de 32 bits. */
TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
/* Configura timer para frequncia de 1 Hz. */
TimerLoadSet(TIMER0_BASE, TIMER_A, 50000000);
/* Configura prioridade da interrupo do timer. */
IntPrioritySet(INT_TIMER0A, configMAX_SYSCALL_INTERRUPT_PRIORITY);
/* Habilita interruo do timer. */
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
IntEnable(INT_TIMER0A);
/* Inicializa fila da interface serial. */
filaInterfaceSerial = xQueueCreate( 2, sizeof( unsigned long ) );
/* Cria tarefa da interface serial. */
xTaskCreate( TarefaSerial, (signed portCHAR*)"UART",
configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
/* Inicia escalonador do FreeRTOS. */
vTaskStartScheduler();
/* No deve chegar aqui. */

73

while(1);
}
void vApplicationTickHook( void )
{
}
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR
*pcTaskName )
{
for( ;; );
}

74

APNDICE B - Listagem de cdigo do arquivo sys_arch.c utilizado na configurao


do LwIP

75

sys_arch.c
Este arquivo tambm foi includo como anexo no documento em PDF.
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Modifications Copyright (c) 2006 Christian Walter <wolti@sil.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
*
this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*
this list of conditions and the following disclaimer in the documentation
*
and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
*
derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/**
* This file is derived from the file provided by the FreeRTOS lwip_MCF5235_GCC
demo.
*/
/* Standart includes */
#include <stdio.h>
/* lwIP includes. */
#include "lwip/opt.h"
#include "lwip/sys.h"
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* Structure needed for the creation of a linked list that
* holds the handles for all the tasks created by LwIP. */
typedef struct sys_tcb {

76

struct sys_tcb *next;


xTaskHandle
pid;
} sys_tcb_t;
/* Pointer to the start of the tasks list. */
static sys_tcb_t *tasks = NULL;
/**
* Initializes the system architecture layer.
*/
void sys_init(void) {
LWIP_ASSERT( "sys_init: not called first", tasks == NULL );
tasks = NULL;
}
/**
* Creates a new semaphore.
*
* @param newSemaphore is a pointer to the handle of the semaphore to be created.
* @param count is non-zero if the semaphore should be acquired initially.
* @return ERR_OK or ERR_MEM.
*/
err_t sys_sem_new(sys_sem_t* newSemaphore, u8_t count) {
xSemaphoreHandle xSemaphore;
vSemaphoreCreateBinary( xSemaphore );
if( xSemaphore != SYS_SEM_NULL ) {
if( count == 0 ) {
xSemaphoreTake( xSemaphore, 1 );
}
#if SYS_STATS
vPortEnterCritical();
lwip_stats.sys.sem.used++;
if( lwip_stats.sys.sem.used > lwip_stats.sys.sem.max ) {
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
}
vPortExitCritical();
#endif
} else {
LWIP_ASSERT( "sys_sem_new: xSemaphore == SYS_SEM_NULL", xSemaphore !=
SYS_SEM_NULL );
return ERR_MEM;
}
*newSemaphore = xSemaphore;
return ERR_OK;
}
/**
* Signal a semaphore.
*
* @param sem is a pointer to the semaphore to signal.
*/
void sys_sem_signal(sys_sem_t* sem) {
LWIP_ASSERT( "sys_sem_signal: sem != SYS_SEM_NULL", *sem != SYS_SEM_NULL );
xSemaphoreGive( *sem );
}
/**

77

* Wait for a semaphore to be signaled.


*
* @param sem is a pointer to the semaphore.
* @param timeout is the maximum number of milliseconds to wait for the
*
semaphore to be signaled.
* @return the number of milliseconds that passed before the semaphore was
*
acquired, or SYS_ARCH_TIMEOUT if the timeout occurred.
*/
u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout) {
portTickType starttime;
LWIP_ASSERT( "sys_arch_sem_wait: sem != SYS_SEM_NULL", *sem != SYS_SEM_NULL
);
/* Get the starting time. */
starttime = xTaskGetTickCount();
/* See if there is a timeout. */
if(timeout != 0) {
/* Send a message to the queue. */
if(xSemaphoreTake(*sem, timeout / portTICK_RATE_MS) == pdPASS) {
/* Return the amount of time it took for the semaphore to be
signalled. */
return (xTaskGetTickCount() - starttime) * portTICK_RATE_MS;
} else {
/* The semaphore failed to signal in the allotted time. */
return SYS_ARCH_TIMEOUT;
}
} else {
/* Try to send a message to the queue until it succeeds. */
while(xSemaphoreTake(*sem, portMAX_DELAY) != pdPASS);
/* Return the amount of time it took for the semaphore to be
signalled. */
return (xTaskGetTickCount() - starttime) * portTICK_RATE_MS;
}
}
/**
* Destroys a semaphore.
*
* @param sem is a pointer to the semaphore to be destroyed.
*/
void sys_sem_free(sys_sem_t* sem) {
LWIP_ASSERT( "sys_sem_free: sem != SYS_SEM_NULL", *sem != NULL );
if( *sem != SYS_SEM_NULL ) {
#if SYS_STATS
vPortEnterCritical();
lwip_stats.sys.sem.used--;
vPortExitCritical();
#endif
vQueueDelete( *sem );
}
}
/**
* Creates a new mailbox.
*
* @param newMbox is a pointer to the handle of the mailbox to be created.

78

* @param size is the number of entries in the mailbox.


* @return ERR_OK or ERR_MEM.
*/
err_t sys_mbox_new(sys_mbox_t* newMbox, int size) {
xQueueHandle mbox;
LWIP_ASSERT( "sys_mbox_new: size != 0", size != 0 );
mbox = xQueueCreate( size, sizeof( void * ) );
if( mbox != SYS_MBOX_NULL ) {
#if SYS_STATS
vPortEnterCritical();
lwip_stats.sys.mbox.used++;
if( lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max ) {
lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
}
vPortExitCritical();
#endif
} else {
return ERR_MEM;
}
*newMbox = mbox;
return ERR_OK;
}
/**
* Sends a message to a mailbox.
*
* @param mbox is a pointer to the mailbox.
* @param msg is the message to send.
*/
void sys_mbox_post(sys_mbox_t* mbox, void *msg) {
/* Send this message to the queue. */
while(xQueueSend(*mbox, &msg, portMAX_DELAY) != pdPASS);
}
/**
* Tries to send a message to a mailbox.
*
* @param mbox is a pointer to the mailbox.
* @param msg is the message to send.
* @return ERR_OK if or ERR_MEM.
*/
err_t sys_mbox_trypost(sys_mbox_t* mbox, void *msg){
/* Send this message to the queue. */
if(xQueueSend(*mbox, &msg, 0) == pdPASS) {
return ERR_OK;
}
/* Update the mailbox statistics. */
#if SYS_STATS
STATS_INC(sys.mbox.err);
#endif /* SYS_STATS */
/* The message could not be sent. */
return ERR_MEM;
}
/**

79

* Retrieve a message from a mailbox.


*
* @param mbox is a pointer to the mailbox.
* @param msg is a pointer to the location to receive the message.
* @param timeout is the maximum number of milliseconds to wait for the message.
* @return the number of milliseconds that passed before the message was
*
received, or SYS_ARCH_TIMEOUT if the tmieout occurred.
*/
u32_t sys_arch_mbox_fetch(sys_mbox_t* mbox, void **msg, u32_t timeout) {
portTickType starttime;
void *dummyptr;
LWIP_ASSERT( "sys_arch_mbox_fetch: mbox != SYS_MBOX_NULL", *mbox !=
SYS_MBOX_NULL );
/* If the actual message contents are not required, provide a local variable
to receive the message. */
if(msg == NULL) {
msg = &dummyptr;
}
/* Get the starting time. */
starttime = xTaskGetTickCount();
/* See if there is a timeout. */
if(timeout != 0) {
/* Receive a message from the queue. */
if(xQueueReceive(*mbox, msg, timeout / portTICK_RATE_MS) == pdPASS) {
/* Return the amount of time it took for the message to be
received. */
return (xTaskGetTickCount() - starttime) * portTICK_RATE_MS;
} else {
/* No message arrived in the allocated time. */
*msg = NULL;
return SYS_ARCH_TIMEOUT;
}
} else {
/* Try to receive a message until one arrives. */
while(xQueueReceive(*mbox, msg, portMAX_DELAY) != pdPASS);
/* Return the amount of time it took for the message to be received.
*/
return (xTaskGetTickCount() - starttime) * portTICK_RATE_MS;
}
}
/**
* Try to receive a message from a mailbox, returning immediately if one is not
* available.
*
* @param mbox is a pointer to the mailbox.
* @param msg is a pointer to the location to receive the message.
* @return ERR_OK if a message was available and SYS_MBOX_EMPTY if one was not
*
available.
*/
u32_t sys_arch_mbox_tryfetch(sys_mbox_t* mbox, void **msg){
void *dummyptr;
/* If the actual message contents are not required, provide a local variable

80

to receive the message. */


if(msg == NULL) {
msg = &dummyptr;
}
/* Receive a message from the queue. */
if(xQueueReceive(*mbox, msg, 0) == pdPASS) {
/* A message was available. */
return ERR_OK;
} else {
/* A message was not available. */
return SYS_MBOX_EMPTY;
}
}
/**
* Destroys a mailbox.
*
* @param mbox is the mailbox to be destroyed.
*/
void sys_mbox_free(sys_mbox_t* mbox) {
void *msg;
LWIP_ASSERT( "sys_mbox_free: mbox != SYS_MBOX_NULL", *mbox != SYS_MBOX_NULL
);
if( *mbox != SYS_MBOX_NULL ) {
while( uxQueueMessagesWaiting( *mbox ) != 0 ) {
if( sys_arch_mbox_fetch( *mbox, &msg, 1 ) != SYS_ARCH_TIMEOUT )
{
LWIP_ASSERT( "sys_mbox_free: memory leak (msg != NULL)",
msg == NULL );
}
}
vQueueDelete( *mbox );
#if SYS_STATS
vPortEnterCritical();
lwip_stats.sys.mbox.used--;
vPortExitCritical();
#endif
}
}
/**
* Creates a new thread.
*
* @param name is the name of this thread.
* @param thread is a pointer to the function to run in the new thread.
* @param arg is the argument to pass to the thread's function.
* @param stacksize is the size of the stack to allocate for this thread.
* @param prio is the priority of the new thread.
* @return the handle for the created thread.
*/
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg,
int stacksize, int prio){
sys_thread_t thread_hdl = SYS_THREAD_NULL;
int i;
sys_tcb_t *p;
char thread_name[ configMAX_TASK_NAME_LEN ];

81

/* We disable the FreeRTOS scheduler because it might be the case that the new
* tasks gets scheduled inside the xTaskCreate function. To prevent this we
* disable the scheduling. Note that this can happen although we have
interrupts
* disabled because xTaskCreate contains a call to taskYIELD( ).
*/
vPortEnterCritical();
p = tasks;
i = 0;
/* We are called the first time. Initialize it. */
if( p == NULL ){
p = pvPortMalloc( sizeof( sys_tcb_t ) );
if( p != NULL ){
tasks = p;
}
} else {
/* First task already counter. */
i++;
/* Cycle to the end of the list. */
while( p->next != NULL ){
i++;
p = p->next;
}
p->next = pvPortMalloc( sizeof( sys_tcb_t ) );
p = p->next;
}
if( p != NULL ){
/* Memory allocated. Initialize the data structure. */
p->next = NULL;
p->pid = ( xTaskHandle )0;
( void )snprintf( thread_name, configMAX_TASK_NAME_LEN, "lwIP%d", i );
/* Now q points to a free element in the list. */
if( xTaskCreate(thread, (signed char*)thread_name, stacksize, arg, prio,
&p->pid ) == pdPASS ){
thread_hdl = p;
}else{
vPortFree( p );
}
}
vPortExitCritical(
return thread_hdl;

);

}
/**
* Removes a thread.
*
* @param hdl is a handle for the thread to be removed.
*/
void sys_arch_thread_remove( sys_thread_t hdl ) {
sys_tcb_t
*current = tasks, *prev;
sys_tcb_t
*toremove = hdl;
xTaskHandle
pid = ( xTaskHandle ) 0;

82

LWIP_ASSERT( "sys_arch_thread_remove: assertion hdl != NULL failed!", hdl !=


NULL );
/* If we have to remove the first task we must update the global "tasks"
* variable. */
vPortEnterCritical();
if( hdl != NULL ){
prev = NULL;
while( ( current != NULL ) && ( current != toremove ) ){
prev = current;
current = current->next;
}
/* Found it. */
if( current == toremove ){
/* Not the first entry in the list. */
if( prev != NULL ){
prev->next = toremove->next;
} else {
tasks = toremove->next;
}
pid = toremove->pid;
toremove->next = NULL;
toremove->pid = ( xTaskHandle )0;
vPortFree( toremove );
}
}
/* We are done with accessing the shared datastructure. Release the
* resources.
*/
vPortExitCritical();
if( pid != ( xTaskHandle ) 0 ) {
vTaskDelete( pid );
/* not reached. */
}
}
/**
* Enters a critical section.
*
* @return the previous protection level.
*/
sys_prot_t sys_arch_protect(void) {
vPortEnterCritical();
return 1;
}
/**
* Leaves a critical section.
*
* @param the previous protection level.
*/
void sys_arch_unprotect(sys_prot_t val) {
vPortExitCritical();
}

83

APNDICE C - Listagem de cdigo do arquivo sys_arch.h utilizado na configurao


do LwIP

84

sys_arch.h
Este arquivo tambm foi includo como anexo no documento em PDF.
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
*
this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*
this list of conditions and the following disclaimer in the documentation
*
and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
*
derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __ARCH_SYS_ARCH_H__
#define __ARCH_SYS_ARCH_H__
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* NULL
#define
#define
#define

Handles. */
SYS_MBOX_NULL
SYS_THREAD_NULL
SYS_SEM_NULL

( xQueueHandle )0
NULL
( xSemaphoreHandle )0

/* Typedefs for the various port-specific types. */


typedef xSemaphoreHandle sys_sem_t;
typedef xQueueHandle sys_mbox_t;
typedef void
*sys_thread_t;
typedef u8_t sys_prot_t;
/* Macro to verify if a semaphore is allocated. */
#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL))
/* Macro to signal a semaphore as deallocated. */

85

#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL;


}}while(0)
/* Macro to verify if a message box is allocated. */
#define sys_mbox_valid(mbox) (*mbox != NULL)
/* Macro to signal a message box as deallocated. */
#define sys_mbox_set_invalid(mbox)
do {*(mbox) = NULL;}while(0)
#endif /* __ARCH_SYS_ARCH_H__ */

86

APNDICE D - Listagem de cdigo do arquivo cc.h utilizado na configurao do


LwIP

87

cc.h
Este arquivo tambm foi includo como anexo no documento em PDF.
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
*
this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*
this list of conditions and the following disclaimer in the documentation
*
and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
*
derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __CC_H__
#define __CC_H__
#ifdef DEBUG
#define U8_F "c"
#define S8_F "c"
#define X8_F "x"
#define U16_F "u"
#define S16_F "d"
#define X16_F "x"
#define U32_F "u"
#define S32_F "d"
#define X32_F "x"
#define STZ_F "uz"
#endif
typedef
typedef
typedef
typedef
typedef
typedef
typedef

unsigned
signed
unsigned
signed
unsigned
signed
u32_t

char
char
short
short
long
long

u8_t;
s8_t;
u16_t;
s16_t;
u32_t;
s32_t;
mem_ptr_t;

88

#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
/* Macro to display debug and trace messages. */
#ifndef LWIP_PLATFORM_DIAG
#include "utils/uartstdio.h"
#define LWIP_PLATFORM_DIAG(msg) UARTprintf msg;
#endif
/* Macro to display error message and call the error handler function. */
#ifndef LWIP_PLATFORM_ASSERT
#ifdef DEBUG
extern void __error__(char *pcFilename, unsigned long ulLine);
#define LWIP_PLATFORM_ASSERT(msg)
\
{
\
UARTprintf(msg);
\
__error__(__FILE__, __LINE__);
\
}
#else
#define LWIP_PLATFORM_ASSERT(msg)
#endif
#endif
#include <stdlib.h>
#define LWIP_RAND() ((u32_t)rand())
#endif /* __CC_H__ */

89

APNDICE E - Listagem de cdigo do arquivo main.h utilizado no exemplo do


LwIP

90

main.c
Este arquivo tambm foi includo como anexo no documento em PDF com o nome
LwIPmain.c.
/*
* main.c
*
* Created on: 06/06/2012
*
Author: Mr. Burns
*/
/* Stellaris Includes */
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "utils/uartstdio.h"
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "task.h"
#include "queue.h"
/* User includes. */
#include "Ethernet/Ethernet.h"
unsigned char ledLigado = true;
int main(){
/* Configura Clock para 50 MHz. */
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_8MHZ);
/* Configura LED */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
/* Inicializa a interface ethernet e cria tarefas da pilha TCP/IP.
* Sero criadas trs tarefas:
*
- tcpip_thread: Tarefa que controla a pilha TCP/IP.
*
- eth_int: Tarefa que recebe os dados e os envia para a
*
tarefa principal quando ocorrem interrupes da ethernet.
*
- ServidorTCP: Tarefa que atualiza os LEDs quando algum
*
cliente se conecta. */
EthernetInicializa();
/* Inicia escalonador do FreeRTOS. */
vTaskStartScheduler();
/* No deve chegar aqui. */
while(1);
}
void vApplicationTickHook( void )
{
static unsigned long Contador=0;

91

Contador++;
if(Contador == 3000){
if (ledLigado){
/* Desliga LED. */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
ledLigado = false;
} else {
/* Liga LED. */
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 1);
ledLigado = true;
}
Contador = 0;
}
}
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR
*pcTaskName )
{
for( ;; );
}

Você também pode gostar