/* ********************************************************************************************************* * IAR Development Kits * on the * * M451 * * Filename : fmc_config.h * Version : V1.00 * Programmer(s) : Qian Xianghong ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #include "includes.h" // 数据区起始地址:116K #define DATA_FLASH_BASE 118784ul // 配置数据起始地址 119K #define CONFIG_PARTITON_BASE 121856ul // Flash可擦除块大小 #define FLASH_ERASE_SIZE 512 // 配置分区大小:主分区=镜像分区=可擦除页大小 #define CONFIG_PARTITION_SIZE 2048 // 配置分块大小(每个分区划为4个块,循环覆盖写入) #define CONFIG_BLOCK_SIZE 512 // 每个配置块划分为4组配置 #define CONFIG_DC_SIZE DATA_BUFF_SIZE // 分区号: 0~1, 分块号: 0~3,分组号: 0~3 #define CONFIG_PARTITION(partition) (partition) #define CONFIG_BLOCK(block) (block) #define CONFIG_DC(DC) ((DC) - 1) // 读写Flash的临时缓冲 static rd_buff_t rdBuff; // CAN发送的锁 //OS_MUTEX Config_saveLock; static uint32_t SetDataFlashBase(uint32_t u32DFBA) { uint32_t au32Config[2]; /* Read current User Configuration */ FMC_ReadConfig(au32Config, 1); /* Just return when Data Flash has been enabled */ if(!(au32Config[0] & 0x1)) return TRUE; /* Enable User Configuration Update */ FMC_ENABLE_CFG_UPDATE(); /* Erase User Configuration */ FMC_Erase(FMC_CONFIG_BASE); /* Write User Configuration to Enable Data Flash */ au32Config[0] &= ~0x1; au32Config[1] = u32DFBA; if(FMC_WriteConfig(au32Config, 2)) return FALSE; printf("\nSet Data Flash base as 0x%x.\n", FMC_ReadDataFlashBaseAddr()); /* Perform chip reset to make new User Config take effect */ SYS->IPRST_CTL1 |= SYS_IPRST_CTL1_CHIP_RST_Msk; return TRUE; } static uint32_t Flash_ErasePartition(uint8_t partition) { uint32_t u32StartAddr = CONFIG_PARTITON_BASE + CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE; uint32_t u32EndAddr = u32StartAddr + CONFIG_PARTITION_SIZE; while(u32StartAddr < u32EndAddr) { FMC_Erase(u32StartAddr); u32StartAddr += FLASH_ERASE_SIZE; } return TRUE; } static uint32_t Flash_WriteDC(uint8_t partition, uint8_t block, uint8_t DC, rd_buff_t *dataBuff) { uint32_t u32StartAddr = CONFIG_PARTITON_BASE + CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE + CONFIG_BLOCK(block) * CONFIG_BLOCK_SIZE + CONFIG_DC(DC) * CONFIG_DC_SIZE; uint32_t u32EndAddr = u32StartAddr + CONFIG_DATA_LEN(DC); uint32_t u32Addr; uint8_t i = 0; for(u32Addr = u32StartAddr; u32Addr < u32EndAddr; u32Addr += 4) { FMC_Write(u32Addr, dataBuff->buff32[i++]); } return TRUE; } static uint32_t Flash_ReadDC(uint8_t partition, uint8_t block, uint8_t DC, rd_buff_t *dataBuff) { uint32_t u32StartAddr = CONFIG_PARTITON_BASE + CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE + CONFIG_BLOCK(block) * CONFIG_BLOCK_SIZE + CONFIG_DC(DC) * CONFIG_DC_SIZE; uint32_t u32EndAddr = u32StartAddr + CONFIG_DATA_LEN(DC); uint32_t u32Addr; uint8_t i = 0; for(u32Addr = u32StartAddr; u32Addr < u32EndAddr; u32Addr += 4) { dataBuff->buff32[i++] = FMC_Read(u32Addr); } return TRUE; } static uint32_t Flash_ReadBlock(uint8_t partition, uint8_t block, uint32_t forTest) { if(!Flash_ReadDC(partition, block, CAN_DC_BOTTLE_CONFIG, &rdBuff) || !Config_CheckValid(&rdBuff, CAN_DC_BOTTLE_CONFIG)) return FALSE; if(forTest) return TRUE; dcBuff.configBottle = rdBuff.configBottle; if(!Flash_ReadDC(partition, block, CAN_DC_SENSOR_CONFIG, &rdBuff) || !Config_CheckValid(&rdBuff, CAN_DC_SENSOR_CONFIG)) return FALSE; dcBuff.configSensor = rdBuff.configSensor; if(!Flash_ReadDC(partition, block, CAN_DC_DATA_CONFIG, &rdBuff) || !Config_CheckValid(&rdBuff, CAN_DC_DATA_CONFIG)) return FALSE; dcBuff.configData = rdBuff.configData; if(!Flash_ReadDC(partition, block, CAN_DC_DISPLAY_CONFIG, &rdBuff) || !Config_CheckValid(&rdBuff, CAN_DC_DISPLAY_CONFIG)) return FALSE; dcBuff.configDisplay = rdBuff.configDisplay; return TRUE; } static uint32_t Flash_ReadConfig(uint8_t partition, uint32_t forTest, uint8_t *blockNo) { uint8_t block; for(block = 0; block < 4; block++) { if(Flash_ReadBlock(partition, block, forTest)) { *blockNo = block; return TRUE; } } return FALSE; } static uint32_t Flash_WriteConfig(uint8_t partition) { uint8_t block = 0; uint8_t i; // 读取现有配置数据的块号 if(!Flash_ReadConfig(partition, TRUE, &block)) block = 3; for(i = 0; i < 4; i++) { // 确定循环写入的块号 block = (block + 1) % 4; if(!Flash_ErasePartition(partition)) return FALSE; rdBuff.configBottle = dcBuff.configBottle; if(!Flash_WriteDC(partition, block, CAN_DC_BOTTLE_CONFIG, &rdBuff)) continue; rdBuff.configSensor = dcBuff.configSensor; if(!Flash_WriteDC(partition, block, CAN_DC_SENSOR_CONFIG, &rdBuff)) continue; rdBuff.configData = dcBuff.configData; if(!Flash_WriteDC(partition, block, CAN_DC_DATA_CONFIG, &rdBuff)) continue; rdBuff.configDisplay = dcBuff.configDisplay; if(!Flash_WriteDC(partition, block, CAN_DC_DISPLAY_CONFIG, &rdBuff)) continue; return TRUE; } return FALSE; } uint32_t Config_LoadConfig() { uint8_t block; if(Flash_ReadConfig(0, FALSE, &block)) return TRUE; return Flash_ReadConfig(1, FALSE, &block); } uint32_t Config_SaveConfig() { // OS_ERR err; // CPU_TS ts; uint32_t ret, ret1; // OSMutexPend(&Config_saveLock, 0, OS_OPT_PEND_BLOCKING, &ts, &err); Config_ForceValid((rd_buff_t *) &dcBuff.configBottle, CAN_DC_BOTTLE_CONFIG); Config_ForceValid((rd_buff_t *) &dcBuff.configSensor, CAN_DC_SENSOR_CONFIG); Config_ForceValid((rd_buff_t *) &dcBuff.configData, CAN_DC_DATA_CONFIG); Config_ForceValid((rd_buff_t *) &dcBuff.configDisplay, CAN_DC_DISPLAY_CONFIG); ret = Flash_WriteConfig(0); ret1= Flash_WriteConfig(1); // OSMutexPost(&Config_saveLock, OS_OPT_POST_NONE, &err); return ret || ret1; } void Config_Init() { FMC_Open(); } void Config_Open() { // OS_ERR err; // 任务列表锁 // OSMutexCreate(&Config_saveLock, "", &err); // 填充采集板系统信息 Config_fillSampleInfo(&dcBuff); // 填充电源板系统信息 Config_fillPowerInfo(&dcBuff); // 填充显示板系统信息 Config_fillDisplayInfo(&dcBuff); // 填充蓝牙板系统信息 Config_fillBluetoothInfo(&dcBuff); // 设置默认参数 Config_setBottleDefParam(&dcBuff); Config_setSensorDefParam(&dcBuff); Config_setDataDefParam(&dcBuff); Config_setDisplayDefParam(&dcBuff); // 读取保存的配置 SetDataFlashBase(DATA_FLASH_BASE); Config_LoadConfig(); }