You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

293 lines
6.7 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2008 by √ėyvind Harboe *
  3. * oyvind.harboe@zylin.com *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "replacements.h"
  24. #include "jtag.h"
  25. #include "bitbang.h"
  26. /* my private tap controller state, which tracks state for calling code */
  27. static tap_state_t dummy_state = TAP_RESET;
  28. static int dummy_clock; /* edge detector */
  29. static int clock_count; /* count clocks in any stable state, only stable states */
  30. static tap_state_t tap_state_transition(tap_state_t cur_state, int tms);
  31. static u32 dummy_data;
  32. int dummy_speed(int speed);
  33. int dummy_register_commands(struct command_context_s *cmd_ctx);
  34. int dummy_init(void);
  35. int dummy_quit(void);
  36. static int dummy_khz(int khz, int *jtag_speed);
  37. static int dummy_speed_div(int speed, int *khz);
  38. /* The dummy driver is used to easily check the code path
  39. * where the target is unresponsive.
  40. */
  41. jtag_interface_t dummy_interface =
  42. {
  43. .name = "dummy",
  44. .execute_queue = bitbang_execute_queue,
  45. .speed = dummy_speed,
  46. .register_commands = dummy_register_commands,
  47. .khz = dummy_khz,
  48. .speed_div = dummy_speed_div,
  49. .init = dummy_init,
  50. .quit = dummy_quit,
  51. };
  52. int dummy_read(void);
  53. void dummy_write(int tck, int tms, int tdi);
  54. void dummy_reset(int trst, int srst);
  55. void dummy_led(int on);
  56. bitbang_interface_t dummy_bitbang =
  57. {
  58. .read = dummy_read,
  59. .write = dummy_write,
  60. .reset = dummy_reset,
  61. .blink = dummy_led
  62. };
  63. int dummy_read(void)
  64. {
  65. int data = 1 & dummy_data;
  66. dummy_data = (dummy_data >> 1) | (1<<31);
  67. return data;
  68. }
  69. void dummy_write(int tck, int tms, int tdi)
  70. {
  71. /* TAP standard: "state transitions occur on rising edge of clock" */
  72. if( tck != dummy_clock )
  73. {
  74. if( tck )
  75. {
  76. int old_state = dummy_state;
  77. dummy_state = tap_state_transition( old_state, tms );
  78. if( old_state != dummy_state )
  79. {
  80. if( clock_count )
  81. {
  82. LOG_DEBUG("dummy_tap: %d stable clocks", clock_count);
  83. clock_count = 0;
  84. }
  85. LOG_DEBUG("dummy_tap: %s", jtag_state_name(dummy_state) );
  86. #if defined(DEBUG)
  87. if(dummy_state == TAP_DRCAPTURE)
  88. dummy_data = 0x01255043;
  89. #endif
  90. }
  91. else
  92. {
  93. /* this is a stable state clock edge, no change of state here,
  94. * simply increment clock_count for subsequent logging
  95. */
  96. ++clock_count;
  97. }
  98. }
  99. dummy_clock = tck;
  100. }
  101. }
  102. void dummy_reset(int trst, int srst)
  103. {
  104. dummy_clock = 0;
  105. if (trst || (srst && (jtag_reset_config & RESET_SRST_PULLS_TRST)))
  106. dummy_state = TAP_RESET;
  107. LOG_DEBUG("reset to: %s", jtag_state_name(dummy_state) );
  108. }
  109. static int dummy_khz(int khz, int *jtag_speed)
  110. {
  111. if (khz==0)
  112. {
  113. *jtag_speed=0;
  114. }
  115. else
  116. {
  117. *jtag_speed=64000/khz;
  118. }
  119. return ERROR_OK;
  120. }
  121. static int dummy_speed_div(int speed, int *khz)
  122. {
  123. if (speed==0)
  124. {
  125. *khz = 0;
  126. }
  127. else
  128. {
  129. *khz=64000/speed;
  130. }
  131. return ERROR_OK;
  132. }
  133. int dummy_speed(int speed)
  134. {
  135. return ERROR_OK;
  136. }
  137. int dummy_register_commands(struct command_context_s *cmd_ctx)
  138. {
  139. return ERROR_OK;
  140. }
  141. int dummy_init(void)
  142. {
  143. bitbang_interface = &dummy_bitbang;
  144. return ERROR_OK;
  145. }
  146. int dummy_quit(void)
  147. {
  148. return ERROR_OK;
  149. }
  150. void dummy_led(int on)
  151. {
  152. }
  153. /**
  154. * Function tap_state_transition
  155. * takes a current TAP state and returns the next state according to the tms value.
  156. *
  157. * Even though there is code to duplicate this elsewhere, we do it here a little
  158. * differently just to get a second opinion, i.e. a verification, on state tracking
  159. * in that other logic. Plus array lookups without index checking are no favorite thing.
  160. * This is educational for developers new to TAP controllers.
  161. */
  162. static tap_state_t tap_state_transition(tap_state_t cur_state, int tms)
  163. {
  164. tap_state_t new_state;
  165. if (tms)
  166. {
  167. switch (cur_state)
  168. {
  169. case TAP_RESET:
  170. new_state = cur_state;
  171. break;
  172. case TAP_IDLE:
  173. case TAP_DRUPDATE:
  174. case TAP_IRUPDATE:
  175. new_state = TAP_DRSELECT;
  176. break;
  177. case TAP_DRSELECT:
  178. new_state = TAP_IRSELECT;
  179. break;
  180. case TAP_DRCAPTURE:
  181. case TAP_DRSHIFT:
  182. new_state = TAP_DREXIT1;
  183. break;
  184. case TAP_DREXIT1:
  185. case TAP_DREXIT2:
  186. new_state = TAP_DRUPDATE;
  187. break;
  188. case TAP_DRPAUSE:
  189. new_state = TAP_DREXIT2;
  190. break;
  191. case TAP_IRSELECT:
  192. new_state = TAP_RESET;
  193. break;
  194. case TAP_IRCAPTURE:
  195. case TAP_IRSHIFT:
  196. new_state = TAP_IREXIT1;
  197. break;
  198. case TAP_IREXIT1:
  199. case TAP_IREXIT2:
  200. new_state = TAP_IRUPDATE;
  201. break;
  202. case TAP_IRPAUSE:
  203. new_state = TAP_IREXIT2;
  204. break;
  205. default:
  206. LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
  207. exit(1);
  208. break;
  209. }
  210. }
  211. else
  212. {
  213. switch (cur_state)
  214. {
  215. case TAP_RESET:
  216. case TAP_IDLE:
  217. case TAP_DRUPDATE:
  218. case TAP_IRUPDATE:
  219. new_state = TAP_IDLE;
  220. break;
  221. case TAP_DRSELECT:
  222. new_state = TAP_DRCAPTURE;
  223. break;
  224. case TAP_DRCAPTURE:
  225. case TAP_DRSHIFT:
  226. case TAP_DREXIT2:
  227. new_state = TAP_DRSHIFT;
  228. break;
  229. case TAP_DREXIT1:
  230. case TAP_DRPAUSE:
  231. new_state = TAP_DRPAUSE;
  232. break;
  233. case TAP_IRSELECT:
  234. new_state = TAP_IRCAPTURE;
  235. break;
  236. case TAP_IRCAPTURE:
  237. case TAP_IRSHIFT:
  238. case TAP_IREXIT2:
  239. new_state = TAP_IRSHIFT;
  240. break;
  241. case TAP_IREXIT1:
  242. case TAP_IRPAUSE:
  243. new_state = TAP_IRPAUSE;
  244. break;
  245. default:
  246. LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
  247. exit(1);
  248. break;
  249. }
  250. }
  251. return new_state;
  252. }