/***************************************************************************** Flash.c *****************************************************************************/ #define THIS_FILE_ID 20 /* Includes ------------------------------------------------------------------*/ #include "includes.h" SUT_STORAGE_FIFO sutStorageFiFo; void StorageFormat(void) { unsigned char buf[1]; int addr; SlwTrace(DEBUG,"Flash Format!!\r\n"); SPI_Flash_Erase_Chip(); SaveDeviceConfigToFlash(); sutStorageFiFo.in=0; sutStorageFiFo.out=0; sutStorageFiFo.len=0; for(addr=STORAGE_POS_START_ADDR;addrflag!=STORAGE_POS_FLAG || pPos->Mark!=STORAGE_POS_MARK){ //这种情况里应不存在,存在说明发生异常! //异常原因可能是Push写入时写到一半突然掉电,此时应该修正之 SlwTrace(DEBUG,"StorageFiFoPOP Exception!\r\n"); //printf("[%d]flag=%02X mark=%08lX\r\n",sutStorageFiFo.out,pPos->flag,pPos->Mark); memset((u8 *)pPos,0xff,STORAGE_POS_LEN); SPI_Flash_Write((u8 *)pPos,addr,STORAGE_POS_LEN); sutStorageFiFo.out=(sutStorageFiFo.out+1)%STORAGE_POS_COUNT_TOTAL; sutStorageFiFo.len--; return 0; } //移位 sutStorageFiFo.out=(sutStorageFiFo.out+1)%STORAGE_POS_COUNT_TOTAL; sutStorageFiFo.len--; //如果移动到新的SECTOR,并且in不在前一区,则将前一区擦除,下次重启才会刷新out if(sutStorageFiFo.out%STORAGE_POS_COUNT_SECTOR==0){ //获取out的前一区 sector=sutStorageFiFo.out/STORAGE_POS_COUNT_SECTOR; if(sector>0)sector--; else sector=STORAGE_POS_COUNT_TOTAL/STORAGE_POS_COUNT_SECTOR-1;//最后一个扇区 // out的前一个扇区 与 in所在扇区 不一样,才允许擦除 if(sector!=(sutStorageFiFo.in/STORAGE_POS_COUNT_SECTOR)){ sector+=STORAGE_POS_START_ADDR/4096; SPI_Flash_Erase_Sector(sector); // printf("Erase[%d]\r\n",sector); // SPI_Flash_Read(SPI_FLASH_BUF,sector*4096,4096);//读出整个扇区的内容 // for(i=0;i<4096;i++){ // if(SPI_FLASH_BUF[i]!=0xFF)break; // } // if(i<4096)printf("Erase Fail!\r\n"); } } return 1; } /****************************************************************** 存储Pos记录到FIFO中 如果已满,自动抛弃最早的数据 *******************************************************************/ int StorageFiFoPush(SUT_POSITION *pRecord) { SUT_POSITION pos; int Sector; int len; int addr; //预留64个元素,少于64则认为满,移除最早的数据,每次移除N个,N取决于当前out所在sector占用元素个数 if (STORAGE_POS_COUNT_TOTAL-sutStorageFiFo.len<64){ //算出当前out位置所在的Sector有len个元素,格式化这个Sector后需要将out移len位 // |FF FF FF XX | XX XX XX XX |XX XX XX FF| // out=3 in=11 (11+4)%12==3 // len=4-(3%4)=1 // |XX FF FF FF | FF XX XX XX |XX XX XX XX| // out=5 in=1 (1+4)%12==5 // len=4-(5%4)=3 // |FF FF FF FF | XX XX XX XX |XX XX XX XX| // out=4 in=0 (0+4)%12==4 // len=4-(4%4)=4 len=STORAGE_POS_COUNT_SECTOR-(sutStorageFiFo.out%STORAGE_POS_COUNT_SECTOR); //|FF FF AA AA| AA AA... //算出当前out位置所处的Sector地址,对其格式化 Sector=(STORAGE_POS_START_ADDR+sutStorageFiFo.out*STORAGE_POS_LEN)/4096; SPI_Flash_Erase_Sector(Sector); //对out进行移位 sutStorageFiFo.out=(sutStorageFiFo.out+len)%STORAGE_POS_COUNT_TOTAL; sutStorageFiFo.len-=len; //printf("\r\nAutoRM[%d]\r\n",len); } //入队列 //printf("Push[%d]\r\n",sutStorageFiFo.in); addr=STORAGE_POS_START_ADDR+sutStorageFiFo.in*STORAGE_POS_LEN; //SPI_Flash_Write((u8 *)pRecord,addr,STORAGE_POS_LEN); //先读出检查 // SPI_Flash_Read((u8 *)&pos,addr,STORAGE_POS_LEN); // if(pos.flag!=0xff || pos.Mark != 0xffffffff){ // printf("[%d]error!\r\n",sutStorageFiFo.in); // printf("flag=%X mark=%lX\r\n",pos.flag,pos.Mark); // } SPI_Flash_Write_NoCheck((u8 *)pRecord,addr,STORAGE_POS_LEN); sutStorageFiFo.in=(sutStorageFiFo.in+1)%STORAGE_POS_COUNT_TOTAL; sutStorageFiFo.len++; return 1; } /* 控制保存 */ void StorageCtrlSavePos(void) { char buf[20]; static unsigned short SaveCt=0; SUT_POSITION pos; if(sutFotaPara.fotaStatus!=FOTA_END)return; if(!RTC_Effective()){ SaveCt=sutDeviceConfig.SamplingInterval; return; } if(++SaveCt>=sutDeviceConfig.SamplingInterval){ SaveCt=0; }else return; memset(&pos,0,sizeof(SUT_POSITION)); pos.flag=STORAGE_POS_FLAG; pos.Mark=STORAGE_POS_MARK; RTC_Get(pos.Time); if(sutGpsInfo.isGpsValid)pos.Status.GNSS=1; else pos.Status.GNSS=0; pos.Status.ACC=1; pos.Status.BD=sutGpsInfo.isBDWork; pos.Status.GPS=sutGpsInfo.isGpsWork; pos.Status.West=sutGpsInfo.West; pos.Status.South=sutGpsInfo.South; pos.Latitude=sutGpsInfo.Latitude;//22620926;//114035268; //114.035268 pos.Longitude=sutGpsInfo.Longitude; //114035268;//22620926; //22.620926 pos.Speed=sutGpsInfo.Speed;//0; pos.Aspect=sutGpsInfo.Aspect;//123; pos.Altitude=sutGpsInfo.Altitude; pos.ExtraMsgId=0x3A;//水表项目固定0x3A pos.ExtraMsgLen=20;//水表项目暂时固定 20 StorageFiFoPush(&pos); sprintf(buf,"SavePos %d\r\n",sutStorageFiFo.len); SlwTrace(DEBUG,buf); } /* 测试 */ void StorageFiFoTest(void) { #if 1 int i,j; unsigned short r; SUT_POSITION pos; memset(&pos,0,sizeof(SUT_POSITION)); pos.flag=STORAGE_POS_FLAG; pos.Mark=STORAGE_POS_MARK; if(StorageFiFoPop(&pos))i=pos.Latitude; else i=0; r=i; while(1){ os_dly_wait(1); printf("\r\n<<[%03d] ",sutStorageFiFo.in); for(j=0;j>[%03d] ",sutStorageFiFo.out); for(j=0;j<10;j++){ if(StorageFiFoPop(&pos)){ printf("%5d ",pos.Latitude); }else{ printf("