From fdaad416b2bd4fe89d28ec46c621d188e52b1490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=A4gel=20=28DF5EQ=29?= Date: Tue, 24 Feb 2015 11:58:40 +1300 Subject: [PATCH] jtaglib: implement breakpoints. --- drivers/eem_defs.h | 192 +++++++++++++++++++++++++++++++++++++++++++++ drivers/jtaglib.c | 100 ++++++++++++++++++++++- drivers/jtaglib.h | 12 ++- drivers/pif.c | 56 ++++++++++++- 4 files changed, 354 insertions(+), 6 deletions(-) create mode 100644 drivers/eem_defs.h diff --git a/drivers/eem_defs.h b/drivers/eem_defs.h new file mode 100644 index 0000000..10701f6 --- /dev/null +++ b/drivers/eem_defs.h @@ -0,0 +1,192 @@ +/* + * EEM_defs.h + * + * + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _EEM_DEFS_H_ +#define _EEM_DEFS_H_ + +#define FALSE 0 +#define TRUE 1 + +#define WRITE 0 +#define READ 1 + +#define TRIGFLAG 0x8E +#define EEMVER 0x86 +/* Definition for EEM General Clock Control Register */ +#define GENCLKCTRL 0x88 +/* Definitions for EEM General Clock Control Register */ +#define MCLK_SEL0 0x0000 +#define SMCLK_SEL0 0x0000 +#define ACLK_SEL0 0x0000 +#define MCLK_SEL3 0x6000 +#define SMCLK_SEL3 0x0C00 +#define ACLK_SEL3 0x0180 +#define STOP_MCLK 0x0008 +#define STOP_SMCLK 0x0004 +#define STOP_ACLK 0x0002 +/* Definition for EEM Module Clock Control Register 0 */ +#define MODCLKCTRL0 0x8A +/* Definition for EEM General Debug Control Register */ +#define GENCTRL 0x82 +/* Definitions for EEM General Debug Control Register */ +#define EEM_EN 0x0001 +#define CLEAR_STOP 0x0002 +#define EMU_CLK_EN 0x0004 +#define EMU_FEAT_EN 0x0008 +#define DEB_TRIG_LATCH 0x0010 +#define EEM_RST 0x0040 +#define E_STOPPED 0x0080 +/* Defintions for Trigger Block base addresses */ +#define TB0 0x0000 +#define TB1 0x0008 +#define TB2 0x0010 +#define TB3 0x0018 +#define TB4 0x0020 +#define TB5 0x0028 +#define TB6 0x0030 +#define TB7 0x0038 +#define TB8 0x0040 +#define TB9 0x0048 +/* Definitions for Trigger Block register addresses */ +#define MBTRIGxVAL 0x0000 +#define MBTRIGxCTL 0x0002 +#define MBTRIGxMSK 0x0004 +#define MBTRIGxCMB 0x0006 +/* Definitions for MAB/MDB Trigger Control Register */ +#define MAB 0x0000 +#define MDB 0x0001 +#define TRIG_0 0x0000 // Instruction Fetch +#define TRIG_1 0x0002 // Instruction Fetch Hold +#define TRIG_2 0x0004 // No Instruction Fetch +#define TRIG_3 0x0006 // Don't care +#define TRIG_4 0x0020 // No Instruction Fetch & Read +#define TRIG_5 0x0022 // No Instruction Fetch & Write +#define TRIG_6 0x0024 // Read +#define TRIG_7 0x0026 // Write +#define TRIG_8 0x0040 // No Instruction Fetch & No DMA Access +#define TRIG_9 0x0042 // DMA Access (Read or Write) +#define TRIG_A 0x0044 // No DMA Access +#define TRIG_B 0x0046 // Write & No DMA Access +#define TRIG_C 0x0060 // No Instruction Fetch & Read & No DMA Access +#define TRIG_D 0x0062 // Read & No DMA Access +#define TRIG_E 0x0064 // Read & DMA Access +#define TRIG_F 0x0066 // Write & DMA Access +#define CMP_EQUAL 0x0000 +#define CMP_GREATER 0x0008 +#define CMP_LESS 0x0010 +#define CMP_NOT_EQUAL 0x0018 +/* Definitions for MAB/MDB Trigger Mask Register */ +#define NO_MASK 0x00000 +#define MASK_ALL 0xFFFFF +#define MASK_XADDR 0xF0000 +#define MASK_HBYTE 0x0FF00 +#define MASK_LBYTE 0x000FF +/* Definitions for MAB/MDB Combination Register & Reaction Registers*/ +#define EN0 0x0001 +#define EN1 0x0002 +#define EN2 0x0004 +#define EN3 0x0008 +#define EN4 0x0010 +#define EN5 0x0020 +#define EN6 0x0040 +#define EN7 0x0080 +#define EN8 0x0100 +#define EN9 0x0200 + +#define STOR_CTL 0x9E +/* Definitions for State Storage Control Register */ +#define VAR_WATCH0 0x0000 // Two +#define VAR_WATCH1 0x2000 // Four +#define VAR_WATCH2 0x4000 // Six +#define VAR_WATCH3 0x6000 // Eight +#define STOR_FULL 0x0200 +#define STOR_WRIT 0x0100 +#define STOR_TEST 0x0080 +#define STOR_RST 0x0040 +#define STOR_STOP_ON_TRIG 0x0020 +#define STOR_START_ON_TRIG 0x0010 +#define STOR_ONE_SHOT 0x0008 +#define STOR_MODE0 0x0000 // Store on enabled triggers +#define STOR_MODE1 0x0002 // Store on Instruction Fetch +#define STOR_MODE2 0x0004 // Variable Watch +#define STOR_MODE3 0x0006 // Store all bus cycles +#define STOR_EN 0x0001 // enable state storage + +/* Definitions for Reaction Registers */ +#define STOR_REACT 0x98 +#define BREAKREACT 0x80 +#define EVENT_REACT 0x94 + +#define EVENT_CTRL 0x96 +#define EVENT_TRIG 0x0001 + +/* Definitions for Cycle Counters */ +#define CCNT0CTL 0xB0 +#define CCNT0L 0xB2 +#define CCNT0H 0xB4 +#define CCNT1CTL 0xB8 +#define CCNT1L 0xBA +#define CCNT1H 0xBC +#define CCNT1REACT 0xBE + +/* Definitions for Cycle Counter Control Register */ +#define CCNTMODE0 0x0000 // Counter stopped +#define CCNTMODE1 0x0001 // Increment on reaction +#define CCNTMODE4 0x0004 // Increment on instruction fetch cycles +#define CCNTMODE5 0x0005 // Increment on all bus cycles (including DMA cycles) +#define CCNTMODE6 0x0006 // Increment on all CPU bus cycles (excluding DMA cycles) +#define CCNTMODE7 0x0007 // Increment on all DMA bus cycles +#define CCNT_RST 0x0040 +#define CCNTSTT0 0x0000 // Start when CPU released from JTAG/EEM +#define CCNTSTT1 0x0100 // Start on reaction CCNT1REACT (only CCNT1) +#define CCNTSTT2 0x0200 // Start when other (second) counter is started (only if available) +#define CCNTSTT3 0x0300 // Start immediately +#define CCNTSTP0 0x0000 // Stop when CPU is stopped by EEM or under JTAG control +#define CCNTSTP1 0x0400 // Stop on reaction CCNT1REACT (only CCNT1) +#define CCNTSTP2 0x0800 // Stop when other (second) counter is started (only if available) +#define CCNTSTP3 0x0C00 // No stop event +#define CCNTCLR0 0x0000 // No clear event +#define CCNTCLR1 0x1000 // Clear on reaction CCNT1REACT (only CCNT1) +#define CCNTCLR2 0x2000 // Clear when other (second) counter is started (only if available) +#define CCNTCLR3 0x3000 // Reserved + +#define GCC_NONE 0x0000 // No clock control +#define GCC_STANDARD 0x0001 // Standard clock control +#define GCC_EXTENDED 0x0002 // Extended clock control + +#endif diff --git a/drivers/jtaglib.c b/drivers/jtaglib.c index aecab3f..1161606 100644 --- a/drivers/jtaglib.c +++ b/drivers/jtaglib.c @@ -1,6 +1,6 @@ /* MSPDebug - debugging tool for MSP430 MCUs * Copyright (C) 2009-2012 Daniel Beer - * Copyright (C) 2012-2014 Peter Bägel + * Copyright (C) 2012-2015 Peter Bägel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,17 +18,24 @@ */ /* jtag functions are taken from TIs SLAA149–September 2002 + * + * breakpoint implementation influenced by a posting of Ruisheng Lin + * to Travis Goodspeed at 2012-09-20 found at: + * http://sourceforge.net/p/goodfet/mailman/message/29860790/ * * 2012-10-03 Peter Bägel (DF5EQ) * 2012-10-03 initial release Peter Bägel (DF5EQ) * 2014-12-26 jtag_single_step added Peter Bägel (DF5EQ) * jtag_read_reg corrected * jtag_write_reg corrected + * 2015-02-21 jtag_set_breakpoint added Peter Bägel (DF5EQ) + * jtag_cpu_state added */ #include #include "jtaglib.h" #include "output.h" +#include "eem_defs.h" /* JTAG identification value for all existing Flash-based MSP430 devices */ @@ -55,6 +62,10 @@ #define IR_EX_BLOW 0x24 /* 0x24 */ /* Bypass instruction */ #define IR_BYPASS 0xFF /* 0xFF */ +/* Instructions for the EEM */ +#define IR_EMEX_DATA_EXCHANGE 0x90 /* 0x09 */ +#define IR_EMEX_WRITE_CONTROL 0x30 /* 0x0C */ +#define IR_EMEX_READ_CONTROL 0xD0 /* 0x0B */ #define jtag_tms_set(p) p->f->jtdev_tms(p, 1) #define jtag_tms_clr(p) p->f->jtdev_tms(p, 0) @@ -658,6 +669,9 @@ void jtag_release_device(struct jtdev *p, address_t address) case 0xffff: /* Nothing to do */ break; case 0xfffe: /* Perform reset */ + /* delete all breakpoints */ + jtag_set_breakpoint(p,-1,0); + /* issue reset */ jtag_ir_shift(p, IR_CNTRL_SIG_16BIT); jtag_dr_shift(p, 0x2C01); jtag_dr_shift(p, 0x2401); @@ -667,6 +681,15 @@ void jtag_release_device(struct jtdev *p, address_t address) break; } + jtag_set_instruction_fetch(p); + + jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); + jtag_dr_shift(p, BREAKREACT + READ); + jtag_dr_shift(p, 0x0000); + + jtag_ir_shift(p, IR_EMEX_WRITE_CONTROL); + jtag_dr_shift(p, 0x000f); + jtag_ir_shift(p, IR_CNTRL_SIG_RELEASE); } @@ -1015,3 +1038,78 @@ void jtag_single_step( struct jtdev *p ) p->failed = 1; } } + +/*----------------------------------------------------------------------------*/ +unsigned int jtag_set_breakpoint( struct jtdev *p,int bp_num, address_t bp_addr ) +{ + /* The breakpoint logic is explained in 'SLAU414c EEM.pdf' */ + /* A good overview is given with Figure 1-1 */ + /* MBx is TBx in EEM_defs.h */ + /* CPU Stop is BREAKREACT in EEM_defs.h */ + /* State Storage is STOR_REACT in EEM_defs.h */ + /* Cycle Counter is EVENT_REACT in EEM_defs.h */ + + unsigned int breakreact; + + if (bp_num >= 8) { + /* there are no more than 8 breakpoints in EEM */ + printc_err("jtag_set_breakpoint: failed setting " + "breakpoint %d at %04x\n", bp_num, bp_addr); + p->failed = 1; + return 0; + } + + if (bp_num < 0) { + /* disable all breakpoints by deleting the BREAKREACT + * register */ + jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); + jtag_dr_shift(p, BREAKREACT + WRITE); + jtag_dr_shift(p, 0x0000); + return 1; + } + + /* set breakpoint */ + jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); + jtag_dr_shift(p, GENCTRL + WRITE); + jtag_dr_shift(p, EEM_EN + CLEAR_STOP + EMU_CLK_EN + EMU_FEAT_EN); + + jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed + jtag_dr_shift(p, 8*bp_num + MBTRIGxVAL + WRITE); + jtag_dr_shift(p, bp_addr); + + jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed + jtag_dr_shift(p, 8*bp_num + MBTRIGxCTL + WRITE); + jtag_dr_shift(p, MAB + TRIG_0 + CMP_EQUAL); + + jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed + jtag_dr_shift(p, 8*bp_num + MBTRIGxMSK + WRITE); + jtag_dr_shift(p, NO_MASK); + + jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed + jtag_dr_shift(p, 8*bp_num + MBTRIGxCMB + WRITE); + jtag_dr_shift(p, 1<> 1) | (1 << bp_num); + jtag_dr_shift(p, BREAKREACT + WRITE); + jtag_dr_shift(p, breakreact); + return 1; +} + +/*----------------------------------------------------------------------------*/ +unsigned int jtag_cpu_state( struct jtdev *p ) +{ + jtag_ir_shift(p, IR_EMEX_READ_CONTROL); + + if ((jtag_dr_shift(p, 0x0000) & 0x0080) == 0x0080) { + return 1; /* halted */ + } else { + return 0; /* running */ + } +} diff --git a/drivers/jtaglib.h b/drivers/jtaglib.h index 41fd722..009c736 100644 --- a/drivers/jtaglib.h +++ b/drivers/jtaglib.h @@ -1,6 +1,6 @@ /* MSPDebug - debugging tool for MSP430 MCUs * Copyright (C) 2009-2012 Daniel Beer - * Copyright (C) 2012-2014 Peter Bägel + * Copyright (C) 2012-2015 Peter Bägel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,10 +18,17 @@ */ /* jtag functions are taken from TIs SLAA149–September 2002 + * + * breakpoint implementation influenced by a posting of Ruisheng Lin + * to Travis Goodspeed at 2012-09-20 found at: + * http://sourceforge.net/p/goodfet/mailman/message/29860790/ + * * * 2012-10-03 Peter Bägel (DF5EQ) * 2012-10-03 initial release Peter Bägel (DF5EQ) * 2014-12-26 jtag_single_step added Peter Bägel (DF5EQ) + * 2015-02-21 jtag_set_breakpoint added Peter Bägel (DF5EQ) + * jtag_cpu_state added */ #ifndef JTAGLIB_H_ @@ -105,5 +112,8 @@ address_t jtag_read_reg(struct jtdev *p, int reg); /* Writes a value into a register of the target CPU */ void jtag_write_reg(struct jtdev *p, int reg, address_t value); void jtag_single_step(struct jtdev *p); +unsigned int jtag_set_breakpoint(struct jtdev *p, + int bp_num, address_t bp_addr); +unsigned int jtag_cpu_state(struct jtdev *p); #endif diff --git a/drivers/pif.c b/drivers/pif.c index 61062b1..384bfd6 100644 --- a/drivers/pif.c +++ b/drivers/pif.c @@ -1,6 +1,6 @@ /* MSPDebug - debugging tool for MSP430 MCUs * Copyright (C) 2009-2012 Daniel Beer - * Copyright (C) 2012-2014 Peter Bägel + * Copyright (C) 2012-2015 Peter Bägel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,8 +20,9 @@ /* Driver for parallel port interface like the Olimex MSP430-JTAG * Starting point was the goodfet driver * - * 2012-10-03 Peter Bägel (DF5EQ) + * 2012-10-03 initial release Peter Bägel (DF5EQ) * 2014-12-26 single step implemented Peter Bägel (DF5EQ) + * 2015-02-21 breakpoints implemented Peter Bägel (DF5EQ) */ #include @@ -147,6 +148,43 @@ struct pif_device { struct jtdev jtag; }; +/*----------------------------------------------------------------------------*/ +static int refresh_bps(struct pif_device *dev) +{ + int i; + int ret; + struct device_breakpoint *bp; + address_t addr; + ret = 0; + + for (i = 0; i < dev->base.max_breakpoints; i++) { + bp = &dev->base.breakpoints[i]; + + printc_dbg("refresh breakpoint %d: type=%d " + "addr=%04x flags=%04x\n", + i, bp->type, bp->addr, bp->flags); + + if ( (bp->flags & DEVICE_BP_DIRTY) && + (bp->type == DEVICE_BPTYPE_BREAK) ) { + addr = bp->addr; + + if ( !(bp->flags & DEVICE_BP_ENABLED) ) { + addr = 0; + } + + if ( jtag_set_breakpoint (&dev->jtag, i, addr) == 0) { + printc_err("pif: failed to refresh " + "breakpoint #%d\n", i); + ret = -1; + } else { + bp->flags &= ~DEVICE_BP_DIRTY; + } + } + } + + return ret; +} + /*----------------------------------------------------------------------------*/ static int pif_readmem( device_t dev_base, address_t addr, @@ -278,6 +316,10 @@ static int pif_ctl(device_t dev_base, device_ctl_t type) break; case DEVICE_CTL_RUN: + /* transfer changed breakpoints to device */ + if (refresh_bps(dev) < 0) { + return -1; + } /* start program execution at current PC */ jtag_release_device(&dev->jtag, 0xffff); break; @@ -303,9 +345,15 @@ static int pif_ctl(device_t dev_base, device_ctl_t type) /*----------------------------------------------------------------------------*/ static device_status_t pif_poll(device_t dev_base) { - if (delay_ms(100) < 0) + struct pif_device *dev = (struct pif_device *)dev_base; + + if (delay_ms(100) < 0 || ctrlc_check()) return DEVICE_STATUS_INTR; + if (jtag_cpu_state(&dev->jtag) == 1) { + return DEVICE_STATUS_HALTED; + } + return DEVICE_STATUS_RUNNING; } @@ -360,7 +408,7 @@ static device_t pif_open(const struct device_args *args) memset(dev, 0, sizeof(*dev)); dev->base.type = &device_pif; - dev->base.max_breakpoints = 0; + dev->base.max_breakpoints = 2; //supported by all devices (&dev->jtag)->f = &jtdev_func_pif; if ((&dev->jtag)->f->jtdev_open(&dev->jtag, args->path) < 0) {