targets/plc_debug.c
changeset 985 cd8dadcef426
parent 969 1950fe687dde
child 1074 92a009dc5826
equal deleted inserted replaced
984:2d03056993f6 985:cd8dadcef426
   302         *buffer = debug_buffer;
   302         *buffer = debug_buffer;
   303     }
   303     }
   304     return wait_error;
   304     return wait_error;
   305 }
   305 }
   306 
   306 
   307 
       
   308 /* LOGGING
       
   309 */
       
   310 
       
   311 #define LOG_LEVELS 4
       
   312 #define LOG_CRITICAL 0
       
   313 #define LOG_WARNING 1
       
   314 #define LOG_INFO 2
       
   315 #define LOG_DEBUG 3
       
   316 
       
   317 #ifndef LOG_BUFFER_SIZE
       
   318 #define LOG_BUFFER_SIZE (1<<14) /*16Ko*/
       
   319 #endif
       
   320 #define LOG_BUFFER_MASK (LOG_BUFFER_SIZE-1)
       
   321 static char LogBuff[LOG_LEVELS][LOG_BUFFER_SIZE];
       
   322 void inline copy_to_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){
       
   323     if(buffpos + size < LOG_BUFFER_SIZE){
       
   324         memcpy(&LogBuff[level][buffpos], buf, size);
       
   325     }else{
       
   326         uint32_t remaining = LOG_BUFFER_SIZE - buffpos - 1; 
       
   327         memcpy(&LogBuff[level][buffpos], buf, remaining);
       
   328         memcpy(LogBuff[level], buf + remaining, size - remaining);
       
   329     }
       
   330 }
       
   331 void inline copy_from_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){
       
   332     if(buffpos + size < LOG_BUFFER_SIZE){
       
   333         memcpy(buf, &LogBuff[level][buffpos], size);
       
   334     }else{
       
   335         uint32_t remaining = LOG_BUFFER_SIZE - buffpos; 
       
   336         memcpy(buf, &LogBuff[level][buffpos], remaining);
       
   337         memcpy(buf + remaining, LogBuff[level], size - remaining);
       
   338     }
       
   339 }
       
   340 
       
   341 /* Log buffer structure
       
   342 
       
   343  |<-Tail1.msgsize->|<-sizeof(mTail)->|<--Tail2.msgsize-->|<-sizeof(mTail)->|...
       
   344  |  Message1 Body  |      Tail1      |   Message2 Body   |      Tail2      |
       
   345 
       
   346 */
       
   347 typedef struct {
       
   348     uint32_t msgidx;
       
   349     uint32_t msgsize;
       
   350     unsigned long tick;
       
   351     IEC_TIME time;
       
   352 } mTail;
       
   353 
       
   354 /* Log cursor : 64b
       
   355    |63 ... 32|31 ... 0|
       
   356    | Message | Buffer |
       
   357    | counter | Index  | */
       
   358 static uint64_t LogCursor[LOG_LEVELS] = {0x0,0x0,0x0,0x0};
       
   359 
       
   360 /* Store one log message of give size */
       
   361 int LogMessage(uint8_t level, uint8_t* buf, uint32_t size){
       
   362     if(size < LOG_BUFFER_SIZE - sizeof(mTail)){
       
   363         uint32_t buffpos;
       
   364         uint64_t new_cursor, old_cursor;
       
   365 
       
   366         mTail tail;
       
   367         tail.msgsize = size;
       
   368         tail.tick = __tick;
       
   369         PLC_GetTime(&tail.time);
       
   370 
       
   371         /* We cannot increment both msg index and string pointer 
       
   372            in a single atomic operation but we can detect having been interrupted.
       
   373            So we can try with atomic compare and swap in a loop until operation
       
   374            succeeds non interrupted */
       
   375         do{
       
   376             old_cursor = LogCursor[level];
       
   377             buffpos = (uint32_t)old_cursor;
       
   378             tail.msgidx = (old_cursor >> 32); 
       
   379             new_cursor = ((uint64_t)(tail.msgidx + 1)<<32) 
       
   380                          | (uint64_t)((buffpos + size + sizeof(mTail)) & LOG_BUFFER_MASK);
       
   381         }while(AtomicCompareExchange64(
       
   382             (long long*)&LogCursor[level],
       
   383             (long long)old_cursor,
       
   384             (long long)new_cursor)!=old_cursor);
       
   385 
       
   386         copy_to_log(level, buffpos, buf, size);
       
   387         copy_to_log(level, (buffpos + size) & LOG_BUFFER_MASK, &tail, sizeof(mTail));
       
   388 
       
   389         return 1; /* Success */
       
   390     }else{
       
   391     	uint8_t mstr[] = "Logging error : message too big";
       
   392         LogMessage(LOG_CRITICAL, mstr, sizeof(mstr));
       
   393     }
       
   394     return 0;
       
   395 }
       
   396 
       
   397 uint32_t GetLogCount(uint8_t level){
       
   398     return (uint64_t)LogCursor[level] >> 32;
       
   399 }
       
   400 
       
   401 /* Return message size and content */
       
   402 uint32_t GetLogMessage(uint8_t level, uint32_t msgidx, char* buf, uint32_t max_size, uint32_t* tick, uint32_t* tv_sec, uint32_t* tv_nsec){
       
   403     uint64_t cursor = LogCursor[level];
       
   404     if(cursor){
       
   405         /* seach cursor */
       
   406         uint32_t stailpos = (uint32_t)cursor; 
       
   407         uint32_t smsgidx;
       
   408         mTail tail;
       
   409         tail.msgidx = cursor >> 32;
       
   410         tail.msgsize = 0;
       
   411 
       
   412         /* Message search loop */
       
   413         do {
       
   414             smsgidx = tail.msgidx;
       
   415             stailpos = (stailpos - sizeof(mTail) - tail.msgsize ) & LOG_BUFFER_MASK;
       
   416             copy_from_log(level, stailpos, &tail, sizeof(mTail));
       
   417         }while((tail.msgidx == smsgidx - 1) && (tail.msgidx > msgidx));
       
   418 
       
   419         if(tail.msgidx == msgidx){
       
   420             uint32_t sbuffpos = (stailpos - tail.msgsize ) & LOG_BUFFER_MASK; 
       
   421             uint32_t totalsize = tail.msgsize;
       
   422             *tick = tail.tick; 
       
   423             *tv_sec = tail.time.tv_sec; 
       
   424             *tv_nsec = tail.time.tv_nsec; 
       
   425             copy_from_log(level, sbuffpos, buf, 
       
   426                           totalsize > max_size ? max_size : totalsize);
       
   427             return totalsize;
       
   428         }
       
   429     }
       
   430     return 0;
       
   431 }