// See flash.h for documentation of this function. status_t flash_verify_erase(flash_driver_t * driver, uint32_t start, uint32_t lengthInBytes, flash_margin_value_t margin) { // Check arguments. status_t returnCode = flash_check_range(driver, start, lengthInBytes, FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT); if (returnCode) { return returnCode; } uint32_t blockSize = driver->PFlashTotalSize / driver->PFlashBlockCount; uint32_t nextBlockStartAddress = ALIGN_UP(start, blockSize); if (nextBlockStartAddress == start) { nextBlockStartAddress += blockSize; } uint32_t remainingBytes = lengthInBytes; while (remainingBytes) { uint32_t verifyLength = nextBlockStartAddress - start; if (verifyLength > remainingBytes) { verifyLength = remainingBytes; } uint32_t numberOfPhrases = verifyLength / FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT; // Fill in verify section command parameters. kFCCOBx[0] = start; FTFx_FCCOBx_WR(FTFx, 0, FTFx_VERIFY_SECTION); FTFx_FCCOBx_WR(FTFx, 4, numberOfPhrases >> 8); FTFx_FCCOBx_WR(FTFx, 5, numberOfPhrases & 0xFF); FTFx_FCCOBx_WR(FTFx, 6, margin); // calling flash command sequence function to execute the command returnCode = flash_command_sequence(); if (returnCode) { return returnCode; } remainingBytes -= verifyLength; start += verifyLength; nextBlockStartAddress += blockSize; } return kStatus_Success; }
// See flash.h for documentation of this function. status_t flash_erase(flash_driver_t * driver, uint32_t start, uint32_t lengthInBytes) { // Check the supplied address range. status_t returnCode = flash_check_range(driver, start, lengthInBytes); if (returnCode) { return returnCode; } uint32_t endAddress; // storing end address uint32_t numberOfSectors; // number of sectors calculated by endAddress // calculating Flash end address endAddress = start + lengthInBytes - 1; // re-calculate the endAddress and align it to the start of the next sector // which will be used in the comparison below if (endAddress % FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE) { numberOfSectors = endAddress / FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE + 1; endAddress = numberOfSectors * FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE - 1; } // the start address will increment to the next sector address // until it reaches the endAdddress while (start <= endAddress) { // preparing passing parameter to erase a flash block kFCCOBx[0] = start; HW_FTFx_FCCOBx_WR(0, FTFx_ERASE_SECTOR); // calling flash command sequence function to execute the command returnCode = flash_command_sequence(); // checking the success of command execution if (kStatus_Success != returnCode) { break; } else { // Increment to the next sector start += FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; } } return(returnCode); }
// See flash.h for documentation of this function. status_t flash_program_section(flash_driver_t * driver, uint32_t start, uint32_t * src, uint32_t lengthInBytes) { #if (!FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) { return kStatus_FlashCommandNotSupported; } #else if (src == NULL) { return kStatus_InvalidArgument; } // Check the supplied address range. status_t returnCode = flash_check_range(driver, start, lengthInBytes, FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT); if (returnCode) { return returnCode; } #if FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD // Switch function of FlexRAM if needed bool needSwitchFlexRamMode = false; if (!(FTFx->FCNFG & BM_FTFx_FCNFG_RAMRDY)) { needSwitchFlexRamMode = true; returnCode = flash_set_flexram_function(driver, kFlash_FlexRAM_Available_As_RAM); if (returnCode != kStatus_Success) { return returnCode; } } #endif // FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD while(lengthInBytes > 0) { // Make sure the write operation doesn't span two sectors uint32_t endAddressOfCurrentSector = ALIGN_UP(start, driver->PFlashSectorSize); uint32_t lengthTobeProgrammedOfCurrentSector; if (lengthInBytes + start > endAddressOfCurrentSector) { lengthTobeProgrammedOfCurrentSector = endAddressOfCurrentSector - start; } else { lengthTobeProgrammedOfCurrentSector = lengthInBytes; } uint32_t currentOffset = 0; // Program Current Sector while(lengthTobeProgrammedOfCurrentSector > 0) { // Make sure the program size doesn't exceeds Accelearating RAM size uint32_t programSizeCurrentPass; if(lengthTobeProgrammedOfCurrentSector > kFlash_AccelerateRam_Size) { programSizeCurrentPass = kFlash_AccelerateRam_Size; } else { programSizeCurrentPass = lengthTobeProgrammedOfCurrentSector; } // Copy data to FlexRAM memcpy((void*)FSL_FEATURE_FLASH_FLEX_RAM_START_ADDRESS, (void*)(start + currentOffset), programSizeCurrentPass); // Set start address of the data to be programmed kFCCOBx[0] = start + currentOffset; // Set program size in terms of 128bits kFCCOBx[1] = programSizeCurrentPass / FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT; // Set FTFx Command to PSEC HW_FTFx_FCCOBx_WR(FTFx_BASE, 0, FTFx_PROGRAM_SECTION); // Peform command sequence returnCode = flash_command_sequence(); // calling flash callback function if it is available if (driver->PFlashCallback) { driver->PFlashCallback(); } if (returnCode != kStatus_Success) { break; } lengthTobeProgrammedOfCurrentSector -= programSizeCurrentPass; currentOffset += programSizeCurrentPass; } if (returnCode != kStatus_Success) { break; } start += currentOffset; lengthInBytes -= currentOffset; } #if FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD // Restore function of FlexRAM if needed. if (needSwitchFlexRamMode) { returnCode = flash_set_flexram_function(driver, kFlash_FlexRAM_Available_For_EEPROM); } #endif // FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD return returnCode; #endif // FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD }
// See flash.h for documentation of this function. status_t flash_is_execute_only(flash_driver_t * driver, uint32_t start, uint32_t lengthInBytes, flash_execute_only_access_state_t * access_state) { if (access_state == NULL) { return kStatus_InvalidArgument; } // Check the supplied address range. status_t returnCode = flash_check_range(driver, start, lengthInBytes, FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE); if (returnCode) { return returnCode; } #if !FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL *access_state = kFlashAccess_UnLimited; #else uint32_t executeOnlySegmentCounter = 0; // calculating end address uint32_t endAddress = start + lengthInBytes; // Aligning start address and end address uint32_t alignedStartAddress = ALIGN_DOWN(start, driver->PFlashAccessSegmentSize); uint32_t alignedEndAddress = ALIGN_UP(endAddress, driver->PFlashAccessSegmentSize); uint32_t segmentIndex = 0; uint32_t maxSupportedExecuteOnlySegmentCount = (alignedEndAddress - alignedStartAddress) / driver->PFlashAccessSegmentSize; while (start < endAddress) { segmentIndex = start / driver->PFlashAccessSegmentSize; uint32_t xacc; if ( segmentIndex < 32) { xacc = *(uint32_t*)&FTFx->XACCL3; } else if (segmentIndex < driver->PFlashAccessSegmentCount) { xacc = *(uint32_t*)&FTFx->XACCH3; segmentIndex -= 32; } else { break; } // Determine if this address range is in a execute-only protection flash segment. if ( (~xacc) & (1 << segmentIndex)) { executeOnlySegmentCounter ++; } start += driver->PFlashAccessSegmentSize; } if (executeOnlySegmentCounter < 1) { *access_state = kFlashAccess_UnLimited; } else if(executeOnlySegmentCounter < maxSupportedExecuteOnlySegmentCount) { *access_state = kFlashAccess_Mixed; } else { *access_state = kFlashAccess_ExecuteOnly; } #endif // FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL return(returnCode); }
// See flash.h for documentation of this function. status_t flash_verify_program(flash_driver_t * driver, uint32_t start, uint32_t lengthInBytes, const uint8_t * expectedData, flash_margin_value_t margin, uint32_t * failedAddress, uint8_t * failedData) { if (expectedData == NULL) { return kStatus_InvalidArgument; } status_t returnCode = flash_check_range(driver, start, lengthInBytes, FSL_FEATURE_FLASH_PFLASH_CHECK_CMD_ADDRESS_ALIGMENT); if (returnCode) { return returnCode; } while (lengthInBytes) { // preparing passing parameter to program check the flash block kFCCOBx[0] = start; FTFx_WR_FCCOBx(FTFx, 0, FTFx_PROGRAM_CHECK); FTFx_WR_FCCOBx(FTFx, 4, margin); kFCCOBx[2] = *(uint32_t *)expectedData; // calling flash command sequence function to execute the command returnCode = flash_command_sequence(); // checking for the success of command execution if (kStatus_Success != returnCode) { if (failedAddress) { *failedAddress = start; } if (failedData) { *(uint32_t *)failedData = 0; } // Read fail returned data: if K70, Nevis2, L1PT, L2K are selected //! @todo Use a feature macro to determine whether this is supported. // #if ((FTFx_KX_512K_512K_16K_4K_4K == FLASH_DERIVATIVE) || (FTFx_KX_1024K_0K_16K_4K_0K == FLASH_DERIVATIVE)\ // ||(FTFx_NX_256K_32K_2K_2K_1K == FLASH_DERIVATIVE)||(FTFx_NX_128K_32K_2K_2K_1K == FLASH_DERIVATIVE)\ // ||(FTFx_NX_96K_32K_2K_2K_1K == FLASH_DERIVATIVE)||(FTFx_NX_64K_32K_2K_2K_1K == FLASH_DERIVATIVE)\ // ||(FTFx_LX_128K_0K_0K_1K_0K == FLASH_DERIVATIVE)||(FTFx_LX_96K_0K_0K_1K_0K == FLASH_DERIVATIVE)\ // ||(FTFx_LX_64K_0K_0K_1K_0K == FLASH_DERIVATIVE)||(FTFx_LX_32K_0K_0K_1K_0K == FLASH_DERIVATIVE)\ // ||(FTFx_LX_8K_0K_0K_1K_0K == FLASH_DERIVATIVE)) // *failedData = 0x0; // *(failedData+1) = 0x0; // *(failedData+2) = 0x0; // *(failedData+3) = 0x0; // #else //other derivative // #if (ENDIANNESS == BIG_ENDIAN) // Big Endian // *(failedData) = FTFA->FCCOB4; // *(failedData+1) = FTFA->FCCOB5; // *(failedData+2) = FTFA->FCCOB6; // *(failedData+3) = FTFA->FCCOB7; // #else // Little Endian // *(failedData+3) = FTFA->FCCOB4; // *(failedData+2) = FTFA->FCCOB5; // *(failedData+1) = FTFA->FCCOB6; // *(failedData) = FTFA->FCCOB7; // #endif //of ENDIANNESS // #endif // of FLASH_DERIVATIVE break; } lengthInBytes -= FSL_FEATURE_FLASH_PFLASH_CHECK_CMD_ADDRESS_ALIGMENT; expectedData += FSL_FEATURE_FLASH_PFLASH_CHECK_CMD_ADDRESS_ALIGMENT; start += FSL_FEATURE_FLASH_PFLASH_CHECK_CMD_ADDRESS_ALIGMENT; } return(returnCode); }