diff --git a/Flash/FlashReadWrite_AssemblyAPI/Driver/__driver_Flash_API.h b/Flash/FlashReadWrite_AssemblyAPI/Driver/__driver_Flash_API.h index 4f4aac677867a5cb23bc57ac98a52ac531f96f59..d0a6d58f57ab7ca0104a789f2cfe8c75eb49025c 100644 --- a/Flash/FlashReadWrite_AssemblyAPI/Driver/__driver_Flash_API.h +++ b/Flash/FlashReadWrite_AssemblyAPI/Driver/__driver_Flash_API.h @@ -67,11 +67,11 @@ unsigned int __FLASH_Read__(unsigned int address,unsigned int length,unsigned i //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ unsigned int __FLASH_UNLOCK_FUNCTION__(volatile unsigned int key,volatile unsigned int isopen); -unsigned int __FLASH_Erase__(volatile unsigned key,volatile unsigned int WritrAddr, +unsigned int __FLASH_Erase__(volatile unsigned key,volatile unsigned int WriteAddr, volatile unsigned int DataLength); -unsigned int __FLASH_Program__(volatile unsigned int key,volatile unsigned int WritrAddr, +unsigned int __FLASH_Program__(volatile unsigned int key,volatile unsigned int WriteAddr, volatile unsigned int DataLength,unsigned int WriteData[]); -unsigned int __FLASH_Program_NBytes__(volatile unsigned int key,volatile unsigned int WritrAddr, +unsigned int __FLASH_Program_NBytes__(volatile unsigned int key,volatile unsigned int WriteAddr, volatile unsigned int DataLength,unsigned int WriteData[]); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/FlashEEPROMEmulation/.cproject b/FlashEEPROMEmulation/.cproject new file mode 100644 index 0000000000000000000000000000000000000000..cb5b0cfff2336f82c8ad75a20cac2784f03a763f --- /dev/null +++ b/FlashEEPROMEmulation/.cproject @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FlashEEPROMEmulation/.project b/FlashEEPROMEmulation/.project new file mode 100644 index 0000000000000000000000000000000000000000..c772c1359019cd1e7e192dfdd821f2d80033615a --- /dev/null +++ b/FlashEEPROMEmulation/.project @@ -0,0 +1,83 @@ + + + FlashEEPROMEmulation + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + -k -j + + + org.eclipse.cdt.make.core.buildCommand + gmake + + + org.eclipse.cdt.make.core.buildLocation + ${workspace_loc:/A156_Project_Templete/Release} + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + com.chipon32.chiponide.core.chiponnature + + diff --git a/FlashEEPROMEmulation/.settings/com.chipon32.chiponide.core.prefs b/FlashEEPROMEmulation/.settings/com.chipon32.chiponide.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..10e05f664be06696112fde9a5538b29a71bb5ddd --- /dev/null +++ b/FlashEEPROMEmulation/.settings/com.chipon32.chiponide.core.prefs @@ -0,0 +1,39 @@ +eclipse.preferences.version=1 +kf32target/ChipPower=3 +kf32target/IspMode=21436587 +kf32target/Protect=5A5AA5A5 +kf32target/chipName=KF32A136KQS +kf32target/compilerType=ccr1_issue +kf32target/debugMode=0 +kf32target/debugRunadd=0 +kf32target/debugSpeed=60 +kf32target/dflashuse=6384 +kf32target/diff0_address=0 +kf32target/diff0_enable=false +kf32target/diff0_length=0 +kf32target/diff0_type=auto +kf32target/diff1_address=0 +kf32target/diff1_enable=false +kf32target/diff1_length=32768 +kf32target/diff1_type=range +kf32target/diff2_address=32768 +kf32target/diff2_enable=false +kf32target/diff2_length=32768 +kf32target/diff2_type=range +kf32target/diff3_address=65536 +kf32target/diff3_enable=false +kf32target/diff3_length=32768 +kf32target/diff3_type=range +kf32target/diff4_address=98304 +kf32target/diff4_enable=false +kf32target/diff4_length=32768 +kf32target/diff4_type=range +kf32target/diff_download_config=false +kf32target/dramuse=460 +kf32target/maintimeout=5 +kf32target/parsefilesizeandstack=0 +kf32target/rflashuse=10336 +kf32target/rramuse=6108 +kf32target/stepintimeout=5 +kf32target/stepouttimeout=5 +kf32target/steppasstimeout=5 diff --git a/FlashEEPROMEmulation/Driver/EmulatedEE.c b/FlashEEPROMEmulation/Driver/EmulatedEE.c new file mode 100644 index 0000000000000000000000000000000000000000..e8b26bee626e35570a1786f2a787b3d61e5fd09c --- /dev/null +++ b/FlashEEPROMEmulation/Driver/EmulatedEE.c @@ -0,0 +1,724 @@ +/****************************************************************************** + * Shanghai ChipON Micro-Electronic Co.,Ltd + ****************************************************************************** + * @File Name : EmulatedEE.c + * @Author : ChipON AE/FAE Group + * @Date : 2024-03-15 + * @Version : V0.2.0 + * @Description : + ***************************************************************************** + * Copyright (C) by Shanghai ChipON Micro-Electronic Co.,Ltd + * All rights reserved. + * + * This software is copyright protected and proprietary to + * Shanghai ChipON Micro-Electronic Co.,Ltd. + ******************************************************************************/ + +/****************************************************************************** + * QAC Warnings + ******************************************************************************/ +/** + * @page QAC Warnings + * + */ +/* PRQA S 0310 EOF #Casting to different object pointer type. */ +/* PRQA S 0306 EOF #Cast between a pointer to object and an integral type. */ +/****************************************************************************** + * Include Files + ******************************************************************************/ +#include +#include +#include "EmulatedEE.h" +#include "__driver_Flash_API.h" +#if EE_USE_FLS_API +#include "kf32a1x6_hli_fls.h" +#endif + +#define EE_PAGE_NONE ((uint32_t)0x0FFFFU) /*!< no valid page found */ +#define EE_PAGE_ERASED ((uint32_t)0xFFFFFFFFU) /*!< page is in erased state */ +#define EE_PAGE_TRANSFER ((uint32_t)0xCCCCCCCCU) /*!< page is in transfer state */ +#define EE_PAGE_VALID ((uint32_t)0x00000000U) /*!< page is in valid state */ + +void EmulatedEE_UpdatePageStatus(void); +uint32_t EmulatedEE_CheckEEFormat(void); + +static uint32_t CurValidPage = EE_PAGE_NONE; +static uint32_t CurValidPageInv = EE_PAGE_NONE; +static uint32_t CurTansferPage = EE_PAGE_NONE; +static uint32_t CurTansferPageInv = EE_PAGE_NONE; + +/** + * @brief:模拟EE擦除页 + * @param[in] PageAddress + * @retval uint32_t + */ +uint32_t EmulatedEE_ErasePage(uint32_t PageAddress) +{ + uint32_t i = 0U; + uint32_t kvEraseAddress = 0U; + uint32_t kvFlashStatus = CMD_SUCCESS; + + /* PRQA S 2877 ++ #This loop will never be executed more than once. */ + /* erase one or more sectors */ + for (i = 0; i < EE_SECTOR_NUM; i++) + { + /* calculate the erase address */ + kvEraseAddress = PageAddress + (i * EE_SECTOR_SIZE); +#if EE_USE_FLS_API + kvFlashStatus = (uint32_t)HLI_Fls_EraseSector(kvEraseAddress, EE_SECTOR_SIZE); + (kvFlashStatus == HLI_FLS_STATUS_OK) ? (kvFlashStatus = CMD_SUCCESS) : (kvFlashStatus = CMD_ERROR); + +#else + + /* erase sector */ + kvFlashStatus = __FLASH_Erase__(Function_Parameter_Validate, kvEraseAddress, EE_SECTOR_SIZE); +#endif + + if (kvFlashStatus != CMD_SUCCESS) + { + break; + } + else + { + /* Do Nothing */ + } + } + + return kvFlashStatus; + /* PRQA S 2877 -- #This loop will never be executed more than once. */ +} + +static inline uint32_t EmulatedEE_WriteFlashData(uint32_t WriteAddress, uint32_t Len, uint32_t *data) +{ + uint32_t kvFlashStatus = CMD_SUCCESS; + +#if EE_USE_FLS_API + kvFlashStatus = (uint32_t)HLI_Fls_WriteMinimumWriteableBytes(WriteAddress, Len, (uint8_t *)data); + (kvFlashStatus == HLI_FLS_STATUS_OK) ? (kvFlashStatus = CMD_SUCCESS) : (kvFlashStatus = CMD_ERROR); +#else + /* write */ + kvFlashStatus = __FLASH_Program_NBytes__(Function_Parameter_Validate, WriteAddress, Len, data); +#endif + return kvFlashStatus; +} +/** + * @brief: 模拟EE获取有效页 + * @retval uint32_t + */ +uint32_t EmulatedEE_GetValidPage(void) +{ + if ((CurValidPage + CurValidPageInv) == 0xFFFFFFFFU) + { + return CurValidPage; + } + else + { + if (EmulatedEE_CheckEEFormat() == 0U) + { + EmulatedEE_UpdatePageStatus(); + return CurValidPage; + } + else + { + return EE_PAGE_NONE; + } + } +} + +/** + * @brief: 模拟EE获取可写Page + * @retval uint32_t + */ +uint32_t EmulatedEE_GetWriteablePage(void) +{ + if (((CurValidPage + CurValidPageInv) == 0xFFFFFFFFU) && ((CurTansferPage + CurTansferPageInv) == 0xFFFFFFFFU)) + { + if (CurTansferPage != EE_PAGE_NONE) + { + return CurTansferPage; + } + else if (CurValidPage != EE_PAGE_NONE) + { + return CurValidPage; + } + else + { + return EE_PAGE_NONE; + } + } + else + { + if (EmulatedEE_CheckEEFormat() == 0U) + { + EmulatedEE_UpdatePageStatus(); + return CurValidPage; + } + else + { + return EE_PAGE_NONE; + } + } +} + +/** + * @brief: 模拟EE写Flash数据 + * @param[in] Address + * @param[in] Data + * @retval uint32_t + */ +uint32_t EmulatedEE_DirectHwWrite(uint32_t Address, uint32_t Data) +{ + uint32_t kvValidPage = EE_PAGE_NONE; + uint32_t kvFindAddress = 0U; + uint32_t kvEndAddress = 0U; + uint32_t kvFlashStatus = 0U; + + /* get the valid page */ + kvValidPage = EmulatedEE_GetWriteablePage(); + + if (kvValidPage == EE_PAGE_NONE) + { + return 0xFFU; + } + else + { + /* Do Nothing */ + } + + /* find address calculation */ + kvFindAddress = EE_BASE_ADDRESS + (kvValidPage * EE_PAGE_SIZE) + 8U; + + /* end address calculation */ + kvEndAddress = EE_BASE_ADDRESS + (kvValidPage * EE_PAGE_SIZE) + EE_PAGE_SIZE; + + while (kvFindAddress < kvEndAddress) + { + /* find addresses without Data */ + if ((*(uint32_t *)kvFindAddress) == 0xFFFFFFFFU) + { + uint32_t kvTempData[2U] = {0U, 0U}; + kvTempData[0U] = Data; + kvTempData[1U] = Address; + + /* write Data to flash */ + kvFlashStatus = EmulatedEE_WriteFlashData(kvFindAddress, 8U, (uint32_t *)&kvTempData); + + return kvFlashStatus; + } + else + { + kvFindAddress += 8U; + } + } + + return kvFlashStatus; +} + +/** + * @brief: 模拟EE复制有效数据到下一页 + * @param[in] ValidPage + * @retval uint32_t + */ +uint32_t EmulatedEE_CopyDataToNewPage(uint32_t ValidPage) +{ + uint32_t kvData = 0U; + uint32_t kvIdx = 0U; + uint32_t kvFullPageAddress = 0U; + uint32_t kvEmptyPageAddress = 0U; + uint32_t kvFlashStatus = CMD_SUCCESS; + + if (ValidPage != EE_PAGE_NONE) + { + kvEmptyPageAddress = (EE_BASE_ADDRESS + (EE_PAGE_SIZE * ((ValidPage + 1) % EE_PAGE_NUM))); + + kvFullPageAddress = (EE_BASE_ADDRESS + (EE_PAGE_SIZE * ValidPage)); + } + else + { + return 0xFFU; + } + + uint32_t kvTempData[2U] = {0U, 0U}; + kvTempData[0U] = EE_PAGE_TRANSFER; + + /* change the status of the empty page to TRANSFER */ + + if ((kvFlashStatus = EmulatedEE_WriteFlashData(kvEmptyPageAddress, 8U, (uint32_t *)&kvTempData)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + + EmulatedEE_UpdatePageStatus(); + + for (kvIdx = 0U; kvIdx < EE_PARA_MAX_NUMBER; kvIdx++) + { + /* find valid variables */ + if (EmulatedEE_ReadData(kvIdx * 4U, &kvData) == 0U) + { + + /* store variable to new page */ + if ((kvFlashStatus = EmulatedEE_DirectHwWrite(kvIdx * 4U, kvData)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + } + else + { + /* Do Nothing */ + } + } + + /* erase old page */ + if ((kvFlashStatus = EmulatedEE_ErasePage(kvFullPageAddress)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + + kvTempData[0U] = EE_PAGE_VALID; + + /* change the status of the empty page to VALID */ + + if ((kvFlashStatus = EmulatedEE_WriteFlashData(kvEmptyPageAddress, 8U, (uint32_t *)&kvTempData)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + + EmulatedEE_UpdatePageStatus(); + + return kvFlashStatus; +} + +/** + * @brief 模拟EE空间格式化 + * @retval uint32_t + */ +uint32_t EmulatedEE_FormatSpace(void) +{ + uint32_t kvFlashStatus = CMD_SUCCESS; + + for (uint32_t i = 0U; i < EE_PAGE_NUM; i++) + { + uint32_t kvEraseAddress = (EE_BASE_ADDRESS + (EE_PAGE_SIZE * i)); + /* erase page */ + if ((kvFlashStatus = EmulatedEE_ErasePage(kvEraseAddress)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + } + + { + uint32_t kvTempData[2U] = {0U, 0U}; + kvTempData[0U] = EE_PAGE_VALID; + /* mark the status of page 0 as VALID */ + kvFlashStatus = EmulatedEE_WriteFlashData(EE_BASE_ADDRESS, 8U, (uint32_t *)&kvTempData); + } + + return kvFlashStatus; +} + +/** + * @brief: 确认是否为模拟EE格式 + * @retval uint32_t + */ +uint32_t EmulatedEE_CheckEEFormat(void) +{ + uint32_t kvPageStatus = EE_PAGE_ERASED; + uint32_t kvValidPage = EE_PAGE_NONE; + uint32_t kvTransferPage = EE_PAGE_NONE; + + for (uint32_t i = 0U; i < EE_PAGE_NUM; i++) + { + kvPageStatus = (*(uint32_t *)(EE_BASE_ADDRESS + (EE_PAGE_SIZE * i))); + + if ((kvPageStatus != EE_PAGE_ERASED) && (kvPageStatus != EE_PAGE_TRANSFER) && (kvPageStatus != EE_PAGE_VALID)) + { + return 1U; + } + else if (kvPageStatus == EE_PAGE_VALID) + { + if (kvValidPage == EE_PAGE_NONE) + { + kvValidPage = i; + } + else + { + return 1U; + } + } + else if (kvPageStatus == EE_PAGE_TRANSFER) + { + if (kvTransferPage == EE_PAGE_NONE) + { + kvTransferPage = i; + } + else + { + return 1U; + } + } + else + { + /* Do Nothing */ + } + } + + if ((kvValidPage == EE_PAGE_NONE) && (kvTransferPage == EE_PAGE_NONE)) + { + return 1U; + } + else + { + /* Do Nothing */ + } + + /* the format is correct */ + return 0U; +} + +/** + * @brief: 模拟EE确认是否写满 + * @retval uint32_t + */ +uint32_t EmulatedEE_CheckPageDateFull(void) +{ + uint32_t kvValidPage = 0U; + uint32_t kvEndAddress = 0U; + uint32_t kvFlashStatus = CMD_SUCCESS; + + /* get the valid page */ + kvValidPage = EmulatedEE_GetValidPage(); + + if (kvValidPage == EE_PAGE_NONE) + { + return 0xFFU; + } + else + { + /* Do Nothing */ + } + + /* end address calculation */ + kvEndAddress = EE_BASE_ADDRESS + (kvValidPage * EE_PAGE_SIZE) + EE_PAGE_SIZE; + + /* check if the page is full */ + if ((*(uint32_t *)(kvEndAddress - 8U)) != 0xFFFFFFFFU) + { + /* when the page is full, transfer the kvData to erase page */ + if ((kvFlashStatus = EmulatedEE_CopyDataToNewPage(kvValidPage)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + } + else + { + /* Do Nothing */ + } + + /* page full check ok */ + return 0U; +} + +/** + * @brief: 模拟EE初始化状态-只有Transfer页 + * @param[in] TransferPage + * @retval uint32_t + */ +uint32_t EmulatedEE_InitStateOnlyTransfer(uint32_t TransferPage) +{ + uint32_t kvFlashStatus = CMD_SUCCESS; + uint32_t kvTransferPageAddress = (EE_BASE_ADDRESS + (EE_PAGE_SIZE * TransferPage)); + + uint32_t kvTempData[2U] = {0U, 0U}; + kvTempData[0U] = EE_PAGE_VALID; + + kvFlashStatus = EmulatedEE_WriteFlashData(kvTransferPageAddress, 8, (uint32_t *)&kvTempData); + + EmulatedEE_UpdatePageStatus(); + return kvFlashStatus; +} + +/** + * @brief: 模拟EE初始化状态- 同时存在Valid,Transfer页 + * @param[in] ValidPage + * @param[in] TransferPage + * @retval uint32_t + */ +uint32_t EmulatedEE_InitStateValidTransfer(uint32_t ValidPage, uint32_t TransferPage) +{ + uint32_t kvErasePageAddress = EE_BASE_ADDRESS + (EE_PAGE_SIZE * TransferPage); + + uint32_t kvFlashStatus = CMD_SUCCESS; + + /* erase the transfer state page */ + if ((kvFlashStatus = EmulatedEE_ErasePage(kvErasePageAddress)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + + EmulatedEE_UpdatePageStatus(); + + /* retransmit kvData */ + return EmulatedEE_CopyDataToNewPage(ValidPage); +} + +/** + * @brief: 模拟EE初始化ram + * @retval uint32_t + */ +void EmulatedEE_UpdatePageStatus(void) +{ + uint32_t kvPageStatus = EE_PAGE_ERASED; + + for (uint32_t i = 0U; i < EE_PAGE_NUM; i++) + { + kvPageStatus = (*(uint32_t *)(EE_BASE_ADDRESS + (EE_PAGE_SIZE * i))); + if (kvPageStatus == EE_PAGE_VALID) + { + CurValidPage = i; + } + else if (kvPageStatus == EE_PAGE_TRANSFER) + { + CurTansferPage = i; + } + else + { + /* Do Nothing */ + } + } + + CurValidPageInv = ~CurValidPage; + CurTansferPageInv = ~CurTansferPage; +} + +/** + * @brief: 模拟EE初始化 + * @retval uint32_t + */ +uint32_t EmulatedEE_Init(void) +{ + uint32_t kvFlashStatus = CMD_SUCCESS; + uint32_t kvPageStatus = EE_PAGE_ERASED; + uint32_t kvValidPage = EE_PAGE_NONE; + uint32_t kvTransferPage = EE_PAGE_NONE; + + /* format validity check */ + if (EmulatedEE_CheckEEFormat() != 0U) + { + /* if the format is invalid, reformat */ + if ((kvFlashStatus = EmulatedEE_FormatSpace()) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + } + else + { + /* Do Nothing */ + } + + EmulatedEE_UpdatePageStatus(); + + for (uint32_t i = 0U; i < EE_PAGE_NUM; i++) + { + kvPageStatus = (*(uint32_t *)(EE_BASE_ADDRESS + (EE_PAGE_SIZE * i))); + if (kvPageStatus == EE_PAGE_VALID) + { + kvValidPage = i; + } + else if (kvPageStatus == EE_PAGE_TRANSFER) + { + kvTransferPage = i; + } + else + { + uint32_t kvEraseAddress = (EE_BASE_ADDRESS + (EE_PAGE_SIZE * i)); + if ((kvFlashStatus = EmulatedEE_ErasePage(kvEraseAddress)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + } + } + + if ((kvValidPage == EE_PAGE_NONE) && (kvTransferPage != EE_PAGE_NONE)) + { + if ((kvFlashStatus = EmulatedEE_InitStateOnlyTransfer(kvTransferPage)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + } + else if ((kvValidPage != EE_PAGE_NONE) && (kvTransferPage != EE_PAGE_NONE)) + { + if ((kvFlashStatus = EmulatedEE_InitStateValidTransfer(kvValidPage, kvTransferPage)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + } + else + { + /* Do Nothing */ + } + + /* check if the page is full, when the page is full, transfer the kvData to erase page */ + if ((kvFlashStatus = EmulatedEE_CheckPageDateFull()) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + + return kvFlashStatus; +} + +/** + * @brief: 模拟EE写数据 + * @param[in] Address EE的虚拟地址 + * @param[in] Data 4字节数据 + * @retval uint32_t + */ +uint32_t EmulatedEE_WriteData(uint32_t Address, uint32_t Data) +{ + uint32_t kvFlashStatus = CMD_SUCCESS; + + if (((Address & 0x3U) > 0U) || (Address > ((EE_PAGE_SIZE / 2U) - 5U))) + { + return PARAM_ERROR; + } + else + { + /* Do Nothing */ + } + + /* check if the page is full, when the page is full, transfer the kvData to erase page */ + if ((kvFlashStatus = EmulatedEE_CheckPageDateFull()) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + + /* write kvData to flash */ + if ((kvFlashStatus = EmulatedEE_DirectHwWrite(Address, Data)) != CMD_SUCCESS) + { + return kvFlashStatus; + } + else + { + /* Do Nothing */ + } + + return kvFlashStatus; +} + +/** + * @brief 模拟EE读取数据 + * @param[in] Address EE的虚拟地址 + * @param[in] Data 4字节数据 + * @retval uint32_t + */ +uint32_t EmulatedEE_ReadData(uint32_t Address, uint32_t *Data) +{ + uint32_t kvValidPage = EE_PAGE_NONE; + uint32_t kvDataAddress = 0U; + uint32_t kvFindAddress = 0U; + uint32_t kvStartAddress = 0U; + + if (((Address & 0x3U) > 0U) && (Address > ((EE_PAGE_SIZE / 2U) - 5U))) + { + return PARAM_ERROR; + } + else + { + /* Do Nothing */ + } + + /* get the valid page */ + kvValidPage = EmulatedEE_GetValidPage(); + + if (kvValidPage == EE_PAGE_NONE) + { + return EE_PAGE_NONE; + } + else + { + /* Do Nothing */ + } + /* start address calculation */ + kvStartAddress = EE_BASE_ADDRESS + (kvValidPage * EE_PAGE_SIZE) + 8U; + + /* find address calculation */ + kvFindAddress = ((EE_BASE_ADDRESS + (kvValidPage * EE_PAGE_SIZE)) + EE_PAGE_SIZE) - 4U; + + while (kvFindAddress > kvStartAddress) + { + /* read variable address */ + kvDataAddress = (*(uint16_t *)kvFindAddress); + + /* variable address matching */ + if (Address == kvDataAddress) + { + + /* read Data */ + *Data = (*(uint32_t *)(kvFindAddress - 4U)); + + /* kvData successfully read */ + return 0U; + } + else + { + /* Do Nothing */ + } + + /* find address - 8 */ + kvFindAddress -= 8U; + } + + /* failed to read kvData */ + return 1U; +} diff --git a/FlashEEPROMEmulation/Driver/EmulatedEE.h b/FlashEEPROMEmulation/Driver/EmulatedEE.h new file mode 100644 index 0000000000000000000000000000000000000000..77314ac8dfef948678265fba35d747e7bbd94d37 --- /dev/null +++ b/FlashEEPROMEmulation/Driver/EmulatedEE.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Shanghai ChipON Micro-Electronic Co.,Ltd + ****************************************************************************** + * @File Name : EmulatedEE.h + * @Author : ChipON AE/FAE Group + * @Date : 2024-03-15 + * @Version : V0.2.0 + * @Description : + ***************************************************************************** + * Copyright (C) by Shanghai ChipON Micro-Electronic Co.,Ltd + * All rights reserved. + * + * This software is copyright protected and proprietary to + * Shanghai ChipON Micro-Electronic Co.,Ltd. + ******************************************************************************/ + +#ifndef EMULATED_EE_H +#define EMULATED_EE_H + +#include "__Kungfu32_chipmodel_define.h" +#include + +/* Flash sector number */ +/* KF32A136 */ +#if defined(KF32A136KQT) || defined(KF32A136KQS) || defined(KF32A136KNP) +#define EE_FLASH_SECTOR_NUM (256U) +#elif defined(KF32A136IQT) || defined(KF32A136IQS) || defined(KF32A136INP) +#define EE_FLASH_SECTOR_NUM (128U) +#elif defined(KF32A136GNP) || defined(KF32A136GQS) +#define EE_FLASH_SECTOR_NUM (64U) +#else +#error "Please define the chip model" +#endif + +/* User-modifiable parameters */ +#define EE_SECTOR_NUM ((uint32_t)1U) /*!< sector number, support multiple sectors to from 1 page */ +#define EE_PAGE_NUM \ + ((uint32_t)2U) /*!< page number, Increase total read and write lifespan by increasing the number of flash pages */ + +/* Non-user-modifiable parameters */ +#define EE_USE_FLS_API (false) + +#define EE_SECTOR_SIZE ((uint32_t)(1024U)) /*!< sector size */ + +#define EE_PAGE_SIZE ((uint32_t)(EE_SECTOR_NUM * EE_SECTOR_SIZE)) /*!< page size */ + +#define EE_BASE_ADDRESS \ + ((uint32_t)((EE_FLASH_SECTOR_NUM * EE_SECTOR_SIZE) - (EE_PAGE_SIZE * EE_PAGE_NUM))) /*!< eeprom base address */ + +#define EE_PARA_MAX_NUMBER \ + ((uint32_t)((EE_PAGE_SIZE / 8U) - 1U)) /*!< maximum number of variables that can be stored \ + */ + +uint32_t EmulatedEE_ErasePage(uint32_t PageAddress); +uint32_t EmulatedEE_GetValidPage(void); +uint32_t EmulatedEE_GetWriteablePage(void); +uint32_t EmulatedEE_DirectHwWrite(uint32_t Address, uint32_t Data); +uint32_t EmulatedEE_CopyDataToNewPage(uint32_t ValidPage); +uint32_t EmulatedEE_FormatSpace(void); +uint32_t EmulatedEE_CheckPageDateFull(void); +uint32_t EmulatedEE_InitStateOnlyTransfer(uint32_t TransferPage); +uint32_t EmulatedEE_InitStateValidTransfer(uint32_t ValidPage, uint32_t TransferPage); +uint32_t EmulatedEE_ReadData(uint32_t Address, uint32_t *Data); +uint32_t EmulatedEE_WriteData(uint32_t Address, uint32_t Data); +uint32_t EmulatedEE_Init(void); + +#endif diff --git a/FlashEEPROMEmulation/Driver/__driver_Flash_API.S b/FlashEEPROMEmulation/Driver/__driver_Flash_API.S new file mode 100644 index 0000000000000000000000000000000000000000..2745d192e8b5c4dbc04398fad1d8d0a1c742c7d2 --- /dev/null +++ b/FlashEEPROMEmulation/Driver/__driver_Flash_API.S @@ -0,0 +1,898 @@ + +//Lib_Version, "V2.0.2.230925" + .text +//############################################################################### + .EQU FLASH_WORK_CLR, 0x50AF0007 + .EQU FLASH_WORK_CMD, 0x50AF0001 + + .EQU Function_Parameter_Validate, 0x5A5A6688 + .EQU CMD_SUCCESS, 0x00 + .EQU CMD_ERROR, 0xAA + .EQU PARAM_ERROR, 0x0C + .EQU TimeOutCountValue, 50000 +//############################################################################### +.macro __FLASH_Function__ name + .section .text$\name + .align 1 + .export \name + .type \name, @function + .func \name +\name: +.endm + +.macro __RAM_Function__ name + .section .indata$\name + .align 1 + .export \name + .type \name, @function + .func \name +\name: +.endm + +.macro __End_Function__ name + .size \name, .-\name + .endfunc +.endm +//############################################################################### + .SET __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN , 0 + .SET __FLASH_Driver_Use_LOCK_UNLOCK_Function, 0 + +//############################################################################### +.if 0 + .SET __FLASH_API_LIKE_A150, 1 +.else +.if 1 + .SET __FLASH_API_LIKE_A156, 1 +.else + .SET __FLASH_API_LIKE_A158, 1 +.endif +.endif +// .if __FLASH_API_LIKE_A158 +.if 0 + .EQU __FLASH_MAX_SIZE__, (2048*1024-1) +.else + .EQU __FLASH_MAX_SIZE__, (512*1024-1) +.endif + .EQU __FLASH_MIN_SIZE__, (0) //erase from address 0 + + +//############################################################################### + +.ifdef __FLASH_API_LIKE_A150 + .SET FLASH_KEY1, 0x87654321 + .SET FLASH_KEY2, 0x05040302 + .SET FLASH_KEY3, 0x789ABCDE + .SET FLASH_KEY4, 0x16151413 +.else +.ifdef __FLASH_API_LIKE_A156 + .SET FLASH_KEY1, 0x27654330; + .SET FLASH_KEY2, 0x81040304 + .SET FLASH_KEY3, 0x7896dcde + .SET FLASH_KEY4, 0x92151407 +.else +.ifdef __FLASH_API_LIKE_A158 + .SET FLASH_KEY1, 0x27654330; + .SET FLASH_KEY2, 0x81040304 + .SET FLASH_KEY3, 0x7896dcde + .SET FLASH_KEY4, 0x92151407 +.else + .error "Err config" +.endif +.endif +.endif +//############################################################################### + .SET FLASH_ISPCON0 , 0x40200100 + .SET FLASH_ISPCON1 , 0x40200104 + .SET FLASH_ISPCMD , 0x40200108 + .SET FLASH_ISPTRG , 0x4020010C + .SET FLASH_ISPADDR , 0x4020011C + .SET FLASH_STATE , 0x40200120 + .SET FLASH_NVMUNLOCK , 0x40200128 + .SET FLASH_PROUNLOCK , 0x4020012C +############################################################################### + __RAM_Function__ __FLASH_UNLOCK_FUNCTION__ + SUB sp,#32 + //++++++++++++++++++++++++++++++++++++++++++++++ + ST.w [sp+#0],r0 + LD R4,#FLASH_KEY1 + ST.w [sp+#1],R4 + + ST.w [sp+#2],r0 + LD R4,#FLASH_KEY2 + ST.w [sp+#3],R4 + + ST.w [sp+#4],r1 + LD R4,#FLASH_KEY3 + ST.w [sp+#5],R4 + + ST.w [sp+#6],r1 + LD R4,#FLASH_KEY4 + ST.w [sp+#7],R4 + //++++++++++++++++++++++++++++++++++++++++++++++ + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key) + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_UNLOCK + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_UNLOCK + //++++++++++++++++++++++++++++++++++++++++++++++if(isopen == 0xAA55) + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_UNLOCK + MOV R2,#0xAA55 + CMP R0,R2 + JZ Cond_OPEN_IN_UNLOCK + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 + JMP Return_CMD_SUCCESS_IN_UNLOCK +Cond_OPEN_IN_UNLOCK: + //++++++++++++++++++++++++++++++++++++++++++++++ key1 key2 + LD.w r0,[SP + #1] + LD.w r1,[SP + #3] + LD r2,#FLASH_NVMUNLOCK + ST.w [R2],R0 + ST.w [R2],R1 + //++++++++++++++++++++++++++++++++++++++++++++++ + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_UNLOCK + MOV R2,#0xAA55 + CMP R0,R2 + JNZ Return_CMD_SUCCESS_IN_UNLOCK + //++++++++++++++++++++++++++++++++++++++++++++++ key3 key4 + LD.w r0,[SP + #5] + LD.w r1,[SP + #7] + LD r2,#FLASH_PROUNLOCK + ST.w [R2],R0 + ST.w [R2],R1 + //++++++++++++++++++++++++++++++++++++++++++++++ + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_UNLOCK + MOV R2,#0xAA55 + CMP R0,R2 + JNZ Return_CMD_SUCCESS_IN_UNLOCK + //++++++++++++++++++++++++++++++++++++++++++++++ +Return_CMD_SUCCESS_IN_UNLOCK: + MOV R0,#0 + JMP Return_PUSH_POP_IN_UNLOCK +Return_PARAM_ERROR_IN_UNLOCK: + MOV R0,#PARAM_ERROR + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 +//++++++++++++++++++++++++++++++++++++++++++++++ +Return_PUSH_POP_IN_UNLOCK: + ST.w [SP+#0],R0 + ST.w [SP+#1],R0 + ST.w [SP+#2],R0 + ST.w [SP+#3],R0 + ST.w [SP+#4],R0 + ST.w [SP+#5],R0 + ST.w [SP+#6],R0 + ST.w [SP+#7],R0 +//++++++++++++++++++++++++++++++++++++++++++++++ + ADD sp,#32 + JMP lr + __End_Function__ __FLASH_UNLOCK_FUNCTION__ + +//######################################################################################### + __RAM_Function__ __FLASH_Read_Byte__ + LD.b r0,[r0] + JMP lr + __End_Function__ __FLASH_Read_Byte__ +//######################################################################################### + __RAM_Function__ __FLASH_Read_WORD__ + LD.w r0,[r0] + JMP lr + __End_Function__ __FLASH_Read_WORD__ +//######################################################################################### + __RAM_Function__ __FLASH_Read_One__ + LD.w r0,[r0] + JMP lr + __End_Function__ __FLASH_Read_One__ +######################################################################################### + __RAM_Function__ __FLASH_Erase__ + SUB sp,#40 + //++++++++++++++++++++++++++++++++++++++++++++++ + ST.w [sp+#0],r0 + LD R4,#FLASH_KEY1 + ST.w [sp+#1],R4 + + ST.w [sp+#2],r0 + LD R4,#FLASH_KEY2 + ST.w [sp+#3],R4 + + ST.w [sp+#4],r1 + LD R4,#FLASH_KEY3 + ST.w [sp+#5],R4 + + ST.w [sp+#6],r1 + LD R4,#FLASH_KEY4 + ST.w [sp+#7],R4 + + ST.w [sp+#8],r2 + ST.w [sp+#9],r2 + //++++++++++++++++++++++++++++++++++++++++++++++ + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key) + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_ERASE + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ key1 key2 + LD.w r0,[SP + #1] + LD.w r1,[SP + #3] + LD r2,#FLASH_NVMUNLOCK + ST.w [R2],R0 + ST.w [R2],R1 + //++++++++++++++++++++++++++++++++++++++++++++++ address check + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_ERASE + LD R4,#__FLASH_MAX_SIZE__ + CMP R0,R4 + JHI Return_PARAM_ERROR_IN_ERASE + MOVL R4,#0x3FF + ANL R1,R4 + JNZ Return_PARAM_ERROR_IN_ERASE + LD R4,#__FLASH_MIN_SIZE__ + CMP R4,R0 + JHI Return_PARAM_ERROR_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ len check + LD.w r0,[SP + #8] + LD.w r1,[SP + #9] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_ERASE + LD R4,#0 + CMP R0,R4 + JZ Return_PARAM_ERROR_IN_ERASE + + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key){ + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_ERASE + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ key3 key4 + LD.w r0,[SP + #5] + LD.w r1,[SP + #7] + LD r2,#FLASH_PROUNLOCK + ST.w [R2],R0 + ST.w [R2],R1 + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key){ + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_ERASE + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ +.if __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN + DSI +.endif + //++++++++++++++++++++++++++++++++++++++++++++++ length 1K/2K aligned +ERASE_NEXT_PAGE_IN_ERASE: + LD.w r0,[SP + #8] + LD.w r1,[SP + #9] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_ERASE +.ifdef __FLASH_API_LIKE_A158 + MOVL R2,#0x07FF +.else + MOVL R2,#0x03FF +.endif + ANL R2,R0,R2 + JNZ Return_PARAM_ERROR_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ address set + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_ERASE + LD R4,#__FLASH_MAX_SIZE__ + CMP R0,R4 + JHI Return_PARAM_ERROR_IN_ERASE + MOVL R4,#0x3FF + ANL R4,R1,R4 + JNZ Return_PARAM_ERROR_IN_ERASE + LD R4,#__FLASH_MIN_SIZE__ + CMP R4,R0 + JHI Return_PARAM_ERROR_IN_ERASE + + LD R2,#FLASH_ISPADDR + ST.w [R2],R0 + LD.w R3,[R2] + CMP R3,R1 + JNZ Return_PARAM_ERROR_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ set cmd + LD R2,#FLASH_ISPCMD + MOVL R0,#0x7FB + ST.w [R2],R0 + LD.w R3,[R2] + CMP R3,R0 + JNZ Return_PARAM_ERROR_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ run cmd + LD R2,#FLASH_ISPTRG + LD R0,#FLASH_WORK_CMD + ST.w [R2],R0 + NOP + NOP + NOP + //++++++++++++++++++++++++++++++++++++++++++++++ wait event + LD R4,#TimeOutCountValue +ERASE_WAIT_BIT_2_TBIT: + LD R3,#FLASH_STATE + LD.w R1,[R3] + JB R1,#2 + JMP ERASE_END_BIT_2_TBIT + SUB R4,#1 + JZ ERASE_END_BIT_2_TBIT + JMP ERASE_WAIT_BIT_2_TBIT + //++++++++++++++++++++++++++++++++++++++++++++++ is timeout find +ERASE_END_BIT_2_TBIT: + CMP R4,#0 + JZ Return_PARAM_ERROR_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ for next + LD.w r0,[SP + #4] + MOV R1,#1 +.ifdef __FLASH_API_LIKE_A158 + LSL R1,#11 +.else + LSL R1,#10 +.endif + ADD R0,R1 + ST.w [SP+#4],R0 + ST.w [SP+#6],R0 + + LD.w r0,[SP + #8] + SUB R0,R1 + ST.w [SP + #8],R0 + ST.w [SP + #9],R0 + + JHI ERASE_NEXT_PAGE_IN_ERASE + //++++++++++++++++++++++++++++++++++++++++++++++ ok + MOV R0,#0 + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 + //++++++++++++++++++++++++++++++++++++++++++++++ ng +Return_CMD_SUCCESS_IN_ERASE: + MOV R0,#0 + JMP Return_PUSH_POP_IN_ERASE +Return_PARAM_ERROR_IN_ERASE: + MOV R0,#PARAM_ERROR + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 +//++++++++++++++++++++++++++++++++++++++++++++++ +Return_PUSH_POP_IN_ERASE: + //++++++++++++++++++++++++++++++++++++++++++++++ +.if __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN + ENI +.endif + ST.w [SP+#0],R0 + ST.w [SP+#1],R0 + ST.w [SP+#2],R0 + ST.w [SP+#3],R0 + ST.w [SP+#4],R0 + ST.w [SP+#5],R0 + ST.w [SP+#6],R0 + ST.w [SP+#7],R0 +//++++++++++++++++++++++++++++++++++++++++++++++ + ADD sp,#40 + JMP lr + __End_Function__ __FLASH_Erase__ +########################################################################### + __RAM_Function__ __FLASH_Program__ + PUSH R5 + SUB sp,#48 + //++++++++++++++++++++++++++++++++++++++++++++++ + ST.w [sp+#0],r0 + LD R4,#FLASH_KEY1 + ST.w [sp+#1],R4 + + ST.w [sp+#2],r0 + LD R4,#FLASH_KEY2 + ST.w [sp+#3],R4 + + ST.w [sp+#4],r1 + LD R4,#FLASH_KEY3 + ST.w [sp+#5],R4 + + ST.w [sp+#6],r1 + LD R4,#FLASH_KEY4 + ST.w [sp+#7],R4 + + ST.w [sp+#8],r2 + ST.w [sp+#9],r2 + ST.w [sp+#10],r3 + ST.w [sp+#11],r3 + //++++++++++++++++++++++++++++++++++++++++++++++ clear syc + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 + //++++++++++++++++++++++++++++++++++++++++++++++ address check + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_FAST + LD R4,#__FLASH_MAX_SIZE__ + CMP R0,R4 + JHI Return_PARAM_ERROR_IN_FAST + MOVL R4,#0x1FF + ANL R1,R4 + JNZ Return_PARAM_ERROR_IN_FAST + LD R4,#__FLASH_MIN_SIZE__ + CMP R4,R0 + JHI Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++ len check + LD.w r0,[SP + #8] + LD.w r1,[SP + #9] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_FAST + LD R4,#0 + CMP R0,R4 + JZ Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key) + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_FAST + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++ key1 key2 + LD.w r0,[SP + #1] + LD.w r1,[SP + #3] + LD r2,#FLASH_NVMUNLOCK + ST.w [R2],R0 + ST.w [R2],R1 + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key){ + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_FAST + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++ key3 key4 + LD.w r0,[SP + #5] + LD.w r1,[SP + #7] + LD r2,#FLASH_PROUNLOCK + ST.w [R2],R0 + ST.w [R2],R1 + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key){ + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_FAST + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++ address re same check + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++ length 512/1024 aligned + LD.w r0,[SP + #8] + LD.w r1,[SP + #9] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_FAST +.ifdef __FLASH_API_LIKE_A158 + MOVL R2,#0x03FF +.else + MOVL R2,#0x01FF +.endif + ANL R0,R2 + JNZ Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++ +.if __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN + DSI +.endif + //++++++++++++++++++++++++++++++++++++++++++++++ dwen bit 3 set + LD R2,#FLASH_ISPCON0 + SET [R2],#3 + LD.b R3,[R2] + MOV R2,#0x4B + CMP R3,R2 + JNZ Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++ cmd page write + LD R2,#FLASH_ISPCMD + MOVL R0,#0x7e5 + MOVL R1,#0x7e5 + ST.w [R2],R0 + LD.w R3,[R2] + CMP R3,R1 + JZ Fast_Process_Start + //++ cmd failed + LD R2,#FLASH_ISPCON0 + LD R0,#FLASH_WORK_CLR + ST.w [R2],R0 + .if __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN + ENI + .endif + JMP Return_PARAM_ERROR_IN_FAST + //++++++++++++++++++++++++++++++++++++++++++++++ +Fast_Process_Start: + LD.w R0,[SP + #4] + LD.w R1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_FAST + + LD.w R1,[SP + #8] + LD.w R2,[SP + #9] + CMP R2,R1 + JNZ Return_PARAM_ERROR_IN_FAST + + LD.w R2,[SP + #10] + LD.w R3,[SP + #11] + CMP R2,R3 + JNZ Return_PARAM_ERROR_IN_FAST + + JMP FAST_FIRST_HALF_PAGE + //++++++++++++++++++++++++++++++++++++++++++++++ +FAST_NEXT_HALF_PAGE: + LD R3,#FLASH_ISPCMD + MOVL R4,#0x7e5 + MOVL R5,#0x7e5 + ST.w [R3],R4 + LD.w R4,[R3] + CMP R4,R5 + JNZ Return_PARAM_ERROR_IN_FAST + +FAST_FIRST_HALF_PAGE: + LD R3,#FLASH_ISPTRG + LD R4,#FLASH_WORK_CMD + ST.w [R3],R4 + NOP + NOP + NOP + //++++++++++++++++++++++++++++++++++++++++++++++ + MOV R4,#64 + //++++++++++++++++++++++++++++++++++++++++++++++ +Fast_DATE_TRAN: + LD.w R3,[R2++] + ST.w [R0++],R3 + LD.w R3,[R2++] + ST.w [R0++],R3 +.ifdef __FLASH_API_LIKE_A158 + LD.w R3,[R2++] + ST.w [R0++],R3 + LD.w R3,[R2++] + ST.w [R0++],R3 + SUB R1,#16 +.else + SUB R1,#8 +.endif + //--------------------------------------- + LD R3,#TimeOutCountValue +FAST_WAIT_BIT_3_TBUSY: + LD R5,#FLASH_STATE + JB [R5],#3 + JMP Fast_DATE_IF_TRAN + SUB R3,#1 + JZ FAST_END_BIT_3_TBUSY_TIMEOUT + JMP FAST_WAIT_BIT_3_TBUSY + +FAST_END_BIT_3_TBUSY_TIMEOUT: + MOV R0,#0x55555555 + JMP Return_TimeOut + //--------------------------------------- +Fast_DATE_IF_TRAN: + + MOV R3,R4 + CMP R3,#65 + JHI Return_PARAM_ERROR_IN_FAST + SUB R4,#1 + JNZ Fast_DATE_TRAN + //++++++++++++++++++++++++++++++++++++++++++++++ + + LD R3,#TimeOutCountValue +FAST_WAIT_BIT_2_TBIT: + LD R5,#FLASH_STATE + JB [R5],#2 + JMP FAST_PAGE_HALF_FINISH + SUB R3,#1 + JZ FAST_TIMEOUT_BIT_2_TBIT + JMP FAST_WAIT_BIT_2_TBIT + //++++++++++++++++++++++++++++++++++++++++++++++ +FAST_TIMEOUT_BIT_2_TBIT: + MOV R0,#0xAAAAAAAA + JMP Return_TimeOut + +FAST_PAGE_HALF_FINISH: + //++++++++++++++++++++++++++++++++++++++++++++++ +.ifdef __FLASH_API_LIKE_A158 + MOVL R3,#0x03FF +.else + MOVL R3,#0x01FF +.endif + ANL R3,R1 + JNZ Return_PARAM_ERROR_IN_FAST + CMP R1,#0 + JNZ FAST_NEXT_HALF_PAGE + //++++++++++++++++++++++++++++++++++++++++++++++ + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 +Return_CMD_SUCCESS_IN_FAST: + MOV R0,#0 + JMP Return_PUSH_POP_IN_FAST + +Return_PARAM_ERROR_IN_FAST: + MOV R0,#PARAM_ERROR + + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 + JMP Return_PUSH_POP_IN_FAST + +Return_TimeOut: + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 +//++++++++++++++++++++++++++++++++++++++++++++++ +Return_PUSH_POP_IN_FAST: + .if __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN + ENI + .endif + ST.w [SP+#0],R0 + ST.w [SP+#1],R0 + ST.w [SP+#2],R0 + ST.w [SP+#3],R0 + ST.w [SP+#4],R0 + ST.w [SP+#5],R0 + ST.w [SP+#6],R0 + ST.w [SP+#7],R0 + ST.w [SP+#8],R0 + ST.w [SP+#9],R0 + ST.w [SP+#10],R0 + ST.w [SP+#11],R0 +//++++++++++++++++++++++++++++++++++++++++++++++ + ADD sp,#48 + POP R5 + JMP lr + __End_Function__ __FLASH_Program__ +######################################################################################### + __RAM_Function__ __FLASH_Program_NBytes__ + PUSH R5 + SUB sp,#48 + //++++++++++++++++++++++++++++++++++++++++++++++ + ST.w [sp+#0],r0 + LD R4,#FLASH_KEY1 + ST.w [sp+#1],R4 + + ST.w [sp+#2],r0 + LD R4,#FLASH_KEY2 + ST.w [sp+#3],R4 + + ST.w [sp+#4],r1 + LD R4,#FLASH_KEY3 + ST.w [sp+#5],R4 + + ST.w [sp+#6],r1 + LD R4,#FLASH_KEY4 + ST.w [sp+#7],R4 + + ST.w [sp+#8],r2 + ST.w [sp+#9],r2 + ST.w [sp+#10],r3 + ST.w [sp+#11],r3 + //++++++++++++++++++++++++++++++++++++++++++++++ clear syc + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 + //++++++++++++++++++++++++++++++++++++++++++++++ address check + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + LD R4,#__FLASH_MAX_SIZE__ + CMP R0,R4 + JHI Return_PARAM_ERROR_IN_NBytes + MOVL R4,#0x7 + ANL R1,R4 + JNZ Return_PARAM_ERROR_IN_NBytes + LD R4,#__FLASH_MIN_SIZE__ + CMP R4,R0 + JHI Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ len check + LD.w r0,[SP + #8] + LD.w r1,[SP + #9] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + LD R4,#0 + CMP R0,R4 + JZ Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key) + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ key1 key2 + LD.w r0,[SP + #1] + LD.w r1,[SP + #3] + LD r2,#FLASH_NVMUNLOCK + ST.w [R2],R0 + ST.w [R2],R1 + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key){ + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ key3 key4 + LD.w r0,[SP + #5] + LD.w r1,[SP + #7] + LD r2,#FLASH_PROUNLOCK + ST.w [R2],R0 + ST.w [R2],R1 + //++++++++++++++++++++++++++++++++++++++++++++++if(Function_Parameter_Validate != key){ + LD.w r0,[SP + #0] + LD.w r1,[SP + #2] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + LD R2,#Function_Parameter_Validate + CMP R0,R2 + JNZ Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ address re same check + LD.w r0,[SP + #4] + LD.w r1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ length 8aligned + LD.w r0,[SP + #8] + LD.w r1,[SP + #9] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + MOV R2,#0x07 + ANL R0,R2 + JNZ Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ +.if __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN + DSI +.endif + //++++++++++++++++++++++++++++++++++++++++++++++ dwen bit 3 set + LD R2,#FLASH_ISPCON0 + SET [R2],#3 + LD.b R3,[R2] + MOV R2,#0x4B + CMP R3,R2 + JNZ Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ cmd word write + LD R2,#FLASH_ISPCMD + MOVL R0,#0x7f5 + MOVL R1,#0x7f5 + ST.w [R2],R0 + LD.w R3,[R2] + CMP R3,R1 + JZ NBytes_Process_Start + //++ cmd failed + LD R2,#FLASH_ISPCON0 + LD R0,#FLASH_WORK_CLR + ST.w [R2],R0 + .if __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN + ENI + .endif + JMP Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ +NBytes_Process_Start: + LD.w R0,[SP + #4] + LD.w R1,[SP + #6] + CMP R0,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + + LD.w R1,[SP + #8] + LD.w R2,[SP + #9] + CMP R2,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + + LD.w R2,[SP + #10] + LD.w R3,[SP + #11] + CMP R2,R3 + JNZ Return_PARAM_ERROR_IN_NBytes + //++++++++++++++++++++++++++++++++++++++++++++++ + //++++++++++++++++++++++++++++++++++++++++++++++ +NBytes_DATE_TRAN: + LD.w R3,[R2++] + ST.w [R0++],R3 + LD.w R3,[R2++] + ST.w [R0++],R3 +.ifdef __FLASH_API_LIKE_A158 + LD.w R3,[R2++] + ST.w [R0++],R3 + LD.w R3,[R2++] + ST.w [R0++],R3 + SUB R1,#16 +.else + SUB R1,#8 +.endif + LD R3,#FLASH_ISPTRG + LD R4,#FLASH_WORK_CMD + ST.w [R3],R4 + NOP + NOP + NOP + //--------------------------------------- + LD R3,#TimeOutCountValue +NBytes_WAIT_BIT_2_TBIT: + LD R5,#FLASH_STATE + JB [R5],#2 + JMP NBytes_DATE_IF_TRAN + SUB R3,#1 + JZ NBytes_END_BIT_2_TBIT_TIMEOUT + JMP NBytes_WAIT_BIT_2_TBIT + //--------------------------------------- +NBytes_DATE_IF_TRAN: +.ifdef __FLASH_API_LIKE_A158 + MOVL R3,#0x0F +.else + MOVL R3,#0x07 +.endif + ANL R3,R1 + JNZ Return_PARAM_ERROR_IN_NBytes + CMP R1,#0 + JNZ NBytes_DATE_TRAN + //++++++++++++++++++++++++++++++++++++++++++++++ +NBytes_END_BIT_2_TBIT_TIMEOUT: +NBytes_FINSH_BIT_2_TBIT: + //++++++++++++++++++++++++++++++++++++++++++++++ + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 +Return_CMD_SUCCESS_IN_NBytes: + MOV R0,#0 + JMP Return_PUSH_POP_IN_NBytes +Return_PARAM_ERROR_IN_NBytes: + MOV R0,#PARAM_ERROR + + LD R2,#FLASH_WORK_CLR + LD R3,#FLASH_ISPCON0 + ST.w [R3],R2 +//++++++++++++++++++++++++++++++++++++++++++++++ +Return_PUSH_POP_IN_NBytes: + .if __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN + ENI + .endif + ST.w [SP+#0],R0 + ST.w [SP+#1],R0 + ST.w [SP+#2],R0 + ST.w [SP+#3],R0 + ST.w [SP+#4],R0 + ST.w [SP+#5],R0 + ST.w [SP+#6],R0 + ST.w [SP+#7],R0 + ST.w [SP+#8],R0 + ST.w [SP+#9],R0 + ST.w [SP+#10],R0 + ST.w [SP+#11],R0 +//++++++++++++++++++++++++++++++++++++++++++++++ + ADD sp,#48 + POP R5 + JMP LR + __End_Function__ __FLASH_Program_NBytes__ + \ No newline at end of file diff --git a/FlashEEPROMEmulation/Driver/__driver_Flash_API.h b/FlashEEPROMEmulation/Driver/__driver_Flash_API.h new file mode 100644 index 0000000000000000000000000000000000000000..d0a6d58f57ab7ca0104a789f2cfe8c75eb49025c --- /dev/null +++ b/FlashEEPROMEmulation/Driver/__driver_Flash_API.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * Shanghai ChipON Micro-Electronic Co.,Ltd + ****************************************************************************** + * @File Name : __driver_Flash_API.h + * @Author : ChipON AE/FAE Group + * @Date : 2023-09-18 + * @Chip Version : A02 + * @HW Version : KF32A136-MINI-EVB_V1.0 + * @Example Version : V2.1.2.230918_release + * @Description : + ***************************************************************************** + * Copyright (C) by Shanghai ChipON Micro-Electronic Co.,Ltd + * All rights reserved. + * + * This software is copyright protected and proprietary to + * Shanghai ChipON Micro-Electronic Co.,Ltd. + ******************************************************************************/ + +#ifndef DRIVER_FLASH_OP_API_HEAD_H_ +#define DRIVER_FLASH_OP_API_HEAD_H_ +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ user config 1 + +#define Function_Parameter_Validate 0x5A5A6688 + +#define CMD_SUCCESS 0x00 +#define CMD_ERROR 0xAA +#define PARAM_ERROR 0x0C + +#define TimeOutCountValue 5000000 +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +#define __FLASH__ __attribute__((section(".text"))) +#define __RAM__ __attribute__((section(".indata"))) + +#define optimize_Os __attribute__((optimize("-Os"))) +#define optimize_O2 __attribute__((optimize("-O2"))) +#define optimize_O0 __attribute__((optimize("-O0"))) + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ user config + +// Macro to select flash function with isr close and open +#if 1 +#define __FLASH_ERASE_WRITE_ISR_CLOSE_AND_OPEN +#endif + +// Macro to select flash function with unlock code +#if 0 + #define __FLASH_Driver_Use_LOCK_UNLOCK_Function +#endif + +//Macro select flash parm +#if 1 + #if 1 + #define __FLASH_API_LIKE_A150 + #else + #define __FLASH_API_LIKE_A156 + #endif +#endif + + +#define __FLASH_MAX_SIZE__ (512*1024) +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +unsigned char __FLASH_Read_Byte__(unsigned int address); +unsigned int __FLASH_Read_WORD__(unsigned int address); +unsigned int __FLASH_Read_One__(unsigned int address); +unsigned int __FLASH_Read__(unsigned int address,unsigned int length,unsigned int buffers[]); + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +unsigned int __FLASH_UNLOCK_FUNCTION__(volatile unsigned int key,volatile unsigned int isopen); + +unsigned int __FLASH_Erase__(volatile unsigned key,volatile unsigned int WriteAddr, + volatile unsigned int DataLength); +unsigned int __FLASH_Program__(volatile unsigned int key,volatile unsigned int WriteAddr, + volatile unsigned int DataLength,unsigned int WriteData[]); +unsigned int __FLASH_Program_NBytes__(volatile unsigned int key,volatile unsigned int WriteAddr, + volatile unsigned int DataLength,unsigned int WriteData[]); +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ user config 1 +#endif /* DRIVER_FLASH_OP_API_HEAD_H_ */ diff --git a/FlashEEPROMEmulation/Driver/fee.c b/FlashEEPROMEmulation/Driver/fee.c new file mode 100644 index 0000000000000000000000000000000000000000..6208477aa1e03e407803a3f4143733c6c41cba29 --- /dev/null +++ b/FlashEEPROMEmulation/Driver/fee.c @@ -0,0 +1,223 @@ +/****************************************************************************** + * Shanghai ChipON Micro-Electronic Co.,Ltd + ****************************************************************************** + * @File Name : fee.c + * @Author : ChipON AE/FAE Group + * @Date : 2024-03-15 + * @Version : V0.2.0 + * @Description : This file provides Driver for flash emulation of EEPROMs + ****************************************************************************** + * Copyright (C) by Shanghai ChipON Micro-Electronic Co.,Ltd + * All rights reserved. + * + * This software is copyright protected and proprietary to + * Shanghai ChipON Micro-Electronic Co.,Ltd. + *****************************************************************************/ + +/****************************************************************************** + ** Include Files + ******************************************************************************/ +#include +#include + +#include "__Kungfu32_chipmodel_define.h" +#include "__driver_Flash_API.h" +#include "EmulatedEE.h" +#include "fee.h" + +/****************************************************************************** + * Macro Definitions + ******************************************************************************/ + +/** + * @brief Fee access to the maximum space + */ +#define FEE_EEPROM_ADDR_MAX ((EE_PAGE_SIZE / 2U) - 5U) +/****************************************************************************** + * Constants + ******************************************************************************/ + +/****************************************************************************** + * Type definitions + ******************************************************************************/ + +/****************************************************************************** + * Variables + ******************************************************************************/ + +/** + * @brief Fee state + */ +static FEE_StateEnumType FeeState = FEE_UNINIT; +/****************************************************************************** + * Function definitions + ******************************************************************************/ +/** + * @brief The function initializes Fee module. + * + */ +void FEE_Init(void) +{ + FeeState = FEE_INIT; + EmulatedEE_Init(); + FeeState = FEE_IDLE; +} + +/** + * @brief Write one or more 4 Bytes Block to Emulated Eeprom. + * + * @details The address range for writing is 0 to 511 bytes + * + * @param WriteAddr Target address in Emulated Eeprom memory. + * @param DataLength Number of bytes to write. + * @param Buffers Pointer to source data buffer. + * + * @return bool + * @retval true write success + * @retval false write failed + */ +FEE_StatusType FEE_Write(uint32_t WriteAddr, uint32_t DataLength, const uint32_t *Buffers) +{ + uint32_t kvRetVal; + FEE_StatusType kvStatus = FEE_STATUS_OK; + + if ((WriteAddr + DataLength) > (FEE_EEPROM_ADDR_MAX + 1U)) + { + return FEE_STATUS_PARAM_ERR; + } + else + { + /* Do Nothing */ + } + + if (((DataLength & 0x3U) > 0U) || (0U == DataLength)) + { + return FEE_STATUS_PARAM_ERR; + } + else + { + /* Do Nothing */ + } + + if (Buffers == NULL) + { + return FEE_STATUS_PARAM_ERR; + } + else + { + /* Do Nothing */ + } + +#if FEE_WRITE_ISR_LOCK_ENABLE + kvIntState = (INT_CTL0 & INT_CTL0_AIE); + SFR_CLR_BIT_ASM(INT_CTL0, INT_CTL0_AIE_POS); +#endif + /** EE_Write Lock*/ + if (FeeState == FEE_IDLE) + { + FeeState = FEE_WRITE; + } + else + { + return false; + } +#if FEE_WRITE_ISR_LOCK_ENABLE + if (kvIntState != 0) + SFR_SET_BIT_ASM(INT_CTL0, INT_CTL0_AIE_POS); +#endif + + for (uint32_t i = 0U; i < DataLength; i += 4U) + { + + kvRetVal = EmulatedEE_WriteData(WriteAddr + i, Buffers[i / 4U]); + + if (kvRetVal != CMD_SUCCESS) + { + kvStatus = FEE_STATUS_ERROR; + break; + } + else + { + /* Do Nothing */ + } + } + + FeeState = FEE_IDLE; + + return kvStatus; +} + +/** + * @brief Reads from Emulated Eeprom memory. + * + * @param ReadAddr Read address in Emulated Eeprom memory. + * @param DataLength Number of bytes to read. + * @param Buffers Pointer to target data buffer. + * @retval true + * @retval false + */ +FEE_StatusType FEE_Read(uint32_t ReadAddr, uint32_t DataLength, uint32_t *Buffers) +{ + uint32_t kvRetVal; + FEE_StatusType kvStatus = FEE_STATUS_OK; + + if ((ReadAddr + DataLength) > (FEE_EEPROM_ADDR_MAX + 1U)) + { + return FEE_STATUS_PARAM_ERR; + } + else + { + /* Do Nothing */ + } + + if (((ReadAddr & 0x3U) > 0U) || (0U == DataLength)) + { + return FEE_STATUS_PARAM_ERR; + } + else + { + /* Do Nothing */ + } + + if (Buffers == NULL) + { + return FEE_STATUS_PARAM_ERR; + } + else + { + /* Do Nothing */ + } + + for (uint32_t i = 0U; i < DataLength; i += 4U) + { + kvRetVal = EmulatedEE_ReadData(ReadAddr + i, &Buffers[i / 4U]); + + if (kvRetVal != CMD_SUCCESS) + { + kvStatus = FEE_STATUS_ERROR; + break; + } + else + { + /* Do Nothing */ + } + } + + return kvStatus; +} + +/** + * @brief Get Fee Current Status + * + * @return FEE_StateEnumType + * @retval FEE_UNINIT + * @retval FEE_INIT + * @retval FEE_WRITE + * @retval FEE_IDLE + */ +FEE_StateEnumType FEE_GetStatus(void) +{ + return FeeState; +} + +/* EOF */ diff --git a/FlashEEPROMEmulation/Driver/fee.h b/FlashEEPROMEmulation/Driver/fee.h new file mode 100644 index 0000000000000000000000000000000000000000..a0caecdf3c6cdcbc908a36ab55f90cea1ec2a2a5 --- /dev/null +++ b/FlashEEPROMEmulation/Driver/fee.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Shanghai ChipON Micro-Electronic Co.,Ltd + ****************************************************************************** + * @File Name : fee.h + * @Author : ChipON AE/FAE Group + * @Date : 2024-03-15 + * @Version : V0.2.0 + * @Description : This file provides Driver for flash emulation of EEPROMs + ****************************************************************************** + * Copyright (C) by Shanghai ChipON Micro-Electronic Co.,Ltd + * All rights reserved. + * + * This software is copyright protected and proprietary to + * Shanghai ChipON Micro-Electronic Co.,Ltd. + *****************************************************************************/ +#ifndef FEE_H +#define FEE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + ** Include Files + ******************************************************************************/ +#include +#include +/****************************************************************************** + * Macro or Inline + ******************************************************************************/ + +/****************************************************************************** + ** Typedef Definitions + ******************************************************************************/ +/** + * @brief fee status + */ +typedef enum +{ + /** @brief fee status ok */ + FEE_STATUS_OK, + /** @brief */ + FEE_STATUS_PARAM_ERR = 0x0CU, + /** @brief */ + FEE_STATUS_ERROR = 0xAAU, +} FEE_StatusType; +typedef enum +{ + FEE_UNINIT, + FEE_INIT, + FEE_WRITE, + FEE_IDLE, +} FEE_StateEnumType; + +/****************************************************************************** + * Export Variables + ******************************************************************************/ + +/****************************************************************************** + * Export Functions + ******************************************************************************/ +/** + * @brief The function initializes Fee module. + * + */ +void FEE_Init(void); + +/** + * @brief Write one or more 4 Bytes Block to Emulated Eeprom. + * + * @details The address range for writing is 0 to 511 bytes + * + * @param WriteAddr Target address in Emulated Eeprom memory. + * @param DataLength Number of bytes to write. + * @param Buffers Pointer to source data buffer. + * + * @return bool + * @retval true write success + * @retval false write failed + */ +FEE_StatusType FEE_Write(uint32_t WriteAddr, uint32_t DataLength, const uint32_t *Buffers); + +/** + * @brief Reads from Emulated Eeprom memory. + * + * @param ReadAddr Read address in Emulated Eeprom memory. + * @param DataLength Number of bytes to read. + * @param Buffers Pointer to target data buffer. + * + * @return bool + * @retval true read success + * @retval false read failed + */ +FEE_StatusType FEE_Read(uint32_t ReadAddr, uint32_t DataLength, uint32_t *Buffers); + +/** + * @brief Get Fee Current Status + * + * @return FEE_StateEnumType + * @retval FEE_UNINIT + * @retval FEE_INIT + * @retval FEE_WRITE + * @retval FEE_IDLE + */ +FEE_StateEnumType FEE_GetStatus(void); + +#ifdef __cplusplus +} +#endif +#endif +/* EOF */ diff --git a/FlashEEPROMEmulation/README.md b/FlashEEPROMEmulation/README.md new file mode 100644 index 0000000000000000000000000000000000000000..836abb115a45cee4a865298405eb4cd6d2a9db2c --- /dev/null +++ b/FlashEEPROMEmulation/README.md @@ -0,0 +1,46 @@ +#### 文件所有 + +本文适用于KF32A136的Flash模拟EEPROM操作的示例例程,例程文件名:FlashEEPROMEmulation + +* * * + + +#### 版权说明 + +目前的固件只是为了给使用者提供指导,目的是向客户提供有关产品的代码信息, + +与使用者的产品信息和代码无关。因此,对于因此类固件内容和(或)客户使用此 + +处包含的与其产品相关的编码信息而引起的任何索赔,上海芯旺微电子技术有限公 + +司不承担任何直接、间接或后果性损害赔偿责任 + +* * * + + +#### Flash说明 + +* KF32A136有两块Flash,分别为保存代码的数据区和信息区 +* 提供数据区域Flash的操作接口,包括读取、擦除、页写入、字节写入、比较等函数 +* FLash的写入过程,关闭了全局中断,若在调用之前打开了全局中断,结束后会主动恢复 + +##### 使用说明 + +* 程序下载后可以通过 KF32A136 开发板板载串口观察程序运行输出 + +1. 写508数据,读取508数据,读出后和写入数据比较,看写、读是否一致 +2. Fee写或读出错后,打印出不同数据并报错 + +* * * +##### 注意事项 + +1. 写接口要求 + - 地址+写长度不能大于511 + - 地址要求4的整数倍 + - 写的长度要求4的整数倍 + - 写长度不为0 +2. 读接口要求 + - 地址+读长度不能大于511 + - 地址要求4的整数倍 + - 读的长度要求4的整数倍 + - 读长度不为0 diff --git a/FlashEEPROMEmulation/__Kungfu32_chipmodel_define.h b/FlashEEPROMEmulation/__Kungfu32_chipmodel_define.h new file mode 100644 index 0000000000000000000000000000000000000000..bc336b2f4b5907dc2851397c53884c3ec178957c --- /dev/null +++ b/FlashEEPROMEmulation/__Kungfu32_chipmodel_define.h @@ -0,0 +1,17 @@ +/**************************************************************************************** + * Auto File.Recreate By ChipType Change,Don't Edit And Write Code here!!! + * Auto File.Recreate By ChipType Change,Don't Edit And Write Code here!!! + * Auto File.Recreate By ChipType Change,Don't Edit And Write Code here!!! + * + * Inlcude this File,Useful For Peripheral Or Application ,Implement Different By ChipType + ****************************************************************************************/ + +#ifndef __Kungfu32_chipmodel_define +#define __Kungfu32_chipmodel_define + +#ifndef KF32A136KQS +#define KF32A136KQS +#endif + +#endif /* __Kungfu32_chipmodel_define */ + diff --git a/FlashEEPROMEmulation/_config/startup.c b/FlashEEPROMEmulation/_config/startup.c new file mode 100644 index 0000000000000000000000000000000000000000..898a5c2971ed334221fcb2626e60a0b8b6f9c136 --- /dev/null +++ b/FlashEEPROMEmulation/_config/startup.c @@ -0,0 +1,54 @@ + +#ifndef HWREG +#define HWREG(x) (*((volatile unsigned int *)(x))) +#endif +//################# auto value variable from tool #############// +extern unsigned int __text_end__; +extern unsigned int __bss_start__; +extern unsigned int __bss_end__; +extern unsigned int __data_start__; + +//#define Project_Type__cplusplus +#ifdef Project_Type__cplusplus +extern unsigned int __init_class_start; +extern unsigned int __init_class_end; +#endif +//####################################################################// +extern int main(); +//####################################################################// +void startup() +{ + unsigned int *s,*begin,*end; +#ifdef Project_Type__cplusplus + void (*pf)(void); +#endif +//############# init work for the chip #############// +// HWREG(0x40000000)=1; + HWREG(0x40000000)=0; +//############# init variable who have initialization #############// + s = (unsigned int*)&__text_end__; + begin = (unsigned int*)&__data_start__; + end = (unsigned int*)&__bss_start__; + while(begin < end) + *begin++ = *s++; +//############# init class who have initialization(C++) #############// +#ifdef Project_Type__cplusplus + begin = (unsigned int*)&__init_class_start; + end = (unsigned int*)&__init_class_end; + while(begin>>\r\n"); + + // Retrieve the current state of the Fee + FeeState = FEE_GetStatus(); + + // If the state is not idle, output an error message and terminate the function + if (FeeState != FEE_IDLE) + { + kf_printf("FeeState State Err [%d][%s:%d]\r\n", FeeState, __func__, __LINE__); + return; + } + + // Populate the write buffer with incrementing values as test data + for (int i = 0; i < 127; i++) + { + write_buffer[i] = i; + } + + // Write the buffer contents into the Fee + FEE_Write(0, 127 * 4, write_buffer); // Assuming FEE_Write accepts starting address, byte count, and data pointer as parameters + + // Clear the read buffer in preparation for receiving read data + memset(&read_buffer, 0, 64); + + // Read data from the Fee into the read buffer + FEE_Read(0, 127 * 4, (uint32_t *)&read_buffer); // Assuming FEE_Read accepts starting address, byte count, and data pointer as parameters + + // Verify that the read data matches the written data exactly + for (int i = 0; i < 127; i++) + { + if (read_buffer[i] != write_buffer[i]) + { + // If a mismatch is found, output detailed data differences and an error message, then terminate the function + FEE_PrintfData(read_buffer, write_buffer, 127); + kf_printf("Fee Write or Read Err [%d][%s:%d]\r\n", i, __func__, __LINE__); + return; + } + } + + // Retrieve and check the current state of the Fee once more + FeeState = FEE_GetStatus(); + + // If the state is not idle, output an error message and terminate the function + if (FeeState != FEE_IDLE) + { + kf_printf("FeeState State Err [%d][%s:%d]\r\n", FeeState, __func__, __LINE__); + return; + } + + // Output the successful completion of the function + kf_printf("\r\n%s %s", __FUNCTION__, "Pass >>>\r\n"); +} + +int main(void) +{ + /* Initialize the system clock is 120M */ + SystemInit(120); + /*Initialize the print function*/ + kfLog_Init(); + /* Setup SysTick Timer as delay function, and input frequency is 120M */ + systick_delay_init(120); + FEE_Init(); + while (1) + { + FEE_example(); + systick_delay_ms(1000); + } +} + +/** + * @brief : Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param[in] file pointer to the source file name + * @param[in] line assert_param error line source number + * @param[out] None + * @retval :None + */ +void check_failed(uint8_t *File, uint32_t Line) +{ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + + /* Infinite loop */ + while (1) + { + ; + } +};