swd.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*
  2. * This Source Code Form is subject to the terms of the MIT License.
  3. * If a copy of the MIT License was not distributed with this file,
  4. * you can obtain one at https://opensource.org/licenses/MIT
  5. */
  6. #include "main.h"
  7. #include "system.h"
  8. #include "swd.h"
  9. #include "target.h"
  10. #define MWAIT __asm__ __volatile__( \
  11. ".syntax unified \n" \
  12. " movs r0, #0x30 \n" \
  13. "1: subs r0, #1 \n" \
  14. " bne 1b \n" \
  15. ".syntax divided" : : : \
  16. "cc", "r0")
  17. #define N_READ_TURN (3u)
  18. static uint8_t swdParity( uint8_t const * data, uint8_t const len );
  19. static void swdDatasend( uint8_t const * data, uint8_t const len );
  20. static void swdDataIdle( void );
  21. static void swdDataPP( void );
  22. static void swdTurnaround( void );
  23. static void swdReset( void );
  24. static void swdDataRead( uint8_t * const data, uint8_t const len );
  25. static void swdBuildHeader( swdAccessDirection_t const adir, swdPortSelect_t const portSel, uint8_t const A32, uint8_t * const header);
  26. static swdStatus_t swdReadPacket( swdPortSelect_t const portSel, uint8_t const A32, uint32_t * const data );
  27. static swdStatus_t swdWritePacket( swdPortSelect_t const portSel, uint8_t const A32, uint32_t const data );
  28. static swdStatus_t swdReadAP0( uint32_t * const data );
  29. #ifdef UNUSED_EXPERIMENTAL
  30. static swdStatus_t swdReadDPCtrl( uint32_t * const data );
  31. static swdStatus_t swdReadAPCtrl( uint32_t * const data );
  32. static swdStatus_t swdReadWIREMODE( uint32_t * const data );
  33. static swdStatus_t swdReadDHCSR( uint32_t * const data );
  34. static swdStatus_t swdWriteAHBAddr( uint32_t const addr, uint32_t const data );
  35. static swdStatus_t swdCoreHalt( void );
  36. static swdStatus_t swdGetRegister( uint8_t const regId, uint32_t * const data );
  37. #endif
  38. static uint8_t swdParity( uint8_t const * data, uint8_t const len )
  39. {
  40. uint8_t par = 0u;
  41. uint8_t cdata = 0u;
  42. uint8_t i = 0u;
  43. for (i=0u; i<len; ++i)
  44. {
  45. if ((i & 0x07u) == 0u)
  46. {
  47. cdata = *data;
  48. ++data;
  49. }
  50. par ^= (cdata & 0x01u);
  51. cdata >>= 1u;
  52. }
  53. return par;
  54. }
  55. static void swdDatasend( uint8_t const * data, uint8_t const len )
  56. {
  57. uint8_t cdata = 0u;
  58. uint8_t i = 0u;
  59. for (i=0u; i<len; ++i)
  60. {
  61. if ((i & 0x07u) == 0x00u)
  62. {
  63. cdata = *data;
  64. ++data;
  65. }
  66. if ((cdata & 0x01u) == 0x01u)
  67. {
  68. GPIOA_BSRR |= (1 << PIN_SWDIO);
  69. }
  70. else
  71. {
  72. GPIOA_BSRR |= (1 << (PIN_SWDIO + 16));
  73. }
  74. MWAIT;
  75. GPIOA_BSRR |= (1 << PIN_SWCLK);
  76. MWAIT;
  77. GPIOA_BSRR |= (1 << (PIN_SWCLK + 16));
  78. cdata >>= 1u;
  79. MWAIT;
  80. }
  81. return ;
  82. }
  83. static void swdDataIdle( void )
  84. {
  85. GPIOA_BSRR |= (1 << PIN_SWDIO);
  86. MWAIT;
  87. GPIOA_MODE &= ~(0x03u << (PIN_SWDIO * 2));
  88. MWAIT;
  89. return ;
  90. }
  91. static void swdDataPP( void )
  92. {
  93. MWAIT;
  94. GPIOA_BSRR |= (1 << (PIN_SWDIO + 16));
  95. GPIOA_MODE |= (1 << (PIN_SWDIO * 2));
  96. MWAIT;
  97. return ;
  98. }
  99. static void swdTurnaround( void )
  100. {
  101. GPIOA_BSRR |= (1 << (PIN_SWCLK));
  102. MWAIT;
  103. GPIOA_BSRR |= (1 << (PIN_SWCLK + 16));
  104. MWAIT;
  105. return ;
  106. }
  107. static void swdDataRead( uint8_t * const data, uint8_t const len )
  108. {
  109. uint8_t i = 0u;
  110. uint8_t cdata = 0u;
  111. MWAIT;
  112. swdDataIdle();
  113. MWAIT;
  114. for (i=0u; i<len; ++i)
  115. {
  116. cdata >>= 1u;
  117. cdata |= (GPIOA_IDR & (0x01u << (PIN_SWDIO))) ? 0x80u : 0x00u;
  118. data[(((len + 7u) >> 3u) - (i >> 3u)) - 1u] = cdata;
  119. swdTurnaround();
  120. /* clear buffer after reading 8 bytes */
  121. if ((i & 0x07u) == 0x07u)
  122. {
  123. cdata = 0u;
  124. }
  125. }
  126. return ;
  127. }
  128. static void swdReset( void )
  129. {
  130. uint8_t i = 0u;
  131. MWAIT;
  132. GPIOA_ODR |= (1 << PIN_SWDIO) | (1 << PIN_SWCLK);
  133. MWAIT;
  134. /* Switch from JTAG to SWD mode. Not required for SWD-only devices (STM32F0x). */
  135. #ifdef DO_JTAG_RESET
  136. /* 50 clk+x */
  137. for (i=0u; i < (50u + 10u); ++i)
  138. {
  139. swdTurnaround();
  140. }
  141. uint8_t send1[] = {0u, 1u, 1u, 1u, 1u, 0u, 0u, 1u, 1u, 1u, 1u, 0u, 0u, 1u, 1u, 1u};
  142. /* send 0111 1001 1110 0111 */
  143. for (i = 0u; i < 16u; ++i)
  144. {
  145. if (send1[i])
  146. GPIOD_BSRR |= (1 << PIN_SWDIO);
  147. else
  148. GPIOD_BSRR |= (1 << (PIN_SWDIO + 16));
  149. MWAIT;
  150. swdTurnaround();
  151. }
  152. #endif
  153. /* 50 clk+x */
  154. for (i = 0u; i < (50u + 10u); ++i)
  155. {
  156. swdTurnaround();
  157. }
  158. GPIOA_BSRR |= (1 << (PIN_SWDIO + 16));
  159. for (i = 0u; i < 3u; ++i)
  160. {
  161. swdTurnaround();
  162. }
  163. return ;
  164. }
  165. static void swdBuildHeader( swdAccessDirection_t const adir, swdPortSelect_t const portSel, uint8_t const A32, uint8_t * const header)
  166. {
  167. if (portSel == swdPortSelectAP)
  168. {
  169. *header |= 0x02u; /* Access AP */
  170. }
  171. if (adir == swdAccessDirectionRead)
  172. {
  173. *header |= 0x04u; /* read access */
  174. }
  175. switch (A32)
  176. {
  177. case 0x01u:
  178. *header |= 0x08u;
  179. break;
  180. case 0x02u:
  181. *header |= 0x10u;
  182. break;
  183. case 0x03u:
  184. *header |= 0x18u;
  185. break;
  186. default:
  187. case 0x00u:
  188. break;
  189. }
  190. *header |= swdParity(header, 7u) << 5u;
  191. *header |= 0x01u; /* startbit */
  192. *header |= 0x80u;
  193. }
  194. static swdStatus_t swdReadPacket( swdPortSelect_t const portSel, uint8_t const A32, uint32_t * const data )
  195. {
  196. swdStatus_t ret = swdStatusNone;
  197. uint8_t header = 0x00u;
  198. uint8_t rp[1] = {0x00u};
  199. uint8_t resp[5] = {0u};
  200. uint8_t i = 0u;
  201. swdBuildHeader( swdAccessDirectionRead, portSel, A32, &header );
  202. swdDatasend( &header, 8u );
  203. swdDataIdle();
  204. swdTurnaround();
  205. swdDataRead( rp, 3u );
  206. swdDataRead( resp, 33u );
  207. swdDataPP();
  208. for (i=0u; i < N_READ_TURN; ++i)
  209. {
  210. swdTurnaround();
  211. }
  212. *data = resp[4] | (resp[3] << 8u) | (resp[2] << 16u) | (resp[1] << 24u);
  213. ret = rp[0];
  214. return ret;
  215. }
  216. static swdStatus_t swdWritePacket( swdPortSelect_t const portSel, uint8_t const A32, uint32_t const data )
  217. {
  218. swdStatus_t ret = swdStatusNone;
  219. uint8_t header = 0x00u;
  220. uint8_t rp[1] = {0x00u};
  221. uint8_t data1[5] = {0u};
  222. uint8_t i = 0u;
  223. swdBuildHeader( swdAccessDirectionWrite, portSel, A32, &header );
  224. swdDatasend( &header, 8u );
  225. MWAIT;
  226. swdDataIdle();
  227. MWAIT;
  228. swdTurnaround();
  229. swdDataRead( rp, 3u );
  230. swdDataIdle();
  231. swdTurnaround();
  232. swdDataPP();
  233. data1[0] = data & 0xFFu;
  234. data1[1] = (data >> 8u) & 0xFFu;
  235. data1[2] = (data >> 16u) & 0xFFu;
  236. data1[3] = (data >> 24u) & 0xFFu;
  237. data1[4] = swdParity(data1, 8u * 4u);
  238. swdDatasend( data1, 33u );
  239. swdDataPP();
  240. for (i=0u; i < 20u; ++i)
  241. {
  242. swdTurnaround();
  243. }
  244. ret = rp[0];
  245. return ret;
  246. }
  247. swdStatus_t swdReadIdcode( uint32_t * const idCode )
  248. {
  249. uint32_t ret = 0u;
  250. ret = swdReadPacket(swdPortSelectDP, 0x00u, idCode);
  251. return ret;
  252. }
  253. swdStatus_t swdSelectAPnBank(uint8_t const ap, uint8_t const bank)
  254. {
  255. swdStatus_t ret = swdStatusNone;
  256. uint32_t data = 0x00000000u;
  257. data |= (uint32_t) (ap & 0xFFu) << 24u;
  258. data |= (uint32_t) (bank & 0x0Fu) << 0u;
  259. /* write to select register */
  260. ret |= swdWritePacket(swdPortSelectDP, 0x02u, data);
  261. return ret;
  262. }
  263. static swdStatus_t swdReadAP0( uint32_t * const data )
  264. {
  265. swdStatus_t ret = swdStatusNone;
  266. swdReadPacket(swdPortSelectAP, 0x00u, data);
  267. return ret;
  268. }
  269. swdStatus_t swdSetAP32BitMode( uint32_t * const data )
  270. {
  271. swdStatus_t ret = swdStatusNone;
  272. swdSelectAPnBank( 0x00u, 0x00u );
  273. uint32_t d = 0u;
  274. ret |= swdReadAP0( &d );
  275. ret |= swdReadPacket(swdPortSelectDP, 0x03u, &d);
  276. d &= ~(0x07u);
  277. d |= 0x02u;
  278. ret |= swdWritePacket(swdPortSelectAP, 0x00u, d);
  279. ret |= swdReadAP0( &d );
  280. ret |= swdReadPacket(swdPortSelectDP, 0x03u, &d);
  281. if (data != NULL)
  282. {
  283. *data = d;
  284. }
  285. return ret;
  286. }
  287. swdStatus_t swdSelectAHBAP( void )
  288. {
  289. swdStatus_t ret = swdSelectAPnBank(0x00u, 0x00u);
  290. return ret;
  291. }
  292. swdStatus_t swdReadAHBAddr( uint32_t const addr, uint32_t * const data )
  293. {
  294. swdStatus_t ret = swdStatusNone;
  295. uint32_t d = 0u;
  296. ret |= swdWritePacket(swdPortSelectAP, 0x01u, addr);
  297. ret |= swdReadPacket(swdPortSelectAP, 0x03u, &d);
  298. ret |= swdReadPacket(swdPortSelectDP, 0x03u, &d);
  299. *data = d;
  300. return ret;
  301. }
  302. swdStatus_t swdEnableDebugIF( void )
  303. {
  304. swdStatus_t ret = swdStatusNone;
  305. ret |= swdWritePacket(swdPortSelectDP, 0x01u, 0x50000000u);
  306. return ret;
  307. }
  308. swdStatus_t swdInit( uint32_t * const idcode )
  309. {
  310. swdStatus_t ret = swdStatusNone;
  311. swdReset();
  312. ret |= swdReadIdcode( idcode );
  313. return ret;
  314. }
  315. #ifdef UNUSED_EXPERIMENTAL
  316. static swdStatus_t swdReadDPCtrl( uint32_t * const data )
  317. {
  318. swdStatus_t ret = swdStatusNone;
  319. ret |= swdSelectAPnBank(0x00u, 0x00u);
  320. ret |= swdReadPacket(swdPortSelectAP, 0x01u, data);
  321. return ret;
  322. }
  323. static swdStatus_t swdReadAPCtrl( uint32_t * const data )
  324. {
  325. swdStatus_t ret = swdStatusNone;
  326. ret |= swdReadPacket(swdPortSelectDP, 0x01u, data);
  327. return ret;
  328. }
  329. static swdStatus_t swdReadWIREMODE( uint32_t * const data )
  330. {
  331. swdStatus_t ret = swdStatusNone;
  332. ret |= swdWritePacket(swdPortSelectDP, 0x02u, 0x00000001u);
  333. ret |= swdReadPacket(swdPortSelectDP, 0x01u, data);
  334. return data;
  335. }
  336. static swdStatus_t swdReadDHCSR( uint32_t * const data )
  337. {
  338. swdStatus_t ret = swdReadAHBAddr(0xE000EDF0u, data);
  339. return ret;
  340. }
  341. static swdStatus_t swdWriteAHBAddr( uint32_t const addr, uint32_t const data )
  342. {
  343. swdStatus_t ret = swdStatusNone;
  344. ret |= swdWritePacket(swdPortSelectAP, 0x01u, addr);
  345. ret |= swdWritePacket(swdPortSelectAP, 0x03u, data);
  346. return ret;
  347. }
  348. static swdStatus_t swdCoreHalt( void )
  349. {
  350. swdStatus_t ret = swdStatusNone;
  351. ret |= swdWriteAHBAddr(0xE000EDF0u, 0xA05F0003u);
  352. return ret;
  353. }
  354. static swdStatus_t swdGetRegister( uint8_t const regId, uint32_t * const data )
  355. {
  356. swdWriteAHBAddr(0xE000EDF4u, regId & 0x1Fu);
  357. swdStatus_t ret = swdReadAHBAddr(0xE000EDF8u, data);
  358. return ret;
  359. }
  360. #endif