target.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include "target.h"
  2. #include <furi.h>
  3. #include "swd.h"
  4. /* Cortex-M registers (taken from Blackmagic) */
  5. #define CORTEXM_PPB_BASE 0xe0000000U
  6. #define CORTEXM_SCS_BASE (CORTEXM_PPB_BASE + 0xe000U)
  7. #define CORTEXM_CPUID (CORTEXM_SCS_BASE + 0xd00U)
  8. #define CORTEXM_AIRCR (CORTEXM_SCS_BASE + 0xd0cU)
  9. #define CORTEXM_CFSR (CORTEXM_SCS_BASE + 0xd28U)
  10. #define CORTEXM_HFSR (CORTEXM_SCS_BASE + 0xd2cU)
  11. #define CORTEXM_DFSR (CORTEXM_SCS_BASE + 0xd30U)
  12. #define CORTEXM_CPACR (CORTEXM_SCS_BASE + 0xd88U)
  13. #define CORTEXM_DHCSR (CORTEXM_SCS_BASE + 0xdf0U)
  14. #define CORTEXM_DCRSR (CORTEXM_SCS_BASE + 0xdf4U)
  15. #define CORTEXM_DCRDR (CORTEXM_SCS_BASE + 0xdf8U)
  16. #define CORTEXM_DEMCR (CORTEXM_SCS_BASE + 0xdfcU)
  17. /* Debug Halting Control and Status Register (DHCSR) */
  18. /* This key must be written to bits 31:16 for write to take effect */
  19. #define CORTEXM_DHCSR_DBGKEY 0xa05f0000U
  20. /* Bits 31:26 - Reserved */
  21. #define CORTEXM_DHCSR_S_RESET_ST (1U << 25U)
  22. #define CORTEXM_DHCSR_S_RETIRE_ST (1U << 24U)
  23. /* Bits 23:20 - Reserved */
  24. #define CORTEXM_DHCSR_S_LOCKUP (1U << 19U)
  25. #define CORTEXM_DHCSR_S_SLEEP (1U << 18U)
  26. #define CORTEXM_DHCSR_S_HALT (1U << 17U)
  27. #define CORTEXM_DHCSR_S_REGRDY (1U << 16U)
  28. /* Bits 15:6 - Reserved */
  29. #define CORTEXM_DHCSR_C_SNAPSTALL (1U << 5U) /* v7m only */
  30. /* Bit 4 - Reserved */
  31. #define CORTEXM_DHCSR_C_MASKINTS (1U << 3U)
  32. #define CORTEXM_DHCSR_C_STEP (1U << 2U)
  33. #define CORTEXM_DHCSR_C_HALT (1U << 1U)
  34. #define CORTEXM_DHCSR_C_DEBUGEN (1U << 0U)
  35. /* Debug Exception and Monitor Control Register (DEMCR) */
  36. /* Bits 31:25 - Reserved */
  37. #define CORTEXM_DEMCR_TRCENA (1U << 24U)
  38. /* Bits 23:20 - Reserved */
  39. #define CORTEXM_DEMCR_MON_REQ (1U << 19U) /* v7m only */
  40. #define CORTEXM_DEMCR_MON_STEP (1U << 18U) /* v7m only */
  41. #define CORTEXM_DEMCR_VC_MON_PEND (1U << 17U) /* v7m only */
  42. #define CORTEXM_DEMCR_VC_MON_EN (1U << 16U) /* v7m only */
  43. /* Bits 15:11 - Reserved */
  44. #define CORTEXM_DEMCR_VC_HARDERR (1U << 10U)
  45. #define CORTEXM_DEMCR_VC_INTERR (1U << 9U) /* v7m only */
  46. #define CORTEXM_DEMCR_VC_BUSERR (1U << 8U) /* v7m only */
  47. #define CORTEXM_DEMCR_VC_STATERR (1U << 7U) /* v7m only */
  48. #define CORTEXM_DEMCR_VC_CHKERR (1U << 6U) /* v7m only */
  49. #define CORTEXM_DEMCR_VC_NOCPERR (1U << 5U) /* v7m only */
  50. #define CORTEXM_DEMCR_VC_MMERR (1U << 4U) /* v7m only */
  51. /* Bits 3:1 - Reserved */
  52. #define CORTEXM_DEMCR_VC_CORERESET (1U << 0U)
  53. #define CORTEXM_DHCSR_DEBUG_HALT (CORTEXM_DHCSR_C_DEBUGEN | CORTEXM_DHCSR_C_HALT)
  54. #define TAG "VgmTarget"
  55. static uint32_t prev_address;
  56. static bool target_memory_access_setup(uint32_t address) {
  57. bool success = false;
  58. do {
  59. // If the address was previously set up, do not waste time on it
  60. if(address != prev_address) {
  61. // Word access, no auto increment
  62. if(!swd_ap_write(
  63. SWD_AP_REG_RW_CSW,
  64. SWD_AP_REG_CSW_HPROT_DATA | SWD_AP_REG_CSW_HPROT_PRIVILIGED |
  65. SWD_AP_REG_CSW_HNONSEC | SWD_AP_REG_CSW_SIZE_WORD))
  66. break;
  67. if(!swd_ap_write(SWD_AP_REG_RW_TAR, address)) break;
  68. prev_address = address;
  69. }
  70. success = true;
  71. } while(false);
  72. return success;
  73. }
  74. static bool target_dbg_power_up(void) {
  75. if(!swd_dp_write(SWD_DP_REG_RW_CTRL_STAT, 0)) return false;
  76. uint32_t status;
  77. do {
  78. if(!swd_dp_read(SWD_DP_REG_RW_CTRL_STAT, &status)) return false;
  79. } while(status & (SWD_DP_REG_CTRL_STAT_CDBGPWRUPACK | SWD_DP_REG_CTRL_STAT_CSYSPWRUPACK));
  80. if(!swd_dp_write(
  81. SWD_DP_REG_RW_CTRL_STAT,
  82. (SWD_DP_REG_CTRL_STAT_CDBGPWRUPREQ | SWD_DP_REG_CTRL_STAT_CSYSPWRUPREQ)))
  83. return false;
  84. do {
  85. furi_delay_us(10000);
  86. if(!swd_dp_read(SWD_DP_REG_RW_CTRL_STAT, &status)) return false;
  87. } while((status & (SWD_DP_REG_CTRL_STAT_CDBGPWRUPACK | SWD_DP_REG_CTRL_STAT_CSYSPWRUPACK)) !=
  88. (SWD_DP_REG_CTRL_STAT_CDBGPWRUPACK | SWD_DP_REG_CTRL_STAT_CSYSPWRUPACK));
  89. return true;
  90. }
  91. static bool target_halt(void) {
  92. bool success = false;
  93. do {
  94. if(!target_write_memory_32(CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_DEBUG_HALT))
  95. break;
  96. bool target_halted = false;
  97. for(bool target_reset = false; !target_halted;) {
  98. uint32_t dhcsr;
  99. if(!target_read_memory_32(CORTEXM_DHCSR, &dhcsr)) break;
  100. if((dhcsr & CORTEXM_DHCSR_S_RESET_ST) && !target_reset) {
  101. target_reset = true;
  102. continue;
  103. }
  104. if((dhcsr & CORTEXM_DHCSR_DEBUG_HALT) == CORTEXM_DHCSR_DEBUG_HALT) {
  105. target_halted = true;
  106. }
  107. }
  108. if(!target_halted) break;
  109. if(!target_write_memory_32(
  110. CORTEXM_DEMCR,
  111. CORTEXM_DEMCR_TRCENA | CORTEXM_DEMCR_VC_HARDERR | CORTEXM_DEMCR_VC_CORERESET))
  112. break;
  113. bool target_local_reset = false;
  114. for(; !target_local_reset;) {
  115. uint32_t dhcsr;
  116. if(!target_read_memory_32(CORTEXM_DHCSR, &dhcsr)) break;
  117. if((dhcsr & CORTEXM_DHCSR_S_RESET_ST) == 0) {
  118. target_local_reset = true;
  119. }
  120. }
  121. if(!target_local_reset) break;
  122. success = true;
  123. } while(false);
  124. return success;
  125. }
  126. bool target_attach(uint32_t id) {
  127. bool success = false;
  128. do {
  129. // Reset previous memory address
  130. prev_address = UINT32_MAX;
  131. swd_select_target(id);
  132. uint32_t dpidr;
  133. if(!swd_dp_read(SWD_DP_REG_RO_DPIDR, &dpidr)) {
  134. FURI_LOG_E(TAG, "Failed to read DPIDR");
  135. break;
  136. }
  137. if(dpidr == 0) {
  138. FURI_LOG_E(TAG, "Zero DPIDR value");
  139. break;
  140. }
  141. if(!target_dbg_power_up()) {
  142. FURI_LOG_E(TAG, "Failed to enable debug power");
  143. break;
  144. }
  145. if(!target_halt()) {
  146. FURI_LOG_E(TAG, "Failed to halt target");
  147. break;
  148. }
  149. success = true;
  150. } while(false);
  151. return success;
  152. }
  153. bool target_detach(void) {
  154. bool success = false;
  155. do {
  156. if(!target_write_memory_32(CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_DEBUG_HALT))
  157. break;
  158. if(!target_write_memory_32(CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN))
  159. break;
  160. if(!target_write_memory_32(CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY)) break;
  161. success = true;
  162. } while(false);
  163. return success;
  164. }
  165. bool target_read_memory_32(uint32_t address, uint32_t* data) {
  166. furi_assert((address & 3U) == 0);
  167. bool success = false;
  168. do {
  169. if(!target_memory_access_setup(address)) break;
  170. if(!swd_ap_read(SWD_AP_REG_RW_DRW, data)) break;
  171. success = true;
  172. } while(false);
  173. return success;
  174. }
  175. bool target_write_memory_32(uint32_t address, uint32_t data) {
  176. furi_assert((address & 3U) == 0);
  177. bool success = false;
  178. do {
  179. if(!target_memory_access_setup(address)) break;
  180. if(!swd_ap_write(SWD_AP_REG_RW_DRW, data)) break;
  181. success = true;
  182. } while(false);
  183. return success;
  184. }