arm-m-debug.c (4213B)
1 /* arm-m-debug 2 * 3 * Copyright 2011 Brian Swetland <swetland@frotz.net> 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <stdio.h> 19 #include <unistd.h> 20 21 #include <fw/types.h> 22 #include "debugger.h" 23 #include "rswdp.h" 24 25 #include "arm-v7m.h" 26 27 // CDBG_* comes from here right now -- FIXME 28 #include <protocol/rswdp.h> 29 30 static volatile int ATTN; 31 32 void swdp_interrupt(void) { 33 ATTN++; 34 if (write(2, "\b\b*INTERRUPT*\n", 16)) { /* do nothing */ } 35 } 36 37 38 int swdp_core_write(u32 n, u32 v) { 39 if (mem_wr_32(CDBG_REG_DATA, v)) { 40 return -1; 41 } 42 if (mem_wr_32(CDBG_REG_ADDR, (n & 0x1F) | 0x10000)) { 43 return -1; 44 } 45 return 0; 46 } 47 48 int swdp_core_read(u32 n, u32 *v) { 49 if (mem_wr_32(CDBG_REG_ADDR, n & 0x1F)) { 50 return -1; 51 } 52 if (mem_rd_32(CDBG_REG_DATA, v)) { 53 return -1; 54 } 55 return 0; 56 } 57 58 int swdp_core_read_all(u32 *v) { 59 unsigned n; 60 for (n = 0; n < 19; n++) { 61 if (mem_wr_32(CDBG_REG_ADDR, n & 0x1F)) { 62 return -1; 63 } 64 if (mem_rd_32(CDBG_REG_DATA, v++)) { 65 return -1; 66 } 67 } 68 return 0; 69 } 70 71 int swdp_step_no_ints = 0; 72 73 int swdp_core_halt(void) { 74 u32 x; 75 if (mem_rd_32(CDBG_CSR, &x)) return -1; 76 x &= (CDBG_C_HALT | CDBG_C_DEBUGEN | CDBG_C_MASKINTS); 77 x |= CDBG_CSR_KEY | CDBG_C_DEBUGEN | CDBG_C_HALT; 78 return mem_wr_32(CDBG_CSR, x); 79 } 80 81 int swdp_core_step(void) { 82 u32 x; 83 if (mem_rd_32(CDBG_CSR, &x)) return -1; 84 x &= (CDBG_C_HALT | CDBG_C_DEBUGEN | CDBG_C_MASKINTS); 85 x |= CDBG_CSR_KEY; 86 87 if (!(x & CDBG_C_HALT)) { 88 // HALT if we're not already HALTED 89 x |= CDBG_C_HALT | CDBG_C_DEBUGEN; 90 mem_wr_32(CDBG_CSR, x); 91 } 92 if (swdp_step_no_ints) { 93 // set MASKINTS if not already set 94 if (!(x & CDBG_C_MASKINTS)) { 95 x |= CDBG_C_MASKINTS; 96 mem_wr_32(CDBG_CSR, x); 97 } 98 } else { 99 // clear MASKINTs if not already clear 100 if (x & CDBG_C_MASKINTS) { 101 x &= (~CDBG_C_MASKINTS); 102 mem_wr_32(CDBG_CSR, x); 103 } 104 } 105 // STEP 106 x &= (~CDBG_C_HALT); 107 return mem_wr_32(CDBG_CSR, x | CDBG_C_STEP); 108 } 109 110 int swdp_core_resume(void) { 111 u32 x; 112 if (mem_rd_32(CDBG_CSR, &x)) return -1; 113 x &= (CDBG_C_HALT | CDBG_C_DEBUGEN | CDBG_C_MASKINTS); 114 x |= CDBG_CSR_KEY | CDBG_C_DEBUGEN; 115 116 if (swdp_step_no_ints > 1) { 117 // not just on during step, but always 118 if (!(x & CDBG_C_MASKINTS)) { 119 x |= CDBG_C_MASKINTS; 120 mem_wr_32(CDBG_CSR, x); 121 } 122 } else { 123 if (x & CDBG_C_MASKINTS) { 124 x &= (~CDBG_C_MASKINTS); 125 mem_wr_32(CDBG_CSR, x); 126 } 127 } 128 129 x &= ~(CDBG_C_HALT | CDBG_C_STEP); 130 return mem_wr_32(CDBG_CSR, x); 131 } 132 133 int swdp_core_wait_for_halt(void) { 134 int last = ATTN; 135 u32 csr; 136 for (;;) { 137 if (mem_rd_32(CDBG_CSR, &csr)) 138 return -1; 139 if (csr & CDBG_S_HALT) 140 return 0; 141 if (ATTN != last) 142 return -2; 143 } 144 } 145 146 int swdp_ahb_wait_for_change(u32 addr, u32 oldval) { 147 int last = ATTN; 148 u32 val; 149 do { 150 if (mem_rd_32(addr, &val)) 151 return -1; 152 if (ATTN != last) 153 return -2; 154 } while (val == oldval); 155 return 0; 156 } 157 158 int swdp_watchpoint(unsigned n, u32 addr, u32 func) { 159 int r; 160 if (n > 3) 161 return -1; 162 163 /* enable DWT, enable all exception traps */ 164 r = mem_wr_32(DEMCR, DEMCR_TRCENA | DEMCR_VC_CORERESET); 165 r |= mem_wr_32(DWT_FUNC(n), DWT_FN_DISABLED); 166 if (func != DWT_FN_DISABLED) { 167 r |= mem_wr_32(DWT_COMP(n), addr); 168 r |= mem_wr_32(DWT_MASK(n), 0); 169 r |= mem_wr_32(DWT_FUNC(n), func); 170 } 171 return r; 172 } 173 174 int swdp_watchpoint_pc(unsigned n, u32 addr) { 175 return swdp_watchpoint(n, addr, DWT_FN_WATCH_PC); 176 } 177 178 int swdp_watchpoint_rd(unsigned n, u32 addr) { 179 return swdp_watchpoint(n, addr, DWT_FN_WATCH_RD); 180 } 181 182 int swdp_watchpoint_wr(unsigned n, u32 addr) { 183 return swdp_watchpoint(n, addr, DWT_FN_WATCH_WR); 184 } 185 186 int swdp_watchpoint_rw(unsigned n, u32 addr) { 187 return swdp_watchpoint(n, addr, DWT_FN_WATCH_RW); 188 } 189 190 int swdp_watchpoint_disable(unsigned n) { 191 return swdp_watchpoint(n, 0, DWT_FN_DISABLED); 192 } 193