Primeiras experiências com o RL78

Olá, neste segundo artigo vou apresentar as minhas primeiras experimentações com o RL78/G13. Vou iniciar com a versão “MCU” do famoso “hello world!”, ou seja, um programa que pisca o led D2 no kit do RL78. Quem ainda não conhece o RL78, pode dar uma olhada no meu artigo com a apresentação do chip e do kit.

Apesar de ser uma aplicação (se é que podemos chamar isso de aplicação) extremamente simples, escrever um programinha como este permite-nos conhecer alguns dos detalhes importantes da arquitetura.

Para piscar um led é necessário configurar o pino do microcontrolador (ao qual o led está conectado) como saída e em seguida escrever “1” e “0” alternadamente neste pino, com um intervalo de tempo apropriado entre cada operação.

Neste primeiro exemplo, não vamos utilizar os timers internos do microcontrolador para controlar o processo de ligar e desligar o led, em vez disso vamos utilizar um atraso por software (através de um loop for em C).

A primeira medida que devemos tomar então é a de configurar como saída o pino ao qual o led está conectado. No kit do RL78/G13, o led D1 está conectado ao VDD (e portanto sempre aceso quando a placa está alimentada) e o led D2 está conectado ao pino P77 do microcontrolador.

A linha RL78 utiliza nomenclatura Pxy para especificar os pinos de I/O, onde x é o número da porta (0 a 15) e y é o número do bit nesta porta (0 a 7). Sendo assim, P77 é o bit 7 da porta 7 (P7). Lembre-se de consultar o datasheet do MCU para obter as informações mais precisas sobre o funcionamento dele. No caso do RL78/G13, o manual de hardware é o RL78/G13 User’s manual: Hardware.

Figura 1 – Pino de I/O do RL78

Basicamente temos três registradores que controlam a porta 7 do microcontrolador (algumas portas possuem outros registradores adicionais):

  • P7: utilizado para ler/escrever nos pinos da porta
  • PM7: utilizado para configurar o modo da porta (0=saída, 1=entrada)
  • PU7: utilizado para configurar o pull-up interno (0=desligado, 1=ligado). O pull-up somente opera quando o pino está configurado como saída

Assim, para configurar o pino P77 como saída, devemos escrever “0” no bit 7 do registrador PM7. Isto pode ser feito através da instrução assembly CLR1 PM7.7 ou através do código C PM7_bit.no7 = 0;

Uma vez configurado o pino como saída, para escrever um “1” no mesmo basta fazer SET1 P7.7  ou em C P7_bit.no7 = 1;

Para escrever “0” podemos utilizar a instrução assembly CLR1 P7.7 ou em C P7_bit.no7 = 0;

Observe que para utilizar os símbolos com nomes de registradores (P7, PM7, P7_bit, etc) é necessário incluir o arquivo ior5f100le.h que contém as definições dos símbolos relacionados aos registradores do MCU.

Além do I/O é importante saber que o RL78 possui alguns registradores de configuração que são gravados em flash (OPTION BYTES). Estes registradores controlam a operação e configuração do watchdog, do sensor de baixa tensão (LVD), do oscilador interno e do depurador. Por isso é muito importante configurar adequadamente estes registradores na sua aplicação!

Ps.: o watchdog permanece ativado se os bytes de opção não forem configurados pela aplicação!

Agora que já sabemos o básico sobre o I/O do RL78, vamos passar ao programa para piscar o led D2. Primeiramente vamos criar um novo projeto no IAR. Selecione a opção Project >Create a new project no menu principal. Selecione a opção “C” como linguagem a ser utilizada no projeto.

Figura 2 – Novo projeto (seleção da linguagem)

Em seguida, defina o nome para o projeto e o local onde o mesmo será salvo. Feito isso o projeto será criado e o ambiente apresentará uma janela do workspace atual, o código inicial da aplicação main.c será exibido em uma janela do editor.

Figura 3 – Novo projeto no IAR

Substitua o código do arquivo main.c pelo código abaixo.

#include "ior5f100le.h"

// Configuração dos registradores de opção (OPTION BYTES)
#pragma location = "OPTBYTE"
__root const char opbyte0 = 0xEF; // Watchdog desligado
#pragma location = "OPTBYTE"
__root const char opbyte1 = 0x73; // Configura detector de baixa tensão
#pragma location = "OPTBYTE"
__root const char opbyte2 = 0xE8; // oscilador HS 32MHz
#pragma location = "OPTBYTE"
__root const char opbyte3 = 0x85; // debug ativado, sem proteção de memória

#define LED_D2  P7_bit.no7

void main( void )
{
  unsigned int temp;
  PM7_bit.no7 = 0;  // porta P77 como saída
  while (1)
  {
    LED_D2 = 1;
    for (temp=10000;temp;temp--);
    LED_D2 = 0;
    for (temp=10000;temp;temp--);
  }
}
Uma vez digitado o programa, devemos proceder à compilação do mesmo. Para isso clique no botão MAKE na IDE, ou pressione a tecla F7. Caso a compilação e ligação transcorra sem problemas, a janela de mensagens na parte inferior da tela deverá apresentar uma mensagem indicando:  Total number of errors: 0
Em seguida, devemos proceder a gravação do microcontrolador e depuração da aplicação. Mas antes vamos configurar o hardware de depuração a ser utilizado. Selecione Project > Options no menu principal, na janela de opções do projeto clique em Debugger e selecione a opção TK em driver, conforme mostra a figura abaixo.
Figura 4 – Opções do projeto (seleção do depurador)
Agora basta pressionar o botão Download and Debug na IDE ou pressionar as teclas CTRL + D… Ahhh, não se esqueça de configurar os jumpers J6 a J9 do kit para a posição 1-2, caso contrário ocorrerá um erro de conexão com o debugger e a depuração não será possível (estes jumpers conectam o chip do depurador, o 78F0730, ao microcontrolador alvo RL78).
Após o download do programa a aparência do IAR deverá ser como a da figura a seguir:
Figura 5 – Depuração no IAR
Agora podemos testar a aplicação! É possível executar o programa passo a passo (teclas F10/F11) ou iniciar a execução em tempo real (tecla F5). Pressione a tecla F5 e veja o que acontece!
Ué, o led ficou aceso? Nenhuma piscada após pressionar F5? Devemos ter cometido algum erro não é? A resposta é NÃO 🙂 Na verdade o “problema” é que o RL78 está operando a 32MHz e ele é MUITO rápido!
A solução para isso é aumentar o número de iterações dos laços for, mas antes, vamos olhar no simulador quanto tempo o RL78 leva para executar cada laço for?
Para isso saia do modo de depuração (botão X vermelho ou teclas CTRL+SHIFT+D), abra a janela de opções do projeto (figura 4) e em Debugger selecione a opção Simulator ao invés de TK. Pressione novamente as teclas CTRL+D para iniciar uma nova sessão de depuração, desta vez utilizando o simulador do IAR.
Marque dois breakpoints: um em frente ao primeiro for e o segundo na linha seguinte. Para marcar um breakpoint, basta dar um duplo clique na margem cinzenta em frente a linha desejada. A aparência do IAR deverá ser igual a da figura 6.
Figura 6 – Simulador IAR

Agora vamos abrir uma janela de visualização dos registradores da CPU, no simulador, esta janela inclui contadores de ciclos de máquina que podem ser utilizados para medir o tempo de execução de trechos do programa.

Figura 7 – Janela de visualização de registradores

Execute o programa (tecla F5 ou o botão GO), a execução irá parar no breakpoint colocado no primeiro for. Na janela de visualização de registradores (figura 7), clique sobre o valor do CCTIMER1 e altere o valor para zero. Em seguida execute novamente o programa (tecla F5). A execução irá parar no segundo breakpoint e o CCTIMER1 irá mostrar quantos ciclos de máquina se passaram desde que o mesmo foi zerado. No nosso caso teremos 40009 ciclos, como cada ciclo é executado em 62,5ns, o tempo total de execução de um laço for é de aproximadamente 2,5ms, ou seja, o led está piscando em uma frequência de aproximadamente 200Hz! Por isso ele aparenta estar aceso e não piscando!

Para que possamos ver o led piscar, vamos então aumentar o número de iterações dos laços for para 100000. Não esqueça de alterar a declaração da variável temp para unsigned long int!!!

#include "ior5f100le.h"

// Configuração dos registradores de opção (OPTION BYTES)
#pragma location = "OPTBYTE"
__root const char opbyte0 = 0xEF; // Watchdog desligado
#pragma location = "OPTBYTE"
__root const char opbyte1 = 0x73; // Configura detector de baixa tensão
#pragma location = "OPTBYTE"
__root const char opbyte2 = 0xE8; // oscilador HS 32MHz
#pragma location = "OPTBYTE"
__root const char opbyte3 = 0x85; // debug ativado, sem proteção de memória

#define LED_D2  P7_bit.no7

void main( void )
{
  unsigned long int temp;
  PM7_bit.no7 = 0;  // porta P77 como saída
  while (1)
  {
    LED_D2 = 1;
    for (temp=100000;temp;temp--);
    LED_D2 = 0;
    for (temp=100000;temp;temp--);
  }
}

Pronto, agora basta selecionar novamente o TK como depurador, fazer o download do código e o led irá piscar!

Para encerrarmos este artigo, vejamos agora como alterar “on the fly” a frequência do oscilador interno do RL78, para isso iremos utilizar o registrador HOCODIV, cuja estrutura pode ser vista na figura 8.

Figura 8 – Registrador HOCODIV

O bit FRQSEL3 apresentado na tabela é o bit 3 do option byte 2, que o nosso programa configurou para “1” (opbyte2 = 0xE8). Assim, para alterar a frequência do oscilador para 8MHz, basta escrever “010” nos três bits menos significativos do registrador, ou seja, fazendo HOCODIV=2 alteramos a frequência do oscilador para 8MHz e fazendo HOCODIV=0 alteramos a frequência do oscilador para 32MHz!

Vejamos a nova versão do nosso programa que pisca led:

#include "ior5f100le.h"
#include "ior5f100le_ext.h"

// Configuração dos registradores de opção (OPTION BYTES)
#pragma location = "OPTBYTE"
__root const char opbyte0 = 0xEF; // Watchdog desligado
#pragma location = "OPTBYTE"
__root const char opbyte1 = 0x73; // Configura detector de baixa tensão
#pragma location = "OPTBYTE"
__root const char opbyte2 = 0xE8; // oscilador HS 32MHz
#pragma location = "OPTBYTE"
__root const char opbyte3 = 0x85; // debug ativado, sem proteção de memória

#define LED_D2  P7_bit.no7

void pisca(void)
{
  unsigned long int temp;
  LED_D2 = 1;
  for (temp=100000;temp;temp--);
  LED_D2 = 0;
  for (temp=100000;temp;temp--);
}

void main( void )
{
  unsigned char cnt;
  PM7_bit.no7 = 0;  // porta P77 como saída
  while (1)
  {
    for (cnt=10;cnt;cnt--) pisca();
    HOCODIV = 2;  // oscilador a 8MHz
    for (cnt=10;cnt;cnt--) pisca();
    HOCODIV = 0;  // oscilador a 32MHz
  }
}

Compile o programa, faça o download e veja o que acontece. Legal não é?

Até a próxima!

Leave a Reply