Witam,
Posiadam mikrokontroler LPC2364, w którym nie potrafię uruchomić pętli PLL. Środowisko programistyczne to Eclipse skonfigurowane według tutoriala Freddiego Chopina. Do uruchomienia LPC2364 posłużyłem się projektem przykładowym naipisanym dla LPC2103 i znajdującym się również na stronie Freddiego Chopina.
Zmieniony został plik linkera:
Zmieniona została nazwa projektu w makefile oraz nagłówek - podłączono LPC23xx.h
Kod w pliku main.c
Różnica pomiędzy mikrokontrolerami LPC2103 i LPC2364 jest taka, że ten drugi posiada wewnętrzny rezonator RC, który po resecie jest skonfigurowany i taktuje CPU z częstotliwością 4Mhz. Jeśli zakomentuję procedurę uruchamiania pętli pll w pliku main, wówczas procesor miga diodą bardzo powoli (pracuje na wewnętrznym oscylatorze z częstotliwością 4MHz). Jeśli procedura startu pll jest odkomentowana nastaje cisza i procesor nie robi nic.
Podejrzewam, że nie są skonfigurowane rejestry odpowiedzialne za wybór rezonatora, ale niestety jestem w armach początkujący i nie wiem jak się zabrać za konfigurację... Będę wdzięczny jeśli ktoś mi pomoże.
Posiadam mikrokontroler LPC2364, w którym nie potrafię uruchomić pętli PLL. Środowisko programistyczne to Eclipse skonfigurowane według tutoriala Freddiego Chopina. Do uruchomienia LPC2364 posłużyłem się projektem przykładowym naipisanym dla LPC2103 i znajdującym się również na stronie Freddiego Chopina.
Zmieniony został plik linkera:
/******************************************************************************
* author: Freddie Chopin, http://www.freddiechopin.info/
* file: LPC2103_rom.ld
* last change: 2012-01-08
*
* chip: LPC2364
* compiler: arm-none-eabi-gcc (Sourcery CodeBench Lite 2011.09-69) 4.6.1
*
* description:
* Linker script for LPC2364 chip (128kB Flash, 34kB SRAM).
******************************************************************************/
SEARCH_DIR(.);
/*
+=============================================================================+
| format configurations
+=============================================================================+
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm");
OUTPUT_ARCH(arm);
/*
+=============================================================================+
| stacks sizes
+=============================================================================+
*/
__user_system_stack_size = 1024;
__fiq_stack_size = 0;
__irq_stack_size = 0;
__supervisor_stack_size = 0;
__abort_stack_size = 0;
__undefined_stack_size = 0;
PROVIDE(__user_system_stack_size = __user_system_stack_size);
PROVIDE(__fiq_stack_size = __fiq_stack_size);
PROVIDE(__irq_stack_size = __irq_stack_size);
PROVIDE(__supervisor_stack_size = __supervisor_stack_size);
PROVIDE(__abort_stack_size = __abort_stack_size);
PROVIDE(__undefined_stack_size = __undefined_stack_size);
/*
+=============================================================================+
| available memories definitions
+=============================================================================+
*/
MEMORY
{
rom (rx) : org = 0x00000000, len = 128k
ram (rwx) : org = 0x40000000, len = 34k
}
__rom_start = ORIGIN(rom);
__rom_size = LENGTH(rom);
__rom_end = __rom_start + __rom_size;
__ram_start = ORIGIN(ram);
__ram_size = LENGTH(ram);
__ram_end = __ram_start + __ram_size;
PROVIDE(__rom_start = __rom_start);
PROVIDE(__rom_size = __rom_size);
PROVIDE(__rom_end = __rom_end);
PROVIDE(__ram_start = __ram_start);
PROVIDE(__ram_size = __ram_size);
PROVIDE(__ram_end = __ram_end);
/*
+=============================================================================+
| entry point
+=============================================================================+
*/
ENTRY(Reset_Handler);
/*
+=============================================================================+
| put data in sections
+=============================================================================+
*/
SECTIONS
{
.text :
{
. = ALIGN(4);
__text_start = .;
PROVIDE(__text_start = __text_start);
. = ALIGN(4);
KEEP(*(.vectors));
. = ALIGN(4);
*(.text .text.* .gnu.linkonce.t.*);
. = ALIGN(4);
*(.glue_7t .glue_7);
. = ALIGN(4);
*(.rodata .rodata.* .gnu.linkonce.r.*);
. = ALIGN(4);
*(.ARM.extab* .gnu.linkonce.armextab.*); /* exception unwinding information */
. = ALIGN(4);
*(.gcc_except_table); /* information used for stack unwinding during exception */
. = ALIGN(4);
*(.eh_frame_hdr); /* additional information about .ex_frame section */
. = ALIGN(4);
*(.eh_frame); /* information used for stack unwinding during exception */
. = ALIGN(4);
KEEP(*(.init));
. = ALIGN(4);
__preinit_array_start = .;
KEEP(*(.preinit_array));
. = ALIGN(4);
__preinit_array_end = .;
__init_array_start = .;
KEEP(*(SORT(.init_array.*)));
. = ALIGN(4);
KEEP(*(.init_array));
. = ALIGN(4);
__init_array_end = .;
KEEP(*(.fini));
. = ALIGN(4);
__fini_array_start = .;
KEEP(*(.fini_array));
. = ALIGN(4);
KEEP(*(SORT(.fini_array.*)));
. = ALIGN(4);
__fini_array_end = .;
. = ALIGN(4);
__text_end = .;
PROVIDE(__text_end = __text_end);
} > rom AT > rom
. = ALIGN(4);
__exidx_start = .;
PROVIDE(__exidx_start = __exidx_start);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*);
} > rom AT > rom /* index entries for section unwinding */
. = ALIGN(4);
__exidx_end = .;
PROVIDE(__exidx_end = __exidx_end);
.data :
{
. = ALIGN(4);
__data_init_start = LOADADDR (.data);
PROVIDE(__data_init_start = __data_init_start);
__data_start = .;
PROVIDE(__data_start = __data_start);
. = ALIGN(4);
*(.data .data.* .gnu.linkonce.d.*)
. = ALIGN(4);
__data_end = .;
PROVIDE(__data_end = __data_end);
} > ram AT > rom
.bss :
{
. = ALIGN(4);
__bss_start = .;
PROVIDE(__bss_start = __bss_start);
. = ALIGN(4);
*(.bss .bss.* .gnu.linkonce.b.*)
. = ALIGN(4);
*(COMMON);
. = ALIGN(4);
__bss_end = .;
PROVIDE(__bss_end = __bss_end);
} > ram AT > ram
.stack :
{
. = ALIGN(8);
__stack_start = .;
PROVIDE(__stack_start = __stack_start);
. = ALIGN(8);
__user_system_stack_start = .;
PROVIDE(__user_system_stack_start = __user_system_stack_start);
. += __user_system_stack_size;
. = ALIGN(8);
__user_system_stack_end = .;
PROVIDE(__user_system_stack_end = __user_system_stack_end);
. = ALIGN(8);
__fiq_stack_start = .;
PROVIDE(__fiq_stack_start = __fiq_stack_start);
. += __fiq_stack_size;
. = ALIGN(8);
__fiq_stack_end = .;
PROVIDE(__fiq_stack_end = __fiq_stack_end);
. = ALIGN(8);
__irq_stack_start = .;
PROVIDE(__irq_stack_start = __irq_stack_start);
. += __irq_stack_size;
. = ALIGN(8);
__irq_stack_end = .;
PROVIDE(__irq_stack_end = __irq_stack_end);
. = ALIGN(8);
__supervisor_stack_start = .;
PROVIDE(__supervisor_stack_start = __supervisor_stack_start);
. += __supervisor_stack_size;
. = ALIGN(8);
__supervisor_stack_end = .;
PROVIDE(__supervisor_stack_end = __supervisor_stack_end);
. = ALIGN(8);
__abort_stack_start = .;
PROVIDE(__abort_stack_start = __abort_stack_start);
. += __abort_stack_size;
. = ALIGN(8);
__abort_stack_end = .;
PROVIDE(__abort_stack_end = __abort_stack_end);
. = ALIGN(8);
__undefined_stack_start = .;
PROVIDE(__undefined_stack_start = __undefined_stack_start);
. += __undefined_stack_size;
. = ALIGN(8);
__undefined_stack_end = .;
PROVIDE(__undefined_stack_end = __undefined_stack_end);
. = ALIGN(8);
__stack_end = .;
PROVIDE(__stack_end = __stack_end);
} > ram AT > ram
. = ALIGN(4);
__heap_start = .;
PROVIDE(__heap_start = __heap_start);
. = ALIGN(4);
__heap_end = __ram_end;
PROVIDE(__heap_end = __heap_end);
.stab 0 (NOLOAD) : { *(.stab) }
.stabstr 0 (NOLOAD) : { *(.stabstr) }
/* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) }
.ARM.attributes 0 : { KEEP(*(.ARM.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) }
}
PROVIDE(__text_size = __text_end - __text_start);
PROVIDE(__exidx_size = __exidx_end - __exidx_start);
PROVIDE(__data_size = __data_end - __data_start);
PROVIDE(__bss_size = __bss_end - __bss_start);
PROVIDE(__stack_size = __stack_end - __stack_start);
PROVIDE(__heap_size = __heap_end - __heap_start);
/******************************************************************************
* END OF FILE
******************************************************************************/
Zmieniona została nazwa projektu w makefile oraz nagłówek - podłączono LPC23xx.h
Kod w pliku main.c
/** \file main.c
* \brief Sample ARM project
* \details This file holds a very basic ARM code for LPC2103. This code
* initializes the Fast GPIOs, starts the MAM (Memory Acceleration Module) and
* enables the PLL to achieve the highest allowed frequency for LPC2103 (72MHz).
* Main code block just blinks the LED. The LED port and pin are defined in
* config.h file. Target core frequency and quartz crystal resonator
* frequency are defined there as well.
*
* \author Freddie Chopin, http://www.freddiechopin.info/
* \date 2012-01-08
*/
/******************************************************************************
* project: lpc2103_blink_led
* chip: LPC2103
* compiler: arm-none-eabi-gcc (Sourcery CodeBench Lite 2011.09-69) 4.6.1
*
* prefix: (none)
*
* available global functions:
* int main(void)
*
* available local functions:
* static void mam_start(uint32_t frequency)
* static void pll_feed(void)
* static uint32_t pll_start(uint32_t crystal, uint32_t frequency)
* static void system_init(void)
*
* available interrupt handlers:
******************************************************************************/
/*
+=============================================================================+
| includes
+=============================================================================+
*/
#include <stdint.h>
#include "inc/LPC23xx.h"
#include "config.h"
#include "hdr/hdr_scb.h"
#include "hdr/hdr_mam.h"
/*
+=============================================================================+
| module variables
+=============================================================================+
*/
/*
+=============================================================================+
| local functions' declarations
+=============================================================================+
*/
static void mam_start(uint32_t frequency);
static void pll_feed(void);
static uint32_t pll_start(uint32_t crystal, uint32_t frequency);
static void system_init(void);
/*
+=============================================================================+
| global functions
+=============================================================================+
*/
/*------------------------------------------------------------------------*//**
* \brief main code block
* \details Call some static initialization functions and blink the led with
* frequency defined via count_max variable.
*//*-------------------------------------------------------------------------*/
int main(void)
{
volatile uint32_t count, count_max = 1000000;
system_init();
pll_start(CRYSTAL, FREQUENCY);
//PINSEL0 = 0x00000000;
LED_DIR |= LED;
while (1)
{
for (count = 0; count < count_max; count++); // delay
LED_SET |= LED; // change LED state
for (count = 0; count < count_max; count++); // delay
LED_CLR |= LED; // change LED state
}
}
/*
+=============================================================================+
| local functions
+=============================================================================+
*/
/*------------------------------------------------------------------------*//**
* \brief Start MAM
* \details Enables the Memory Acceleration Module in LPC2103, which allows the
* CPU to work full-speed out of Flash.
*
* \param [in] frequency defines the target frequency of the core
*//*-------------------------------------------------------------------------*/
static void mam_start(uint32_t frequency)
{
uint32_t latency;
if (frequency < 20000000) // 1 cycle latency for core speed below 20MHz
latency = 1;
else if (frequency < 40000000) // 2 cycle latency for core speed between 20MHz and 40MHz
latency = 2;
else // 3 cycle latency for core speed over 40MHz
latency = 3;
MAMTIM = latency; // set the latency
MAMCR = MAMCR_MODE_FULL; // enable MAM
}
/*------------------------------------------------------------------------*//**
* \brief PLL feed sequence
* \details Issues a special "PLL feed sequence" which validates the changes to
* PLL control registers
*//*-------------------------------------------------------------------------*/
static void pll_feed(void)
{
PLLFEED = PLLFEED_FIRST;
PLLFEED = PLLFEED_SECOND;
}
/*------------------------------------------------------------------------*//**
* \brief Starts the PLL
* \details Configure and enable PLL to achieve some frequency with some crystal.
* Before the speed change MAM is enabled via mam_start(). PLL parameters m and p
* are based on function parameters. The PLL is set up, started and connected.
* Finally, APB clock ratio is set to 1:1.
*
* \param [in] crystal is the frequency of the crystal resonator connected to the
* LPC2103
* \param [in] frequency is the desired target frequency after enabling the PLL
*
* \return real frequency that was set
*//*-------------------------------------------------------------------------*/
static uint32_t pll_start(uint32_t crystal, uint32_t frequency)
{
uint32_t m, p = 0, fcco;
mam_start(frequency); // reconfigure/enable MAM before changing speed
m = frequency / crystal; // M is the PLL multiplier
fcco = m * crystal * 2; // FCCO is the internal PLL frequency
frequency = crystal * m;
while (fcco < 156000000)
{
fcco *= 2;
p++; // find P which gives FCCO in the allowed range (over 156MHz)
}
PLLCFG = (m - 1) | (p << PLLCFG_PSEL_bit); // set basic PLL parameters
pll_feed();
PLLCON = PLLCON_PLLE; // enable PLL
pll_feed();
while (!(PLLSTAT & PLLSTAT_PLOCK)); // wait for PLL lock
PLLCON = PLLCON_PLLE | PLLCON_PLLC; // connect PLL as the system clock
pll_feed();
APBDIV = APBDIV_APBDIV_1; // set APB clock ratio to 1:1
return frequency;
}
/*------------------------------------------------------------------------*//**
* \brief Initialize system
* \details Enables the Fast GPIOs and ensures the vectors are taken from Flash
*//*-------------------------------------------------------------------------*/
static void system_init(void)
{
SCS = SCS_GPIO0M; // enable Fast I/O
MEMMAP = MEMMAP_MAP_FLASH; // vectors in Flash
}
/*
+=============================================================================+
| ISRs
+=============================================================================+
*/
/******************************************************************************
* END OF FILE
******************************************************************************/
Różnica pomiędzy mikrokontrolerami LPC2103 i LPC2364 jest taka, że ten drugi posiada wewnętrzny rezonator RC, który po resecie jest skonfigurowany i taktuje CPU z częstotliwością 4Mhz. Jeśli zakomentuję procedurę uruchamiania pętli pll w pliku main, wówczas procesor miga diodą bardzo powoli (pracuje na wewnętrznym oscylatorze z częstotliwością 4MHz). Jeśli procedura startu pll jest odkomentowana nastaje cisza i procesor nie robi nic.
Podejrzewam, że nie są skonfigurowane rejestry odpowiedzialne za wybór rezonatora, ale niestety jestem w armach początkujący i nie wiem jak się zabrać za konfigurację... Będę wdzięczny jeśli ktoś mi pomoże.