Lab. Processadores: Programação do LPC2478 usando o gcc

| Laboratório de Processadores Programação do LPC2478 usando o arm-elf-gcc Parte 6: Sistema de Clock e PLL |

Neste exemplo vamos fazer o programa a06_pll para testar a configuração do sistema de clock, e do PLL de modo a alterar a ffrequência de operação da CPU.

Neste programa usaremos um módulo adicional chamado `uart.c` onde estão as funções de configuração do Clock/PLL e da porta serial.

### Instruções para compilar e usar

Iniciar expandindo o arquivo `a06_pll.tgz` e abrindo um shell e entrando no diretório `a06_pll`. Prepara-se o microprocessador para programar a Flash, conectando o cabo serial e colocando em modo de programação. Então pode-se compilar o programa e gravar na Flash com o comando

    make isp

Para testar o programa recomenda-se usar um teminal serial, como o ltser.exe. Como o ltser foi configurado por default para 9600Baud, é necessário chama-lo especificando que baud-rate deve ser de 19200 Baud usando seguinte linha de comando:

    ltser b=19200

Tendo o programa `mon23` instalado na FLASH e sendo executado, pode-se testar este programa rodando na RAM. Para isto usa-se o comando

    make tser

Este comando compila o programa e envia-o para a RAM usando o terminal `ltser`. Para executar o programa usa-se o comando "P" do monitor `mon23`.

### Sistema de Clock do LPC2478

Os microcontroladores tipo LPC23xx tem um sistema de geração de clock bastante complexo e configurável. Para começar existem tres osciladores que podem servir como base para as temporizações do LPC2478:

- Um oscilador interno de 4MHz, totalmente incorporado no chip, permite que o microcontrolador funcione sem qualquer componente externo. Este oscilador é usado inicialmente, antes que qualquer configuração tenha sido feita.
- Um oscilador que usa um cristal ressonante externo, que no nosso kit finciona a 12MHz.
- Um oscilador de 32768Hz alimentado por bateria, feito para manter o relógio RTC funcionando até com o microcontrolador desligado.

O registrador `CLKSRCSEL` seleciona qual destes osciladores será usado como base para as demais temporizações. Para usar o oscilador externo de 12MHz é necessário liga-lo e esperar até que ele esteja estabilizado. Isto é feito usando o registrador `SCS`. Portanto usaremos os seguintes registradores na configuração do clock:

SCS 0xE01FC1A0 | System Control Status: Configurações variadas. bit 0: Habilita modo Fast do GPIO. Neste modo deve-se usar instruções tipo FIOxPIN para acessar as portas P0 e P1. bit 5: Liga o oscilador externo. bit 6: Indica oscilador externo funcionando. Pode ser usado.
CCLKCFG 0xE01FC104 | Configura o divisor de clock para a CPU. O valor a ser escrito é o divisor-1. O valor do divisor, se não for um, deve ser par.
CLKSRCSEL 0xE01FC10C | Seleciona o oscilador de clock a ser ligado ao PLL valor 0: Conecta ao oscilador interno de 4MHz valor 1: Conecta ao oscilador externo 12MHz valor 2: Usa o oscolador do RTC
PLLCON 0xE01FC080 | Conecta ou habilita o PLL bit 0: Habilita o funcionamento do PLL bit 1: Conecta o PLL à CPU
PLLCFG 0xE01FC084 | Configura o multiplicador e o divisor do PLL: bit 0 a 14: `MSEL` (Multiplicador/2)-1 bit 16 a 23: `NSEL` Divisor-1
PLLSTAT 0xE01FC088 | Somente leitura. Le a configuração do PLL. bit 0 a 14: `MSEL` Multiplicador-1 bit 16 a 23: `NSEL` Divisor-1 bit 24: `PLLE` Indica que o PLL está habilitado bit 25: `PLLC` PLL conectado à CPU bit 26: `PLLLOCK` PLL travado na frequencia desejada
PLLFEED 0xE01FC08C | Para que alterações de configuração do PLL tenham efeito é necessário escrever os valores 0xAA e 0x55 neste registrador.

Desta forma temos no módulo `uart.c` uma função chamada PLL_Init que configura o multiplicador do PLL e o divisor `CCLKCFG` para fazer com que o núcleo do microcontrolador opere a uma frequencia `cpuclock` de acordo com a fórmula:

`cpuclock = 12MHz*(pllmulti/cpudiv)`

O PLL tem um oscilador controlado por corrente (o CCO) que oscila em uma frequência múltipla da frequência do oscilador de referência. O CCO oscila em frequências que podem variar de 275MHz a 550MHz.

Ajustando os campos `MSEL` e `NSEL` pode-se ajustar a frequência do CCO:

`CCO freq = 4*(MSEL+1)/(NSEL+1)*12MHz`

A oscilação do CCO entra no microcontrolador dividida por 2, como o sinal `SYSCLK`. Este sinal é dividido por `CCLKCFG + 1` para gerar o clock `CCLK` usado no núcleo do microcontrolador. Este clock `CCLK` pode ainda passar por um divisor por 1,2,4 ou 8 específico para cada periférico, controlado pelos registradores `PCLKSEL0` e `PCLKSEL1`.

Com um cristal oscilador de 12MHz temos uma frequencia `SYSCLK` no núcleo do processador dada por:

`SYSCLK = 12MHz * (2*(MSEL+1)/(NSEL+1))`

Com a divisão por `(CLKCFG+1)` temos o clock `CCLK` da CPU

`CCLK = 12MHz * (2*(MSEL+1)/(NSEL+1))/(CCLKCFG+1)`

Este clock `CCLK` também entra nos divisores por 1,2,4 ou 8 específicos para cada periférico configurados pelos registradores `PCLKSEL0` e `PCLKSEL1`.de acordo com a tebela a seguir:

PCLKSEL | bits | Periférico
--- | --- | ---
`PCLKSEL0` | 1:0 | Watchdog Timer WDT
3:2 | Timer T0
5:4 | Timer T1
7:6 | UART0
9:8 | UART1
11:10 | Sempre 00
13:12 | PWM1
15:14 | I2C0
17:16 | SPI
19:18 | RTC
21:20 | SSP1
23:22 | DAC
25:24 | ADC
27:26 | CAN1
29:28 | CAN2
31:30 | CAN Filtering
PCLKSEL | bits | Periférico
--- | --- | ---
`PCLKSEL1` | 1:0 | Battery RAM
3:2 | GPIO
5:4 | Pin Connect Block
7:6 | I2C1
9:8 | Sempre 00
11:10 | SSP0
13:12 | Timer 2
15:14 | Timer 3
17:16 | UART2
19:18 | UART3
21:20 | I2C2
23:22 | I2S
25:24 | MCI
27:26 | Sempre 00
29:28 | System Control Block
31:30 | Sempre 00

Nestes registradores `PCLKSEL0` e `PCLKSEL1` os pares de bits tem o seguinte significado:

00 | PCLK = CCLK/4 (Divide por 4)
01 | PCLK = CCLK (Divide por 1)
10 | PCLK = CCLK/2 (Divide por 2)
11 | PCLK = CCLK/8 (Exceto no CAN1 e CAN2 onde divide por 6)

### Exemplo de configuração do clock

Neste exemplo vamos partir de um oscilador de 12 MHz. O PLL será configurado com um pré divisor por 5 e um multiplicador por 96. Nesta configuração o CCO deverá oscilar a uma frequência dada por:

`CCOfreq = 12MHz / 5 * 96 * 2 = 460,8 MHz`

Obrseve que é necessário que a frequência do CCO fique no intervalo entre 275 MHz e 550MHz. No sinal `SYSCLK` temos a mentade do CCOfreq, que é 230,4 MHz. O clock da cpu `CCLK` aparece na divisão do `SYSCLK` por `(CCLKCFG+1)`.

`CCLK = SYSCLK/(CCLKCFG+1) = 230,4 MHz / (3 + 1) = 57,6 MHz`

Veja a seguir o trecho de código em Linguagem C que faz esta configuração:

    /* Este trecho de programa gera um clock de CCLK = 57,6 MHz na CPU */
    /* a partir de um oscilador de 12 MHz */
    #define PLLDIV	5
    #define PLLMULTI 96
    if(PLLSTAT & (1 << 25)){	/* Se PLL nao estava configurado */
    	PLLCON = 1;		/* Habilita PLL, desconectado */
    	PLLFEED=0xAA;PLLFEED=0x55;
    	}
    PLLCON=0;			/* Desconecta e desabilita o PLL */
    PLLFEED=0xAA;PLLFEED=0x55;
    SCS |= 0x20;			/* Liga o oscilador externo (12MHz) (bit 5 do SCS) */
    while( !(SCS & 0x40) );		/* Espera estabilizar o oscilador */
    CLKSRCSEL = 0x1;		/* Usa o 12MHz como oscilador principal */
    /* Para dividir por PLLDIV=5 e multiplicar por PLLMULTI=96 temos que */
    /* PLLCFG = ((PLLDIV-1) << 16) + ((PLLMULTI/2)-1) = 0x04002f */
    PLLCFG = ((PLLDIV-1) << 16) + (PLLMULTI/2-1));
    CCLKCFG = 3;			/* Divide por 4: CCLK = 12MHz * 96/5/4 = 57,6MHz */
    PLLCON=1;			/* Habilita o PLL */
    PLLFEED=0xAA;PLLFEED=0x55;
    while(!(PLLSTAT & (1<<26)));	/* espera PLL Lock (indicado pelo bit 26 do PLLSTAT) */
    PLLCON=3;			/* Usa o PLL para CCLK ( CPU operando a 57,6MHz) */
    PLLFEED=0xAA;PLLFEED=0x55;