From c3d51bf0da7333de303adf86011913a4bca96e4d Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Sun, 15 Aug 2010 21:51:34 +0200 Subject: avr32: work-in-progress committed so as to ease cooperation and to let it be improved over time. So far it supports: - halt/resume - registers inspection - memory inspection/modification I'm still getting up to speed with OpenOCD internals and AVR32 so code is a little bit messy and I'd appreciate any feedback. --- src/target/avr32_jtag.c | 392 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 src/target/avr32_jtag.c (limited to 'src/target/avr32_jtag.c') diff --git a/src/target/avr32_jtag.c b/src/target/avr32_jtag.c new file mode 100644 index 00000000..b6b5e37b --- /dev/null +++ b/src/target/avr32_jtag.c @@ -0,0 +1,392 @@ +/*************************************************************************** + * Copyright (C) 2010 by Oleksandr Tymoshenko * + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "target.h" +#include "helper/types.h" +#include "jtag/jtag.h" +#include "avr32_jtag.h" + +static int avr32_jtag_set_instr(struct avr32_jtag *jtag_info, int new_instr) +{ + struct jtag_tap *tap; + int busy = 0; + + tap = jtag_info->tap; + if (tap == NULL) + return ERROR_FAIL; + + if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) + { + do { + struct scan_field field; + uint8_t t[4]; + uint8_t ret[4]; + + field.num_bits = tap->ir_length; + field.out_value = t; + buf_set_u32(t, 0, field.num_bits, new_instr); + field.in_value = ret; + + jtag_add_ir_scan(tap, &field, TAP_IDLE); + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("%s: setting address failed", __func__); + return ERROR_FAIL; + } + busy = buf_get_u32(ret, 2, 1); + } while (busy); /* check for busy bit */ + } + + return ERROR_OK; +} + +int avr32_jtag_nexus_set_address(struct avr32_jtag *jtag_info, + uint32_t addr, int mode) +{ + struct scan_field fields[2]; + uint8_t addr_buf[4]; + uint8_t busy_buf[4]; + int busy; + + memset(fields, 0, sizeof(fields)); + + do { + memset(addr_buf, 0, sizeof(addr_buf)); + memset(busy_buf, 0, sizeof(busy_buf)); + + buf_set_u32(addr_buf, 0, 1, mode); + buf_set_u32(addr_buf, 1, 7, addr); + + fields[0].num_bits = 26; + fields[0].in_value = NULL; + fields[0].out_value = NULL; + + fields[1].num_bits = 8; + fields[1].in_value = busy_buf; + fields[1].out_value = addr_buf; + + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("%s: setting address failed", __func__); + return ERROR_FAIL; + } + busy = buf_get_u32(busy_buf, 6, 1); + } while(busy); + + return ERROR_OK; +} + + +int avr32_jtag_nexus_read_data(struct avr32_jtag *jtag_info, + uint32_t *pdata) +{ + + struct scan_field fields[2]; + uint8_t data_buf[4]; + uint8_t busy_buf[4]; + int busy; + + do { + memset(data_buf, 0, sizeof(data_buf)); + memset(busy_buf, 0, sizeof(busy_buf)); + + fields[0].num_bits = 32; + fields[0].out_value = NULL; + fields[0].in_value = data_buf; + + + fields[1].num_bits = 2; + fields[1].in_value = busy_buf; + fields[1].out_value = NULL; + + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); + + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("%s: reading data failed", __func__); + return ERROR_FAIL; + } + + busy = buf_get_u32(busy_buf, 0, 1); + } while (busy); + + *pdata = buf_get_u32(data_buf, 0, 32); + + return ERROR_OK; +} + + +int avr32_jtag_nexus_write_data(struct avr32_jtag *jtag_info, + uint32_t data) +{ + + struct scan_field fields[2]; + uint8_t data_buf[4]; + uint8_t busy_buf[4]; + uint8_t dummy_buf[4]; + int busy; + + do { + memset(data_buf, 0, sizeof(data_buf)); + memset(busy_buf, 0, sizeof(busy_buf)); + memset(dummy_buf, 0, sizeof(dummy_buf)); + + fields[0].num_bits = 2; + fields[0].in_value = busy_buf; + fields[0].out_value = dummy_buf; + + + buf_set_u32(data_buf, 0, 32, data); + fields[1].num_bits = 32; + fields[1].in_value = NULL; + fields[1].out_value = data_buf; + + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); + + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("%s: reading data failed", __func__); + return ERROR_FAIL; + } + + busy = buf_get_u32(busy_buf, 0, 0); + } while (busy); + + + return ERROR_OK; +} + + + + +int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info, + uint32_t addr, uint32_t *value) +{ + avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS); + avr32_jtag_nexus_set_address(jtag_info, addr, MODE_READ); + avr32_jtag_nexus_read_data(jtag_info, value); + + return ERROR_OK; + +} +int avr32_jtag_nexus_write(struct avr32_jtag *jtag_info, + uint32_t addr, uint32_t value) +{ + avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS); + avr32_jtag_nexus_set_address(jtag_info, addr, MODE_WRITE); + avr32_jtag_nexus_write_data(jtag_info, value); + + return ERROR_OK; +} + +int avr32_jtag_mwa_set_address(struct avr32_jtag *jtag_info, int slave, + uint32_t addr, int mode) +{ + struct scan_field fields[2]; + uint8_t addr_buf[4]; + uint8_t slave_buf[4]; + uint8_t busy_buf[4]; + int busy; + + memset(fields, 0, sizeof(fields)); + + do { + memset(addr_buf, 0, sizeof(addr_buf)); + memset(busy_buf, 0, sizeof(busy_buf)); + memset(slave_buf, 0, sizeof(slave_buf)); + + buf_set_u32(slave_buf, 0, 4, slave); + buf_set_u32(addr_buf, 0, 1, mode); + buf_set_u32(addr_buf, 1, 30, addr >> 2); + + fields[0].num_bits = 31; + fields[0].in_value = NULL; + fields[0].out_value = addr_buf; + + fields[1].num_bits = 4; + fields[1].in_value = busy_buf; + fields[1].out_value = slave_buf; + + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("%s: setting address failed", __func__); + return ERROR_FAIL; + } + busy = buf_get_u32(busy_buf, 1, 1); + } while(busy); + + return ERROR_OK; +} + +int avr32_jtag_mwa_read_data(struct avr32_jtag *jtag_info, + uint32_t *pdata) +{ + + struct scan_field fields[2]; + uint8_t data_buf[4]; + uint8_t busy_buf[4]; + int busy; + + do { + memset(data_buf, 0, sizeof(data_buf)); + memset(busy_buf, 0, sizeof(busy_buf)); + + fields[0].num_bits = 32; + fields[0].out_value = NULL; + fields[0].in_value = data_buf; + + + fields[1].num_bits = 3; + fields[1].in_value = busy_buf; + fields[1].out_value = NULL; + + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); + + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("%s: reading data failed", __func__); + return ERROR_FAIL; + } + + busy = buf_get_u32(busy_buf, 0, 1); + } while (busy); + + *pdata = buf_get_u32(data_buf, 0, 32); + + return ERROR_OK; +} + +int avr32_jtag_mwa_write_data(struct avr32_jtag *jtag_info, + uint32_t data) +{ + + struct scan_field fields[2]; + uint8_t data_buf[4]; + uint8_t busy_buf[4]; + uint8_t zero_buf[4]; + int busy; + + do { + memset(data_buf, 0, sizeof(data_buf)); + memset(busy_buf, 0, sizeof(busy_buf)); + memset(zero_buf, 0, sizeof(zero_buf)); + + buf_set_u32(data_buf, 0, 32, data); + fields[0].num_bits = 3; + fields[0].in_value = busy_buf; + fields[0].out_value = zero_buf; + + fields[1].num_bits = 32; + fields[1].out_value = data_buf; + fields[1].in_value = NULL; + + + jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE); + + if (jtag_execute_queue() != ERROR_OK) + { + LOG_ERROR("%s: reading data failed", __func__); + return ERROR_FAIL; + } + + busy = buf_get_u32(busy_buf, 0, 1); + } while (busy); + + return ERROR_OK; +} + + + +int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave, + uint32_t addr, uint32_t *value) +{ + avr32_jtag_set_instr(jtag_info, AVR32_INST_MW_ACCESS); + avr32_jtag_mwa_set_address(jtag_info, slave, addr, MODE_READ); + avr32_jtag_mwa_read_data(jtag_info, value); + + return ERROR_OK; +} + +int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave, + uint32_t addr, uint32_t value) +{ + avr32_jtag_set_instr(jtag_info, AVR32_INST_MW_ACCESS); + avr32_jtag_mwa_set_address(jtag_info, slave, addr, MODE_WRITE); + avr32_jtag_mwa_write_data(jtag_info, value); + + return ERROR_OK; +} + +int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst) +{ + int retval; + uint32_t ds; + + retval = avr32_jtag_nexus_write(jtag_info, AVR32_OCDREG_DINST, inst); + if (retval != ERROR_OK) + return retval; + + do { + retval = avr32_jtag_nexus_read(jtag_info, AVR32_OCDREG_DS, &ds); + if (retval != ERROR_OK) + return retval; + } while ((ds & OCDREG_DS_DBA) && !(ds & OCDREG_DS_INC)); + + return ERROR_OK; +} + +int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits) +{ + uint32_t value; + int res; + + res = avr32_jtag_nexus_read(jtag, reg, &value); + if (res) + return res; + + value |= bits; + res = avr32_jtag_nexus_write(jtag, reg, value); + if (res) + return res; + + return ERROR_OK; +} + +int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits) +{ + uint32_t value; + int res; + + res = avr32_jtag_nexus_read(jtag, reg, &value); + if (res) + return res; + + value &= ~bits; + res = avr32_jtag_nexus_write(jtag, reg, value); + if (res) + return res; + + return ERROR_OK; +} + -- cgit v1.2.3