Modo Stop no RL78

Olá Pessoal!

Neste artigo abordo o modo stop dos microcontroladores RL78. Assim como em outros microcontroladores, o modo stop paralisa a operação da CPU e da maioria dos periféricos, mas mantém o conteúdo da RAM e registradores, permitindo também que alguns periféricos (watchdog, timer de intervalo, RTC  ou interrupção de pino) possam continuar operando e fazer com que a CPU retorne ao estado ativo. Vale ressaltar que além do modo stop, os RL78 possuem também o modo halt, onde apenas a CPU é paralisada, mas o restante dos periféricos pode continuar operando normalmente. Obviamente que o modo stop garante um consumo de energia substancialmente menor que o modo halt. Há também o modo snooze, uma variação do modo stop onde alguns periféricos (UART, CSI e ADC) podem continuar operando e provocar o retorno ao modo ativo.

Para ilustrar a diferença de consumo a tabela a seguir demonstra o consumo típico (em µA) para os modos ativo, halt e stop. É claro que o consumo no modo ativo e no modo halt irá variar conforme os periféricos operando.

Modo

Consumo típico (µA)

Ativo

4600

Halt

540

Stop

0,23

O modo stop é executado pela instrução assembly STOP e o seu uso em linguagem C é feito através da macro __stop().

Quando em modo stop o clock da CPU e da maioria dos periféricos é parado, reduzindo o consumo de energia do chip. Uma interrupção de um periférico pode fazer com que o sistema retorna ao estado ativo (o controle global de interrupção EI não precisa estar habilitado, apenas a interrupção individual do periférico que será responsável pela saída do modo stop).

O exemplo a seguir demonstra a utilização deste modo. Ao ser ligada a alimentação o led D2 da placa de promoção do RL78/G13 irá piscar brevemente e em seguida a CPU irá entrar em modo stop, com o consumo reduzido para cerca de 230nA. A saída desde modo é realizada por meio do pino P5.0 que é configurado para operação como fonte de interrupção externa INTP1 com o seu resistor interno de pull-up ativado (uma tecla deve ser conectada entre este pino e o GND).

Uma transição negativa no pino (do nível “1” para nível “0”) provoca a saída do modo stop e o retorno ao modo normal de execução. Observe que o flag da interrupção é apagado por software (PIF1 = 0). Isto é necessário porque a aplicação não está com as interrupções habilitadas (EI = 0) e por isso não há uma ISR para o tratamento da mesma (o flag seria apagado automaticamente quando o programa fosse desviado para a ISR).

Para a correta operação do exemplo, alguns passos devem ser observados:

  1. A aplicação deve ser compilada com o depurador interno (OCD) desativado no byte de opção número 3;
  2. O projeto deve ser compilado no modo “Release” dentro do ambiente EWRL78. Lembre-se de configurar as opções de projeto da mesma forma que no modo “Debug”. O linker deve ser configurado para gerar um arquivo .hex, necessário para a gravação através da ferramenta RFP (Renesas Flash Programmer);
  3. Após a gravação do arquivo .hex gerado no passo 2, basta remover o jumper J9 para que o microcontrolador saia do reset e execute a aplicação. Para medição da corrente consumida, basta conectar um multímetro ou microamperímetro no local do jumper J3.
#include "ior5f100le.h"
#include "ior5f100le_ext.h"
#include "intrinsics.h"
#include "myRL78.h"

// Configura watchdog
#pragma location = "OPTBYTE"
__root __far const char opbyte0 = WDT_OFF; 
// Configura detector de baixa tensão
#pragma location = "OPTBYTE"
__root __far const char opbyte1 = LVD_OFF; 
// oscilador 4MHz flash low speed
#pragma location = "OPTBYTE"
__root __far const char opbyte2 = FLASH_HS | CLK_32MHZ;
// debug ativado, com apagamento em casa de falha de autenticação
#pragma location = "OPTBYTE"
__root __far const char opbyte3 = DEBUG_OFF; 
/* 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

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

void main (void)
{
  P0=P1=P2=P3=P4=P5=P6=P7=P12=P14=0;
  // configura todos os pinos como saídas
  PM0=PM1=PM2=PM3=PM4=PM5=PM6=PM7=PM12=PM14=0;
  // configura pinos analógicos para modo digital
  ADPC = 1;
  PMC0=PMC12=PMC14=0;
  CMC = 0;	// desativa osciladores X1 e XT1
  PM5_bit.no0 = 1;    // pino P5.0 como entrada
  PU5_bit.no0 = 1;    // liga pull-up do pino P5.0
  EGN0 = BIT1;        // interrupção INTP1 na borda de descida
  PIF1 = 0;           // limpa o flag da interrupção INTP1
  PMK1 = 0;           // habilita a interrupção INTP1
  while(1)
  {
    pisca();          // pisca 10 vezes o led
    __stop();         // entra em modo stop
    // ocorreu um sinal de wake-up
    PIF1 = 0;         // limpa o flag da interrupção
  }
}

Leave a Reply