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.

armv7m.c 26 KiB

Magnus Lundin <lundin@mlu.mine.nu>, Oyvind Harboe <oyvind.harboe@zylin.com>, David Brownell <david-b@pacbell.net>: Some cleanup of the ARMv7-M support: - Reference the relevant ARMv7-M ARM doc (DDI 0405C to non-Vendors), and update the Cortex-M3 doc refs (DDI 0337C is no longer available). - Those registers aren't actually general, and some are incorrect (per all public docs anyway). Update comments and code accordingly. * What the Core Debug facility exposes is *implementation-specific* not architectural. These values aren't fully portable. They match Cortex-M3 ... so no current implementation will make trouble, but the next v7m implementation might. * Four of the registers are actually not exposed that way. Before Cortex-M3 r2p0 they are read/written through MRS/MSR instructions. In that newest silicon, they are four bytes in one register, not four separate registers. - Update the CM3 code to report when that one register is available, and not try to access it when it isn't. Also declare the register numbers that an eventual MRS/MSR solution will need to be using. - Stop line wrapping the exception labels. So for parts before r2p0 OpenOCD behavior is effectively unchanged, and still buggy; but for those newer parts a few things might now be correct. Most current Cortex-M3 parts use r1p1 (or earlier); this seems to include most LM3S parts and all STM32 parts. Parts using r2p0 are available, and include fourth generation LM3S parts ("Tempest") plus AT91SAM3 and LPC17xx parts which are now sampling. git-svn-id: svn://svn.berlios.de/openocd/trunk@2543 b42882b7-edfa-0310-969c-e2dbd0fdcd60
15 years ago
Magnus Lundin <lundin@mlu.mine.nu>, Oyvind Harboe <oyvind.harboe@zylin.com>, David Brownell <david-b@pacbell.net>: Some cleanup of the ARMv7-M support: - Reference the relevant ARMv7-M ARM doc (DDI 0405C to non-Vendors), and update the Cortex-M3 doc refs (DDI 0337C is no longer available). - Those registers aren't actually general, and some are incorrect (per all public docs anyway). Update comments and code accordingly. * What the Core Debug facility exposes is *implementation-specific* not architectural. These values aren't fully portable. They match Cortex-M3 ... so no current implementation will make trouble, but the next v7m implementation might. * Four of the registers are actually not exposed that way. Before Cortex-M3 r2p0 they are read/written through MRS/MSR instructions. In that newest silicon, they are four bytes in one register, not four separate registers. - Update the CM3 code to report when that one register is available, and not try to access it when it isn't. Also declare the register numbers that an eventual MRS/MSR solution will need to be using. - Stop line wrapping the exception labels. So for parts before r2p0 OpenOCD behavior is effectively unchanged, and still buggy; but for those newer parts a few things might now be correct. Most current Cortex-M3 parts use r1p1 (or earlier); this seems to include most LM3S parts and all STM32 parts. Parts using r2p0 are available, and include fourth generation LM3S parts ("Tempest") plus AT91SAM3 and LPC17xx parts which are now sampling. git-svn-id: svn://svn.berlios.de/openocd/trunk@2543 b42882b7-edfa-0310-969c-e2dbd0fdcd60
15 years ago
Magnus Lundin <lundin@mlu.mine.nu>, Oyvind Harboe <oyvind.harboe@zylin.com>, David Brownell <david-b@pacbell.net>: Some cleanup of the ARMv7-M support: - Reference the relevant ARMv7-M ARM doc (DDI 0405C to non-Vendors), and update the Cortex-M3 doc refs (DDI 0337C is no longer available). - Those registers aren't actually general, and some are incorrect (per all public docs anyway). Update comments and code accordingly. * What the Core Debug facility exposes is *implementation-specific* not architectural. These values aren't fully portable. They match Cortex-M3 ... so no current implementation will make trouble, but the next v7m implementation might. * Four of the registers are actually not exposed that way. Before Cortex-M3 r2p0 they are read/written through MRS/MSR instructions. In that newest silicon, they are four bytes in one register, not four separate registers. - Update the CM3 code to report when that one register is available, and not try to access it when it isn't. Also declare the register numbers that an eventual MRS/MSR solution will need to be using. - Stop line wrapping the exception labels. So for parts before r2p0 OpenOCD behavior is effectively unchanged, and still buggy; but for those newer parts a few things might now be correct. Most current Cortex-M3 parts use r1p1 (or earlier); this seems to include most LM3S parts and all STM32 parts. Parts using r2p0 are available, and include fourth generation LM3S parts ("Tempest") plus AT91SAM3 and LPC17xx parts which are now sampling. git-svn-id: svn://svn.berlios.de/openocd/trunk@2543 b42882b7-edfa-0310-969c-e2dbd0fdcd60
15 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  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 "breakpoints.h"
  37. #include "armv7m.h"
  38. #include "algorithm.h"
  39. #include "register.h"
  40. #if 0
  41. #define _DEBUG_INSTRUCTION_EXECUTION_
  42. #endif
  43. /** Maps from enum armv7m_mode (except ARMV7M_MODE_ANY) to name. */
  44. char *armv7m_mode_strings[] =
  45. {
  46. "Thread", "Thread (User)", "Handler",
  47. };
  48. static char *armv7m_exception_strings[] =
  49. {
  50. "", "Reset", "NMI", "HardFault",
  51. "MemManage", "BusFault", "UsageFault", "RESERVED",
  52. "RESERVED", "RESERVED", "RESERVED", "SVCall",
  53. "DebugMonitor", "RESERVED", "PendSV", "SysTick"
  54. };
  55. #ifdef ARMV7_GDB_HACKS
  56. uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
  57. struct reg armv7m_gdb_dummy_cpsr_reg =
  58. {
  59. .name = "GDB dummy cpsr register",
  60. .value = armv7m_gdb_dummy_cpsr_value,
  61. .dirty = 0,
  62. .valid = 1,
  63. .size = 32,
  64. .arch_info = NULL,
  65. };
  66. #endif
  67. /*
  68. * These registers are not memory-mapped. The ARMv7-M profile includes
  69. * memory mapped registers too, such as for the NVIC (interrupt controller)
  70. * and SysTick (timer) modules; those can mostly be treated as peripherals.
  71. *
  72. * The ARMv6-M profile is almost identical in this respect, except that it
  73. * doesn't include basepri or faultmask registers.
  74. */
  75. static const struct {
  76. unsigned id;
  77. char *name;
  78. unsigned bits;
  79. } armv7m_regs[] = {
  80. { ARMV7M_R0, "r0", 32 },
  81. { ARMV7M_R1, "r1", 32 },
  82. { ARMV7M_R2, "r2", 32 },
  83. { ARMV7M_R3, "r3", 32 },
  84. { ARMV7M_R4, "r4", 32 },
  85. { ARMV7M_R5, "r5", 32 },
  86. { ARMV7M_R6, "r6", 32 },
  87. { ARMV7M_R7, "r7", 32 },
  88. { ARMV7M_R8, "r8", 32 },
  89. { ARMV7M_R9, "r9", 32 },
  90. { ARMV7M_R10, "r10", 32 },
  91. { ARMV7M_R11, "r11", 32 },
  92. { ARMV7M_R12, "r12", 32 },
  93. { ARMV7M_R13, "sp", 32 },
  94. { ARMV7M_R14, "lr", 32 },
  95. { ARMV7M_PC, "pc", 32 },
  96. { ARMV7M_xPSR, "xPSR", 32 },
  97. { ARMV7M_MSP, "msp", 32 },
  98. { ARMV7M_PSP, "psp", 32 },
  99. { ARMV7M_PRIMASK, "primask", 1 },
  100. { ARMV7M_BASEPRI, "basepri", 8 },
  101. { ARMV7M_FAULTMASK, "faultmask", 1 },
  102. { ARMV7M_CONTROL, "control", 2 },
  103. };
  104. #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
  105. /**
  106. * Restores target context using the cache of core registers set up
  107. * by armv7m_build_reg_cache(), calling optional core-specific hooks.
  108. */
  109. int armv7m_restore_context(struct target *target)
  110. {
  111. int i;
  112. struct armv7m_common *armv7m = target_to_armv7m(target);
  113. LOG_DEBUG(" ");
  114. if (armv7m->pre_restore_context)
  115. armv7m->pre_restore_context(target);
  116. for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
  117. {
  118. if (armv7m->core_cache->reg_list[i].dirty)
  119. {
  120. armv7m->write_core_reg(target, i);
  121. }
  122. }
  123. if (armv7m->post_restore_context)
  124. armv7m->post_restore_context(target);
  125. return ERROR_OK;
  126. }
  127. /* Core state functions */
  128. /**
  129. * Maps ISR number (from xPSR) to name.
  130. * Note that while names and meanings for the first sixteen are standardized
  131. * (with zero not a true exception), external interrupts are only numbered.
  132. * They are assigned by vendors, which generally assign different numbers to
  133. * peripherals (such as UART0 or a USB peripheral controller).
  134. */
  135. char *armv7m_exception_string(int number)
  136. {
  137. static char enamebuf[32];
  138. if ((number < 0) | (number > 511))
  139. return "Invalid exception";
  140. if (number < 16)
  141. return armv7m_exception_strings[number];
  142. sprintf(enamebuf, "External Interrupt(%i)", number - 16);
  143. return enamebuf;
  144. }
  145. static int armv7m_get_core_reg(struct reg *reg)
  146. {
  147. int retval;
  148. struct armv7m_core_reg *armv7m_reg = reg->arch_info;
  149. struct target *target = armv7m_reg->target;
  150. struct armv7m_common *armv7m = target_to_armv7m(target);
  151. if (target->state != TARGET_HALTED)
  152. {
  153. return ERROR_TARGET_NOT_HALTED;
  154. }
  155. retval = armv7m->read_core_reg(target, armv7m_reg->num);
  156. return retval;
  157. }
  158. static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
  159. {
  160. struct armv7m_core_reg *armv7m_reg = reg->arch_info;
  161. struct target *target = armv7m_reg->target;
  162. uint32_t value = buf_get_u32(buf, 0, 32);
  163. if (target->state != TARGET_HALTED)
  164. {
  165. return ERROR_TARGET_NOT_HALTED;
  166. }
  167. buf_set_u32(reg->value, 0, 32, value);
  168. reg->dirty = 1;
  169. reg->valid = 1;
  170. return ERROR_OK;
  171. }
  172. static int armv7m_read_core_reg(struct target *target, unsigned num)
  173. {
  174. uint32_t reg_value;
  175. int retval;
  176. struct armv7m_core_reg * armv7m_core_reg;
  177. struct armv7m_common *armv7m = target_to_armv7m(target);
  178. if (num >= ARMV7M_NUM_REGS)
  179. return ERROR_INVALID_ARGUMENTS;
  180. armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
  181. retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, &reg_value);
  182. buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
  183. armv7m->core_cache->reg_list[num].valid = 1;
  184. armv7m->core_cache->reg_list[num].dirty = 0;
  185. return retval;
  186. }
  187. static int armv7m_write_core_reg(struct target *target, unsigned num)
  188. {
  189. int retval;
  190. uint32_t reg_value;
  191. struct armv7m_core_reg *armv7m_core_reg;
  192. struct armv7m_common *armv7m = target_to_armv7m(target);
  193. if (num >= ARMV7M_NUM_REGS)
  194. return ERROR_INVALID_ARGUMENTS;
  195. reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
  196. armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
  197. retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, reg_value);
  198. if (retval != ERROR_OK)
  199. {
  200. LOG_ERROR("JTAG failure");
  201. armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
  202. return ERROR_JTAG_DEVICE_ERROR;
  203. }
  204. LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
  205. armv7m->core_cache->reg_list[num].valid = 1;
  206. armv7m->core_cache->reg_list[num].dirty = 0;
  207. return ERROR_OK;
  208. }
  209. /**
  210. * Returns generic ARM userspace registers to GDB.
  211. * GDB doesn't quite understand that most ARMs don't have floating point
  212. * hardware, so this also fakes a set of long-obsolete FPA registers that
  213. * are not used in EABI based software stacks.
  214. */
  215. int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
  216. {
  217. struct armv7m_common *armv7m = target_to_armv7m(target);
  218. int i;
  219. *reg_list_size = 26;
  220. *reg_list = malloc(sizeof(struct reg*) * (*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. (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
  234. (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
  235. #ifdef ARMV7_GDB_HACKS
  236. /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
  237. (*reg_list)[25] = &armv7m_gdb_dummy_cpsr_reg;
  238. /* ARMV7M is always in thumb mode, try to make GDB understand this
  239. * if it does not support this arch */
  240. *((char*)armv7m->core_cache->reg_list[15].value) |= 1;
  241. #else
  242. (*reg_list)[25] = &armv7m->core_cache->reg_list[ARMV7M_xPSR];
  243. #endif
  244. return ERROR_OK;
  245. }
  246. /* run to exit point. return error if exit point was not reached. */
  247. static int armv7m_run_and_wait(struct target *target, uint32_t entry_point, int timeout_ms, uint32_t exit_point, struct armv7m_common *armv7m)
  248. {
  249. uint32_t pc;
  250. int retval;
  251. /* This code relies on the target specific resume() and poll()->debug_entry()
  252. * sequence to write register values to the processor and the read them back */
  253. if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
  254. {
  255. return retval;
  256. }
  257. retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
  258. /* If the target fails to halt due to the breakpoint, force a halt */
  259. if (retval != ERROR_OK || target->state != TARGET_HALTED)
  260. {
  261. if ((retval = target_halt(target)) != ERROR_OK)
  262. return retval;
  263. if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
  264. {
  265. return retval;
  266. }
  267. return ERROR_TARGET_TIMEOUT;
  268. }
  269. armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
  270. if (pc != exit_point)
  271. {
  272. LOG_DEBUG("failed algoritm halted at 0x%" PRIx32 " ", pc);
  273. return ERROR_TARGET_TIMEOUT;
  274. }
  275. return ERROR_OK;
  276. }
  277. /** Runs a Thumb algorithm in the target. */
  278. int armv7m_run_algorithm(struct target *target,
  279. int num_mem_params, struct mem_param *mem_params,
  280. int num_reg_params, struct reg_param *reg_params,
  281. uint32_t entry_point, uint32_t exit_point,
  282. int timeout_ms, void *arch_info)
  283. {
  284. struct armv7m_common *armv7m = target_to_armv7m(target);
  285. struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
  286. enum armv7m_mode core_mode = armv7m->core_mode;
  287. int retval = ERROR_OK;
  288. uint32_t context[ARMV7M_NUM_REGS];
  289. if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
  290. {
  291. LOG_ERROR("current target isn't an ARMV7M target");
  292. return ERROR_TARGET_INVALID;
  293. }
  294. if (target->state != TARGET_HALTED)
  295. {
  296. LOG_WARNING("target not halted");
  297. return ERROR_TARGET_NOT_HALTED;
  298. }
  299. /* refresh core register cache */
  300. /* Not needed if core register cache is always consistent with target process state */
  301. for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++)
  302. {
  303. if (!armv7m->core_cache->reg_list[i].valid)
  304. armv7m->read_core_reg(target, i);
  305. context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
  306. }
  307. for (int i = 0; i < num_mem_params; i++)
  308. {
  309. if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
  310. return retval;
  311. }
  312. for (int i = 0; i < num_reg_params; i++)
  313. {
  314. struct reg *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
  315. // uint32_t regvalue;
  316. if (!reg)
  317. {
  318. LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
  319. return ERROR_INVALID_ARGUMENTS;
  320. }
  321. if (reg->size != reg_params[i].size)
  322. {
  323. LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
  324. return ERROR_INVALID_ARGUMENTS;
  325. }
  326. // regvalue = buf_get_u32(reg_params[i].value, 0, 32);
  327. armv7m_set_core_reg(reg, reg_params[i].value);
  328. }
  329. if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY)
  330. {
  331. LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
  332. buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value,
  333. 0, 1, armv7m_algorithm_info->core_mode);
  334. armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
  335. armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
  336. }
  337. /* REVISIT speed things up (3% or so in one case) by requiring
  338. * algorithms to include a BKPT instruction at each exit point.
  339. * This eliminates overheads of adding/removing a breakpoint.
  340. */
  341. /* ARMV7M always runs in Thumb state */
  342. if ((retval = breakpoint_add(target, exit_point, 2, BKPT_SOFT)) != ERROR_OK)
  343. {
  344. LOG_ERROR("can't add breakpoint to finish algorithm execution");
  345. return ERROR_TARGET_FAILURE;
  346. }
  347. retval = armv7m_run_and_wait(target, entry_point, timeout_ms, exit_point, armv7m);
  348. breakpoint_remove(target, exit_point);
  349. if (retval != ERROR_OK)
  350. {
  351. return retval;
  352. }
  353. /* Read memory values to mem_params[] */
  354. for (int i = 0; i < num_mem_params; i++)
  355. {
  356. if (mem_params[i].direction != PARAM_OUT)
  357. if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
  358. {
  359. return retval;
  360. }
  361. }
  362. /* Copy core register values to reg_params[] */
  363. for (int i = 0; i < num_reg_params; i++)
  364. {
  365. if (reg_params[i].direction != PARAM_OUT)
  366. {
  367. struct reg *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
  368. if (!reg)
  369. {
  370. LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
  371. return ERROR_INVALID_ARGUMENTS;
  372. }
  373. if (reg->size != reg_params[i].size)
  374. {
  375. LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
  376. return ERROR_INVALID_ARGUMENTS;
  377. }
  378. buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
  379. }
  380. }
  381. for (int i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
  382. {
  383. uint32_t regvalue;
  384. regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
  385. if (regvalue != context[i])
  386. {
  387. LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
  388. armv7m->core_cache->reg_list[i].name, context[i]);
  389. buf_set_u32(armv7m->core_cache->reg_list[i].value,
  390. 0, 32, context[i]);
  391. armv7m->core_cache->reg_list[i].valid = 1;
  392. armv7m->core_cache->reg_list[i].dirty = 1;
  393. }
  394. }
  395. armv7m->core_mode = core_mode;
  396. return retval;
  397. }
  398. /** Logs summary of ARMv7-M state for a halted target. */
  399. int armv7m_arch_state(struct target *target)
  400. {
  401. struct armv7m_common *armv7m = target_to_armv7m(target);
  402. uint32_t ctrl, sp;
  403. ctrl = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
  404. sp = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
  405. LOG_USER("target halted due to %s, current mode: %s %s\n"
  406. "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32,
  407. debug_reason_name(target),
  408. armv7m_mode_strings[armv7m->core_mode],
  409. armv7m_exception_string(armv7m->exception_number),
  410. buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
  411. buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_PC].value, 0, 32),
  412. (ctrl & 0x02) ? 'p' : 'm',
  413. sp);
  414. return ERROR_OK;
  415. }
  416. static const struct reg_arch_type armv7m_reg_type = {
  417. .get = armv7m_get_core_reg,
  418. .set = armv7m_set_core_reg,
  419. };
  420. /** Builds cache of architecturally defined registers. */
  421. struct reg_cache *armv7m_build_reg_cache(struct target *target)
  422. {
  423. struct armv7m_common *armv7m = target_to_armv7m(target);
  424. int num_regs = ARMV7M_NUM_REGS;
  425. struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
  426. struct reg_cache *cache = malloc(sizeof(struct reg_cache));
  427. struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
  428. struct armv7m_core_reg *arch_info = calloc(num_regs, sizeof(struct armv7m_core_reg));
  429. int i;
  430. #ifdef ARMV7_GDB_HACKS
  431. register_init_dummy(&armv7m_gdb_dummy_cpsr_reg);
  432. #endif
  433. /* Build the process context cache */
  434. cache->name = "arm v7m registers";
  435. cache->next = NULL;
  436. cache->reg_list = reg_list;
  437. cache->num_regs = num_regs;
  438. (*cache_p) = cache;
  439. armv7m->core_cache = cache;
  440. for (i = 0; i < num_regs; i++)
  441. {
  442. arch_info[i].num = armv7m_regs[i].id;
  443. arch_info[i].target = target;
  444. arch_info[i].armv7m_common = armv7m;
  445. reg_list[i].name = armv7m_regs[i].name;
  446. reg_list[i].size = armv7m_regs[i].bits;
  447. reg_list[i].value = calloc(1, 4);
  448. reg_list[i].dirty = 0;
  449. reg_list[i].valid = 0;
  450. reg_list[i].type = &armv7m_reg_type;
  451. reg_list[i].arch_info = &arch_info[i];
  452. }
  453. return cache;
  454. }
  455. /** Sets up target as a generic ARMv7-M core */
  456. int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
  457. {
  458. /* register arch-specific functions */
  459. target->arch_info = armv7m;
  460. armv7m->read_core_reg = armv7m_read_core_reg;
  461. armv7m->write_core_reg = armv7m_write_core_reg;
  462. return ERROR_OK;
  463. }
  464. /** Generates a CRC32 checksum of a memory region. */
  465. int armv7m_checksum_memory(struct target *target,
  466. uint32_t address, uint32_t count, uint32_t* checksum)
  467. {
  468. struct working_area *crc_algorithm;
  469. struct armv7m_algorithm armv7m_info;
  470. struct reg_param reg_params[2];
  471. int retval;
  472. static const uint16_t cortex_m3_crc_code[] = {
  473. 0x4602, /* mov r2, r0 */
  474. 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
  475. 0x460B, /* mov r3, r1 */
  476. 0xF04F, 0x0400, /* mov r4, #0 */
  477. 0xE013, /* b ncomp */
  478. /* nbyte: */
  479. 0x5D11, /* ldrb r1, [r2, r4] */
  480. 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
  481. 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
  482. 0xF04F, 0x0500, /* mov r5, #0 */
  483. /* loop: */
  484. 0x2800, /* cmp r0, #0 */
  485. 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
  486. 0xF105, 0x0501, /* add r5, r5, #1 */
  487. 0x4630, /* mov r0, r6 */
  488. 0xBFB8, /* it lt */
  489. 0xEA86, 0x0007, /* eor r0, r6, r7 */
  490. 0x2D08, /* cmp r5, #8 */
  491. 0xD1F4, /* bne loop */
  492. 0xF104, 0x0401, /* add r4, r4, #1 */
  493. /* ncomp: */
  494. 0x429C, /* cmp r4, r3 */
  495. 0xD1E9, /* bne nbyte */
  496. /* end: */
  497. 0xE7FE, /* b end */
  498. 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
  499. };
  500. uint32_t i;
  501. if (target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm) != ERROR_OK)
  502. {
  503. return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
  504. }
  505. /* convert flash writing code into a buffer in target endianness */
  506. for (i = 0; i < ARRAY_SIZE(cortex_m3_crc_code); i++)
  507. if ((retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i])) != ERROR_OK)
  508. {
  509. return retval;
  510. }
  511. armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
  512. armv7m_info.core_mode = ARMV7M_MODE_ANY;
  513. init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
  514. init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
  515. buf_set_u32(reg_params[0].value, 0, 32, address);
  516. buf_set_u32(reg_params[1].value, 0, 32, count);
  517. if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
  518. crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m3_crc_code)-6), 20000, &armv7m_info)) != ERROR_OK)
  519. {
  520. LOG_ERROR("error executing cortex_m3 crc algorithm");
  521. destroy_reg_param(&reg_params[0]);
  522. destroy_reg_param(&reg_params[1]);
  523. target_free_working_area(target, crc_algorithm);
  524. return retval;
  525. }
  526. *checksum = buf_get_u32(reg_params[0].value, 0, 32);
  527. destroy_reg_param(&reg_params[0]);
  528. destroy_reg_param(&reg_params[1]);
  529. target_free_working_area(target, crc_algorithm);
  530. return ERROR_OK;
  531. }
  532. /** Checks whether a memory region is zeroed. */
  533. int armv7m_blank_check_memory(struct target *target,
  534. uint32_t address, uint32_t count, uint32_t* blank)
  535. {
  536. struct working_area *erase_check_algorithm;
  537. struct reg_param reg_params[3];
  538. struct armv7m_algorithm 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 < ARRAY_SIZE(erase_check_code); 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. int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)
  584. {
  585. struct armv7m_common *armv7m = target_to_armv7m(target);
  586. struct reg *r = armv7m->core_cache->reg_list + 15;
  587. bool result = false;
  588. /* if we halted last time due to a bkpt instruction
  589. * then we have to manually step over it, otherwise
  590. * the core will break again */
  591. if (target->debug_reason == DBG_REASON_BREAKPOINT)
  592. {
  593. uint16_t op;
  594. uint32_t pc = buf_get_u32(r->value, 0, 32);
  595. pc &= ~1;
  596. if (target_read_u16(target, pc, &op) == ERROR_OK)
  597. {
  598. if ((op & 0xFF00) == 0xBE00)
  599. {
  600. pc = buf_get_u32(r->value, 0, 32) + 2;
  601. buf_set_u32(r->value, 0, 32, pc);
  602. r->dirty = true;
  603. r->valid = true;
  604. result = true;
  605. LOG_DEBUG("Skipping over BKPT instruction");
  606. }
  607. }
  608. }
  609. if (inst_found) {
  610. *inst_found = result;
  611. }
  612. return ERROR_OK;
  613. }
  614. /*--------------------------------------------------------------------------*/
  615. /*
  616. * Only stuff below this line should need to verify that its target
  617. * is an ARMv7-M node.
  618. *
  619. * FIXME yet none of it _does_ verify target types yet!
  620. */
  621. /*
  622. * Return the debug ap baseaddress in hexadecimal;
  623. * no extra output to simplify script processing
  624. */
  625. COMMAND_HANDLER(handle_dap_baseaddr_command)
  626. {
  627. struct target *target = get_current_target(CMD_CTX);
  628. struct armv7m_common *armv7m = target_to_armv7m(target);
  629. struct swjdp_common *swjdp = &armv7m->swjdp_info;
  630. uint32_t apsel, apselsave, baseaddr;
  631. int retval;
  632. apselsave = swjdp->apsel;
  633. switch (CMD_ARGC) {
  634. case 0:
  635. apsel = swjdp->apsel;
  636. break;
  637. case 1:
  638. COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
  639. break;
  640. default:
  641. return ERROR_COMMAND_SYNTAX_ERROR;
  642. }
  643. if (apselsave != apsel)
  644. dap_ap_select(swjdp, apsel);
  645. /* NOTE: assumes we're talking to a MEM-AP, which
  646. * has a base address. There are other kinds of AP,
  647. * though they're not common for now. This should
  648. * use the ID register to verify it's a MEM-AP.
  649. */
  650. dap_ap_read_reg_u32(swjdp, AP_REG_BASE, &baseaddr);
  651. retval = swjdp_transaction_endcheck(swjdp);
  652. command_print(CMD_CTX, "0x%8.8" PRIx32 "", baseaddr);
  653. if (apselsave != apsel)
  654. dap_ap_select(swjdp, apselsave);
  655. return retval;
  656. }
  657. /*
  658. * Return the debug ap id in hexadecimal;
  659. * no extra output to simplify script processing
  660. */
  661. COMMAND_HANDLER(handle_dap_apid_command)
  662. {
  663. struct target *target = get_current_target(CMD_CTX);
  664. struct armv7m_common *armv7m = target_to_armv7m(target);
  665. struct swjdp_common *swjdp = &armv7m->swjdp_info;
  666. return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
  667. }
  668. COMMAND_HANDLER(handle_dap_apsel_command)
  669. {
  670. struct target *target = get_current_target(CMD_CTX);
  671. struct armv7m_common *armv7m = target_to_armv7m(target);
  672. struct swjdp_common *swjdp = &armv7m->swjdp_info;
  673. return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
  674. }
  675. COMMAND_HANDLER(handle_dap_memaccess_command)
  676. {
  677. struct target *target = get_current_target(CMD_CTX);
  678. struct armv7m_common *armv7m = target_to_armv7m(target);
  679. struct swjdp_common *swjdp = &armv7m->swjdp_info;
  680. return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
  681. }
  682. COMMAND_HANDLER(handle_dap_info_command)
  683. {
  684. struct target *target = get_current_target(CMD_CTX);
  685. struct armv7m_common *armv7m = target_to_armv7m(target);
  686. struct swjdp_common *swjdp = &armv7m->swjdp_info;
  687. uint32_t apsel;
  688. switch (CMD_ARGC) {
  689. case 0:
  690. apsel = swjdp->apsel;
  691. break;
  692. case 1:
  693. COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
  694. break;
  695. default:
  696. return ERROR_COMMAND_SYNTAX_ERROR;
  697. }
  698. return dap_info_command(CMD_CTX, swjdp, apsel);
  699. }
  700. /* FIXME this table should be part of generic DAP support, and
  701. * be shared by the ARMv7-A/R and ARMv7-M support ...
  702. */
  703. static const struct command_registration armv7m_exec_command_handlers[] = {
  704. {
  705. .name = "info",
  706. .handler = handle_dap_info_command,
  707. .mode = COMMAND_EXEC,
  708. .help = "display ROM table for MEM-AP "
  709. "(default currently selected AP)",
  710. .usage = "[ap_num]",
  711. },
  712. {
  713. .name = "apsel",
  714. .handler = handle_dap_apsel_command,
  715. .mode = COMMAND_EXEC,
  716. .help = "Set the currently selected AP (default 0) "
  717. "and display the result",
  718. .usage = "[ap_num]",
  719. },
  720. {
  721. .name = "apid",
  722. .handler = handle_dap_apid_command,
  723. .mode = COMMAND_EXEC,
  724. .help = "return ID register from AP "
  725. "(default currently selected AP)",
  726. .usage = "[ap_num]",
  727. },
  728. {
  729. .name = "baseaddr",
  730. .handler = handle_dap_baseaddr_command,
  731. .mode = COMMAND_EXEC,
  732. .help = "return debug base address from MEM-AP "
  733. "(default currently selected AP)",
  734. .usage = "[ap_num]",
  735. },
  736. {
  737. .name = "memaccess",
  738. .handler = handle_dap_memaccess_command,
  739. .mode = COMMAND_EXEC,
  740. .help = "set/get number of extra tck for MEM-AP memory "
  741. "bus access [0-255]",
  742. .usage = "[cycles]",
  743. },
  744. COMMAND_REGISTRATION_DONE
  745. };
  746. const struct command_registration armv7m_command_handlers[] = {
  747. {
  748. .name = "dap",
  749. .mode = COMMAND_EXEC,
  750. .help = "Cortex DAP command group",
  751. .chain = armv7m_exec_command_handlers,
  752. },
  753. COMMAND_REGISTRATION_DONE
  754. };