/**
* @file
*
* @ingroup lpc24xx
*
* @brief Startup code.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
#include <string.h>
#include <bsp.h>
#include <bsp/bootcard.h>
#include <bsp/dma.h>
#include <bsp/irq.h>
#include <bsp/linker-symbols.h>
#include <bsp/lpc24xx.h>
#include <bsp/start.h>
#include <bsp/system-clocks.h>
static void lpc24xx_fatal_error( void)
{
while (true) {
/* Spin forever */
}
}
static void lpc24xx_ram_test_32( void)
{
volatile unsigned *out = (volatile unsigned *) bsp_ram_ext_start;
while (out < (volatile unsigned *) bsp_ram_ext_end) {
*out = (unsigned) out;
++out;
}
out = (volatile unsigned *) bsp_ram_ext_start;
while (out < (volatile unsigned *) bsp_ram_ext_end) {
if (*out != (unsigned) out) {
lpc24xx_fatal_error();
}
++out;
}
}
/**
* @brief EMC initialization.
*
* Dynamic Memory 0: Micron M T48LC 4M16 A2 P 75 IT
*/
static void lpc24xx_init_emc( void)
{
#ifdef LPC24XX_EMC_MICRON
int i = 0;
uint32_t mode = 0;
/* Enable power */
PCONP = SET_FLAGS( PCONP, 0x0800);
/* Set PIN selects */
PINSEL5 = SET_FLAGS( PINSEL5, 0x05050555);
PINSEL6 = SET_FLAGS( PINSEL6, 0x55555555);
PINSEL8 = SET_FLAGS( PINSEL8, 0x55555555);
PINSEL9 = SET_FLAGS( PINSEL9, 0x50555555);
/* Enable module, normal memory map and normal power mode */
EMC_CTRL = 1;
/* Use little-endian mode and 1:1 clock ratio */
EMC_CONFIG = 0;
/* Global dynamic settings */
/* FIXME */
EMC_DYN_APR = 2;
/* Data-in to active command period tWR + tRP */
EMC_DYN_DAL = 4;
/* Load mode register to active or refresh command period 2 tCK */
EMC_DYN_MRD = 1;
/* Active to precharge command period 44 ns */
EMC_DYN_RAS = 3;
/* Active to active command period 66 ns */
EMC_DYN_RC = 4;
/* Use command delayed strategy */
EMC_DYN_RD_CFG = 1;
/* Auto refresh period 66 ns */
EMC_DYN_RFC = 4;
/* Precharge command period 20 ns */
EMC_DYN_RP = 1;
/* Active bank a to active bank b command period 15 ns */
EMC_DYN_RRD = 1;
/* FIXME */
EMC_DYN_SREX = 5;
/* Write recovery time 15 ns */
EMC_DYN_WR = 1;
/* Exit self refresh to active command period 75 ns */
EMC_DYN_XSR = 5;
/* Dynamic Memory 0 settings */
/*
* Use SDRAM, 0 0 001 01 address mapping, disabled buffer, unprotected writes
*/
EMC_DYN_CFG0 = 0x0280;
/* CAS and RAS latency */
EMC_DYN_RASCAS0 = 0x0202;
/* Wait 50 micro seconds */
lpc24xx_micro_seconds_delay( 50);
/* Send command: NOP */
EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_NOP;
/* Wait 50 micro seconds */
lpc24xx_micro_seconds_delay( 50);
/* Send command: PRECHARGE ALL */
EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_PALL;
/* Shortest possible refresh period */
EMC_DYN_RFSH = 0x01;
/* Wait at least 128 ABH clock cycles */
for (i = 0; i < 128; ++i) {
asm volatile (" nop");
}
/* Wait 1 micro second */
lpc24xx_micro_seconds_delay( 1);
/* Set refresh period */
EMC_DYN_RFSH = 0x46;
/* Send command: MODE */
EMC_DYN_CTRL = EMC_DYN_CTRL_CE | EMC_DYN_CTRL_CS | EMC_DYN_CTRL_CMD_MODE;
/* Set mode registerin SDRAM */
mode = *((volatile uint32_t *) (0xa0000000 | (0x23 << (1 + 2 + 8))));
/* Send command: NORMAL */
EMC_DYN_CTRL = 0;
/* Enable buffer */
EMC_DYN_CFG0 |= 0x00080000;
/* Static Memory 0 settings */
EMC_STA_WAITWEN0 = 0x02;
EMC_STA_WAITOEN0 = 0x02;
EMC_STA_WAITRD0 = 0x1f;
EMC_STA_WAITPAGE0 = 0x1f;
EMC_STA_WAITWR0 = 0x1f;
EMC_STA_WAITTURN0 = 0x0f;
EMC_STA_CFG0 = 0x81;
/* Static Memory 1 settings */
EMC_STA_WAITWEN1 = 0x02;
EMC_STA_WAITOEN1 = 0x02;
EMC_STA_WAITRD1 = 0x08;
EMC_STA_WAITPAGE1 = 0x1f;
EMC_STA_WAITWR1 = 0x08;
EMC_STA_WAITTURN1 = 0x0f;
EMC_STA_CFG1 = 0x80;
/* RAM test */
lpc24xx_ram_test_32();
#endif /* LPC24XX_EMC_MICRON */
}
static void lpc24xx_init_pll( void)
{
#ifndef LPC24XX_HAS_UBOOT
/* Enable main oscillator */
SCS = SET_FLAGS( SCS, 0x20);
while (IS_FLAG_CLEARED( SCS, 0x40)) {
/* Wait */
}
/* Set PLL */
lpc24xx_set_pll( 1, 0, 11, 3);
#endif /* LPC24XX_HAS_UBOOT */
}
void /* __attribute__ ((section (".entry"))) */ bsp_start_hook_0( void)
{
/* Initialize PLL */
lpc24xx_init_pll();
#ifndef LPC24XX_HAS_UBOOT
/* Set pin functions */
PINSEL0 = 0;
PINSEL1 = 0;
PINSEL2 = 0;
PINSEL3 = 0;
PINSEL4 = 0;
PINSEL5 = 0;
PINSEL6 = 0;
PINSEL7 = 0;
PINSEL8 = 0;
PINSEL9 = 0;
PINSEL10 = 0;
/* Set periperal clocks */
PCLKSEL0 = 0;
PCLKSEL1 = 0;
/* Disable power for all modules */
PCONP = 0;
/* Set memory accelerator module (MAM) */
MAMCR = 0;
MAMTIM = 4;
/* Set general purpose IO */
IODIR0 = 0;
IODIR1 = 0;
IOSET0 = 0xffffffff;
IOSET1 = 0xffffffff;
/* Set fast IO */
FIO0DIR = 0;
FIO1DIR = 0;
FIO2DIR = 0;
FIO3DIR = 0;
FIO4DIR = 0;
FIO0SET = 0xffffffff;
FIO1SET = 0xffffffff;
FIO2SET = 0xffffffff;
FIO3SET = 0xffffffff;
FIO4SET = 0xffffffff;
/* Initialize UART 0 */
PCONP = SET_FLAGS( PCONP, 0x08);
PCLKSEL0 = SET_FLAGS( PCLKSEL0, 0x40);
PINSEL0 = SET_FLAGS( PINSEL0, 0x50);
U0LCR = 0;
U0IER = 0;
U0LCR = 0x80;
U0DLL = lpc24xx_cclk() / 16 / LPC24XX_UART_BAUD;
U0DLM = 0;
U0LCR = 0x03;
U0FCR = 0x07;
/* Initialize Timer 1 */
PCONP = SET_FLAGS( PCONP, 0x04);
PCLKSEL0 = SET_FLAGS( PCLKSEL0, 0x10);
#endif /* LPC24XX_HAS_UBOOT */
}
static void lpc24xx_copy_data( void)
{
#ifndef LPC24XX_HAS_UBOOT
unsigned *in = bsp_section_text_end;
unsigned *out = bsp_section_data_start;
/* Copy data */
while (out < bsp_section_data_end) {
*out = *in;
++out;
++in;
}
#endif /* LPC24XX_HAS_UBOOT */
}
static void lpc24xx_clear_bss( void)
{
unsigned *out = bsp_section_bss_start;
/* Clear BSS */
while (out < bsp_section_bss_end) {
*out = 0;
++out;
}
}
void /* __attribute__ ((section (".entry"))) */ bsp_start_hook_1( void)
{
/* Re-map interrupt vectors to internal RAM */
MEMMAP = SET_MEMMAP_MAP( MEMMAP, 2);
/* Initialize External Memory Controller (EMC) */
lpc24xx_init_emc();
/* Copy data */
lpc24xx_copy_data();
/* Clear BSS */
lpc24xx_clear_bss();
}
void bsp_start( void)
{
printk( "CPU clock (CCLK): %u\n", lpc24xx_cclk());
/* Exceptions */
rtems_exception_init_mngt();
/* Interrupts */
if (bsp_interrupt_initialize() != RTEMS_SUCCESSFUL) {
/* FIXME */
printk( "cannot intitialize interrupt support\n");
lpc24xx_fatal_error();
}
/* DMA */
lpc24xx_dma_initialize();
}
#define ULSR_THRE 0x00000020U
static void lpc24xx_BSP_output_char( char c)
{
while (IS_FLAG_CLEARED( U0LSR, ULSR_THRE)) {
/* Wait */
}
U0THR = c;
if (c == '\n') {
while (IS_FLAG_CLEARED( U0LSR, ULSR_THRE)) {
/* Wait */
}
U0THR = '\r';
}
}
BSP_output_char_function_type BSP_output_char = lpc24xx_BSP_output_char;