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.
 
 
 
 
 
 

720 lines
25 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2008 by Marvell Semiconductors, Inc. *
  3. * Written by Nicolas Pitre <nico@marvell.com> *
  4. * *
  5. * Copyright (C) 2008 by Hongtao Zheng *
  6. * hontor@126.com *
  7. * *
  8. * This program is free software; you can redistribute it and/or modify *
  9. * it under the terms of the GNU General Public License as published by *
  10. * the Free Software Foundation; either version 2 of the License, or *
  11. * (at your option) any later version. *
  12. * *
  13. * This program is distributed in the hope that it will be useful, *
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  16. * GNU General Public License for more details. *
  17. * *
  18. * You should have received a copy of the GNU General Public License *
  19. * along with this program; if not, write to the *
  20. * Free Software Foundation, Inc., *
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  22. ***************************************************************************/
  23. /*
  24. * Marvell Feroceon (88F5182, 88F5281) support.
  25. *
  26. * The Feroceon core mimics the ARM926 ICE interface with the following
  27. * differences:
  28. *
  29. * - the MOE (method of entry) reporting is not implemented
  30. *
  31. * - breakpoint/watchpoint comparator #1 is seemingly not implemented
  32. *
  33. * - due to a different pipeline implementation, some injected debug
  34. * instruction sequences have to be somewhat different
  35. *
  36. * Other issues:
  37. *
  38. * - asserting DBGRQ doesn't work if target is looping on the undef vector
  39. *
  40. * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
  41. * not at the top, and rather meaningless due to existing discrepencies
  42. *
  43. * - the DCC channel is half duplex (only one FIFO for both directions) with
  44. * seemingly no proper flow control.
  45. */
  46. #ifdef HAVE_CONFIG_H
  47. #include "config.h"
  48. #endif
  49. #include "arm926ejs.h"
  50. #include "jtag.h"
  51. #include "log.h"
  52. #include <stdlib.h>
  53. #include <string.h>
  54. int feroceon_examine(struct target_s *target);
  55. int feroceon_target_create(struct target_s *target, Jim_Interp *interp);
  56. int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
  57. int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
  58. int feroceon_quit(void);
  59. int feroceon_assert_reset(target_t *target)
  60. {
  61. armv4_5_common_t *armv4_5 = target->arch_info;
  62. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  63. int ud = arm7_9->use_dbgrq;
  64. arm7_9->use_dbgrq = 0;
  65. if (target->reset_halt)
  66. arm7_9_halt(target);
  67. arm7_9->use_dbgrq = ud;
  68. return arm7_9_assert_reset(target);
  69. }
  70. target_type_t feroceon_target =
  71. {
  72. .name = "feroceon",
  73. .poll = arm7_9_poll,
  74. .arch_state = arm926ejs_arch_state,
  75. .target_request_data = arm7_9_target_request_data,
  76. .halt = arm7_9_halt,
  77. .resume = arm7_9_resume,
  78. .step = arm7_9_step,
  79. .assert_reset = feroceon_assert_reset,
  80. .deassert_reset = arm7_9_deassert_reset,
  81. .soft_reset_halt = arm926ejs_soft_reset_halt,
  82. .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
  83. .read_memory = arm7_9_read_memory,
  84. .write_memory = arm926ejs_write_memory,
  85. .bulk_write_memory = feroceon_bulk_write_memory,
  86. .checksum_memory = arm7_9_checksum_memory,
  87. .blank_check_memory = arm7_9_blank_check_memory,
  88. .run_algorithm = armv4_5_run_algorithm,
  89. .add_breakpoint = arm7_9_add_breakpoint,
  90. .remove_breakpoint = arm7_9_remove_breakpoint,
  91. .add_watchpoint = arm7_9_add_watchpoint,
  92. .remove_watchpoint = arm7_9_remove_watchpoint,
  93. .register_commands = arm926ejs_register_commands,
  94. .target_create = feroceon_target_create,
  95. .init_target = feroceon_init_target,
  96. .examine = feroceon_examine,
  97. .quit = feroceon_quit
  98. };
  99. int feroceon_dummy_clock_out(arm_jtag_t *jtag_info, u32 instr)
  100. {
  101. scan_field_t fields[3];
  102. u8 out_buf[4];
  103. u8 instr_buf[4];
  104. u8 sysspeed_buf = 0x0;
  105. /* prepare buffer */
  106. buf_set_u32(out_buf, 0, 32, 0);
  107. buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
  108. jtag_add_end_state(TAP_DRPAUSE);
  109. arm_jtag_scann(jtag_info, 0x1);
  110. arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
  111. fields[0].tap = jtag_info->tap;
  112. fields[0].num_bits = 32;
  113. fields[0].out_value = out_buf;
  114. fields[0].out_mask = NULL;
  115. fields[0].in_value = NULL;
  116. fields[0].in_handler = NULL;
  117. fields[0].in_handler_priv = NULL;
  118. fields[0].in_check_value = NULL;
  119. fields[0].in_check_mask = NULL;
  120. fields[1].tap = jtag_info->tap;
  121. fields[1].num_bits = 3;
  122. fields[1].out_value = &sysspeed_buf;
  123. fields[1].out_mask = NULL;
  124. fields[1].in_value = NULL;
  125. fields[1].in_check_value = NULL;
  126. fields[1].in_check_mask = NULL;
  127. fields[1].in_handler = NULL;
  128. fields[1].in_handler_priv = NULL;
  129. fields[2].tap = jtag_info->tap;
  130. fields[2].num_bits = 32;
  131. fields[2].out_value = instr_buf;
  132. fields[2].out_mask = NULL;
  133. fields[2].in_value = NULL;
  134. fields[2].in_check_value = NULL;
  135. fields[2].in_check_mask = NULL;
  136. fields[2].in_handler = NULL;
  137. fields[2].in_handler_priv = NULL;
  138. jtag_add_dr_scan(3, fields, -1);
  139. /* no jtag_add_runtest(0, -1) here */
  140. return ERROR_OK;
  141. }
  142. void feroceon_change_to_arm(target_t *target, u32 *r0, u32 *pc)
  143. {
  144. armv4_5_common_t *armv4_5 = target->arch_info;
  145. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  146. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  147. /*
  148. * save r0 before using it and put system in ARM state
  149. * to allow common handling of ARM and THUMB debugging
  150. */
  151. feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
  152. feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
  153. feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
  154. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
  155. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  156. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  157. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
  158. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  159. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  160. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
  161. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
  162. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  163. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  164. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
  165. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  166. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  167. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 0, NULL, 0);
  168. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  169. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  170. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  171. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  172. jtag_execute_queue();
  173. /*
  174. * fix program counter:
  175. * MOV R0, PC was the 7th instruction (+12)
  176. * reading PC in Thumb state gives address of instruction + 4
  177. */
  178. *pc -= (12 + 4);
  179. }
  180. void feroceon_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
  181. {
  182. int i;
  183. armv4_5_common_t *armv4_5 = target->arch_info;
  184. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  185. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  186. arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
  187. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  188. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  189. for (i = 0; i <= 15; i++)
  190. if (mask & (1 << i))
  191. arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
  192. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  193. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  194. }
  195. void feroceon_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
  196. {
  197. int i;
  198. armv4_5_common_t *armv4_5 = target->arch_info;
  199. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  200. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  201. int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
  202. u32 *buf_u32 = buffer;
  203. u16 *buf_u16 = buffer;
  204. u8 *buf_u8 = buffer;
  205. arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
  206. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  207. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  208. for (i = 0; i <= 15; i++)
  209. {
  210. if (mask & (1 << i)) {
  211. switch (size)
  212. {
  213. case 4:
  214. arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
  215. break;
  216. case 2:
  217. arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
  218. break;
  219. case 1:
  220. arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
  221. break;
  222. }
  223. }
  224. }
  225. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  226. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  227. }
  228. void feroceon_read_xpsr(target_t *target, u32 *xpsr, int spsr)
  229. {
  230. armv4_5_common_t *armv4_5 = target->arch_info;
  231. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  232. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  233. arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
  234. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  235. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  236. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  237. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  238. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  239. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  240. arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
  241. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  242. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  243. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
  244. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  245. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  246. }
  247. void feroceon_write_xpsr(target_t *target, u32 xpsr, int spsr)
  248. {
  249. armv4_5_common_t *armv4_5 = target->arch_info;
  250. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  251. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  252. LOG_DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
  253. arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
  254. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  255. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  256. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  257. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  258. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  259. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  260. arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
  261. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  262. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  263. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  264. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  265. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  266. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  267. arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
  268. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  269. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  270. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  271. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  272. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  273. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  274. arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
  275. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  276. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  277. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  278. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  279. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  280. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  281. }
  282. void feroceon_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
  283. {
  284. armv4_5_common_t *armv4_5 = target->arch_info;
  285. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  286. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  287. LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
  288. arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
  289. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  290. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  291. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  292. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  293. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  294. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  295. }
  296. void feroceon_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
  297. {
  298. int i;
  299. armv4_5_common_t *armv4_5 = target->arch_info;
  300. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  301. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  302. arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
  303. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  304. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  305. for (i = 0; i <= 15; i++)
  306. if (mask & (1 << i))
  307. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
  308. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  309. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  310. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  311. }
  312. void feroceon_branch_resume(target_t *target)
  313. {
  314. armv4_5_common_t *armv4_5 = target->arch_info;
  315. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  316. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  317. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  318. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  319. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  320. arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
  321. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
  322. arm7_9->need_bypass_before_restart = 1;
  323. }
  324. void feroceon_branch_resume_thumb(target_t *target)
  325. {
  326. LOG_DEBUG("-");
  327. armv4_5_common_t *armv4_5 = target->arch_info;
  328. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  329. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  330. u32 r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
  331. u32 pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
  332. (void)(r0); // use R0...
  333. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  334. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  335. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  336. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  337. arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); // add r0,pc,#1
  338. arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
  339. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  340. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  341. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL, 0);
  342. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  343. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  344. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, pc, NULL, 0);
  345. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  346. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
  347. pc = (pc & 2) >> 1;
  348. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
  349. arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
  350. arm7_9->need_bypass_before_restart = 1;
  351. }
  352. int feroceon_read_cp15(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)
  353. {
  354. armv4_5_common_t *armv4_5 = target->arch_info;
  355. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  356. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  357. int err;
  358. arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
  359. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
  360. err = arm7_9_execute_sys_speed(target);
  361. if (err != ERROR_OK)
  362. return err;
  363. arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
  364. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  365. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  366. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, value, 0);
  367. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  368. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  369. return jtag_execute_queue();
  370. }
  371. int feroceon_write_cp15(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)
  372. {
  373. armv4_5_common_t *armv4_5 = target->arch_info;
  374. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  375. arm_jtag_t *jtag_info = &arm7_9->jtag_info;
  376. arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0);
  377. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  378. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  379. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, value, NULL, 0);
  380. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  381. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  382. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
  383. arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
  384. arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
  385. return arm7_9_execute_sys_speed(target);
  386. }
  387. void feroceon_set_dbgrq(target_t *target)
  388. {
  389. armv4_5_common_t *armv4_5 = target->arch_info;
  390. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  391. reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
  392. buf_set_u32(dbg_ctrl->value, 0, 8, 2);
  393. embeddedice_store_reg(dbg_ctrl);
  394. }
  395. void feroceon_enable_single_step(target_t *target, u32 next_pc)
  396. {
  397. armv4_5_common_t *armv4_5 = target->arch_info;
  398. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  399. /* set a breakpoint there */
  400. embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
  401. embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
  402. embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
  403. embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
  404. embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
  405. }
  406. void feroceon_disable_single_step(target_t *target)
  407. {
  408. armv4_5_common_t *armv4_5 = target->arch_info;
  409. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  410. embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
  411. embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
  412. embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
  413. embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
  414. embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
  415. }
  416. int feroceon_examine_debug_reason(target_t *target)
  417. {
  418. /* the MOE is not implemented */
  419. if (target->debug_reason != DBG_REASON_SINGLESTEP)
  420. {
  421. target->debug_reason = DBG_REASON_DBGRQ;
  422. }
  423. return ERROR_OK;
  424. }
  425. int feroceon_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
  426. {
  427. int retval;
  428. armv4_5_common_t *armv4_5 = target->arch_info;
  429. arm7_9_common_t *arm7_9 = armv4_5->arch_info;
  430. enum armv4_5_state core_state = armv4_5->core_state;
  431. u32 x, flip, shift, save[7];
  432. int i;
  433. /*
  434. * We can't use the dcc flow control bits, so let's transfer data
  435. * with 31 bits and flip the MSB each time a new data word is sent.
  436. */
  437. static u32 dcc_code[] =
  438. {
  439. 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
  440. 0xe3a0301e, /* 1: mov r3, #30 */
  441. 0xe3a04002, /* mov r4, #2 */
  442. 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
  443. 0xe1310005, /* teq r1, r5 */
  444. 0x0afffffc, /* beq 1b */
  445. 0xe1a05001, /* mov r5, r1 */
  446. 0xe1a01081, /* mov r1, r1, lsl #1 */
  447. 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
  448. 0xe1320005, /* teq r2, r5 */
  449. 0x0afffffc, /* beq 3b */
  450. 0xe1a05002, /* mov r5, r2 */
  451. 0xe3c22102, /* bic r2, r2, #0x80000000 */
  452. 0xe1811332, /* orr r1, r1, r2, lsr r3 */
  453. 0xe2533001, /* subs r3, r3, #1 */
  454. 0xe4801004, /* str r1, [r0], #4 */
  455. 0xe1a01412, /* mov r1, r2, lsl r4 */
  456. 0xe2844001, /* add r4, r4, #1 */
  457. 0x4affffed, /* bmi 1b */
  458. 0xeafffff3, /* b 3b */
  459. };
  460. int dcc_size = sizeof(dcc_code);
  461. if (!arm7_9->dcc_downloads)
  462. return target->type->write_memory(target, address, 4, count, buffer);
  463. /* regrab previously allocated working_area, or allocate a new one */
  464. if (!arm7_9->dcc_working_area)
  465. {
  466. u8 dcc_code_buf[dcc_size];
  467. /* make sure we have a working area */
  468. if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK)
  469. {
  470. LOG_INFO("no working area available, falling back to memory writes");
  471. return target->type->write_memory(target, address, 4, count, buffer);
  472. }
  473. /* copy target instructions to target endianness */
  474. for (i = 0; i < dcc_size/4; i++)
  475. target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
  476. /* write DCC code to working area */
  477. if((retval = target->type->write_memory(target, arm7_9->dcc_working_area->address, 4, dcc_size, dcc_code_buf)) != ERROR_OK)
  478. {
  479. return retval;
  480. }
  481. }
  482. /* backup clobbered processor state */
  483. for (i = 0; i <= 5; i++)
  484. save[i] = buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32);
  485. save[i] = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
  486. /* set up target address in r0 */
  487. buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, address);
  488. armv4_5->core_cache->reg_list[0].valid = 1;
  489. armv4_5->core_cache->reg_list[0].dirty = 1;
  490. armv4_5->core_state = ARMV4_5_STATE_ARM;
  491. embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
  492. arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
  493. /* send data over */
  494. x = 0;
  495. flip = 0;
  496. shift = 1;
  497. for (i = 0; i < count; i++)
  498. {
  499. u32 y = target_buffer_get_u32(target, buffer);
  500. u32 z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
  501. embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
  502. x = y << (32 - shift);
  503. if (++shift >= 32 || i + 1 >= count)
  504. {
  505. z = (x >> 1) | (flip ^= 0x80000000);
  506. embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
  507. x = 0;
  508. shift = 1;
  509. }
  510. buffer += 4;
  511. }
  512. target_halt(target);
  513. while (target->state != TARGET_HALTED)
  514. target_poll(target);
  515. /* restore target state */
  516. for (i = 0; i <= 5; i++)
  517. {
  518. buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, save[i]);
  519. armv4_5->core_cache->reg_list[i].valid = 1;
  520. armv4_5->core_cache->reg_list[i].dirty = 1;
  521. }
  522. buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, save[i]);
  523. armv4_5->core_cache->reg_list[15].valid = 1;
  524. armv4_5->core_cache->reg_list[15].dirty = 1;
  525. armv4_5->core_state = core_state;
  526. return ERROR_OK;
  527. }
  528. int feroceon_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
  529. {
  530. arm9tdmi_init_target(cmd_ctx, target);
  531. return ERROR_OK;
  532. }
  533. int feroceon_quit(void)
  534. {
  535. return ERROR_OK;
  536. }
  537. int feroceon_target_create(struct target_s *target, Jim_Interp *interp)
  538. {
  539. armv4_5_common_t *armv4_5;
  540. arm7_9_common_t *arm7_9;
  541. arm926ejs_common_t *arm926ejs = calloc(1,sizeof(arm926ejs_common_t));
  542. arm926ejs_init_arch_info(target, arm926ejs, target->tap);
  543. armv4_5 = target->arch_info;
  544. arm7_9 = armv4_5->arch_info;
  545. /* override some insn sequence functions */
  546. arm7_9->change_to_arm = feroceon_change_to_arm;
  547. arm7_9->read_core_regs = feroceon_read_core_regs;
  548. arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
  549. arm7_9->read_xpsr = feroceon_read_xpsr;
  550. arm7_9->write_xpsr = feroceon_write_xpsr;
  551. arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
  552. arm7_9->write_core_regs = feroceon_write_core_regs;
  553. arm7_9->branch_resume = feroceon_branch_resume;
  554. arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
  555. /* must be implemented with only one comparator */
  556. arm7_9->enable_single_step = feroceon_enable_single_step;
  557. arm7_9->disable_single_step = feroceon_disable_single_step;
  558. /* MOE is not implemented */
  559. arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
  560. /* the standard ARM926 methods don't always work (don't ask...) */
  561. arm926ejs->read_cp15 = feroceon_read_cp15;
  562. arm926ejs->write_cp15 = feroceon_write_cp15;
  563. /* Note: asserting DBGRQ might not win over the undef exception.
  564. If that happens then just use "arm7_9 dbgrq disable". */
  565. arm7_9->use_dbgrq = 1;
  566. arm7_9->set_special_dbgrq = feroceon_set_dbgrq;
  567. /* only one working comparator */
  568. arm7_9->wp_available_max = 1;
  569. arm7_9->wp1_used_default = -1;
  570. return ERROR_OK;
  571. }
  572. int feroceon_examine(struct target_s *target)
  573. {
  574. armv4_5_common_t *armv4_5;
  575. arm7_9_common_t *arm7_9;
  576. int retval;
  577. retval = arm9tdmi_examine(target);
  578. if (retval!=ERROR_OK)
  579. return retval;
  580. armv4_5 = target->arch_info;
  581. arm7_9 = armv4_5->arch_info;
  582. /* the COMMS_CTRL bits are all contiguous */
  583. if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
  584. LOG_ERROR("unexpected Feroceon EICE version signature");
  585. arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
  586. arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
  587. arm7_9->has_monitor_mode = 1;
  588. /* vector catch reg is not initialized on reset */
  589. embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
  590. /* clear monitor mode, enable comparators */
  591. embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
  592. jtag_execute_queue();
  593. buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
  594. buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
  595. embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
  596. return ERROR_OK;
  597. }