- add support for hardware breakpoints to mips32 target
[openocd.git] / src / target / mips_ejtag.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "mips32.h"
27 #include "mips_ejtag.h"
28
29 #include "binarybuffer.h"
30 #include "log.h"
31 #include "jtag.h"
32
33 #include <stdlib.h>
34
35 int mips_ejtag_set_instr(mips_ejtag_t *ejtag_info, int new_instr, in_handler_t handler)
36 {
37 jtag_device_t *device = jtag_get_device(ejtag_info->chain_pos);
38
39 if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
40 {
41 scan_field_t field;
42 u8 t[4];
43
44 field.device = ejtag_info->chain_pos;
45 field.num_bits = device->ir_length;
46 field.out_value = t;
47 buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
48 field.out_mask = NULL;
49 field.in_value = NULL;
50 field.in_check_value = NULL;
51 field.in_check_mask = NULL;
52 field.in_handler = handler;
53 field.in_handler_priv = NULL;
54 jtag_add_ir_scan(1, &field, -1);
55 }
56
57 return ERROR_OK;
58 }
59
60 int mips_ejtag_get_idcode(mips_ejtag_t *ejtag_info, u32 *idcode, in_handler_t handler)
61 {
62 scan_field_t field;
63
64 jtag_add_end_state(TAP_RTI);
65
66 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE, NULL);
67
68 field.device = ejtag_info->chain_pos;
69 field.num_bits = 32;
70 field.out_value = NULL;
71 field.out_mask = NULL;
72 field.in_value = (void*)idcode;
73 field.in_check_value = NULL;
74 field.in_check_mask = NULL;
75 field.in_handler = NULL;
76 field.in_handler_priv = NULL;
77 jtag_add_dr_scan(1, &field, -1);
78
79 if (jtag_execute_queue() != ERROR_OK)
80 {
81 LOG_ERROR("register read failed");
82 }
83
84 return ERROR_OK;
85 }
86
87 int mips_ejtag_get_impcode(mips_ejtag_t *ejtag_info, u32 *impcode, in_handler_t handler)
88 {
89 scan_field_t field;
90
91 jtag_add_end_state(TAP_RTI);
92
93 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE, NULL);
94
95 field.device = ejtag_info->chain_pos;
96 field.num_bits = 32;
97 field.out_value = NULL;
98 field.out_mask = NULL;
99 field.in_value = (void*)impcode;
100 field.in_check_value = NULL;
101 field.in_check_mask = NULL;
102 field.in_handler = NULL;
103 field.in_handler_priv = NULL;
104 jtag_add_dr_scan(1, &field, -1);
105
106 if (jtag_execute_queue() != ERROR_OK)
107 {
108 LOG_ERROR("register read failed");
109 }
110
111 return ERROR_OK;
112 }
113
114 int mips_ejtag_drscan_32(mips_ejtag_t *ejtag_info, u32 *data)
115 {
116 jtag_device_t *device;
117 device = jtag_get_device(ejtag_info->chain_pos);
118 scan_field_t field;
119 u8 t[4];
120 int retval;
121
122 field.device = ejtag_info->chain_pos;
123 field.num_bits = 32;
124 field.out_value = t;
125 buf_set_u32(field.out_value, 0, field.num_bits, *data);
126 field.out_mask = NULL;
127 field.in_value = (u8*)data;
128 field.in_check_value = NULL;
129 field.in_check_mask = NULL;
130 field.in_handler = NULL;
131 field.in_handler_priv = NULL;
132 jtag_add_dr_scan(1, &field, -1);
133
134 if ((retval = jtag_execute_queue()) != ERROR_OK)
135 {
136 LOG_ERROR("register read failed");
137 return retval;
138 }
139
140 return ERROR_OK;
141 }
142
143 int mips_ejtag_step_enable(mips_ejtag_t *ejtag_info)
144 {
145 u32 code[] = {
146 MIPS32_MTC0(1,31,0), /* move $1 to COP0 DeSave */
147 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
148 MIPS32_ORI(1,1,0x0100), /* set SSt bit in debug reg */
149 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
150 MIPS32_MFC0(1,31,0), /* move COP0 DeSave to $1 */
151 MIPS32_NOP,
152 MIPS32_B(NEG16(7)),
153 MIPS32_NOP,
154 };
155
156 mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
157 0, NULL, 0, NULL, 1);
158
159 return ERROR_OK;
160 }
161 int mips_ejtag_step_disable(mips_ejtag_t *ejtag_info)
162 {
163 u32 code[] = {
164 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
165 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
166 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
167 MIPS32_SW(1,0,15), /* sw $1,($15) */
168 MIPS32_SW(2,0,15), /* sw $2,($15) */
169 MIPS32_MFC0(1,23,0), /* move COP0 Debug to $1 */
170 MIPS32_LUI(2,0xFFFF), /* $2 = 0xfffffeff */
171 MIPS32_ORI(2,2,0xFEFF),
172 MIPS32_AND(1,1,2),
173 MIPS32_MTC0(1,23,0), /* move $1 to COP0 Debug */
174 MIPS32_LW(2,0,15),
175 MIPS32_LW(1,0,15),
176 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
177 MIPS32_NOP,
178 MIPS32_B(NEG16(15)),
179 MIPS32_NOP,
180 };
181
182 mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
183 0, NULL, 0, NULL, 1);
184
185 return ERROR_OK;
186 }
187
188 int mips_ejtag_config_step(mips_ejtag_t *ejtag_info, int enable_step)
189 {
190 if (enable_step)
191 return mips_ejtag_step_enable(ejtag_info);
192 return mips_ejtag_step_disable(ejtag_info);
193 }
194
195 int mips_ejtag_enter_debug(mips_ejtag_t *ejtag_info)
196 {
197 u32 ejtag_ctrl;
198 jtag_add_end_state(TAP_RTI);
199 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
200
201 /* set debug break bit */
202 ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK;
203 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
204
205 /* break bit will be cleared by hardware */
206 ejtag_ctrl = ejtag_info->ejtag_ctrl;
207 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
208 LOG_DEBUG("ejtag_ctrl: 0x%8.8x", ejtag_ctrl);
209 if((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0)
210 LOG_DEBUG("Failed to enter Debug Mode!");
211
212 return ERROR_OK;
213 }
214
215 int mips_ejtag_exit_debug(mips_ejtag_t *ejtag_info, int enable_interrupts)
216 {
217 u32 inst;
218 inst = MIPS32_DRET;
219
220 /* TODO : enable/disable interrrupts */
221
222 /* execute our dret instruction */
223 mips32_pracc_exec(ejtag_info, 1, &inst, 0, NULL, 0, NULL, 0);
224
225 return ERROR_OK;
226 }
227
228 int mips_ejtag_read_debug(mips_ejtag_t *ejtag_info, u32* debug_reg)
229 {
230 /* read ejtag ECR */
231 u32 code[] = {
232 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
233 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
234 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
235 MIPS32_SW(1,0,15), /* sw $1,($15) */
236 MIPS32_SW(2,0,15), /* sw $2,($15) */
237 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
238 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
239 MIPS32_MFC0(2,23,0), /* move COP0 Debug to $2 */
240 MIPS32_SW(2,0,1),
241 MIPS32_LW(2,0,15),
242 MIPS32_LW(1,0,15),
243 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
244 MIPS32_NOP,
245 MIPS32_B(NEG16(14)),
246 MIPS32_NOP,
247 };
248
249 mips32_pracc_exec(ejtag_info, sizeof(code)/sizeof(code[0]), code, \
250 0, NULL, 1, debug_reg, 1);
251
252 return ERROR_OK;
253 }
254
255 int mips_ejtag_init(mips_ejtag_t *ejtag_info)
256 {
257 u32 ejtag_version;
258
259 mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode, NULL);
260 LOG_DEBUG("impcode: 0x%8.8x", ejtag_info->impcode);
261
262 /* get ejtag version */
263 ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
264
265 switch (ejtag_version)
266 {
267 case 0:
268 LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
269 break;
270 case 1:
271 LOG_DEBUG("EJTAG: Version 2.5 Detected");
272 break;
273 case 2:
274 LOG_DEBUG("EJTAG: Version 2.6 Detected");
275 break;
276 case 3:
277 LOG_DEBUG("EJTAG: Version 3.1 Detected");
278 break;
279 default:
280 LOG_DEBUG("EJTAG: Unknown Version Detected");
281 break;
282 }
283 LOG_DEBUG("EJTAG: features:%s%s%s%s%s%s%s",
284 ejtag_info->impcode & (1<<28) ? " R3k": " R4k",
285 ejtag_info->impcode & (1<<24) ? " DINT": "",
286 ejtag_info->impcode & (1<<22) ? " ASID_8": "",
287 ejtag_info->impcode & (1<<21) ? " ASID_6": "",
288 ejtag_info->impcode & (1<<16) ? " MIPS16": "",
289 ejtag_info->impcode & (1<<14) ? " noDMA": " DMA",
290 ejtag_info->impcode & (1<<0) ? " MIPS64": " MIPS32"
291 );
292
293 if((ejtag_info->impcode & (1<<14)) == 0)
294 LOG_DEBUG("EJTAG: DMA Access Mode Support Enabled");
295
296 /* set initial state for ejtag control reg */
297 ejtag_info->ejtag_ctrl = EJTAG_CTRL_ROCC | EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN | EJTAG_CTRL_SETDEV;
298
299 return ERROR_OK;
300 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)