/** * \brief Sets the selected GPNVM bit. * * \param gpnvm GPNVM bit index. * \returns 0 if successful; otherwise returns an error code. */ extern uint32_t FLASHD_SetGPNVM( uint8_t ucGPNVM ) { assert( ucGPNVM < 3 ) ; if ( !FLASHD_IsGPNVMSet( ucGPNVM ) ) { return EFC_PerformCommand( EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP ) ; } else { return 0 ; } }
/** * \brief Clears the selected GPNVM bit. * * \param gpnvm GPNVM bit index. * \returns 0 if successful; otherwise returns an error code. */ extern uint32_t FLASHD_ClearGPNVM( uint8_t ucGPNVM ) { assert( ucGPNVM < GPNVM_NUM_MAX ) ; if ( FLASHD_IsGPNVMSet( ucGPNVM ) ) { return EFC_PerformCommand( EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP ) ; } else { return 0 ; } }
//------------------------------------------------------------------------------ /// Clears the selected GPNVM bit. /// Returns 0 if successful; otherwise returns an error code. /// \param gpnvm GPNVM index. //------------------------------------------------------------------------------ unsigned char FLASHD_ClearGPNVM(unsigned char gpnvm) { SANITY_CHECK(gpnvm < EFC_NUM_GPNVMS); if (FLASHD_IsGPNVMSet(gpnvm)) { return EFC_PerformCommand(AT91C_EFC_FCMD_CFB, gpnvm); } else { return 0; } }
//------------------------------------------------------------------------------ /// Sets the selected GPNVM bit. /// Returns 0 if successful; otherwise returns an error code. /// \param gpnvm GPNVM index. //------------------------------------------------------------------------------ unsigned char FLASHD_SetGPNVM(unsigned char gpnvm) { SANITY_CHECK(gpnvm < CHIP_EFC_NUM_GPNVMS); if (!FLASHD_IsGPNVMSet(gpnvm)) { return EFC_PerformCommand(AT91C_BASE_EFC, AT91C_EFC_FCMD_SFB, gpnvm); } else { return 0; } }
//------------------------------------------------------------------------------ /// Clears the selected GPNVM bit. /// Returns 0 if successful; otherwise returns an error code. /// \param gpnvm GPNVM index. //------------------------------------------------------------------------------ unsigned char FLASHD_ClearGPNVM(unsigned char gpnvm) { AT91S_EFC *pEfc = AT91C_BASE_EFC0; //SANITY_CHECK(gpnvm < EFC_NUM_GPNVMS); if (FLASHD_IsGPNVMSet(gpnvm)) { #ifdef AT91C_BASE_EFC1 // GPNVM in EFC1 if (gpnvm >= 8) { pEfc = AT91C_BASE_EFC1; gpnvm -= 8; } #endif return EFC_PerformCommand(pEfc, AT91C_MC_FCMD_CLR_GP_NVM, gpnvm); } else { return 0; } }
int flash_test( void ) { unsigned int i, j; unsigned char error; unsigned int pBuffer[AT91C_IFLASH_PAGE_SIZE / 4]; unsigned int lastPageAddress; volatile unsigned int *pLastPageData; //unsigned char pageLocked; // Initialize flash driver //FLASHD_Initialize( BOARD_MCK ); // Unlock whole flash //printf("-I- Unlocking the whole flash\n\r"); LED_Clear(LED_DS2); // The AT91SAM7A3 has 16 lock regions. Each lock region contains 16 pages of 256 bytes. // Each lock region has a size of 4 Kbytes, thus only the first 64 Kbytes can be locked. #if defined(at91sam7a3) error = FLASHD_Unlock(AT91C_IFLASH, AT91C_IFLASH + 64 * 1024, 0, 0); // 16* 16 * 256 = 64kB, Only the first 64KB can be locked in the SAM7A3 #else error = FLASHD_Unlock(AT91C_IFLASH, AT91C_IFLASH + AT91C_IFLASH_SIZE, 0, 0); #endif //ASSERT(!error, "-F- Error while trying to unlock the whole flash (0x%02X)\n\r", error); if(error !=0 ) { while(1); } //fill data to sectors : 512 ~ 1024. for(j = 1; j<= 512; j++) { LED_Toggle(LED_DS2); // Performs tests on last page (to avoid overriding existing program). lastPageAddress = AT91C_IFLASH + AT91C_IFLASH_SIZE - AT91C_IFLASH_PAGE_SIZE * j; pLastPageData = (volatile unsigned int *) lastPageAddress; // Write page with walking bit pattern (0x00000001, 0x00000002, ...) //printf("-I- Writing last page with walking bit pattern\n\r"); for (i=0; i < (AT91C_IFLASH_PAGE_SIZE / 4); i++) { pBuffer[i] = 0xee;//(i % 32); } error = FLASHD_Write(lastPageAddress, pBuffer, AT91C_IFLASH_PAGE_SIZE); //ASSERT(!error, "-F- Error when trying to write page (0x%02X)\n\r", error); // Check page contents //printf("-I- Checking page contents "); for (i=0; i < (AT91C_IFLASH_PAGE_SIZE / 4); i++) { //printf("."); //ASSERT(pLastPageData[i] == (1 << (i % 32)),\ "\n\r-F- Expected 0x%08X at address 0x%08X, found 0x%08X\n\r",\ (1 << (i % 32)), (unsigned int) &(pLastPageData[i]), pLastPageData[i]); if( pLastPageData[i] != (1 << (i % 32))) { LED_Set(LED_DS2); break; } } } /*****************************************************************************/ LED_Clear(LED_DS2); //while(1); //printf(" ok \n\r"); #if defined(at91sam7a3) // Only the first 64Kb can be locked in the SAM7A3 lastPageAddress = AT91C_IFLASH + (64*1024) - AT91C_IFLASH_PAGE_SIZE; #endif // Lock page //printf("-I- Locking last page\n\r"); //error = FLASHD_Lock(lastPageAddress, lastPageAddress + AT91C_IFLASH_PAGE_SIZE, 0, 0); //ASSERT(!error, "-F- Error when trying to lock page (0x%02X)\n\r", error); // Check that associated region is locked //printf("-I- Checking lock status ... "); //pageLocked = FLASHD_IsLocked(lastPageAddress, lastPageAddress + AT91C_IFLASH_PAGE_SIZE); //ASSERT(pageLocked, "\n\r-F- Page is not locked\n\r"); //printf("ok\n\r"); // Unlock page //printf("-I- Unlocking last page\n\r"); //error = FLASHD_Unlock(lastPageAddress, lastPageAddress + AT91C_IFLASH_PAGE_SIZE, 0, 0); //ASSERT(!error, "-F- Error when trying to unlock page (0x%02X)\n\r", error); // Check that associated region is unlocked //printf("-I- Checking lock status ... "); //pageLocked = FLASHD_IsLocked(lastPageAddress, lastPageAddress + AT91C_IFLASH_PAGE_SIZE); //ASSERT(!pageLocked, "\n\r-F- Page is locked\n\r"); //printf("ok\n\r"); #if (EFC_NUM_GPNVMS > 0) // Test GPNVM bit #1 (should be safe) if (FLASHD_IsGPNVMSet(1)) { //printf("-I- GPNVM #1 is set\n\r"); // Clear GPNVM //printf("-I- Clearing GPNVM #%d\n\r", 1); error = FLASHD_ClearGPNVM(1); //ASSERT(!error, "-F- Error while trying to clear GPNVM (0x%02X)\n\r", error); //ASSERT(!FLASHD_IsGPNVMSet(1), "-F- GPNVM is set\n\r"); // Set GPNVM //printf("-I- Setting GPNVM #%d\n\r", 1); error = FLASHD_SetGPNVM(1); //ASSERT(!error, "-F- Error while trying to set GPNVM (0x%02X)\n\r", error); //ASSERT(FLASHD_IsGPNVMSet(1), "-F- GPNVM is not set\n\r"); } else { //printf("-I- GPNVM #1 is cleared\n\r"); // Set GPNVM //printf("-I- Setting GPNVM #%d\n\r", 1); error = FLASHD_SetGPNVM(1); //ASSERT(!error, "-F- Error while trying to set GPNVM (0x%02X)\n\r", error); //ASSERT(FLASHD_IsGPNVMSet(1), "-F- GPNVM is not set\n\r"); // Clear GPNVM //printf("-I- Clearing GPNVM #%d\n\r", 1); error = FLASHD_ClearGPNVM(1); //ASSERT(!error, "-F- Error while trying to clear GPNVM (0x%02X)\n\r", error); //ASSERT(!FLASHD_IsGPNVMSet(1), "-F- GPNVM is set\n\r"); } #endif //printf("-I- All tests ok\n\r"); return 0; }
/** * \brief Applet main entry. This function decodes received command and executes it. * * \param argc always 1 * \param argv Address of the argument area.. */ int main(int argc, char **argv) { struct _Mailbox *pMailbox = (struct _Mailbox *) argv; uint32_t bytesToWrite, bufferAddr, memoryOffset; uint32_t l_start, l_end; uint32_t *pActualStart = NULL; uint32_t *pActualEnd = NULL; uint8_t error; uint32_t writeSize; /* Disable watchdog */ WDT_Disable( WDT ) ; /*---------------------------------------------------------- * INIT: *----------------------------------------------------------*/ if (pMailbox->command == APPLET_CMD_INIT) { /* Re-configurate UART (MCK maybe change in LowLevelInit()) */ UART_Configure(115200, BOARD_MCK); /* Set 6 WS for internal Flash writing (refer to errata) */ EFC_SetWaitState(EFC, 6); /* Save communication link type */ comType = pMailbox->argument.inputInit.comType; #if (DYN_TRACES == 1) dwTraceLevel = pMailbox->argument.inputInit.traceLevel; #endif flashBaseAddr = IFLASH_ADDR; flashBaseAddrInit = IFLASH_ADDR; flashSize = IFLASH_SIZE; flashPageSize = IFLASH_PAGE_SIZE; flashNbLockBits = IFLASH_NB_OF_LOCK_BITS; flashLockRegionSize = IFLASH_LOCK_REGION_SIZE; TRACE_INFO("-- Internal Flash SAM-BA Applet %s --\n\r", SAM_BA_APPLETS_VERSION); TRACE_INFO("-- %s\n\r", BOARD_NAME); TRACE_INFO("-- Compiled: %s %s --\n\r", __DATE__, __TIME__); /* Initialize flash driver */ FLASHD_Initialize(BOARD_MCK, 1); /* flash accesses must be 4 bytes aligned */ pMailbox->argument.outputInit.bufferAddress = ((uint32_t) &end); bufferSize = IRAM_SIZE /* sram size */ - ( ((uint32_t) &end) - IRAM_ADDR ) /* program size (romcode, code+data) */ - STACK_SIZE; /* stack size at the end */ /* integer number of pages can be contained in each buffer */ /* operation is : buffersize -= bufferSize % flashPageSize */ /* modulo can be done with a mask since flashpagesize is a power of two integer */ #ifdef sam3s16 bufferSize = bufferSize > SECTOR_SIZE ? SECTOR_SIZE: bufferSize; #else bufferSize -= (bufferSize & (flashPageSize - 1)); #endif pMailbox->argument.outputInit.bufferSize = bufferSize; pMailbox->argument.outputInit.memorySize = flashSize; pMailbox->argument.outputInit.memoryInfo.lockRegionSize = flashLockRegionSize; pMailbox->argument.outputInit.memoryInfo.numbersLockBits = flashNbLockBits; TRACE_INFO("bufferSize : %d bufferAddr: 0x%x \n\r", (int)pMailbox->argument.outputInit.bufferSize, (unsigned int) &end ); TRACE_INFO("memorySize : %d lockRegionSize : 0x%x numbersLockBits : 0x%x \n\r", (int)pMailbox->argument.outputInit.memorySize, (unsigned int)pMailbox->argument.outputInit.memoryInfo.lockRegionSize, (unsigned int)pMailbox->argument.outputInit.memoryInfo.numbersLockBits); pMailbox->status = APPLET_SUCCESS; #ifdef sam3sd8 TRACE_INFO("GPNVM bit 0: %d\n\r", (unsigned int)FLASHD_IsGPNVMSet(0)); TRACE_INFO("GPNVM bit 1: %d\n\r", (unsigned int)FLASHD_IsGPNVMSet(1)); TRACE_INFO("GPNVM bit 2: %d\n\r", (unsigned int)FLASHD_IsGPNVMSet(2)); #endif } /*---------------------------------------------------------- * WRITE: *----------------------------------------------------------*/ else if (pMailbox->command == APPLET_CMD_WRITE) { memoryOffset = pMailbox->argument.inputWrite.memoryOffset; bufferAddr = pMailbox->argument.inputWrite.bufferAddr; bytesToWrite = pMailbox->argument.inputWrite.bufferSize; TRACE_INFO("WRITE at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes (flash base addr : 0x%x)\n\r", (unsigned int)memoryOffset, (unsigned int)bufferAddr, (unsigned int)bytesToWrite, (unsigned int)flashBaseAddr); /* Check the giving sector have been locked before. */ if (FLASHD_IsLocked(flashBaseAddr + memoryOffset, flashBaseAddr + memoryOffset + bytesToWrite) != 0) { TRACE_INFO("Error page locked\n\r"); pMailbox->argument.outputWrite.bytesWritten = 0; pMailbox->status = APPLET_PROTECT_FAIL; goto exit; } #ifdef sam3s16 if (memoryOffset % SECTOR_SIZE) { writeSize = SECTOR_SIZE - memoryOffset % SECTOR_SIZE; writeSize = writeSize > bufferSize ? bufferSize : writeSize; } else { writeSize = bytesToWrite; } TRACE_INFO("Write <%x> bytes from <#%x> \n\r", (unsigned int )writeSize, (unsigned int )memoryOffset ); l_start = memoryOffset / SECTOR_SIZE; if ((memoryOffset % SECTOR_SIZE == 0) || ((memoryOffset % SECTOR_SIZE != 0) && ( memoryOffset != (lastWrittenAddr + 1)))) { TRACE_INFO("Erase sector <#%d> \n\r", (unsigned int )l_start ); TRACE_INFO("Unlock from <#%x> to <#%x> for sector erasing \n\r", (unsigned int )(l_start * SECTOR_SIZE), (unsigned int)((l_start + 1) * SECTOR_SIZE -1)); FLASHD_Unlock(flashBaseAddr + l_start * SECTOR_SIZE, flashBaseAddr + (l_start + 1) * SECTOR_SIZE -1 , pActualStart, pActualEnd); if (memoryOffset < SECTOR_SIZE) { FLASHD_EraseSector(IFLASH_ADDR); /* Small sector 0: 8K */ FLASHD_EraseSector(IFLASH_ADDR + 1024 * 8); /* Small sector 1: 8K */ FLASHD_EraseSector(IFLASH_ADDR + 1024 * 16); /* Large sector : 48K */ } else { /* Common erase Other sectors */ FLASHD_EraseSector(flashBaseAddr + memoryOffset); } } #else writeSize = bytesToWrite; #endif /* Write data */ if (FLASHD_Write(flashBaseAddr + memoryOffset, (const void *)bufferAddr, writeSize) != 0) { TRACE_INFO("Error write operation\n\r"); pMailbox->argument.outputWrite.bytesWritten = writeSize ; pMailbox->status = APPLET_WRITE_FAIL; goto exit; } #ifdef sam3s16 lastWrittenAddr = memoryOffset + writeSize - 1; #endif TRACE_INFO("Write achieved\n\r"); pMailbox->argument.outputWrite.bytesWritten = writeSize; pMailbox->status = APPLET_SUCCESS; } /*---------------------------------------------------------- * READ: *----------------------------------------------------------*/ else if (pMailbox->command == APPLET_CMD_READ) { memoryOffset = pMailbox->argument.inputRead.memoryOffset; bufferAddr = pMailbox->argument.inputRead.bufferAddr; bufferSize = pMailbox->argument.inputRead.bufferSize; TRACE_INFO("READ at offset: 0x%x buffer at : 0x%x of: 0x%x Bytes (flash base addr : 0x%x)\n\r", (unsigned int)memoryOffset, (unsigned int)bufferAddr, (unsigned int)bufferSize, (unsigned int)flashBaseAddr); /* read data */ memcpy((void *)bufferAddr, (void *)(flashBaseAddr + memoryOffset), bufferSize); TRACE_INFO("Read achieved\n\r"); pMailbox->argument.outputRead.bytesRead = bufferSize; pMailbox->status = APPLET_SUCCESS; } /*---------------------------------------------------------- * FULL ERASE: *----------------------------------------------------------*/ else if (pMailbox->command == APPLET_CMD_FULL_ERASE) { TRACE_INFO("FULL ERASE command \n\r"); /* Check if at least one page has been locked */ if (FLASHD_IsLocked(flashBaseAddr, flashBaseAddr + flashSize) != 0) { TRACE_INFO("Error page locked \n\r"); pMailbox->status = APPLET_PROTECT_FAIL; goto exit; } /* Implement the erase all command */ /* Erase the flash */ if (FLASHD_Erase(flashBaseAddr) != 0) { TRACE_INFO("Flash erase failed! \n\r"); pMailbox->status = APPLET_ERASE_FAIL; goto exit; } lastWrittenAddr = 0; TRACE_INFO("Full erase achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } /*---------------------------------------------------------- * LOCK SECTOR: *----------------------------------------------------------*/ else if (pMailbox->command == APPLET_CMD_LOCK) { TRACE_INFO("LOCK command \n\r"); l_start = (pMailbox->argument.inputLock.sector * flashLockRegionSize) + flashBaseAddr; l_end = l_start + flashLockRegionSize; if( FLASHD_Lock(l_start, l_end, pActualStart, pActualEnd) != 0) { TRACE_INFO("Lock failed! \n\r"); pMailbox->status = APPLET_PROTECT_FAIL; goto exit; } TRACE_INFO("Lock sector achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } /*---------------------------------------------------------- * UNLOCK SECTOR: *----------------------------------------------------------*/ else if (pMailbox->command == APPLET_CMD_UNLOCK) { TRACE_INFO("UNLOCK command \n\r"); l_start = (pMailbox->argument.inputLock.sector * flashLockRegionSize) + flashBaseAddr; l_end = l_start + flashLockRegionSize; if( FLASHD_Unlock(l_start, l_end, pActualStart, pActualEnd) != 0) { TRACE_INFO("Unlock failed! \n\r"); pMailbox->status = APPLET_UNPROTECT_FAIL; goto exit; } TRACE_INFO("Unlock sector achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } /*---------------------------------------------------------- * GPNVM : *----------------------------------------------------------*/ else if (pMailbox->command == APPLET_CMD_GPNVM) { if( pMailbox->argument.inputGPNVM.action == 0) { TRACE_INFO("DEACTIVATES GPNVM command \n\r"); error = FLASHD_ClearGPNVM(pMailbox->argument.inputGPNVM.bitsOfNVM); } else { TRACE_INFO("ACTIVATES GPNVM command \n\r"); error = FLASHD_SetGPNVM(pMailbox->argument.inputGPNVM.bitsOfNVM); } if(error != 0) { TRACE_INFO("GPNVM failed! \n\r"); pMailbox->status = APPLET_FAIL; goto exit; } TRACE_INFO("GPNVM achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } /*---------------------------------------------------------- * READ UNIQUE ID : *----------------------------------------------------------*/ else if (pMailbox->command == APPLET_CMD_READ_UNIQUE_ID) { TRACE_INFO("READ UNIQUE ID command \n\r"); if (FLASHD_ReadUniqueID ((uint32_t *)(pMailbox->argument.inputReadUniqueID.bufferAddr)) != 0) { TRACE_INFO("Read Unique ID failed! \n\r"); pMailbox->status = APPLET_FAIL; goto exit; } TRACE_INFO("Read Unique ID achieved\n\r"); pMailbox->status = APPLET_SUCCESS; } exit: /* Acknowledge the end of command */ TRACE_INFO("\tEnd of Applet %x %x.\n\r", (unsigned int)pMailbox->command, (unsigned int)pMailbox->status); /* Notify the host application of the end of the command processing */ pMailbox->command = ~(pMailbox->command); if (comType == DBGU_COM_TYPE) { UART_PutChar(0x6); } return 0; }