void Flash_Write(uint8_t addr, uint32_t value) { uint32_t block_addr = GetBlockAddr(); if(addr < BLOCK_SIZE / 4 - 1) { if(FirstUse) { FMC_Write(block_addr + 4 * (addr + 1), value); FirstUse = FALSE; } else { uint32_t i, write_addr; for(i = block_addr; i < block_addr + BLOCK_SIZE; i += 4) { write_addr = (i - (block_addr + 4)) / 4; if(write_addr != addr) { FMC_Write(i + BLOCK_SIZE, FMC_Read(i)); } } FMC_Write(block_addr, BLOCK_STAT_DISABLED); block_addr += BLOCK_SIZE; Block_Init(block_addr); FMC_Write(block_addr + (4 * (addr + 1)), value); } } }
/** * @brief Execute ISP command to write User Configuration. * @param[in] u32Config A two-word array. * u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1. * @param[in] u32Count Avaliable word count in u32Config. * @return Success or not. * @retval 0 Success. * @retval -1 Invalid parameter. */ int32_t FMC_WriteConfig(uint32_t *u32Config, uint32_t u32Count) { FMC_ENABLE_CFG_UPDATE(); FMC_Erase(FMC_CONFIG_BASE); FMC_Write(FMC_CONFIG_BASE, u32Config[0]); FMC_Write(FMC_CONFIG_BASE+4, u32Config[1]); FMC_DISABLE_CFG_UPDATE(); return 0; }
void Block_Write(uint32_t block, uint32_t* values) { uint8_t i; uint32_t CRC = USED_SIZE; for (i = 0; i < USED_SIZE / 4; i++) { CRC ^= Using_Values[i]; FMC_Write(block + i * 4, Using_Values[i]); } FMC_Write(block + USED_SIZE, CRC); }
int32_t fill_data_pattern(uint32_t u32StartAddr, uint32_t u32EndAddr, uint32_t u32Pattern) { uint32_t u32Addr; for (u32Addr = u32StartAddr; u32Addr < u32EndAddr; u32Addr += 4) { FMC_Write(u32Addr, u32Pattern); } return 0; }
uint32_t FMC_ProgramPage(uint32_t u32StartAddr, uint32_t * u32Buf) { uint32_t i; for (i = 0; i < FLASH_PAGE_SIZE/4; i++) { FMC_Write(u32StartAddr + i*4, u32Buf[i]); } return 0; }
/** * @brief Write User Configuration * * @param[in] u32Config The word buffer to store the User Configuration data. * @param[in] u32Count The word count to program to User Configuration. * * @retval 0 Success * @retval -1 Failed * * @details User must enable User Configuration update before writing it. * User must erase User Configuration before writing it. * User Configuration is also be page erase. User needs to backup necessary data * before erase User Configuration. */ int32_t FMC_WriteConfig(uint32_t *u32Config, uint32_t u32Count) { int32_t i; for(i = 0; i < u32Count; i++) { FMC_Write(FMC_CONFIG_BASE + i * 4, u32Config[i]); if(FMC_Read(FMC_CONFIG_BASE + i * 4) != u32Config[i]) return -1; } return 0; }
bool flash_io_driver_write(__ROM void* address, const void* data, uint16_t length) { if(is_range_valid(address) == false) { return false; } uint32_t _address = (uint32_t)address; uint32_t* _data = (uint32_t*)data; length /= sizeof(uint32_t); // number of bytes -> number of whole words // write for(uint16_t i = 0; i < length; i++) { UNLOCKREG(); if(FMC_Write(_address, *_data++) != E_FMC_OK) { LOCKREG(); return false; } LOCKREG(); _address += sizeof(uint32_t); } // verify uint32_t* source = (uint32_t*)address; _data = (uint32_t*)data; for(uint16_t i = 0; i < length; i++) { uint32_t s = *source++; uint32_t t = *_data++; if(s != t) { return false; } } return true; }
//============================================================================ // DATA FLASH OPERATION // u32addr : 0-1024 (For 4KBytes Data Flash) // u32data : 0-0xFFFFFFFF (4Bytes) //============================================================================ void DATA_FLASH_Write(uint32_t u32addr,uint32_t u32data) { uint32_t i=0; #ifdef M451 SYS_UnlockReg(); FMC_Open(); for(i=0; i<PAGE_SIZE; i++) data_buff[i] = FMC_Read(DATA_Flash_Start_ADD+i*4+ u32addr/PAGE_SIZE*2048); FMC_Erase(DATA_Flash_Start_ADD+u32addr/PAGE_SIZE*2048); data_buff[u32addr%PAGE_SIZE]=u32data; for(i=0; i<PAGE_SIZE; i++) FMC_Write(DATA_Flash_Start_ADD+i*4+ u32addr/PAGE_SIZE*2048, data_buff[i]); FMC_Close(); SYS_LockReg(); #else uint32_t data_buff[PAGE_SIZE]; __set_PRIMASK(1);//Avoid interrupt UNLOCKREG(); DrvFMC_EnableISP(); for(i=0; i<PAGE_SIZE; i++) DrvFMC_Read(DATA_Flash_Start_ADD+i*4+ u32addr/128*512, &data_buff[i]); DrvFMC_Erase(DATA_Flash_Start_ADD+u32addr/128*512); data_buff[u32addr%128]=u32data; for(i=0; i<PAGE_SIZE; i++) DrvFMC_Write(DATA_Flash_Start_ADD+i*4+ u32addr/128*512, data_buff[i]); DrvFMC_DisableISP(); LOCKREG(); __set_PRIMASK(0); #endif }
void write_impl_less(uint8_t * addressE, const uint8_t * data, int size) { uint32_t buf[PAGE_SIZE_32B]; int i; uint32_t * p_adr_start = (uint32_t*) (((int)addressE) & (~(PAGE_SIZE - 1))); uint8_t * p_adr_pos = ((uint8_t*)buf) + (((int)addressE) & (PAGE_SIZE - 1)); for(i=0; i<PAGE_SIZE_32B; i++) buf[i] = p_adr_start[i]; for(i=0; i<size; i++) p_adr_pos[i] = ((uint8_t*)data)[i]; // Erase page FMC_Erase((uint32_t)p_adr_start); for(i = 0; i < PAGE_SIZE_32B; i++) FMC_Write((uint32_t)&p_adr_start[i], buf[i]); }
static int LoadImage(uint32_t u32ImageBase, uint32_t u32ImageLimit, uint32_t u32FlashAddr, uint32_t u32MaxSize) { uint32_t i, j, u32Data, u32ImageSize, *pu32Loader; u32ImageSize = u32MaxSize; printf("Program image to flash address 0x%x...", u32FlashAddr); pu32Loader = (uint32_t *)u32ImageBase; for(i = 0; i < u32ImageSize; i += FMC_FLASH_PAGE_SIZE) { FMC_Erase(u32FlashAddr + i); for(j = 0; j < FMC_FLASH_PAGE_SIZE; j += 4) { FMC_Write(u32FlashAddr + i + j, pu32Loader[(i + j) / 4]); } } printf("OK.\n"); printf("Verify ..."); /* 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(u32FlashAddr + i + j); if(u32Data != pu32Loader[(i + j) / 4]) { printf("data mismatch on 0x%x, [0x%x], [0x%x]\n", u32FlashAddr + i + j, u32Data, pu32Loader[(i + j) / 4]); return -1; } if(i + j >= u32ImageSize) break; } } printf("OK.\n"); return 0; }
void Block_Init(uint32_t addr) { FMC_Write(addr, BLOCK_STAT_ENABLED); }
/*---------------------------------------------------------------------------------------------------------*/ 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_RESET_CPU(); } while (1); } else { /* LED blanking for 200ms */ P2->DOUT ^= 1; SYS_SysTickDelay(100000); } } }
/** * @brief Main funcion * @param None * @retval 0: Success; <0: Failed */ int32_t main (void) { int32_t i32Err; uint32_t u32Data, i, u32ImageSize, j, *pu32Loader; uint8_t ch; UNLOCKREG(); /* Enable FMC ISP function */ FMC_Init(); /* Read Company ID */ u32Data = 0; FMC_ReadCID(&u32Data); if (u32Data != 0xda) { printf("Wrong CID: 0x%x\n", u32Data); goto lexit; } /* Check the signature to check if Simple LD code is finished or not */ if (inpw(KEY_ADDR) == SIGNATURE) { /* Just clear SIGNATURE and finish the sample code if Simple LD code has been executed. */ outpw(KEY_ADDR, 0); /* Read BS */ printf(" Boot Mode .................................. "); if (FMC_GetBootSelect() == E_FMC_APROM) printf("[APROM]\n"); else { printf("[LDROM]\n"); printf(" WARNING: The driver sample code must execute in AP mode!\n"); } goto lexit; } printf("\n\n"); printf("+-------------------------------------------------------------------------+\n"); printf("| NANO1xx Flash Memory Controller Driver Sample Code |\n"); printf("+-------------------------------------------------------------------------+\n"); printf(" NOTE: This sample must be applied to NANO1xx series equipped with 16KB RAM.\n"); /* Read BS */ printf(" Boot Mode .................................. "); if (FMC_GetBootSelect() == E_FMC_APROM) printf("[APROM]\n"); else { printf("[LDROM]\n"); printf(" WARNING: The driver sample code must execute in AP mode!\n"); goto lexit; } /* Read Data Flash base address */ u32Data = FMC_ReadDataFlashBaseAddr(); printf(" Data Flash Base Address .................... [0x%08x]\n", u32Data); /* Check the data in LD ROM to avoid overwrite them */ FMC_Read(LDROM_BASE, &u32Data); if (u32Data != 0xFFFFFFFF) { printf("\n WARNING: There is code in LD ROM.\n If you proceed, the code in LD ROM will be corrupted.\n"); printf(" Continue? [y/n]:"); ch = getchar(); putchar(ch); if (ch != 'y') goto lexit; printf("\n\n"); } /* Enable LDROM update */ FMC_EnableLDUpdate(); printf(" Erase LD ROM ............................... "); /* 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) { FMC_Read(i, &u32Data); if(u32Data != 0xFFFFFFFF) { printf(" u32Data = 0x%x\n", u32Data); i32Err = 1; } } if (i32Err) printf("[FAIL]\n"); else printf("[OK]\n"); printf(" Program LD ROM test ........................ "); /* Program LD ROM and read out data to compare it */ for (i = LDROM_BASE; i < (LDROM_BASE+4096); i += 4) { FMC_Write(i, i); } i32Err = 0; for (i = LDROM_BASE; i < (LDROM_BASE+4096); i += 4) { FMC_Read(i, &u32Data); if(u32Data != i) { i32Err = 1; } } if (i32Err) printf("[FAIL]\n"); else printf("[OK]\n"); /* Check LD image size */ u32ImageSize = (uint32_t)&loaderImageLimit - (uint32_t)&loaderImageBase; if (u32ImageSize == 0) { printf(" ERROR: Loader Image is 0 bytes!\n"); goto lexit; } if (u32ImageSize > 4096) { printf(" ERROR: Loader Image is larger than 4KBytes!\n"); goto lexit; } printf(" Program Simple LD Code ..................... "); pu32Loader = (uint32_t *)&loaderImageBase; 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) { FMC_Read(LDROM_BASE + i + j, &u32Data); if (u32Data != pu32Loader[(i+j)/4]) i32Err = 1; if (i + j >= u32ImageSize) break; } } if(i32Err) { printf("[FAIL]\n"); } else { printf("[OK]\n"); /* Reset CPU to boot to LD mode */ printf("\n >>> Reset to LD mode <<<\n"); FMC_BootSelect(E_FMC_LDROM); GCR->IPRST_CTL1 = GCR_IPRSTCTL1_CPU; } lexit: /* Disable FMC ISP function */ FMC_DeInit(); /* Lock protected registers */ LOCKREG(); printf("\nFMC Sample Code Completed.\n"); }
void FMC_LDROM_Test(void) { int32_t i32Err; uint32_t u32Data, i, j, *pu32Loader; /* Enable LDROM Update */ _FMC_ENABLE_LD_UPDATE(); printf(" Erase LD ROM ............................... "); /* Page Erase LDROM */ for (i = 0; i < FMC_LDROM_SIZE; i += FMC_FLASH_PAGE_SIZE) FMC_Erase(FMC_LDROM_BASE + i); /* Erase Verify */ i32Err = 0; for (i = FMC_LDROM_BASE; i < (FMC_LDROM_BASE+FMC_LDROM_SIZE); i += 4) { u32Data = FMC_Read(i); if (u32Data != 0xFFFFFFFF) { i32Err = 1; } } if (i32Err) printf("[FAIL]\n"); else printf("[OK]\n"); printf(" Program LD ROM test ........................ "); /* Program LDROM and read out data to compare it */ for(i = FMC_LDROM_BASE; i < (FMC_LDROM_BASE+FMC_LDROM_SIZE); i += 4) { FMC_Write(i, i); } i32Err = 0; for(i = FMC_LDROM_BASE; i < (FMC_LDROM_BASE+FMC_LDROM_SIZE); i += 4) { u32Data = FMC_Read(i); if (u32Data != i) { i32Err = 1; } } if (i32Err) printf("[FAIL]\n"); else printf("[OK]\n"); printf(" Program Simple LD Code ..................... "); pu32Loader = (uint32_t *)&loaderImageBase; for (i=0;i<g_u32ImageSize;i+=FMC_FLASH_PAGE_SIZE) { FMC_Erase(FMC_LDROM_BASE + i); for (j=0;j<FMC_FLASH_PAGE_SIZE;j+=4) { FMC_Write(FMC_LDROM_BASE + i + j, pu32Loader[(i + j) / 4]); } } /* Verify loader */ i32Err = 0; for (i=0;i<g_u32ImageSize;i+=FMC_FLASH_PAGE_SIZE) { for (j=0;j<FMC_FLASH_PAGE_SIZE;j+=4) { u32Data = FMC_Read(FMC_LDROM_BASE + i + j); if (u32Data != pu32Loader[(i+j)/4]) i32Err = 1; if (i + j >= g_u32ImageSize) break; } } if (i32Err) { printf("[FAIL]\n"); } else { printf("[OK]\n"); /* Reset CPU to boot to LD mode */ printf("\n >>> Reset to LD mode <<<\n"); /* Make sure message has printed out */ _UART_WAIT_TX_EMPTY(UART0); FMC->ISPCON |= FMC_ISPCON_BS_LDROM; /* CPU Reset */ _SYS_RESET_CPU(); } }
_Bool Flash_Read(uint8_t addr, uint32_t* dist) { if (addr < USED_SIZE / 4) { if (ReadRequed) { uint8_t i; uint32_t CRC = USED_SIZE; Block_Read(NEW_BLOCK_ADDR); for (i = 0; i < USED_SIZE / 4; i++) { CRC ^= Using_Values[i]; } if (CRC == FMC_Read(NEW_BLOCK_ADDR + USED_SIZE)) { *dist = FMC_Read(NEW_BLOCK_ADDR + addr * 4); /*if (*dist == 0xffff) { return FALSE; }*/ ReadRequed = FALSE; return TRUE; } else { FMC_Erase(NEW_BLOCK_ADDR); Flash_Init(); DPRINTF(("Area 1 error! \n")); } Block_Read(BAK_BLOCK_ADDR); for (i = 0; i < USED_SIZE / 4; i++) { CRC ^= Using_Values[i]; } if (CRC == FMC_Read(BAK_BLOCK_ADDR + USED_SIZE)) { Block_Clear(NEW_BLOCK_ADDR); for (i = 0; i < USED_SIZE / 4; i++) { FMC_Write(NEW_BLOCK_ADDR + i * 4, Using_Values[i]); } FMC_Write(NEW_BLOCK_ADDR + USED_SIZE, CRC); *dist = FMC_Read(BAK_BLOCK_ADDR + addr * 4); /*if (*dist == 0xffff) { return FALSE; }*/ ReadRequed = FALSE; return TRUE; } else { FMC_Erase(BAK_BLOCK_ADDR); Flash_Init(); DPRINTF(("Area 2 CRC error! \n")); } } else { *dist = Using_Values[addr]; return TRUE; } } else { DPRINTF(("Err: Addr: %d overrange!\n", addr)); } return FALSE; }