/******************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* @brief
* Demonstrate how to implement a USB mouse device.
* It use PC0 ~ PC5 to control mouse direction and mouse key.
* It also supports USB suspend and remote wakeup.
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "NUC123.h"
#include "hid_mouse.h"
#include "common.h"
#define CLK_PLLCON_60MHz_XTAL 0xC026 // 60MHz
#define CLK_PLLCON_72MHz_XTAL 0xC02E // 72MHz
#define CLK_PLLCON_144MHz_XTAL 0x402E // 144MHz
/*--------------------------------------------------------------------------*/
void SYS_Init(void)
{
/* Enable XT1_OUT (PF0) and XT1_IN (PF1) */
SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Enable Internal RC 22.1184MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);
/* Waiting for Internal RC clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
/* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
/* Enable external XTAL 12MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);
/* Waiting for external XTAL clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);
/* Set Flash Access Delay */
FMC->FATCON |= FMC_FATCON_FOMSEL1_Msk | FMC_FATCON_FOMSEL0_Msk;
/* Set core clock */
CLK_SetCoreClock(72000000);
/* Enable module clock */
CLK_EnableModuleClock(UART0_MODULE);
CLK_EnableModuleClock(USBD_MODULE);
/* Select module clock source */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));
CLK_SetModuleClock(USBD_MODULE, 0, CLK_CLKDIV_USB(3));
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFP |= (SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD);
/* Set PC.13 as CLKO function pin */
//SYS->GPC_MFP = SYS_GPC_MFP_PC13_CLKO;
//SYS->ALT_MFP = SYS_ALT_MFP_PC13_CLKO;
/* Enable CLKO (PC.13) for monitor HCLK. CLKO = HCLK/8 Hz*/
//CLK_EnableCKO(CLK_CLKSEL2_FRQDIV_S_HCLK, 2, NULL);
}
void UART0_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
/* Reset IP */
SYS->IPRSTC2 |= SYS_IPRSTC2_UART0_RST_Msk;
SYS->IPRSTC2 &= ~SYS_IPRSTC2_UART0_RST_Msk;
/* Configure UART0 and set UART0 Baudrate */
UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HXT, 115200);
UART0->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
}
void GPIO_Init(void)
{
/* Enable PC0~5 interrupt for wakeup */
PC->ISRC |= 0x3f;
PC->IEN |= 0x3f | (0x3f << 16);
PC->DBEN |= 0x3f; // Enable key debounce
GPIO->DBNCECON = 0x16; // Debounce time is about 6ms
NVIC_EnableIRQ(GPCDF_IRQn);
}
void GPCDF_IRQHandler(void)
{
PC->ISRC = 0x3f;
//PB4 ^= 1;
}
unsigned int Check_Sum_read_flash(uint32_t u32StartAddr, uint32_t u32EndAddr)
{
uint32_t u32Addr;
uint32_t u32data=0,temp;
for (u32Addr = u32StartAddr; u32Addr < u32EndAddr; u32Addr += 4)
{
//temp=Read_Flash(u32Addr);
temp=FMC_Read(u32Addr);
u32data += (temp&0xff);
u32data += (temp>>8)&0xff;
u32data += (temp>>16)&0xff;
u32data += (temp>>24)&0xff;
}
return u32data;
}
#define IAP_COMMAND_RAM (0x20004000-4)
#define IAP_SIG 0X5AA55771
volatile unsigned int CHECKSUM, AP_FLASH_CHECKSUM;
typedef void (FUNC_PTR)(void);
static int load_image_to_flash(uint32_t image_base, uint32_t image_limit)
{
uint32_t u32ImageSize;
u32ImageSize = image_limit - image_base;
if (u32ImageSize == 0) {
//printf(" ERROR: Loader Image is 0 bytes!\n");
return -1;
}
if (u32ImageSize > APROM_SIZE) {
//printf(" ERROR: Loader Image is larger than %d KBytes!\n", APROM_SIZE/1024);
return -1;
}
//printf("OK.\n");
return 0;
}
extern uint32_t loaderImage1Base, loaderImage1Limit;
uint32_t jump_flag;
/*---------------------------------------------------------------------------------------------------------*/
/* Main Function */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
uint32_t *IAP_COMMAND;
uint32_t i;
FUNC_PTR *ResetFunc;
IAP_COMMAND = (uint32_t *)IAP_COMMAND_RAM; //for ram command
//for backrom file
load_image_to_flash((uint32_t)&loaderImage1Base, (uint32_t)&loaderImage1Limit);
/* Unlock protected registers */
SYS_UnlockReg();
SYS_Init();
UART0_Init();
GPIO_Init();
/*enable FMC ISP function */
//for flash operation
FMC_Open();
//FMC_SetVectorPageAddr(0x0);
FMC_EnableAPUpdate();
if(*IAP_COMMAND==IAP_SIG)
goto JMP_IAP;
//read flash backup checksum
CHECKSUM=FMC_Read(CHECKSUM_ADDRESS);
//CHECK SUM
AP_FLASH_CHECKSUM=Check_Sum_read_flash(APROM_ADDRESS,APROM_ADDRESS_END);
if(CHECKSUM == AP_FLASH_CHECKSUM){
goto JMP_APROM;
}
//if checksum is ok, jump to IAP
JMP_IAP:
USBD_Open(&gsInfo, HID_ClassRequest, NULL); //OPEN USB FUNCTION.
/* Endpoint configuration */
HID_Init();
USBD_Start();
NVIC_EnableIRQ(USBD_IRQn);
USBD_SET_PAYLOAD_LEN(EP4,64);
USBD_SET_PAYLOAD_LEN(EP5,64);
//PB4 = 0; // LED to show system is on line
//DO IAP FLOW
jump_flag=0;
while(1)
{
if(jump_flag==1)
{
for(i=0;i<100;i++)
CLK_SysTickDelay(5000);
break;
}
//HID_UpdateMouseData();
//HID_UpdateKbData();
}
JMP_APROM:
//FMC_DisableAPUpdate();
//FMC_Close();
//BranchTo(APROM_ADDRESS);
*IAP_COMMAND=0;
/* Disable all interrupts before change VECMAP */
NVIC->ICER[0] = 0xFFFFFFFF;
/* Set vector table of startup AP address */
FMC_SetVectorPageAddr(0x8000);
/* Reset All IP before boot to new AP */
SYS->IPRSTC2 = 0xFFFFFFFF;
SYS->IPRSTC2 = 0;
/* Obtain Reset Handler address of new boot. */
ResetFunc = (FUNC_PTR *)M32(4);
/* Set Main Stack Pointer register of new boot */
__set_MSP(M32(0));
/* Call reset handler of new boot */
ResetFunc();
while(1);
}
typedef __packed struct
{
uint32_t u8Cmd;
uint32_t address;
uint32_t data;
uint32_t pid;
} CMD_T;
CMD_T rCmd, tCmd;
void EP5_Handler(void) /* Interrupt out handler */
{
uint8_t *ptr4;
uint8_t *ptr5;
uint32_t erase_addrss;
/* Interrupt In */
ptr4 = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP4));
/* Interrupt OUT */
ptr5 = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP5));
//USBD_MemCopy(&g_u8PageBuff[0], ptr5, EP5_MAX_PKT_SIZE);
//do iap command in here
/*
for(t=0;t<64;t++)
{
printf("0x%x\n\r",g_u8PageBuff[t]);
g_u8PageBuff[t]=g_u8PageBuff[t]+sss;
}
sss=sss+1;
*/
USBD_MemCopy((uint8_t *)&rCmd, ptr5, 64);
//check verison
if(rCmd.u8Cmd==ISP_COMMAND_VERSION)
{
tCmd.u8Cmd=ISP_COMMAND_VERSION;
tCmd.data=ISP_VERION;
}
//erase
if(rCmd.u8Cmd==ISP_COMMAND_ERASE_APROM)
{
tCmd.u8Cmd=ISP_COMMAND_ERASE_APROM;
for(erase_addrss=APROM_ADDRESS;erase_addrss<APROM_ADDRESS+APROM_SIZE;erase_addrss=erase_addrss+512)
{
if(FMC_Erase(erase_addrss)!=0)
{
tCmd.data=0;//false
goto finish;
}
}
tCmd.data=1;//true
}
//program
if(rCmd.u8Cmd==ISP_COMMAND_PROGRAM_APROM)
{
tCmd.u8Cmd=ISP_COMMAND_PROGRAM_APROM;
FMC_Write(rCmd.address,rCmd.data);
if(FMC_Read(rCmd.address)!=rCmd.data)
tCmd.data=0;//false
else
tCmd.data=1;//pass
}
if(rCmd.u8Cmd==ISP_COMMAND_JUMP_APROM)
{
tCmd.u8Cmd=ISP_COMMAND_JUMP_APROM;
tCmd.data=1;
jump_flag=1;
}
finish:
tCmd.pid=rCmd.pid;
//end iap
USBD_MemCopy(ptr4, (uint8_t *)&tCmd, EP4_MAX_PKT_SIZE);
USBD_SET_PAYLOAD_LEN(EP4, EP4_MAX_PKT_SIZE);
USBD_SET_PAYLOAD_LEN(EP5, EP5_MAX_PKT_SIZE);
// g_u8EP5Ready = 1;
}
/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
|