#include "app_flash.h" #include "bsp_wdt.h" /************************************* *DEFINITION */ #define FLASH_HEAD 0xAA5555AA #define FLASH_TAIL_H 0xA5 //高位字节不能为0,因为结构体强制4字节对齐缘故,会导致解析错误。 #define FLASH_TAIL_L 0x55 //低字节随意,最好是0101组合 #define FLASH_ADDR_INFO_PAGENUM 1 #define FLASH_ADDR_STEP_PAGENUM 2 #define FLASH_ADDR_BACKUP_PAGENUM 1 #define MaxLength(a,b) a>b?a:b /********************************************************************* * LOCAL VARIABLES */ static uint32_t info_zone; static uint32_t step_zone; static uint32_t backup_zone; Flash_t mFlash; FlashBackup_t mBackup; /********************************************************************* * LOCAL FUCTIONS */ /** @brief crc16校验码 @param crc - [in] 默认0 @param buf - [in] 指向需要校验的数据 @param len - [in] 校验数据的长度 @return 返回crc16校验码 */ static int CalCrc(int crc, const char *buf, int len) { unsigned int byte; unsigned char k; unsigned short ACC,TOPBIT; unsigned short remainder = crc; TOPBIT = 0x8000; for (byte = 0; byte < len; ++byte) { ACC = buf[byte]; remainder ^= (ACC <<8); for (k = 8; k > 0; --k) { if (remainder & TOPBIT) { remainder = (remainder << 1) ^0x8005; } else { remainder = (remainder << 1); } } } remainder=remainder^0x0000; return remainder; } /****************************************************接口****************************************************/ void Flash_Initialize(void) { uint8_t ret = 0; uint32_t* addr_R; Fstorage_FlashInit(); SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_INFO_PAGENUM, &info_zone):%d\n",Zone_Alloca(FLASH_ADDR_INFO_PAGENUM, &info_zone)); SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_STEP_PAGENUM, &step_zone):%d\n",Zone_Alloca(FLASH_ADDR_STEP_PAGENUM, &step_zone)); SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_BACKUP_PAGENUM, &backup_zone):%d\n",Zone_Alloca(FLASH_ADDR_BACKUP_PAGENUM, &backup_zone)); addr_R = (uint32_t*)info_zone; SEGGER_RTT_printf(0,"Flash head read(%04X).\n",*addr_R); if((*addr_R)!=FLASH_HEAD){ SEGGER_RTT_printf(0,"Flash first init(%04X),write infomation to flash.\n",*addr_R); memset((uint8_t*)(&mFlash),0,sizeof(Flash_t)); mFlash.head = FLASH_HEAD; mFlash.m_struct_size = sizeof(mFlash); Flash_SaveInfomation(); SEGGER_RTT_printf(0,"Flash head second read(%04X).\n",*addr_R); if((*addr_R)!=FLASH_HEAD){ SEGGER_RTT_printf(0,"Flash write head fail.\n"); app_err_Set(ERR_NUM_FLASH,1); ret = 1; return; } SEGGER_RTT_printf(0,"System reset...\n",*addr_R); #if WATCHDOG_ENANBLE for(uint8_t i =0;i<6;i++){ nrf_delay_ms(500); feed_watchdog(); } #else nrf_delay_ms(3000); #endif NVIC_SystemReset(); } if(ret==0){ SEGGER_RTT_printf(0,"Flash_GetInfomation(&mFlash)\n"); SEGGER_RTT_printf(0,"Flash_GetInfomation(&mFlash):%d \n",Flash_GetInfomation(&mFlash)); SEGGER_RTT_printf(0,"Flash_GetInfomation(&mBackup):%d \n",Flash_GetBackup(&mBackup)); // SEGGER_RTT_printf(0,">>>>>>>>>add:%02x,add1:%02x,add2:%02x,add3:%02x,add4:%02x,add5:%02x\r\n",mFlash.add,mFlash.add2,mFlash.add3,mFlash.add4,mFlash.add5); // mFlash.add = 0x11; // mFlash.add2 = 0x22; // mFlash.add3 = 0x33; // mFlash.add4 = 0x44; // SEGGER_RTT_printf(0,"Flash_SaveInfomation():%d\n",Flash_SaveInfomation()); } if(mFlash.mStep.stepCur[0]>8 & 0x0000ff00) | (step>>24 & 0x000000ff)); err_code = Zone_Write(step_zone + (mFlash.mStep.num * 4), &flash_data, 4); if(err_code != ZONE_OP_SUCCESS)return err_code; mFlash.mStep.num++; mFlash.mStep.step[0] = mFlash.mStep.stepCur[0]; mFlash.mStep.step[1] = mFlash.mStep.stepCur[1]; } else return ZONE_ERROR_WRITE_FAIL; return ZONE_OP_SUCCESS; } /** @brief 获取步数区域首地址 @param 无 @return 错误代码 */ uint32_t Flash_GetStepZoneStartAddr(void) { return step_zone; } /** @brief 获取步数区域数据 @param 无 @return 错误代码 */ uint32_t Flash_GetStep(uint32_t destination_addr, uint32_t *pData, uint32_t dataLen) { return Zone_Read(destination_addr,pData,dataLen); } /** @brief 删除所有步数 @param 无 @return 错误代码 */ uint32_t Flash_DeleteAllStep(void) { mFlash.mStep.num = 0; return Zone_Erase(step_zone); } /** @brief 存储基本信息 @param 无 @return 错误代码 */ uint32_t Flash_SaveInfomation(void) { uint32_t err_code; uint32_t zone_bytes; Flash_t temp_flash; int32_t offset; uint16_t crc; uint8_t tail_h; memset(&temp_flash,0,sizeof(temp_flash)); err_code = Zone_GetByteSize(info_zone, &zone_bytes); if(err_code != ZONE_OP_SUCCESS)return err_code; //从区域尾开始找起,找到最新的帧尾 for(offset = zone_bytes - 1; offset >= 0; offset--) { err_code = Zone_Read(info_zone + offset, (uint32_t*)&tail_h, 1); if(err_code != ZONE_OP_SUCCESS)return err_code; if(tail_h == FLASH_TAIL_H)break; } //重新获取crc16校验码 mFlash.tail_crc16 = 0; mFlash.m_struct_size = sizeof(mFlash); mFlash.head = FLASH_HEAD; crc = CalCrc(0, (char*)&mFlash, sizeof(mFlash));//计算得到的16位CRC校验码 mFlash.tail_crc16 = (uint32_t)((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc; //写入 if(offset < 0){ //意味着整个区域是干净的,直接写开头。 err_code = Zone_Write(info_zone, (uint32_t*)&mFlash, sizeof(mFlash)); if(err_code != ZONE_OP_SUCCESS)return err_code; SEGGER_RTT_printf(0,"write zone all clear,mFlash.tail_crc16:0x%x\r\n",mFlash.tail_crc16); }else{ //这里要偏移才能对齐成员 offset++; //获取最新的帧尾 err_code = Zone_Read(info_zone + offset - sizeof(temp_flash.tail_crc16), (uint32_t*)&temp_flash.tail_crc16, sizeof(temp_flash.tail_crc16)); if(err_code != ZONE_OP_SUCCESS)return err_code; //获取最新的帧长度 err_code = Zone_Read(info_zone + offset - sizeof(temp_flash.tail_crc16) - sizeof(temp_flash.m_struct_size) , (uint32_t*)&temp_flash.m_struct_size, sizeof(temp_flash.m_struct_size)); if(err_code != ZONE_OP_SUCCESS)return err_code; //因为结构体强制4字节对齐缘故,所以tail_crc16未必是真实存储的帧尾,后面可能带一些数据为0的填充字节。所以要做校准。 // uint32_t pad_len = temp_flash.m_struct_size - ((uint32_t)&temp_flash.tail_crc16 + sizeof(temp_flash.tail_crc16) - (uint32_t)&temp_flash.head); uint32_t pad_len = 0; SEGGER_RTT_printf(0,"save info_zone:0x%x offset:%d pad_len:%d temp_flash.m_struct_size:%d\n",info_zone,offset,pad_len,temp_flash.m_struct_size); if(offset + pad_len < temp_flash.m_struct_size)pad_len = temp_flash.m_struct_size - offset; err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size, (uint32_t*)&temp_flash.head, sizeof(temp_flash.head)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,"save >>>>>>p_head:0x%x,addr:0x%x\n",temp_flash.head,info_zone + offset + pad_len - temp_flash.m_struct_size); while(temp_flash.head != FLASH_HEAD){ pad_len++; err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size, (uint32_t*)&temp_flash.head, sizeof(temp_flash.head)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,"save >>>>>>p_head:0x%x,addr:0x%x\n",temp_flash.head,info_zone + offset + pad_len - temp_flash.m_struct_size); // nrf_delay_ms(5); } // while(1) // { // SEGGER_RTT_printf(0,"save info_zone:0x%x offset:%d pad_len:%d temp_flash.m_struct_size:%d\n",info_zone,offset,pad_len,temp_flash.m_struct_size); // nrf_delay_ms(1000); // feed_watchdog(); // } err_code = Zone_Write(info_zone + offset + pad_len, (uint32_t*)&mFlash, sizeof(mFlash)); // if(err_code == ZONE_OP_SUCCESS)SEGGER_RTT_printf(0,"write zone forward ,mFlash.tail_crc16:0x%x\r\n",mFlash.tail_crc16); if(err_code != ZONE_OP_SUCCESS){ //如果写失败了 //擦除该区域 err_code = Zone_Erase(info_zone); if(err_code != ZONE_OP_SUCCESS)return err_code; //写在开头 err_code = Zone_Write(info_zone, (uint32_t*)&mFlash, sizeof(mFlash)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,"write zone all erase ,mFlash.tail_crc16:0x%x\r\n",mFlash.tail_crc16); } } return ZONE_OP_SUCCESS; } /** @brief 获取基本信息 @param 无 @return 错误代码 */ uint32_t Flash_GetInfomation(Flash_t *pflash) { uint32_t err_code; uint32_t zone_bytes; Flash_t temp_flash; int32_t offset; uint16_t crc; uint8_t tail_h; memset(&temp_flash,0,sizeof(temp_flash)); SEGGER_RTT_printf(0,"Zone_GetByteSize(info_zone, &zone_bytes):%d\n",zone_bytes); err_code = Zone_GetByteSize(info_zone, &zone_bytes); if(err_code != ZONE_OP_SUCCESS)return err_code; SEGGER_RTT_printf(0,"Zone_GetByteSize(info_zone, &zone_bytes):%d\n",zone_bytes); //从区域尾开始找起,找到最新的帧尾 for(offset = zone_bytes - 1; offset >= 0; offset--) { err_code = Zone_Read(info_zone + offset, (uint32_t*)&tail_h, 1); if(err_code != ZONE_OP_SUCCESS)return err_code; if(tail_h == FLASH_TAIL_H)break; } //意味着整个区域是干净的 if(offset < 0){ memset(pflash,0,sizeof(Flash_t)); pflash->head = FLASH_HEAD; pflash->m_struct_size = sizeof(Flash_t); //这里是包括填充字节的 crc = CalCrc(0, (char*)pflash, sizeof(Flash_t));//计算得到的16位CRC校验码,这里注意,有可能会将填充的字节也拿来做运算 pflash->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc; //这里最后才加,是因为不知道填充字节的个数 SEGGER_RTT_printf(0,"read zone all clear,pflash->tail_crc16:0x%x\r\n",pflash->tail_crc16); return ZONE_OP_SUCCESS; } //这里要偏移才能对齐成员 offset++; //获取最新的帧尾 err_code = Zone_Read(info_zone + offset - sizeof(temp_flash.tail_crc16), (uint32_t*)&temp_flash.tail_crc16, sizeof(temp_flash.tail_crc16)); if(err_code != ZONE_OP_SUCCESS)return err_code; //获取最新的帧长度 err_code = Zone_Read(info_zone + offset - sizeof(temp_flash.tail_crc16) - sizeof(temp_flash.m_struct_size) , (uint32_t*)&temp_flash.m_struct_size, sizeof(temp_flash.m_struct_size)); if(err_code != ZONE_OP_SUCCESS)return err_code; //因为结构体强制4字节对齐缘故,所以tail_crc16未必是真实存储的帧尾,后面可能带一些数据为0的填充字节。所以要做校准。 // uint32_t pad_len = temp_flash.m_struct_size - ((uint32_t)&temp_flash.tail_crc16 + sizeof(temp_flash.tail_crc16) - (uint32_t)&temp_flash.head); uint32_t pad_len = 0; SEGGER_RTT_printf(0,"get info_zone:0x%x offset:%d pad_len:%d temp_flash.m_struct_size:%d\n",info_zone,offset,pad_len,temp_flash.m_struct_size); if(offset + pad_len < temp_flash.m_struct_size)pad_len = temp_flash.m_struct_size - offset; err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size, (uint32_t*)&temp_flash.head, sizeof(temp_flash.head)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_flash.head,info_zone + offset + pad_len - temp_flash.m_struct_size); while(temp_flash.head != FLASH_HEAD){ pad_len++; err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size, (uint32_t*)&temp_flash.head, sizeof(temp_flash.head)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_flash.head,info_zone + offset + pad_len - temp_flash.m_struct_size); // nrf_delay_ms(5); } // SEGGER_RTT_printf(0,"read pad_len 0x%x info_zone + offset + pad_len - temp_flash.m_struct_size:0x%x\r\n",pad_len,info_zone + offset + pad_len - temp_flash.m_struct_size); //获取最新的帧 err_code = Zone_Read(info_zone + offset + pad_len - temp_flash.m_struct_size , (uint32_t*)&temp_flash, temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len); if(err_code != ZONE_OP_SUCCESS)return err_code; //校验数据 Flash_t crc_buf;//单纯做一个缓冲区 memset(&crc_buf,0,sizeof(crc_buf)); char *buf = (char*)&crc_buf; //获取成员head ~ m_struct_size // SEGGER_RTT_printf(0,"1:sizeof(crc_buf):%d temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len:%d\n",sizeof(crc_buf),temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len); memcpy(buf,&temp_flash,temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len); // SEGGER_RTT_printf(0,"read pad_len:%d,info_zone:0x%x,offset:%d,pad_len:%d,temp_flash.m_struct_size:%d\r\n",pad_len,info_zone,offset,pad_len,temp_flash.m_struct_size); // SEGGER_RTT_printf(0,"2:buf:0x%x sizeof(temp_flash.m_struct_size):%d\n",buf + temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len,sizeof(temp_flash.m_struct_size)); memcpy(buf + temp_flash.m_struct_size - sizeof(temp_flash.tail_crc16)-sizeof(temp_flash.m_struct_size)-pad_len,(uint32_t*)&temp_flash.m_struct_size,sizeof(temp_flash.m_struct_size)); //计算得到的16位CRC校验码 crc = CalCrc(0, buf, temp_flash.m_struct_size); if(crc == (temp_flash.tail_crc16 & 0xFFFF)){ SEGGER_RTT_printf(0,"read crc success :0x%x 0x%x \r\n",crc,temp_flash.tail_crc16 & 0xFFFF); temp_flash.head = FLASH_HEAD; temp_flash.m_struct_size = sizeof(temp_flash); temp_flash.tail_crc16 = 0; crc = CalCrc(0, (char*)&temp_flash, sizeof(temp_flash));//计算得到的16位CRC校验码 temp_flash.tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc; *pflash = temp_flash;//校验通过 } else{ //校验没通过 SEGGER_RTT_printf(0,"read crc fail :0x%x 0x%x \r\n",crc,temp_flash.tail_crc16 & 0xFFFF); memset(pflash,0,sizeof(Flash_t)); pflash->head = FLASH_HEAD; pflash->m_struct_size = sizeof(Flash_t); //将备份区域的数据拷贝 FlashBackup_t temp_backup; Flash_GetBackup(&temp_backup); for(int i=0;i<6;i++){ pflash->mClient.macAddr[i] = temp_backup.macAddr_R[i]; pflash->macHost[i] = temp_backup.macAddr_L[i]; } pflash->mClient.isConfig = temp_backup.isConfig; pflash->mClient.hardVersion = temp_backup.hardVersion; pflash->mClient.sotfVersion = temp_backup.sotfVersion; crc = CalCrc(0, (char*)pflash, sizeof(Flash_t));//计算得到的16位CRC校验码 pflash->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc; err_code = Zone_Erase(info_zone); if(err_code != ZONE_OP_SUCCESS)return err_code; err_code = Flash_SaveInfomation(); if(err_code != ZONE_OP_SUCCESS)return err_code; } return ZONE_OP_SUCCESS; } /** @brief 存储备份信息 @param 无 @return 错误代码 */ uint32_t Flash_SaveBackup(void) { uint32_t err_code; uint32_t zone_bytes; FlashBackup_t temp_backup; int32_t offset; uint16_t crc; uint8_t tail_h; memset(&temp_backup,0,sizeof(temp_backup)); err_code = Zone_GetByteSize(backup_zone, &zone_bytes); if(err_code != ZONE_OP_SUCCESS)return err_code; //从区域尾开始找起,找到最新的帧尾 for(offset = zone_bytes - 1; offset >= 0; offset--) { err_code = Zone_Read(backup_zone + offset, (uint32_t*)&tail_h, 1); if(err_code != ZONE_OP_SUCCESS)return err_code; if(tail_h == FLASH_TAIL_H)break; } //重新获取crc16校验码 mBackup.tail_crc16 = 0; mBackup.m_struct_size = sizeof(mBackup); mBackup.head = FLASH_HEAD; crc = CalCrc(0, (char*)&mBackup, sizeof(mBackup));//计算得到的16位CRC校验码 mBackup.tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc; //写入 if(offset < 0){ //意味着整个区域是干净的,直接写开头。 err_code = Zone_Write(backup_zone, (uint32_t*)&mBackup, sizeof(mBackup)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,"write zone all clear,mBackup.tail_crc16:0x%x\r\n",mBackup.tail_crc16); }else{ //这里要偏移才能对齐成员 offset++; //获取最新的帧尾 err_code = Zone_Read(backup_zone + offset - sizeof(temp_backup.tail_crc16), (uint32_t*)&temp_backup.tail_crc16, sizeof(temp_backup.tail_crc16)); if(err_code != ZONE_OP_SUCCESS)return err_code; //获取最新的帧长度 err_code = Zone_Read(backup_zone + offset - sizeof(temp_backup.tail_crc16) - sizeof(temp_backup.m_struct_size) , (uint32_t*)&temp_backup.m_struct_size, sizeof(temp_backup.m_struct_size)); if(err_code != ZONE_OP_SUCCESS)return err_code; //因为结构体强制4字节对齐缘故,所以tail_crc16未必是真实存储的帧尾,后面可能带一些数据为0的填充字节。所以要做校准。 // uint32_t pad_len = temp_backup.m_struct_size - ((uint32_t)&temp_backup.tail_crc16 + sizeof(temp_backup.tail_crc16) - (uint32_t)&temp_backup.head); uint32_t pad_len = 0; SEGGER_RTT_printf(0,"save back up info_zone:0x%x offset:%d pad_len:%d temp_backup.m_struct_size:%d\n",info_zone,offset,pad_len,temp_backup.m_struct_size); if(offset + pad_len < temp_backup.m_struct_size)pad_len = temp_backup.m_struct_size - offset; err_code = Zone_Read(info_zone + offset + pad_len - temp_backup.m_struct_size, (uint32_t*)&temp_backup.head, sizeof(temp_backup.head)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_backup.head,info_zone + offset + pad_len - temp_backup.m_struct_size); while(temp_backup.head != FLASH_HEAD){ pad_len++; err_code = Zone_Read(info_zone + offset + pad_len - temp_backup.m_struct_size, (uint32_t*)&temp_backup.head, sizeof(temp_backup.head)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_backup.head,info_zone + offset + pad_len - temp_backup.m_struct_size); // nrf_delay_ms(5); } err_code = Zone_Write(backup_zone + offset + pad_len, (uint32_t*)&mBackup, sizeof(mBackup)); // if(err_code == ZONE_OP_SUCCESS)SEGGER_RTT_printf(0,"write zone forward ,mBackup.tail_crc16:0x%x\r\n",mBackup.tail_crc16); if(err_code != ZONE_OP_SUCCESS){ //如果写失败了 //擦除该区域 err_code = Zone_Erase(backup_zone); if(err_code != ZONE_OP_SUCCESS)return err_code; //写在开头 err_code = Zone_Write(backup_zone, (uint32_t*)&mBackup, sizeof(mBackup)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,"write zone all erase ,mBackup.tail_crc16:0x%x\r\n",mBackup.tail_crc16); } } return ZONE_OP_SUCCESS; } /** @brief 获取备份信息 @param 无 @return 错误代码 */ uint32_t Flash_GetBackup(FlashBackup_t *pbackup) { uint32_t err_code; uint32_t zone_bytes; FlashBackup_t temp_backup; int32_t offset; uint16_t crc; uint8_t tail_h; memset(&temp_backup,0,sizeof(temp_backup)); err_code = Zone_GetByteSize(backup_zone, &zone_bytes); if(err_code != ZONE_OP_SUCCESS)return err_code; //从区域尾开始找起,找到最新的帧尾 for(offset = zone_bytes - 1; offset >= 0; offset--) { err_code = Zone_Read(backup_zone + offset, (uint32_t*)&tail_h, 1); if(err_code != ZONE_OP_SUCCESS)return err_code; if(tail_h == FLASH_TAIL_H)break; } //意味着整个区域是干净的 if(offset < 0){ memset(pbackup,0,sizeof(FlashBackup_t)); pbackup->head = FLASH_HEAD; pbackup->m_struct_size = sizeof(FlashBackup_t); //这里是包括填充字节的 crc = CalCrc(0, (char*)pbackup, sizeof(FlashBackup_t));//计算得到的16位CRC校验码,这里注意,有可能会将填充的字节也拿来做运算 pbackup->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc; //这里最后才加,是因为不知道填充字节的个数 // SEGGER_RTT_printf(0,"read zone all clear,pbackup->tail_crc16:0x%x\r\n",pbackup->tail_crc16); return ZONE_OP_SUCCESS; } //这里要偏移才能对齐成员 offset++; //获取最新的帧尾 err_code = Zone_Read(backup_zone + offset - sizeof(temp_backup.tail_crc16), (uint32_t*)&temp_backup.tail_crc16, sizeof(temp_backup.tail_crc16)); if(err_code != ZONE_OP_SUCCESS)return err_code; //获取最新的帧长度 err_code = Zone_Read(backup_zone + offset - sizeof(temp_backup.tail_crc16) - sizeof(temp_backup.m_struct_size) , (uint32_t*)&temp_backup.m_struct_size, sizeof(temp_backup.m_struct_size)); if(err_code != ZONE_OP_SUCCESS)return err_code; //因为结构体强制4字节对齐缘故,所以tail_crc16未必是真实存储的帧尾,后面可能带一些数据为0的填充字节。所以要做校准。 // uint32_t pad_len = temp_backup.m_struct_size - ((uint32_t)&temp_backup.tail_crc16 + sizeof(temp_backup.tail_crc16) - (uint32_t)&temp_backup.head); uint32_t pad_len = 0; SEGGER_RTT_printf(0,"back up info_zone:0x%x offset:%d pad_len:%d temp_backup.m_struct_size:%d\n",info_zone,offset,pad_len,temp_backup.m_struct_size); if(offset + pad_len < temp_backup.m_struct_size)pad_len = temp_backup.m_struct_size - offset; err_code = Zone_Read(info_zone + offset + pad_len - temp_backup.m_struct_size, (uint32_t*)&temp_backup.head, sizeof(temp_backup.head)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_backup.head,info_zone + offset + pad_len - temp_backup.m_struct_size); while(temp_backup.head != FLASH_HEAD){ pad_len++; err_code = Zone_Read(info_zone + offset + pad_len - temp_backup.m_struct_size, (uint32_t*)&temp_backup.head, sizeof(temp_backup.head)); if(err_code != ZONE_OP_SUCCESS)return err_code; // SEGGER_RTT_printf(0,">>>>>>p_head:0x%x,addr:0x%x\n",temp_backup.head,info_zone + offset + pad_len - temp_backup.m_struct_size); // nrf_delay_ms(5); } // SEGGER_RTT_printf(0,"read pad_len 0x%x\r\n",pad_len); //获取最新的帧 err_code = Zone_Read(backup_zone + offset + pad_len - temp_backup.m_struct_size , (uint32_t*)&temp_backup, temp_backup.m_struct_size - sizeof(temp_backup.tail_crc16)-sizeof(temp_backup.m_struct_size)-pad_len); if(err_code != ZONE_OP_SUCCESS)return err_code; //校验数据 FlashBackup_t crc_buf;//单纯做一个缓冲区 memset(&crc_buf,0,sizeof(crc_buf)); char *buf = (char*)&crc_buf; //获取成员head ~ m_struct_size memcpy(buf,&temp_backup,temp_backup.m_struct_size - sizeof(temp_backup.tail_crc16)-sizeof(temp_backup.m_struct_size)-pad_len); memcpy(buf + temp_backup.m_struct_size - sizeof(temp_backup.tail_crc16)-sizeof(temp_backup.m_struct_size)-pad_len,(uint32_t*)&temp_backup.m_struct_size,sizeof(temp_backup.m_struct_size)); //计算得到的16位CRC校验码 crc = CalCrc(0, buf, temp_backup.m_struct_size); if(crc == (temp_backup.tail_crc16 & 0xFFFF)){ // SEGGER_RTT_printf(0,"read crc success :0x%x 0x%x \r\n",crc,temp_backup.tail_crc16 & 0xFFFF); temp_backup.head = FLASH_HEAD; temp_backup.m_struct_size = sizeof(temp_backup); temp_backup.tail_crc16 = 0; crc = CalCrc(0, (char*)&temp_backup, sizeof(temp_backup));//计算得到的16位CRC校验码 temp_backup.tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc; *pbackup = temp_backup;//校验通过 } else{ //校验没通过 // SEGGER_RTT_printf(0,"read crc fail :0x%x 0x%x \r\n",crc,temp_backup.tail_crc16 & 0xFFFF); memset(pbackup,0,sizeof(FlashBackup_t)); pbackup->head = FLASH_HEAD; pbackup->m_struct_size = sizeof(FlashBackup_t); crc = CalCrc(0, (char*)pbackup, sizeof(FlashBackup_t));//计算得到的16位CRC校验码 pbackup->tail_crc16 = ((uint32_t)(FLASH_TAIL_H << 8 | FLASH_TAIL_L) << 16) | crc; err_code = Zone_Erase(backup_zone); if(err_code != ZONE_OP_SUCCESS)return err_code; } return ZONE_OP_SUCCESS; } /** @brief 保存日志信息 @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. @param[in] pc The program counter of the instruction that triggered the fault, or 0 if unavailable. @param[in] info Optional additional information regarding the fault. The value of the @p id parameter dictates how to interpret this parameter. Refer to the documentation for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for details about interpreting @p info. @return 错误代码 */ uint32_t Flash_SaveLog(uint32_t id, uint32_t pc, uint32_t info) { memset((uint8_t*)(&mFlash.mFlashLog),0,sizeof(FlashLog)); mFlash.mFlashLog.Errorflag =1; switch (id) { #if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT case NRF_FAULT_ID_SD_ASSERT: memcpy(mFlash.mFlashLog.logData,"SD: ASSERTION FAILED\r\n",MaxLength(sizeof("SD: ASSERTION FAILED\r\n"),sizeof(mFlash.mFlashLog.logData))); break; case NRF_FAULT_ID_APP_MEMACC: memcpy(mFlash.mFlashLog.logData,"SD: INVALID MEMORY ACCESS\r\n",MaxLength(sizeof("SD: INVALID MEMORY ACCESS\r\n"),sizeof(mFlash.mFlashLog.logData))); break; #endif case NRF_FAULT_ID_SDK_ASSERT: { assert_info_t * p_info = (assert_info_t *)info; sprintf((char *)mFlash.mFlashLog.logData,"ASSERTION FAILED %s:%u\r\n", p_info->p_file_name, p_info->line_num); break; } case NRF_FAULT_ID_SDK_ERROR: { error_info_t * p_info = (error_info_t *)info; sprintf((char *)mFlash.mFlashLog.logData,"error:%u,%s:%u\r\n", p_info->err_code, p_info->p_file_name, p_info->line_num); SEGGER_RTT_printf(0,">>>>>err code :%d,%s",p_info->err_code,mFlash.mFlashLog.logData); break; } default: sprintf((char *)mFlash.mFlashLog.logData,"UNKNOWN FAULT 0x%08X\n", pc); break; } return Flash_SaveInfomation(); } /** @brief 返回主机标志位 @param 无 @return 主机标志位 */ uint8_t Get_isHost(void) { return mFlash.isHost; } /** @brief 测试halflash接口 @param 无 @return 无 */ void TestHalFlashInterface(void) { Fstorage_FlashInit(); SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_INFO_PAGENUM, &info_zone):%d\n",Zone_Alloca(FLASH_ADDR_INFO_PAGENUM, &info_zone)); SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_STEP_PAGENUM, &step_zone):%d\n",Zone_Alloca(FLASH_ADDR_STEP_PAGENUM, &step_zone)); SEGGER_RTT_printf(0,"Zone_Alloca(FLASH_ADDR_BACKUP_PAGENUM, &backup_zone):%d\n",Zone_Alloca(FLASH_ADDR_BACKUP_PAGENUM, &backup_zone)); SEGGER_RTT_printf(0,"Flash_GetInfomation(&mFlash):%d \n",Flash_GetInfomation(&mFlash)); SEGGER_RTT_printf(0,"Flash_GetInfomation(&mBackup):%d \n",Flash_GetBackup(&mBackup)); uint32_t i; // Flash_t m_testflash; // FlashBackup_t m_testbackup; // //测试基本信息和备份信息的写入和读取 // for(i=0;i<10000;i++) // { // mFlash.mStep.num = i; // SEGGER_RTT_printf(0,"Flash_SaveInfomation[%d]:%d \n",i,Flash_SaveInfomation()); // // mBackup.hardVersion = i; // SEGGER_RTT_printf(0,"Flash_SaveBackup[%d]:%d \n",i,Flash_SaveBackup()); // } // // SEGGER_RTT_printf(0,"Flash_GetInfomation[%d]:%d \n",i,Flash_GetInfomation(&m_testflash)); // SEGGER_RTT_printf(0,"m_testflash:%d \n",m_testflash.mStep.num); // // SEGGER_RTT_printf(0,"Flash_GetBackup[%d]:%d \n",i,Flash_GetBackup(&m_testbackup)); // SEGGER_RTT_printf(0,"m_testbackup:%d \n",m_testbackup.hardVersion); //测试步数信息的写入和读取 for(i=0;i<(PAGE_INT_SIZE * FLASH_ADDR_STEP_PAGENUM+100);i++) { mFlash.mStep.stepCur[0] = 0; mFlash.mStep.stepCur[1] = i; SEGGER_RTT_printf(0,"Flash_SaveStep[%d]:%d \n\n",i,Flash_SaveStep()); } uint8_t checkflash[4] = {0}; for(i=0;i<(PAGE_INT_SIZE * FLASH_ADDR_STEP_PAGENUM);i+=4) { // Zone_Read(step_zone + i, (uint32_t*)&step, 4); // SEGGER_RTT_printf(0,"step[%d]:0x%x ",i,step); Zone_Read(step_zone + i,(uint32_t*)&checkflash[0], 4); SEGGER_RTT_printf(0,"checkflash[%d]:%02x,%02x,%02x,%02x ",i,checkflash[0],checkflash[1],checkflash[2],checkflash[3]); if(i%5 == 0)SEGGER_RTT_printf(0,"\n"); nrf_delay_ms(5); } ////uint32_t Flash_SaveStep(void); //////存储基本信息 ////uint32_t Flash_SaveInfomation(void); //////存储备份信息 ////uint32_t Flash_SaveBackup(void); //////获取基本信息 ////uint32_t Flash_GetInfomation(Flash_t *pflash); //////获取备份信息 ////uint32_t Flash_GetBackup(FlashBackup_t *pbackup); // // uint32_t i; // Flash_t m_testflash; // FlashBackup_t m_testbackup; // Fstorage_FlashInit(); // // #define INFO_PAGE_SIZE 1 // #define BACKUP_PAGE_SIZE 1 // #define STEP_PAGE_SIZE 2 // // static uint32_t info_index; // static uint32_t backup_index; // static uint32_t step_index; // // Zone_Init(INFO_PAGE_SIZE, &info_index); // Zone_Init(BACKUP_PAGE_SIZE, &backup_index); // Zone_Init(STEP_PAGE_SIZE, &step_index); // // SEGGER_RTT_printf(0,"info_index=%d backup_index=%d step_index=%d\n",info_index,backup_index,step_index); // // // // while(1); // // //测试基本信息和备份信息的写入和读取 // for(i=0;i<10000;i++) // { // mFlash.mStep.num = i; // SEGGER_RTT_printf(0,"Flash_SaveInfomation[%d]:%d \n",i,Flash_SaveInfomation()); // // mBackup.hardVersion = i; // SEGGER_RTT_printf(0,"Flash_SaveBackup[%d]:%d \n",i,Flash_SaveBackup()); // } // // SEGGER_RTT_printf(0,"Flash_GetInfomation[%d]:%d \n",i,Flash_GetInfomation(&m_testflash)); // SEGGER_RTT_printf(0,"m_testflash:%d \n",m_testflash.mStep.num); // // SEGGER_RTT_printf(0,"Flash_GetInfomation[%d]:%d \n",i,Flash_GetBackup(&m_testbackup)); // SEGGER_RTT_printf(0,"m_testbackup:%d \n",m_testbackup.hardVersion); // //测试步数信息的写入和读取 // for(i=0;i<1500;i++) // { // mFlash.mStep.num = i; // mFlash.mStep.stepCur[0] = i; // mFlash.mStep.stepCur[1] = i+i; // // SEGGER_RTT_printf(0,"Flash_SaveStep[%d]:%d \n\n",i,Flash_SaveStep()); // } // uint32_t checkflash[750]; // Read_N_Byte_flash(FLASH_ADDR_STEP , (uint32_t*)checkflash, sizeof(checkflash)); // // for(i=0;i<750;i++) // { // SEGGER_RTT_printf(0,"checkflash[%d]:0x%x ",i,checkflash[i]); // if(i%5 == 0)SEGGER_RTT_printf(0,"\n"); // nrf_delay_ms(5); // } SEGGER_RTT_printf(0,"TestHalFlashInterface done !!!!!!!\n"); }