duan ellis target tcl work in progress
[fw/openocd] / src / target / mips_m4k.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_m4k.h"
28 #include "jtag.h"
29 #include "log.h"
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 /* cli handling */
35
36 /* forward declarations */
37 int mips_m4k_poll(target_t *target);
38 int mips_m4k_halt(struct target_s *target);
39 int mips_m4k_soft_reset_halt(struct target_s *target);
40 int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
41 int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
42 int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
43 int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
44 int mips_m4k_register_commands(struct command_context_s *cmd_ctx);
45 int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
46 int mips_m4k_quit(void);
47 int mips_m4k_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
48
49 int mips_m4k_examine(struct target_s *target);
50 int mips_m4k_assert_reset(target_t *target);
51 int mips_m4k_deassert_reset(target_t *target);
52
53 target_type_t mips_m4k_target =
54 {
55         .name = "mips_m4k",
56
57         .poll = mips_m4k_poll,
58         .arch_state = mips32_arch_state,
59
60         .target_request_data = NULL,
61
62         .halt = mips_m4k_halt,
63         .resume = mips_m4k_resume,
64         .step = mips_m4k_step,
65
66         .assert_reset = mips_m4k_assert_reset,
67         .deassert_reset = mips_m4k_deassert_reset,
68         .soft_reset_halt = mips_m4k_soft_reset_halt,
69         
70         .get_gdb_reg_list = mips32_get_gdb_reg_list,
71
72         .read_memory = mips_m4k_read_memory,
73         .write_memory = mips_m4k_write_memory,
74         .bulk_write_memory = mips_m4k_bulk_write_memory,
75         .checksum_memory = NULL,
76         .blank_check_memory = NULL,
77         
78         .run_algorithm = mips32_run_algorithm,
79
80         .add_breakpoint = mips_m4k_add_breakpoint,
81         .remove_breakpoint = mips_m4k_remove_breakpoint,
82         .add_watchpoint = mips_m4k_add_watchpoint,
83         .remove_watchpoint = mips_m4k_remove_watchpoint,
84
85         .register_commands = mips_m4k_register_commands,
86         .target_command = mips_m4k_target_command,
87         .init_target = mips_m4k_init_target,
88         .examine = mips_m4k_examine,
89         .quit = mips_m4k_quit
90 };
91
92 int mips_m4k_debug_entry(target_t *target)
93 {
94         u32 debug_reg;
95         mips32_common_t *mips32 = target->arch_info;
96         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
97         
98         /* read debug register */
99         mips_ejtag_read_debug(ejtag_info, &debug_reg);
100         
101         if ((target->debug_reason != DBG_REASON_DBGRQ)
102                 && (target->debug_reason != DBG_REASON_SINGLESTEP))
103         {
104 //              if (cortex_m3->nvic_dfsr & DFSR_BKPT)
105 //              {
106 //                      target->debug_reason = DBG_REASON_BREAKPOINT;
107 //                      if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
108 //                              target->debug_reason = DBG_REASON_WPTANDBKPT;
109 //              }
110 //              else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
111 //                      target->debug_reason = DBG_REASON_WATCHPOINT;
112         }
113         
114         if (debug_reg & EJTAG_DEBUG_DSS)
115         {
116                 /* stopped due to single step - clear step bit */
117                 mips_ejtag_config_step(ejtag_info, 0);
118         }
119         
120         mips32_save_context(target);
121         
122         LOG_DEBUG("entered debug state at PC 0x%x, target->state: %s", 
123                 *(u32*)(mips32->core_cache->reg_list[MIPS32_PC].value), 
124                   Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
125         
126         return ERROR_OK;
127 }
128
129 int mips_m4k_poll(target_t *target)
130 {
131         int retval;
132         mips32_common_t *mips32 = target->arch_info;
133         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
134         
135         /* read ejtag control reg */
136         jtag_add_end_state(TAP_RTI);
137         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
138         mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl);
139         
140         if (ejtag_info->ejtag_ctrl & EJTAG_CTRL_BRKST)
141         {
142                 if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
143                 {
144                         jtag_add_end_state(TAP_RTI);
145                         mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL);
146                         
147                         target->state = TARGET_HALTED;
148                         
149                         if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK)
150                                 return retval;
151                         
152                         target_call_event_callbacks(target, TARGET_EVENT_HALTED);
153                 }
154                 else if (target->state == TARGET_DEBUG_RUNNING)
155                 {
156                         target->state = TARGET_HALTED;
157                         
158                         if ((retval = mips_m4k_debug_entry(target)) != ERROR_OK)
159                                 return retval;
160                         
161                         target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
162                 }
163         }
164         else
165         {
166                 target->state = TARGET_RUNNING;
167         }
168         
169         if (ejtag_info->ejtag_ctrl & EJTAG_CTRL_ROCC)
170         {
171                 /* we have detected a reset, clear flag
172                  * otherwise ejtag will not work */
173                 jtag_add_end_state(TAP_RTI);
174                 ejtag_info->ejtag_ctrl &= ~EJTAG_CTRL_ROCC;
175                 
176                 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
177                 mips_ejtag_drscan_32(ejtag_info, &ejtag_info->ejtag_ctrl);
178                 LOG_DEBUG("Reset Detected");
179         }
180         
181 //      LOG_DEBUG("ctrl=0x%08X", ejtag_info->ejtag_ctrl);
182         
183         return ERROR_OK;
184 }
185
186 int mips_m4k_halt(struct target_s *target)
187 {
188         mips32_common_t *mips32 = target->arch_info;
189         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
190         
191         LOG_DEBUG("target->state: %s", 
192                   Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
193         
194         if (target->state == TARGET_HALTED)
195         {
196                 LOG_DEBUG("target was already halted");
197                 return ERROR_OK;
198         }
199         
200         if (target->state == TARGET_UNKNOWN)
201         {
202                 LOG_WARNING("target was in unknown state when halt was requested");
203         }
204         
205         if (target->state == TARGET_RESET) 
206         {
207                 if ((jtag_reset_config & RESET_SRST_PULLS_TRST) && jtag_srst)
208                 {
209                         LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
210                         return ERROR_TARGET_FAILURE;
211                 }
212                 else
213                 {
214                         /* we came here in a reset_halt or reset_init sequence
215                          * debug entry was already prepared in mips32_prepare_reset_halt()
216                          */
217                         target->debug_reason = DBG_REASON_DBGRQ;
218                         
219                         return ERROR_OK;
220                 }
221         }
222         
223         /* break processor */
224         mips_ejtag_enter_debug(ejtag_info);
225         
226         target->debug_reason = DBG_REASON_DBGRQ;
227         
228         return ERROR_OK;
229 }
230
231 int mips_m4k_assert_reset(target_t *target)
232 {
233         mips32_common_t *mips32 = target->arch_info;
234         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
235         
236         LOG_DEBUG("target->state: %s", 
237                   Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
238         
239         if (!(jtag_reset_config & RESET_HAS_SRST))
240         {
241                 LOG_ERROR("Can't assert SRST");
242                 return ERROR_FAIL;
243         }
244         
245         if (target->reset_halt)
246         {
247                 /* use hardware to catch reset */
248                 jtag_add_end_state(TAP_RTI);
249                 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT, NULL);
250         }
251         else
252         {
253                 jtag_add_end_state(TAP_RTI);
254                 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT, NULL);
255         }
256         
257         /* here we should issue a srst only, but we may have to assert trst as well */
258         if (jtag_reset_config & RESET_SRST_PULLS_TRST)
259         {
260                 jtag_add_reset(1, 1);
261         }
262         else
263         {
264                 jtag_add_reset(0, 1);
265         }
266         
267         target->state = TARGET_RESET;
268         jtag_add_sleep(50000);
269
270         mips32_invalidate_core_regs(target);
271
272     if (target->reset_halt)
273     {
274         int retval;
275                 if ((retval = target_halt(target))!=ERROR_OK)
276                         return retval;
277     }
278         
279         
280         return ERROR_OK;
281 }
282
283 int mips_m4k_deassert_reset(target_t *target)
284 {
285         LOG_DEBUG("target->state: %s", 
286                   Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
287         
288         /* deassert reset lines */
289         jtag_add_reset(0, 0);
290         
291         return ERROR_OK;
292 }
293
294 int mips_m4k_soft_reset_halt(struct target_s *target)
295 {
296         /* TODO */
297         return ERROR_OK;
298 }
299
300 int mips_m4k_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
301 {
302         mips32_common_t *mips32 = target->arch_info;
303         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
304         breakpoint_t *breakpoint = NULL;
305         u32 resume_pc;
306         
307         if (target->state != TARGET_HALTED)
308         {
309                 LOG_WARNING("target not halted");
310                 return ERROR_TARGET_NOT_HALTED;
311         }
312         
313         if (!debug_execution)
314         {
315                 target_free_all_working_areas(target);
316                 mips_m4k_enable_breakpoints(target);
317                 mips_m4k_enable_watchpoints(target);
318         }
319         
320         /* current = 1: continue on current pc, otherwise continue at <address> */
321         if (!current) 
322         {
323                 buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
324                 mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
325                 mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
326         }
327         
328         resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
329         
330         mips32_restore_context(target);
331         
332         /* the front-end may request us not to handle breakpoints */
333         if (handle_breakpoints)
334         {
335                 /* Single step past breakpoint at current address */
336                 if ((breakpoint = breakpoint_find(target, resume_pc)))
337                 {
338                         LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
339                         mips_m4k_unset_breakpoint(target, breakpoint);
340                         //mips_m4k_single_step_core(target);
341                         mips_m4k_set_breakpoint(target, breakpoint);
342                 }
343         }
344         
345         /* exit debug mode - enable interrupts if required */
346         mips_ejtag_exit_debug(ejtag_info, !debug_execution);
347         
348         /* registers are now invalid */
349         mips32_invalidate_core_regs(target);
350         
351         if (!debug_execution)
352         {
353                 target->state = TARGET_RUNNING;
354                 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
355                 LOG_DEBUG("target resumed at 0x%x", resume_pc);
356         }
357         else
358         {
359                 target->state = TARGET_DEBUG_RUNNING;
360                 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
361                 LOG_DEBUG("target debug resumed at 0x%x", resume_pc);
362         }
363         
364         return ERROR_OK;
365 }
366
367 int mips_m4k_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
368 {
369         /* get pointers to arch-specific information */
370         mips32_common_t *mips32 = target->arch_info;
371         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
372         breakpoint_t *breakpoint = NULL;
373
374         if (target->state != TARGET_HALTED)
375         {
376                 LOG_WARNING("target not halted");
377                 return ERROR_TARGET_NOT_HALTED;
378         }
379
380         /* current = 1: continue on current pc, otherwise continue at <address> */
381         if (!current)
382                 buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
383         
384         /* the front-end may request us not to handle breakpoints */
385         if (handle_breakpoints)
386                 if ((breakpoint = breakpoint_find(target, buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32))))
387                         mips_m4k_unset_breakpoint(target, breakpoint);
388         
389         /* restore context */
390         mips32_restore_context(target);
391         
392         /* configure single step mode */
393         mips_ejtag_config_step(ejtag_info, 1);
394         
395         target->debug_reason = DBG_REASON_SINGLESTEP;
396         
397         target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
398         
399         /* exit debug mode */
400         mips_ejtag_exit_debug(ejtag_info, 1);
401         
402         /* registers are now invalid */
403         mips32_invalidate_core_regs(target);
404         
405         if (breakpoint)
406                 mips_m4k_set_breakpoint(target, breakpoint);
407
408         LOG_DEBUG("target stepped ");
409         
410         mips_m4k_debug_entry(target);
411         target_call_event_callbacks(target, TARGET_EVENT_HALTED);
412         
413         return ERROR_OK;
414 }
415
416 void mips_m4k_enable_breakpoints(struct target_s *target)
417 {
418         breakpoint_t *breakpoint = target->breakpoints;
419         
420         /* set any pending breakpoints */
421         while (breakpoint)
422         {
423                 if (breakpoint->set == 0)
424                         mips_m4k_set_breakpoint(target, breakpoint);
425                 breakpoint = breakpoint->next;
426         }
427 }
428
429 int mips_m4k_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
430 {
431         /* TODO */
432         return ERROR_OK;
433 }
434
435 int mips_m4k_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
436 {
437         /* TODO */
438         return ERROR_OK;
439 }
440
441 int mips_m4k_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
442 {
443         /* TODO */
444         return ERROR_OK;
445 }
446
447 int mips_m4k_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
448 {
449         /* TODO */
450         return ERROR_OK;
451 }
452
453 int mips_m4k_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
454 {
455         /* TODO */
456         return ERROR_OK;
457 }
458
459 int mips_m4k_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
460 {
461         /* TODO */
462         return ERROR_OK;
463 }
464
465 int mips_m4k_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
466 {
467         /* TODO */
468         return ERROR_OK;
469 }
470
471 int mips_m4k_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
472 {
473         /* TODO */
474         return ERROR_OK;
475 }
476
477 void mips_m4k_enable_watchpoints(struct target_s *target)
478 {
479         watchpoint_t *watchpoint = target->watchpoints;
480         
481         /* set any pending watchpoints */
482         while (watchpoint)
483         {
484                 if (watchpoint->set == 0)
485                         mips_m4k_set_watchpoint(target, watchpoint);
486                 watchpoint = watchpoint->next;
487         }
488 }
489
490 int mips_m4k_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
491 {
492         mips32_common_t *mips32 = target->arch_info;
493         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
494         
495         LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
496
497         if (target->state != TARGET_HALTED)
498         {
499                 LOG_WARNING("target not halted");
500                 return ERROR_TARGET_NOT_HALTED;
501         }
502
503         /* sanitize arguments */
504         if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
505                 return ERROR_INVALID_ARGUMENTS;
506
507         if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
508                 return ERROR_TARGET_UNALIGNED_ACCESS;
509         
510         switch (size)
511         {
512                 case 4:
513                 case 2:
514                 case 1:
515                         return mips32_pracc_read_mem(ejtag_info, address, size, count, (void *)buffer);
516                 default:
517                         LOG_ERROR("BUG: we shouldn't get here");
518                         exit(-1);
519                         break;
520         }
521
522         return ERROR_OK;
523 }
524
525 int mips_m4k_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
526 {
527         mips32_common_t *mips32 = target->arch_info;
528         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
529         
530         LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
531
532         if (target->state != TARGET_HALTED)
533         {
534                 LOG_WARNING("target not halted");
535                 return ERROR_TARGET_NOT_HALTED;
536         }
537
538         /* sanitize arguments */
539         if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
540                 return ERROR_INVALID_ARGUMENTS;
541
542         if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
543                 return ERROR_TARGET_UNALIGNED_ACCESS;
544         
545         switch (size)
546         {
547                 case 4:
548                 case 2:
549                 case 1:
550                         mips32_pracc_write_mem(ejtag_info, address, size, count, (void *)buffer);
551                         break;
552                 default:
553                         LOG_ERROR("BUG: we shouldn't get here");
554                         exit(-1);
555                         break;
556         }
557         
558         return ERROR_OK;
559 }
560
561 int mips_m4k_register_commands(struct command_context_s *cmd_ctx)
562 {
563         int retval;
564         
565         retval = mips32_register_commands(cmd_ctx);
566         return retval;
567 }
568
569 int mips_m4k_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
570 {
571         mips32_build_reg_cache(target);
572         
573         return ERROR_OK;
574 }
575
576 int mips_m4k_quit(void)
577 {
578         return ERROR_OK;
579 }
580
581 int mips_m4k_init_arch_info(target_t *target, mips_m4k_common_t *mips_m4k, int chain_pos, char *variant)
582 {
583         mips32_common_t *mips32 = &mips_m4k->mips32_common;
584         
585         if (variant)
586         {
587                 mips_m4k->variant = strdup(variant);
588         }
589         else
590         {
591                 mips_m4k->variant = strdup("");
592         }
593         
594         mips_m4k->common_magic = MIPSM4K_COMMON_MAGIC;
595         
596         /* initialize mips4k specific info */
597         mips32_init_arch_info(target, mips32, chain_pos, variant);
598         mips32->arch_info = mips_m4k;
599                 
600         return ERROR_OK;
601 }
602
603 int mips_m4k_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
604 {
605         int chain_pos;
606         char *variant = NULL;
607         mips_m4k_common_t *mips_m4k = malloc(sizeof(mips_m4k_common_t));
608         
609         if (argc < 4)
610         {
611                 LOG_ERROR("'target mips4k' requires at least one additional argument");
612                 exit(-1);
613         }
614         
615         chain_pos = strtoul(args[3], NULL, 0);
616         
617         if (argc >= 5)
618                 variant = args[4];
619         
620         mips_m4k_init_arch_info(target, mips_m4k, chain_pos, variant);
621         
622         return ERROR_OK;
623 }
624
625 int mips_m4k_examine(struct target_s *target)
626 {
627         int retval;
628         mips32_common_t *mips32 = target->arch_info;
629         mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
630         u32 idcode = 0;
631         
632         target->type->examined = 1;
633         
634         mips_ejtag_get_idcode(ejtag_info, &idcode, NULL);
635         
636         if (((idcode >> 1) & 0x7FF) == 0x29)
637         {
638                 /* we are using a pic32mx so select ejtag port
639                  * as it is not selected by default */
640                 mips_ejtag_set_instr(ejtag_info, 0x05, NULL);
641                 LOG_DEBUG("PIC32MX Detected - using EJTAG Interface");
642         }
643         
644         /* init rest of ejtag interface */
645         if ((retval = mips_ejtag_init(ejtag_info)) != ERROR_OK)
646                 return retval;
647         
648         return ERROR_OK;
649 }
650
651 int mips_m4k_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
652 {
653         return mips_m4k_write_memory(target, address, 4, count, buffer);
654 }