SWO.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /*
  2. * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * ----------------------------------------------------------------------
  19. *
  20. * $Date: 20. May 2015
  21. * $Revision: V1.10
  22. *
  23. * Project: CMSIS-DAP Source
  24. * Title: SWO.c CMSIS-DAP SWO I/O
  25. *
  26. *---------------------------------------------------------------------------*/
  27. #include "DAP_config.h"
  28. #include "DAP.h"
  29. #if (SWO_UART != 0)
  30. #include "Driver_USART.h"
  31. #endif
  32. #if (SWO_UART != 0)
  33. #ifndef USART_PORT
  34. #define USART_PORT 0 /* USART Port Number */
  35. #endif
  36. // USART Driver
  37. #define _USART_Driver_(n) Driver_USART##n
  38. #define USART_Driver_(n) _USART_Driver_(n)
  39. extern ARM_DRIVER_USART USART_Driver_(USART_PORT);
  40. #define pUSART (&USART_Driver_(USART_PORT))
  41. static uint8_t USART_Ready;
  42. #endif /* (SWO_UART != 0) */
  43. #if ((SWO_UART != 0) || (SWO_MANCHESTER != 0))
  44. // Trace State
  45. static uint8_t TraceTransport = 0U; /* Trace Transport */
  46. static uint8_t TraceMode = 0U; /* Trace Mode */
  47. static uint8_t TraceStatus = 0U; /* Trace Status without Errors */
  48. static uint8_t TraceError[2] = {0U, 0U}; /* Trace Error flags (banked) */
  49. static uint8_t TraceError_n = 0U; /* Active Trace Error bank */
  50. // Trace Buffer
  51. static uint8_t TraceBuf[SWO_BUFFER_SIZE]; /* Trace Buffer (must be 2^n) */
  52. static volatile uint32_t TraceIn = 0U; /* Incoming Trace Index */
  53. static volatile uint32_t TraceOut = 0U; /* Outgoing Trace Index */
  54. static volatile uint32_t TracePending = 0U; /* Pending Trace Count */
  55. // Trace Helper functions
  56. static void ClearTrace (void);
  57. static uint32_t GetTraceSpace (void);
  58. static uint32_t GetTraceCount (void);
  59. static uint8_t GetTraceStatus (void);
  60. static void SetTraceError (uint8_t flag);
  61. #if (SWO_UART != 0)
  62. // USART Driver Callback function
  63. // event: event mask
  64. static void USART_Callback (uint32_t event) {
  65. uint32_t count;
  66. if (event & ARM_USART_EVENT_RECEIVE_COMPLETE) {
  67. TracePending = 0U;
  68. TraceIn += pUSART->GetRxCount();
  69. count = GetTraceSpace();
  70. if (count != 0U) {
  71. pUSART->Receive(&TraceBuf[TraceIn & (SWO_BUFFER_SIZE-1U)], count);
  72. } else {
  73. TraceStatus = DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED;
  74. }
  75. }
  76. if (event & ARM_USART_EVENT_RX_OVERFLOW) {
  77. SetTraceError(DAP_SWO_BUFFER_OVERRUN);
  78. }
  79. if (event & (ARM_USART_EVENT_RX_BREAK |
  80. ARM_USART_EVENT_RX_FRAMING_ERROR |
  81. ARM_USART_EVENT_RX_PARITY_ERROR)) {
  82. SetTraceError(DAP_SWO_STREAM_ERROR);
  83. }
  84. }
  85. // Enable or disable UART SWO Mode
  86. // enable: enable flag
  87. // return: 1 - Success, 0 - Error
  88. __weak uint32_t UART_SWO_Mode (uint32_t enable) {
  89. int32_t status;
  90. USART_Ready = 0U;
  91. if (enable) {
  92. status = pUSART->Initialize(USART_Callback);
  93. if (status != ARM_DRIVER_OK) { return (0U); }
  94. status = pUSART->PowerControl(ARM_POWER_FULL);
  95. if (status != ARM_DRIVER_OK) {
  96. pUSART->Uninitialize();
  97. return (0U);
  98. }
  99. } else {
  100. pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
  101. pUSART->PowerControl(ARM_POWER_OFF);
  102. pUSART->Uninitialize();
  103. }
  104. return (1U);
  105. }
  106. // Configure UART SWO Baudrate
  107. // baudrate: requested baudrate
  108. // return: actual baudrate or 0 when not configured
  109. __weak uint32_t UART_SWO_Baudrate (uint32_t baudrate) {
  110. int32_t status;
  111. uint32_t count;
  112. if (baudrate > SWO_UART_MAX_BAUDRATE) {
  113. baudrate = SWO_UART_MAX_BAUDRATE;
  114. }
  115. if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
  116. pUSART->Control(ARM_USART_CONTROL_RX, 0U);
  117. if (pUSART->GetStatus().rx_busy) {
  118. TracePending = 0U;
  119. TraceIn += pUSART->GetRxCount();
  120. pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
  121. }
  122. }
  123. status = pUSART->Control(ARM_USART_MODE_ASYNCHRONOUS |
  124. ARM_USART_DATA_BITS_8 |
  125. ARM_USART_PARITY_NONE |
  126. ARM_USART_STOP_BITS_1,
  127. baudrate);
  128. if (status == ARM_DRIVER_OK) {
  129. USART_Ready = 1U;
  130. } else {
  131. USART_Ready = 0U;
  132. baudrate = 0U;
  133. }
  134. if ((TraceStatus & DAP_SWO_CAPTURE_ACTIVE) && USART_Ready) {
  135. pUSART->Control(ARM_USART_CONTROL_RX, 1U);
  136. count = GetTraceSpace();
  137. if (count != 0U) {
  138. pUSART->Receive(&TraceBuf[TraceIn & (SWO_BUFFER_SIZE-1U)], count);
  139. } else {
  140. TraceStatus = DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED;
  141. }
  142. }
  143. return (baudrate);
  144. }
  145. // Control UART SWO Capture
  146. // active: active flag
  147. // return: 1 - Success, 0 - Error
  148. __weak uint32_t UART_SWO_Control (uint32_t active) {
  149. int32_t status;
  150. if (active) {
  151. if (!USART_Ready) { return (0U); }
  152. status = pUSART->Control(ARM_USART_CONTROL_RX, 1U);
  153. if (status != ARM_DRIVER_OK) { return (0U); }
  154. status = pUSART->Receive(TraceBuf, SWO_BUFFER_SIZE);
  155. if (status != ARM_DRIVER_OK) { return (0U); }
  156. } else {
  157. pUSART->Control(ARM_USART_CONTROL_RX, 0U);
  158. if (pUSART->GetStatus().rx_busy) {
  159. TracePending = 0U;
  160. TraceIn += pUSART->GetRxCount();
  161. pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
  162. }
  163. }
  164. return (1U);
  165. }
  166. // Start UART SWO Capture
  167. // buf: pointer to buffer for capturing
  168. // count: number of bytes to capture
  169. __weak void UART_SWO_Capture (uint8_t *buf, uint32_t count) {
  170. pUSART->Receive(buf, count);
  171. }
  172. // Update UART SWO Trace Info
  173. __weak void UART_SWO_Update (void) {
  174. TracePending = pUSART->GetRxCount();
  175. }
  176. #endif /* (SWO_UART != 0) */
  177. #if (SWO_MANCHESTER != 0)
  178. // Enable or disable Manchester SWO Mode
  179. // enable: enable flag
  180. // return: 1 - Success, 0 - Error
  181. __weak uint32_t Manchester_SWO_Mode (uint32_t enable) {
  182. return (0U);
  183. }
  184. // Configure Manchester SWO Baudrate
  185. // baudrate: requested baudrate
  186. // return: actual baudrate or 0 when not configured
  187. __weak uint32_t Manchester_SWO_Baudrate (uint32_t baudrate) {
  188. return (0U);
  189. }
  190. // Control Manchester SWO Capture
  191. // active: active flag
  192. // return: 1 - Success, 0 - Error
  193. __weak uint32_t Manchester_SWO_Control (uint32_t active) {
  194. return (0U);
  195. }
  196. // Start Manchester SWO Capture
  197. // buf: pointer to buffer for capturing
  198. // count: number of bytes to capture
  199. __weak void Manchester_SWO_Capture (uint8_t *buf, uint32_t count) {
  200. }
  201. // Update Manchester SWO Trace Info
  202. __weak void Manchester_SWO_Update (void) {
  203. }
  204. #endif /* (SWO_MANCHESTER != 0) */
  205. // Clear Trace Errors and Data
  206. static void ClearTrace (void) {
  207. TraceError[0] = 0U;
  208. TraceError[1] = 0U;
  209. TraceError_n = 0U;
  210. TraceIn = 0U;
  211. TraceOut = 0U;
  212. TracePending = 0U;
  213. }
  214. // Get Trace Space
  215. // return: number of contiguous free bytes in trace buffer
  216. static uint32_t GetTraceSpace (void) {
  217. uint32_t index;
  218. uint32_t limit;
  219. uint32_t count;
  220. index = TraceIn & (SWO_BUFFER_SIZE-1U);
  221. limit = SWO_BUFFER_SIZE - index;
  222. count = SWO_BUFFER_SIZE - (TraceIn - TraceOut);
  223. if (count > limit) {
  224. count = limit;
  225. }
  226. return (count);
  227. }
  228. // Get Trace Count
  229. // return: number of available data bytes in trace buffer
  230. static uint32_t GetTraceCount (void) {
  231. uint32_t count;
  232. if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) {
  233. count = (TraceIn - TraceOut) + TracePending;
  234. if (TracePending == 0U) {
  235. count = TraceIn - TraceOut;
  236. }
  237. } else {
  238. count = TraceIn - TraceOut;
  239. }
  240. return (count);
  241. }
  242. // Get Trace Status (clear Error flags)
  243. // return: Trace Status (Active flag and Error flags)
  244. static uint8_t GetTraceStatus (void) {
  245. uint8_t status;
  246. uint32_t n;
  247. n = TraceError_n;
  248. TraceError_n ^= 1U;
  249. status = TraceStatus | TraceError[n];
  250. TraceError[n] = 0U;
  251. return (status);
  252. }
  253. // Set Trace Error flag(s)
  254. // flag: error flag(s) to set
  255. static void SetTraceError (uint8_t flag) {
  256. TraceError[TraceError_n] |= flag;
  257. }
  258. // Process SWO Transport command and prepare response
  259. // request: pointer to request data
  260. // response: pointer to response data
  261. // return: number of bytes in response (lower 16 bits)
  262. // number of bytes in request (upper 16 bits)
  263. uint32_t SWO_Transport (const uint8_t *request, uint8_t *response) {
  264. uint8_t transport;
  265. uint32_t result;
  266. if (!(TraceStatus & DAP_SWO_CAPTURE_ACTIVE)) {
  267. transport = *request;
  268. switch (transport) {
  269. case 0:
  270. case 1:
  271. TraceTransport = transport;
  272. result = 1U;
  273. break;
  274. default:
  275. result = 0U;
  276. break;
  277. }
  278. } else {
  279. result = 0U;
  280. }
  281. if (result != 0U) {
  282. *response = DAP_OK;
  283. } else {
  284. *response = DAP_ERROR;
  285. }
  286. return ((1U << 16) | 1U);
  287. }
  288. // Process SWO Mode command and prepare response
  289. // request: pointer to request data
  290. // response: pointer to response data
  291. // return: number of bytes in response (lower 16 bits)
  292. // number of bytes in request (upper 16 bits)
  293. uint32_t SWO_Mode (const uint8_t *request, uint8_t *response) {
  294. uint8_t mode;
  295. uint32_t result;
  296. mode = *request;
  297. switch (TraceMode) {
  298. #if (SWO_UART != 0)
  299. case DAP_SWO_UART:
  300. UART_SWO_Mode(0U);
  301. break;
  302. #endif
  303. #if (SWO_MANCHESTER != 0)
  304. case DAP_SWO_MANCHESTER:
  305. Manchester_SWO_Mode(0U);
  306. break;
  307. #endif
  308. default:
  309. break;
  310. }
  311. switch (mode) {
  312. case DAP_SWO_OFF:
  313. result = 1U;
  314. break;
  315. #if (SWO_UART != 0)
  316. case DAP_SWO_UART:
  317. result = UART_SWO_Mode(1U);
  318. break;
  319. #endif
  320. #if (SWO_MANCHESTER != 0)
  321. case DAP_SWO_MANCHESTER:
  322. result = Manchester_SWO_Mode(1U);
  323. break;
  324. #endif
  325. default:
  326. result = 0U;
  327. break;
  328. }
  329. if (result != 0U) {
  330. TraceMode = mode;
  331. } else {
  332. TraceMode = DAP_SWO_OFF;
  333. }
  334. TraceStatus = 0U;
  335. ClearTrace();
  336. if (result != 0U) {
  337. *response = DAP_OK;
  338. } else {
  339. *response = DAP_ERROR;
  340. }
  341. return ((1U << 16) | 1U);
  342. }
  343. // Process SWO Baudrate command and prepare response
  344. // request: pointer to request data
  345. // response: pointer to response data
  346. // return: number of bytes in response (lower 16 bits)
  347. // number of bytes in request (upper 16 bits)
  348. uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response) {
  349. uint32_t baudrate;
  350. baudrate = (*(request+0) << 0) |
  351. (*(request+1) << 8) |
  352. (*(request+2) << 16) |
  353. (*(request+3) << 24);
  354. switch (TraceMode) {
  355. #if (SWO_UART != 0)
  356. case DAP_SWO_UART:
  357. baudrate = UART_SWO_Baudrate(baudrate);
  358. break;
  359. #endif
  360. #if (SWO_MANCHESTER != 0)
  361. case DAP_SWO_MANCHESTER:
  362. baudrate = Manchester_SWO_Baudrate(baudrate);
  363. break;
  364. #endif
  365. default:
  366. baudrate = 0U;
  367. break;
  368. }
  369. if (baudrate == 0U) {
  370. TraceStatus = 0U;
  371. }
  372. *response++ = (uint8_t)(baudrate >> 0);
  373. *response++ = (uint8_t)(baudrate >> 8);
  374. *response++ = (uint8_t)(baudrate >> 16);
  375. *response = (uint8_t)(baudrate >> 24);
  376. return ((4U << 16) | 4U);
  377. }
  378. // Process SWO Control command and prepare response
  379. // request: pointer to request data
  380. // response: pointer to response data
  381. // return: number of bytes in response (lower 16 bits)
  382. // number of bytes in request (upper 16 bits)
  383. uint32_t SWO_Control (const uint8_t *request, uint8_t *response) {
  384. uint8_t active;
  385. uint32_t result;
  386. active = *request & DAP_SWO_CAPTURE_ACTIVE;
  387. if (active != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)) {
  388. if (active) {
  389. ClearTrace();
  390. }
  391. switch (TraceMode) {
  392. #if (SWO_UART != 0)
  393. case DAP_SWO_UART:
  394. result = UART_SWO_Control(active);
  395. break;
  396. #endif
  397. #if (SWO_MANCHESTER != 0)
  398. case DAP_SWO_MANCHESTER:
  399. result = Manchester_SWO_Control(active);
  400. break;
  401. #endif
  402. default:
  403. result = 0U;
  404. break;
  405. }
  406. if (result != 0U) {
  407. TraceStatus = active;
  408. }
  409. } else {
  410. result = 1U;
  411. }
  412. if (result != 0U) {
  413. *response = DAP_OK;
  414. } else {
  415. *response = DAP_ERROR;
  416. }
  417. return ((1U << 16) | 1U);
  418. }
  419. // Process SWO Status command and prepare response
  420. // response: pointer to response data
  421. // return: number of bytes in response
  422. uint32_t SWO_Status (uint8_t *response) {
  423. uint8_t status;
  424. uint32_t count;
  425. if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) {
  426. switch (TraceMode) {
  427. #if (SWO_UART != 0)
  428. case DAP_SWO_UART:
  429. UART_SWO_Update();
  430. break;
  431. #endif
  432. #if (SWO_MANCHESTER != 0)
  433. case DAP_SWO_MANCHESTER:
  434. Manchester_SWO_Update();
  435. break;
  436. #endif
  437. default:
  438. break;
  439. }
  440. }
  441. status = GetTraceStatus();
  442. count = GetTraceCount();
  443. *response++ = status;
  444. *response++ = (uint8_t)(count >> 0);
  445. *response++ = (uint8_t)(count >> 8);
  446. *response++ = (uint8_t)(count >> 16);
  447. *response = (uint8_t)(count >> 24);
  448. return (5U);
  449. }
  450. // Process SWO Data command and prepare response
  451. // request: pointer to request data
  452. // response: pointer to response data
  453. // return: number of bytes in response (lower 16 bits)
  454. // number of bytes in request (upper 16 bits)
  455. uint32_t SWO_Data (const uint8_t *request, uint8_t *response) {
  456. uint8_t status;
  457. uint32_t count;
  458. uint32_t n;
  459. if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) {
  460. switch (TraceMode) {
  461. #if (SWO_UART != 0)
  462. case DAP_SWO_UART:
  463. UART_SWO_Update();
  464. break;
  465. #endif
  466. #if (SWO_MANCHESTER != 0)
  467. case DAP_SWO_MANCHESTER:
  468. Manchester_SWO_Update();
  469. break;
  470. #endif
  471. default:
  472. break;
  473. }
  474. }
  475. status = GetTraceStatus();
  476. count = GetTraceCount();
  477. if (TraceTransport == 1U) {
  478. n = (*(request+0) << 0) |
  479. (*(request+1) << 8);
  480. } else {
  481. n = 0U;
  482. }
  483. if (count > n) {
  484. count = n;
  485. }
  486. *response++ = status;
  487. *response++ = (uint8_t)(count >> 0);
  488. *response++ = (uint8_t)(count >> 8);
  489. for (n = count; n; n--) {
  490. *response++ = TraceBuf[TraceOut++ & (SWO_BUFFER_SIZE-1U)];
  491. }
  492. if (TraceStatus == (DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED)) {
  493. n = GetTraceSpace();
  494. if (n != 0U) {
  495. switch (TraceMode) {
  496. #if (SWO_UART != 0)
  497. case DAP_SWO_UART:
  498. UART_SWO_Capture(&TraceBuf[TraceIn & (SWO_BUFFER_SIZE-1U)], n);
  499. TraceStatus = DAP_SWO_CAPTURE_ACTIVE;
  500. break;
  501. #endif
  502. #if (SWO_MANCHESTER != 0)
  503. case DAP_SWO_MANCHESTER:
  504. Manchester_SWO_Capture(&TraceBuf[TraceIn & (SWO_BUFFER_SIZE-1U)], n);
  505. TraceStatus = DAP_SWO_CAPTURE_ACTIVE;
  506. break;
  507. #endif
  508. default:
  509. break;
  510. }
  511. }
  512. }
  513. return ((2U << 16) | (3U + count));
  514. }
  515. #endif /* ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) */