mdebug

cortex m series debugger
git clone http://frotz.net/git/mdebug.git
Log | Files | Refs | README | LICENSE

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