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

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 LPC2378

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 LPC2378:

Sistema de Clock do LPC2378

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