JLINKDCC_Process.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*********************************************************************
  2. * SEGGER Microcontroller GmbH *
  3. * The Embedded Experts *
  4. **********************************************************************
  5. * *
  6. * (c) 2006 - 2019 SEGGER Microcontroller GmbH *
  7. * *
  8. * www.segger.com Support: support@segger.com *
  9. * *
  10. **********************************************************************
  11. * *
  12. * All rights reserved. *
  13. * *
  14. * Redistribution and use in source and binary forms, with or *
  15. * without modification, are permitted provided that the following *
  16. * condition is met: *
  17. * *
  18. * o Redistributions of source code must retain the above copyright *
  19. * notice, this condition and the following disclaimer. *
  20. * *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
  22. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
  23. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
  25. * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
  26. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
  28. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
  29. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
  30. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
  32. * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
  33. * DAMAGE. *
  34. * *
  35. **********************************************************************
  36. -------------------------- END-OF-HEADER -----------------------------
  37. File : JLINKDCC_Process.c
  38. Purpose : Data handler for ARM J-Link type communication via DCC (IAR version, using intrinsics)
  39. Changes : 08-10-08
  40. Support for "channels"added, where
  41. channel 0 is reserved for terminal
  42. channel 1 is reserved for OS communication such as embOSView
  43. 11-11-15
  44. Cortex A/R defines modified.
  45. Notes : (1) How to use
  46. In order to use the DCC communication to read / write memory, the
  47. following needs to be done:
  48. * Add this file to the project / make-file
  49. * Make sure this data handler is called regularly
  50. * Add the JLINKDCC data abort handler (optional)
  51. For details, refer to the documentation or see file JLINKDCC_HandleDataAbort.s79.
  52. (2) Compatibility
  53. The J-Link ARM DCC handler is compatible to the DCC communication
  54. protocol used by IAR in the embedded workbench for ARM and allows
  55. using the live data window in C-Spy
  56. Protocol
  57. Following response packets from target will be possible:
  58. 00 00 00 XX - reading a byte XX
  59. 00 00 XX XX - reading a half word XXXX
  60. XX XX XX XX - reading a word, except words starting with 93zX XXXX (10010011-1xxxxxxx-xxxxxxx-xxxxxxx)
  61. 93 8z 00 XX - terminal I/O one byte XX to channel z=0-15
  62. 93 9z 00 XX - terminal I/O one byte XX to channel z=16-31
  63. 93 Az XX XX - terminal I/O two bytes XX XX to channel z=0-15
  64. 93 Bz XX XX - terminal I/O two bytes XX XX to channel z=16-31
  65. 93 C0 XX XX - escape sequence for words starting with 93XX, the lower 16-bit part is in XX XX
  66. 93 C1 XX XX - escape sequence for words starting with 93XX, the upper 16-bit part is in XX XX
  67. 93 C2 XX XX - data abort for reading
  68. 91 CA XX XX - signature (same as before)
  69. There is a new capability flag. C-SPY will use the new protocol when this is set.
  70. #define DCC_CAP_TERM_OUT 0x80
  71. Sequence for U8 write:
  72. H->T Addr & 0xFFFFFFFE
  73. H->T ((Addr & 1) << 31) | (Data << 2) | 0x40000001
  74. Sequence for U16 write:
  75. H->T Addr & 0xFFFFFFFE
  76. H->T ((Addr & 1) << 31) | (Data << 2) | 0x20000001
  77. Sequence for U32 write:
  78. H->T Addr & 0xFFFFFFFE
  79. H->T (Data & 0xFFFF) << 2
  80. H->T ((Addr & 1) << 31) | ((Data >> 14) & 0xFFFF) | 0x10000001
  81. Sequence for U8 Read:
  82. H->T Addr & 0xFFFFFFFE
  83. H->T ((Addr & 1) << 31) | (NumItems << 2) | 0x04000001
  84. if (Aborted) {
  85. T->H 0x93c20000
  86. } else {
  87. T->H Data
  88. }
  89. Sequence for U16 Read:
  90. H->T Addr & 0xFFFFFFFE
  91. H->T ((Addr & 1) << 31) | (NumItems << 2) | 0x02000001
  92. if (Aborted) {
  93. T->H 0x93c20000
  94. } else {
  95. T->H Data
  96. }
  97. Sequence for U32 Read:
  98. H->T Addr & 0xFFFFFFFE
  99. H->T ((Addr & 1) << 31) | (NumItems << 2) | 0x01000001
  100. if (Aborted) {
  101. T->H 0x93c20000
  102. } else if ((Data >> 24) != 0x93) {
  103. T->H Data
  104. } else {
  105. T->H 0x93c0.0000 | (Data & 0xFFFF)
  106. T->H 0x93c1.0000 | (Data >> 16)
  107. }
  108. Terminal IN: (target receives data)
  109. H->T 0x93000000 + (Channel << 19) + (Data8 << 1) + DCC_OP_COMMAND
  110. Terminal OUT: (target sends data)
  111. T->H 0x93800000 + (Channel << 16) + (Data8)
  112. */
  113. #include "JLINKDCC.h"
  114. #ifdef __ICCARM__
  115. /* With IAR workbench we use intrinsics for CP14 communication */
  116. #include <intrinsics.h>
  117. #else
  118. #define __ARM7A__ 1
  119. #define __ARM7R__ 2
  120. #define __CORE__ 0 // Default is: DCC module is designed for ARM7/9. In order to support Cortex-A/R, __CORE__ has to be set to __ARM7A__ or __ARM7R__
  121. /* We use external functions from assembly module JLINKDCC_Process_ASM.s */
  122. extern unsigned long CP14_ReadDCCStat(void);
  123. extern unsigned long CP14_ReadDCC(void);
  124. extern void CP14_WriteDCC(unsigned long Data);
  125. #endif
  126. /*********************************************************************
  127. *
  128. * Defines, configurable
  129. *
  130. **********************************************************************
  131. */
  132. #ifndef JLINKDCC_BUFFER_SIZE
  133. #define JLINKDCC_BUFFER_SIZE 1024 // Used for channel 0 (terminal out buffer)
  134. #endif
  135. #define NUM_CHANNELS 2
  136. /*********************************************************************
  137. *
  138. * Defines, non- configurable
  139. *
  140. **********************************************************************
  141. */
  142. #define U8 unsigned char
  143. #define U16 unsigned short
  144. #define U32 unsigned long
  145. #define DCC_OP_READ_U32 0x01000000
  146. #define DCC_OP_READ_U16 0x02000000
  147. #define DCC_OP_READ_U8 0x04000000
  148. #define DCC_OP_GET_CAPS 0x08000000
  149. #define DCC_OP_WRITE_U32 0x10000000
  150. #define DCC_OP_WRITE_U16 0x20000000
  151. #define DCC_OP_WRITE_U8 0x40000000
  152. #define DCC_OP_ODD_ADDR 0x80000000
  153. #define DCC_OP_COMMAND 0x00000001
  154. #define DCC_SIGNATURE 0x91CA0000
  155. #define DCC_CONFIG 0xFF // All features are supported
  156. #define DCC_CHANNEL_TERMINAL 0
  157. #define DCC_CHANNEL_OS 1
  158. //
  159. // The bit positions for DCC RX and TX ready are different for ARM7/9 and Cortex-A/R,
  160. // so we have to distinguish here.
  161. //
  162. #if (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || (defined (__ARM7R__) && (__CORE__ == __ARM7R__))
  163. #define RX_FULL_FLAG_SHIFT 30
  164. #define TX_FULL_FLAG_SHIFT 29
  165. #else
  166. #define RX_FULL_FLAG_SHIFT 0
  167. #define TX_FULL_FLAG_SHIFT 1
  168. #endif
  169. /*********************************************************************
  170. *
  171. * Global data
  172. *
  173. **********************************************************************
  174. */
  175. U8 JLINKDCC_IsInHandler;
  176. U8 JLINKDCC_AbortOccurred;
  177. /*********************************************************************
  178. *
  179. * Static data
  180. *
  181. **********************************************************************
  182. */
  183. void (* _pfOnRx[2]) (unsigned Channel, U8 Data);
  184. void (* _pfOnTx[2]) (unsigned Channel);
  185. static U16 _NumReadItems;
  186. static U32 _Command;
  187. static U32 _Addr;
  188. static char _acBuffer[JLINKDCC_BUFFER_SIZE];
  189. static U16 _RdPos;
  190. static U16 _WrPos;
  191. static U8 _ActiveChannel = 0;
  192. static char _WritePendingNB = 0;
  193. static U32 _PendingPacketNB = 0;
  194. static char _WritePending;
  195. static U32 _Data;
  196. /*********************************************************************
  197. *
  198. * Static code
  199. *
  200. **********************************************************************
  201. */
  202. #ifdef __ICCARM__
  203. /****** Use intrinsics for CP14 communication ***********************/
  204. #if (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || (defined (__ARM7R__) && (__CORE__ == __ARM7R__))
  205. /*********************************************************************
  206. *
  207. * _ReadDCCStat
  208. *
  209. * IAR macro: unsigned long __MRC(coproc, opcode_1, CRn, CRm, opcode_2);
  210. * Inst: MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} Move from coproc to ARM reg
  211. * ARMv4 / ARMv5: MRC p14,0,<Rt>,c0,c0,0
  212. * ARMv7-AR: MRC p14,0,<Rt>,c0,c1,0 DBGDSCR
  213. */
  214. static int _ReadDCCStat(void) {
  215. return __MRC(14, 0, 0, 1, 0);
  216. }
  217. /*********************************************************************
  218. *
  219. * _ReadDCC
  220. *
  221. * IAR macro: unsigned long __MRC(coproc, opcode_1, CRn, CRm, opcode_2);
  222. * Inst: MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} Move from coproc to ARM reg
  223. * ARMv4 / ARMv5: MRC p14,0,<Rt>,c1,c0,0
  224. * ARMv7-AR: MRC p14,0,<Rt>,c0,c5,0 DTRRX
  225. */
  226. static U32 _ReadDCC(void) {
  227. return __MRC(14, 0, 0, 5, 0);
  228. }
  229. /*********************************************************************
  230. *
  231. * _WriteDCC
  232. *
  233. * IAR macro: void __MCR(coproc, opcode_1, Data, CRn, CRm, opcode_2);
  234. * Inst: MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} Move to coproc
  235. * ARMv4 / ARMv5: MCR P14,0,<Rt>,C1,C0,0
  236. * ARMv7-AR: MCR p14,0,<Rt>,c0,c5,0 DTRTX
  237. */
  238. static void _WriteDCC(U32 Data) {
  239. __MCR(14, 0, Data, 0, 5, 0);
  240. }
  241. #else // (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || (defined (__ARM7R__) && (__CORE__ == __ARM7R__))
  242. /*********************************************************************
  243. *
  244. * _ReadDCCStat
  245. *
  246. * IAR macro: unsigned long __MRC(coproc, opcode_1, CRn, CRm, opcode_2);
  247. * Inst: MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} Move from coproc to ARM reg
  248. * ARMv4 / ARMv5: MRC p14,0,<Rt>,c0,c0,0
  249. * ARMv7-AR: MRC p14,0,<Rt>,c0,c1,0 DBGDSCR
  250. */
  251. static __interwork __arm int _ReadDCCStat(void) {
  252. return __MRC( 14, 0, 0, 0, 0 ); // __asm("mrc P14,0,R0,C0,C0,0");
  253. }
  254. /*********************************************************************
  255. *
  256. * _ReadDCC
  257. *
  258. * IAR macro: unsigned long __MRC(coproc, opcode_1, CRn, CRm, opcode_2);
  259. * Inst: MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} Move from coproc to ARM reg
  260. * ARMv4 / ARMv5: MRC p14,0,<Rt>,c1,c0,0
  261. * ARMv7-AR: MRC p14,0,<Rt>,c0,c5,0 DTRRX
  262. */
  263. static __interwork __arm U32 _ReadDCC(void) {
  264. return __MRC( 14, 0, 1, 0, 0 ); // __asm("mrc P14,0,R0,C1,C0,0");
  265. }
  266. /*********************************************************************
  267. *
  268. * _WriteDCC
  269. *
  270. * IAR macro: void __MCR(coproc, opcode_1, Data, CRn, CRm, opcode_2);
  271. * Inst: MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} Move to coproc
  272. * ARMv4 / ARMv5: MCR P14,0,<Rt>,C1,C0,0
  273. * ARMv7-AR: MCR p14,0,<Rt>,c0,c5,0 DTRTX
  274. */
  275. static __interwork __arm void _WriteDCC(U32 Data) {
  276. __MCR( 14, 0, Data, 1, 0, 0 ); // __asm("mcr P14,0,R0,C1,C0,0");
  277. }
  278. #endif // (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || (defined (__ARM7R__) && (__CORE__ == __ARM7R__))
  279. #else //__ICCARM__
  280. /****** Map externel CP14 communication routines ********************/
  281. #define _ReadDCCStat CP14_ReadDCCStat
  282. #define _ReadDCC CP14_ReadDCC
  283. #define _WriteDCC(Data) CP14_WriteDCC(Data)
  284. #endif // __ICCARM__
  285. /*********************************************************************
  286. *
  287. * _HandleRead
  288. *
  289. * Function description
  290. * Performs Command / data read from host
  291. */
  292. static void _HandleRead(void) {
  293. U32 Data;
  294. if (((_ReadDCCStat() >> RX_FULL_FLAG_SHIFT) & 1) == 0) { // Data or command received ?
  295. return; // Nothing received
  296. }
  297. Data = _ReadDCC();
  298. //
  299. // If item received does not have the command-flag set, it is the new addr.
  300. //
  301. if ((Data & DCC_OP_COMMAND) == 0) {
  302. _Addr = Data;
  303. return;
  304. }
  305. //
  306. // If item received is a terminal out command,
  307. //
  308. if ((Data & 0xFF000000) == 0x93000000) {
  309. unsigned Channel;
  310. Channel = (Data >> 19) & 0x1F;
  311. if (_pfOnRx[Channel]) {
  312. _pfOnRx[Channel](Channel, (Data >> 1) & 0xFF);
  313. }
  314. return;
  315. }
  316. //
  317. // We received a new command.
  318. //
  319. _Command = Data;
  320. if (_Command & DCC_OP_ODD_ADDR) {
  321. _Addr |= 1;
  322. }
  323. if (_Command & (DCC_OP_READ_U32 | DCC_OP_READ_U16 | DCC_OP_READ_U8 | DCC_OP_GET_CAPS)) {
  324. _NumReadItems = (_Command >> 2) & 0xffff;
  325. } else {
  326. // Clear before write
  327. JLINKDCC_AbortOccurred = 0;
  328. if (_Command & DCC_OP_WRITE_U32) {
  329. _Data |= (_Command << 14) & 0xffff0000;
  330. } else {
  331. _Data = (_Command >> 2) & 0xffff;
  332. }
  333. if (_Command & DCC_OP_WRITE_U8) {
  334. *(U8*)_Addr = _Data;
  335. _Addr += 1;
  336. }
  337. if (_Command & DCC_OP_WRITE_U16) {
  338. *(U16*)_Addr = _Data;
  339. _Addr += 2;
  340. }
  341. if (_Command & DCC_OP_WRITE_U32) {
  342. *(U32*)_Addr =_Data;
  343. _Addr += 4;
  344. }
  345. }
  346. }
  347. /*********************************************************************
  348. *
  349. * _HandleWrite
  350. *
  351. * Function description
  352. * Sends data back to host if there is space in DCC buffer and data to be send.
  353. */
  354. static void _HandleWrite(void) {
  355. U32 Data;
  356. int DCCBusy;
  357. int NumBytes;
  358. Data = 0;
  359. DCCBusy = (_ReadDCCStat() >> TX_FULL_FLAG_SHIFT) & 1;
  360. if (DCCBusy) { // Can we send data ?
  361. return; // If not, we are done.
  362. }
  363. if (_ActiveChannel) {
  364. U32 Channel;
  365. Channel = _ActiveChannel;
  366. _ActiveChannel = 0;
  367. if (_WritePendingNB) {
  368. _WriteDCC(_PendingPacketNB);
  369. _WritePendingNB = 0;
  370. }
  371. if (_pfOnTx[Channel]) {
  372. _pfOnTx[Channel](Channel);
  373. }
  374. return;
  375. }
  376. //
  377. // Check if a data item is pending
  378. //
  379. if (_WritePending) {
  380. _WriteDCC(_Data);
  381. _WritePending = 0;
  382. return;
  383. }
  384. //
  385. // Check if a read command is pending
  386. //
  387. if (_NumReadItems) {
  388. if (_Command & DCC_OP_GET_CAPS) {
  389. Data = (DCC_CONFIG | DCC_SIGNATURE);
  390. Data |= (JLINKDCC_AbortOccurred << 8); // write abort status
  391. JLINKDCC_AbortOccurred = 0;
  392. } else {
  393. // Clear before next read
  394. JLINKDCC_AbortOccurred = 0;
  395. if (_Command & DCC_OP_READ_U8) {
  396. Data = *(U8*)_Addr;
  397. _Addr += 1;
  398. } else if (_Command & DCC_OP_READ_U16) {
  399. Data = *(U16*)_Addr;
  400. _Addr += 2;
  401. } else if (_Command & DCC_OP_READ_U32) {
  402. Data = *(U32*)_Addr;
  403. _Addr += 4;
  404. if ((Data & 0xFF800000) == 0x93800000) { // Do we need to use the escape sequence and split it up into 2 transfers ?
  405. _Data = 0x93c10000 | (Data >> 16);
  406. Data = 0x93c00000 | (Data & 0xFFFF);
  407. _WritePending = 1;
  408. }
  409. }
  410. if (JLINKDCC_AbortOccurred) {
  411. Data = 0x93c20000; // read abort status
  412. _WritePending = 0;
  413. JLINKDCC_AbortOccurred = 0; // clear it
  414. }
  415. }
  416. _WriteDCC(Data);
  417. _NumReadItems--;
  418. return;
  419. }
  420. //
  421. // Handle terminal out. Up to 2 bytes in one 32-bit unit
  422. //
  423. NumBytes = _WrPos - _RdPos;
  424. if (NumBytes < 0) {
  425. NumBytes += sizeof(_acBuffer);
  426. }
  427. if (NumBytes) {
  428. int i;
  429. if (NumBytes > 2) {
  430. NumBytes = 2;
  431. }
  432. if (NumBytes == 2) {
  433. Data = 0x93A00000;
  434. } else {
  435. Data = 0x93800000;
  436. }
  437. for (i = 0; i < NumBytes; i++) {
  438. Data |= _acBuffer[_RdPos] << (8*i);
  439. _RdPos++;
  440. if (_RdPos == sizeof(_acBuffer)) {
  441. _RdPos = 0;
  442. }
  443. }
  444. _WriteDCC(Data);
  445. }
  446. }
  447. /*********************************************************************
  448. *
  449. * Public code
  450. *
  451. **********************************************************************
  452. */
  453. /*********************************************************************
  454. *
  455. * JLINKDCC_Process
  456. *
  457. * Function description
  458. * This function should be called more or less regularily to allow
  459. * memory reads while the application progam is running.
  460. * The more often it is called, the higher the transfer speed.
  461. */
  462. void JLINKDCC_Process(void) {
  463. //
  464. // Avoid problems if this code is called from multiple threads or interrupts
  465. //
  466. if (JLINKDCC_IsInHandler) {
  467. return;
  468. }
  469. JLINKDCC_IsInHandler = 1;
  470. _HandleRead();
  471. _HandleWrite();
  472. JLINKDCC_IsInHandler = 0;
  473. }
  474. /*********************************************************************
  475. *
  476. * JLINKDCC_SendChar
  477. *
  478. * Function description
  479. * Sends a single char to terminal out.
  480. */
  481. void JLINKDCC_SendChar(char c) {
  482. int Pos;
  483. Pos = _WrPos + 1;
  484. if (Pos == sizeof(_acBuffer)) {
  485. Pos = 0;
  486. }
  487. if (Pos == _RdPos) {
  488. return;
  489. }
  490. _acBuffer[_WrPos] = c;
  491. _WrPos = Pos;
  492. }
  493. /*********************************************************************
  494. *
  495. * JLINKDCC_SendString
  496. *
  497. * Function description
  498. * Sends a NUL- terminated string to terminal out.
  499. */
  500. void JLINKDCC_SendString(const char * s) {
  501. char c;
  502. while (1) {
  503. c = *s++;
  504. if (c == 0) {
  505. break;
  506. }
  507. JLINKDCC_SendChar(c);
  508. }
  509. }
  510. /*********************************************************************
  511. *
  512. * JLINKDCC_SendCharOnChannelNB
  513. *
  514. * Function description
  515. * Send data to the host on selected channel.
  516. * This function is non-blocking.
  517. * If data can not be send it is stored in a buffer
  518. * and sent later, when the DCC Handler is called.
  519. */
  520. void JLINKDCC_SendCharOnChannelNB(unsigned Channel, U8 Data) {
  521. U32 DCCPacket;
  522. int DCCBusy;
  523. DCCPacket = 0x93800000 | (Channel << 16);
  524. DCCPacket |= Data;
  525. DCCBusy = _ReadDCCStat() & 2;
  526. if (DCCBusy == 0) {
  527. _WriteDCC(DCCPacket);
  528. } else {
  529. _WritePendingNB = 1;
  530. _PendingPacketNB = DCCPacket;
  531. }
  532. _ActiveChannel = Channel;
  533. }
  534. /*********************************************************************
  535. *
  536. * JLINKDCC_SendOnChannel
  537. *
  538. * Function description
  539. * Send data to the host.
  540. * 32 channels are available, channel 0 is used for terminal output and is buffered,
  541. * all other channels are unbuffered.
  542. */
  543. void JLINKDCC_SendOnChannel(unsigned Channel, U8 * pData, int NumItems) {
  544. U32 Data;
  545. if (Channel == DCC_CHANNEL_TERMINAL) {
  546. while (NumItems-- > 0) {
  547. Data = *pData++;
  548. JLINKDCC_SendChar(Data);
  549. }
  550. } else {
  551. while (NumItems-- > 0) {
  552. Data = *pData++;
  553. if (NumItems > 0) {
  554. Data |= *pData++ << 8;
  555. NumItems--;
  556. Data |= 0x200000;
  557. }
  558. Data |= 0x93800000;
  559. Data |= Channel << 16;
  560. while (_ReadDCCStat() & 2); // Wait until we can send data
  561. _WriteDCC(Data);
  562. }
  563. }
  564. }
  565. /*********************************************************************
  566. *
  567. * JLINKDCC_SetpfOnRx
  568. *
  569. */
  570. void JLINKDCC_SetpfOnRx(unsigned Channel, void (* pf)(unsigned Channel, U8 Data)) {
  571. _pfOnRx[Channel] = pf;
  572. }
  573. /*********************************************************************
  574. *
  575. * JLINKDCC_SetpfOnTx
  576. *
  577. */
  578. void JLINKDCC_SetpfOnTx(unsigned Channel, void (* pf)(unsigned Channel)) {
  579. _pfOnTx[Channel] = pf;
  580. }
  581. /*************************** end of file ****************************/