#include #include #include #include #include #include #include "hal.h" #include "gps.h" #include "sdlog.h" #include "timesync.h" #include "fifo.h" static char LogFileName[32]; static FILE *LogFile = 0; static uint16_t LogDate = 0; // [~days] date = FatTime>>16 static TickType_t LogOpenTime; // [msec] when was the log file (re)open static const TickType_t LogReopen = 30000; // [msec] when to close and re-open the log file const size_t FIFOsize = 16384; static FIFO Log_FIFO; // 16K buffer for SD-log SemaphoreHandle_t Log_Mutex; // Mutex for the FIFO to prevent mixing between threads void Log_Write(char Byte) // write a byte into the log file buffer (FIFO) { if(Log_FIFO.Write(Byte)>0) return; // if byte written into FIFO return while(Log_FIFO.Write(Byte)<=0) vTaskDelay(1); } // wait while the FIFO is full - we have to use vTaskDelay not TaskYIELD int Log_Free(void) { return Log_FIFO.Free(); } // how much space left in the buffer static int Log_Open(void) { LogDate=GPS_FatTime>>16; // get the FAT-time date part int32_t Day = LogDate &0x1F; // get day, month, year int32_t Month = (LogDate>>5)&0x0F; int32_t Year = (LogDate>>9)-20; uint32_t Date = 0; if(Year>=0) Date = Day*10000 + Month*100 + Year; // create DDMMYY number for easy printout strcpy(LogFileName, "/sdcard/TR000000.LOG"); Format_UnsDec(LogFileName+10, Date, 6); // format the date into the log file name LogFile = fopen(LogFileName, "at"); if(LogFile==0) return -1; LogOpenTime=xTaskGetTickCount(); return 0; } // TaskYIELD would not give time to lower priority task like log-writer static void Log_Check(void) // time check: { if(!LogFile) return; // if last operation in error then don't do anything TickType_t TimeSinceOpen = xTaskGetTickCount()-LogOpenTime; // when did we (re)open the log file last time if(LogDate) { if(TimeSinceOpen=0) // get file attributes (maybe not really needed) { LogTime.actime = Time; // set access and modification times of the dest. file LogTime.modtime = Time; utime(LogFileName, &LogTime); } } static int WriteLog(size_t MaxBlock=FIFOsize/2) // process the queue of lines to be written to the log { if(!LogFile) return 0; int Count=0; for( ; ; ) { char *Block; size_t Len=Log_FIFO.getReadBlock(Block); if(Len==0) break; if(Len>MaxBlock) Len/=2; int Write=fwrite(Block, 1, Len, LogFile); Log_FIFO.flushReadBlock(Len); if(Write!=Len) { fclose(LogFile); LogFile=0; return -1; } Count+=Write; } return Count; } extern "C" void vTaskSDLOG(void* pvParameters) { Log_FIFO.Clear(); for( ; ; ) { if(!SD_isMounted()) { vTaskDelay(5000); SD_Mount(); continue; } if(!LogFile) { Log_Open(); if(!LogFile) { SD_Unmount(); vTaskDelay(1000); continue; } } if(Log_FIFO.Full()0); if(Write<0) { SD_Unmount(); vTaskDelay(1000); continue; } // if(Write==0) vTaskDelay(100); Log_Check(); } }