Freescale Flash - Implementação
Autor: Jorge d'Avila | Publicado: 2012-03-24T06:15:00-07:00



Bom, para discutirmos implementação temos que ser mais específicos.&nbsp; A ferramenta que utilizo para programar os S08 é o Freescale CodeWarrior, e é sobre este ambiente que vamos discutir.

A primeira providência para utilizar parte da Flash na gravação de dados é definir um segmento de memória para isso.&nbsp; O CodeWarrior cria, para cada projeto, um arquivo "project.prm" com informações de segmentos de memória para o Linker.&nbsp; Por default, são criados os seguintes segmentos, na seção "SEGMENTS" desse arquivo:

&nbsp;&nbsp;&nbsp; Z_RAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp; READ_WRITE&nbsp;&nbsp; 0x0080 TO 0x00FF;&nbsp;&nbsp;&nbsp; RAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp; READ_WRITE&nbsp;&nbsp; 0x0100 TO 0x017F;&nbsp;&nbsp;&nbsp; ROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp; READ_ONLY&nbsp;&nbsp;&nbsp; 0xF000 TO 0xFFAD;

Cuidado!!&nbsp; O "0xF000" mostrado acima é o início da memória Flash do microcontrolador utilizado!&nbsp; Isto vai variar para cada modelo!

Temos que criar um novo segmento, no início da Flash, do tamanho desejado, para armazenar dados&nbsp;(eu o&nbsp;chamei de "FLASH"), e alterar o endereço inicial do segmento "ROM" (memória de código), da seguinte forma:

&nbsp;&nbsp;&nbsp; FLASH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp; READ_WRITE&nbsp;&nbsp; 0xF000 TO 0xF1FF;&nbsp;&nbsp;&nbsp; ROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp; READ_ONLY&nbsp;&nbsp;&nbsp; 0xF200 TO 0xFFAD;

Reparem que o novo segmento ocupa os primeiros 0x200 (512) bytes da Flash, e o início do segmento "ROM" foi alterado para o fim desse novo segmento.

Da mesma forma, na seção "PLACEMENT" do arquivo deve ser criada uma nova linha:

&nbsp;&nbsp;&nbsp; FLASH_VAR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INTO FLASH;

O segundo passo é programar o controlador da Flash.&nbsp; Costumo utilizar o "Device Initialization", mas isso pode ser também feito manualmente.&nbsp; No "Device Initialization" basta acessar o periférico "intFLASH" e programar o "Clock Divider" para obter a frequência de operação necessária.&nbsp; Essa frequência, segundo informado no manual e também nesta tela do CodeWarrior, deve ficar entre 150kHz e 200kHz.&nbsp; O divisor depende, portanto, da frequência de barramento que estamos utilizando.&nbsp; Sem esta programação a gravação na Flash não irá funcionar!

Feito isso, podemos agora utilizar esse novo segmento, "FLASH_VAR", em nosso programa.&nbsp; Foi então criado um módulo de programa que chamei de "iFLash.c", e um módulo header, "iFlash.h".

Esses módulos estão disponíveis aqui: iFLash.c&nbsp;e iFlash.h.

Reproduzo aqui o header&nbsp;iFlash.h para melhor examinarmos seu conteúdo:

// **************************************************************// internal Flash Erase/Write for Data Storage// (C) d'Avila, 2012// **************************************************************#include "derivative.h" /* include peripheral declarations */#define iFLashByteProg&nbsp; 0x20#define iFLashBurstProg 0x25#define iFLashPageErase 0x40#pragma DATA_SEG FLASH_VARextern byte&nbsp;&nbsp;&nbsp; iFlash [512];#pragma DATA_SEG __SHORT_SEG MY_ZEROPAGEvoid iFlashComm (char Comm, char *Add, char Data);&nbsp;&nbsp; // Command Functionvoid iFlashBurst (char Size, char *Add, char *Buf);&nbsp; //&nbsp;Burst Function

As três definições (#define) acima são os códigos de comandos para a Flash.&nbsp; O vetor iFlash&nbsp;[512] é a área da Flash a ser utilizada para dados.&nbsp; Reparem que ele está alocado no segmento FLASH_VAR, sobre o qual falamos acima ao descrever o arquivo de comandos do Linker.&nbsp; As funções disponíveis são iFlashComm e iFlashBurst.&nbsp; A primeira é utilizada para apagar a página e para gravar um byte de dados.&nbsp; A segunda grava vários bytes em sequência, de forma bem mais rápida do que se utilizássemos a gravação de um byte várias vezes.

IMPORTANTE!! A Flash não suporta várias gravações no mesmo endereço, sem que a página seja apagada entre as gravações.&nbsp; Após apagar a página (comando&nbsp;iFLashPageErase), pode-se gravar todos os bytes da página, mas cada byte apenas uma vez!

Para apagar ou gravar um byte, executa-se a função iFlashComm, passando como parâmetros o comando desejado, um pointer para o endereço a ser agagado/gravado, e o valor a ser gravado.&nbsp; Para apagar a página qualquer endereço dentro da página é válido, e o valor é desconsiderado.&nbsp; Exemplo:

iFlashComm (iFLashByteProg, &iFlash [10], 200);

Este comando irá gravar no elemento 10 do vetor iFlash o valor 200.

Para gravar em modo "burst" executa-se a função iFlashBurst, passando como parâmetros o tamanho do vetor a ser gravado (número de bytes), um pointer para o endereço a ser gravado, e outro pointer para os dados a serem gravados.&nbsp; Reparem que não é necessário informar o comando - para esta função ele é sempre iFLashBurstProg.&nbsp; Exemplo:

void iFlashBurst (3, &iFlash [0], &amp;Dados);

Este comando grava 3 bytes na Flash, a partir do início (elemento zero) do vetor iFlash, com os valores apontados por Dados.

Uma última observação: atenção para os tempos de execução dessas funções!&nbsp; Apagar uma página, especialmente, demora de 20ms a 30ms, dependendo da frequência programada no controlador da Flash.&nbsp; Durante esse tempo o programa ficará "morto", não executando nem interrupções (lembrem-se, a Flash não pode ser lida para executar código).