fenglogo
Laboratório de Processadores
Programação do LPC2378 usando o arm-elf-gcc
Parte 9: Programação de memória Flash:
IAP: In Application Programming
puclogo

O LPC2378 tem uma ROM com um programa tipo boot-loader que serve para programar a sua própria memória Flash. Um computador pode comunicar-se com o boot-loader através da interface serial, fornecedo os comandos e dados do programa a ser gavado na memória Flash, usando a técnica conhecida pela sigla ISP (In System Programming).

As funções da ROM do boot-loader podem também ser chamadas como subrotinas de um programa aplicativo. Chamamos isto de IAP (In Application Programming).

As funções do IAP são acessíveis em um único ponto de entrada no endereço 0x7ffffff0. Recomenda-se usar em vez disto o endereço 0x7ffffff1 para forçar o LPC2378 a executar a função do IAP em modo THUMB. Este ponto de entrada recebe como parâmetros, nos registradores R0 e R1, dois apontadores para arrays de inteiros de 32 bits sem sinal. Estes arrays tem os parâmetros de entrada e de saída das funções IAP.

Nos nossos exemplos de programação, o monitor mon23/ inclui funções para programar a memória flash incorporada. Estas funções encontram-se no módulo iap.c.

Em linguagem C, o acesso às funções IAP pode ser feito da seguinte maneira:

/* Tipo de dados da funcao IAP */
typedef void (*IAP)(unsigned *rin, unsigned *rout);
/* Ponto de entrada do IAP */
#define IAP_ENTRY ((IAP)0x7ffffff1)
/* Array dos parametros de E/S do IAP */
unsigned regs[5];

/* Array com as mensagens de status do IAP */
static const char *sstatus[]={
"Done","Command error", "Invalid src addr","Invalid dest addr",
"Src not mapped","Dest not mapped","Count_error",
"Invalid sector","Sector not blank","Sector not prepared",
"Compare error", "Busy"};

/* Exemplo de uso do IAP */
void ReadPartID()
{
UART0puts("Read part ID: ");
regs[0]=54;		/* Comando IAP 54: Read Part ID */
IAP_ENTRY(regs,regs);	/* Chama a ROM IAP */
UART0puts(sstatus[regs[0]]);	/* Esceve mensagem de status */
UART0puts("! ID=");
escreve_num(regs[1]);		/* Escreve o numero Part ID */
}

O LPC2378 tem 512kBytes de memória Flash dividida em 28 setores, com tamanhos e edereços iniciais conforme mostra a tabela a seguir:
SetorEndereço inicial Endereço finalTamanho (Bytes)
0 0x000000000x00000FFF 4096
1 0x000010000x00001FFF 4096
2 0x000020000x00002FFF 4096
3 0x000030000x00003FFF 4096
4 0x000040000x00004FFF 4096
5 0x000050000x00005FFF 4096
6 0x000060000x00006FFF 4096
7 0x000070000x00007FFF 4096
8 0x000080000x0000FFFF 32768
9 0x000100000x00017FFF 32768
10 0x000180000x0001FFFF 32768
11 0x000200000x00027FFF 32768
12 0x000280000x0002FFFF 32768
13 0x000300000x00037FFF 32768
14 0x000380000x0003FFFF 32768
15 0x000400000x00047FFF 32768
16 0x000480000x0004FFFF 32768
17 0x000500000x00057FFF 32768
18 0x000580000x0005FFFF 32768
19 0x000600000x00067FFF 32768
20 0x000680000x0006FFFF 32768
21 0x000700000x00077FFF 32768
22 0x000780000x00078FFF 4096
23 0x000790000x00079FFF 4096
24 0x0007A0000x0007AFFF 4096
25 0x0007B0000x0007BFFF 4096
26 0x0007C0000x0007CFFF 4096
27 0x0007D0000x0007DFFF 4096

Pode-se escrever a seguinte função para obter o endereço na memória Flash a partir do número do sertor:

unsigned sect2addr(int sector)
{
unsigned addr;
addr=(sector << 12);
if(sector > 8) addr=(sector << 15)-0x38000;
if(sector > 0x16) addr=(sector << 12)+0x62000;
return addr;
}

Os parâmetros da função IAP_ENTRY são especificados inicializando-se os valores do array regs[]. O primeiro (regs[0]) seleciona qual será a operação; os outros fornecem informações adicionais.

A tabela a seguir apresenta os comandos da ROM IAP:

50 Preparar setores para escrita
Este comando deve ser executado antes de apagar ou escrever setores.
Entrada:
reg[0]=50;
reg[1]=Setor_Inicial;
reg[2]=Setor_Final;
Saída
reg[0]=STATUS;
51 Copiar da RAM para a Flash
Este comando grava um conjunto de bytes da RAM (Endereço 0x40000000 a 0x40007FFF) para a flash (a partir do endereço 0x00000000). O número de bytes deve ser 256, 512, 1024 ou 4096. Outros valores de número de bytes não são aceitos. O endereço de destino na Flash deve ser múltiplo de 256;
Entrada:
reg[0]=51;
reg[1]=Endereço destino na Flash.
reg[2]=Numero de bytes (256 | 512 | 1024 | 4096)
reg[3]=Frequência de clock (CCLK) em Hz
Saída:
reg[0]=STATUS;
52 Apagar setores
A memória Flash deve estar apagada (com todos os bytes com valor 0xFF) para que possa ser gravada. Este comando apaga um conjunto de setores.
Entrada:
reg[0]=52;
reg[1]=Número do setor inicial
reg[2]=Número do setor final
reg[3]=Frequência de clock (CCLK) em Hz
Saída:
reg[0]=STATUS;
53 Verificar se setores estão apagados
Entrada:
reg[0]=53;
reg[1]=Número do setor inicial
reg[2]=Número do setor final
Saída:
reg[0]=STATUS;
reg[1]=Endereço da primeira palavra não apagada.
reg[1]=Valor da primeira palavra não apagada.
54 Le número de identificação do microcontrolador
Para o LPC2378 este número é 117702437 decimal.
Entrada:
reg[0]=54;
Saída:
reg[0]=STATUS;
reg[1]=número de identificação
55 Le número de versão do Boot Loader
Entrada:
reg[0]=55;
Saída:
reg[0]=STATUS;
reg[1]=número de versão (major)
reg[2]=número de versão (minor)
57 Entra em modo ISP
Este comando invoca o Boot Loador no modo ISP (In System Programming) de modo que se possa usar um programador externo (como o lpc21isp).
Entrada:
reg[0]=57;
Saída:
Não retorna.