Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Cparamicrocontroladores
HansJrgSchneebeli
Objetivo
Introduo
Devidoarestriesdecusto,tamanhoeconsumo,emsistemasembarcadosso
usados microcontroladores com pouca memria e baixa velocidade. Deve ser
notadoqueocustodeprogramaoumcustonorecorrente,equeocustode
um microcontrolador maior se refletir em um custo maior por cada unidade
fabricada. Alm disso, deve ser notado ainda que um tempo maior de
desenvolvimentoaumentaocustoediminuiotempodemercadodeumproduto.
Porfim,geralmente,existemrestriesdetempoderespostaqueexigemtcnicas
eficientesdeprogramao.
Alternativasparaprogramao
Entre as linguagens usadas ou projetadas para uso em sistemas embarcados,
destacamse:
Assemblypossibilitacdigomaiseficienteemtermosdevelocidadeeuso
dememria,masinerentementenoportveleexigetempomuitogrande
dedesenvolvimento.
Cpermitetempomenordedesenvolvimento,masexigeumadisciplinado
programador, similar a exigida em Assembly. No tem suporte direto a
concorrncia.
C++permiteousodetcnicasdeprogramaoorientadaaobjetos,mas
apresenta problemas de tamanho de memria e de velocidade. Para
diminuir estes problemas existe uma verso mais enxuta, chamada
1de17
Embedded C++, que impede o uso de mecanismos que aumentam
demasiadamente o consumo de memria, ou tornam o comportamento
temporaldificildeprever.Entreosmecanismosdescartadosestoherana
multipla,exceesetemplates.
Java embora tenha sido inicialmente planejada para sistemas
embarcados,ademandapormemriaexcessivaparaamaiorpartedas
aplicaes.Ofatodenoserocomportamentonotemponoserprevisvel
devidoaogarbagecollectorimpedeoseuusoemcertasaplicaes.
Ada foi desenvolvida especialmente para sistemas embarcados, tem
suporteembutidoaconcorrncia,existeumpadroparaalinguagem,mas
verbosaeocdigoresultantemaioremaislentodoqueogeradoporC.
Esterelrepresentaumaalternativainteressanteparaaprogramaode
sistemasreativos,comoocasodesistemasembarcados.
Outras Existem ainda linguagens como Forth e dialetos de Basic ou
Pascal,masousodestesmuitoraro.
Originalmente,ossistemasembarcadoseramdesenvolvidosemAssembly.Como
aumentodecomplexidadedestessistemaseapressoportemposmenoresde
desenvolvimento, o uso exclusivo de Assembly tem diminuido, e hoje alcana
apenas cerca de 8% dos projetos. Devido a facilidade de se construir um
compiladorC,eofato dequealinguagemimplementa um nveldeabstrao
bastante prximo ao hardware, a linguagem C representa um excelente
compromisso entre eficincia e facilidade de programao. Atualmente, a
absolutamaioria,cercade90%dossistemas,sodesenvolvidosemC/C++,as
vezes com alguma parte pequena em Assembly. O uso do Embedded C++
crescente mas ainda representa uma parte menor do uso do C. Finalmente o
restantefeitobasicamenteemJava,masdeseesperaroaumentodeseuuso,
principalmenteemsistemascomocelularesePDAs.
AlinguagemC
C foi desenvolvido por Richie e Kernighan na dcada de 70 para servir como
ferramentadeumsistemaoperacional,quemaistardepassouaserconhecido
comoLinux.Anfasefoiemdesempenhoeportabilidade.Ousuriotpicoseria
programador experiente, que necessitasse acessar recursos de hardware,
manipularbitsegerenciarmemria.
OUNIXfoiusadoemambientesuniversitriosnadcadade80.Pelofatodeum
compiladorCfazerpartedamaiorpartedasinstalaesUNIX,muitosoftwarefoi
escrito usando este compilador j disponvel. Alm disso, no final da dcada
passou a haver uma verso livre de um compilador C bastante eficiente
2de17
(chamandoGNUCC,oumaispopularmentegcc).AssimoCacabousendousado
no desenvolvimento de aplicaes fora de suas intenes originais. Isto por
exemplo,ocasodesoftwarematemticabaseadoemmanipulaodematrizes,
ondeosuportedalinguagemcatastrfico.
OresultadoquealinguagemCumadasmaisusadasatualmenteebase
para vrias outras linguagens como C++, Java e C#. No entanto, no
desenvolvimentodesistemasembarcadosqueso,pornatureza,maisprximos
as intenes originais da linguagem que ele mais usado, representado uma
alternativaaousodelinguagensdemontagem(assembly)comresultadosmuito
bons.Emboraumbomprogramadorusandoassemblypossagerarcdigomenor
e mais rpido que o gerado por um compilador C, atualmente a diferena em
desempenhoetamanhonorelevante.Nopiordoscasos,otrechocrticopode
serprogramadoemAssemblyeorestanteemC.
AdiferenadetamanhodecdigogeradoededesempenhodevidoaousodoCou
doassemblydependentedaarquiteturadomicroprocessadoralvo.Emalgumas
arquiteturas,comconjuntodeinstruesmaisadequados,adiferenapodeser
daordemde10%,emoutrasdeat300%.
OusodoCimplicananecessidadededisciplinaporpartedoprogramador.Dois
errossomuitocomuns:
Usarumareaquejfoiliberada(danglingpointers)
Usaralmdareaalocada(memoryoverflow)
Ascaractersticasprincipaisdalinguagemso:
Estruturasimplescompoucaspalavraschave.
Operaesdeentradaesadasofeitaspormeiodebiblioteca.
Flexibilidadedeimplementao.
Manuseiodememriapormeiodeapontadores.
Operadoresincrementoedecremento.
Portabilidade.
3de17
momento em que uma rotina chamada, suas variveis locais so alocadas.
Quandodesuaexecuo,diretamenteapenassuasvariveislocaiseasglobais
(definidasforadocontextodequalquerrotina)soacessveis.Quandoarotinase
encerra,aexecuocontinuanarotinaqueachamou,restaurandooacessoa
suasvariveislocais.
Figura:AchamaB,quechamaC
Paragarantiraportabilidade,aespecificaodetamanhodevariveisemC
extremamenteflexvel.Elaestabeleceapenasonmeromnimodebitsdecada
tipo,comomostradonatabelaabaixo.
TamanhosTipicosusadosemCompiladores
char 8 8 8 8 8 8
short 16 16 16 16 16 16
int 16 16 32 32 32 64
long 32 32 32 64 64 64
ponteiro 16 16 32 64 64 64
float 32 32 32 32 64 64
double* 32 32 32 64 64 64
Outrasreasquenosepodegarantirotipodeoperaodedeslocamentopara
adireita(serepeteounoobitdesinal)earepresentaodenmerosnegativos.
VersesdoC
KR Verso original. no havia checagem de parmetros (exceto por uma
ferramentaexternachamadalint).
C89 VersopadronizadapelaANSI.Bibliotecaspadronizadas.Sointroduzidos
prottiposderotinaseapalavrachavevoidindicaausnciadeparmetros
oudevalorderetorno.
C99 Tipospadrodetamanhodeterminado(stdint.h).Comentrioscom//.
4de17
UsoemMicrocontroladores
Emmuitasarquiteturasdemicroprocessadores,aspilhassoimplementadasde
maneiramuitoineficientee/ouapresentaolimitaessriasparaotamanho
oucontedo.Porexemplo,pilhasnoMicrochipPICpodemconteremalgunscaso,
soitoendereosderetorno.
MISRA
Cyclone
TiposdeDados
Ostipospadrodedadossoinadequadoparaousoemsistemasembarcados,
se houver necessidade de definio de tamanho. Existem ento algumas
alternativasparadefiniodevariveiscomtamanhoconhecido:
Padro(somenteC9X)
Usodepreprocessador
Usodedefiniodenovotipo
OpadroC9Xestabeleceumcabealhoquedefineumconjuntodetipospadro
comtamanhoprestabelecido.Aimplementaopodeserfeitapelocompilador
dediversasmaneiras,inclusiveusandosimplesmenteumadefinicodenovotipo.
Oarquivocabealhoostdint.hedefine,entreoutros,
5de17
BYTE Byte 8bits unsignedchar
POINTER Pointer 32bits
Existemduasmaneirasdedefinirestestipos:
Usandooprprocessador.
ouusandotypedef
Umavantagemdosegundoesquemaqueostiposdefinidossoconhecidospelo
compilador.Noesquemausandooprprocessador,todasasreferenciasaostipos
so substitudas pelos equivalentes antes que o compilador processe o cdigo
fonte.
Parasedescobrirascaractersticasimportantesdoprocessadoredocompilador,
veroapndiceA.
EntradaeSaida
O acesso a registradores de CPU, como apontador de pilha ou contador de
programa, em geral s necessrio, na inicializao. Durante a execuo, o
modelodeexecuodeCcontrolaestesregistradores.
Emboraarquiteturasmaismodernasno usemmaisinstruesespeciaispara
acessoahardware,aarquiteturadoIntel8086eseusderivadosusaestaforma.
Existem ento instrues especiais (no caso, IN e OUT) e um espao de
6de17
endereamentoseparadoparaosregistradoresdehardware.Externamente,deve
haverumpinoquesinalizequalaformadeendereamentousado.Adesvantagem
que este pino poderia ser usado para duplicar a quantidade de memria
endereavel.
ExistemvariaesparaacessoaregistradoresdotipoWORDcom16bits(inportw
e outportw). Alm disso, em muitos casos, por motivos de eficiencia podese
inserir diretamente o cdigo assembly na posio do chamado da rotina,
evitandoseocursodepassagemdeparametrosechamadoeretornodarotina.
Seocompiladoraceitarumaextensonopadrodeinserodecdigoassembly
nomeiodecdigoC,arotinaacimapodeserdefinida(preferencialmenteemum
arquivocabealho)atravsdasinstruesdeprprocessadorabaixo.
Atendnciaatualousodeendereosderegiesdememriaparaacessoao
registradoresdehardware.Avantagemquepodemserusadas asinstrues
normais de acesso a memria e a desvantagem, a diminuio da rea de
memriarealmenteutilizvel.
Omecanismobsicoousodeapontadores,comomostradoabaixo.
Nestecaso,umapontadorinicializadocomovalorinteiro.Ocast(BYTE*)s
usadoparaindicarocompilador,queopadrodebitsaseguir(uminteiro)seja
interpretadocomoumapontador.Aseguireleusadoparaumacessodeleitura
eoutrodeescrita.Comoobservao,'\x11'poderiaserescritotambm0x11,mas
7de17
algunscompiladores,usariamumainstruoparamanipulaodeinteirospara
manipulalo e usaria somente os bits menossignificativos para a operao de
escrita.
Istotudopodeserfeitoemumaunicainstruodeleituraeoutradeescrita.
BYTE b;
...
b = *((BYTE *) 0x876); // leitura
*((BYTE *) 0x876) = '\x12'; // escrita
...
Parafacilitaraindamais,podeserusadooprprocessadordefinindoumsimbolo
comonoexemploabaixo,quesemduvidabemmaislegivel.
Oconjuntodedefiniesdestetipopodesercolocadoemumarquivocabealho,
especificoparaummodelodeumaarquiteturacontendoasdefiniesdetodosos
registradoresdehardwaredodispositivo.Assim,temsecdigocomleituramais
facileaomesmotempo,umnomepadroparaseacessarestesregistradores.
Deveserlevadoemcontaqueocompiladornoesforodeotimizarocdigopode
prejudicar o funcionamento deste tipo de acesso. Isto acontece, por que o
compiladorassume,queoprogramaonicoresponsvelpelamodificaodos
valoresemmemriaeprocuramanterovaloremumregistradordeacessomais
rpido.Assimumaestruturadotipoabaixo,queesperaqueovalordaportaseja
zero
while ( PORTA != 0 ) {}
resulteemumcdigodotipo
MOVE 0x876,R0 ; move valor da memria para R0
LOOP: BNZ R0,LOOP ; testa se valor diferente de zero
; e repete o teste sem buscar
; o novo valor na memria
8de17
podeterovalormodificadoindependentedaaodoprograma.Istofeitocoma
palavrachavevolatile.Assim,definindosePORTAatravsdainstruoabaixo,
resolveseesteproblema.
#define PORTA *( (volatile BYTE *) 0x876)
ManipulaodeBits
Na programao de sistemas embarcados muito importante e freqente a
necessidadedesesetarumbit(fazloiguala1),resetarumbit(fazloiguala
0),complementarumbit(troclode1para0ouviceversa)efinalmentetestaro
valor.
O C padro no tem suporte para variveis tipo tipo booleano (embora C9X
especifique variveis tipo bool_t, que podem assumir os valores false e true,
atravsdeumarquivocabealhostdbool.h).
Tambm no tem suporte para a definio de constantes inteiras em formato
binrio.comum,noentanto,quecompiladoresimplementemcomoextenso,
constantesdotipo0b0101ou0B0111,valendo5e7respectivamente.Ocorreto
usar a representao decimal (5 ou 7) para valores de contadores e a
representaohexadecimal(0x05ou0x07ouainda,emcasodebytes,'\x05'ou
'\x07'),paraamanipulaodebits.
Usandostructs
Umadasmaneirasmaisfceisparaacessarbitsusandoofatopoucoconhecido
decampodebitsemestruturas.Porexemplo,adeclaraoabaixo,especificaos
bitsdeumtipobyte.
typedef struct {
unsigned bit7 : 1;
unsigned bit6 : 1;
unsigned bit5 : 1;
unsigned bit4 : 1;
unsigned bit3 : 1;
unsigned bit2 : 1;
unsigned bit1 : 1;
unsigned bit0 : 1;
} Port;
UmavariveldotipoBytepodeserdefinidaatravsde
Port x;
eosbitsindividuaisatravsde
x.bit4 = 1;
9de17
x.bit2 = 0;
x.bit1 = ~x.bit1;
if( x.bit3 ) ....
Deve ser chamada a ateno para o fato que o tamanho da tipo de dado,
sizeof(Port),acimanoprecisaserexatamenteumbyte.Emboraistosejacomum
emcompiladoresparamicrocontroladores,EmcompiladoresparaPCusualque
otamanhodaestruturasejaigualaodeuminteiro,isto,sizeof(byte)iguala
sizeof(int).
Umcompiladordeboaqualidadeusarasinstruesdemanipulaodebitsdo
processador,seesteastiver.Emoutroscasos,asinstruesusaroasoperaes
bitabitquesodescritasaseguir.
Umdosproblemasquenosepodeacessartodososbitsembloco,oquepode
resultaremcdigoineficiente.Paraisto,usaseumaconstruoobscuradoC
quedefinedoistiposdedadosocupandoamesmaregiodememria.
typedef union {
BYTE val;
struct {
unsigned bit7 : 1;
unsigned bit6 : 1;
unsigned bit5 : 1;
unsigned bit4 : 1;
unsigned bit3 : 1;
unsigned bit2 : 1;
unsigned bit1 : 1;
unsigned bit0 : 1;
};
} Port;
Assimpossvelseacessarosbitsdeformaindividualoutodooregistradorcomo
mostradoabaixo.
Port PORTA;
...
PORTA.bit7 = 1;
if ( PORTA.bit5 ) {
....
}
...
PORTA.val = 0;
...
Usandooperaesbitabit
Paraamanipulaodebitemvariveisinteiraspodemserusadasasoperaes
10de17
Operao OperadorC
E &
OU |
OUExclusivo ^
Negao ~
EstesnodevemserconfundidoscomosoperadoreslgicosE(&&),OU(||)ede
negao(!),queretornamovalor0ou1.
Parasesetarumbitemumavariveldeveseusarumamascara,quetemtodos
osbitszero,excetoobitnaposiodesejada.Porexemplo,parasesetarobit2
devese usar a mascara 000000100, que em C, representada por 0x04 em
formatohexadecimal,4(formatodecimal)ou04(formatooctal).Aoperao
x=x|0x4;
oumelhor
x|=0x4;
setaobit2dointeirodotipochar,short,intoulong.
Problemascomacessocompartilhado
Domesmomodoqueosvalorespresentesemumaportadeummicrocontrolador
podem variar, valores de uma varivel podem variar em funo de outros
processos ou de interrupo. A linguagem C no tem suporte direto a
concorrncia.Istoexigequeoprogramadortenhaclaroosperigosenvolvidos.
ProcessosconcorrentessoimplementadosemCatravsdebibliotecas.
Interrupes
Noexisteumamaneirapadrodesedefinirrotinasdeinterrupo.Emborauma
rotina de interrupo seja semelhante a um rotina normal que no retorne
nenhum valor e tambm no receba nenhum parmetro (com o prottipo void
intproc(void)),elaapresentacaractersticasespecificas:
11de17
Ocomandoderetornodeumarotinadeinterruponoidnticoaodo
retornodeumarotinacomum.
A rotina de interrupo deve restaurar todos os registradores, mas as
rotinascomunspodem,emmuitossistemas,modificaralgunsregistradores
(chamados registrados de rascunho (scratch registers), sem que seja
necessriorestaurlos.
Portanto,ocompiladordeveterainformaoseumarotinaparatratamentode
interrupoparagerarocdigocorreto.Amaneiratradicionalousodapalavra
chave interrupt (em alguns casos, __interrupt, pois simbolos iniciados com
sublinhado so de uso exclusivo da implementao). Assim uma rotina de
interruposeriadescritacomo
interrupt void intproc(void) {
...
}
Amaneiramaismoderna,compativelcomopadro,ousodocomandopragma
parapassarestainformao.Assimarotinaacimaseriadescritacomo
#pragma interrupt
void intproc(void) {
...
}
Emgeral,existeumarotinadotiposetintproc,quemodificaumaposiodovetor
de interrupo para que aponte para a rotina especificada. Ela retorna um
apontadorparaarotinaqueestavaencarregadadainterrupo,Existemduas
maneiras de se definir esta rotina, uma usando typedef, que a forma mais
legvel,comomostradoabaixo.
12de17
pfunc setintproc(int level,pfunc f) {
...
}
Aoutramaneiradefineamesmafunodeformadireta,semauxiliodeumtipo
dedados,quefazcomquefiquemenoslegvel.
void (*setintproc(int level, void (*f)(void) ))(void) {
...
}
int main(void) {
void (*oldfunc)(void); // poderia ser pfunc oldfunc;
...
oldfunc = setintproc(10,func);
...
}
Deve ser observado que a notao pfunc oldfunc pode ser usada com a
definiodiretaeviceversa.Aindadeveserobservadoquepodesernecessrio,
emboranosejacomum,queaespecificaodarotinaincluaapalavrachave
interrupt.
Mapeamentodememria
ProgramasemC,umavezcompilados,possuemdiversostiposdesegmentospara
osvriostiposdeinformaonecessriosemumcdigoobjeto.
Cdigo
Constantes
Dadosinicializados
Dadosnoinicializados
Pilha
Em principio, o cdigo objeto relocvel, isto , pode ser adaptado para ser
13de17
executadoemqualquerendereodememria.Atarefadoligadorjuntarestes
cdigos objeto, coloclos nas posies adequadas de memria e acertar as
referncias. O acertar de referncias mencionado ajustar uma instruo de
chamadoderotinaparaquetenhaoendereocorretodopontodeentrada.Istos
podeserfeito,depoisdomapeamentodosdiversossegmentosdoscdigosobjeto
nas regies de memria adequadas. O procedimento bsico concatenar os
segmentos de diversos tipos separadamente. Por exemplo, todos os segmentos
cdigosoconcatenadosgerandoosegmentocdigodomduloexecutvel.
Emtermosdehardware,osmicrocontroladorestemumaregiodememriano
volatil(ROM)eumadememriavoltil(RAM).Emalgunscasos,estasnoso
contguas.
Figura
Oproblemadealinhamento
Alocaodinmicadememria
14de17
Interfacecomassembly
Referencias
Kernighan,Richie.TheCProgrammingLanguage.
Jack Ganssle. Microcontroller C Compilers. Electronic Engineering Times,
November1990.
JackGanssle.MylovehaterelationshipwithC.Embedded.com.10/16/03.
Wikipedia.LinguagemdeprogramaoC.
JamesACJoyce. Why C Is Not My Favourite Programming Language.
http://www.kuro5hin.org/print/2004/2/7/144019/8872
Harsha S. Adiga. Porting Linux applications to 64bit systems.http://www
128.ibm.com/developerworks/linux/library/lport64.html.12Apr2006.
MISRA. Guidelines for the use of the C language in critical systems.
http://www.misrac2.com/
The Open Group. 64Bit Programming Models: Why LP64?.
http://www.unix.org/version2/whatsnew/lp64_wp.html.
15de17
ApndiceA
/*
* imprime tamanhos de tipos de variaveis em C
*
* Hans 2006
*/
#include <stdio.h>
b = 1;
c = 0;
while( b ) {
b <<= 1;
c++;
}
printf("Caracteristicas do processador\n");
printf ("Tamanho de um Byte .. %3d bits\n\n",c);
if( *((unsigned char *) &s) == 0x12 ) {
printf("Big Endian (Byte MAIS significativo primeiro)\n");
} else if( *((unsigned char *) &s) == 0x34 ) {
printf("Little Endian (Byte MENOS significativo
primeiro)\n");
} else {
printf("Endianness indeterminado\n");
}
16de17
int));
printf ("long int ............ %3d\n", sizeof (long int));
printf ("signed long int ..... %3d\n", sizeof (signed long
int));
printf ("unsigned long int ... %3d\n", sizeof (unsigned long
int));
printf ("float ............... %3d\n", sizeof (float));
printf ("double .............. %3d\n", sizeof (double));
printf ("long double ......... %3d\n", sizeof (long double));
#ifdef OUTRAS
printf( "long char .......... %3d\n", sizeof(long char) );
printf( "unsigned long char . %3d\n", sizeof(unsigned long
char) );
printf( "short char ......... %3d\n", sizeof(short char) );
printf( "unsigned short char. %3d\n", sizeof(unsigned short
char) );
printf( "long float ......... %3d\n", sizeof(long float) );
printf( "short float ........ %3d\n", sizeof(short float) );
printf( "short double ....... %3d\n", sizeof(short double) );
#endif
return 0;
}
17de17