traceptp.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*!
  2. * Copyright (C) Fraunhofer-Institut for Photonic Microsystems (IPMS)
  3. * Maria-Reiche-Str. 2
  4. * 01109 Dresden
  5. *
  6. * Unauthorized copying of this file, via any medium is strictly prohibited
  7. * Proprietary and confidential
  8. *
  9. * \file traceptp.c
  10. * \author zimmerli
  11. * \date 2020-01-30
  12. * \brief PTP trace tool
  13. *
  14. */
  15. #include <kernel/base/klibc.h>
  16. #include "traceptp.h"
  17. #include "tsn_ptp_stack.h"
  18. #include <string.h>
  19. // ----------------------------------------------------------------
  20. #define SZ_PER_ENTRY 32
  21. #define CMD_LOG_TX 1
  22. #define CMD_LOG_TX_DONE 2
  23. #define CMD_LOG_RX 3
  24. #define CMD_LOG_TMR 4
  25. #define CMD_LOG_ROLE 5
  26. typedef struct {
  27. int64_t localtime;
  28. uint32_t stamp_sec;
  29. uint32_t stamp_nsec;
  30. uint16_t cmd;
  31. uint8_t msgtype;
  32. uint8_t timerid;
  33. uint16_t seqid;
  34. } trace_entry_t;
  35. typedef struct {
  36. uint32_t baseaddr;
  37. uint32_t ports;
  38. uint32_t entries;
  39. struct rtc_s *rtc;
  40. uint32_t port_wp[TSN_PTP_CFG_PORTNUM]; // write pointer per port
  41. uint8_t disable; // disable for printing
  42. } trace_ptp_t;
  43. trace_ptp_t _ptp_trace = { 0 };
  44. static trace_entry_t *_getNextEntry(uint16_t portnum);
  45. static const char *_strTmr(uint8_t timerid);
  46. static const char *_strMsgType(uint8_t msgtype);
  47. //ERSTMAL
  48. static const char *PTPTRC_CONTEXT = "PTPTRC";
  49. // ----------------------------------------------------------------
  50. void traceptp_init(addr_t baseaddr, uint32_t ports, uint32_t entries, struct rtc_s *rtc)
  51. {
  52. // each entry will require 32 byte
  53. // 1 ringbuffer per port
  54. // ports limited to TSN_PTP_CFG_PORTNUM
  55. uint32_t portidx;
  56. uint32_t size;
  57. if (ports > TSN_PTP_CFG_PORTNUM)
  58. ports = TSN_PTP_CFG_PORTNUM;
  59. _ptp_trace.baseaddr = baseaddr;
  60. _ptp_trace.ports = ports;
  61. _ptp_trace.entries = entries;
  62. _ptp_trace.rtc = rtc;
  63. _ptp_trace.disable = 0;
  64. for (portidx = 0; portidx < TSN_PTP_CFG_PORTNUM; ++portidx) {
  65. _ptp_trace.port_wp[portidx] = 0;
  66. }
  67. kassert(SZ_PER_ENTRY >= sizeof(trace_entry_t));
  68. size = ports * entries * SZ_PER_ENTRY;
  69. memset((void *)baseaddr, 0, size);
  70. logk(LOG_ALWAYS, PTPTRC_CONTEXT, "PTP trace initialized (baseaddr=0x%08X size=%d)\n", baseaddr, size);
  71. }
  72. void traceptp_print(uint16_t portnum)
  73. {
  74. uint32_t idx;
  75. addr_t addr;
  76. trace_entry_t *p;
  77. int64_t localtime;
  78. int32_t sec, usec;
  79. if (!_ptp_trace.baseaddr)
  80. return; // not initialized
  81. if (!portnum || (portnum > _ptp_trace.ports))
  82. return;
  83. _ptp_trace.disable = 1;
  84. logk(LOG_ALWAYS, PTPTRC_CONTEXT, "Trace port %d (wp=%d, entries=%d)\n", portnum, _ptp_trace.port_wp[portnum - 1], _ptp_trace.entries);
  85. addr = _ptp_trace.baseaddr + _ptp_trace.entries * SZ_PER_ENTRY * (portnum - 1);
  86. for (idx = 0; idx < _ptp_trace.entries; ++idx) {
  87. p = (trace_entry_t *)addr;
  88. sec = (int32_t)(p->localtime / NSEC_PER_SEC);
  89. localtime = (int64_t)(sec) * (int64_t)NSEC_PER_SEC;
  90. localtime = (p->localtime - localtime) / 1000LL;
  91. usec = (int32_t)localtime;
  92. // print entry
  93. if (p->cmd != 0)
  94. logs(LOG_ALWAYS, PTPTRC_CONTEXT, "[%03d] %2d.%06d ", idx, sec, usec);
  95. if (p->cmd == CMD_LOG_TX)
  96. loge(LOG_ALWAYS, "tx ---> %s (s=%5d)\n", _strMsgType(p->msgtype), p->seqid);
  97. else if (p->cmd == CMD_LOG_TX_DONE)
  98. loge(LOG_ALWAYS, "tx done %s %d.%06d\n", _strMsgType(p->msgtype), p->stamp_sec, p->stamp_nsec / 1000);
  99. else if (p->cmd == CMD_LOG_RX)
  100. loge(LOG_ALWAYS, "rx <--- %s (s=%5d) %d.%06d\n", _strMsgType(p->msgtype), p->seqid, p->stamp_sec, p->stamp_nsec / 1000);
  101. else if (p->cmd == CMD_LOG_TMR)
  102. loge(LOG_ALWAYS, "Tmr %s\n", _strTmr(p->timerid));
  103. else if (p->cmd == CMD_LOG_ROLE) {
  104. uint8_t *pGmid = (uint8_t *)(addr + 8); //TODO magic number
  105. //uint8_t *pGmid = (uint8_t*)(&p->stamp_nsec + 2); //???
  106. logc(LOG_ALWAYS, "RoleSel GM");
  107. for (uint8_t gmbyte = 0; gmbyte < sizeof(clock_id); ++gmbyte)
  108. logc(LOG_ALWAYS, " %02X", pGmid[gmbyte]);
  109. //for (gmbyte=0; gmbyte<8; ++gmbyte) logc(LOG_ALWAYS, " %02X", MEM8(addr + 8 + gmbyte));
  110. loge(LOG_ALWAYS, "\n");
  111. }
  112. addr += SZ_PER_ENTRY;
  113. }
  114. _ptp_trace.disable = 0;
  115. }
  116. void traceptp_tx(uint16_t portnum, uint8_t msgtype, uint16_t seqid)
  117. {
  118. trace_entry_t *p = _getNextEntry(portnum);
  119. if (p == NULL)
  120. return;
  121. p->cmd = CMD_LOG_TX;
  122. p->msgtype = msgtype;
  123. p->seqid = seqid;
  124. }
  125. void traceptp_tx_done(uint16_t portnum, uint8_t msgtype, uint32_t sec, uint32_t nsec)
  126. {
  127. trace_entry_t *p = _getNextEntry(portnum);
  128. if (p == NULL)
  129. return;
  130. p->cmd = CMD_LOG_TX_DONE;
  131. p->msgtype = msgtype;
  132. p->stamp_sec = sec;
  133. p->stamp_nsec = nsec;
  134. }
  135. void traceptp_rx(uint16_t portnum, addr_t addr, uint32_t len, uint32_t sec, uint32_t nsec)
  136. {
  137. (void)len;
  138. uint8_t msgtype;
  139. uint16_t seqid;
  140. trace_entry_t *p = _getNextEntry(portnum);
  141. if (p == NULL)
  142. return;
  143. msgtype = (*(uint8_t *)(addr)); // 1st byte
  144. seqid = klibc_ntohs((*(uint16_t *)(addr + 30)));
  145. p->cmd = CMD_LOG_RX;
  146. p->msgtype = msgtype;
  147. p->seqid = seqid;
  148. p->stamp_sec = sec;
  149. p->stamp_nsec = nsec;
  150. }
  151. void traceptp_tmr(uint16_t portnum, uint8_t timer_id)
  152. {
  153. trace_entry_t *p = _getNextEntry(portnum);
  154. if (p == NULL)
  155. return;
  156. p->cmd = CMD_LOG_TMR;
  157. p->timerid = timer_id;
  158. }
  159. void traceptp_reselect(uint64_t gmid)
  160. {
  161. uint32_t portnum;
  162. trace_entry_t *p;
  163. for (portnum = 1; portnum <= _ptp_trace.ports; ++portnum) {
  164. p = _getNextEntry(portnum);
  165. if (!p)
  166. continue;
  167. p->cmd = CMD_LOG_ROLE;
  168. p->stamp_sec = gmid & 0xFFFFFFFF;
  169. p->stamp_nsec = gmid >> 32;
  170. }
  171. }
  172. // ----------------------------------------------------------------
  173. static trace_entry_t *_getNextEntry(uint16_t portnum)
  174. {
  175. trace_entry_t *p;
  176. uint32_t wp;
  177. addr_t addr;
  178. struct timespec64 localtime;
  179. int portindex;
  180. if (!_ptp_trace.baseaddr)
  181. return NULL; // not initialized
  182. if (_ptp_trace.disable)
  183. return NULL; // currently disabled
  184. // check portnum
  185. if ((portnum <= 0) || (portnum > _ptp_trace.ports))
  186. return NULL;
  187. portindex = portnum - 1;
  188. // calc addr && inc ptr
  189. portENTER_CRITICAL();
  190. wp = _ptp_trace.port_wp[portindex];
  191. _ptp_trace.port_wp[portindex]++;
  192. if (_ptp_trace.port_wp[portindex] >= _ptp_trace.entries) {
  193. _ptp_trace.port_wp[portindex] = 0;
  194. }
  195. portEXIT_CRITICAL();
  196. addr = _ptp_trace.baseaddr;
  197. addr += portindex * _ptp_trace.entries * SZ_PER_ENTRY;
  198. addr += wp * SZ_PER_ENTRY;
  199. p = (trace_entry_t *)addr;
  200. // prepare localtime of log
  201. rtc_get_local_time64(_ptp_trace.rtc, &localtime);
  202. p->localtime = timespec64_to_ns(&localtime);
  203. return p;
  204. }
  205. static char *_strTmrText[5] = { "tx-pd", "tx-annc", "tx-syn", "tmout-annc", "tmout-syn" };
  206. static const char *_strTmr(uint8_t timerid)
  207. {
  208. if (timerid >= 5)
  209. return "unknown";
  210. return _strTmrText[timerid];
  211. }
  212. static const char *_strMsgType(uint8_t msgtype)
  213. {
  214. msgtype &= PTP_MSGTYPE_MASK;
  215. switch (msgtype) {
  216. case PTP_MSGTYPE_SYNC:
  217. return "sync ";
  218. case PTP_MSGTYPE_PDELAY_REQ:
  219. return "pdreq";
  220. case PTP_MSGTYPE_PDELAY_RESP:
  221. return "pdrsp";
  222. case PTP_MSGTYPE_FOLLOWUP:
  223. return "fup ";
  224. case PTP_MSGTYPE_PDELAY_FUP:
  225. return "pdfup";
  226. case PTP_MSGTYPE_ANNOUNCE:
  227. return "annc ";
  228. case PTP_MSGTYPE_SIGNALING:
  229. return "sign ";
  230. }
  231. return "unknown";
  232. }