- /******************************************************************************
- * [url=home.php?mod=space&uid=288409]@file[/url] APROM_main.c
- * [url=home.php?mod=space&uid=895143]@version[/url] V1.00
- * $Revision: 6 $
- * $Date: 16/02/16 9:21a $
- * [url=home.php?mod=space&uid=247401]@brief[/url] FMC APROM IAP sample for NANO103 series MCU
- *
- * @note
- * Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
- *****************************************************************************/
- #include <stdio.h>
- #include "Nano103.h"
- typedef void (FUNC_PTR)(void);
- extern uint32_t loaderImage1Base, loaderImage1Limit; /* symbol of image start and end */
- void SYS_Init(void)
- {
- SYS_UnlockReg(); /* Unlock protected registers */
- /* Set HCLK source form HXT and HCLK source divide 1 */
- CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HXT,CLK_HCLK_CLK_DIVIDER(1));
- /* Enable external 12MHz HXT, 32KHz LXT and HIRC */
- CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk | CLK_PWRCTL_LXTEN_Msk | CLK_PWRCTL_HIRC0EN_Msk | CLK_PWRCTL_HIRC1EN_Msk | CLK_PWRCTL_MIRCEN_Msk);
- /* Waiting for clock ready */
- CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk | CLK_STATUS_LXTSTB_Msk | CLK_STATUS_HIRC0STB_Msk | CLK_STATUS_HIRC1STB_Msk | CLK_STATUS_MIRCSTB_Msk);
- CLK_SetCoreClock(32000000); /* Set HCLK frequency 32MHz */
- CLK_EnableModuleClock(UART0_MODULE); /* Enable UART0 input clock */
- /* Select IP clock source */
- CLK_SetModuleClock(UART0_MODULE,CLK_CLKSEL1_UART0SEL_HIRC,CLK_UART0_CLK_DIVIDER(1));
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init I/O Multi-function */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Set PA multi-function pins for UART0 RXD and TXD */
- SYS->GPB_MFPL &= ~( SYS_GPB_MFPL_PB0MFP_Msk | SYS_GPB_MFPL_PB1MFP_Msk);
- SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB0MFP_UART0_RXD | SYS_GPB_MFPL_PB1MFP_UART0_TXD );
- SYS_LockReg(); /* Lock protected registers */
- }
- void UART0_Init(void)
- {
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init UART */
- /*---------------------------------------------------------------------------------------------------------*/
- SYS_ResetModule(UART0_RST); /* Reset UART0 */
- UART_Open(UART0, 115200); /* Configure UART0 and set UART0 as baudrate 115200, N,8,1 */
- }
- /**
- * @brief Check User Configuration CONFIG0 bit 6 IAP boot setting. If it's not boot with IAP
- * mode, modify it and execute a chip reset to make it take effect.
- * [url=home.php?mod=space&uid=266161]@return[/url] Is boot with IAP mode or not.
- * @retval 0 Success.
- * @retval -1 Failed on reading or programming User Configuration.
- */
- static int set_IAP_boot_mode(void)
- {
- uint32_t au32Config[2]; /* User Configuration */
- if (FMC_ReadConfig(au32Config, 2) < 0) { /* Read User Configuration CONFIG0 and CONFIG1. */
- printf("\nRead User Config failed!\n");
- return -1; /* Failed on reading User Configuration */
- }
- if (au32Config[0] & 0x40) { /* Check if it's boot from APROM/LDROM with IAP. */
- FMC_ENABLE_CFG_UPDATE(); /* Enable User Configuration update. */
- au32Config[0] &= ~0x40; /* Select IAP boot mode. */
- FMC_WriteConfig(au32Config, 2);/* Update User Configuration CONFIG0 and CONFIG1. */
- SYS->IPRST1 = SYS_IPRST1_CHIPRST_Msk; /* Perform chip reset to make new User Config take effect. */
- }
- return 0; /* success */
- }
- /*
- * Set stack base address to SP register.
- */
- #ifdef __ARMCC_VERSION /* for Keil compiler */
- __asm __set_SP(uint32_t _sp)
- {
- MSR MSP, r0
- BX lr
- }
- #endif
- /**
- * @brief Load an image to specified flash address. The flash area must have been enabled by
- * caller. For example, if caller want to program an image to LDROM, FMC_ENABLE_LD_UPDATE()
- * must be called prior to calling this function.
- * @return Image is successfully programmed or not.
- * @retval 0 Success.
- * @retval -1 Program/verify failed.
- */
- static int load_image_to_flash(uint32_t image_base, uint32_t image_limit, uint32_t flash_addr, uint32_t max_size)
- {
- uint32_t i, j, u32Data, u32ImageSize, *pu32Loader;
- u32ImageSize = max_size; /* Give the maximum size of programmable flash area. */
- printf("Program image to flash address 0x%x...", flash_addr); /* information message */
- /*
- * program the whole image to specified flash area
- */
- pu32Loader = (uint32_t *)image_base;
- for (i = 0; i < u32ImageSize; i += FMC_FLASH_PAGE_SIZE) {
- FMC_Erase(flash_addr + i); /* erase a flash page */
- for (j = 0; j < FMC_FLASH_PAGE_SIZE; j += 4) { /* program image to this flash page */
- FMC_Write(flash_addr + i + j, pu32Loader[(i + j) / 4]);
- }
- }
- printf("OK.\nVerify ...");
- /* Verify loader */
- for (i = 0; i < u32ImageSize; i += FMC_FLASH_PAGE_SIZE) {
- for (j = 0; j < FMC_FLASH_PAGE_SIZE; j += 4) {
- u32Data = FMC_Read(flash_addr + i + j); /* read a word from flash memory */
- if (u32Data != pu32Loader[(i+j)/4]) { /* check if the word read from flash be matched with original image */
- printf("data mismatch on 0x%x, [0x%x], [0x%x]\n", flash_addr + i + j, u32Data, pu32Loader[(i+j)/4]);
- return -1; /* image program failed */
- }
- if (i + j >= u32ImageSize) /* check if it reach the end of image */
- break;
- }
- }
- printf("OK.\n");
- return 0; /* success */
- }
- int main()
- {
- uint8_t u8Item; /* menu item */
- uint32_t u32Data; /* temporary data word */
- FUNC_PTR *func; /* function pointer */
- SYS_Init(); /* Init System, IP clock and multi-function I/O */
- UART0_Init(); /* initialize UART0 */
- /*---------------------------------------------------------------------------------------------------------*/
- /* SAMPLE CODE */
- /*---------------------------------------------------------------------------------------------------------*/
- printf("\n\n");
- printf("+----------------------------------------+\n");
- printf("| Nano103 FMC_IAP Sample Code |\n");
- printf("| [APROM code] |\n");
- printf("+----------------------------------------+\n");
- SYS_UnlockReg(); /* Unlock register lock protect */
- FMC_Open(); /* Enable FMC ISP function */
- /*
- * Check if User Configuration CBS is boot with IAP mode.
- * If not, modify it.
- */
- if (set_IAP_boot_mode() < 0) {
- printf("Failed to set IAP boot mode!\n");
- goto lexit; /* Failed to set IAP boot mode. Program aborted. */
- }
- /* Read BS */
- printf(" Boot Mode ............................. ");
- if (FMC_GetBootSource() == 0) /* Get boot source */
- printf("[APROM]\n"); /* Is booting from APROM */
- else {
- printf("[LDROM]\n"); /* Is booting from LDROM */
- printf(" WARNING: The sample code must execute in APROM!\n");
- goto lexit; /* This sample program must execute in APROM. Program aborted. */
- }
- u32Data = FMC_ReadCID(); /* get company ID */
- printf(" Company ID ............................ [0x%08x]\n", u32Data);
- u32Data = FMC_ReadPID(); /* get product ID */
- printf(" Product ID ............................ [0x%08x]\n", u32Data);
- /* Read User Configuration CONFIG0 */
- printf(" User Config 0 ......................... [0x%08x]\n", FMC_Read(FMC_CONFIG_BASE));
- /* Read User Configuration CONFIG1 */
- printf(" User Config 1 ......................... [0x%08x]\n", FMC_Read(FMC_CONFIG_BASE+4));
- do {
- printf("\n\n\n");
- printf("+----------------------------------------+\n");
- printf("| Select |\n");
- printf("+----------------------------------------+\n");
- printf("| [0] Load IAP code to LDROM |\n");
- printf("| [1] Run IAP program (in LDROM) |\n");
- printf("+----------------------------------------+\n");
- printf("Please select...");
- u8Item = getchar(); /* block waiting to receive any one character from UART0 */
- printf("%c\n", u8Item); /* print out the selected item */
- switch (u8Item) {
- case '0':
- FMC_ENABLE_LD_UPDATE(); /* Enable LDROM update capability */
- /*
- * The binary image of LDROM code is embedded in this sample.
- * load_image_to_flash() will program this LDROM code to LDROM.
- */
- if (load_image_to_flash((uint32_t)&loaderImage1Base, (uint32_t)&loaderImage1Limit,
- FMC_LDROM_BASE, FMC_LDROM_SIZE) != 0) {
- printf("Load image to LDROM failed!\n");
- goto lexit; /* Load LDROM code failed. Program aborted. */
- }
- FMC_DISABLE_LD_UPDATE(); /* Disable LDROM update capability */
- break;
- case '1':
- printf("\n\nChange VECMAP and branch to LDROM...\n");
- while (!(UART0->FIFOSTS & UART_FIFOSTS_TXEMPTY_Msk)); /* Wait for UART0 TX FIFO cleared */
- /* NOTE!
- * Before change VECMAP, user MUST disable all interrupts.
- * The following code CANNOT locate in address 0x0 ~ 0x200.
- */
- /* FMC_SetVectorPageAddr(FMC_LDROM_BASE) */
- FMC->ISPCMD = FMC_ISPCMD_VECMAP; /* ISP command */
- FMC->ISPADDR = FMC_LDROM_BASE; /* Vector remap address */
- FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; /* Trigger ISP command */
- while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ; /* Wait for ISP command done. */
- /*
- * The reset handler address of an executable image is located at offset 0x4.
- * Thus, this sample get reset handler address of LDROM code from FMC_LDROM_BASE + 0x4.
- */
- func = (FUNC_PTR *)*(uint32_t *)(FMC_LDROM_BASE + 4);
- /*
- * The stack base address of an executable image is located at offset 0x0.
- * Thus, this sample get stack base address of LDROM code from FMC_LDROM_BASE + 0x0.
- */
- __set_SP(*(uint32_t *)FMC_LDROM_BASE);
- /*
- * Brach to the LDROM code's reset handler in way of function call.
- */
- func();
- break;
- default :
- continue; /* invalid selection */
- }
- } while (1);
- lexit: /* program exit */
- FMC_Close(); /* Disable FMC ISP function */
- SYS_LockReg(); /* Lock protected registers */
- printf("\nFMC Sample Code Completed.\n");
- while (1);
- }
- /*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/