Fábio Pereira Microcontroladores RL78 Guia Básico 1ª Edição Versão 1.01 Joinville - SC Edição do Autor 2013 Microcontroladores RL78: Guia Básico 1 Copyright © 2013 Fábio Pereira Todos os direitos reservados. É proibida a redistribuição, de forma parcial, do conteúdo deste livro ou arquivo eletrônico. A utilização parcial do material desta obra é condicionada a sua citação como fonte do conteúdo. Todas as marcas registradas, nomes ou direitos de uso citados neste livro pertencem aos seus respectivos proprietários. O autor acredita que todas as informações apresentadas nesta obra estão corretas e podem ser utilizadas para qualquer fim legal. Entretanto, não existe qualquer garantia implícita ou explícita, de que o uso de tais informações conduzirá sempre ao resultado esperado. Acesse: www.perse.com.br para adquirir cópias impressas adicionais. Material para download disponível em: www.sctec.com.br/blog ISBN: 978-85-8196-334-1 2 Microcontroladores RL78: Guia Básico Agradecimentos Este é o meu nono livro e ele não teria sido possível sem a colaboração de algumas pessoas, por isso, os meus agradecimentos a: - André Machado de Oliveira, da Renesas do Brasil, pela amizade e incentivo (há anos) na utilização dos microcontroladores Renesas, além do suporte, ajuda na revisão do texto, sugestões, kits e apoio incondicional ao livro. - Huéliquis Fernandes, da Renesas do Brasil, pela amizade e grande apoio dado à viabilização deste livro e também por acreditar no meu trabalho. - Felipe Torrezan e Leonardo Carlos Afonso, da Renesas do Brasil, pelo apoio técnico, ajuda na revisão e suporte ao livro. - William Severino, da Renesas Electronics America, pelas sugestões iniciais e apoio dado ao livro. - Ritesh Tyagi, diretor da área de marketing de microcontroladores pelo apoio da Renesas Electronics America a edição deste livro. - José Carlos Nunes, da VLA, representante da Renesas no Brasil, pelo apoio dado ao livro, sugestões e amostras. Dedicatória Escrever um livro implica em centenas de horas de dedicação. Por isso, quero dedicar este livro a minha esposa Débora e agradecer pelo carinho, compreensão, apoio e por estar ao meu lado! Amo você! Microcontroladores RL78: Guia Básico 3 Sobre o Autor Fábio Pereira é técnico em Eletrônica (CEFET-PR), bacharel em Direito (ACE-SC), especialista em projeto de equipamentos eletrônicos (CEFET-SC) e autor de outros oito livros na área de programação de microcontroladores (sete deles em português e um em inglês). Também atuou como professor de disciplinas relacionadas a microcontroladores e programação em C em cursos técnicos e universidades na região de Joinville e atualmente trabalha como advogado e nas horas vagas mantém o seu blog FPB (www.sctec.com.br/blog) além de desenvolver projetos de sistemas embarcados. Ao longo dos últimos 20 anos, desenvolveu diversas aplicações utilizando diferentes plataformas tais como 8051, ARM, AVR, Cortex, Coldfire, HC908, HCS08, MSP430, PIC, RL78, Z8-Encore, Z-80 em diferentes linguagens como Assembly, BASIC, C e Pascal. Outros livros do autor: Microcontroladores PIC: Técnicas Avançadas; Microcontroladores PIC: Programação em C; Microcontroladores HC908Q: Teoria e Prática; Microcontroladores MSP430: Teoria e Prática; Microcontroladores HCS08: Teoria e Prática; Tecnologia ARM: Microcontroladores de 32 bits; HCS08 Unleashed: Designer’s guide to the HCS08 Microcontrollers; Microcontrolador PIC18 Detalhado : Hardware e Software. Para entrar em contato com o autor, acesse o blog: www.sctec.com.br/blog 4 Microcontroladores RL78: Guia Básico Sobre a Renesas Renesas é uma empresa japonesa na área de eletrônica e foi fundada em 2003 como uma joint venture entre a Hitachi e a Mitsubishi Electric, ambas gigantes japonesas com grande atuação na área da eletrônica. Em 2010 a NEC Electronics Corporation juntou-se à Renesas e trouxe com ela a sua linha de microcontroladores e microprocessadores (expandindo ainda mais a já ampla linha de MCUs e MPUs da Renesas). A linha de produtos fabricados pela Renesas é digna do peso dos três principais sócios da empresa: vai de microcontroladores 8 bits de baixo custo (como os 78K0 desenvolvidos pela NEC e H8 desenvolvidos pela Hitachi), passando pelos microcontroladores de 16 bits (H8, R8C e M16C desenvolvidos pela Hitachi, 78K0R desenvolvidos pela NEC e RL78 da Renesas), microcontroladores de 32 bits (como o R32C, RX e RH850 da Renesas, V850 desenvolvido pela NEC e os SuperH desenvolvidos pela Hitachi), até microprocessadores SoC de alta performance para os mercados móveis e automotivos (utilizando múltiplos núcleos ARM, Cortex e SuperH). Além dos MCUs e MPUs a Renesas fabrica diversos outros semicondutores como integrados LSI, ASSP, Displays, IGBTs, MOSFETs, etc. A Renesas foi o quinto maior fabricante de semicondutores nos anos de 2010 e 2011 e o primeiro em venda de microcontroladores no mesmo período. A participação da Renesas no mercado mundial de microcontroladores é de aproximadamente 28%, com vendas anuais de mais de 4 bilhões de dólares. A empresa possui diversos escritórios ao redor do mundo. No Brasil, a presença da empresa vem crescendo, com um escritório em São Paulo e investimentos em divulgação e ampliação da margem local de mercado. Microcontroladores RL78: Guia Básico 5 6 Microcontroladores RL78: Guia Básico Índice 1. Introdução ............................................................................................................................... 13 1.1. Uma Breve História da Computação .......................................................................... 13 1.2. Sistemas Embarcados ................................................................................................. 17 1.3. Conceitos Básicos....................................................................................................... 18 1.4. Microcontroladores RL78........................................................................................... 30 1.5. Pinagens e Encapsulamentos ...................................................................................... 32 1.6. R5F100LEA ............................................................................................................... 35 1.7. Kits e Ferramentas de Programação ........................................................................... 36 1.8. Convenções Utilizadas ............................................................................................... 38 2. Ferramentas de Programação ............................................................................................... 41 2.1. O Ambiente Embedded Workbench EWRL78........................................................... 41 2.1.1. Criando o Primeiro Projeto ............................................................................. 41 2.1.2. Simulando um Programa................................................................................. 46 2.1.3. Depurando um Programa ................................................................................ 51 2.1.4. Gerando o Código Final .................................................................................. 52 3. Arquitetura e Modelo de Programação ................................................................................ 55 3.1. A CPU RL78 .............................................................................................................. 55 3.1.1. Registradores Especiais da CPU ..................................................................... 56 3.1.1.1. Registrador PSW....................................................................................................57 3.1.1.2. Registrador PC.......................................................................................................58 3.1.1.3. Registrador SP .......................................................................................................58 3.1.1.4. Registradores ES e CS ...........................................................................................60 3.1.1.5. Registrador PMC ...................................................................................................60 3.1.2. Mapa de Memória ........................................................................................... 61 3.1.3. Modos de Endereçamento ............................................................................... 63 3.2. Conjunto de Instruções Assembly .............................................................................. 65 3.2.1. Instruções de Manipulação de Dados.............................................................. 65 3.2.2. Instruções Aritméticas, Lógicas e de Comparação.......................................... 66 3.2.3. Instruções de Incremento e Decremento ......................................................... 68 3.2.4. Instruções de Rotação e Deslocamento de Bits ............................................... 68 3.2.5. Instruções de Manipulação e Processamento de Bits ...................................... 71 3.2.6. Instruções de Desvio ....................................................................................... 71 Microcontroladores RL78 Guia Básico 7 3.2.7. Instruções para Sub-rotinas e Funções ............................................................ 72 3.2.8. Instruções de Pulo Condicional....................................................................... 73 3.2.9. Instruções de Controle da CPU....................................................................... 73 3.2.10. Temporização das Instruções ........................................................................ 74 3.3. Módulo OCD e Código de Segurança (Security ID) .................................................. 74 3.4. Configurações do Chip ............................................................................................... 76 4. Suporte à CPU ........................................................................................................................ 81 4.1. Reset........................................................................................................................... 81 4.2. Sistema de Clock ........................................................................................................ 83 4.2.1. Oscilador X1 ................................................................................................... 84 4.2.2. Oscilador XT1................................................................................................. 85 4.2.3. Oscilador Interno de Alta Frequência ............................................................. 86 4.2.4. Oscilador Interno de Baixa Frequência........................................................... 87 4.2.5. Registradores do Sistema de Clock................................................................. 87 4.2.6. Exemplo .......................................................................................................... 91 4.3. Gerenciamento de Energia ......................................................................................... 92 4.3.1. Modo Halt ....................................................................................................... 93 4.3.2. Modo Stop....................................................................................................... 93 4.3.3. Modo Snooze .................................................................................................. 94 4.3.4. Gerenciamento de Clock................................................................................. 95 4.3.5. Dicas para Reduzir o Consumo de Energia..................................................... 96 4.3.6. Exemplo .......................................................................................................... 96 4.4. Clock/Buzzer Output .................................................................................................. 98 4.4.1. Exemplo .......................................................................................................... 99 4.5. Detector de Baixa Tensão......................................................................................... 100 4.5.1. Modo Reset ................................................................................................... 100 4.5.2. Modo Interrupção.......................................................................................... 101 4.5.3. Modo Interrupção e Reset ............................................................................. 101 4.5.4. Registradores do LVD .................................................................................. 102 4.6. Watchdog (WDT)..................................................................................................... 104 4.6.1. Exemplo ........................................................................................................ 106 4.7. Regulador Interno de Tensão.................................................................................... 108 5. Portas de Entrada e Saída.................................................................................................... 109 8 Microcontroladores RL78: Guia Básico 5.1. Registradores das Portas de E/S ............................................................................... 110 5.2. Redirecionamento de Funções.................................................................................. 116 5.3. Exemplo.................................................................................................................... 117 6. Sistema de Interrupções ....................................................................................................... 121 6.1. Categorias de Interrupções ....................................................................................... 123 6.2. Sistema de Interrupções do RL78............................................................................. 123 6.2.1. Sistema de Prioridades de Interrupção .......................................................... 127 6.2.2. Latência de Interrupção ................................................................................. 129 6.2.3. Utilizando os Bancos de Registradores dos RL78......................................... 130 6.3. Interrupções Externas ............................................................................................... 131 6.3.1. Exemplo ........................................................................................................ 133 6.4. Interrupção de Teclado ............................................................................................. 134 6.4.1. Exemplo ........................................................................................................ 134 7. Periféricos de Temporização................................................................................................ 137 7.1. Timer de Intervalo (IT)............................................................................................. 138 7.1.1. Exemplo ........................................................................................................ 139 7.2. RTC .......................................................................................................................... 140 7.2.1. Configuração do RTC ................................................................................... 142 7.2.2. Registradores do RTC ................................................................................... 143 7.2.3. Ajuste do RTC............................................................................................... 147 7.2.4. Exemplo ........................................................................................................ 148 7.3. TAU.......................................................................................................................... 150 7.3.1. Visão Geral de uma Unidade TAU ............................................................... 151 7.3.2. Operação em Modo Timer/Gerador de Onda Quadrada ............................... 153 7.3.3. Operação no Modo Gerador de Atraso/Disparo Único ................................. 156 7.3.4. Operação em Modo Contador de Eventos..................................................... 158 7.3.5. Operação como Divisor de Frequência ......................................................... 159 7.3.6. Operação no Modo de Captura de Período.................................................... 160 7.3.7. Operação no Modo de Captura de Ciclo ....................................................... 161 7.3.8. Operação no Modo de Pulso Configurável ................................................... 162 7.3.9. Operação em Modo PWM............................................................................. 166 7.3.10. Registradores das TAU ............................................................................... 169 7.4. Outros Timers ........................................................................................................... 177 Microcontroladores RL78 Guia Básico 9 8. Periféricos de Analógicos ..................................................................................................... 179 8.1. Detalhes Gerais do Conversor A/D .......................................................................... 179 8.2. Modos de Operação.................................................................................................. 185 8.2.1. Conversão Simples ou Múltipla .................................................................... 185 8.2.2. Conversão de Um Canal ou Varredura de Canais......................................... 186 8.2.3. Formas de Disparo do Conversor.................................................................. 186 8.2.3.1. Disparo por Software........................................................................................... 187 8.2.3.2. Disparo por Hardware ......................................................................................... 187 8.3. Referência Interna de Tensão ................................................................................... 188 8.4. Sensor de Temperatura ............................................................................................. 188 8.5. Operação em Modo Snooze...................................................................................... 189 8.6. Registradores do ADC.............................................................................................. 190 8.7. Exemplo ................................................................................................................... 193 8.8. Outros Periféricos Disponíveis................................................................................. 194 8.8.1. Comparador Analógico ................................................................................. 194 8.8.2. Conversor A/D de 12 bits.............................................................................. 194 8.8.3. Conversor D/A .............................................................................................. 194 9. Periféricos de Comunicação................................................................................................. 195 9.1. Unidades SAU.......................................................................................................... 195 9.1.1. Registradores das SAU ................................................................................. 198 9.1.2. Modo UART ................................................................................................. 205 9.1.2.1. Configuração do Baud Rate................................................................................. 207 9.1.2.2. Operação em Modo Snooze................................................................................. 210 9.1.2.3. LIN ...................................................................................................................... 210 9.1.2.4. API Applilet ........................................................................................................ 210 9.1.2.5. Exemplo .............................................................................................................. 211 9.1.3. Modo CSI...................................................................................................... 213 9.1.3.1. Configuração do Baud Rate................................................................................. 216 9.1.3.2. API Applilet ........................................................................................................ 217 9.1.4. Modo I2C....................................................................................................... 218 9.1.4.1. I2C Simplificado na SAU .................................................................................... 220 9.1.4.2. Configuração do Baud Rate................................................................................. 223 9.1.4.3. Comunicação I2C................................................................................................. 223 9.1.4.4. API Applilet ........................................................................................................ 225 9.2. Unidades IICA (I2C)................................................................................................. 226 9.2.1. Operação da IICA ......................................................................................... 227 9.2.2. API Applilet .................................................................................................. 228 9.2.3. Registradores IICA ....................................................................................... 230 10 Microcontroladores RL78: Guia Básico 10. Tópicos Avançados ............................................................................................................. 235 10.1. Ajuste BCD ............................................................................................................ 235 10.2. Funções de Segurança ............................................................................................ 236 10.2.1. Checagem de CRC da Flash........................................................................ 237 10.2.2. Checagem de Paridade da RAM ................................................................. 238 10.2.3. Bloqueio de Registradores e da RAM ......................................................... 239 10.2.4. Execução de Opcode Ilegal (Trap).............................................................. 240 10.2.5. Acesso Ilegal à Memória (IAW) ................................................................. 240 10.2.6. Verificação do A/D ..................................................................................... 240 10.2.7. Verificação do Clock................................................................................... 240 10.3. CRC de Uso Geral .................................................................................................. 241 10.4. Gravação e Apagamento da Flash e DataFlash....................................................... 242 10.4.1. FSL.............................................................................................................. 242 10.4.1.1. Utilização da FSL ..............................................................................................247 10.5. Hardware de Multiplicação e Divisão .................................................................... 253 10.6. DMA....................................................................................................................... 255 10.6.1. Registradores dos Canais de DMA ............................................................. 258 10.6.2. Exemplo ...................................................................................................... 261 10.7. Otimizando Aplicações para o RL78...................................................................... 263 10.7.1. Tamanho do Dado ....................................................................................... 263 10.7.2. Endereçamento Rápido ............................................................................... 264 10.7.3. Campos de Bit ............................................................................................. 264 10.7.4. Funções CALLT.......................................................................................... 265 10.8. Utilizando o Applilet3 ............................................................................................ 266 10.8.1. Configuração do Timer de Intervalo ........................................................... 268 10.8.2. Configuração da UART .............................................................................. 271 11. Exemplos de Aplicação ....................................................................................................... 273 11.1. Utilização de Módulos LCD Alfanuméricos .......................................................... 273 11.2. Mostrador Analógico no LCD ................................................................................ 280 11.3. Termômetro Digital ................................................................................................ 283 11.4. Medidor de Distância por Ultrassom ...................................................................... 286 12. Tabela ASCII ...................................................................................................................... 291 Microcontroladores RL78 Guia Básico 11 12 Microcontroladores RL78: Guia Básico 1 Introdução 1. Introdução O objetivo deste livro é apresentar a família RL78 de microcontroladores da Renesas, com ênfase nos modelos RL78/G13. Antes de nos dedicarmos ao estudo deles é importante conhecer um pouco da história da computação digital, além de revisar conceitos cruciais na área da eletrônica digital e lógica de programação. 1.1. Uma Breve História da Computação As primeiras máquinas de computação de que se tem notícia datam de 1623 (a máquina de cálculos de Wilhelm Schickard) e 1642 (a máquina Pascaline de Blaise Pascal). Ambas eram totalmente mecânicas e utilizavam intrincados mecanismos para realizar operações de adição. Em 1671, o matemático e filósofo alemão Gottfried Von Leibniz desenhou a Staffelwalze (também conhecida como “Stepped Reckoner” ou calculadora de passos), a primeira calculadora mecânica capaz de realizar as quatro operações básicas da matemática (adição, subtração, multiplicação e divisão). Figura 1.1 – Pascaline Fonte: http://fr.wikipedia.org/wiki/Fichier:Arts_et_Metiers_Pascaline _dsc03869.jpg Figura 1.2 – Stepped Reckoner Fonte:http://en.wikipedia.org/wiki/File:Leibniz_Stepped_Reckoner.png Todas essas máquinas eram apenas calculadoras mecânicas e não podiam ser programadas para executar operações predefinidas. As primeiras máquinas programáveis surgiram no início do século XIX e eram muito diferentes do conceito atual de um computador. O tear Jacquard (criado por Joseph Marie Jacquard em 1801) é provavelmente a primeira máquina passível de ser programada pelo usuário. Utilizando cartões de papel perfurados, era possível programar complexos padrões a serem tecidos, aumentando drasticamente a flexibilidade dos teares, que até então somente podiam tecer um mesmo padrão. Isso permitiu que um mesmo tear fosse utilizado para produzir diferentes padrões de tecidos. Introdução 13 Alguns anos depois (1837), Charles Babbage desenhou a sua “Analytical Engine” (máquina analítica) que seria provavelmente o primeiro computador totalmente programável se ela tivesse sido realmente construída. Figura 1.3 - Tear Jacquard. Fonte: http://commons.wikimedia.org/wiki/Image:Jacquard.loom. full.view.jpg Figura 1.4 – Cartões perfurados para programação do tear Jacquard. Fonte: http://en.wikipedia.org/ wiki/File:Jacquard.loom.cards.jpg O grande progresso da computação ocorreu com o advento das “Tabulating Machines” (máquinas de tabular) de Herman Hollerith (manufaturadas pela “Computing Tabulating Recording Corporation”, que algum tempo depois originou a IBM). As máquinas de tabular de Hollerith também utilizavam cartões de papel perfurados e permitiram que o censo Norte-Americano de 1890 fosse completado em apenas dezoito meses (o censo anterior, de 1880, foi completado em sete anos!). Essas máquinas não eram programáveis, mas foram um passo importante na direção dos computadores programáveis. Em 1941, no Iowa State College, o pesquisador John Vincent Atanasoff projetou e construiu o Atanasoff-Berry Computer (ABC), primeiro computador eletrônico norte-americano. Ele foi projetado especificamente para auxiliar na resolução de equações lineares e, apesar de não ser programável nem ser máquina Turing completa, o ABC apresentou alguns conceitos importantes: 14 • Sistema organizado com unidades separadas de computação e de memória (como nos computadores atuais). • Memória capacitiva regenerativa com aproximadamente 3.200 capacitores organizados em dois tambores, cada um com 32 bandas de 50 capacitores (duas bandas não eram utilizadas e ficavam como reserva), resultando numa capacidade total de armazenamento de 60 números de 50 bits. Esse sistema de regeneração foi o precursor dos sistemas de refresh das memórias DRAM atuais e funcionava rotacionando os tambores num eixo com pinças para acesso aos dados. Microcontroladores RL78: Guia Básico • Unidade lógica e aritmética (ULA) totalmente eletrônica construída com uso de cerca de 280 válvulas a vácuo. • O sistema de I/O era composto de um sistema primário e um sistema secundário para resultados intermediários (utilizado quando os problemas sendo resolvidos excediam a capacidade de armazenamento da memória eletrônica interna). O primeiro computador digital (e binário) totalmente programável foi o Z3, projetado e construído pelo engenheiro alemão Konrad Zuse em 1941. Esse computador utilizava cerca de 2.000 relés no papel de chaves, portanto era eletromecânico. O programa era armazenado externamente numa fita perfurada, permitindo que diferentes programas fossem executados com relativa facilidade. O Z3 possuía em seu conjunto de instruções praticamente todas as Figura 1.5 - Zuse Z3. funcionalidades encontradas nos computadores Fonte:http://www.computerhistory.org/timeline/images/1941_zuse_z3_ large.jpg modernos, com exceção das instruções de desvio (que foram implementadas posteriormente no microcódigo para cálculos em ponto flutuante). Em 1943, os pesquisadores do Post Office Research Station em Dollis Hill (Inglaterra) apresentaram o protótipo de um dos primeiros computadores eletrônicos: o Colossus Mark 1. Esse computador (na verdade a sua segunda geração, Colossus Mark 2) foi utilizado para auxiliar na decodificação das mensagens alemãs criptografadas durante a Segunda Guerra Mundial. Outro famoso computador dessa era foi o ENIAC (Electronic Numerical Integrator And Computer), um computador eletrônico projetado e construído pelo Laboratório de Pesquisa Balística do Exército Norte-Americano, em 1946, para auxiliar no cálculo de tabelas de artilharia e outros problemas matemáticos complexos (como os relacionados ao projeto das primeiras bombas atômicas). O ENIAC era um computador enorme, composto por milhares de válvulas eletrônicas, diodos de cristal e relés. Possuía registradores decimais de dez dígitos e operava com clock de 100kHz, consumindo cerca de 174kW em operação. Uma de suas grandes fraquezas era o sistema de armazenamento do programa, que era realizado pela interligação de fios no interior do computador. Sendo assim, qualquer alteração implicava esforço considerável. Em 1948, alguns melhoramentos foram adicionados ao ENIAC; o mais importante foi um Introdução Figura 1.6 - ENIAC. Fonte: http://en.wikipedia.org/wiki/Image:Classic_shot_of_the_ENIAC.jpg 15 dispositivo de leitura de programa utilizando tabelas de funções (proposto pelo matemático John von Neumann). Esse mecanismo funcionava como uma ROM (Read-Only Memory ou memória somente de leitura) de programa primitiva. Outro computador famoso e importante foi o ASCC (Automatic Sequence Controlled Calculator - calculadora automática de sequência controlada) da IBM (também conhecido como IBM Mark I), projetado por Howard H. Aiken da Universidade de Harvard e construído pela IBM em 1944. Ele foi o primeiro computador totalmente automático e que funcionava de forma muito semelhante aos computadores modernos. O ASCC era um computador eletromecânico e possuía memórias separadas para o armazenamento das instruções do programa e os dados. Essa arquitetura ficaria conhecida como “arquitetura Harvard”. Já o IBM SSEC (Selective Sequence Electronic Calculator - calculadora eletrônica de sequência seletiva), construído em 1948, implementava outra abordagem para a sua arquitetura interna: um espaço de memória unificado onde são armazenadas tanto as instruções quanto os dados. Essa arquitetura ficou conhecida como “Von Neumann” ou Princeton, em homenagem ao matemático John von Neumann da Universidade de Princeton (EUA), ainda que John Presper Eckert (um dos homens por trás do projeto do ENIAC) tenha proposto a mesma arquitetura anos antes de Von Neumann. Essas duas arquiteturas de computadores (Von Neumann e Harvard) ainda estão em uso mesmo nos mais modernos computadores da atualidade. A Figura 1.7 mostra os diagramas simplificados dessas duas arquiteturas. A arquitetura Von Neumann (também chamada Princeton) caracteriza-se por utilizar três barramentos de comunicação que são compartilhados pela memória e E/S, um para o endereçamento (seleção da posição a ser lida ou escrita), um para o controle (seleção do tipo de operação a ser realizada) e outro para dados (que carrega a informação propriamente dita). A arquitetura Harvard, por sua vez, utiliza conjuntos de barramentos separados para as memórias e E/S, diferenciando ainda entre memória de programa (onde ficam armazenados as instruções do programa) e de dados (onde ficam os dados utilizados pelo programa). Endereço Endereço (programa) Memória Programa/ Dados Controle CPU Dados Dados (programa) Controle (programa) Memória de Programa Endereço (dados) CPU Dados (dados) Controle (dados) Memória de Dados Endereço (periféricos) Periféricos Dados (periféricos) Controle (periféricos) Arquitetura Von Neumann (Princeton) Periféricos Arquitetura Harvard Figura 1.7 Cada arquitetura apresenta prós e contras: Von Neumann oferece mais flexibilidade, pois não faz distinção entre instruções e dados. Por outro lado, ela impõe uma única largura para o barramento de dados, implicando que uma CPU de 8 bits busque instruções de 8 ou múltiplos de 16 Microcontroladores RL78: Guia Básico 8 bits. Outro ponto fraco da arquitetura Von Neumann é um problema conhecido como “gargalo de Von Neumann”, causado pela capacidade limitada de transferência de dados da memória, quando comparada à necessidade da CPU de acessar a memória para leitura de instruções e a leitura/escrita de dados. Apesar de todos os problemas impostos por essa arquitetura, ela ainda é vastamente utilizada pela maioria dos computadores atuais e dos microprocessadores e microcontroladores no mercado. Na arquitetura Harvard, a velocidade é o benefício mais relevante do arranjo de múltiplos barramentos: enquanto executa uma instrução, a CPU pode ler e escrever dados na memória de dados e simultaneamente buscar a próxima instrução na memória de programa. Neste caso, os prós e contras se misturam devido à distinção entre a memória de programa e de dados: normalmente não é possível ter dados na memória de programa ou instruções na memória de dados. Algumas máquinas Harvard incluem instruções especiais que permitem o acesso à memória de programa para leitura/escrita de dados. Outras implementam áreas especiais de memória compartilhadas por instruções e dados. Além das arquiteturas de projeto citadas, existem também dois diferentes conceitos básicos de projeto do conjunto de instruções de um processador: o conceito CISC e o conceito RISC. O conceito CISC (computador com conjunto complexo de instruções) defende que a máquina possua uma grande quantidade de instruções (normalmente acima de 100), capazes de desempenhar as mais diferentes tarefas. Máquinas CISC normalmente possuem instruções complexas que realizam uma série de operações. Já o conceito RISC (computador com conjunto reduzido de instruções) defende que a máquina possua um conjunto pequeno de instruções, mas que devem ser executadas rapidamente. Máquinas RISC normalmente possuem instruções simples e rápidas e necessitam de múltiplas instruções para realizar operações mais complexas. Normalmente encontramos máquinas RISC associadas à arquitetura Harvard, ao passo que as máquinas CISC normalmente utilizam a arquitetura Von Neumann. 1.2. Sistemas Embarcados A aplicação de computadores em dispositivos móveis ou capazes de ser movidos resultou em uma geração totalmente diferente de computadores e originou o termo “embedded system” ou sistema embarcado. Um dos primeiros sistemas embarcados de que se tem notícia foi o Apollo Guidance Computer, ou AGC. Ele foi um computador (na verdade um microcomputador) de 16 bits (15 de dados mais um de paridade), que operava a 1,024MHz e que possuía 2.048 words de memória RAM e 36.864 words de memória de programa. Este microcomputador foi um dos primeiros computadores digitais a utilizar circuitos integrados e foi utilizado para o controle das espaçonaves Apollo (que em diversas missões nas décadas de 60 e 70, levaram o homem à Lua). Ele também possuía uma IHM (Interface Homem Máquina) composta de um teclado numérico e displays eletroluminescentes, através da qual os astronautas podiam operá-lo, inserir Introdução 17 e visualizar dados, executar comandos e programas e até mesmo reprogramá-lo (como aconteceu na missão Apollo 14). A – Módulos AGC e DSKY B – Módulo DSKY. Fonte: http://en.wikipedia.org/wiki/File:Agc_view.jpg Fonte:http://www.computerhistory.org/timeline/images/ 1968_apollo.jpg Figura 1.8 O AGC utilizava a primeira geração de circuitos integrados (portas NOR duplas com 3 entradas cada e implementadas utilizando tecnologia RTL – Resistor Transistor Logic), mas foi o advento do microprocessador (o 4004 desenvolvido pela Intel em 1971) e posteriormente do microcontrolador (o TMS1000 desenvolvido pela Texas Instruments em 1971 e lançado em 1974) que permitiu que os sistemas embarcados pudessem ser barateados e terem reduzidos drasticamente o seu tamanho físico e o consumo de energia (todos fatores importantes quando se fala em sistemas embarcados). Atualmente os microcontroladores e o termo “sistema embarcado” possuem uma aplicação muito ampla, sendo utilizados em equipamentos simples (como torradeiras, cafeteiras, etc.) até complexos (como equipamentos médicos, smartphones, GPS, etc.). 1.3. Conceitos Básicos Eletrônica é a ciência que estuda e aplica a eletricidade (o movimento de cargas elétricas) aos componentes (resistores, capacitores, indutores, semicondutores etc.) para construir circuitos complexos que podem interagir com o ambiente ou com os seres humanos. De cafeteiras a TVs LCD, de lâmpadas elétricas a smartphones, de relógios de pulso a tablets e computadores, interagimos diariamente com um grande número de diferentes dispositivos elétricos e eletrônicos, alguns dos quais são tão pequenos ou simples que sequer nos damos conta da sua existência. Dentro do universo da eletrônica, uma das áreas mais interessantes e que movimenta o mercado é a dos microprocessadores e microcontroladores, pequenos chips que incluem internamente praticamente toda a eletrônica necessária para construir máquinas e dispositivos dotados de alguma forma de inteligência. A base por trás dos microcontroladores e microprocessadores é a eletrônica digital. Para melhor entendê-la, é necessária uma breve reflexão sobre como o universo funciona. 18 Microcontroladores RL78: Guia Básico O mundo é analógico: a temperatura de uma sala, a intensidade da luz, o tempo, as dimensões físicas de uma caixa, o som, a distância entre casas e trabalhos, tudo isso é medido por grandezas analógicas. Elas podem ser medidas utilizando algum tipo de unidade de medição e podem variar consideravelmente (imagine que nada no mundo é exatamente igual; mesmo os mecanismos produzidos pela máquina mais precisa serão ligeiramente diferentes se medidos com a devida precisão). Por outro lado, os computadores modernos são máquinas eminentemente binárias. Eles somente podem reconhecer dois tipos de informação: 0 (falso) ou 1 (verdadeiro). As imagens, filmes e cores que vemos na tela de um computador ou em filme em DVD, a música que ouvimos de um CD player ou de um MP3 player, tudo isso pode ser reduzido somente a zeros e uns. As razões para utilizar um sistema binário (digital) em vez de um sistema analógico são muito simples: 1. Por existirem somente dois níveis de tensão, é mais simples projetar os circuitos eletrônicos de computadores digitais. A utilização de transistores como chaves permite obter dois níveis distintos de tensão (0V para chave aberta ou falso e 5V para chave fechada ou verdadeiro). 2. A matemática por trás dos modernos computadores é baseada na álgebra booleana, criada por George Boole (um matemático e filósofo inglês que viveu no século XVIII e que criou a álgebra booleana, baseada em dois estados: verdadeiro e falso). Vemos então que os computadores utilizam a base binária, ao passo que nós, seres humanos, utilizamos a base decimal, constituída de 10 diferentes símbolos (0 a 9) e adotada em virtude de possuirmos 10 dedos nas mãos (as mãos foram o primeiro instrumento de cálculo na história da humanidade), mas além dessas duas bases, existem outras bases numéricas importantes, entre elas a octal (que utiliza 8 diferentes símbolos, de 0 a 7) e hexadecimal (base 16 diferentes símbolos, de 0 a 9, A, B, C, D, E, F). A base hexadecimal permite representar diretamente um valor binário utilizando poucos dígitos. Ela foi muito importante nos primórdios da computação, pois permitia que os sistemas de apresentação de dados utilizassem displays com poucos dígitos, assim como os teclados também eram mais fáceis de construir (displays eram itens complexos e caros até a década de 80, foi somente com a invenção dos LEDs e posteriormente dos displays LED que houve uma redução significativa no custo dos mesmos). A facilidade de representação de valores binários em hexadecimal é oriunda do processo de conversão, que é absolutamente simples e intuitivo (o mesmo não ocorre com binário e decimal, por exemplo). Para entender a razão desta simplicidade, vejamos como funciona o sistema de bases numéricas. Primeiramente, é importante observar que em qualquer base numérica existem dígitos e através da junção de múltiplos dígitos é que se pode representar uma quantidade arbitrária qualquer. O primeiro dígito (o menos significativo) em qualquer base tem sempre o peso 1. Ele corresponde a base elevada a potência 0. O dígito de magnitude imediatamente superior é o da Introdução 19 base elevada a potência 1 e assim por diante. Os pesos das diferentes posições nas bases numéricas podem ser vistos na tabela 1.2. Binário Decimal Hexadecimal 0000 0 0 0001 1 1 0010 2 2 0011 3 3 0100 4 4 0101 5 5 0110 6 6 0111 7 7 1000 8 8 1001 9 9 1010 10 A 1011 11 B 1100 12 C 1101 13 D 1110 14 E 1111 15 F Tabela 1.1 Peso 3 2 1 0 3 2 1 0 2 =1 1 Binário 2 =8 Decimal 3 2 =4 10 =1000 10 =100 10 =10 100=1 Hexadecimal 163=4096 162=256 161=16 160=1 2 2 =2 Tabela 1.2 Seguindo a tabela 1.2, o número 1001 binário equivale a 1*8 + 0*4 + 0*2 + 1*1 = 9 decimal, o número 1001 decimal equivale a uma milhar (1*1000) mais uma unidade (1*1) e o número 1001 hexadecimal equivale a 1*4096 + 1*1 = 4097 decimal. É fácil perceber que com dois dígitos binários podemos representar até 4 diferentes valores (00, 01, 10 e 11), com dois dígitos decimais podemos representar até 100 diferentes valores (de 0 a 99) e com dois dígitos hexadecimais podemos representar até 256 valores (de 0 a FF). Mas além da simplificação da representação de dados (em termos de redução no número de dígitos), a base hexadecimal oferece ainda a facilidade adicional de permitir a simples e rápida conversão de/para binário. Tudo o que é necessário é agrupar os dígitos binários em nibbles (conjuntos de 4 bits) e em seguida realizar diretamente a conversão de/para hexadecimal. Vejamos alguns exemplos: 01000010 em binário pode ser separado em 0100 e 0010, 0100 equivale a 4 hexadecimal, 0010 equivale a 2 hexadecimal, então 01000010 binário equivale a 42 hexadecimal. 10100110 em binário, 1010 equivale a A hexadecimal, 0110 equivale a 6 hexadecimal, então 10100110 binário equivale a A6 hexadecimal. A recíproca também é 20 Microcontroladores RL78: Guia Básico verdadeira: 7B hexadecimal, 7 hexadecimal equiva e 0111 binário e B hexadecimal equivale a 1011 binário, então 7B hexadecimal equivale a 01111011 binário! A aritmética, em qualquer que seja a base, também é baseada em princípios comuns e deve sempre levar em consideração a quantidade de símbolos únicos existentes na base, para cada posição numérica. Assim, a soma de 7 + 5 em decimal é feita agrupando os dígitos de magnitude equivalente. Nos casos onde não há dígito para representar a magnitude desejada, ocorre o transporte para a próxima posição: 7 5 12 + No caso, a adição de 7 com 5, resulta que não há um símbolo decimal único para representar a grandeza, por isso, há um transporte para a próxima posição. Nas operações em outras bases (seja binário, hexadecimal, etc.), o procedimento é exatamente o mesmo. Vejamos a adição dos valores binários 10 + 10: 10 10 100 + Outro exemplo, desta vez em hexadecimal. Vejamos a adição de 9 + 9: 9 9 12 + Quando se realiza operações aritméticas envolvendo bytes (conjuntos de 8 bits), diz-se que ocorre um transporte (carry em inglês) quando há um transporte binário do bit 7 (o oitavo bit do byte). No caso das operações de subtração, utiliza-se basicamente o mesmo princípio da adição e os circuitos somadores, no entanto, para a subtração, faz-se a soma do minuendo com subtraendo, sendo este escrito com sinal inverso: - 10 4 6 10 -4 6 + é o mesmo que Isto permite que as unidades lógicas e aritméticas dos microprocessadores e microcontroladores possam realizar operações de subtração a partir de um circuito somador. Para isso, utiliza-se uma representação binária chamada de “complemento de dois”, que consiste no complemento (inversão de todos os bits) e a adição de um. Assim, para obtermos o equivale a -4, utilizamos o valor absoluto 4 para obter o complemento de dois conforme abaixo: Valor absoluto (4) Complemento + 1 Resultado 0 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 1 0 Para realizar a operação 10-4 podemos, através de uma adição (8 bits), fazer: Introdução 21 10 + -4 Resultado 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 0 0 A representação em complemento de dois também é utilizada nas operações com números sinalizados (como os signed char e signed int em C). Neste caso, o bit mais significativo (aquele mais à esquerda) representa o sinal (0 = positivo e 1 = negativo), enquanto que os demais bits representam a magnitude do número. Assim, a representação binária de 8 e 16 bits em complemento de dois segue a seguinte forma: sinal Bit 6 Bit 5 sinal Bit 14 Bit 13 Bit 12 Bit 11 Bit 10 Bit 9 Bit 4 Bit 8 Bit 3 Bit 7 Bit 2 Bit 6 Bit 1 Bit 5 Bit 0 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 Figura 1.9 A tabela a seguir mostra uma escala reduzida dos valores decimais de 8 bits sinalizados e a sua representação binária em complemento de dois. Decimal 127 126 ... 2 1 0 -1 -2 ... -126 -127 -128 Binário 01111111 01111110 ... 00000010 00000001 00000000 11111111 11111110 ... 10000010 10000001 10000000 Tabela 1.3 Agora que já vimos alguns conceitos importantes acerca de bases numéricas e suas operações básicas é hora de rever alguns dos conceitos relacionados aos circuitos digitais que formam a base para os computadores e microcontroladores. Circuitos digitais podem ser construídos com transistores (circuitos TTL - TransistorTransistor Logic), MOSFETs (circuitos CMOS - Complementary Metal-Oxide-Seminconductor), etc. Nos circuitos TTL, transistores NPN e PNP, figura 1.10B, são utilizados para controlar os níveis lógicos no interior do chip. Nos circuitos CMOS, MOSFETs canal N e canal P (figura 1.10C), fazem o papel das chaves. O propósito é sempre o mesmo: utilizar um elemento de comutação para simular uma chave, de forma a produzir os dois estados lógicos possíveis. Figura 1.10 - Três elementos de Com base na álgebra booleana existem comutação quatro funções básicas na eletrônica digital: NÃO, 22 Microcontroladores RL78: Guia Básico E, OU e OU exclusivo (ou simplesmente EOU). A função NÃO realiza a inversão do nível lógico de entrada: NÃO 0 = 1 e NÃO 1 = 0. A função E retorna verdadeiro (1) quando todas as entradas são verdadeiras, a função OU retorna verdadeiro quando qualquer uma das entradas é verdadeira e a função EOU retorna verdadeiro quando as entradas são diferentes. A tabela 1.4 mostra a tabela verdade para as três funções lógicas básicas. Entrada A B 0 0 0 1 1 0 1 1 AND 0 0 0 1 Saída OR EOR 0 0 1 1 1 1 1 0 Tabela 1.4 - Funções lógicas básicas da eletrônica digital Nas figuras 1.11A e 1.11B é possível ver como são construídas portas lógicas NÃO e NÃO-E utilizando MOSFETs. A - Porta lógica NÃO B - Porta lógica NÃO-E (NAND) Figura 1.11 Os símbolos padronizados das funções lógicas básicas (chamadas portas lógicas) estão representados na figura 1.12. Figura 1.12 - Portas lógicas básicas: NÃO (A), E (B), OU (C) e EOU (D) Utilizando estas funções lógicas básicas é possível criar circuitos digitais complexos que podem ser classificados em duas categorias: circuitos combinacionais e sequenciais. Nos circuitos combinacionais, a saída é uma função do sinal de entrada. Alguns exemplos são os somadores, subtratores, comparadores digitais etc. A figura 1.13A mostra a implementação de um somador completo (o bloco básico dos circuitos aritméticos de qualquer computador). Nos circuitos sequenciais, a saída é uma função não somente do conteúdo atual da entrada, mas também dos estados anteriores. Alguns exemplos de circuitos lógicos sequenciais Introdução 23 são os flip-flops, registradores, contadores, latches etc. A figura 1.13B mostra um latch de dados que constitui um dos elementos básicos de memória nos computadores modernos. B - Latch de dados A - Somador completo Figura 1.13 Os circuitos lógicos sequenciais e combinacionais são elementos construtivos básicos das CPUs (Unidades Centrais de Processamento) dos microprocessadores e microcontroladores que utilizamos diariamente. Mas o que é microprocessador? Como ele funciona? Qual a diferença entre microprocessador e microcontrolador? Para entender o que é um microprocessador, primeiro devemos entender mais alguns conceitos relacionados a programação. Um programa é a codificação em linguagem computacional de um algoritmo lógico criado para resolver um problema específico. Para escrever um programa, é necessário analisar cuidadosamente o problema a ser resolvido, identificando todos os passos necessários para se atingir a solução. Uma vez determinados os passos para chegar à solução, é preciso criar um algoritmo que os descreva. A utilização de uma ferramenta gráfica como um fluxograma pode auxiliar na criação de tal algoritmo. Como exemplo, imagine o problema simples de contar de 0 até 10. Os passos para a solução deste problema poderiam ser: 1. Iniciar a contagem em 0. 2. A contagem atual é igual a 10? 3. Sim? Então vai para o final. 4. Não? Então incrementa a contagem em um. 5. Retorna ao passo 2. Listagem 1.1 O fluxograma que descreve o algoritmo sugerido pode ser visto na figura 1.14. Estando de posse do algoritmo, é possível iniciar a codificação do programa de forma que um computador entenda, mas como se faz isso? A resposta é simples: utilizando a linguagem binária de zeros e uns! 24 Microcontroladores RL78: Guia Básico Figura 1.14 - Fluxograma À primeira vista pode parecer incrível que um computador capaz de desempenhar tarefas tão complexas (como navegar pela Internet, reproduzir música, jogos etc.) somente seja capaz de diferenciar zeros de uns, mas é exatamente isso que acontece. De fato, é possível agrupar bits formando-se sequências maiores, que podem representar números, instruções, cores ou o que quer que o programador deseje representar. Qualquer computador, microcomputador, microprocessador, microcontrolador, etc. reconhece algumas sequências de bits como instruções. Essas instruções dizem o que ele deve fazer: adicionar números, armazenar algo na memória, desviar para outro ponto do programa etc. A CPU é responsável pela leitura dessas instruções da memória, sua interpretação e execução. Esses grupos de bits que possuem significado especial para a CPU são chamados de códigos de operação (em inglês operation codes ou opcodes). Computadores diferentes frequentemente possuem diferentes CPUs e diferentes CPUs possuem diferentes opcodes para as instruções que elas reconhecem (isso explica por que você não pode executar uma aplicação de um celular Android® em um celular iPhone® ou vice versa). Tomemos como exemplo a instrução clear (CLRB). Ela apaga (preenche com zero) um registrador ou o conteúdo de uma posição da memória. Nos microcontroladores RL78, essa instrução pode ser representada por diversos opcodes (dependendo do tipo de operando da instrução), assim, a instrução CLRB end (apaga o conteúdo da posição de memória indicada por end) é representada pelo código binário 11110100 xxxxxxxx yyyyyyyy (onde xxxxxxxx yyyyyyyy é o endereço em binário de end). Após a leitura do opcode na memória do chip, a CPU decodifica a instrução e executa a operação indicada. Depois de apagar o conteúdo da posição de memória end, a CPU busca uma nova instrução no endereço seguinte da memória e o processo de decodificação e execução é realizado novamente. A figura 1.15 demonstra os ciclos básicos de execução de uma instrução. No interior da CPU encontramos normalmente alguns importantes elementos (que variam de um modelo de CPU para outro): o decodificador de instruções (responsável por decodificar Introdução 25 cada opcode), o PC (Program Counter - contador de programa, responsável por controlar a sequência do programa), a unidade lógica e aritmética (ULA, responsável pelos cálculos), o registrador acumulador de resultados, além de outros registradores de propósitos gerais. O decodificador de instruções é um circuito lógico que traduz os opcodes na sequência interna de microoperações necessárias para realizar a operação descrita pela instrução. Algumas CPUs utilizam um decodificador chamado de hardwired, ao passo que outras utilizam um decodificador baseado em microcódigos. Busca instrução na memória Decodifica a instrução Escreve o resultado da operação Figura 1.15 - Ciclos de execução de uma instrução. Os decodificadores hardwired são normalmente mais rápidos, pois fazem com que grupos de bits do opcode selecionem e ativem diretamente as partes da CPU necessárias para a execução da instrução. Os decodificadores baseados em microcódigos utilizam máquinas de estado para realizar a decodificação das instruções, o que os torna normalmente mais lentos e ao mesmo tempo mais flexíveis que os decodificadores hardwired. A maioria das CPUs modernas inclui também algum tipo de memória interna. Os elementos básicos de memória interna são os registradores, geralmente utilizados para o armazenamento temporário de dados e no controle da operação da CPU. Os registradores mais importantes em praticamente todas as arquiteturas são o contador de programa (PC) e o acumulador. O contador de programa (PC) é um registrador especial responsável pelo controle e sequenciamento do fluxo do programa. Devido ao fato de ser uma máquina sequencial (na maioria dos casos), a CPU deve executar uma sequência de instruções armazenadas em algum tipo de memória. A função do PC é apontar o endereço de memória onde a próxima instrução a ser executada encontra-se armazenada. A instrução apontada pelo PC é buscada e enviada ao decodificador seguindo os passos descritos na figura 1.15. Antes de completar a instrução corrente a CPU automaticamente incrementa o PC de forma que ele aponte sempre o endereço de memória da próxima instrução. O acumulador é utilizado principalmente nas operações lógicas e aritméticas. A maioria das CPUs utiliza o conteúdo do acumulador como um operando nas instruções aritméticas e lógicas (o outro operando pode ser um registrador ou um valor lido da memória). Como veremos mais adiante, os RL78 não possuem um registrador acumulador específico, ao invés disso existe um conjunto de registradores que podem também atuar como acumuladores. Outro componente importante da CPU é a unidade lógica e aritmética (ULA). Esse circuito lógico combinacional é utilizado por todas as operações aritméticas e lógicas. Na maioria dos sistemas, a ULA possui duas entradas (os operandos das operações): uma é geralmente conectada ao acumulador e a outra, a um registrador ou recebe um valor lido da memória. Os resultados das operações da ULA são normalmente armazenados no acumulador. 26 Microcontroladores RL78: Guia Básico Antes de retomarmos o tópico de programação, vejamos a diferença entre microprocessador e microcontrolador. Em poucas palavras, podemos dizer que microprocessador é um chip com uma CPU, ULA e circuitos básicos de suporte. Esses chips necessitam de memórias externas e outros chips para poderem realizar tarefas úteis. Já o microcontrolador é um chip que integra num mesmo encapsulamento a CPU, ULA, circuitos de suporte, memórias e periféricos. Um microcontrolador é frequentemente referido como um computador num único chip. A aplicação alvo de um microprocessador também é diferente daquela de um microcontrolador. Enquanto um microprocessador é projetado para ser utilizado em computadores e dispositivos computacionais (como tablets e smartphones) de uso geral, capazes de executar programas complexos e sistemas operacionais, um microcontrolador, por outro lado, é projetado para realizar tarefas específicas e executar programas mais simples (geralmente sem a necessidade de um sistema operacional). É cada vez mais complexo estabelecer uma distinção entre microprocessadores e microcontroladores, pois estes tornam-se mais e mais complexos e muitas vezes confundem-se com microprocessadores. Voltando ao tópico de programação, é fácil constatar que a utilização de números binários e opcodes para escrever um programa pode ser bastante trabalhosa, especialmente porque dificultam a leitura e o entendimento do código, além de aumentar a probabilidade de erros (inclusive aqueles oriundos de falhas de digitação). Por isso, ainda na década de 1950 surgiu a primeira linguagem de programação, o assembly. Na verdade, a linguagem assembly é somente uma representação simbólica dos opcodes. Utilizando um programa especial (chamado Assembler ou montador), os mnemônicos assembly são traduzidos diretamente para códigos binários (opcodes). Essa tradução é feita numa razão de um para um, ou seja, cada instrução assembly é traduzida em um único opcode. Sendo assim, para podermos programar uma máquina, é necessário primeiramente conhecer quais instruções essa máquina é capaz de entender e como utilizá-las corretamente. Considerando a CPU dos RL78, existem cinco instruções (de um conjunto de oitenta e uma) que podem ser utilizadas para implementar o programa descrito na listagem 1.1: CLRB: apaga o conteúdo de um registrador ou endereço da memória. CMP a,b: compara o conteúdo de uma registrador ou posição da memória (operando “a”) com o conteúdo do segundo operando (“b”), modificando os bits Z, CY e AY, de acordo com o resultado (a comparação é feita pela subtração do operando “b” do operando “a”). INC: adiciona um ao operando. BR: desvio incondicional para o endereço especificado. BZ: desvio para o endereço especificado no caso do flag Z = 1. A figura 1.16 apresenta uma adaptação do fluxograma da figura 1.13 utilizando instruções assembly do RL78. Introdução 27 Início CLRB CNT CMP CNT,#10 INC CNT Fim Figura 1.16 A listagem 1.2 mostra o programa codificado em linguagem assembly. Ele foi escrita com base em algumas considerações iniciais: 1. O programa é armazenado a partir do endereço 0x000CE (0x significa que o número está em hexadecimal). Este é normalmente o endereço inicial da memória flash para armazenamento de programas nos microcontroladores RL78; 2. A variável “cnt” está localizada no endereço 0xEF00 da memória, o primeiro endereço válido da memória RAM no modelo do RL78/G13 utilizado (o R5F100LE); 3. Utilizaremos o prefixo “N:” para especificar um endereço de 16 bits na memória do microcontrolador, esta é a notação utilizada pelo compilador IAR para representar o modo de endereçamento direto de 16 bits (maiores detalhes serão vistos no capítulo 3); 4. Uma constante (como o valor 10 decimal) é escrita precedida do símbolo #. Este símbolo indica ao assembler que o valor que o segue é uma constante imediata; 5. Os endereços e opcodes estão escritos em base hexadecimal. Analisando o fluxograma da figura 1.16 e a listagem 1.2, podemos entender o funcionamento do pequeno programa apresentado. É fácil perceber que a instrução CMP possui um importante papel no controle do programa. Endereço Opcode 000CE F500EF 000D1 000D5 4000EF0A DD07 000D7 000DA 000DC A000EF EFF7 CLRB repete: CMP BZ INC BR final: Assembly N:cnt N:cnt,#10 final N:cnt repete Comentários Apaga o conteúdo da memória cnt Compara o valor de cnt com 10 (cnt-10) Desvia para “final” se Z=1 (Z=1 comparação anterior cnt era igual a 10) Incrementa cnt em um Desvia para “repete” se na Listagem 1.2 28 Microcontroladores RL78: Guia Básico A instrução “CMP N:cnt,#10” realiza a comparação entre dois valores: o conteúdo da variável “cnt” e o valor imediato 10 decimal. Observando a coluna dos opcodes, encontramos o valor 0x4000EF0A, sendo 0x40 o código da instrução, 0x00EF o endereço do operando “cnt” na memória de dados (o endereço da variável é 0xEF00 e na instrução é escrito em formato little endian, iniciando pela parte menos significativa) e finalmente a constante com a qual deve ser feita a comparação (0x0A que é a representação hexadecimal de 10 decimal). Os termos little endian e big endian são utilizados em computação para especificar como uma máquina armazena dados numéricos de múltiplos bytes na memória. No formato little endian tais dados são armazenados na memória sempre iniciando-se pelo seu byte menos significativo, já no formato big endian, tais dados são armazenados na sua forma natural, ou seja, iniciando-se pelo byte mais significativo. Exemplo: o número 0x1234 hexadecimal é armazenado 0x34,0x12 no formato little endian e 0x12,0x34 no formato big endian! Observe que a comparação é realizada por meio de uma operação de subtração realizada no interior da ULA. De acordo com o resultado da comparação (subtração) alguns bits do registrador PSW são alterados: Z, AC e CY. Se o valor do contador for igual a 10, o bit Z é setado. Em seguida, a instrução “BZ final” é o chamado desvio condicional. Este tipo de instrução avalia uma condição e efetua o desvio do programa caso a condição seja verdadeira. No caso, a instrução avalia o estado do bit Z (localizado no registrador PSW) e desvia para “final” caso Z=1. Caso Z=0, a instrução não produz efeito e o programa segue a sua sequência natural. Note que o opcode da instrução é 0xDD07, onde 0xDD indica a instrução propriamente dita (BZ) e 0x07 é o endereço de destino do desvio. Nestas instruções o endereço de destino é escrito relativamente ao endereço da instrução de desvio, ou seja, o valor 0x07 indica que o endereço de destino é igual ao endereço de BZ (0x000D5) mais o deslocamento 0x07, ou seja, 0x000DC. A próxima instrução “INC N:cnt” faz o incremento do valor da variável “cnt”, ou seja, soma um ao conteúdo dela. Novamente podemos perceber que o opcode da instrução é 0xA000EF, onde 0xA0 indica a instrução INC e 0x00EF é o endereço little endian da variável “cnt”. A última instrução “BR final” provoca o desvio do fluxo do programa para o endereço indicado por “repete”, ou seja 0x000D1. O opcode da instrução é 0xEFF7, sendo 0xEF o código da instrução e 0xF7 o deslocamento do endereço de destino. Observe que neste caso o endereço de destino está localizado antes da instrução de desvio e por isso o deslocamento é negativo. O valor de deslocamento é calculado da seguinte forma: 0xD1 (o destino) – 0xDA (endereço onde está a instrução de desvio) = 0xF7. Note que 0xF7 é a representação em complemento de dois do número -9 decimal. Analisando o programa inteiro podemos perceber que inicialmente a variável “cnt” é iniciada em zero “CLRB N:cnt”, em seguida verificamos se o valor dela é igual a 10 “CMP N:cnt,#10”, caso negativo “BZ final”, o programa segue, incrementa a variável “INC N:cnt” e em seguida desvia “BR repete” para uma nova comparação. Quando a comparação da variável com Introdução 29 10 “CMP N:cnt,#10” resulta verdadeira (Z=1), o desvio condicional “BZ final” é tomado e o programa desvia para o endereço “final”! Esta foi apenas uma apresentação rápida da operação de uma CPU e de como uma sequência de instruções é executada. No decorrer do livro vamos explorar em mais detalhes o funcionamento de cada instrução dos RL78. 1.4. Microcontroladores RL78 A linha de microcontroladores RL78 da Renesas é derivada da união de duas linhas de microcontroladores: a linha 78K0R originalmente desenvolvida pela NEC e R8C da Renesas. Os microcontroladores RL78 são máquinas CISC de 16 bits que possuem como diferencial a sua alta eficiência, decorrente de duas características importantes das CPUs RL78: alta velocidade de execução de código (pois utilizam um pipeline de três estágios que faz com que 56% das instruções sejam executadas em apenas um ciclo de clock) e consumo de energia extremamente baixo (graças ao design focado principalmente na eficiência energética e a utilização de tecnologias de semicondutores de baixo consumo de energia), o consumo de energia, no melhor caso, é de aproximadamente 66µA/MHz. Um regulador interno de tensão também auxilia na redução do consumo de energia e permite que os RL78 apresentem níveis muito baixos de emissão eletromagnética (EMI). Além de consumirem pouca energia quando em operação, a existência dos modos de baixo consumo de energia halt, stop e snooze permite reduzir grandemente o consumo de energia quando a CPU não está em operação. Em termos de performance, os RL78 podem operar até 32MHz, executam a maioria das instruções em 1 ou 2 ciclos de clock e possuem capacidade de endereçamento de até 1MiB, permitindo que o fabricante disponibilize grandes quantidades de memória flash e RAM (até 512KiB de flash e até 32KiB de RAM nos modelos mais poderosos lançados até o momento). A linha de periféricos inclui unidades de temporização TAU onde cada canal de 16 bits pode atuar praticamente como um timer independente, relógio de tempo real com calendário, timer de intervalo, timer para controle de motores (até 6 canais de PWM), interfaces de comunicação serial (síncronas SPI e I2C, assíncronas UART/LIN e USB), conversor A/D de 8, 10 ou 12 bits (com capacidade de varredura de 4 canais), conversor D/A, comparadores analógicos, controlador de displays LCD, etc. Praticamente todos os modelos contam com DMA (Direct Memory Access - acesso direto a memória) de 1 ou 2 canais, que permite automatizar as transferências entre os periféricos e a memória, dispensando a intervenção da CPU. Além de facilitar a transferência de dados entre a memória e os periféricos, o DMA também pode auxiliar na redução do consumo de energia (permitindo fazer transferências enquanto a CPU está em modo halt). A maioria dos modelos (exceto os G10) possui suporte a divisão e multiplicação, em alguns modelos por meio de um módulo periférico de hardware, em outros, por meio de instruções DSP especiais (RL78/G14). 30 Microcontroladores RL78: Guia Básico Também estão disponíveis periféricos de segurança como, por exemplo, checagem de erros na memória flash (ECC com CRC) e RAM (paridade), watchdog com janela de tempo, detector de baixa tensão, detecção de falha de oscilador e de acesso a endereço ilegal da memória. A linha RL78 é composta dos seguintes membros: Modelos de uso geral: • RL78/G10 – com versões de 10 e 16 pinos, capacidades de memória flash de 1KiB até 4KiB e memória RAM de 128 até 512 bytes. Estes microcontroladores possuem núcleo de 8 bits e operam a até 20MHz, incluem interfaces de comunicação como UART, SPI e I2C (nos modelos de 16 pinos), conversor A/D de 10 bits, comparador analógico (nos modelos de 16 pinos) e são os elementos de uso geral e mais baixo custo da linha RL78. Nestes chips a faixa de tensões de alimentação vai de 2,0 a 5,5V. • RL78/G12 - com versões de 20, 24 e 30 pinos, capacidades de memória flash de 2KiB até 16KiB, memória RAM de 256 bytes até 2KiB e dataflash até 2KiB. Estes microcontroladores operam a até 24MHz, incluem interfaces de comunicação como UART, SPI e I2C, conversor A/D de 10 bits, DMA (em alguns modelos) e juntamente com os G10 são os elementos de uso geral e mais baixo custo da linha RL78. o • RL78/G13 - com versões de 20 a 128 pinos, capacidades de memória flash de 16KiB até 512KiB, memória RAM de 2KiB até 32KiB e dataflash de 4 ou 8KiB. Estes microcontroladores operam a até 32MHz, incluem múltiplas interfaces de comunicação como UART, SPI, I2C, conversor A/D de 10 bits, DMA e são voltados ao uso geral em aplicações de pequena e média complexidade. o • RL78/G1C - com versões de 32 e 48 pinos, capacidade de memória flash de 32KiB, memória RAM de 5,5KiB e dataflash de 2KiB. Estes microcontroladores operam a até 24MHz e incluem interfaces de comunicação como UART, SPI, I2C e USB 2.0 full speed (12Mbits/s) capaz de operar como host ou device e compatível com a versão 1.2 da especificação de carga de bateria pela porta USB (até duas portas USB disponíveis). RL78/G1A - com versões de 25 a 64 pinos, capacidades de memória flash de 16KiB até 64KiB, memória RAM de 2KiB até 4 KiB e dataflash de 4KiB. Estes microcontroladores operam a até 32MHz, incluem interfaces de comunicação como UART, SPI e I2C, DMA e um conversor A/D de 12 bits. RL78/G14 - com versões de 30 a 100 pinos, capacidades de memória flash de 16KiB até 256KiB, memória RAM de 2,5KiB até 24KiB e dataflash de 4 ou 8KiB. Estes microcontroladores operam a até 32MHz, além dos periféricos da linha G13, incluem instruções DSP para processamento digital de sinais, timer para controle de motores, D/A de 8 bits e comparador analógico. Eles são os membros mais avançados da linha RL78 e são voltados ao uso geral em aplicações de média complexidade. Com controlador de display LCD integrado: Introdução 31 • RL78/L12 - com versões de 32 a 64 pinos, capacidades de memória flash de 8KiB até 32KiB, memória RAM de 1KiB até 1,5KiB e dataflash de 2KiB. Estes microcontroladores operam a até 24MHz e incluem controladores para displays LCD com até 280 segmentos (13 a 39 segmentos com 4 planos ou 18 a 35 segmentos com 8 planos). • RL78/L13 - com versões de 64 e 80 pinos, capacidades de memória flash de 16KiB até 128KiB, memória RAM de 1KiB até 8KiB e dataflash de 4KiB. Estes microcontroladores operam a até 24MHz e incluem controladores para displays LCD com até 376 segmentos (36 a 51 segmentos com 4 planos ou 32 a 47 segmentos com 8 planos). Modelos destinados a aplicações específicas: • RL78/D1x - com versões de 48 a 100 pinos, capacidades de memória flash de 24KiB até 256KiB, memória RAM de 2KiB até 16KiB e dataflash de 8KiB. Estes microcontroladores operam a até 32MHz e incluem controladores para displays LCD com até 212 segmentos (4 planos com até 53 segmentos), controlador de motor de passo e gerador de som, são voltados a aplicações de mostradores e painéis automotivos. • RL78/F1x - com versões de 20 a 64 pinos, capacidades de memória flash de 8KiB até 64KiB, memória RAM de 512 bytes até 4KiB e dataflash de 4KiB. Estes microcontroladores operam a até 32MHz, suportam temperaturas de até 150ºC e são voltados para aplicações automotivas em dispositivos de carroceria (car body). • RL78/I1x - com versões de 20 a 38 pinos, capacidades de memória flash de 32KiB até 64KiB, memória RAM de 2KiB até 4KiB e dataflash de 4KiB. Estes microcontroladores operam a até 32MHz, com tensões de alimentação de 2,7 a 5,5V e incluem controladores PWM para leds , UART com suporte a DALI e DMX512 e são voltados a aplicações de controle de iluminação e correção de fator de potência. 1.5. Pinagens e Encapsulamentos Abaixo apresentamos a pinagem de alguns modelos de RL78: Figura 1.17 – Modelos de 10 pinos (RL78/G10) 32 Microcontroladores RL78: Guia Básico Figura 1.18 – Modelos de 20 pinos (RL78/G12) Figura 1.19 – Modelos de 20 pinos (RL78/G13) Figura 1.20 – Modelos de 30 pinos (RL78/G13) Introdução 33 Figura 1.21 – Modelos de 64 pinos (RL78/G13) Pinos especiais: • VDD - alimentação positiva (1,6 a 5,5 Volts, nos G10 é de 2,0 a 5,5V) • EVDD0 - alimentação positiva (1,6 a 5,5 Volts) para as portas P0, P1, P3, P4, P5, P6, P7 e P14 • VSS - referência de terra (0 Volt) • EVSS0 - referência de terra (0 Volt) para as portas P0, P1, P3, P4, P5, P6, P7 e P14 • REGC - estabilização do regulador interno (conectar um capacitor de 0,47 a 1µF) • RESET - sinal de reset ativo em nível lógico “0” • P40/TOOL0 – pino de E/S (bit 0 da porta 4) e pino de programação/depuração (TOOL0) Cuidado ao utilizar o pino TOOL0 como E/S na aplicação, pois cargas muito elevadas neste pino podem prejudicar a programação e a depuração do chip no circuito! 34 Microcontroladores RL78: Guia Básico 1.6. R5F100LEA O microcontrolador objeto de estudo deste livro é o R5F100LEA, um membro da linha RL78/G13 de microcontroladores da Renesas. Ele inclui uma CPU RL78, além de 64kibibytes de memória flash, 4.096 bytes de memória RAM e 4.096 bytes de memória dataflash. Este chip pode operar a até 32MHz e a tensão de alimentação pode ir de 1,6 a 5,5 Volts. Além das características gerais dos RL78/G13, o R5F100LEA inclui também: • 58 pinos de entrada/saída, divididos em 11 portas de entrada/saída (E/S): P0, P1, P2, P3, P4, P5, P6, P7, P12, P13 e P14; • Diversos pinos podem ser configurados para operar como saídas dreno aberto e podem fazer interface com outros níveis de tensão (desde que dentro da faixa de 1,6 a 5,5V); • Seis pinos de interrupção externa, com borda de sensibilidade configurável; • Oito pinos de interrupção de teclado (geram interrupção ao mudar de estado); • Quatro diferentes periféricos de temporização: o Duas unidades de temporização TAU, cada uma com 8 canais (total de 16 canais). Cada canal do TAU pode operar como um timer independente ou ser utilizado em conjunto com outros canais. Os canais dos TAU podem fazer captura de sinais (medição de período), comparação (geração de interrupção ou sinais de largura definida), PWM, etc. o Relógio de tempo real com calendário e interrupção de alarme, que pode operar com clock externo de 32768Hz ou com clock interno de 15kHz; o Timer de interrupção periódica (12 bits) que pode ser utilizado para criar bases de tempo; o Watchdog programável com operação em “janela de tempo”. • Dois tipos de interface de comunicação (até 7 portas seriais simultâneas): o Duas unidades seriais SAU, que podem operar no modo SPI de 3 fios, UART ou I2C simplificado* (a SAU0 pode operar como 4 canais SPI/I2C ou 2 canais UART, a SAU1 pode operar como 2 canais SPI/I2C ou 1 canal UART com suporte a LIN); o Uma unidade I2C completa. A interface I2C simplificada não pode operar no modo escravo e nem suporta o modo multimaster. • Conversor A/D de 10 bits com 12 canais de entrada, taxa de conversão de até 470ksps (mil amostras por segundo), varredura de até 4 canais, comparador digital interno e capacidade de operação em modo snooze; • Quatro canais de DMA, cada canal pode transferir blocos de até 1024 bytes ou words (um byte ou word a cada disparo). Introdução 35 1.7. Kits e Ferramentas de Programação A Renesas possui uma série de kits disponíveis para facilitar o aprendizado e desenvolvimento de aplicações com o RL78. O kit mais acessível é o YRPBRL78G13, também chamado de “Promotion Board” do RL78/G13. Este kit consiste numa PCI contendo um R5F100LEA e um microcontrolador 78F0730, que atua como programador e depurador USB. Figura 1.22 – YRPBRL78G13 A placa possui também dois leds, um cristal de 32.768Hz conectado ao oscilador secundário do RL78, um trimpot, duas fileiras de pads conectados aos pinos de E/S do chip e um conector para programação do RL78 através de um programador E1 externo. Também existem jumpers que podem ser utilizados para medição do consumo de corrente do chip. A figura 1.23 mostra as conexões das duas fileiras de 30 pinos nas bordas da placa (o pino 1 é indicado na borda da placa). Não conectado P30 P05 P06 P147 P146 P137 P41 P42 P43 P120 T_RESET P27 P26 P25 P24 P23 (conectado ao trimpot R15) P22 AVREFM AVREFP P130 P04 P03 P02 P01 P00 P141 P140 VDD GND Não conectado P70 P71 P72 P73 P74 P75 P76 P77 (conectado ao LED D2) P31 P63 P62 P61 P60 P50 P51 P52 P53 P54 P55 P17 P16 P15 P14 (recebe dados da COM virtual) P13 (transmite dados para a COM virtual) P12 P11 P10 VDD GND Conector E1 Figura 1.23 36 Microcontroladores RL78: Guia Básico Para desenvolvimento de aplicações mais avançadas o “Starter kit” ou RSK do RL78/G13 inclui 4 leds, 3 teclas de usuário, módulo de display LCD de 8 caracteres por 2 linhas, cristal de 20MHz e de 32.768Hz, conector para depurador E1, porta serial DB9 e interface LIN. O kit inclui um depurador E1 que pode ser utilizado para programar e depurar qualquer microcontrolador RL78, RX e alguns modelos do R8C, 78K e V850. Figura 1.24 – Starter kit do RL78/G13 Figura 1.25 – Depurador/programador E1 Outro kit bastante interessante e que inclui uma quantidade de periféricos muito maior que os anteriores, é o “Demonstration kit” do RL78/G14. Ele utiliza um microcontrolador R5F104PJA (256KiB de flash, 8KiB de dataflash e 24KiB de RAM num encapsulamento de 100 pinos) e inclui diversos periféricos interessantes na placa: módulo Wi-Fi GainSpan GS1011, display LCD TFT gráfico de 1,5 polegadas, display Eink com seis segmentos, conector para cartão MicroSD, acelerômetro de 3 eixos, sensor de temperatura, EEPROM I2C de 512kib, memória flash SPI de 8Mib (conectada ao módulo Wi-Fi), sensor de luz, microfone, alto falante, sensor de IR, led IR, conector serial DB9, treze leds de usuário, 4 teclas (1 reset), potenciômetro, FET com conector externo, TRIAC isolado com conector externo, portas de expansão e depurador TK integrado com conector USB. Figura 1.26 – Demonstration kit do RL78/G14 Introdução 37 1.8. Convenções Utilizadas No decorrer deste livro utilizamos algumas convenções para representação de símbolos, nomes e outros termos técnicos: • Este livro utiliza as unidades de informação padronizadas pela Comissão Internacional de Eletrotécnica (IEC) em 2000, as quais foram criadas para ajudar na diferenciação entre os padrões decimais (utilizados no cotidiano) e os padrões binários (utilizados para representar grandezas binárias, comuns no mundo da computação digital): Prefixo Padrão (Sistema Internacional) Prefixo Símbolo Peso Kilo k 103 6 Prefixo Binário (Sistema Internacional) Prefixo Símbolo Peso kibi Ki 210 mebi Mi 220 Mega M 10 Giga G 109 gibi Gi 230 Tera T 10 12 tebi Ti 240 Peta P 1015 pebi Pi 250 E 18 exbi Ei 260 Exa 10 Tabela 1.5 Note que 1024 bytes são 1KiB e 1024 bits são 1Kibit! 38 • Referências a nomes de bit e nomes de registrador são feitas sempre utilizando letras maiúsculas. • As referências aos nomes dos bits são feitas sempre utilizando o nome ou a associação do nome do registrador e o nome do bit no seguinte formato: REGISTRADOR.BIT. Assim, a referência ao bit Z do registrador PSW pode ser feita apenas ao nome do bit (Z) ou PSW.Z. • Para representar genericamente um conjunto de registradores ou bits pertencentes a um periférico ou registrador, utilizamos a letra “x” minúscula. Assim, o termo Px representa qualquer um dos seguintes registradores: P0, P1, P2, etc. No caso dos timers, TAUx poderá significar TAU1 ou TAU0 e assim por diante. • Os símbolos C utilizados neste livro são aqueles definidos e fornecidos pela IAR. Os registradores e bits específicos que podem ser manipulados diretamente pelo código em C estarão sempre grafados em letras maiúsculas. Os símbolos escritos com a primeira letra minúscula “b” referem-se aos bits dos registradores e somente devem ser utilizados nas operações envolvendo registradores. Por exemplo: para se setar o bit RTCEN (registrador PER0) é possível escrever RTCEN = 1 (uma operação de manipulação direta de bit) ou ainda PER0 = bRTCEN (uma operação de escrita de 8 bits no registrador). Os símbolos bXXXX estão definidos no arquivo myRL78.h. Microcontroladores RL78: Guia Básico • No decorrer do texto, as palavras reservadas da linguagem C estão escritas em negrito. • As notas importantes são apresentadas utilizando a seguinte caixa de texto: Esta é uma nota importante! As dicas de utilização utilizam a seguinte caixa de texto: • Esta é uma dica! • Os registradores do microcontrolador são representados por figuras como a mostrada a seguir: Registrador LVIM (Exemplo) Nome BIT 7 Leitura LVIM Escrita Reset BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 LVISEN 0 0 0 0 0 0* 0 0 0 0 0 BIT 1 BIT 0 LVIOMSK LVIF 0 0 0* 0* * Após um reset LVD este registrador não é alterado. Nome do Bit Descrição LVISEN Controle de escrita no registrador LVIS: 0 – escrita desabilitada (não produz efeito) 1 – escrita habilitada LVIOMSK Máscara de estado de saída do LVD: 0 – LVD operando normalmente 1 – LVD em estabilização LVIF Indicador de status do LVD: 0 – tensão (VDD) ≥ valor configurado (VLVD) (ou quando o LVD está desligado) 1 – tensão (VDD) < valor configurado (VLVD) Bit C Símbolo C LVISEN bLVISEN LVIOMSK bLVIOMSK LVIF bLVIF Vejamos como ler a tabela: Existem três linhas rotuladas “Leitura”, “Escrita” e “Reset”. A primeira e a segunda linhas indicam a função de cada bit na sua leitura e escrita respectivamente. A linha “Reset” indica o estado de cada bit após um reset. Os bits 0 e 1 deste registrador são do tipo “somente leitura”, o que significa que eles somente podem ser lidos pelo software, mas não modificados por ele. A leitura do bit 0 do registrador retorna o estado do bit LVIF, mas a escrita no mesmo não produz efeitos. Da mesma forma, a leitura do bit 1 retorna o estado do bit LVIOMSK, mas a escrita não produz efeitos. Os bits 2 a 6 não são implementados e a leitura deles retorna sempre o valor “0”. Normalmente se recomenda escrever somente “0” nos bits não implementados. Alguns bits Introdução 39 podem apresentar um “?” no seu estado de reset. Isso significa que ele não é alterado após um reset. O bit 7 (LVISEN) pode ser lido ou escrito pelo software. Desta forma, supondo que o registrador LVIM possua o valor 0x00, após a seguinte linha de código: LVIM = 0x81; O registrador irá conter o valor 0x80 (já que o bit 0 não é alterado pelo programa). Observe que os símbolos definidos na coluna “Bit C” estão incluídos nos headers do chip e são fornecidos juntamente com o compilador (pasta include dentro da pasta onde foi instalado o compilador IAR). Cada modelo de microcontrolador possui dois arquivos header com as definições dos seus registradores SFR e GPR: o arquivo “ior5f10xxx.h” para os SFR principais e “ior5f10xxx_ext.h” para o conjunto de registradores estendido. No caso do microcontrolador utilizado neste livro (R5F100LE) os arquivos header são "ior5f100le.h" e "ior5f100le_ext.h". Os símbolos mostrados na coluna “Símbolo C” estão definidos no arquivo “myRL78.h” que pode ser baixado juntamente com os projetos deste livro. 40 Microcontroladores RL78: Guia Básico 2 Ferramentas de Programação 2. Ferramentas de Programação 2.1. O Ambiente Embedded Workbench EWRL78 O ambiente IAR Embedded Workbench for RL78 (EWRL78) é um IDE que integra editor, compilador, assembler, linker, simulador e depurador em um único software. Os leitores dos livros “MSP430: Teoria e Prática” e “Tecnologia ARM: Microcontroladores de 32 bits” irão perceber que o EWRL78 (como é chamado o Embedded Workbench para os RL78) é muito semelhante ao EW430 e EWARM. Esta identidade de ambientes é sem dúvida uma vantagem para os desenvolvedores que necessitam trabalhar com múltiplas plataformas, pois o tempo gasto com a familiarização com a ferramenta de programação é amplamente reduzido. 2.1.1. Criando o Primeiro Projeto No decorrer deste tópico o leitor poderá aprender como configurar corretamente o ambiente EWRL78 (versão 1.20) e a criação de um projeto em linguagem C. Para criar um novo projeto no IAR, é necessário selecionar a opção “Create a New Project” dentro do menu principal. Figura 2.1A Figura 2.1B Em seguida, devemos selecionar a linguagem de programação a ser utilizada no projeto. Nos exemplos deste livro, utilizaremos a linguagem C, por isso, a seleção deve ser feita conforme a figura 2.1A. Uma vez selecionada a linguagem é necessário dar um nome ao projeto, conforme demonstra a figura 2.1B. Ferramentas de Programação 41 Feito isso, teremos uma tela igual a representada na figura 2.2. Nela encontramos a janela do workspace atual (2), a janela de edição de código fonte (3) e a janela de mensagens da IDE (4) e a seleção do modo do projeto (1). 1 3 2 4 Figura 2.2 O projeto inclui um arquivo genérico “main.c” que consiste no mínimo de código necessário a um programa em C, ou seja, apenas a função principal (main). Vencida esta etapa é necessário configurar o projeto. Para isso, selecione a opção Project > Options... no menu principal ou, alternativamente, pressione as teclas ALT+F7, ou ainda, pressione o botão direito do mouse sobre a janela do workspace e selecione a opção Options no menu flutuante. A janela de opções (figura 2.3) será exibida. As configurações de projeto feitas para o modo “Debug” (item 4 da figura 2.2) deverão ser feitas também para o modo “Release”. O modo “Debug” é útil durante a fase de desenvolvimento e testes da aplicação, ao passo que a o modo “Release” é utilizado para geração do código final (normalmente um arquivo .hex para gravação em produção). Nesta janela, o programador irá selecionar o modelo de RL78 utilizado (no campo Device), além do modelo de memória a ser utilizado para o código (Code model) e dados (Data model) e como as constantes “near” serão colocadas na memória. Modelos “near” utilizam apenas um segmento de 64KiB de memória, ao passo que modelos “far” utilizam todo o espaço de 1MiB de endereçamento. Preferencialmente devemos utilizar modelos “near”, pois eles geram códigos menores e mais rápidos que os gerados com modelos “far”. 42 Microcontroladores RL78: Guia Básico Pressione este botão para selecionar a CPU Figura 2.3 Ainda na categoria “General Options”, clique na aba “Library Configuration”. Ali é possível selecionar o tipo de biblioteca padrão C que será utilizada com o projeto (“Normal DLIB”, “Full DLIB” ou “Custom”) e também é possível selecionar se o compilador deve ou não utilizar o hardware de multiplicação integrado (“Use hardware multiplier/divider unit”). Esta opção, ao ser selecionada, faz com que o compilador inclua uma pequena biblioteca (cerca de 260 bytes) que faz com que o multiplicador/divisor por hardware seja utilizado para acelerar as operações de divisão e multiplicação. Cabe ao programador decidir sobre a necessidade ou não de se utilizar o hardware multiplicador/divisor interno, mas via de regra, se você tiver 260 bytes de flash sobrando, os benefícios em termos de ganho de velocidade valem o espaço adicional necessário. Além das configurações da categoria “General Options” é importante também configurarmos outras opções. Na categoria “C/C++ compiler”, verifique a aba “Output” e certifique-se de que a opção “Generate debug information” esteja selecionada. Esta opção faz com que o compilador gere informações adicionais necessárias à depuração do programa. Na aba “Optimizations” é possível configurar algumas opções de otimização de código. Por hora não iremos nos preocupar com isso, mas para produção de código final, é importante utilizar a otimização máxima do compilador (“level high”). Note que é possível otimizar o programa para ocupar menos espaço (Optimize for space), para ser executado mais rapidamente (optimize for speed) ou para a melhor relação custo/benefício entre velocidade e tamanho (balanced). Na categoria “Linker”, aba “Output”, é importante que a opção “Debug information for CSPY” esteja selecionada. Ela é responsável por gerar código de depuração necessário para que a ferramenta C-SPY possa funcionar corretamente. Ferramentas de Programação 43 Ainda na categoria “Linker” é possível selecionar outro arquivo de configuração do linker. Isto é necessário quando se necessita modificar a forma como o linker utiliza e distribui código e dados na memória do microcontrolador. Um exemplo típico é o uso das bibliotecas FSL, FDL ou EEL para armazenamento de dados na flash, todas elas necessitam de modificações na configuração do linker para poder operar corretamente. Adicionalmente, pode ser interessante configurar o linker para gerar um arquivo de informações sobre a utilização e alocação da memória. Para isso, basta selecionar a aba “List” e habilitar a opção “Generate linker listing”. O arquivo .map gerado irá conter diversas informações acerca da distribuição das funções e símbolos na memória do chip. Também é possível verificar a quantidade de memória flash e RAM utilizada. Seleção do depurador a ser utilizado pelo EWRL78 Figura 2.4 Finalmente, o último passo para configuração do projeto consiste em selecionar o tipo de depurador a ser utilizado. Esta seleção será realizada conforme o tipo de hardware de depuração disponível. Normalmente iremos optar entre o simulador e um depurador externo como o TK ou E1. A opção pelo simulador (figura 2.4) pode ser interessante para se testar trechos de código, desde que estes não utilizem nenhum periférico dos RL78, pois o simulador da IAR não simula periféricos internos do microcontrolador. Uma vez que o projeto esteja configurado, podemos nos dedicar ao programa propriamente dito. Assim, o arquivo “main.c” do projeto recém criado deve ser alterado conforme a listagem do exemplo 2.1. Este programa exemplo irá fazer com que o led da placa de demonstração do RL78 pisque. #include #include #include #include "ior5f100le.h" "ior5f100le_ext.h" "intrinsics.h" "myRL78.h" // Configura watchdog = desligado #pragma location = "OPTBYTE" __root __far const char opbyte0 = WDT_OFF; // Configura detector de baixa tensão = desligado #pragma location = "OPTBYTE" 44 Microcontroladores RL78: Guia Básico __root __far const char opbyte1 = LVD_OFF; // oscilador 32MHz flash high speed #pragma location = "OPTBYTE" __root __far const char opbyte2 = FLASH_HS | CLK_32MHZ; // debug ativado, com apagamento em caso de falha de autenticação #pragma location = "OPTBYTE" __root __far const char opbyte3 = DEBUG_ON_ERASE; /* Configura security ID */ #pragma location = "SECUID" __root __far const char senha[10] = {0,0,0,0,0,0,0,0,0,0}; #define LED_D2 P7_bit.no7 unsigned long int temp, cnt; void main( void ) { PM7_bit.no7 = 0; // porta P77 como saída cnt = 0; while (1) { LED_D2 = 1; for (temp=100000;temp;temp--); LED_D2 = 0; for (temp=100000;temp;temp--); cnt++; } } Exemplo 2.1 – Pisca led por software Uma vez que o programa tenha sido digitado (ou carregado) corretamente, a aparência do IDE deve ser próxima a da figura 2.5. Podemos então passar a etapa de compilação e depuração. Para proceder à compilação e montagem completa do projeto, basta clicar no botão MAKE indicado na figura 2.5. O IDE irá automaticamente compilar e “linkar” o programa, gerando os arquivos binários conforme selecionado nas opções do projeto. O mesmo efeito pode ser obtido pressionando-se a tecla F7 ou selecionando-se a opção Project>Make no menu principal. DEBUG Depurar o projeto atual MAKE Compilar o projeto atual Figura 2.5 Ferramentas de Programação 45 Após o processo, a janela de mensagens da IDE estará mostrando, na aba Build, as mensagens emitidas pelo compilador e pelo linker. Caso a mensagem exibida seja diferente de “Total number of errors: 0” e “Total number of warnings: 0”, verifique o código digitado a procura de erros. 2.1.2. Simulando um Programa Após termos compilado o programa, podemos passar ao teste do mesmo. Primeiramente iremos testar o programa utilizando o simulador do EWRL78. Para isso é necessário selecionar a opção simulator na janela de opções do projeto conforme a figura 2.4. Pressionando-se o botão DEBUG (figura 2.5), poderemos dar início a uma sessão de depuração utilizando o simulador. Após pressionar o botão DEBUG, a tela do IDE deverá passar a ser aquela da figura 2.6. Botões do depurador Go to Janela de disassembly Figura 2.6 – Depurador do EWRL78 Repare que a janela de mensagens apresenta informações na aba Debug Log, informando que o download foi completado e que o Target (dispositivo alvo, que no caso é o simulador) foi ressetado. Além disso, temos uma nova janela (Disassembly) e uma barra de botões do depurador. A janela Disassembly apresenta uma visão da memória de programa do chip, incluindo os endereços de memória, o conteúdo hexadecimal e a instrução assembly correspondente. Permeando as instruções assembly encontramos linhas de código C: as instruções seguintes a cada linha de código C representam as instruções necessárias para executar a tarefa determinada pela linha de código de alto nível. 46 Microcontroladores RL78: Guia Básico O campo “Go to” permite visualizar o código a partir de um endereço específico, por exemplo: se o programador desejar visualizar o código a partir do endereço 0x2000, basta entrar com este valor no campo “Go to” e pressionar a tecla ENTER. As linhas destacadas em fundo verde representam o próximo comando/instrução a ser executado A barra de botões do depurador permite controlar a execução do programa: estão disponíveis botões para executar o programa, paralisar a execução, execução passo a passo, criação de breakpoints, etc. A figura 2.7 apresenta a função de cada um dos botões. Saída do modo de depuração; Executa o programa até um ponto de parada (breakpoint) ou o término do programa (tecla F5); Executa o programa até o ponto em que se encontra o cursor; Pula para o próximo comando (o atual é executado sem visualização no depurador) (tecla F10); Executa o programa até o término da função atual (teclas SHIFT + F11); Executa a próxima instrução ou comando (passo a passo) (tecla F11); Executa a próxima instrução ou comando (se for uma chamada de função, ela é inteiramente executada e o controle retorna para a instrução seguinte à chamada); Para a execução do programa; Reset do processador. Figura 2.7 – Botões de controle do depurador Utilizando a execução passo a passo (tecla F10), podemos acompanhar exatamente o que ocorre com a CPU RL78 durante a execução dos comandos C ou das instruções assembly. Observe que se a janela selecionada for a disassembly, a execução passo a passo do programa será feita instrução por instrução assembly. Se a janela selecionada for a do código fonte em C, a execução do programa será de comando por comando C. Além de executar o programa é possível visualizar o estado dos registradores da CPU e dos periféricos, além do conteúdo das variáveis e da memória. Para visualizar o conteúdo dos registradores é necessário selecionar a opção View > Register no menu principal. Isto fará com que a janela Register (figura 2.8) seja apresentada na tela. A janela “Register” pode ser utilizada para visualizar e alterar o conteúdo tanto dos registradores da CPU (conforme mostra a figura 2.8) como de qualquer registrador de periféricos. Para selecionar o conjunto de registradores a ser apresentado, basta utilizar a caixa drop-down localizada no topo da janela. Ferramentas de Programação Seleção do conjunto de registradores a ser visualizado Contadores de ciclos Figura 2.8 – Janela de registradores 47 Agora que já vimos os procedimentos para execução do programa, o próximo passo é visualizarmos o conteúdo das variáveis. No presente caso, iremos nos limitar a visualizar as variáveis globais “temp” e “cnt”. Para isso, basta selecionar a opção View > Statics no menu principal, o que irá fazer com que a janela da figura 2.9A seja apresentada. Figura 2.9A Figura 2.9B Repare que estão listados outros símbolos globais, como os bytes de opção (option bytes) e a variável “temp”, que aparece na última linha. Também são apresentados os endereços onde os símbolos estão armazenados. No caso da variável “temp”, o endereço da mesma é 0xFEF00. Caso necessário, também é possível alterar o formato de visualização da variável, bastando clicar com o botão direito do mouse sobre a mesma e no menu flutuante selecionar a opção desejada (figura 2.9B). Também é possível alterar o valor de qualquer variável, basta clicar sobre ela e digitar o novo valor seguido da tecla ENTER. Uma outra possibilidade interessante é a janela de visualização em tempo real “Live Watch”, ela permite que se acompanhe a alteração do conteúdo das variáveis em tempo real, ou seja, durante a execução do programa. Selecionando a opção View > Live Watch no menu principal será apresentada uma janela similar a da figura 2.10A, onde podem ser inseridas as variáveis cujo conteúdo se deseja visualizar em tempo real. Figura 2.10A Figura 2.10B Por padrão, o conteúdo da janela “Live Watch” é atualizado a cada segundo (1000ms), mas este valor pode ser modificado na janela de opções da IDE (Tools > Options no menu principal). A figura 2.10B mostra esta janela e o campo para alteração do intervalo de atualização da janela “Live Watch”. Outra característica importante é a criação de breakpoints (pontos de parada) que são utilizados para interromper a execução do programa. Os breakpoints permitem que o 48 Microcontroladores RL78: Guia Básico programador possa paralisar o programa em um determinado ponto ou no instante em que uma determinada condição ocorra (breakpoints condicionais). Primeiramente, iremos criar um breakpoint de código, que consiste em marcar uma determinada linha de código ou um endereço de memória que ao ser atingido, a execução do programa é suspensa. Para fazer isso, basta um duplo-clique na área cinza que precede a linha de código na janela do código fonte. A título de exemplo, sugerimos que se dê um duplo-clique na linha de programa indicada como breakpoint 1 na figura 2.11. Ao fazer isso, surgirá um círculo vermelho em frente a linha, indicando que a mesma possui um breakpoint ativo. Antes de prosseguirmos com os testes é interessante que o leitor habilite a janela de breakpoints, de forma a poder visualizar e selecionar os breakpoints marcados. Para fazer isso, basta selecionar a opção View > Breakpoints no menu principal. Breakpoint 1 Breakpoint 2 Janela de breakpoints Figura 2.11 – Breakpoints Uma vez que tenha marcado o breakpoint e ativado a janela de breakpoints, a aparência do IDE deve ser aproximadamente igual a da figura 2.11. Se o leitor desejar, poderá iniciar a execução do programa pressionando a tecla F5 e verá que o programa será executado até encontrar o ponto marcado como breakpoint 1 na figura 2.11. Até aqui, nada mais fizemos do que criar breakpoints de código. No entanto, podemos adicionar inteligência ao mesmo: clique com o botão direito do mouse sobre a variável “temp” no código fonte, no menu que irá surgir (figura 2.12A), selecione a opção “Set Data Breakpoint for ‘temp’”. Um novo breakpoint será adicionado na janela de breakpoints (figura 2.12B). Ferramentas de Programação 49 Figura 2.12A Figura 2.12B Figura 2.12C Clicando-se com o botão direito do mouse sobre o data breakpoint na janela de breakpoints e selecionando-se a opção “Edit” será apresentada a janela da figura 2.12C, na qual é possível preencher a condição desejada para que o programa seja interrompido (no caso o programa irá parar quando “temp” atingir o valor 10000). Se o programa for executado (tecla F5), o leitor poderá observar que a execução será paralisada na linha do comando for e no mesmo instante, a janela de visualização das variáveis estáticas estará indicando que a variável “temp” possui o valor 10000, exatamente o que seria de se esperar. Desta forma, criamos um breakpoint condicional. Finalmente é importante saber que é possível desabilitar temporariamente um breakpoint. Para isso, basta clicar sobre a marca em frente ao mesmo na janela de breakpoints. Um breakpoint desabilitado é representado como um círculo vermelho preenchido de branco. Uma característica interessante do simulador é a disponibilidade de dois contadores de ciclos (CCTIMER1 e CCTIMER2), que podem ser utilizados para se efetuar medições do tempo de execução do programa ou de trechos do mesmo, inclusive com a possibilidade de alterar o conteúdo dos mesmos de forma a facilitar as medições. Estes contadores estão disponíveis na janela de visualização de registradores da CPU do simulador. As figuras 2.13 e 2.14 demonstram a utilização do contador de ciclos para medição do intervalo de tempo transcorrido durante uma chamada à função atraso no nosso programa exemplo. Na figura 2.13, o CCTIMER1 foi zerado manualmente antes de executar o comando for. Figura 2.13 A figura 2.14 mostra o conteúdo do CCTIMER1 após a execução do laço for. Observe que o conteúdo do mesmo é apresentado em vermelho, indicando que o mesmo foi alterado desde o último comando do depurador. 50 Microcontroladores RL78: Guia Básico