/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright(c) 2009 Nuvoton Technology Corp. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include "M051Series.h"
#include "LCD_Driver.h"
#define PLLCON_SETTING CLK_PLLCON_50MHz_HXT
#define PLL_CLOCK 50000000
#define LDROM_BASE FMC_LDROM_BASE
#define PAGE_SIZE FMC_FLASH_PAGE_SIZE
volatile uint8_t g_u8IsPress = FALSE;
#ifndef LDROM
extern uint32_t g_u32LoaderImageBase;
extern uint32_t g_u32LoaderImageLimit;
#endif
void EINT0_IRQHandler(void)
{
/* Clear P3.2 interrupt flag */
P3->ISRC = 1 << 2;
g_u8IsPress = TRUE;
}
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable Internal RC clock */
CLK->PWRCON |= CLK_PWRCON_IRC22M_EN_Msk;
/* Waiting for IRC22M clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_IRC22M_STB_Msk);
/* Switch HCLK clock source to internal RC */
CLK->CLKSEL0 = CLK_CLKSEL0_HCLK_S_HIRC;
/* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware.*/
CLK->PLLCON |= CLK_PLLCON_PD_Msk;
/* Enable external 12MHz XTAL, 10kHz */
CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk | CLK_PWRCON_IRC10K_EN_Msk;
/* Enable PLL and Set PLL frequency */
CLK->PLLCON = PLLCON_SETTING;
/* Waiting for clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk | CLK_CLKSTATUS_XTL12M_STB_Msk | CLK_CLKSTATUS_IRC10K_STB_Msk);
/* Switch HCLK clock source to PLL, STCLK to HCLK/2 */
CLK->CLKSEL0 = CLK_CLKSEL0_STCLK_S_HCLK_DIV2 | CLK_CLKSEL0_HCLK_S_PLL;
/* Enable IP clock */
CLK->AHBCLK = CLK_AHBCLK_ISP_EN_Msk;
CLK->APBCLK = CLK_APBCLK_UART0_EN_Msk | CLK_APBCLK_SPI0_EN_Msk;
/* IP clock source */
CLK->CLKSEL1 = CLK_CLKSEL1_UART_S_PLL;
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
//SystemCoreClockUpdate();
PllClock = PLL_CLOCK; // PLL
SystemCoreClock = PLL_CLOCK / 1; // HCLK
CyclesPerUs = PLL_CLOCK / 1000000; // For SYS_SysTickDelay()
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set P3 multi-function pins for UART0 RXD and TXD */
SYS->P3_MFP = SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0;
/* Set P1.4, P1.5, P1.6, P1.7 for SPI0 */
SYS->P1_MFP = SYS_MFP_P14_SPISS0 | SYS_MFP_P15_MOSI_0 | SYS_MFP_P16_MISO_0 | SYS_MFP_P17_SPICLK0;
/* Lock protected registers */
SYS_LockReg();
}
void UART0_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(PLL_CLOCK, 115200);
UART0->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
}
void GPIO_Init(void)
{
/*set P2.0 as output*/
GPIO_SetMode(P2, (1 << 0), GPIO_PMD_OUTPUT);
/* Enable debunce function of P3.2 (EINT0) */
GPIO_ENABLE_DEBOUNCE(P3, (1 << 2));
/* Set debounce time. it is about 6.4 ms */
GPIO_SET_DEBOUNCE_TIME(GPIO_DBCLKSRC_LIRC, GPIO_DBCLKSEL_64);
/*Initialize external interrupt*/
GPIO_EnableInt(P3, 2, GPIO_INT_FALLING);
NVIC_EnableIRQ(EINT0_IRQn);
}
#ifndef LDROM
/*---------------------------------------------------------------------------------------------------------*/
/* Main Function */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
int32_t i32Err = 0;
uint32_t u32Data, u32ImageSize, i, j, *pu32Loader;
/* Init system, IP clock and multi-function I/O */
SYS_Init();
/* Init UART0 for printf */
UART0_Init();
/* Init GPIO P2.0 (output) and P3.2 (EINT0) */
GPIO_Init();
/* Init SPI0 and LCD */
LCD_Init();
LCD_EnableBackLight();
LCD_ClearScreen();
/*
This sample shows how to switch between APROM and LDROM.
Target:
Smpl_FMC
Smpl_FMC is the code for APROM. It will program the firmware to LDROM and
user can press SW_INT to change to boot from LDROM.
In APROM, the LED blanking interval is 200ms.
Smpl_LDROM
Smpl_LDROM is the code for LDROM. User can press SW_INT to change to boot from APROM.
In LDROM, the LED blanking interval is 1000ms.
*/
LCD_Print(0, "Boot from APROM");
LCD_Print(1, "Press SW_INT ");
while(1)
{
if(g_u8IsPress)
{
g_u8IsPress = FALSE;
/* Unlock protected registers to write ISP Control Register (ISPCON) */
SYS_UnlockReg();
/* Program sample LD code to LDROM */
/* Enable ISP LDROM update function */
FMC->ISPCON = FMC_ISPCON_LDUEN_Msk | FMC_ISPCON_ISPEN_Msk;
/* Page Erase LDROM */
for(i = 0; i < 4096; i += PAGE_SIZE)
FMC_Erase(LDROM_BASE + i);
/* Erase Verify */
i32Err = 0;
for(i = LDROM_BASE; i < (LDROM_BASE + 4096); i += 4)
{
u32Data = FMC_Read(i);
if(u32Data != 0xFFFFFFFF)
{
i32Err = 1;
}
}
u32ImageSize = (uint32_t)&g_u32LoaderImageLimit - (uint32_t)&g_u32LoaderImageBase;
pu32Loader = (uint32_t *)&g_u32LoaderImageBase;
for(i = 0; i < u32ImageSize; i += PAGE_SIZE)
{
FMC_Erase(LDROM_BASE + i);
for(j = 0; j < PAGE_SIZE; j += 4)
{
FMC_Write(LDROM_BASE + i + j, pu32Loader[(i + j) / 4]);
}
}
/* Verify loader */
i32Err = 0;
for(i = 0; i < u32ImageSize; i += PAGE_SIZE)
{
for(j = 0; j < PAGE_SIZE; j += 4)
{
u32Data = FMC_Read(LDROM_BASE + i + j);
if(u32Data != pu32Loader[(i + j) / 4])
i32Err = 1;
if(i + j >= u32ImageSize)
break;
}
}
if(i32Err)
{
LCD_ClearScreen();
LCD_Print(0, "LDROM write fail");
}
else
{
/* Switch to boot from LDROM */
FMC->ISPCON = FMC_ISPCON_BS_LDROM;
SYS_ResetCPU();
}
while(1);
}
else
{
/* LED blanking for 200ms */
P2->DOUT ^= 1;
CLK_SysTickDelay(100000);
}
}
}
#else
/*---------------------------------------------------------------------------------------------------------*/
/* Main Function for LDROM */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
/* Init system, IP clock and multi-function I/O */
SYS_Init();
/* Init UART0 for printf */
UART0_Init();
/* Init GPIO P2.0 (output) and P3.2 (EINT0) */
GPIO_Init();
/* Init SPI0 and LCD */
LCD_Init();
LCD_EnableBackLight();
LCD_ClearScreen();
LCD_Print(0, "Boot from LDROM");
LCD_Print(1, "Press SW_INT ");
while(1)
{
if(g_u8IsPress)
{
g_u8IsPress = FALSE;
/* Switch to boot from APROM */
SYS_UnlockReg();
FMC->ISPCON = FMC_ISPCON_BS_APROM;
SYS_ResetCPU();
while(1);
}
else
{
/* LED blanking for 1000ms */
P2->DOUT ^= 1;
CLK_SysTickDelay(300000);
CLK_SysTickDelay(200000);
}
}
}
#endif
|