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.
 
 
 
 
 
 

829 lines
24 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2005 by Dominic Rath *
  3. * Dominic.Rath@gmx.de *
  4. * *
  5. * Copyright (C) 2006 by Magnus Lundin *
  6. * lundin@mlu.mine.nu *
  7. * *
  8. * Copyright (C) 2008 by Spencer Oliver *
  9. * spen@spen-soft.co.uk *
  10. * *
  11. * Copyright (C) 2007,2008 Øyvind Harboe *
  12. * oyvind.harboe@zylin.com *
  13. * *
  14. * This program is free software; you can redistribute it and/or modify *
  15. * it under the terms of the GNU General Public License as published by *
  16. * the Free Software Foundation; either version 2 of the License, or *
  17. * (at your option) any later version. *
  18. * *
  19. * This program is distributed in the hope that it will be useful, *
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  22. * GNU General Public License for more details. *
  23. * *
  24. * You should have received a copy of the GNU General Public License *
  25. * along with this program; if not, write to the *
  26. * Free Software Foundation, Inc., *
  27. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  28. * *
  29. * ARMv7-M Architecture, Application Level Reference Manual *
  30. * ARM DDI 0405C (September 2008) *
  31. * *
  32. ***************************************************************************/
  33. #ifdef HAVE_CONFIG_H
  34. #include "config.h"
  35. #endif
  36. #include "armv7m.h"
  37. #define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0])))
  38. #if 0
  39. #define _DEBUG_INSTRUCTION_EXECUTION_
  40. #endif
  41. char* armv7m_mode_strings[] =
  42. {
  43. "Thread", "Thread (User)", "Handler",
  44. };
  45. static char *armv7m_exception_strings[] =
  46. {
  47. "", "Reset", "NMI", "HardFault",
  48. "MemManage", "BusFault", "UsageFault", "RESERVED",
  49. "RESERVED", "RESERVED", "RESERVED", "SVCall",
  50. "DebugMonitor", "RESERVED", "PendSV", "SysTick"
  51. };
  52. uint8_t armv7m_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  53. reg_t armv7m_gdb_dummy_fp_reg =
  54. {
  55. "GDB dummy floating-point register", armv7m_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
  56. };
  57. uint8_t armv7m_gdb_dummy_fps_value[] = {0, 0, 0, 0};
  58. reg_t armv7m_gdb_dummy_fps_reg =
  59. {
  60. "GDB dummy floating-point status register", armv7m_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
  61. };
  62. #ifdef ARMV7_GDB_HACKS
  63. uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
  64. reg_t armv7m_gdb_dummy_cpsr_reg =
  65. {
  66. "GDB dummy cpsr register", armv7m_gdb_dummy_cpsr_value, 0, 1, 32, NULL, 0, NULL, 0
  67. };
  68. #endif
  69. /*
  70. * These registers are not memory-mapped. The ARMv7-M profile includes
  71. * memory mapped registers too, such as for the NVIC (interrupt controller)
  72. * and SysTick (timer) modules; those can mostly be treated as peripherals.
  73. */
  74. static const struct {
  75. unsigned id;
  76. char *name;
  77. unsigned bits;
  78. } armv7m_regs[] = {
  79. { ARMV7M_R0, "r0", 32 },
  80. { ARMV7M_R1, "r1", 32 },
  81. { ARMV7M_R2, "r2", 32 },
  82. { ARMV7M_R3, "r3", 32 },
  83. { ARMV7M_R4, "r4", 32 },
  84. { ARMV7M_R5, "r5", 32 },
  85. { ARMV7M_R6, "r6", 32 },
  86. { ARMV7M_R7, "r7", 32 },
  87. { ARMV7M_R8, "r8", 32 },
  88. { ARMV7M_R9, "r9", 32 },
  89. { ARMV7M_R10, "r10", 32 },
  90. { ARMV7M_R11, "r11", 32 },
  91. { ARMV7M_R12, "r12", 32 },
  92. { ARMV7M_R13, "sp", 32 },
  93. { ARMV7M_R14, "lr", 32 },
  94. { ARMV7M_PC, "pc", 32 },
  95. { ARMV7M_xPSR, "xPSR", 32 },
  96. { ARMV7M_MSP, "msp", 32 },
  97. { ARMV7M_PSP, "psp", 32 },
  98. { ARMV7M_PRIMASK, "primask", 1 },
  99. { ARMV7M_BASEPRI, "basepri", 8 },
  100. { ARMV7M_FAULTMASK, "faultmask", 1 },
  101. { ARMV7M_CONTROL, "control", 2 },
  102. };
  103. #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
  104. int armv7m_core_reg_arch_type = -1;
  105. int armv7m_dummy_core_reg_arch_type = -1;
  106. int armv7m_restore_context(target_t *target)
  107. {
  108. int i;
  109. /* get pointers to arch-specific information */
  110. armv7m_common_t *armv7m = target->arch_info;
  111. LOG_DEBUG(" ");
  112. if (armv7m->pre_restore_context)
  113. armv7m->pre_restore_context(target);
  114. for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
  115. {
  116. if (armv7m->core_cache->reg_list[i].dirty)
  117. {
  118. armv7m->write_core_reg(target, i);
  119. }
  120. }
  121. if (armv7m->post_restore_context)
  122. armv7m->post_restore_context(target);
  123. return ERROR_OK;
  124. }
  125. /* Core state functions */
  126. char *armv7m_exception_string(int number)
  127. {
  128. static char enamebuf[32];
  129. if ((number < 0) | (number > 511))
  130. return "Invalid exception";
  131. if (number < 16)
  132. return armv7m_exception_strings[number];
  133. sprintf(enamebuf, "External Interrupt(%i)", number - 16);
  134. return enamebuf;
  135. }
  136. int armv7m_get_core_reg(reg_t *reg)
  137. {
  138. int retval;
  139. armv7m_core_reg_t *armv7m_reg = reg->arch_info;
  140. target_t *target = armv7m_reg->target;
  141. armv7m_common_t *armv7m_target = target->arch_info;
  142. if (target->state != TARGET_HALTED)
  143. {
  144. return ERROR_TARGET_NOT_HALTED;
  145. }
  146. retval = armv7m_target->read_core_reg(target, armv7m_reg->num);
  147. return retval;
  148. }
  149. int armv7m_set_core_reg(reg_t *reg, uint8_t *buf)
  150. {
  151. armv7m_core_reg_t *armv7m_reg = reg->arch_info;
  152. target_t *target = armv7m_reg->target;
  153. uint32_t value = buf_get_u32(buf, 0, 32);
  154. if (target->state != TARGET_HALTED)
  155. {
  156. return ERROR_TARGET_NOT_HALTED;
  157. }
  158. buf_set_u32(reg->value, 0, 32, value);
  159. reg->dirty = 1;
  160. reg->valid = 1;
  161. return ERROR_OK;
  162. }
  163. int armv7m_read_core_reg(struct target_s *target, int num)
  164. {
  165. uint32_t reg_value;
  166. int retval;
  167. armv7m_core_reg_t * armv7m_core_reg;
  168. /* get pointers to arch-specific information */
  169. armv7m_common_t *armv7m = target->arch_info;
  170. if ((num < 0) || (num >= ARMV7M_NUM_REGS))
  171. return ERROR_INVALID_ARGUMENTS;
  172. armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
  173. retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, &reg_value);
  174. buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
  175. armv7m->core_cache->reg_list[num].valid = 1;
  176. armv7m->core_cache->reg_list[num].dirty = 0;
  177. return retval;
  178. }
  179. int armv7m_write_core_reg(struct target_s *target, int num)
  180. {
  181. int retval;
  182. uint32_t reg_value;
  183. armv7m_core_reg_t *armv7m_core_reg;
  184. /* get pointers to arch-specific information */
  185. armv7m_common_t *armv7m = target->arch_info;
  186. if ((num < 0) || (num >= ARMV7M_NUM_REGS))
  187. return ERROR_INVALID_ARGUMENTS;
  188. reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
  189. armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
  190. retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, reg_value);
  191. if (retval != ERROR_OK)
  192. {
  193. LOG_ERROR("JTAG failure");
  194. armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
  195. return ERROR_JTAG_DEVICE_ERROR;
  196. }
  197. LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
  198. armv7m->core_cache->reg_list[num].valid = 1;
  199. armv7m->core_cache->reg_list[num].dirty = 0;
  200. return ERROR_OK;
  201. }
  202. int armv7m_invalidate_core_regs(target_t *target)
  203. {
  204. /* get pointers to arch-specific information */
  205. armv7m_common_t *armv7m = target->arch_info;
  206. int i;
  207. for (i = 0; i < armv7m->core_cache->num_regs; i++)
  208. {
  209. armv7m->core_cache->reg_list[i].valid = 0;
  210. armv7m->core_cache->reg_list[i].dirty = 0;
  211. }
  212. return ERROR_OK;
  213. }
  214. int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
  215. {
  216. /* get pointers to arch-specific information */
  217. armv7m_common_t *armv7m = target->arch_info;
  218. int i;
  219. *reg_list_size = 26;
  220. *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
  221. /*
  222. * GDB register packet format for ARM:
  223. * - the first 16 registers are r0..r15
  224. * - (obsolete) 8 FPA registers
  225. * - (obsolete) FPA status
  226. * - CPSR
  227. */
  228. for (i = 0; i < 16; i++)
  229. {
  230. (*reg_list)[i] = &armv7m->core_cache->reg_list[i];
  231. }
  232. for (i = 16; i < 24; i++)
  233. {
  234. (*reg_list)[i] = &armv7m_gdb_dummy_fp_reg;
  235. }
  236. (*reg_list)[24] = &armv7m_gdb_dummy_fps_reg;
  237. #ifdef ARMV7_GDB_HACKS
  238. /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
  239. (*reg_list)[25] = &armv7m_gdb_dummy_cpsr_reg;
  240. /* ARMV7M is always in thumb mode, try to make GDB understand this
  241. * if it does not support this arch */
  242. *((char*)armv7m->core_cache->reg_list[15].value) |= 1;
  243. #else
  244. (*reg_list)[25] = &armv7m->core_cache->reg_list[ARMV7M_xPSR];
  245. #endif
  246. return ERROR_OK;
  247. }
  248. /* run to exit point. return error if exit point was not reached. */
  249. static int armv7m_run_and_wait(struct target_s *target, uint32_t entry_point, int timeout_ms, uint32_t exit_point, armv7m_common_t *armv7m)
  250. {
  251. uint32_t pc;
  252. int retval;
  253. /* This code relies on the target specific resume() and poll()->debug_entry()
  254. * sequence to write register values to the processor and the read them back */
  255. if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
  256. {
  257. return retval;
  258. }
  259. retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
  260. /* If the target fails to halt due to the breakpoint, force a halt */
  261. if (retval != ERROR_OK || target->state != TARGET_HALTED)
  262. {
  263. if ((retval = target_halt(target)) != ERROR_OK)
  264. return retval;
  265. if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
  266. {
  267. return retval;
  268. }
  269. return ERROR_TARGET_TIMEOUT;
  270. }
  271. armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
  272. if (pc != exit_point)
  273. {
  274. LOG_DEBUG("failed algoritm halted at 0x%" PRIx32 " ", pc);
  275. return ERROR_TARGET_TIMEOUT;
  276. }
  277. return ERROR_OK;
  278. }
  279. int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info)
  280. {
  281. /* get pointers to arch-specific information */
  282. armv7m_common_t *armv7m = target->arch_info;
  283. armv7m_algorithm_t *armv7m_algorithm_info = arch_info;
  284. enum armv7m_mode core_mode = armv7m->core_mode;
  285. int retval = ERROR_OK;
  286. int i;
  287. uint32_t context[ARMV7M_NUM_REGS];
  288. if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
  289. {
  290. LOG_ERROR("current target isn't an ARMV7M target");
  291. return ERROR_TARGET_INVALID;
  292. }
  293. if (target->state != TARGET_HALTED)
  294. {
  295. LOG_WARNING("target not halted");
  296. return ERROR_TARGET_NOT_HALTED;
  297. }
  298. /* refresh core register cache */
  299. /* Not needed if core register cache is always consistent with target process state */
  300. for (i = 0; i < ARMV7M_NUM_REGS; i++)
  301. {
  302. if (!armv7m->core_cache->reg_list[i].valid)
  303. armv7m->read_core_reg(target, i);
  304. context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
  305. }
  306. for (i = 0; i < num_mem_params; i++)
  307. {
  308. if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
  309. return retval;
  310. }
  311. for (i = 0; i < num_reg_params; i++)
  312. {
  313. reg_t *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
  314. // uint32_t regvalue;
  315. if (!reg)
  316. {
  317. LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
  318. exit(-1);
  319. }
  320. if (reg->size != reg_params[i].size)
  321. {
  322. LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
  323. exit(-1);
  324. }
  325. // regvalue = buf_get_u32(reg_params[i].value, 0, 32);
  326. armv7m_set_core_reg(reg, reg_params[i].value);
  327. }
  328. if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY)
  329. {
  330. LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
  331. buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value,
  332. 0, 1, armv7m_algorithm_info->core_mode);
  333. armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
  334. armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
  335. }
  336. /* ARMV7M always runs in Thumb state */
  337. if ((retval = breakpoint_add(target, exit_point, 2, BKPT_SOFT)) != ERROR_OK)
  338. {
  339. LOG_ERROR("can't add breakpoint to finish algorithm execution");
  340. return ERROR_TARGET_FAILURE;
  341. }
  342. retval = armv7m_run_and_wait(target, entry_point, timeout_ms, exit_point, armv7m);
  343. breakpoint_remove(target, exit_point);
  344. if (retval != ERROR_OK)
  345. {
  346. return retval;
  347. }
  348. /* Read memory values to mem_params[] */
  349. for (i = 0; i < num_mem_params; i++)
  350. {
  351. if (mem_params[i].direction != PARAM_OUT)
  352. if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
  353. {
  354. return retval;
  355. }
  356. }
  357. /* Copy core register values to reg_params[] */
  358. for (i = 0; i < num_reg_params; i++)
  359. {
  360. if (reg_params[i].direction != PARAM_OUT)
  361. {
  362. reg_t *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
  363. if (!reg)
  364. {
  365. LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
  366. exit(-1);
  367. }
  368. if (reg->size != reg_params[i].size)
  369. {
  370. LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
  371. exit(-1);
  372. }
  373. buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
  374. }
  375. }
  376. for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
  377. {
  378. uint32_t regvalue;
  379. regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
  380. if (regvalue != context[i])
  381. {
  382. LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
  383. armv7m->core_cache->reg_list[i].name, context[i]);
  384. buf_set_u32(armv7m->core_cache->reg_list[i].value,
  385. 0, 32, context[i]);
  386. armv7m->core_cache->reg_list[i].valid = 1;
  387. armv7m->core_cache->reg_list[i].dirty = 1;
  388. }
  389. }
  390. armv7m->core_mode = core_mode;
  391. return retval;
  392. }
  393. int armv7m_arch_state(struct target_s *target)
  394. {
  395. /* get pointers to arch-specific information */
  396. armv7m_common_t *armv7m = target->arch_info;
  397. uint32_t ctrl, sp;
  398. ctrl = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
  399. sp = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
  400. LOG_USER("target halted due to %s, current mode: %s %s\n"
  401. "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32,
  402. Jim_Nvp_value2name_simple(nvp_target_debug_reason,
  403. target->debug_reason)->name,
  404. armv7m_mode_strings[armv7m->core_mode],
  405. armv7m_exception_string(armv7m->exception_number),
  406. buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
  407. buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_PC].value, 0, 32),
  408. (ctrl & 0x02) ? 'p' : 'm',
  409. sp);
  410. return ERROR_OK;
  411. }
  412. reg_cache_t *armv7m_build_reg_cache(target_t *target)
  413. {
  414. /* get pointers to arch-specific information */
  415. armv7m_common_t *armv7m = target->arch_info;
  416. int num_regs = ARMV7M_NUM_REGS;
  417. reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
  418. reg_cache_t *cache = malloc(sizeof(reg_cache_t));
  419. reg_t *reg_list = calloc(num_regs, sizeof(reg_t));
  420. armv7m_core_reg_t *arch_info = calloc(num_regs, sizeof(armv7m_core_reg_t));
  421. int i;
  422. if (armv7m_core_reg_arch_type == -1)
  423. {
  424. armv7m_core_reg_arch_type = register_reg_arch_type(armv7m_get_core_reg, armv7m_set_core_reg);
  425. }
  426. register_init_dummy(&armv7m_gdb_dummy_fps_reg);
  427. #ifdef ARMV7_GDB_HACKS
  428. register_init_dummy(&armv7m_gdb_dummy_cpsr_reg);
  429. #endif
  430. register_init_dummy(&armv7m_gdb_dummy_fp_reg);
  431. /* Build the process context cache */
  432. cache->name = "arm v7m registers";
  433. cache->next = NULL;
  434. cache->reg_list = reg_list;
  435. cache->num_regs = num_regs;
  436. (*cache_p) = cache;
  437. armv7m->core_cache = cache;
  438. for (i = 0; i < num_regs; i++)
  439. {
  440. arch_info[i].num = armv7m_regs[i].id;
  441. arch_info[i].target = target;
  442. arch_info[i].armv7m_common = armv7m;
  443. reg_list[i].name = armv7m_regs[i].name;
  444. reg_list[i].size = armv7m_regs[i].bits;
  445. reg_list[i].value = calloc(1, 4);
  446. reg_list[i].dirty = 0;
  447. reg_list[i].valid = 0;
  448. reg_list[i].bitfield_desc = NULL;
  449. reg_list[i].num_bitfields = 0;
  450. reg_list[i].arch_type = armv7m_core_reg_arch_type;
  451. reg_list[i].arch_info = &arch_info[i];
  452. }
  453. return cache;
  454. }
  455. int armv7m_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
  456. {
  457. armv7m_build_reg_cache(target);
  458. return ERROR_OK;
  459. }
  460. int armv7m_init_arch_info(target_t *target, armv7m_common_t *armv7m)
  461. {
  462. /* register arch-specific functions */
  463. target->arch_info = armv7m;
  464. armv7m->read_core_reg = armv7m_read_core_reg;
  465. armv7m->write_core_reg = armv7m_write_core_reg;
  466. return ERROR_OK;
  467. }
  468. int armv7m_checksum_memory(struct target_s *target, uint32_t address, uint32_t count, uint32_t* checksum)
  469. {
  470. working_area_t *crc_algorithm;
  471. armv7m_algorithm_t armv7m_info;
  472. reg_param_t reg_params[2];
  473. int retval;
  474. static const uint16_t cortex_m3_crc_code[] = {
  475. 0x4602, /* mov r2, r0 */
  476. 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
  477. 0x460B, /* mov r3, r1 */
  478. 0xF04F, 0x0400, /* mov r4, #0 */
  479. 0xE013, /* b ncomp */
  480. /* nbyte: */
  481. 0x5D11, /* ldrb r1, [r2, r4] */
  482. 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
  483. 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
  484. 0xF04F, 0x0500, /* mov r5, #0 */
  485. /* loop: */
  486. 0x2800, /* cmp r0, #0 */
  487. 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
  488. 0xF105, 0x0501, /* add r5, r5, #1 */
  489. 0x4630, /* mov r0, r6 */
  490. 0xBFB8, /* it lt */
  491. 0xEA86, 0x0007, /* eor r0, r6, r7 */
  492. 0x2D08, /* cmp r5, #8 */
  493. 0xD1F4, /* bne loop */
  494. 0xF104, 0x0401, /* add r4, r4, #1 */
  495. /* ncomp: */
  496. 0x429C, /* cmp r4, r3 */
  497. 0xD1E9, /* bne nbyte */
  498. /* end: */
  499. 0xE7FE, /* b end */
  500. 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
  501. };
  502. uint32_t i;
  503. if (target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm) != ERROR_OK)
  504. {
  505. return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
  506. }
  507. /* convert flash writing code into a buffer in target endianness */
  508. for (i = 0; i < (sizeof(cortex_m3_crc_code)/sizeof(uint16_t)); i++)
  509. if ((retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i])) != ERROR_OK)
  510. {
  511. return retval;
  512. }
  513. armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
  514. armv7m_info.core_mode = ARMV7M_MODE_ANY;
  515. init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
  516. init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
  517. buf_set_u32(reg_params[0].value, 0, 32, address);
  518. buf_set_u32(reg_params[1].value, 0, 32, count);
  519. if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
  520. crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m3_crc_code)-6), 20000, &armv7m_info)) != ERROR_OK)
  521. {
  522. LOG_ERROR("error executing cortex_m3 crc algorithm");
  523. destroy_reg_param(&reg_params[0]);
  524. destroy_reg_param(&reg_params[1]);
  525. target_free_working_area(target, crc_algorithm);
  526. return retval;
  527. }
  528. *checksum = buf_get_u32(reg_params[0].value, 0, 32);
  529. destroy_reg_param(&reg_params[0]);
  530. destroy_reg_param(&reg_params[1]);
  531. target_free_working_area(target, crc_algorithm);
  532. return ERROR_OK;
  533. }
  534. int armv7m_blank_check_memory(struct target_s *target, uint32_t address, uint32_t count, uint32_t* blank)
  535. {
  536. working_area_t *erase_check_algorithm;
  537. reg_param_t reg_params[3];
  538. armv7m_algorithm_t armv7m_info;
  539. int retval;
  540. uint32_t i;
  541. static const uint16_t erase_check_code[] =
  542. {
  543. /* loop: */
  544. 0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
  545. 0xEA02, 0x0203, /* and r2, r2, r3 */
  546. 0x3901, /* subs r1, r1, #1 */
  547. 0xD1F9, /* bne loop */
  548. /* end: */
  549. 0xE7FE, /* b end */
  550. };
  551. /* make sure we have a working area */
  552. if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
  553. {
  554. return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
  555. }
  556. /* convert flash writing code into a buffer in target endianness */
  557. for (i = 0; i < (sizeof(erase_check_code)/sizeof(uint16_t)); i++)
  558. target_write_u16(target, erase_check_algorithm->address + i*sizeof(uint16_t), erase_check_code[i]);
  559. armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
  560. armv7m_info.core_mode = ARMV7M_MODE_ANY;
  561. init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
  562. buf_set_u32(reg_params[0].value, 0, 32, address);
  563. init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
  564. buf_set_u32(reg_params[1].value, 0, 32, count);
  565. init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
  566. buf_set_u32(reg_params[2].value, 0, 32, 0xff);
  567. if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
  568. erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code)-2), 10000, &armv7m_info)) != ERROR_OK)
  569. {
  570. destroy_reg_param(&reg_params[0]);
  571. destroy_reg_param(&reg_params[1]);
  572. destroy_reg_param(&reg_params[2]);
  573. target_free_working_area(target, erase_check_algorithm);
  574. return 0;
  575. }
  576. *blank = buf_get_u32(reg_params[2].value, 0, 32);
  577. destroy_reg_param(&reg_params[0]);
  578. destroy_reg_param(&reg_params[1]);
  579. destroy_reg_param(&reg_params[2]);
  580. target_free_working_area(target, erase_check_algorithm);
  581. return ERROR_OK;
  582. }
  583. /*
  584. * Return the debug ap baseaddress in hexadecimal;
  585. * no extra output to simplify script processing
  586. */
  587. static int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx,
  588. char *cmd, char **args, int argc)
  589. {
  590. target_t *target = get_current_target(cmd_ctx);
  591. armv7m_common_t *armv7m = target->arch_info;
  592. swjdp_common_t *swjdp = &armv7m->swjdp_info;
  593. uint32_t apsel, apselsave, baseaddr;
  594. int retval;
  595. apsel = swjdp->apsel;
  596. apselsave = swjdp->apsel;
  597. if (argc > 0)
  598. {
  599. apsel = strtoul(args[0], NULL, 0);
  600. }
  601. if (apselsave != apsel)
  602. {
  603. dap_ap_select(swjdp, apsel);
  604. }
  605. dap_ap_read_reg_u32(swjdp, 0xF8, &baseaddr);
  606. retval = swjdp_transaction_endcheck(swjdp);
  607. command_print(cmd_ctx, "0x%8.8" PRIx32 "", baseaddr);
  608. if (apselsave != apsel)
  609. {
  610. dap_ap_select(swjdp, apselsave);
  611. }
  612. return retval;
  613. }
  614. /*
  615. * Return the debug ap id in hexadecimal;
  616. * no extra output to simplify script processing
  617. */
  618. extern int handle_dap_apid_command(struct command_context_s *cmd_ctx,
  619. char *cmd, char **args, int argc)
  620. {
  621. target_t *target = get_current_target(cmd_ctx);
  622. armv7m_common_t *armv7m = target->arch_info;
  623. swjdp_common_t *swjdp = &armv7m->swjdp_info;
  624. return dap_apid_command(cmd_ctx, swjdp, args, argc);
  625. }
  626. static int handle_dap_apsel_command(struct command_context_s *cmd_ctx,
  627. char *cmd, char **args, int argc)
  628. {
  629. target_t *target = get_current_target(cmd_ctx);
  630. armv7m_common_t *armv7m = target->arch_info;
  631. swjdp_common_t *swjdp = &armv7m->swjdp_info;
  632. return dap_apsel_command(cmd_ctx, swjdp, args, argc);
  633. }
  634. static int handle_dap_memaccess_command(struct command_context_s *cmd_ctx,
  635. char *cmd, char **args, int argc)
  636. {
  637. target_t *target = get_current_target(cmd_ctx);
  638. armv7m_common_t *armv7m = target->arch_info;
  639. swjdp_common_t *swjdp = &armv7m->swjdp_info;
  640. return dap_memaccess_command(cmd_ctx, swjdp, args, argc);
  641. }
  642. static int handle_dap_info_command(struct command_context_s *cmd_ctx,
  643. char *cmd, char **args, int argc)
  644. {
  645. target_t *target = get_current_target(cmd_ctx);
  646. armv7m_common_t *armv7m = target->arch_info;
  647. swjdp_common_t *swjdp = &armv7m->swjdp_info;
  648. uint32_t apsel;
  649. apsel = swjdp->apsel;
  650. if (argc > 0)
  651. apsel = strtoul(args[0], NULL, 0);
  652. return dap_info_command(cmd_ctx, swjdp, apsel);
  653. }
  654. int armv7m_register_commands(struct command_context_s *cmd_ctx)
  655. {
  656. command_t *arm_adi_v5_dap_cmd;
  657. arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
  658. NULL, COMMAND_ANY,
  659. "cortex dap specific commands");
  660. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
  661. handle_dap_info_command, COMMAND_EXEC,
  662. "Displays dap info for ap [num],"
  663. "default currently selected AP");
  664. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
  665. handle_dap_apsel_command, COMMAND_EXEC,
  666. "Select a different AP [num] (default 0)");
  667. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
  668. handle_dap_apid_command, COMMAND_EXEC,
  669. "Displays id reg from AP [num], "
  670. "default currently selected AP");
  671. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
  672. handle_dap_baseaddr_command, COMMAND_EXEC,
  673. "Displays debug base address from AP [num],"
  674. "default currently selected AP");
  675. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
  676. handle_dap_memaccess_command, COMMAND_EXEC,
  677. "set/get number of extra tck for mem-ap "
  678. "memory bus access [0-255]");
  679. return ERROR_OK;
  680. }