Cuidados na Declaração dos Bytes de Configuração e Security ID nos RL78

Estou trabalhando num projeto utilizando o RL78/G12 de 20 pinos (R5F10367, com 4KiB de flash e sem dataflash) e precisei configurar o oscilador interno de alta velocidade (HOCO) para operar a 1MHz. Abaixo está a configuração que utilizei nos bytes de configuração:

// Watchdog desligado
#pragma location = "OPTBYTE"
__root const char opbyte0 = WDT_OFF; 
// Configura detector de baixa tensão
#pragma location = "OPTBYTE"
__root const char opbyte1 = LVD_RESET_MODE | LVD_VMODE2; 
// oscilador 1MHz flash low voltage
#pragma location = "OPTBYTE"
__root const char opbyte2 = FLASH_LV | CLK_1MHZ;
// debug ativado, apaga a flash em caso de falha de autenticação
#pragma location = "OPTBYTE"
__root const char opbyte3 = DEBUG_ON_ERASE;

Pois bem, ao rodar o programa da aplicação, percebi que os atrasos de tempo estavam muito rápidos. Verifiquei a configuração do timer TAU, tudo certo. Parti então para observar o código na memória flash, fui direto nos endereços 0x000C0 a 0x000C3, onde são armazenados os bytes de configuração. Fiquei pasmo: estavam todos em 0xFF!!!! O quê estaria acontecendo?

Com certeza alguma coisa com o compilador ou linker. Ativei a geração do MAP file e fui procurar onde estavam sendo armazenados os bytes de configuração (já que obviamente eles não haviam sido armazenados no local correto)…

Gotcha! Eles estavam sendo armazenados nos endereços 0xFFD00 a 0xFFD03! Esta área é memória RAM e nada tem a ver com a área dos bytes de configuração!!! O quê estaria acontecendo?

A explicação está na forma como o compilador trata as constantes conforme o modelo de memória e de microcontrolador. Alguns RL78 possuem a facilidade de espelhar uma área da flash (do primeiro segmento da memória) no último de segmento, de forma que o programa pode acessar as constantes em flash e dados em RAM utilizando apenas endereçamento near, o que acelera o código.

No entanto, nos modelos G12 com 8KiB de flash ou menos, esta facilidade de espelhamento não está disponível e o compilador assume que deve copiar as constantes near da flash para a RAM. O problema é que as constantes near terminam por ser alocadas na faixa do último segmento, o que, no caso dos bytes de opção e security ID, inviabiliza totalmente a operação do chip!

A solução para isso é simples: basta declarar estes símbolos utilizando o modificador __far:

// Watchdog desligado
#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_RESET_MODE | LVD_VMODE2; 
// oscilador 1MHz flash low voltage
#pragma location = "OPTBYTE"
__root __far const char opbyte2 = FLASH_LV | CLK_1MHZ;
// debug ativado, apaga a flash em caso de falha de autenticação
#pragma location = "OPTBYTE"
__root __far const char opbyte3 = DEBUG_ON_ERASE;

Desta forma o linker armazena os bytes de configuração nos endereços corretos e tudo funciona perfeitamente! Ahh e tem mais: você pode utilizar o modificador __far na declaração dos bytes de configuração e security ID inclusive dos outros modelos de  RL78, pois ele não produz nenhum efeito colateral nos outros chips e modelos de memória!

Leave a Reply