BOOL __section(SectionForFlashOperations) AM29DL_32_BS_Driver::Read(void* context, ByteAddress address, UINT32 numBytes, BYTE * pSectorBuff) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); CHIP_WORD* ChipAddress, *EndAddress; #if _DEBUG UINT32 iRegion, iRange; MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; const BlockDeviceInfo * deviceInfo = config->BlockConfig.BlockDeviceInformation; if(!deviceInfo->FindRegionFromAddress(address, iRegion, iRange)) return FALSE; #endif address = CPU_GetUncachableAddress(address); ChipAddress = (CHIP_WORD *) address; EndAddress = (CHIP_WORD *)(address + numBytes); CHIP_WORD *pBuf = (CHIP_WORD *)pSectorBuff; while(ChipAddress < EndAddress) { *pBuf++ = *ChipAddress++; } return TRUE; }
BOOL __section("SectionForFlashOperations")I28F_16_BS_Driver::WriteX(void* context, ByteAddress StartSector, UINT32 NumBytes, BYTE * pSectorBuff, BOOL ReadModifyWrite, BOOL fIncrementDataPtr) { NATIVE_PROFILE_PAL_FLASH(); volatile CHIP_WORD * ChipAddress; BOOL result= TRUE; CHIP_WORD * pData = (CHIP_WORD*)pSectorBuff; MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; // if write protected, no update const BlockDeviceInfo * deviceInfo = config->BlockConfig.BlockDeviceInformation; if (deviceInfo->Attribute.WriteProtected) return FALSE; ChipAddress = (volatile CHIP_WORD *)CPU_GetUncachableAddress(StartSector); ChipReadOnly( config, FALSE, FLASH_PROTECTION_KEY ); for(UINT32 i = 0; i < NumBytes; i += sizeof(CHIP_WORD), ChipAddress++) { // if same, nothing to do, continue nextword. if(*ChipAddress != *pData) { // check for having to move bits from 0->1, a failure case for a write if(0 != (*pData & ~(*ChipAddress))) { debug_printf( "erase failure: 0x%08x=0x%04x\r\n", (size_t)ChipAddress, *ChipAddress ); ASSERT(0); result =FALSE; break; } CHIP_WORD StatusRegister = Action_WriteWord( ChipAddress, *pData, config ); if(0 != (StatusRegister & ~SR_WSM_READY)) { debug_printf( "Flash_WriteWord(0x%08x): Status Register non-zero after word program: 0x%08x\r\n", (UINT32)ChipAddress, StatusRegister ); result= FALSE; break; } if (*ChipAddress != *pData) { debug_printf( "Flash_WriteToSector failure @ 0x%08x, wrote 0x%08x, read 0x%08x\r\n", (UINT32)ChipAddress, *pData, *ChipAddress ); result = FALSE; break; } } if(fIncrementDataPtr) pData++; } ChipReadOnly(config, TRUE, FLASH_PROTECTION_KEY); return result; }
BOOL __section(SectionForFlashOperations) AM29DL_16_BS_Driver::WriteX(void* context, ByteAddress address, UINT32 numBytes, BYTE * pSectorBuff, BOOL ReadModifyWrite, BOOL fIncrementDataPtr) { NATIVE_PROFILE_PAL_FLASH(); MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; const BlockDeviceInfo * deviceInfo = config->BlockConfig.BlockDeviceInformation; CHIP_WORD* ChipAddress; CHIP_WORD* EndAddress, *pData; BOOL result = TRUE; if (deviceInfo->Attribute.WriteProtected) return FALSE; address = CPU_GetUncachableAddress(address); ChipAddress = (CHIP_WORD *)address; EndAddress = (CHIP_WORD *)(address + numBytes); pData = (CHIP_WORD *)pSectorBuff; ChipReadOnly(config, FALSE, FLASH_PROTECTION_KEY); while(ChipAddress < EndAddress) { // if same, nothing to do, continue nextword. if(*ChipAddress != *pData) { // check for having to move bits from 0->1, a failure case for a write if(0 != (*pData & ~(*ChipAddress))) { debug_printf( "Write X erase failure: 0x%08x=0x%04x\r\n", (size_t)ChipAddress, *ChipAddress ); ASSERT(0); result =FALSE; break; } Action_WriteWord( config, ChipAddress, *pData ); if (*ChipAddress != *pData) { debug_printf( "Flash_WriteToSector failure @ 0x%08x, wrote 0x%08x, read 0x%08x\r\n", (UINT32)ChipAddress, *pData, *ChipAddress ); result = FALSE; break; } } ChipAddress++; if(fIncrementDataPtr) pData++; } ChipReadOnly(config, TRUE, FLASH_PROTECTION_KEY); return result; }
BOOL __section(SectionForFlashOperations) SAM7X_BS_Driver::Read( void* context, ByteAddress Address, UINT32 NumBytes, BYTE * pSectorBuff ) { Address = CPU_GetUncachableAddress(Address); CHIP_WORD* chipAddress = (CHIP_WORD *)Address; CHIP_WORD* endAddress = (CHIP_WORD *)(Address + NumBytes); CHIP_WORD *pBuf = (CHIP_WORD *)pSectorBuff; while(chipAddress < endAddress) { *pBuf++ = *chipAddress++; } return TRUE; }
// erase one page BOOL __section(SectionForFlashOperations) SAM7X_BS_Driver::EraseBlock( void* context, ByteAddress address ) { MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; const BlockDeviceInfo * deviceInfo = config->BlockConfig.BlockDeviceInformation; UINT32 iRegion, iRange; UINT32 pageNumber=0, baseAddress; // 1st or 2nd FLASH controller if (!deviceInfo->FindRegionFromAddress( address, iRegion, iRange )) return FALSE; address = CPU_GetUncachableAddress(address); baseAddress = CPU_GetCachableAddress(deviceInfo->Regions[iRegion].Start); // the pageNumber is the start of page of "Sector", even Sector is not the start sectoraddres of the block pageNumber = ((address - baseAddress) / AT91C_IFLASH_PAGE_SIZE); AT91_BL_EFC &efc = AT91_BL_EFC::BL_EFC(( pageNumber < 1024 ) ? 0:1); ChipReadOnly( context, FALSE, FLASH_PROTECTION_KEY ); // Set EFC Mode Register - number of cycles during 1.5 microsecond efc.EFC_FMR = (efc.EFC_FMR & ~(AT91_BL_EFC::MC_FMCN | AT91_BL_EFC::MC_NEBP)) | (((SYSTEM_CYCLE_CLOCK_HZ / 2000000) * 3) << 16); pageNumber = pageNumber % 1024; { GLOBAL_LOCK(irq); // Erase Block (write 0xFFFFFFFF) // perform write/erase command for (UINT32 i=0; i<AT91C_IFLASH_PAGE_PER_BLOCK; i++) { efc.EFC_FCR = (AT91_BL_EFC::MC_KEY_VALUE | (pageNumber << 8) | AT91_BL_EFC::MC_FCMD_START_PROG); // wait for FLASH ready while( (efc.EFC_FSR & AT91_BL_EFC::MC_FRDY) != AT91_BL_EFC::MC_FRDY ); pageNumber ++; } } ChipReadOnly( context, TRUE, FLASH_PROTECTION_KEY ); return TRUE; }
void __section("SectionForFlashOperations") I28F_16_BS_Driver::Action_ClearStatusRegister( volatile CHIP_WORD* SectorCheck ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); /////////////////////////////////// // // FLASH_BEGIN_PROGRAMMING_FAST(); SectorCheck = CPU_GetUncachableAddress( SectorCheck ); // clear the status register for this block, just in case it has some residual error present *SectorCheck = CLEAR_STATUS_REGISTER; *SectorCheck = ENTER_READ_ARRAY_MODE; FLASH_END_PROGRAMMING_FAST( "I28F_16 ClearStatus", NULL ); // // /////////////////////////////////// }
void __section("SectionForFlashOperations") I28F_16_BS_Driver::Action_Unlock( volatile CHIP_WORD* SectorCheck ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); /////////////////////////////////// // // FLASH_BEGIN_PROGRAMMING_FAST(); SectorCheck = CPU_GetUncachableAddress( SectorCheck ); *SectorCheck = LOCK_SETUP; *SectorCheck = LOCK_UNLOCK_BLOCK; *SectorCheck = ENTER_READ_ARRAY_MODE; FLASH_END_PROGRAMMING_FAST( "I28F_16 Unlock", NULL ); // // /////////////////////////////////// }
BOOL __section(SectionForFlashOperations) AM29DL_32_BS_Driver::IsBlockErased( void* context, ByteAddress address, UINT32 blockLength ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); address = CPU_GetUncachableAddress(address); volatile CHIP_WORD * ChipAddress = (volatile CHIP_WORD *) address; CHIP_WORD * EndAddress = (CHIP_WORD*)(address + blockLength); while(ChipAddress < EndAddress) { if( (*ChipAddress ) != 0xFFFFFFFF) { return FALSE; } ChipAddress ++; } return TRUE; }
BOOL SH7216_INTERNAL_FLASH_Driver::IsBlockErased( void* context, ByteAddress address, UINT32 blockLength ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); address = CPU_GetUncachableAddress(address); volatile CHIP_WORD * ChipAddress = (volatile CHIP_WORD *) address; CHIP_WORD * EndAddress = (CHIP_WORD*)(address + blockLength); while(ChipAddress < EndAddress) { if( (*ChipAddress ) != (CHIP_WORD)0xFFFFFFFF) { return FALSE; } ChipAddress ++; } return TRUE; }
BOOL __section("SectionForFlashOperations")I28F_16_BS_Driver::IsBlockErased( void* context, ByteAddress BlockStart, UINT32 BlockLength ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); BlockStart = CPU_GetUncachableAddress(BlockStart); CHIP_WORD* ChipAddress = (CHIP_WORD *) BlockStart; CHIP_WORD* EndAddress = (CHIP_WORD *)(BlockStart + BlockLength); while(ChipAddress < EndAddress) { if(*ChipAddress != 0xFFFF) { return FALSE; } ChipAddress++; } return TRUE; }
BOOL __section("SectionForFlashOperations")I28F_16_BS_Driver::Read( void* context, ByteAddress StartSector, UINT32 NumBytes, BYTE * pSectorBuff) { // XIP device does not need to read into a buffer NATIVE_PROFILE_HAL_DRIVERS_FLASH(); if (pSectorBuff == NULL) return FALSE; StartSector = CPU_GetUncachableAddress(StartSector); CHIP_WORD* ChipAddress = (CHIP_WORD *)StartSector; CHIP_WORD* EndAddress = (CHIP_WORD *)(StartSector + NumBytes); CHIP_WORD *pBuf = (CHIP_WORD *)pSectorBuff; while(ChipAddress < EndAddress) { *pBuf++ = *ChipAddress++; } return TRUE; }
I28F_16_BS_Driver::CHIP_WORD __section("SectionForFlashOperations") I28F_16_BS_Driver::Action_ReadLockStatus( volatile CHIP_WORD* SectorCheck ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); CHIP_WORD BlockLockStatus; /////////////////////////////////// // // FLASH_BEGIN_PROGRAMMING_FAST(); SectorCheck = CPU_GetUncachableAddress( SectorCheck ); *SectorCheck = READ_ID; BlockLockStatus = SectorCheck[0x0002]; *SectorCheck = ENTER_READ_ARRAY_MODE; // Exit product ID mode FLASH_END_PROGRAMMING_FAST( "I28F_16 ReadLocks", NULL ); // // /////////////////////////////////// return BlockLockStatus; }
void __section("SectionForFlashOperations") I28F_16_BS_Driver::Action_ReadID( volatile CHIP_WORD* SectorCheck, FLASH_WORD& ManufacturerCode, FLASH_WORD& DeviceCode ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); /////////////////////////////////// // // FLASH_BEGIN_PROGRAMMING_FAST(); SectorCheck = CPU_GetUncachableAddress( SectorCheck ); *SectorCheck = READ_ID; ManufacturerCode = SectorCheck[0x0000]; DeviceCode = SectorCheck[0x0001]; // Exit product ID mode *SectorCheck = ENTER_READ_ARRAY_MODE; FLASH_END_PROGRAMMING_FAST( "I28F_16 ReadID", NULL ); // // /////////////////////////////////// }
I28F_16_BS_Driver::CHIP_WORD __section("SectionForFlashOperations") I28F_16_BS_Driver::Action_WriteWord( volatile CHIP_WORD * Sector, CHIP_WORD Data, MEMORY_MAPPED_NOR_BLOCK_CONFIG* FlashConfig ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); CHIP_WORD StatusRegister; /////////////////////////////////// // // FLASH_BEGIN_PROGRAMMING_FAST(); Sector = CPU_GetUncachableAddress( Sector ); // Enter Word Program Mode. *Sector = PROGRAM_WORD; *Sector = Data; // wait for device to signal completion // break when the device signals completion by looking for Data (0xff erasure value) on I/O 7 (a 0 on I/O 7 indicates erasure in progress) while((*Sector & SR_WSM_READY) != SR_WSM_READY); StatusRegister = *Sector; // Exit Status Read Mode. *Sector = CLEAR_STATUS_REGISTER; *Sector = ENTER_READ_ARRAY_MODE; CPU_InvalidateAddress( CPU_GetCachableAddress( Sector ) ); FLASH_END_PROGRAMMING_FAST( "I28F_16 WriteWord", Sector ); // // /////////////////////////////////// return StatusRegister; }
I28F_16_BS_Driver::CHIP_WORD __section("SectionForFlashOperations") I28F_16_BS_Driver::Action_EraseSector( void* context, volatile CHIP_WORD * Sector, MEMORY_MAPPED_NOR_BLOCK_CONFIG* FlashConfig ) { NATIVE_PROFILE_HAL_DRIVERS_FLASH(); CHIP_WORD StatusRegister; /////////////////////////////////// // // FLASH_BEGIN_PROGRAMMING_FAST( ); Sector = (volatile CHIP_WORD*)CPU_GetUncachableAddress( Sector ); // now setup erasing *Sector = BLOCK_ERASE_SETUP; *Sector = BLOCK_ERASE_CONFIRM; // wait for device to signal completion // break when the device signals completion by looking for Data (0xff erasure value) on I/O 7 (a 0 on I/O 7 indicates erasure in progress) while((*Sector & SR_WSM_READY) != SR_WSM_READY); StatusRegister = *Sector; // error conditions must be cleared *Sector = CLEAR_STATUS_REGISTER; *Sector = ENTER_READ_ARRAY_MODE; CPU_FlushCaches(); FLASH_END_PROGRAMMING_FAST( "I28F_16 EraseSector", Sector ); // // /////////////////////////////////// return StatusRegister; }
BOOL __section(SectionForFlashOperations) SAM7X_BS_Driver::WriteX( void* context, ByteAddress address, UINT32 numBytes, BYTE * pSectorBuff, BOOL ReadModifyWrite, BOOL fIncrementDataPtr ) { MEMORY_MAPPED_NOR_BLOCK_CONFIG* config = (MEMORY_MAPPED_NOR_BLOCK_CONFIG*)context; const BlockDeviceInfo * deviceInfo = config->BlockConfig.BlockDeviceInformation; UINT8 pageBuffer[AT91C_IFLASH_PAGE_SIZE]; BYTE* localpData = pSectorBuff; UINT32 baseAddress; UINT32 endAddress; UINT32 pageNumber; UINT32 offset; UINT32 writeSize; UINT32 pageAddress; UINT32 iRegion, iRange; INT32 NumOfBytes = (INT32)numBytes; CHIP_WORD *chipAddress; if (deviceInfo->Attribute.WriteProtected) return FALSE; if (!deviceInfo->FindRegionFromAddress(address, iRegion, iRange)) return FALSE; address = CPU_GetUncachableAddress(address); baseAddress = CPU_GetUncachableAddress(deviceInfo->Regions[iRegion].Start); endAddress = (baseAddress + deviceInfo->Regions[iRegion].Size()); chipAddress = (CHIP_WORD *)address; if(( address < baseAddress) || (address >= endAddress)) return FALSE; pageNumber = ((address - baseAddress) / AT91C_IFLASH_PAGE_SIZE); offset = ((address - baseAddress) % AT91C_IFLASH_PAGE_SIZE); pageAddress = pageNumber * AT91C_IFLASH_PAGE_SIZE + baseAddress; ChipReadOnly( context, FALSE, FLASH_PROTECTION_KEY ); while(NumOfBytes > 0) { writeSize = __min(AT91C_IFLASH_PAGE_SIZE - offset, NumOfBytes); // 1st or 2nd FLASH controller AT91_BL_EFC &efc = AT91_BL_EFC::BL_EFC(( pageNumber < 1024 ) ? 0:1); CHIP_WORD * tmpWrData =(CHIP_WORD*) localpData; for (UINT32 i=0; i <writeSize; i+=sizeof(CHIP_WORD)) { CHIP_WORD Data; Data = *tmpWrData; if(0 != (Data & ~(*chipAddress))) { debug_printf( "Erase failure: 0x%08x=0x%08x, writeTo(0x%08x)\r\n", (size_t)chipAddress, *chipAddress, Data ); ASSERT(0); return FALSE; } chipAddress ++; tmpWrData ++; } // get the whole page first memcpy(pageBuffer, (void *) pageAddress, AT91C_IFLASH_PAGE_SIZE); memcpy(pageBuffer + offset, localpData, writeSize); // --// // Set EFC Mode Register - number of cycles during 1.5 microsecond { GLOBAL_LOCK(irq); efc.EFC_FMR = (efc.EFC_FMR & ~(AT91_BL_EFC::MC_FMCN)) | (((SYSTEM_CYCLE_CLOCK_HZ / 2000000) * 3) << 16); volatile CHIP_WORD *pageAddr = (CHIP_WORD *)pageAddress; CHIP_WORD * pageBuf = (CHIP_WORD*)&pageBuffer[0]; for (UINT32 i=0; i< AT91C_IFLASH_PAGE_SIZE; i+= sizeof(CHIP_WORD)) { *pageAddr++ = *pageBuf++; } //memcpy((void *) pageAddress, pageBuffer, AT91C_IFLASH_PAGE_SIZE); // perform write command efc.EFC_FCR = ( AT91_BL_EFC::MC_KEY_VALUE | ((pageNumber % 1024) << 8) | AT91_BL_EFC::MC_FCMD_START_PROG); // wait for FLASH ready while( (efc.EFC_FSR & AT91_BL_EFC::MC_FRDY) != AT91_BL_EFC::MC_FRDY ); } NumOfBytes -= writeSize; if(fIncrementDataPtr) localpData += writeSize; pageAddress += AT91C_IFLASH_PAGE_SIZE; pageNumber++; offset = 0; } ChipReadOnly( context, TRUE, FLASH_PROTECTION_KEY ); return TRUE; }