- convert all files to unix line-ending
git-svn-id: svn://svn.berlios.de/openocd/trunk@347 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
parent
7f1944a478
commit
3d6bcf0792
|
@ -1,100 +1,100 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2006 by Magnus Lundin *
|
||||
* lundin@mlu.mine.nu *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef AT91SAM7_H
|
||||
#define AT91SAM7_H
|
||||
|
||||
#include "flash.h"
|
||||
#include "target.h"
|
||||
|
||||
typedef struct at91sam7_flash_bank_s
|
||||
{
|
||||
u32 working_area;
|
||||
u32 working_area_size;
|
||||
|
||||
/* chip id register */
|
||||
u32 cidr;
|
||||
u16 cidr_ext;
|
||||
u16 cidr_nvptyp;
|
||||
u16 cidr_arch;
|
||||
u16 cidr_sramsiz;
|
||||
u16 cidr_nvpsiz;
|
||||
u16 cidr_nvpsiz2;
|
||||
u16 cidr_eproc;
|
||||
u16 cidr_version;
|
||||
char * target_name;
|
||||
|
||||
/* flash geometry */
|
||||
u16 num_pages;
|
||||
u16 pagesize;
|
||||
u16 pages_in_lockregion;
|
||||
u8 num_erase_regions;
|
||||
u8 num_planes;
|
||||
u32 *erase_region_info;
|
||||
|
||||
/* nv memory bits */
|
||||
u16 num_lockbits;
|
||||
u16 lockbits[4];
|
||||
u16 num_nvmbits;
|
||||
u16 nvmbits;
|
||||
u8 securitybit;
|
||||
u8 flashmode[4]; /* 0: not init, 1: fmcn for nvbits (1uS), 2: fmcn for flash (1.5uS) */
|
||||
|
||||
/* main clock status */
|
||||
u8 mck_valid;
|
||||
u32 mck_freq;
|
||||
|
||||
int probed;
|
||||
|
||||
} at91sam7_flash_bank_t;
|
||||
|
||||
/* AT91SAM7 control registers */
|
||||
#define DBGU_CIDR 0xFFFFF240
|
||||
#define CKGR_MCFR 0xFFFFFC24
|
||||
#define CKGR_MCFR_MAINRDY 0x10000
|
||||
#define CKGR_PLLR 0xFFFFFC2c
|
||||
#define CKGR_PLLR_DIV 0xff
|
||||
#define CKGR_PLLR_MUL 0x07ff0000
|
||||
#define PMC_MCKR 0xFFFFFC30
|
||||
#define PMC_MCKR_CSS 0x03
|
||||
#define PMC_MCKR_PRES 0x1c
|
||||
|
||||
/* Flash Controller Commands */
|
||||
#define WP 0x01
|
||||
#define SLB 0x02
|
||||
#define WPL 0x03
|
||||
#define CLB 0x04
|
||||
#define EA 0x08
|
||||
#define SGPB 0x0B
|
||||
#define CGPB 0x0D
|
||||
#define SSB 0x0F
|
||||
|
||||
/* MC_FSR bit definitions */
|
||||
#define MC_FSR_FRDY 1
|
||||
#define MC_FSR_EOL 2
|
||||
|
||||
/* AT91SAM7 constants */
|
||||
#define RC_FREQ 32000
|
||||
|
||||
/* FLASH_TIMING_MODES */
|
||||
#define FMR_TIMING_NONE 0
|
||||
#define FMR_TIMING_NVBITS 1
|
||||
#define FMR_TIMING_FLASH 2
|
||||
|
||||
#endif /* AT91SAM7_H */
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2006 by Magnus Lundin *
|
||||
* lundin@mlu.mine.nu *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef AT91SAM7_H
|
||||
#define AT91SAM7_H
|
||||
|
||||
#include "flash.h"
|
||||
#include "target.h"
|
||||
|
||||
typedef struct at91sam7_flash_bank_s
|
||||
{
|
||||
u32 working_area;
|
||||
u32 working_area_size;
|
||||
|
||||
/* chip id register */
|
||||
u32 cidr;
|
||||
u16 cidr_ext;
|
||||
u16 cidr_nvptyp;
|
||||
u16 cidr_arch;
|
||||
u16 cidr_sramsiz;
|
||||
u16 cidr_nvpsiz;
|
||||
u16 cidr_nvpsiz2;
|
||||
u16 cidr_eproc;
|
||||
u16 cidr_version;
|
||||
char * target_name;
|
||||
|
||||
/* flash geometry */
|
||||
u16 num_pages;
|
||||
u16 pagesize;
|
||||
u16 pages_in_lockregion;
|
||||
u8 num_erase_regions;
|
||||
u8 num_planes;
|
||||
u32 *erase_region_info;
|
||||
|
||||
/* nv memory bits */
|
||||
u16 num_lockbits;
|
||||
u16 lockbits[4];
|
||||
u16 num_nvmbits;
|
||||
u16 nvmbits;
|
||||
u8 securitybit;
|
||||
u8 flashmode[4]; /* 0: not init, 1: fmcn for nvbits (1uS), 2: fmcn for flash (1.5uS) */
|
||||
|
||||
/* main clock status */
|
||||
u8 mck_valid;
|
||||
u32 mck_freq;
|
||||
|
||||
int probed;
|
||||
|
||||
} at91sam7_flash_bank_t;
|
||||
|
||||
/* AT91SAM7 control registers */
|
||||
#define DBGU_CIDR 0xFFFFF240
|
||||
#define CKGR_MCFR 0xFFFFFC24
|
||||
#define CKGR_MCFR_MAINRDY 0x10000
|
||||
#define CKGR_PLLR 0xFFFFFC2c
|
||||
#define CKGR_PLLR_DIV 0xff
|
||||
#define CKGR_PLLR_MUL 0x07ff0000
|
||||
#define PMC_MCKR 0xFFFFFC30
|
||||
#define PMC_MCKR_CSS 0x03
|
||||
#define PMC_MCKR_PRES 0x1c
|
||||
|
||||
/* Flash Controller Commands */
|
||||
#define WP 0x01
|
||||
#define SLB 0x02
|
||||
#define WPL 0x03
|
||||
#define CLB 0x04
|
||||
#define EA 0x08
|
||||
#define SGPB 0x0B
|
||||
#define CGPB 0x0D
|
||||
#define SSB 0x0F
|
||||
|
||||
/* MC_FSR bit definitions */
|
||||
#define MC_FSR_FRDY 1
|
||||
#define MC_FSR_EOL 2
|
||||
|
||||
/* AT91SAM7 constants */
|
||||
#define RC_FREQ 32000
|
||||
|
||||
/* FLASH_TIMING_MODES */
|
||||
#define FMR_TIMING_NONE 0
|
||||
#define FMR_TIMING_NVBITS 1
|
||||
#define FMR_TIMING_FLASH 2
|
||||
|
||||
#endif /* AT91SAM7_H */
|
||||
|
|
4710
src/flash/cfi.c
4710
src/flash/cfi.c
File diff suppressed because it is too large
Load Diff
|
@ -1,179 +1,179 @@
|
|||
/* src/flash/s3c2440_nand.c
|
||||
*
|
||||
* S3C2440 OpenOCD NAND Flash controller support.
|
||||
*
|
||||
* Copyright 2007,2008 Ben Dooks <ben@fluff.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Many thanks to Simtec Electronics for sponsoring this work.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "replacements.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nand.h"
|
||||
#include "s3c24xx_nand.h"
|
||||
#include "target.h"
|
||||
|
||||
int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
|
||||
int s3c2440_init(struct nand_device_s *device);
|
||||
int s3c2440_nand_ready(struct nand_device_s *device, int timeout);
|
||||
|
||||
nand_flash_controller_t s3c2440_nand_controller =
|
||||
{
|
||||
.name = "s3c2440",
|
||||
.nand_device_command = s3c2440_nand_device_command,
|
||||
.register_commands = s3c24xx_register_commands,
|
||||
.init = s3c2440_init,
|
||||
.reset = s3c24xx_reset,
|
||||
.command = s3c24xx_command,
|
||||
.address = s3c24xx_address,
|
||||
.write_data = s3c24xx_write_data,
|
||||
.read_data = s3c24xx_read_data,
|
||||
.write_page = s3c24xx_write_page,
|
||||
.read_page = s3c24xx_read_page,
|
||||
.write_block_data = s3c2440_write_block_data,
|
||||
.read_block_data = s3c2440_read_block_data,
|
||||
.controller_ready = s3c24xx_controller_ready,
|
||||
.nand_ready = s3c2440_nand_ready,
|
||||
};
|
||||
|
||||
int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
|
||||
char **args, int argc,
|
||||
struct nand_device_s *device)
|
||||
{
|
||||
s3c24xx_nand_controller_t *info;
|
||||
|
||||
info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);
|
||||
if (info == NULL) {
|
||||
return ERROR_NAND_DEVICE_INVALID;
|
||||
}
|
||||
|
||||
/* fill in the address fields for the core device */
|
||||
info->cmd = S3C2440_NFCMD;
|
||||
info->addr = S3C2440_NFADDR;
|
||||
info->data = S3C2440_NFDATA;
|
||||
info->nfstat = S3C2440_NFSTAT;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int s3c2440_init(struct nand_device_s *device)
|
||||
{
|
||||
s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
|
||||
target_t *target = s3c24xx_info->target;
|
||||
u32 version;
|
||||
|
||||
target_write_u32(target, S3C2410_NFCONF,
|
||||
S3C2440_NFCONF_TACLS(3) |
|
||||
S3C2440_NFCONF_TWRPH0(7) |
|
||||
S3C2440_NFCONF_TWRPH1(7));
|
||||
|
||||
target_write_u32(target, S3C2440_NFCONT,
|
||||
S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int s3c2440_nand_ready(struct nand_device_s *device, int timeout)
|
||||
{
|
||||
s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
|
||||
target_t *target = s3c24xx_info->target;
|
||||
u8 status;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
do {
|
||||
target_read_u8(target, s3c24xx_info->nfstat, &status);
|
||||
|
||||
if (status & S3C2440_NFSTAT_READY)
|
||||
return 1;
|
||||
|
||||
usleep(1000);
|
||||
} while (timeout-- > 0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* use the fact we can read/write 4 bytes in one go via a single 32bit op */
|
||||
|
||||
int s3c2440_read_block_data(struct nand_device_s *device, u8 *data, int data_size)
|
||||
{
|
||||
s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
|
||||
target_t *target = s3c24xx_info->target;
|
||||
u32 nfdata = s3c24xx_info->data;
|
||||
u32 tmp;
|
||||
|
||||
INFO("%s: reading data: %p, %p, %d\n", __func__, device, data, data_size);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
while (data_size >= 4) {
|
||||
target_read_u32(target, nfdata, &tmp);
|
||||
|
||||
data[0] = tmp;
|
||||
data[1] = tmp >> 8;
|
||||
data[2] = tmp >> 16;
|
||||
data[3] = tmp >> 24;
|
||||
|
||||
data_size -= 4;
|
||||
data += 4;
|
||||
}
|
||||
|
||||
while (data_size > 0) {
|
||||
target_read_u8(target, nfdata, data);
|
||||
|
||||
data_size -= 1;
|
||||
data += 1;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int s3c2440_write_block_data(struct nand_device_s *device, u8 *data, int data_size)
|
||||
{
|
||||
s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
|
||||
target_t *target = s3c24xx_info->target;
|
||||
u32 nfdata = s3c24xx_info->data;
|
||||
u32 tmp;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
while (data_size >= 4) {
|
||||
tmp = le_to_h_u32(data);
|
||||
target_write_u32(target, nfdata, tmp);
|
||||
|
||||
data_size -= 4;
|
||||
data += 4;
|
||||
}
|
||||
|
||||
while (data_size > 0) {
|
||||
target_write_u8(target, nfdata, *data);
|
||||
|
||||
data_size -= 1;
|
||||
data += 1;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
/* src/flash/s3c2440_nand.c
|
||||
*
|
||||
* S3C2440 OpenOCD NAND Flash controller support.
|
||||
*
|
||||
* Copyright 2007,2008 Ben Dooks <ben@fluff.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Many thanks to Simtec Electronics for sponsoring this work.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "replacements.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nand.h"
|
||||
#include "s3c24xx_nand.h"
|
||||
#include "target.h"
|
||||
|
||||
int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
|
||||
int s3c2440_init(struct nand_device_s *device);
|
||||
int s3c2440_nand_ready(struct nand_device_s *device, int timeout);
|
||||
|
||||
nand_flash_controller_t s3c2440_nand_controller =
|
||||
{
|
||||
.name = "s3c2440",
|
||||
.nand_device_command = s3c2440_nand_device_command,
|
||||
.register_commands = s3c24xx_register_commands,
|
||||
.init = s3c2440_init,
|
||||
.reset = s3c24xx_reset,
|
||||
.command = s3c24xx_command,
|
||||
.address = s3c24xx_address,
|
||||
.write_data = s3c24xx_write_data,
|
||||
.read_data = s3c24xx_read_data,
|
||||
.write_page = s3c24xx_write_page,
|
||||
.read_page = s3c24xx_read_page,
|
||||
.write_block_data = s3c2440_write_block_data,
|
||||
.read_block_data = s3c2440_read_block_data,
|
||||
.controller_ready = s3c24xx_controller_ready,
|
||||
.nand_ready = s3c2440_nand_ready,
|
||||
};
|
||||
|
||||
int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
|
||||
char **args, int argc,
|
||||
struct nand_device_s *device)
|
||||
{
|
||||
s3c24xx_nand_controller_t *info;
|
||||
|
||||
info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);
|
||||
if (info == NULL) {
|
||||
return ERROR_NAND_DEVICE_INVALID;
|
||||
}
|
||||
|
||||
/* fill in the address fields for the core device */
|
||||
info->cmd = S3C2440_NFCMD;
|
||||
info->addr = S3C2440_NFADDR;
|
||||
info->data = S3C2440_NFDATA;
|
||||
info->nfstat = S3C2440_NFSTAT;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int s3c2440_init(struct nand_device_s *device)
|
||||
{
|
||||
s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
|
||||
target_t *target = s3c24xx_info->target;
|
||||
u32 version;
|
||||
|
||||
target_write_u32(target, S3C2410_NFCONF,
|
||||
S3C2440_NFCONF_TACLS(3) |
|
||||
S3C2440_NFCONF_TWRPH0(7) |
|
||||
S3C2440_NFCONF_TWRPH1(7));
|
||||
|
||||
target_write_u32(target, S3C2440_NFCONT,
|
||||
S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int s3c2440_nand_ready(struct nand_device_s *device, int timeout)
|
||||
{
|
||||
s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
|
||||
target_t *target = s3c24xx_info->target;
|
||||
u8 status;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
do {
|
||||
target_read_u8(target, s3c24xx_info->nfstat, &status);
|
||||
|
||||
if (status & S3C2440_NFSTAT_READY)
|
||||
return 1;
|
||||
|
||||
usleep(1000);
|
||||
} while (timeout-- > 0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* use the fact we can read/write 4 bytes in one go via a single 32bit op */
|
||||
|
||||
int s3c2440_read_block_data(struct nand_device_s *device, u8 *data, int data_size)
|
||||
{
|
||||
s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
|
||||
target_t *target = s3c24xx_info->target;
|
||||
u32 nfdata = s3c24xx_info->data;
|
||||
u32 tmp;
|
||||
|
||||
INFO("%s: reading data: %p, %p, %d\n", __func__, device, data, data_size);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
while (data_size >= 4) {
|
||||
target_read_u32(target, nfdata, &tmp);
|
||||
|
||||
data[0] = tmp;
|
||||
data[1] = tmp >> 8;
|
||||
data[2] = tmp >> 16;
|
||||
data[3] = tmp >> 24;
|
||||
|
||||
data_size -= 4;
|
||||
data += 4;
|
||||
}
|
||||
|
||||
while (data_size > 0) {
|
||||
target_read_u8(target, nfdata, data);
|
||||
|
||||
data_size -= 1;
|
||||
data += 1;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int s3c2440_write_block_data(struct nand_device_s *device, u8 *data, int data_size)
|
||||
{
|
||||
s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
|
||||
target_t *target = s3c24xx_info->target;
|
||||
u32 nfdata = s3c24xx_info->data;
|
||||
u32 tmp;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
ERROR("target must be halted to use S3C24XX NAND flash controller");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
while (data_size >= 4) {
|
||||
tmp = le_to_h_u32(data);
|
||||
target_write_u32(target, nfdata, tmp);
|
||||
|
||||
data_size -= 4;
|
||||
data += 4;
|
||||
}
|
||||
|
||||
while (data_size > 0) {
|
||||
target_write_u8(target, nfdata, *data);
|
||||
|
||||
data_size -= 1;
|
||||
data += 1;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
2696
src/flash/str9xpec.c
2696
src/flash/str9xpec.c
File diff suppressed because it is too large
Load Diff
1214
src/helper/command.c
1214
src/helper/command.c
File diff suppressed because it is too large
Load Diff
|
@ -1,104 +1,104 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "types.h"
|
||||
#include "command.h"
|
||||
#include "configuration.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static size_t num_config_files;
|
||||
static char** config_file_names;
|
||||
|
||||
static size_t num_script_dirs;
|
||||
static char** script_search_dirs;
|
||||
|
||||
|
||||
void add_script_search_dir (const char *dir)
|
||||
{
|
||||
num_script_dirs++;
|
||||
script_search_dirs = (char **)realloc(script_search_dirs, (num_script_dirs+1) * sizeof (char *));
|
||||
|
||||
script_search_dirs[num_script_dirs-1] = strdup(dir);
|
||||
script_search_dirs[num_script_dirs] = NULL;
|
||||
}
|
||||
|
||||
void add_config_file_name (const char *cfg)
|
||||
{
|
||||
num_config_files++;
|
||||
config_file_names = (char **)realloc(config_file_names, (num_config_files+1) * sizeof (char *));
|
||||
|
||||
config_file_names[num_config_files-1] = strdup(cfg);
|
||||
config_file_names[num_config_files] = NULL;
|
||||
}
|
||||
|
||||
FILE *open_file_from_path (command_context_t *cmd_ctx, char *file, char *mode)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
char **search_dirs = script_search_dirs;
|
||||
char *dir;
|
||||
char full_path[1024];
|
||||
|
||||
/* Check absolute and relative to current working dir first.
|
||||
* This keeps full_path reporting belowing working. */
|
||||
snprintf(full_path, 1024, "%s", file);
|
||||
fp = fopen(full_path, mode);
|
||||
|
||||
while (!fp)
|
||||
{
|
||||
dir = *search_dirs++;
|
||||
|
||||
if (!dir)
|
||||
break;
|
||||
|
||||
snprintf(full_path, 1024, "%s/%s", dir, file);
|
||||
fp = fopen(full_path, mode);
|
||||
}
|
||||
|
||||
if (fp)
|
||||
command_print(cmd_ctx, "opened %s", full_path);
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
int parse_config_file(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
char **cfg;
|
||||
FILE *config_file;
|
||||
|
||||
if (!config_file_names)
|
||||
add_config_file_name ("script openocd.cfg");
|
||||
|
||||
cfg = config_file_names;
|
||||
|
||||
while (*cfg)
|
||||
{
|
||||
command_run_line(cmd_ctx, *cfg);
|
||||
cfg++;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "types.h"
|
||||
#include "command.h"
|
||||
#include "configuration.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static size_t num_config_files;
|
||||
static char** config_file_names;
|
||||
|
||||
static size_t num_script_dirs;
|
||||
static char** script_search_dirs;
|
||||
|
||||
|
||||
void add_script_search_dir (const char *dir)
|
||||
{
|
||||
num_script_dirs++;
|
||||
script_search_dirs = (char **)realloc(script_search_dirs, (num_script_dirs+1) * sizeof (char *));
|
||||
|
||||
script_search_dirs[num_script_dirs-1] = strdup(dir);
|
||||
script_search_dirs[num_script_dirs] = NULL;
|
||||
}
|
||||
|
||||
void add_config_file_name (const char *cfg)
|
||||
{
|
||||
num_config_files++;
|
||||
config_file_names = (char **)realloc(config_file_names, (num_config_files+1) * sizeof (char *));
|
||||
|
||||
config_file_names[num_config_files-1] = strdup(cfg);
|
||||
config_file_names[num_config_files] = NULL;
|
||||
}
|
||||
|
||||
FILE *open_file_from_path (command_context_t *cmd_ctx, char *file, char *mode)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
char **search_dirs = script_search_dirs;
|
||||
char *dir;
|
||||
char full_path[1024];
|
||||
|
||||
/* Check absolute and relative to current working dir first.
|
||||
* This keeps full_path reporting belowing working. */
|
||||
snprintf(full_path, 1024, "%s", file);
|
||||
fp = fopen(full_path, mode);
|
||||
|
||||
while (!fp)
|
||||
{
|
||||
dir = *search_dirs++;
|
||||
|
||||
if (!dir)
|
||||
break;
|
||||
|
||||
snprintf(full_path, 1024, "%s/%s", dir, file);
|
||||
fp = fopen(full_path, mode);
|
||||
}
|
||||
|
||||
if (fp)
|
||||
command_print(cmd_ctx, "opened %s", full_path);
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
int parse_config_file(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
char **cfg;
|
||||
FILE *config_file;
|
||||
|
||||
if (!config_file_names)
|
||||
add_config_file_name ("script openocd.cfg");
|
||||
|
||||
cfg = config_file_names;
|
||||
|
||||
while (*cfg)
|
||||
{
|
||||
command_run_line(cmd_ctx, *cfg);
|
||||
cfg++;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
496
src/helper/log.c
496
src/helper/log.c
|
@ -1,248 +1,248 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "log.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
int debug_level = -1;
|
||||
|
||||
static FILE* log_output;
|
||||
static log_callback_t *log_callbacks = NULL;
|
||||
|
||||
static time_t start;
|
||||
|
||||
static char *log_strings[5] =
|
||||
{
|
||||
"User: ",
|
||||
"Error: ",
|
||||
"Warning:",
|
||||
"Info: ",
|
||||
"Debug: "
|
||||
};
|
||||
|
||||
void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...)
|
||||
{
|
||||
static int count = 0;
|
||||
count++;
|
||||
va_list args;
|
||||
char buffer[512];
|
||||
log_callback_t *cb;
|
||||
|
||||
if (level > debug_level)
|
||||
return;
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(buffer, 512, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (level == LOG_OUTPUT)
|
||||
{
|
||||
/* do not prepend any headers, just print out what we were given and return */
|
||||
fputs(buffer, log_output);
|
||||
fflush(log_output);
|
||||
return;
|
||||
}
|
||||
|
||||
char *f = strrchr(file, '/');
|
||||
if (f != NULL)
|
||||
file = f + 1;
|
||||
|
||||
if (debug_level >= LOG_DEBUG)
|
||||
{
|
||||
/* print with count and time information */
|
||||
time_t t=time(NULL)-start;
|
||||
fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do not print count and time */
|
||||
fprintf(log_output, "%s %s:%d %s(): %s\n", log_strings[level+1], file, line, function, buffer);
|
||||
}
|
||||
|
||||
fflush(log_output);
|
||||
|
||||
/* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */
|
||||
if (level <= LOG_INFO)
|
||||
{
|
||||
for (cb = log_callbacks; cb; cb = cb->next)
|
||||
{
|
||||
va_start(args, format);
|
||||
cb->fn(cb->priv, file, line, function, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* change the current debug level on the fly
|
||||
* 0: only ERRORS
|
||||
* 1: + WARNINGS
|
||||
* 2: + INFORMATIONAL MSGS
|
||||
* 3: + DEBUG MSGS
|
||||
*/
|
||||
int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
command_print(cmd_ctx, "debug_level: %i", debug_level);
|
||||
|
||||
if (argc > 0)
|
||||
debug_level = strtoul(args[0], NULL, 0);
|
||||
|
||||
if (debug_level < 0)
|
||||
debug_level = 0;
|
||||
|
||||
if (debug_level > 3)
|
||||
debug_level = 3;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
FILE* file = fopen(args[0], "w");
|
||||
|
||||
if (file)
|
||||
{
|
||||
log_output = file;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int log_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
start = time(NULL);
|
||||
register_command(cmd_ctx, NULL, "log_output", handle_log_output_command,
|
||||
COMMAND_ANY, "redirect logging to <file> (default: stderr)");
|
||||
register_command(cmd_ctx, NULL, "debug_level", handle_debug_level_command,
|
||||
COMMAND_ANY, "adjust debug level <0-3>");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int log_init(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
/* set defaults for daemon configuration, if not set by cmdline or cfgfile */
|
||||
if (debug_level == -1)
|
||||
debug_level = LOG_INFO;
|
||||
|
||||
if (log_output == NULL)
|
||||
{
|
||||
log_output = stderr;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int set_log_output(struct command_context_s *cmd_ctx, FILE *output)
|
||||
{
|
||||
log_output = output;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* add/remove log callback handler */
|
||||
int log_add_callback(log_callback_fn fn, void *priv)
|
||||
{
|
||||
log_callback_t *cb;
|
||||
|
||||
/* prevent the same callback to be registered more than once, just for sure */
|
||||
for (cb = log_callbacks; cb; cb = cb->next)
|
||||
{
|
||||
if (cb->fn == fn && cb->priv == priv)
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
/* alloc memory, it is safe just to return in case of an error, no need for the caller to check this */
|
||||
if ((cb = malloc(sizeof(log_callback_t))) == NULL)
|
||||
return ERROR_BUF_TOO_SMALL;
|
||||
|
||||
/* add item to the beginning of the linked list */
|
||||
cb->fn = fn;
|
||||
cb->priv = priv;
|
||||
cb->next = log_callbacks;
|
||||
log_callbacks = cb;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int log_remove_callback(log_callback_fn fn, void *priv)
|
||||
{
|
||||
log_callback_t *cb, **p;
|
||||
|
||||
for (p = &log_callbacks; cb = *p; p = &(*p)->next)
|
||||
{
|
||||
if (cb->fn == fn && cb->priv == priv)
|
||||
{
|
||||
*p = cb->next;
|
||||
free(cb);
|
||||
return ERROR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* no such item */
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
/* return allocated string w/printf() result */
|
||||
char *alloc_printf(const char *fmt, va_list ap)
|
||||
{
|
||||
char *string = NULL;
|
||||
|
||||
/* start by 0 to exercise all the code paths. Need minimum 2 bytes to
|
||||
* fit 1 char and 0 terminator. */
|
||||
int size = 0;
|
||||
int first = 1;
|
||||
for (;;)
|
||||
{
|
||||
if ((string == NULL) || (!first))
|
||||
{
|
||||
size = size * 2 + 2;
|
||||
char *t = string;
|
||||
string = realloc(string, size);
|
||||
if (string == NULL)
|
||||
{
|
||||
if (t != NULL)
|
||||
free(t);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int ret;
|
||||
ret = vsnprintf(string, size, fmt, ap);
|
||||
/* NB! The result of the vsnprintf() might be an *EMPTY* string! */
|
||||
if ((ret >= 0) && ((ret + 1) < size))
|
||||
{
|
||||
return string;
|
||||
}
|
||||
/* there was just enough or not enough space, allocate more. */
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "log.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
int debug_level = -1;
|
||||
|
||||
static FILE* log_output;
|
||||
static log_callback_t *log_callbacks = NULL;
|
||||
|
||||
static time_t start;
|
||||
|
||||
static char *log_strings[5] =
|
||||
{
|
||||
"User: ",
|
||||
"Error: ",
|
||||
"Warning:",
|
||||
"Info: ",
|
||||
"Debug: "
|
||||
};
|
||||
|
||||
void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...)
|
||||
{
|
||||
static int count = 0;
|
||||
count++;
|
||||
va_list args;
|
||||
char buffer[512];
|
||||
log_callback_t *cb;
|
||||
|
||||
if (level > debug_level)
|
||||
return;
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(buffer, 512, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (level == LOG_OUTPUT)
|
||||
{
|
||||
/* do not prepend any headers, just print out what we were given and return */
|
||||
fputs(buffer, log_output);
|
||||
fflush(log_output);
|
||||
return;
|
||||
}
|
||||
|
||||
char *f = strrchr(file, '/');
|
||||
if (f != NULL)
|
||||
file = f + 1;
|
||||
|
||||
if (debug_level >= LOG_DEBUG)
|
||||
{
|
||||
/* print with count and time information */
|
||||
time_t t=time(NULL)-start;
|
||||
fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do not print count and time */
|
||||
fprintf(log_output, "%s %s:%d %s(): %s\n", log_strings[level+1], file, line, function, buffer);
|
||||
}
|
||||
|
||||
fflush(log_output);
|
||||
|
||||
/* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */
|
||||
if (level <= LOG_INFO)
|
||||
{
|
||||
for (cb = log_callbacks; cb; cb = cb->next)
|
||||
{
|
||||
va_start(args, format);
|
||||
cb->fn(cb->priv, file, line, function, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* change the current debug level on the fly
|
||||
* 0: only ERRORS
|
||||
* 1: + WARNINGS
|
||||
* 2: + INFORMATIONAL MSGS
|
||||
* 3: + DEBUG MSGS
|
||||
*/
|
||||
int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
command_print(cmd_ctx, "debug_level: %i", debug_level);
|
||||
|
||||
if (argc > 0)
|
||||
debug_level = strtoul(args[0], NULL, 0);
|
||||
|
||||
if (debug_level < 0)
|
||||
debug_level = 0;
|
||||
|
||||
if (debug_level > 3)
|
||||
debug_level = 3;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
FILE* file = fopen(args[0], "w");
|
||||
|
||||
if (file)
|
||||
{
|
||||
log_output = file;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int log_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
start = time(NULL);
|
||||
register_command(cmd_ctx, NULL, "log_output", handle_log_output_command,
|
||||
COMMAND_ANY, "redirect logging to <file> (default: stderr)");
|
||||
register_command(cmd_ctx, NULL, "debug_level", handle_debug_level_command,
|
||||
COMMAND_ANY, "adjust debug level <0-3>");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int log_init(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
/* set defaults for daemon configuration, if not set by cmdline or cfgfile */
|
||||
if (debug_level == -1)
|
||||
debug_level = LOG_INFO;
|
||||
|
||||
if (log_output == NULL)
|
||||
{
|
||||
log_output = stderr;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int set_log_output(struct command_context_s *cmd_ctx, FILE *output)
|
||||
{
|
||||
log_output = output;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* add/remove log callback handler */
|
||||
int log_add_callback(log_callback_fn fn, void *priv)
|
||||
{
|
||||
log_callback_t *cb;
|
||||
|
||||
/* prevent the same callback to be registered more than once, just for sure */
|
||||
for (cb = log_callbacks; cb; cb = cb->next)
|
||||
{
|
||||
if (cb->fn == fn && cb->priv == priv)
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
/* alloc memory, it is safe just to return in case of an error, no need for the caller to check this */
|
||||
if ((cb = malloc(sizeof(log_callback_t))) == NULL)
|
||||
return ERROR_BUF_TOO_SMALL;
|
||||
|
||||
/* add item to the beginning of the linked list */
|
||||
cb->fn = fn;
|
||||
cb->priv = priv;
|
||||
cb->next = log_callbacks;
|
||||
log_callbacks = cb;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int log_remove_callback(log_callback_fn fn, void *priv)
|
||||
{
|
||||
log_callback_t *cb, **p;
|
||||
|
||||
for (p = &log_callbacks; cb = *p; p = &(*p)->next)
|
||||
{
|
||||
if (cb->fn == fn && cb->priv == priv)
|
||||
{
|
||||
*p = cb->next;
|
||||
free(cb);
|
||||
return ERROR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* no such item */
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
/* return allocated string w/printf() result */
|
||||
char *alloc_printf(const char *fmt, va_list ap)
|
||||
{
|
||||
char *string = NULL;
|
||||
|
||||
/* start by 0 to exercise all the code paths. Need minimum 2 bytes to
|
||||
* fit 1 char and 0 terminator. */
|
||||
int size = 0;
|
||||
int first = 1;
|
||||
for (;;)
|
||||
{
|
||||
if ((string == NULL) || (!first))
|
||||
{
|
||||
size = size * 2 + 2;
|
||||
char *t = string;
|
||||
string = realloc(string, size);
|
||||
if (string == NULL)
|
||||
{
|
||||
if (t != NULL)
|
||||
free(t);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int ret;
|
||||
ret = vsnprintf(string, size, fmt, ap);
|
||||
/* NB! The result of the vsnprintf() might be an *EMPTY* string! */
|
||||
if ((ret >= 0) && ((ret + 1) < size))
|
||||
{
|
||||
return string;
|
||||
}
|
||||
/* there was just enough or not enough space, allocate more. */
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
|
|
226
src/helper/log.h
226
src/helper/log.h
|
@ -1,113 +1,113 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
#include "replacements.h"
|
||||
#include "command.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* logging priorities
|
||||
* LOG_USER - user messages. Could be anything from information
|
||||
* to progress messags. These messages do not represent
|
||||
* incorrect or unexpected behaviour, just normal execution.
|
||||
* LOG_ERROR - fatal errors, that are likely to cause program abort
|
||||
* LOG_WARNING - non-fatal errors, that may be resolved later
|
||||
* LOG_INFO - state information, etc.
|
||||
* LOG_DEBUG - debug statements, execution trace
|
||||
*/
|
||||
enum log_levels
|
||||
{
|
||||
LOG_OUTPUT = -2,
|
||||
LOG_USER = -1,
|
||||
LOG_ERROR = 0,
|
||||
LOG_WARNING = 1,
|
||||
LOG_INFO = 2,
|
||||
LOG_DEBUG = 3
|
||||
};
|
||||
|
||||
extern void log_printf(enum log_levels level, const char *file, int line,
|
||||
const char *function, const char *format, ...)
|
||||
__attribute__ ((format (printf, 5, 6)));
|
||||
extern int log_register_commands(struct command_context_s *cmd_ctx);
|
||||
extern int log_init(struct command_context_s *cmd_ctx);
|
||||
extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);
|
||||
|
||||
typedef void (*log_callback_fn)(void *priv, const char *file, int line,
|
||||
const char *function, const char *format, va_list args);
|
||||
|
||||
typedef struct log_callback_s
|
||||
{
|
||||
log_callback_fn fn;
|
||||
void *priv;
|
||||
struct log_callback_s *next;
|
||||
} log_callback_t;
|
||||
|
||||
extern int log_add_callback(log_callback_fn fn, void *priv);
|
||||
extern int log_remove_callback(log_callback_fn fn, void *priv);
|
||||
|
||||
char *alloc_printf(const char *fmt, va_list ap);
|
||||
|
||||
extern int debug_level;
|
||||
|
||||
/* Avoid fn call and building parameter list if we're not outputting the information.
|
||||
* Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */
|
||||
|
||||
#define DEBUG(expr ...) \
|
||||
do { if (debug_level >= LOG_DEBUG) \
|
||||
log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define INFO(expr ...) \
|
||||
do { if (debug_level >= LOG_INFO) \
|
||||
log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define WARNING(expr ...) \
|
||||
do { \
|
||||
log_printf (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define ERROR(expr ...) \
|
||||
do { \
|
||||
log_printf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define USER(expr ...) \
|
||||
do { \
|
||||
log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define OUTPUT(expr ...) \
|
||||
do { \
|
||||
log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* general failures
|
||||
* error codes < 100
|
||||
*/
|
||||
#define ERROR_OK (0)
|
||||
#define ERROR_INVALID_ARGUMENTS (-1)
|
||||
#define ERROR_NO_CONFIG_FILE (-2)
|
||||
#define ERROR_BUF_TOO_SMALL (-3)
|
||||
|
||||
#endif /* LOG_H */
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
#include "replacements.h"
|
||||
#include "command.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* logging priorities
|
||||
* LOG_USER - user messages. Could be anything from information
|
||||
* to progress messags. These messages do not represent
|
||||
* incorrect or unexpected behaviour, just normal execution.
|
||||
* LOG_ERROR - fatal errors, that are likely to cause program abort
|
||||
* LOG_WARNING - non-fatal errors, that may be resolved later
|
||||
* LOG_INFO - state information, etc.
|
||||
* LOG_DEBUG - debug statements, execution trace
|
||||
*/
|
||||
enum log_levels
|
||||
{
|
||||
LOG_OUTPUT = -2,
|
||||
LOG_USER = -1,
|
||||
LOG_ERROR = 0,
|
||||
LOG_WARNING = 1,
|
||||
LOG_INFO = 2,
|
||||
LOG_DEBUG = 3
|
||||
};
|
||||
|
||||
extern void log_printf(enum log_levels level, const char *file, int line,
|
||||
const char *function, const char *format, ...)
|
||||
__attribute__ ((format (printf, 5, 6)));
|
||||
extern int log_register_commands(struct command_context_s *cmd_ctx);
|
||||
extern int log_init(struct command_context_s *cmd_ctx);
|
||||
extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);
|
||||
|
||||
typedef void (*log_callback_fn)(void *priv, const char *file, int line,
|
||||
const char *function, const char *format, va_list args);
|
||||
|
||||
typedef struct log_callback_s
|
||||
{
|
||||
log_callback_fn fn;
|
||||
void *priv;
|
||||
struct log_callback_s *next;
|
||||
} log_callback_t;
|
||||
|
||||
extern int log_add_callback(log_callback_fn fn, void *priv);
|
||||
extern int log_remove_callback(log_callback_fn fn, void *priv);
|
||||
|
||||
char *alloc_printf(const char *fmt, va_list ap);
|
||||
|
||||
extern int debug_level;
|
||||
|
||||
/* Avoid fn call and building parameter list if we're not outputting the information.
|
||||
* Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */
|
||||
|
||||
#define DEBUG(expr ...) \
|
||||
do { if (debug_level >= LOG_DEBUG) \
|
||||
log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define INFO(expr ...) \
|
||||
do { if (debug_level >= LOG_INFO) \
|
||||
log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define WARNING(expr ...) \
|
||||
do { \
|
||||
log_printf (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define ERROR(expr ...) \
|
||||
do { \
|
||||
log_printf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define USER(expr ...) \
|
||||
do { \
|
||||
log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
#define OUTPUT(expr ...) \
|
||||
do { \
|
||||
log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* general failures
|
||||
* error codes < 100
|
||||
*/
|
||||
#define ERROR_OK (0)
|
||||
#define ERROR_INVALID_ARGUMENTS (-1)
|
||||
#define ERROR_NO_CONFIG_FILE (-2)
|
||||
#define ERROR_BUF_TOO_SMALL (-3)
|
||||
|
||||
#endif /* LOG_H */
|
||||
|
|
|
@ -1,153 +1,153 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "types.h"
|
||||
#include "command.h"
|
||||
#include "configuration.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static int help_flag;
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"help", no_argument, &help_flag, 1},
|
||||
|
||||
{"debug", optional_argument, 0, 'd'},
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"search", required_argument, 0, 's'},
|
||||
{"log_output", required_argument, 0, 'l'},
|
||||
{"command", required_argument, 0, 'c'},
|
||||
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int configuration_output_handler(struct command_context_s *context, char* line)
|
||||
{
|
||||
INFO(line);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
char command_buffer[128];
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
c = getopt_long(argc, argv, "hd::l:f:s:c:", long_options, &option_index);
|
||||
|
||||
/* Detect the end of the options. */
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 'h': /* --help | -h */
|
||||
help_flag = 1;
|
||||
break;
|
||||
case 'f': /* --file | -f */
|
||||
snprintf(command_buffer, 128, "script %s", optarg);
|
||||
add_config_file_name(command_buffer);
|
||||
break;
|
||||
case 's': /* --search | -s */
|
||||
add_script_search_dir(optarg);
|
||||
break;
|
||||
case 'd': /* --debug | -d */
|
||||
if (optarg)
|
||||
snprintf(command_buffer, 128, "debug_level %s", optarg);
|
||||
else
|
||||
snprintf(command_buffer, 128, "debug_level 3");
|
||||
command_run_line(cmd_ctx, command_buffer);
|
||||
break;
|
||||
case 'l': /* --log_output | -l */
|
||||
if (optarg)
|
||||
{
|
||||
snprintf(command_buffer, 128, "log_output %s", optarg);
|
||||
command_run_line(cmd_ctx, command_buffer);
|
||||
}
|
||||
break;
|
||||
case 'c': /* --command | -c */
|
||||
if (optarg)
|
||||
{
|
||||
add_config_file_name(optarg);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (help_flag)
|
||||
{
|
||||
OUTPUT("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n");
|
||||
OUTPUT("--help | -h\tdisplay this help\n");
|
||||
OUTPUT("--file | -f\tuse configuration file <name>\n");
|
||||
OUTPUT("--search | -s\tdir to search for config files and scripts.\n");
|
||||
OUTPUT("--debug | -d\tset debug level <0-3>\n");
|
||||
OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
|
||||
OUTPUT("--command | -c\trun <command>\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Add the parent of the directory where openocd.exe resides to the
|
||||
* config script search path.
|
||||
* Directory layout:
|
||||
* bin\openocd.exe
|
||||
* lib\openocd
|
||||
* event\at91eb40a_reset.cfg
|
||||
* target\at91eb40a.cfg
|
||||
*/
|
||||
{
|
||||
char strExePath [MAX_PATH];
|
||||
GetModuleFileName (NULL, strExePath, MAX_PATH);
|
||||
/* Either this code will *always* work or it will SEGFAULT giving
|
||||
* excellent information on the culprit.
|
||||
*/
|
||||
*strrchr(strExePath, '\\')=0;
|
||||
strcat(strExePath, "\\..");
|
||||
add_script_search_dir(strExePath);
|
||||
}
|
||||
#else
|
||||
/* Add dir for openocd supplied scripts last so that user can over
|
||||
ride those scripts if desired. */
|
||||
add_script_search_dir(PKGDATADIR);
|
||||
add_script_search_dir(PKGLIBDIR);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "types.h"
|
||||
#include "command.h"
|
||||
#include "configuration.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static int help_flag;
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"help", no_argument, &help_flag, 1},
|
||||
|
||||
{"debug", optional_argument, 0, 'd'},
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"search", required_argument, 0, 's'},
|
||||
{"log_output", required_argument, 0, 'l'},
|
||||
{"command", required_argument, 0, 'c'},
|
||||
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int configuration_output_handler(struct command_context_s *context, char* line)
|
||||
{
|
||||
INFO(line);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
char command_buffer[128];
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
c = getopt_long(argc, argv, "hd::l:f:s:c:", long_options, &option_index);
|
||||
|
||||
/* Detect the end of the options. */
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 'h': /* --help | -h */
|
||||
help_flag = 1;
|
||||
break;
|
||||
case 'f': /* --file | -f */
|
||||
snprintf(command_buffer, 128, "script %s", optarg);
|
||||
add_config_file_name(command_buffer);
|
||||
break;
|
||||
case 's': /* --search | -s */
|
||||
add_script_search_dir(optarg);
|
||||
break;
|
||||
case 'd': /* --debug | -d */
|
||||
if (optarg)
|
||||
snprintf(command_buffer, 128, "debug_level %s", optarg);
|
||||
else
|
||||
snprintf(command_buffer, 128, "debug_level 3");
|
||||
command_run_line(cmd_ctx, command_buffer);
|
||||
break;
|
||||
case 'l': /* --log_output | -l */
|
||||
if (optarg)
|
||||
{
|
||||
snprintf(command_buffer, 128, "log_output %s", optarg);
|
||||
command_run_line(cmd_ctx, command_buffer);
|
||||
}
|
||||
break;
|
||||
case 'c': /* --command | -c */
|
||||
if (optarg)
|
||||
{
|
||||
add_config_file_name(optarg);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (help_flag)
|
||||
{
|
||||
OUTPUT("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n");
|
||||
OUTPUT("--help | -h\tdisplay this help\n");
|
||||
OUTPUT("--file | -f\tuse configuration file <name>\n");
|
||||
OUTPUT("--search | -s\tdir to search for config files and scripts.\n");
|
||||
OUTPUT("--debug | -d\tset debug level <0-3>\n");
|
||||
OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
|
||||
OUTPUT("--command | -c\trun <command>\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Add the parent of the directory where openocd.exe resides to the
|
||||
* config script search path.
|
||||
* Directory layout:
|
||||
* bin\openocd.exe
|
||||
* lib\openocd
|
||||
* event\at91eb40a_reset.cfg
|
||||
* target\at91eb40a.cfg
|
||||
*/
|
||||
{
|
||||
char strExePath [MAX_PATH];
|
||||
GetModuleFileName (NULL, strExePath, MAX_PATH);
|
||||
/* Either this code will *always* work or it will SEGFAULT giving
|
||||
* excellent information on the culprit.
|
||||
*/
|
||||
*strrchr(strExePath, '\\')=0;
|
||||
strcat(strExePath, "\\..");
|
||||
add_script_search_dir(strExePath);
|
||||
}
|
||||
#else
|
||||
/* Add dir for openocd supplied scripts last so that user can over
|
||||
ride those scripts if desired. */
|
||||
add_script_search_dir(PKGDATADIR);
|
||||
add_script_search_dir(PKGLIBDIR);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -67,38 +67,38 @@ struct timezone {
|
|||
};
|
||||
|
||||
extern int gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**** clear_malloc & fill_malloc ****/
|
||||
void *clear_malloc(size_t size);
|
||||
void *fill_malloc(size_t size);
|
||||
|
||||
/*
|
||||
* Now you have 3 ways for the malloc function:
|
||||
*
|
||||
* 1. Do not change anything, use the original malloc
|
||||
*
|
||||
* 2. Use the clear_malloc function instead of the original malloc.
|
||||
* In this case you must use the following define:
|
||||
* #define malloc((_a)) clear_malloc((_a))
|
||||
*
|
||||
* 3. Use the fill_malloc function instead of the original malloc.
|
||||
* In this case you must use the following define:
|
||||
* #define malloc((_a)) fill_malloc((_a))
|
||||
*
|
||||
* We have figured out that there could exist some malloc problems
|
||||
* where variables are using without to be initialise. To find this
|
||||
* places, use the fill_malloc function. With this function we want
|
||||
* to initialize memory to some known bad state. This is quite easily
|
||||
* spotted in the debugger and will trap to an invalid address.
|
||||
*
|
||||
* clear_malloc can be used if you want to set not initialise
|
||||
* variable to 0.
|
||||
*
|
||||
* If you do not want to change the malloc function, to not use one of
|
||||
* the following macros. Which is the default way.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Now you have 3 ways for the malloc function:
|
||||
*
|
||||
* 1. Do not change anything, use the original malloc
|
||||
*
|
||||
* 2. Use the clear_malloc function instead of the original malloc.
|
||||
* In this case you must use the following define:
|
||||
* #define malloc((_a)) clear_malloc((_a))
|
||||
*
|
||||
* 3. Use the fill_malloc function instead of the original malloc.
|
||||
* In this case you must use the following define:
|
||||
* #define malloc((_a)) fill_malloc((_a))
|
||||
*
|
||||
* We have figured out that there could exist some malloc problems
|
||||
* where variables are using without to be initialise. To find this
|
||||
* places, use the fill_malloc function. With this function we want
|
||||
* to initialize memory to some known bad state. This is quite easily
|
||||
* spotted in the debugger and will trap to an invalid address.
|
||||
*
|
||||
* clear_malloc can be used if you want to set not initialise
|
||||
* variable to 0.
|
||||
*
|
||||
* If you do not want to change the malloc function, to not use one of
|
||||
* the following macros. Which is the default way.
|
||||
*/
|
||||
|
||||
//#define malloc(_a) clear_malloc(_a)
|
||||
//#define malloc(_a) fill_malloc(_a)
|
||||
|
||||
|
|
732
src/jtag/bitq.c
732
src/jtag/bitq.c
|
@ -1,366 +1,366 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Pavel Chromy *
|
||||
* chromy@asix.cz *
|
||||
* *
|
||||
* 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 "bitq.h"
|
||||
|
||||
/* project specific includes */
|
||||
#include "log.h"
|
||||
#include "types.h"
|
||||
#include "jtag.h"
|
||||
#include "configuration.h"
|
||||
|
||||
/* system includes */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
bitq_interface_t *bitq_interface; /* low level bit queue interface */
|
||||
|
||||
bitq_state_t bitq_in_state; /* state of input queue */
|
||||
|
||||
u8 *bitq_in_buffer; /* buffer dynamically reallocated as needed */
|
||||
unsigned long bitq_in_bufsize=32; /* min. buffer size */
|
||||
|
||||
|
||||
/*
|
||||
* input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
|
||||
* also the buffer for incomming data is reallocated only if necessary
|
||||
* no parameters, makes use of stored state information
|
||||
*/
|
||||
void bitq_in_proc(void)
|
||||
{
|
||||
/* static information preserved between calls to increase performance */
|
||||
static u8 *in_buff; /* pointer to buffer for scanned data */
|
||||
static int in_idx; /* index of byte being scanned */
|
||||
static u8 in_mask; /* mask of next bit to be scanned */
|
||||
|
||||
scan_field_t *field;
|
||||
int tdo;
|
||||
|
||||
/* loop through the queue */
|
||||
while (bitq_in_state.cmd) {
|
||||
/* only JTAG_SCAN command may return data */
|
||||
if (bitq_in_state.cmd->type==JTAG_SCAN) {
|
||||
/* loop through the fields */
|
||||
while (bitq_in_state.field_idx<bitq_in_state.cmd->cmd.scan->num_fields) {
|
||||
|
||||
field=&bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
|
||||
if ( field->in_value || field->in_handler) {
|
||||
|
||||
if (bitq_in_state.bit_pos==0) {
|
||||
/* initialize field scanning */
|
||||
in_mask=0x01;
|
||||
in_idx=0;
|
||||
if (field->in_value) in_buff=field->in_value;
|
||||
else {
|
||||
/* buffer reallocation needed? */
|
||||
if (field->num_bits>bitq_in_bufsize*8) {
|
||||
/* buffer previously allocated? */
|
||||
if (bitq_in_buffer!=NULL) {
|
||||
/* free it */
|
||||
free(bitq_in_buffer);
|
||||
bitq_in_buffer=NULL;
|
||||
}
|
||||
/* double the buffer size until it fits */
|
||||
while (field->num_bits>bitq_in_bufsize*8) bitq_in_bufsize*=2;
|
||||
}
|
||||
/* if necessary, allocate buffer and check for malloc error */
|
||||
if (bitq_in_buffer==NULL && (bitq_in_buffer=malloc(bitq_in_bufsize))==NULL) {
|
||||
ERROR("malloc error");
|
||||
exit(-1);
|
||||
}
|
||||
in_buff=(void *)bitq_in_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* field scanning */
|
||||
while (bitq_in_state.bit_pos<field->num_bits) {
|
||||
if ((tdo=bitq_interface->in())<0) {
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("bitq in EOF");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (in_mask==0x01) in_buff[in_idx]=0;
|
||||
if (tdo) in_buff[in_idx]|=in_mask;
|
||||
if (in_mask==0x80) {
|
||||
in_mask=0x01;
|
||||
in_idx++;
|
||||
}
|
||||
else in_mask<<=1;
|
||||
bitq_in_state.bit_pos++;
|
||||
}
|
||||
|
||||
|
||||
if (field->in_handler && bitq_in_state.status==ERROR_OK) {
|
||||
bitq_in_state.status=(*field->in_handler)(in_buff, field->in_handler_priv, field);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bitq_in_state.field_idx++; /* advance to next field */
|
||||
bitq_in_state.bit_pos=0; /* start next field from the first bit */
|
||||
}
|
||||
|
||||
}
|
||||
bitq_in_state.cmd=bitq_in_state.cmd->next; /* advance to next command */
|
||||
bitq_in_state.field_idx=0; /* preselect first field */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void bitq_io(int tms, int tdi, int tdo_req)
|
||||
{
|
||||
bitq_interface->out(tms, tdi, tdo_req);
|
||||
/* check and process the input queue */
|
||||
if (bitq_interface->in_rdy()) bitq_in_proc();
|
||||
}
|
||||
|
||||
|
||||
void bitq_end_state(enum tap_state state)
|
||||
{
|
||||
if (state==-1) return;
|
||||
if (tap_move_map[state]==-1) {
|
||||
ERROR("BUG: %i is not a valid end state", state);
|
||||
exit(-1);
|
||||
}
|
||||
end_state = state;
|
||||
}
|
||||
|
||||
|
||||
void bitq_state_move(enum tap_state new_state)
|
||||
{
|
||||
int i=0;
|
||||
u8 tms_scan;
|
||||
|
||||
if (tap_move_map[cur_state]==-1 || tap_move_map[new_state]==-1) {
|
||||
ERROR("TAP move from or to unstable state");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
tms_scan=TAP_MOVE(cur_state, new_state);
|
||||
|
||||
for (i=0; i<7; i++) {
|
||||
bitq_io(tms_scan&1, 0, 0);
|
||||
tms_scan>>=1;
|
||||
}
|
||||
|
||||
cur_state = new_state;
|
||||
}
|
||||
|
||||
|
||||
void bitq_path_move(pathmove_command_t *cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<=cmd->num_states; i++) {
|
||||
if (tap_transitions[cur_state].low == cmd->path[i]) bitq_io(0, 0, 0);
|
||||
else if (tap_transitions[cur_state].high == cmd->path[i]) bitq_io(1, 0, 0);
|
||||
else {
|
||||
ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[i]]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
cur_state = cmd->path[i];
|
||||
}
|
||||
|
||||
end_state = cur_state;
|
||||
}
|
||||
|
||||
|
||||
void bitq_runtest(int num_cycles)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* only do a state_move when we're not already in RTI */
|
||||
if (cur_state != TAP_RTI) bitq_state_move(TAP_RTI);
|
||||
|
||||
/* execute num_cycles */
|
||||
for (i = 0; i < num_cycles; i++)
|
||||
bitq_io(0, 0, 0);
|
||||
|
||||
/* finish in end_state */
|
||||
if (cur_state != end_state) bitq_state_move(end_state);
|
||||
}
|
||||
|
||||
|
||||
void bitq_scan_field(scan_field_t *field, int pause)
|
||||
{
|
||||
int bit_cnt;
|
||||
int tdo_req;
|
||||
|
||||
u8 *out_ptr;
|
||||
u8 out_mask;
|
||||
|
||||
if ( field->in_value || field->in_handler) tdo_req=1;
|
||||
else tdo_req=0;
|
||||
|
||||
if (field->out_value==NULL) {
|
||||
/* just send zeros and request data from TDO */
|
||||
for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--)
|
||||
bitq_io(0, 0, tdo_req);
|
||||
bitq_io(pause, 0, tdo_req);
|
||||
}
|
||||
else {
|
||||
/* send data, and optionally request TDO */
|
||||
out_mask=0x01;
|
||||
out_ptr=field->out_value;
|
||||
for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--) {
|
||||
bitq_io(0, ((*out_ptr)&out_mask)!=0, tdo_req);
|
||||
if (out_mask==0x80) {
|
||||
out_mask=0x01;
|
||||
out_ptr++;
|
||||
}
|
||||
else out_mask<<=1;
|
||||
}
|
||||
bitq_io(pause, ((*out_ptr)&out_mask)!=0, tdo_req);
|
||||
}
|
||||
|
||||
if (pause) {
|
||||
bitq_io(0,0,0);
|
||||
if (cur_state==TAP_SI) cur_state=TAP_PI;
|
||||
else if (cur_state==TAP_SD) cur_state=TAP_PD;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bitq_scan(scan_command_t *cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cmd->ir_scan) bitq_state_move(TAP_SI);
|
||||
else bitq_state_move(TAP_SD);
|
||||
|
||||
for (i=0; i < cmd->num_fields-1; i++)
|
||||
bitq_scan_field(&cmd->fields[i], 0);
|
||||
bitq_scan_field(&cmd->fields[i], 1);
|
||||
}
|
||||
|
||||
|
||||
int bitq_execute_queue(void)
|
||||
{
|
||||
jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
|
||||
|
||||
bitq_in_state.cmd = jtag_command_queue;
|
||||
bitq_in_state.field_idx = 0;
|
||||
bitq_in_state.bit_pos = 0;
|
||||
bitq_in_state.status = ERROR_OK;
|
||||
|
||||
while (cmd) {
|
||||
|
||||
switch (cmd->type) {
|
||||
|
||||
case JTAG_END_STATE:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
|
||||
#endif
|
||||
bitq_end_state(cmd->cmd.end_state->end_state);
|
||||
break;
|
||||
|
||||
case JTAG_RESET:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
|
||||
#endif
|
||||
bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
|
||||
if (bitq_interface->in_rdy()) bitq_in_proc();
|
||||
break;
|
||||
|
||||
case JTAG_RUNTEST:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
|
||||
#endif
|
||||
bitq_end_state(cmd->cmd.runtest->end_state);
|
||||
bitq_runtest(cmd->cmd.runtest->num_cycles);
|
||||
break;
|
||||
|
||||
case JTAG_STATEMOVE:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
|
||||
#endif
|
||||
bitq_end_state(cmd->cmd.statemove->end_state);
|
||||
bitq_state_move(end_state); /* uncoditional TAP move */
|
||||
break;
|
||||
|
||||
case JTAG_PATHMOVE:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
|
||||
#endif
|
||||
bitq_path_move(cmd->cmd.pathmove);
|
||||
break;
|
||||
|
||||
case JTAG_SCAN:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("scan end in %i", cmd->cmd.scan->end_state);
|
||||
if (cmd->cmd.scan->ir_scan) DEBUG("scan ir");
|
||||
else DEBUG("scan dr");
|
||||
#endif
|
||||
bitq_end_state(cmd->cmd.scan->end_state);
|
||||
bitq_scan(cmd->cmd.scan);
|
||||
if (cur_state != end_state) bitq_state_move(end_state);
|
||||
break;
|
||||
|
||||
case JTAG_SLEEP:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("sleep %i", cmd->cmd.sleep->us);
|
||||
#endif
|
||||
bitq_interface->sleep(cmd->cmd.sleep->us);
|
||||
if (bitq_interface->in_rdy()) bitq_in_proc();
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR("BUG: unknown JTAG command type encountered");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
cmd = cmd->next;
|
||||
}
|
||||
|
||||
bitq_interface->flush();
|
||||
bitq_in_proc();
|
||||
|
||||
if (bitq_in_state.cmd) {
|
||||
ERROR("missing data from bitq interface");
|
||||
return ERROR_JTAG_QUEUE_FAILED;
|
||||
}
|
||||
if (bitq_interface->in()>=0) {
|
||||
ERROR("extra data from bitq interface");
|
||||
return ERROR_JTAG_QUEUE_FAILED;
|
||||
}
|
||||
|
||||
return bitq_in_state.status;
|
||||
}
|
||||
|
||||
|
||||
void bitq_cleanup(void)
|
||||
{
|
||||
if (bitq_in_buffer!=NULL)
|
||||
{
|
||||
free(bitq_in_buffer);
|
||||
bitq_in_buffer=NULL;
|
||||
}
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Pavel Chromy *
|
||||
* chromy@asix.cz *
|
||||
* *
|
||||
* 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 "bitq.h"
|
||||
|
||||
/* project specific includes */
|
||||
#include "log.h"
|
||||
#include "types.h"
|
||||
#include "jtag.h"
|
||||
#include "configuration.h"
|
||||
|
||||
/* system includes */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
bitq_interface_t *bitq_interface; /* low level bit queue interface */
|
||||
|
||||
bitq_state_t bitq_in_state; /* state of input queue */
|
||||
|
||||
u8 *bitq_in_buffer; /* buffer dynamically reallocated as needed */
|
||||
unsigned long bitq_in_bufsize=32; /* min. buffer size */
|
||||
|
||||
|
||||
/*
|
||||
* input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
|
||||
* also the buffer for incomming data is reallocated only if necessary
|
||||
* no parameters, makes use of stored state information
|
||||
*/
|
||||
void bitq_in_proc(void)
|
||||
{
|
||||
/* static information preserved between calls to increase performance */
|
||||
static u8 *in_buff; /* pointer to buffer for scanned data */
|
||||
static int in_idx; /* index of byte being scanned */
|
||||
static u8 in_mask; /* mask of next bit to be scanned */
|
||||
|
||||
scan_field_t *field;
|
||||
int tdo;
|
||||
|
||||
/* loop through the queue */
|
||||
while (bitq_in_state.cmd) {
|
||||
/* only JTAG_SCAN command may return data */
|
||||
if (bitq_in_state.cmd->type==JTAG_SCAN) {
|
||||
/* loop through the fields */
|
||||
while (bitq_in_state.field_idx<bitq_in_state.cmd->cmd.scan->num_fields) {
|
||||
|
||||
field=&bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
|
||||
if ( field->in_value || field->in_handler) {
|
||||
|
||||
if (bitq_in_state.bit_pos==0) {
|
||||
/* initialize field scanning */
|
||||
in_mask=0x01;
|
||||
in_idx=0;
|
||||
if (field->in_value) in_buff=field->in_value;
|
||||
else {
|
||||
/* buffer reallocation needed? */
|
||||
if (field->num_bits>bitq_in_bufsize*8) {
|
||||
/* buffer previously allocated? */
|
||||
if (bitq_in_buffer!=NULL) {
|
||||
/* free it */
|
||||
free(bitq_in_buffer);
|
||||
bitq_in_buffer=NULL;
|
||||
}
|
||||
/* double the buffer size until it fits */
|
||||
while (field->num_bits>bitq_in_bufsize*8) bitq_in_bufsize*=2;
|
||||
}
|
||||
/* if necessary, allocate buffer and check for malloc error */
|
||||
if (bitq_in_buffer==NULL && (bitq_in_buffer=malloc(bitq_in_bufsize))==NULL) {
|
||||
ERROR("malloc error");
|
||||
exit(-1);
|
||||
}
|
||||
in_buff=(void *)bitq_in_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* field scanning */
|
||||
while (bitq_in_state.bit_pos<field->num_bits) {
|
||||
if ((tdo=bitq_interface->in())<0) {
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("bitq in EOF");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (in_mask==0x01) in_buff[in_idx]=0;
|
||||
if (tdo) in_buff[in_idx]|=in_mask;
|
||||
if (in_mask==0x80) {
|
||||
in_mask=0x01;
|
||||
in_idx++;
|
||||
}
|
||||
else in_mask<<=1;
|
||||
bitq_in_state.bit_pos++;
|
||||
}
|
||||
|
||||
|
||||
if (field->in_handler && bitq_in_state.status==ERROR_OK) {
|
||||
bitq_in_state.status=(*field->in_handler)(in_buff, field->in_handler_priv, field);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bitq_in_state.field_idx++; /* advance to next field */
|
||||
bitq_in_state.bit_pos=0; /* start next field from the first bit */
|
||||
}
|
||||
|
||||
}
|
||||
bitq_in_state.cmd=bitq_in_state.cmd->next; /* advance to next command */
|
||||
bitq_in_state.field_idx=0; /* preselect first field */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void bitq_io(int tms, int tdi, int tdo_req)
|
||||
{
|
||||
bitq_interface->out(tms, tdi, tdo_req);
|
||||
/* check and process the input queue */
|
||||
if (bitq_interface->in_rdy()) bitq_in_proc();
|
||||
}
|
||||
|
||||
|
||||
void bitq_end_state(enum tap_state state)
|
||||
{
|
||||
if (state==-1) return;
|
||||
if (tap_move_map[state]==-1) {
|
||||
ERROR("BUG: %i is not a valid end state", state);
|
||||
exit(-1);
|
||||
}
|
||||
end_state = state;
|
||||
}
|
||||
|
||||
|
||||
void bitq_state_move(enum tap_state new_state)
|
||||
{
|
||||
int i=0;
|
||||
u8 tms_scan;
|
||||
|
||||
if (tap_move_map[cur_state]==-1 || tap_move_map[new_state]==-1) {
|
||||
ERROR("TAP move from or to unstable state");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
tms_scan=TAP_MOVE(cur_state, new_state);
|
||||
|
||||
for (i=0; i<7; i++) {
|
||||
bitq_io(tms_scan&1, 0, 0);
|
||||
tms_scan>>=1;
|
||||
}
|
||||
|
||||
cur_state = new_state;
|
||||
}
|
||||
|
||||
|
||||
void bitq_path_move(pathmove_command_t *cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<=cmd->num_states; i++) {
|
||||
if (tap_transitions[cur_state].low == cmd->path[i]) bitq_io(0, 0, 0);
|
||||
else if (tap_transitions[cur_state].high == cmd->path[i]) bitq_io(1, 0, 0);
|
||||
else {
|
||||
ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[i]]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
cur_state = cmd->path[i];
|
||||
}
|
||||
|
||||
end_state = cur_state;
|
||||
}
|
||||
|
||||
|
||||
void bitq_runtest(int num_cycles)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* only do a state_move when we're not already in RTI */
|
||||
if (cur_state != TAP_RTI) bitq_state_move(TAP_RTI);
|
||||
|
||||
/* execute num_cycles */
|
||||
for (i = 0; i < num_cycles; i++)
|
||||
bitq_io(0, 0, 0);
|
||||
|
||||
/* finish in end_state */
|
||||
if (cur_state != end_state) bitq_state_move(end_state);
|
||||
}
|
||||
|
||||
|
||||
void bitq_scan_field(scan_field_t *field, int pause)
|
||||
{
|
||||
int bit_cnt;
|
||||
int tdo_req;
|
||||
|
||||
u8 *out_ptr;
|
||||
u8 out_mask;
|
||||
|
||||
if ( field->in_value || field->in_handler) tdo_req=1;
|
||||
else tdo_req=0;
|
||||
|
||||
if (field->out_value==NULL) {
|
||||
/* just send zeros and request data from TDO */
|
||||
for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--)
|
||||
bitq_io(0, 0, tdo_req);
|
||||
bitq_io(pause, 0, tdo_req);
|
||||
}
|
||||
else {
|
||||
/* send data, and optionally request TDO */
|
||||
out_mask=0x01;
|
||||
out_ptr=field->out_value;
|
||||
for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--) {
|
||||
bitq_io(0, ((*out_ptr)&out_mask)!=0, tdo_req);
|
||||
if (out_mask==0x80) {
|
||||
out_mask=0x01;
|
||||
out_ptr++;
|
||||
}
|
||||
else out_mask<<=1;
|
||||
}
|
||||
bitq_io(pause, ((*out_ptr)&out_mask)!=0, tdo_req);
|
||||
}
|
||||
|
||||
if (pause) {
|
||||
bitq_io(0,0,0);
|
||||
if (cur_state==TAP_SI) cur_state=TAP_PI;
|
||||
else if (cur_state==TAP_SD) cur_state=TAP_PD;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bitq_scan(scan_command_t *cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cmd->ir_scan) bitq_state_move(TAP_SI);
|
||||
else bitq_state_move(TAP_SD);
|
||||
|
||||
for (i=0; i < cmd->num_fields-1; i++)
|
||||
bitq_scan_field(&cmd->fields[i], 0);
|
||||
bitq_scan_field(&cmd->fields[i], 1);
|
||||
}
|
||||
|
||||
|
||||
int bitq_execute_queue(void)
|
||||
{
|
||||
jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
|
||||
|
||||
bitq_in_state.cmd = jtag_command_queue;
|
||||
bitq_in_state.field_idx = 0;
|
||||
bitq_in_state.bit_pos = 0;
|
||||
bitq_in_state.status = ERROR_OK;
|
||||
|
||||
while (cmd) {
|
||||
|
||||
switch (cmd->type) {
|
||||
|
||||
case JTAG_END_STATE:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
|
||||
#endif
|
||||
bitq_end_state(cmd->cmd.end_state->end_state);
|
||||
break;
|
||||
|
||||
case JTAG_RESET:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
|
||||
#endif
|
||||
bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
|
||||
if (bitq_interface->in_rdy()) bitq_in_proc();
|
||||
break;
|
||||
|
||||
case JTAG_RUNTEST:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
|
||||
#endif
|
||||
bitq_end_state(cmd->cmd.runtest->end_state);
|
||||
bitq_runtest(cmd->cmd.runtest->num_cycles);
|
||||
break;
|
||||
|
||||
case JTAG_STATEMOVE:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
|
||||
#endif
|
||||
bitq_end_state(cmd->cmd.statemove->end_state);
|
||||
bitq_state_move(end_state); /* uncoditional TAP move */
|
||||
break;
|
||||
|
||||
case JTAG_PATHMOVE:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
|
||||
#endif
|
||||
bitq_path_move(cmd->cmd.pathmove);
|
||||
break;
|
||||
|
||||
case JTAG_SCAN:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("scan end in %i", cmd->cmd.scan->end_state);
|
||||
if (cmd->cmd.scan->ir_scan) DEBUG("scan ir");
|
||||
else DEBUG("scan dr");
|
||||
#endif
|
||||
bitq_end_state(cmd->cmd.scan->end_state);
|
||||
bitq_scan(cmd->cmd.scan);
|
||||
if (cur_state != end_state) bitq_state_move(end_state);
|
||||
break;
|
||||
|
||||
case JTAG_SLEEP:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
DEBUG("sleep %i", cmd->cmd.sleep->us);
|
||||
#endif
|
||||
bitq_interface->sleep(cmd->cmd.sleep->us);
|
||||
if (bitq_interface->in_rdy()) bitq_in_proc();
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR("BUG: unknown JTAG command type encountered");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
cmd = cmd->next;
|
||||
}
|
||||
|
||||
bitq_interface->flush();
|
||||
bitq_in_proc();
|
||||
|
||||
if (bitq_in_state.cmd) {
|
||||
ERROR("missing data from bitq interface");
|
||||
return ERROR_JTAG_QUEUE_FAILED;
|
||||
}
|
||||
if (bitq_interface->in()>=0) {
|
||||
ERROR("extra data from bitq interface");
|
||||
return ERROR_JTAG_QUEUE_FAILED;
|
||||
}
|
||||
|
||||
return bitq_in_state.status;
|
||||
}
|
||||
|
||||
|
||||
void bitq_cleanup(void)
|
||||
{
|
||||
if (bitq_in_buffer!=NULL)
|
||||
{
|
||||
free(bitq_in_buffer);
|
||||
bitq_in_buffer=NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,237 +1,237 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "log.h"
|
||||
#include "jtag.h"
|
||||
#include "bitbang.h"
|
||||
|
||||
#define TDO_BIT 1
|
||||
#define TDI_BIT 2
|
||||
#define TCK_BIT 4
|
||||
#define TMS_BIT 8
|
||||
#define TRST_BIT 16
|
||||
#define SRST_BIT 32
|
||||
#define VCC_BIT 64
|
||||
|
||||
/* system includes */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static u8 output_value = 0x0;
|
||||
static int dev_mem_fd;
|
||||
static void *gpio_controller;
|
||||
static volatile u8 *gpio_data_register;
|
||||
static volatile u8 *gpio_data_direction_register;
|
||||
|
||||
/* low level command set
|
||||
*/
|
||||
int ep93xx_read(void);
|
||||
void ep93xx_write(int tck, int tms, int tdi);
|
||||
void ep93xx_reset(int trst, int srst);
|
||||
|
||||
int ep93xx_speed(int speed);
|
||||
int ep93xx_register_commands(struct command_context_s *cmd_ctx);
|
||||
int ep93xx_init(void);
|
||||
int ep93xx_quit(void);
|
||||
|
||||
struct timespec ep93xx_zzzz;
|
||||
|
||||
jtag_interface_t ep93xx_interface =
|
||||
{
|
||||
.name = "ep93xx",
|
||||
|
||||
.execute_queue = bitbang_execute_queue,
|
||||
|
||||
.speed = ep93xx_speed,
|
||||
.register_commands = ep93xx_register_commands,
|
||||
.init = ep93xx_init,
|
||||
.quit = ep93xx_quit,
|
||||
};
|
||||
|
||||
bitbang_interface_t ep93xx_bitbang =
|
||||
{
|
||||
.read = ep93xx_read,
|
||||
.write = ep93xx_write,
|
||||
.reset = ep93xx_reset,
|
||||
.blink = 0;
|
||||
};
|
||||
|
||||
int ep93xx_read(void)
|
||||
{
|
||||
return !!(*gpio_data_register & TDO_BIT);
|
||||
}
|
||||
|
||||
void ep93xx_write(int tck, int tms, int tdi)
|
||||
{
|
||||
if (tck)
|
||||
output_value |= TCK_BIT;
|
||||
else
|
||||
output_value &= TCK_BIT;
|
||||
|
||||
if (tms)
|
||||
output_value |= TMS_BIT;
|
||||
else
|
||||
output_value &= TMS_BIT;
|
||||
|
||||
if (tdi)
|
||||
output_value |= TDI_BIT;
|
||||
else
|
||||
output_value &= TDI_BIT;
|
||||
|
||||
*gpio_data_register = output_value;
|
||||
nanosleep(ep93xx_zzzz);
|
||||
}
|
||||
|
||||
/* (1) assert or (0) deassert reset lines */
|
||||
void ep93xx_reset(int trst, int srst)
|
||||
{
|
||||
if (trst == 0)
|
||||
output_value |= TRST_BIT;
|
||||
else if (trst == 1)
|
||||
output_value &= TRST_BIT;
|
||||
|
||||
if (srst == 0)
|
||||
output_value |= SRST_BIT;
|
||||
else if (srst == 1)
|
||||
output_value &= SRST_BIT;
|
||||
|
||||
*gpio_data_register = output_value;
|
||||
nanosleep(ep93xx_zzzz);
|
||||
}
|
||||
|
||||
int ep93xx_speed(int speed)
|
||||
{
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int ep93xx_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int set_gonk_mode(void)
|
||||
{
|
||||
void *syscon;
|
||||
u32 devicecfg;
|
||||
|
||||
syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, dev_mem_fd, 0x80930000);
|
||||
if (syscon == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
devicecfg = *((volatile int *)(syscon + 0x80));
|
||||
*((volatile int *)(syscon + 0xc0)) = 0xaa;
|
||||
*((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000;
|
||||
|
||||
munmap(syscon, 4096);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int ep93xx_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
bitbang_interface = &ep93xx_bitbang;
|
||||
|
||||
ep93xx_zzzz.tv_sec = 0;
|
||||
ep93xx_zzzz.tv_nsec = 10000000;
|
||||
|
||||
dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
|
||||
if (dev_mem_fd < 0) {
|
||||
perror("open");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, dev_mem_fd, 0x80840000);
|
||||
if (gpio_controller == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
close(dev_mem_fd);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
ret = set_gonk_mode();
|
||||
if (ret != ERROR_OK) {
|
||||
munmap(gpio_controller, 4096);
|
||||
close(dev_mem_fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Use GPIO port A. */
|
||||
gpio_data_register = gpio_controller + 0x00;
|
||||
gpio_data_direction_register = gpio_controller + 0x10;
|
||||
|
||||
|
||||
/* Use GPIO port B. */
|
||||
gpio_data_register = gpio_controller + 0x04;
|
||||
gpio_data_direction_register = gpio_controller + 0x14;
|
||||
|
||||
/* Use GPIO port C. */
|
||||
gpio_data_register = gpio_controller + 0x08;
|
||||
gpio_data_direction_register = gpio_controller + 0x18;
|
||||
|
||||
/* Use GPIO port D. */
|
||||
gpio_data_register = gpio_controller + 0x0c;
|
||||
gpio_data_direction_register = gpio_controller + 0x1c;
|
||||
#endif
|
||||
|
||||
/* Use GPIO port C. */
|
||||
gpio_data_register = gpio_controller + 0x08;
|
||||
gpio_data_direction_register = gpio_controller + 0x18;
|
||||
|
||||
INFO("gpio_data_register = %p\n", gpio_data_register);
|
||||
INFO("gpio_data_direction_reg = %p\n", gpio_data_direction_register);
|
||||
/*
|
||||
* Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK
|
||||
* TMS, TRST, SRST) as outputs. Drive TDI and TCK low, and
|
||||
* TMS/TRST/SRST high.
|
||||
*/
|
||||
output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
|
||||
*gpio_data_register = output_value;
|
||||
nanosleep(ep93xx_zzzz);
|
||||
|
||||
/*
|
||||
* Configure the direction register. 1 = output, 0 = input.
|
||||
*/
|
||||
*gpio_data_direction_register =
|
||||
TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
|
||||
|
||||
nanosleep(ep93xx_zzzz);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int ep93xx_quit(void)
|
||||
{
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "log.h"
|
||||
#include "jtag.h"
|
||||
#include "bitbang.h"
|
||||
|
||||
#define TDO_BIT 1
|
||||
#define TDI_BIT 2
|
||||
#define TCK_BIT 4
|
||||
#define TMS_BIT 8
|
||||
#define TRST_BIT 16
|
||||
#define SRST_BIT 32
|
||||
#define VCC_BIT 64
|
||||
|
||||
/* system includes */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static u8 output_value = 0x0;
|
||||
static int dev_mem_fd;
|
||||
static void *gpio_controller;
|
||||
static volatile u8 *gpio_data_register;
|
||||
static volatile u8 *gpio_data_direction_register;
|
||||
|
||||
/* low level command set
|
||||
*/
|
||||
int ep93xx_read(void);
|
||||
void ep93xx_write(int tck, int tms, int tdi);
|
||||
void ep93xx_reset(int trst, int srst);
|
||||
|
||||
int ep93xx_speed(int speed);
|
||||
int ep93xx_register_commands(struct command_context_s *cmd_ctx);
|
||||
int ep93xx_init(void);
|
||||
int ep93xx_quit(void);
|
||||
|
||||
struct timespec ep93xx_zzzz;
|
||||
|
||||
jtag_interface_t ep93xx_interface =
|
||||
{
|
||||
.name = "ep93xx",
|
||||
|
||||
.execute_queue = bitbang_execute_queue,
|
||||
|
||||
.speed = ep93xx_speed,
|
||||
.register_commands = ep93xx_register_commands,
|
||||
.init = ep93xx_init,
|
||||
.quit = ep93xx_quit,
|
||||
};
|
||||
|
||||
bitbang_interface_t ep93xx_bitbang =
|
||||
{
|
||||
.read = ep93xx_read,
|
||||
.write = ep93xx_write,
|
||||
.reset = ep93xx_reset,
|
||||
.blink = 0;
|
||||
};
|
||||
|
||||
int ep93xx_read(void)
|
||||
{
|
||||
return !!(*gpio_data_register & TDO_BIT);
|
||||
}
|
||||
|
||||
void ep93xx_write(int tck, int tms, int tdi)
|
||||
{
|
||||
if (tck)
|
||||
output_value |= TCK_BIT;
|
||||
else
|
||||
output_value &= TCK_BIT;
|
||||
|
||||
if (tms)
|
||||
output_value |= TMS_BIT;
|
||||
else
|
||||
output_value &= TMS_BIT;
|
||||
|
||||
if (tdi)
|
||||
output_value |= TDI_BIT;
|
||||
else
|
||||
output_value &= TDI_BIT;
|
||||
|
||||
*gpio_data_register = output_value;
|
||||
nanosleep(ep93xx_zzzz);
|
||||
}
|
||||
|
||||
/* (1) assert or (0) deassert reset lines */
|
||||
void ep93xx_reset(int trst, int srst)
|
||||
{
|
||||
if (trst == 0)
|
||||
output_value |= TRST_BIT;
|
||||
else if (trst == 1)
|
||||
output_value &= TRST_BIT;
|
||||
|
||||
if (srst == 0)
|
||||
output_value |= SRST_BIT;
|
||||
else if (srst == 1)
|
||||
output_value &= SRST_BIT;
|
||||
|
||||
*gpio_data_register = output_value;
|
||||
nanosleep(ep93xx_zzzz);
|
||||
}
|
||||
|
||||
int ep93xx_speed(int speed)
|
||||
{
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int ep93xx_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int set_gonk_mode(void)
|
||||
{
|
||||
void *syscon;
|
||||
u32 devicecfg;
|
||||
|
||||
syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, dev_mem_fd, 0x80930000);
|
||||
if (syscon == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
devicecfg = *((volatile int *)(syscon + 0x80));
|
||||
*((volatile int *)(syscon + 0xc0)) = 0xaa;
|
||||
*((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000;
|
||||
|
||||
munmap(syscon, 4096);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int ep93xx_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
bitbang_interface = &ep93xx_bitbang;
|
||||
|
||||
ep93xx_zzzz.tv_sec = 0;
|
||||
ep93xx_zzzz.tv_nsec = 10000000;
|
||||
|
||||
dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
|
||||
if (dev_mem_fd < 0) {
|
||||
perror("open");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, dev_mem_fd, 0x80840000);
|
||||
if (gpio_controller == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
close(dev_mem_fd);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
ret = set_gonk_mode();
|
||||
if (ret != ERROR_OK) {
|
||||
munmap(gpio_controller, 4096);
|
||||
close(dev_mem_fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Use GPIO port A. */
|
||||
gpio_data_register = gpio_controller + 0x00;
|
||||
gpio_data_direction_register = gpio_controller + 0x10;
|
||||
|
||||
|
||||
/* Use GPIO port B. */
|
||||
gpio_data_register = gpio_controller + 0x04;
|
||||
gpio_data_direction_register = gpio_controller + 0x14;
|
||||
|
||||
/* Use GPIO port C. */
|
||||
gpio_data_register = gpio_controller + 0x08;
|
||||
gpio_data_direction_register = gpio_controller + 0x18;
|
||||
|
||||
/* Use GPIO port D. */
|
||||
gpio_data_register = gpio_controller + 0x0c;
|
||||
gpio_data_direction_register = gpio_controller + 0x1c;
|
||||
#endif
|
||||
|
||||
/* Use GPIO port C. */
|
||||
gpio_data_register = gpio_controller + 0x08;
|
||||
gpio_data_direction_register = gpio_controller + 0x18;
|
||||
|
||||
INFO("gpio_data_register = %p\n", gpio_data_register);
|
||||
INFO("gpio_data_direction_reg = %p\n", gpio_data_direction_register);
|
||||
/*
|
||||
* Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK
|
||||
* TMS, TRST, SRST) as outputs. Drive TDI and TCK low, and
|
||||
* TMS/TRST/SRST high.
|
||||
*/
|
||||
output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
|
||||
*gpio_data_register = output_value;
|
||||
nanosleep(ep93xx_zzzz);
|
||||
|
||||
/*
|
||||
* Configure the direction register. 1 = output, 0 = input.
|
||||
*/
|
||||
*gpio_data_direction_register =
|
||||
TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
|
||||
|
||||
nanosleep(ep93xx_zzzz);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int ep93xx_quit(void)
|
||||
{
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
4278
src/jtag/ft2232.c
4278
src/jtag/ft2232.c
File diff suppressed because it is too large
Load Diff
3682
src/jtag/jtag.c
3682
src/jtag/jtag.c
File diff suppressed because it is too large
Load Diff
1362
src/jtag/usbprog.c
1362
src/jtag/usbprog.c
File diff suppressed because it is too large
Load Diff
314
src/openocd.c
314
src/openocd.c
|
@ -1,157 +1,157 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
#include "types.h"
|
||||
#include "jtag.h"
|
||||
#include "configuration.h"
|
||||
#include "interpreter.h"
|
||||
#include "xsvf.h"
|
||||
#include "target.h"
|
||||
#include "flash.h"
|
||||
#include "nand.h"
|
||||
#include "pld.h"
|
||||
|
||||
#include "command.h"
|
||||
#include "server.h"
|
||||
#include "telnet_server.h"
|
||||
#include "gdb_server.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <strings.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Give TELNET a way to find out what version this is */
|
||||
int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
command_print(cmd_ctx, OPENOCD_VERSION);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
void exit_handler(void)
|
||||
{
|
||||
/* close JTAG interface */
|
||||
if (jtag && jtag->quit)
|
||||
jtag->quit();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* initialize commandline interface */
|
||||
command_context_t *cmd_ctx, *cfg_cmd_ctx;
|
||||
cmd_ctx = command_init();
|
||||
|
||||
register_command(cmd_ctx, NULL, "version", handle_version_command,
|
||||
COMMAND_EXEC, "show OpenOCD version");
|
||||
|
||||
/* register subsystem commands */
|
||||
server_register_commands(cmd_ctx);
|
||||
telnet_register_commands(cmd_ctx);
|
||||
gdb_register_commands(cmd_ctx);
|
||||
log_register_commands(cmd_ctx);
|
||||
jtag_register_commands(cmd_ctx);
|
||||
interpreter_register_commands(cmd_ctx);
|
||||
xsvf_register_commands(cmd_ctx);
|
||||
target_register_commands(cmd_ctx);
|
||||
flash_register_commands(cmd_ctx);
|
||||
nand_register_commands(cmd_ctx);
|
||||
pld_register_commands(cmd_ctx);
|
||||
|
||||
if (log_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("log init complete");
|
||||
|
||||
printf( OPENOCD_VERSION );
|
||||
printf( "\n$URL$\n");
|
||||
|
||||
DEBUG( OPENOCD_VERSION );
|
||||
DEBUG( "$URL$");
|
||||
|
||||
cfg_cmd_ctx = copy_command_context(cmd_ctx);
|
||||
cfg_cmd_ctx->mode = COMMAND_CONFIG;
|
||||
command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
|
||||
|
||||
if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
command_done(cfg_cmd_ctx);
|
||||
|
||||
command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
|
||||
|
||||
atexit(exit_handler);
|
||||
|
||||
if (jtag_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("jtag init complete");
|
||||
|
||||
if (target_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("target init complete");
|
||||
|
||||
if (flash_init_drivers(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("flash init complete");
|
||||
|
||||
if (nand_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("NAND init complete");
|
||||
|
||||
if (pld_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("pld init complete");
|
||||
|
||||
/* initialize tcp server */
|
||||
server_init();
|
||||
|
||||
/* initialize telnet subsystem */
|
||||
telnet_init("Open On-Chip Debugger");
|
||||
gdb_init();
|
||||
|
||||
/* call any target resets */
|
||||
if (target_init_reset(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("target init reset complete");
|
||||
|
||||
/* handle network connections */
|
||||
server_loop(cmd_ctx);
|
||||
|
||||
/* shut server down */
|
||||
server_quit();
|
||||
|
||||
/* free commandline interface */
|
||||
command_done(cmd_ctx);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
#include "types.h"
|
||||
#include "jtag.h"
|
||||
#include "configuration.h"
|
||||
#include "interpreter.h"
|
||||
#include "xsvf.h"
|
||||
#include "target.h"
|
||||
#include "flash.h"
|
||||
#include "nand.h"
|
||||
#include "pld.h"
|
||||
|
||||
#include "command.h"
|
||||
#include "server.h"
|
||||
#include "telnet_server.h"
|
||||
#include "gdb_server.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <strings.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Give TELNET a way to find out what version this is */
|
||||
int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
command_print(cmd_ctx, OPENOCD_VERSION);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
void exit_handler(void)
|
||||
{
|
||||
/* close JTAG interface */
|
||||
if (jtag && jtag->quit)
|
||||
jtag->quit();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* initialize commandline interface */
|
||||
command_context_t *cmd_ctx, *cfg_cmd_ctx;
|
||||
cmd_ctx = command_init();
|
||||
|
||||
register_command(cmd_ctx, NULL, "version", handle_version_command,
|
||||
COMMAND_EXEC, "show OpenOCD version");
|
||||
|
||||
/* register subsystem commands */
|
||||
server_register_commands(cmd_ctx);
|
||||
telnet_register_commands(cmd_ctx);
|
||||
gdb_register_commands(cmd_ctx);
|
||||
log_register_commands(cmd_ctx);
|
||||
jtag_register_commands(cmd_ctx);
|
||||
interpreter_register_commands(cmd_ctx);
|
||||
xsvf_register_commands(cmd_ctx);
|
||||
target_register_commands(cmd_ctx);
|
||||
flash_register_commands(cmd_ctx);
|
||||
nand_register_commands(cmd_ctx);
|
||||
pld_register_commands(cmd_ctx);
|
||||
|
||||
if (log_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("log init complete");
|
||||
|
||||
printf( OPENOCD_VERSION );
|
||||
printf( "\n$URL$\n");
|
||||
|
||||
DEBUG( OPENOCD_VERSION );
|
||||
DEBUG( "$URL$");
|
||||
|
||||
cfg_cmd_ctx = copy_command_context(cmd_ctx);
|
||||
cfg_cmd_ctx->mode = COMMAND_CONFIG;
|
||||
command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
|
||||
|
||||
if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
command_done(cfg_cmd_ctx);
|
||||
|
||||
command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
|
||||
|
||||
atexit(exit_handler);
|
||||
|
||||
if (jtag_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("jtag init complete");
|
||||
|
||||
if (target_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("target init complete");
|
||||
|
||||
if (flash_init_drivers(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("flash init complete");
|
||||
|
||||
if (nand_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("NAND init complete");
|
||||
|
||||
if (pld_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("pld init complete");
|
||||
|
||||
/* initialize tcp server */
|
||||
server_init();
|
||||
|
||||
/* initialize telnet subsystem */
|
||||
telnet_init("Open On-Chip Debugger");
|
||||
gdb_init();
|
||||
|
||||
/* call any target resets */
|
||||
if (target_init_reset(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
DEBUG("target init reset complete");
|
||||
|
||||
/* handle network connections */
|
||||
server_loop(cmd_ctx);
|
||||
|
||||
/* shut server down */
|
||||
server_quit();
|
||||
|
||||
/* free commandline interface */
|
||||
command_done(cmd_ctx);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,264 +1,264 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2006 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "virtex2.h"
|
||||
|
||||
#include "pld.h"
|
||||
#include "xilinx_bit.h"
|
||||
#include "command.h"
|
||||
#include "log.h"
|
||||
#include "jtag.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int virtex2_register_commands(struct command_context_s *cmd_ctx);
|
||||
int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);
|
||||
int virtex2_load(struct pld_device_s *pld_device, char *filename);
|
||||
|
||||
pld_driver_t virtex2_pld =
|
||||
{
|
||||
.name = "virtex2",
|
||||
.register_commands = virtex2_register_commands,
|
||||
.pld_device_command = virtex2_pld_device_command,
|
||||
.load = virtex2_load,
|
||||
};
|
||||
|
||||
int virtex2_set_instr(int chain_pos, u32 new_instr)
|
||||
{
|
||||
jtag_device_t *device = jtag_get_device(chain_pos);
|
||||
|
||||
if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
|
||||
{
|
||||
scan_field_t field;
|
||||
|
||||
field.device = chain_pos;
|
||||
field.num_bits = device->ir_length;
|
||||
field.out_value = calloc(CEIL(field.num_bits, 8), 1);
|
||||
buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
|
||||
field.out_mask = NULL;
|
||||
field.in_value = NULL;
|
||||
field.in_check_value = NULL;
|
||||
field.in_check_mask = NULL;
|
||||
field.in_handler = NULL;
|
||||
field.in_handler_priv = NULL;
|
||||
|
||||
jtag_add_ir_scan(1, &field, TAP_RTI);
|
||||
|
||||
free(field.out_value);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_send_32(struct pld_device_s *pld_device, int num_words, u32 *words)
|
||||
{
|
||||
virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
|
||||
scan_field_t scan_field;
|
||||
u8 *values;
|
||||
int i;
|
||||
|
||||
values = malloc(num_words * 4);
|
||||
|
||||
scan_field.device = virtex2_info->chain_pos;
|
||||
scan_field.num_bits = num_words * 32;
|
||||
scan_field.out_value = values;
|
||||
scan_field.out_mask = NULL;
|
||||
scan_field.in_value = NULL;
|
||||
scan_field.in_check_value = NULL;
|
||||
scan_field.in_check_mask = NULL;
|
||||
scan_field.in_handler = NULL;
|
||||
scan_field.in_handler_priv = NULL;
|
||||
|
||||
for (i = 0; i < num_words; i++)
|
||||
buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
|
||||
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
|
||||
|
||||
jtag_add_dr_scan(1, &scan_field, TAP_PD);
|
||||
|
||||
free(values);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u32 *dest = priv;
|
||||
*dest = flip_u32(le_to_h_u32(in_buf), 32);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_receive_32(struct pld_device_s *pld_device, int num_words, u32 *words)
|
||||
{
|
||||
virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
|
||||
scan_field_t scan_field;
|
||||
|
||||
scan_field.device = virtex2_info->chain_pos;
|
||||
scan_field.num_bits = 32;
|
||||
scan_field.out_value = NULL;
|
||||
scan_field.out_mask = NULL;
|
||||
scan_field.in_value = NULL;
|
||||
scan_field.in_check_value = NULL;
|
||||
scan_field.in_check_mask = NULL;
|
||||
scan_field.in_handler = virtex2_jtag_buf_to_u32;
|
||||
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x4); /* CFG_OUT */
|
||||
|
||||
while (num_words--)
|
||||
{
|
||||
scan_field.in_handler_priv = words++;
|
||||
jtag_add_dr_scan(1, &scan_field, TAP_PD);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_read_stat(struct pld_device_s *pld_device, u32 *status)
|
||||
{
|
||||
u32 data[5];
|
||||
|
||||
jtag_add_statemove(TAP_TLR);
|
||||
|
||||
data[0] = 0xaa995566; /* synch word */
|
||||
data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */
|
||||
data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
|
||||
data[3] = 0x20000000; /* NOOP */
|
||||
data[4] = 0x20000000; /* NOOP */
|
||||
virtex2_send_32(pld_device, 5, data);
|
||||
|
||||
virtex2_receive_32(pld_device, 1, status);
|
||||
|
||||
jtag_execute_queue();
|
||||
|
||||
DEBUG("status: 0x%8.8x", *status);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_load(struct pld_device_s *pld_device, char *filename)
|
||||
{
|
||||
virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
|
||||
xilinx_bit_file_t bit_file;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
scan_field_t field;
|
||||
|
||||
field.device = virtex2_info->chain_pos;
|
||||
field.out_mask = NULL;
|
||||
field.in_value = NULL;
|
||||
field.in_check_value = NULL;
|
||||
field.in_check_mask = NULL;
|
||||
field.in_handler = NULL;
|
||||
field.in_handler_priv = NULL;
|
||||
|
||||
if ((retval = xilinx_read_bit_file(&bit_file, filename)) != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
jtag_add_end_state(TAP_RTI);
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0xb); /* JPROG_B */
|
||||
jtag_execute_queue();
|
||||
jtag_add_sleep(1000);
|
||||
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
|
||||
jtag_execute_queue();
|
||||
|
||||
for (i = 0; i < bit_file.length; i++)
|
||||
bit_file.data[i] = flip_u32(bit_file.data[i], 8);
|
||||
|
||||
field.num_bits = bit_file.length * 8;
|
||||
field.out_value = bit_file.data;
|
||||
|
||||
jtag_add_dr_scan(1, &field, TAP_PD);
|
||||
jtag_execute_queue();
|
||||
|
||||
jtag_add_statemove(TAP_TLR);
|
||||
|
||||
jtag_add_end_state(TAP_RTI);
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
|
||||
jtag_add_runtest(13, TAP_RTI);
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
|
||||
jtag_add_runtest(13, TAP_RTI);
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
|
||||
jtag_execute_queue();
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_handle_read_stat_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
pld_device_t *device;
|
||||
virtex2_pld_device_t *virtex2_info;
|
||||
u32 status;
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
command_print(cmd_ctx, "usage: virtex2 read_stat <num>");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
device = get_pld_device_by_num(strtoul(args[0], NULL, 0));
|
||||
if (!device)
|
||||
{
|
||||
command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
virtex2_info = device->driver_priv;
|
||||
|
||||
virtex2_read_stat(device, &status);
|
||||
|
||||
command_print(cmd_ctx, "virtex2 status register: 0x%8.8x", status);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
command_t *virtex2_cmd = register_command(cmd_ctx, NULL, "virtex2", NULL, COMMAND_ANY, "virtex2 specific commands");
|
||||
|
||||
register_command(cmd_ctx, virtex2_cmd, "read_stat", virtex2_handle_read_stat_command, COMMAND_EXEC,
|
||||
"read Virtex-II status register");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device)
|
||||
{
|
||||
virtex2_pld_device_t *virtex2_info;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
WARNING("incomplete pld device 'virtex2' configuration");
|
||||
return ERROR_PLD_DEVICE_INVALID;
|
||||
}
|
||||
|
||||
virtex2_info = malloc(sizeof(virtex2_pld_device_t));
|
||||
pld_device->driver_priv = virtex2_info;
|
||||
|
||||
virtex2_info->chain_pos = strtoul(args[1], NULL, 0);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2006 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "virtex2.h"
|
||||
|
||||
#include "pld.h"
|
||||
#include "xilinx_bit.h"
|
||||
#include "command.h"
|
||||
#include "log.h"
|
||||
#include "jtag.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int virtex2_register_commands(struct command_context_s *cmd_ctx);
|
||||
int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);
|
||||
int virtex2_load(struct pld_device_s *pld_device, char *filename);
|
||||
|
||||
pld_driver_t virtex2_pld =
|
||||
{
|
||||
.name = "virtex2",
|
||||
.register_commands = virtex2_register_commands,
|
||||
.pld_device_command = virtex2_pld_device_command,
|
||||
.load = virtex2_load,
|
||||
};
|
||||
|
||||
int virtex2_set_instr(int chain_pos, u32 new_instr)
|
||||
{
|
||||
jtag_device_t *device = jtag_get_device(chain_pos);
|
||||
|
||||
if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
|
||||
{
|
||||
scan_field_t field;
|
||||
|
||||
field.device = chain_pos;
|
||||
field.num_bits = device->ir_length;
|
||||
field.out_value = calloc(CEIL(field.num_bits, 8), 1);
|
||||
buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
|
||||
field.out_mask = NULL;
|
||||
field.in_value = NULL;
|
||||
field.in_check_value = NULL;
|
||||
field.in_check_mask = NULL;
|
||||
field.in_handler = NULL;
|
||||
field.in_handler_priv = NULL;
|
||||
|
||||
jtag_add_ir_scan(1, &field, TAP_RTI);
|
||||
|
||||
free(field.out_value);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_send_32(struct pld_device_s *pld_device, int num_words, u32 *words)
|
||||
{
|
||||
virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
|
||||
scan_field_t scan_field;
|
||||
u8 *values;
|
||||
int i;
|
||||
|
||||
values = malloc(num_words * 4);
|
||||
|
||||
scan_field.device = virtex2_info->chain_pos;
|
||||
scan_field.num_bits = num_words * 32;
|
||||
scan_field.out_value = values;
|
||||
scan_field.out_mask = NULL;
|
||||
scan_field.in_value = NULL;
|
||||
scan_field.in_check_value = NULL;
|
||||
scan_field.in_check_mask = NULL;
|
||||
scan_field.in_handler = NULL;
|
||||
scan_field.in_handler_priv = NULL;
|
||||
|
||||
for (i = 0; i < num_words; i++)
|
||||
buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
|
||||
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
|
||||
|
||||
jtag_add_dr_scan(1, &scan_field, TAP_PD);
|
||||
|
||||
free(values);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u32 *dest = priv;
|
||||
*dest = flip_u32(le_to_h_u32(in_buf), 32);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_receive_32(struct pld_device_s *pld_device, int num_words, u32 *words)
|
||||
{
|
||||
virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
|
||||
scan_field_t scan_field;
|
||||
|
||||
scan_field.device = virtex2_info->chain_pos;
|
||||
scan_field.num_bits = 32;
|
||||
scan_field.out_value = NULL;
|
||||
scan_field.out_mask = NULL;
|
||||
scan_field.in_value = NULL;
|
||||
scan_field.in_check_value = NULL;
|
||||
scan_field.in_check_mask = NULL;
|
||||
scan_field.in_handler = virtex2_jtag_buf_to_u32;
|
||||
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x4); /* CFG_OUT */
|
||||
|
||||
while (num_words--)
|
||||
{
|
||||
scan_field.in_handler_priv = words++;
|
||||
jtag_add_dr_scan(1, &scan_field, TAP_PD);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_read_stat(struct pld_device_s *pld_device, u32 *status)
|
||||
{
|
||||
u32 data[5];
|
||||
|
||||
jtag_add_statemove(TAP_TLR);
|
||||
|
||||
data[0] = 0xaa995566; /* synch word */
|
||||
data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */
|
||||
data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
|
||||
data[3] = 0x20000000; /* NOOP */
|
||||
data[4] = 0x20000000; /* NOOP */
|
||||
virtex2_send_32(pld_device, 5, data);
|
||||
|
||||
virtex2_receive_32(pld_device, 1, status);
|
||||
|
||||
jtag_execute_queue();
|
||||
|
||||
DEBUG("status: 0x%8.8x", *status);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_load(struct pld_device_s *pld_device, char *filename)
|
||||
{
|
||||
virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
|
||||
xilinx_bit_file_t bit_file;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
scan_field_t field;
|
||||
|
||||
field.device = virtex2_info->chain_pos;
|
||||
field.out_mask = NULL;
|
||||
field.in_value = NULL;
|
||||
field.in_check_value = NULL;
|
||||
field.in_check_mask = NULL;
|
||||
field.in_handler = NULL;
|
||||
field.in_handler_priv = NULL;
|
||||
|
||||
if ((retval = xilinx_read_bit_file(&bit_file, filename)) != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
jtag_add_end_state(TAP_RTI);
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0xb); /* JPROG_B */
|
||||
jtag_execute_queue();
|
||||
jtag_add_sleep(1000);
|
||||
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
|
||||
jtag_execute_queue();
|
||||
|
||||
for (i = 0; i < bit_file.length; i++)
|
||||
bit_file.data[i] = flip_u32(bit_file.data[i], 8);
|
||||
|
||||
field.num_bits = bit_file.length * 8;
|
||||
field.out_value = bit_file.data;
|
||||
|
||||
jtag_add_dr_scan(1, &field, TAP_PD);
|
||||
jtag_execute_queue();
|
||||
|
||||
jtag_add_statemove(TAP_TLR);
|
||||
|
||||
jtag_add_end_state(TAP_RTI);
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
|
||||
jtag_add_runtest(13, TAP_RTI);
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
|
||||
jtag_add_runtest(13, TAP_RTI);
|
||||
virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
|
||||
jtag_execute_queue();
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_handle_read_stat_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
pld_device_t *device;
|
||||
virtex2_pld_device_t *virtex2_info;
|
||||
u32 status;
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
command_print(cmd_ctx, "usage: virtex2 read_stat <num>");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
device = get_pld_device_by_num(strtoul(args[0], NULL, 0));
|
||||
if (!device)
|
||||
{
|
||||
command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
virtex2_info = device->driver_priv;
|
||||
|
||||
virtex2_read_stat(device, &status);
|
||||
|
||||
command_print(cmd_ctx, "virtex2 status register: 0x%8.8x", status);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
command_t *virtex2_cmd = register_command(cmd_ctx, NULL, "virtex2", NULL, COMMAND_ANY, "virtex2 specific commands");
|
||||
|
||||
register_command(cmd_ctx, virtex2_cmd, "read_stat", virtex2_handle_read_stat_command, COMMAND_EXEC,
|
||||
"read Virtex-II status register");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device)
|
||||
{
|
||||
virtex2_pld_device_t *virtex2_info;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
WARNING("incomplete pld device 'virtex2' configuration");
|
||||
return ERROR_PLD_DEVICE_INVALID;
|
||||
}
|
||||
|
||||
virtex2_info = malloc(sizeof(virtex2_pld_device_t));
|
||||
pld_device->driver_priv = virtex2_info;
|
||||
|
||||
virtex2_info->chain_pos = strtoul(args[1], NULL, 0);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,450 +1,450 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "replacements.h"
|
||||
|
||||
#include "server.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "telnet_server.h"
|
||||
#include "target.h"
|
||||
|
||||
#include <command.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
|
||||
service_t *services = NULL;
|
||||
|
||||
/* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
|
||||
static int shutdown_openocd = 0;
|
||||
int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
|
||||
int add_connection(service_t *service, command_context_t *cmd_ctx)
|
||||
{
|
||||
unsigned int address_size;
|
||||
connection_t *c, **p;
|
||||
int retval;
|
||||
|
||||
c = malloc(sizeof(connection_t));
|
||||
c->fd = -1;
|
||||
memset(&c->sin, 0, sizeof(c->sin));
|
||||
c->cmd_ctx = copy_command_context(cmd_ctx);
|
||||
c->service = service;
|
||||
c->input_pending = 0;
|
||||
c->priv = NULL;
|
||||
c->next = NULL;
|
||||
|
||||
address_size = sizeof(c->sin);
|
||||
c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
|
||||
if ((retval = service->new_connection(c)) == ERROR_OK)
|
||||
{
|
||||
INFO("accepted '%s' connection from %i", service->name, c->sin.sin_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
close_socket(c->fd);
|
||||
INFO("attempted '%s' connection rejected", service->name);
|
||||
free(c);
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
for (p = &service->connections; *p; p = &(*p)->next);
|
||||
*p = c;
|
||||
|
||||
service->max_connections--;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int remove_connection(service_t *service, connection_t *connection)
|
||||
{
|
||||
connection_t **p = &service->connections;
|
||||
connection_t *c;
|
||||
|
||||
/* find connection */
|
||||
while(c = *p)
|
||||
{
|
||||
if (c->fd == connection->fd)
|
||||
{
|
||||
service->connection_closed(c);
|
||||
close_socket(c->fd);
|
||||
command_done(c->cmd_ctx);
|
||||
|
||||
/* delete connection */
|
||||
*p = c->next;
|
||||
free(c);
|
||||
|
||||
service->max_connections++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* redirect p to next list pointer */
|
||||
p = &(*p)->next;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int add_service(char *name, enum connection_type type, unsigned short port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv)
|
||||
{
|
||||
service_t *c, **p;
|
||||
int so_reuseaddr_option = 1;
|
||||
|
||||
c = malloc(sizeof(service_t));
|
||||
|
||||
c->name = strdup(name);
|
||||
c->type = type;
|
||||
c->port = port;
|
||||
c->max_connections = max_connections;
|
||||
c->fd = -1;
|
||||
c->connections = NULL;
|
||||
c->new_connection = new_connection_handler;
|
||||
c->input = input_handler;
|
||||
c->connection_closed = connection_closed_handler;
|
||||
c->priv = priv;
|
||||
c->next = NULL;
|
||||
|
||||
if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
ERROR("error creating socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
|
||||
|
||||
socket_nonblock(c->fd);
|
||||
|
||||
memset(&c->sin, 0, sizeof(c->sin));
|
||||
c->sin.sin_family = AF_INET;
|
||||
c->sin.sin_addr.s_addr = INADDR_ANY;
|
||||
c->sin.sin_port = htons(port);
|
||||
|
||||
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)
|
||||
{
|
||||
ERROR("couldn't bind to socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (listen(c->fd, 1) == -1)
|
||||
{
|
||||
ERROR("couldn't listen on socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
for (p = &services; *p; p = &(*p)->next);
|
||||
*p = c;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int remove_service(unsigned short port)
|
||||
{
|
||||
service_t **p = &services;
|
||||
service_t *c;
|
||||
|
||||
/* find service */
|
||||
while(c = *p)
|
||||
{
|
||||
if (c->port == port)
|
||||
{
|
||||
if (c->name)
|
||||
free(c->name);
|
||||
|
||||
if (c->priv)
|
||||
free(c->priv);
|
||||
|
||||
/* delete service */
|
||||
*p = c->next;
|
||||
free(c);
|
||||
}
|
||||
|
||||
/* redirect p to next list pointer */
|
||||
p = &(*p)->next;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int remove_services()
|
||||
{
|
||||
service_t *c = services;
|
||||
|
||||
/* loop service */
|
||||
while(c)
|
||||
{
|
||||
service_t *next = c->next;
|
||||
|
||||
if (c->name)
|
||||
free(c->name);
|
||||
|
||||
if (c->priv)
|
||||
free(c->priv);
|
||||
|
||||
/* delete service */
|
||||
free(c);
|
||||
|
||||
/* remember the last service for unlinking */
|
||||
c = next;
|
||||
}
|
||||
|
||||
services = NULL;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int server_loop(command_context_t *command_context)
|
||||
{
|
||||
service_t *service;
|
||||
|
||||
/* used in select() */
|
||||
fd_set read_fds;
|
||||
struct timeval tv;
|
||||
int fd_max;
|
||||
|
||||
/* used in accept() */
|
||||
int retval;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||
ERROR("couldn't set SIGPIPE to SIG_IGN");
|
||||
#endif
|
||||
|
||||
/* do regular tasks after at most 10ms */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
|
||||
while(!shutdown_openocd)
|
||||
{
|
||||
/* monitor sockets for acitvity */
|
||||
fd_max = 0;
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
/* add service and connection fds to read_fds */
|
||||
for (service = services; service; service = service->next)
|
||||
{
|
||||
if (service->fd != -1)
|
||||
{
|
||||
/* listen for new connections */
|
||||
FD_SET(service->fd, &read_fds);
|
||||
|
||||
if (service->fd > fd_max)
|
||||
fd_max = service->fd;
|
||||
}
|
||||
|
||||
if (service->connections)
|
||||
{
|
||||
connection_t *c;
|
||||
|
||||
for (c = service->connections; c; c = c->next)
|
||||
{
|
||||
/* check for activity on the connection */
|
||||
FD_SET(c->fd, &read_fds);
|
||||
if (c->fd > fd_max)
|
||||
fd_max = c->fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/* add STDIN to read_fds */
|
||||
FD_SET(fileno(stdin), &read_fds);
|
||||
#endif
|
||||
|
||||
retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
|
||||
|
||||
if (retval == -1)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
errno = WSAGetLastError();
|
||||
|
||||
if (errno == WSAEINTR)
|
||||
FD_ZERO(&read_fds);
|
||||
else
|
||||
{
|
||||
ERROR("error during select: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
|
||||
if (errno == EINTR)
|
||||
{
|
||||
FD_ZERO(&read_fds);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("error during select: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
target_call_timer_callbacks();
|
||||
|
||||
if (retval == 0)
|
||||
{
|
||||
/* do regular tasks after at most 100ms */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */
|
||||
}
|
||||
|
||||
for (service = services; service; service = service->next)
|
||||
{
|
||||
/* handle new connections on listeners */
|
||||
if ((service->fd != -1)
|
||||
&& (FD_ISSET(service->fd, &read_fds)))
|
||||
{
|
||||
if (service->max_connections > 0)
|
||||
{
|
||||
add_connection(service, command_context);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
unsigned int address_size = sizeof(sin);
|
||||
int tmp_fd;
|
||||
tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
close_socket(tmp_fd);
|
||||
INFO("rejected '%s' connection, no more connections allowed", service->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* handle activity on connections */
|
||||
if (service->connections)
|
||||
{
|
||||
connection_t *c;
|
||||
|
||||
for (c = service->connections; c;)
|
||||
{
|
||||
if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending)
|
||||
{
|
||||
if (service->input(c) != ERROR_OK)
|
||||
{
|
||||
connection_t *next = c->next;
|
||||
remove_connection(service, c);
|
||||
INFO("dropped '%s' connection", service->name);
|
||||
c = next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
if (FD_ISSET(fileno(stdin), &read_fds))
|
||||
{
|
||||
if (getc(stdin) == 'x')
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void sig_handler(int sig) {
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int server_init()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
|
||||
wVersionRequested = MAKEWORD( 2, 2 );
|
||||
|
||||
if (WSAStartup(wVersionRequested, &wsaData) != 0)
|
||||
{
|
||||
ERROR("Failed to Open Winsock");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
SetConsoleCtrlHandler( ControlHandler, TRUE );
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
signal(SIGBREAK, sig_handler);
|
||||
signal(SIGABRT, sig_handler);
|
||||
#endif
|
||||
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int server_quit()
|
||||
{
|
||||
remove_services();
|
||||
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
SetConsoleCtrlHandler( ControlHandler, FALSE );
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int server_register_commands(command_context_t *context)
|
||||
{
|
||||
register_command(context, NULL, "shutdown", handle_shutdown_command,
|
||||
COMMAND_ANY, "shut the server down");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* tell the server we want to shut down */
|
||||
int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
|
||||
return ERROR_COMMAND_CLOSE_CONNECTION;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "replacements.h"
|
||||
|
||||
#include "server.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "telnet_server.h"
|
||||
#include "target.h"
|
||||
|
||||
#include <command.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
|
||||
service_t *services = NULL;
|
||||
|
||||
/* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
|
||||
static int shutdown_openocd = 0;
|
||||
int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
|
||||
int add_connection(service_t *service, command_context_t *cmd_ctx)
|
||||
{
|
||||
unsigned int address_size;
|
||||
connection_t *c, **p;
|
||||
int retval;
|
||||
|
||||
c = malloc(sizeof(connection_t));
|
||||
c->fd = -1;
|
||||
memset(&c->sin, 0, sizeof(c->sin));
|
||||
c->cmd_ctx = copy_command_context(cmd_ctx);
|
||||
c->service = service;
|
||||
c->input_pending = 0;
|
||||
c->priv = NULL;
|
||||
c->next = NULL;
|
||||
|
||||
address_size = sizeof(c->sin);
|
||||
c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
|
||||
if ((retval = service->new_connection(c)) == ERROR_OK)
|
||||
{
|
||||
INFO("accepted '%s' connection from %i", service->name, c->sin.sin_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
close_socket(c->fd);
|
||||
INFO("attempted '%s' connection rejected", service->name);
|
||||
free(c);
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
for (p = &service->connections; *p; p = &(*p)->next);
|
||||
*p = c;
|
||||
|
||||
service->max_connections--;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int remove_connection(service_t *service, connection_t *connection)
|
||||
{
|
||||
connection_t **p = &service->connections;
|
||||
connection_t *c;
|
||||
|
||||
/* find connection */
|
||||
while(c = *p)
|
||||
{
|
||||
if (c->fd == connection->fd)
|
||||
{
|
||||
service->connection_closed(c);
|
||||
close_socket(c->fd);
|
||||
command_done(c->cmd_ctx);
|
||||
|
||||
/* delete connection */
|
||||
*p = c->next;
|
||||
free(c);
|
||||
|
||||
service->max_connections++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* redirect p to next list pointer */
|
||||
p = &(*p)->next;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int add_service(char *name, enum connection_type type, unsigned short port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv)
|
||||
{
|
||||
service_t *c, **p;
|
||||
int so_reuseaddr_option = 1;
|
||||
|
||||
c = malloc(sizeof(service_t));
|
||||
|
||||
c->name = strdup(name);
|
||||
c->type = type;
|
||||
c->port = port;
|
||||
c->max_connections = max_connections;
|
||||
c->fd = -1;
|
||||
c->connections = NULL;
|
||||
c->new_connection = new_connection_handler;
|
||||
c->input = input_handler;
|
||||
c->connection_closed = connection_closed_handler;
|
||||
c->priv = priv;
|
||||
c->next = NULL;
|
||||
|
||||
if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
ERROR("error creating socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
|
||||
|
||||
socket_nonblock(c->fd);
|
||||
|
||||
memset(&c->sin, 0, sizeof(c->sin));
|
||||
c->sin.sin_family = AF_INET;
|
||||
c->sin.sin_addr.s_addr = INADDR_ANY;
|
||||
c->sin.sin_port = htons(port);
|
||||
|
||||
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)
|
||||
{
|
||||
ERROR("couldn't bind to socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (listen(c->fd, 1) == -1)
|
||||
{
|
||||
ERROR("couldn't listen on socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
for (p = &services; *p; p = &(*p)->next);
|
||||
*p = c;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int remove_service(unsigned short port)
|
||||
{
|
||||
service_t **p = &services;
|
||||
service_t *c;
|
||||
|
||||
/* find service */
|
||||
while(c = *p)
|
||||
{
|
||||
if (c->port == port)
|
||||
{
|
||||
if (c->name)
|
||||
free(c->name);
|
||||
|
||||
if (c->priv)
|
||||
free(c->priv);
|
||||
|
||||
/* delete service */
|
||||
*p = c->next;
|
||||
free(c);
|
||||
}
|
||||
|
||||
/* redirect p to next list pointer */
|
||||
p = &(*p)->next;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int remove_services()
|
||||
{
|
||||
service_t *c = services;
|
||||
|
||||
/* loop service */
|
||||
while(c)
|
||||
{
|
||||
service_t *next = c->next;
|
||||
|
||||
if (c->name)
|
||||
free(c->name);
|
||||
|
||||
if (c->priv)
|
||||
free(c->priv);
|
||||
|
||||
/* delete service */
|
||||
free(c);
|
||||
|
||||
/* remember the last service for unlinking */
|
||||
c = next;
|
||||
}
|
||||
|
||||
services = NULL;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int server_loop(command_context_t *command_context)
|
||||
{
|
||||
service_t *service;
|
||||
|
||||
/* used in select() */
|
||||
fd_set read_fds;
|
||||
struct timeval tv;
|
||||
int fd_max;
|
||||
|
||||
/* used in accept() */
|
||||
int retval;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||
ERROR("couldn't set SIGPIPE to SIG_IGN");
|
||||
#endif
|
||||
|
||||
/* do regular tasks after at most 10ms */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
|
||||
while(!shutdown_openocd)
|
||||
{
|
||||
/* monitor sockets for acitvity */
|
||||
fd_max = 0;
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
/* add service and connection fds to read_fds */
|
||||
for (service = services; service; service = service->next)
|
||||
{
|
||||
if (service->fd != -1)
|
||||
{
|
||||
/* listen for new connections */
|
||||
FD_SET(service->fd, &read_fds);
|
||||
|
||||
if (service->fd > fd_max)
|
||||
fd_max = service->fd;
|
||||
}
|
||||
|
||||
if (service->connections)
|
||||
{
|
||||
connection_t *c;
|
||||
|
||||
for (c = service->connections; c; c = c->next)
|
||||
{
|
||||
/* check for activity on the connection */
|
||||
FD_SET(c->fd, &read_fds);
|
||||
if (c->fd > fd_max)
|
||||
fd_max = c->fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/* add STDIN to read_fds */
|
||||
FD_SET(fileno(stdin), &read_fds);
|
||||
#endif
|
||||
|
||||
retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
|
||||
|
||||
if (retval == -1)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
errno = WSAGetLastError();
|
||||
|
||||
if (errno == WSAEINTR)
|
||||
FD_ZERO(&read_fds);
|
||||
else
|
||||
{
|
||||
ERROR("error during select: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
|
||||
if (errno == EINTR)
|
||||
{
|
||||
FD_ZERO(&read_fds);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("error during select: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
target_call_timer_callbacks();
|
||||
|
||||
if (retval == 0)
|
||||
{
|
||||
/* do regular tasks after at most 100ms */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */
|
||||
}
|
||||
|
||||
for (service = services; service; service = service->next)
|
||||
{
|
||||
/* handle new connections on listeners */
|
||||
if ((service->fd != -1)
|
||||
&& (FD_ISSET(service->fd, &read_fds)))
|
||||
{
|
||||
if (service->max_connections > 0)
|
||||
{
|
||||
add_connection(service, command_context);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
unsigned int address_size = sizeof(sin);
|
||||
int tmp_fd;
|
||||
tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
close_socket(tmp_fd);
|
||||
INFO("rejected '%s' connection, no more connections allowed", service->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* handle activity on connections */
|
||||
if (service->connections)
|
||||
{
|
||||
connection_t *c;
|
||||
|
||||
for (c = service->connections; c;)
|
||||
{
|
||||
if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending)
|
||||
{
|
||||
if (service->input(c) != ERROR_OK)
|
||||
{
|
||||
connection_t *next = c->next;
|
||||
remove_connection(service, c);
|
||||
INFO("dropped '%s' connection", service->name);
|
||||
c = next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
if (FD_ISSET(fileno(stdin), &read_fds))
|
||||
{
|
||||
if (getc(stdin) == 'x')
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void sig_handler(int sig) {
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int server_init()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
|
||||
wVersionRequested = MAKEWORD( 2, 2 );
|
||||
|
||||
if (WSAStartup(wVersionRequested, &wsaData) != 0)
|
||||
{
|
||||
ERROR("Failed to Open Winsock");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
SetConsoleCtrlHandler( ControlHandler, TRUE );
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
signal(SIGBREAK, sig_handler);
|
||||
signal(SIGABRT, sig_handler);
|
||||
#endif
|
||||
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int server_quit()
|
||||
{
|
||||
remove_services();
|
||||
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
SetConsoleCtrlHandler( ControlHandler, FALSE );
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int server_register_commands(command_context_t *context)
|
||||
{
|
||||
register_command(context, NULL, "shutdown", handle_shutdown_command,
|
||||
COMMAND_ANY, "shut the server down");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* tell the server we want to shut down */
|
||||
int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
|
||||
return ERROR_COMMAND_CLOSE_CONNECTION;
|
||||
}
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
2716
src/target/arm11.c
2716
src/target/arm11.c
File diff suppressed because it is too large
Load Diff
|
@ -1,250 +1,250 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2008 digenius technology GmbH. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef ARM11_H
|
||||
#define ARM11_H
|
||||
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "embeddedice.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
|
||||
#define bool int
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define asizeof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define NEW(type, variable, items) \
|
||||
type * variable = malloc(sizeof(type) * items)
|
||||
|
||||
|
||||
#define ARM11_REGCACHE_MODEREGS 0
|
||||
#define ARM11_REGCACHE_FREGS 0
|
||||
|
||||
#define ARM11_REGCACHE_COUNT (20 + \
|
||||
23 * ARM11_REGCACHE_MODEREGS + \
|
||||
9 * ARM11_REGCACHE_FREGS)
|
||||
|
||||
|
||||
typedef struct arm11_register_history_s
|
||||
{
|
||||
u32 value;
|
||||
u8 valid;
|
||||
}arm11_register_history_t;
|
||||
|
||||
|
||||
|
||||
typedef struct arm11_common_s
|
||||
{
|
||||
target_t * target;
|
||||
|
||||
arm_jtag_t jtag_info;
|
||||
|
||||
/** \name Processor type detection */
|
||||
/*@{*/
|
||||
|
||||
u32 device_id; /**< IDCODE readout */
|
||||
u32 didr; /**< DIDR readout (debug capabilities) */
|
||||
u8 implementor; /**< DIDR Implementor readout */
|
||||
|
||||
size_t brp; /**< Number of Breakpoint Register Pairs */
|
||||
size_t wrp; /**< Number of Watchpoint Register Pairs */
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
u32 last_dscr; /**< Last retrieved DSCR value;
|
||||
* Can be used to detect changes */
|
||||
|
||||
u8 trst_active;
|
||||
u8 halt_requested;
|
||||
|
||||
/** \name Shadow registers to save processor state */
|
||||
/*@{*/
|
||||
|
||||
reg_t * reg_list; /**< target register list */
|
||||
u32 reg_values[ARM11_REGCACHE_COUNT]; /**< data for registers */
|
||||
|
||||
/*@}*/
|
||||
|
||||
arm11_register_history_t
|
||||
reg_history[ARM11_REGCACHE_COUNT]; /**< register state before last resume */
|
||||
|
||||
|
||||
} arm11_common_t;
|
||||
|
||||
|
||||
/**
|
||||
* ARM11 DBGTAP instructions
|
||||
*
|
||||
* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html
|
||||
*/
|
||||
enum arm11_instructions
|
||||
{
|
||||
ARM11_EXTEST = 0x00,
|
||||
ARM11_SCAN_N = 0x02,
|
||||
ARM11_RESTART = 0x04,
|
||||
ARM11_HALT = 0x08,
|
||||
ARM11_INTEST = 0x0C,
|
||||
ARM11_ITRSEL = 0x1D,
|
||||
ARM11_IDCODE = 0x1E,
|
||||
ARM11_BYPASS = 0x1F,
|
||||
};
|
||||
|
||||
enum arm11_dscr
|
||||
{
|
||||
ARM11_DSCR_CORE_HALTED = 1 << 0,
|
||||
ARM11_DSCR_CORE_RESTARTED = 1 << 1,
|
||||
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK = 0x0F << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT = 0x00 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT = 0x01 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT = 0x02 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION = 0x03 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ = 0x04 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH = 0x05 << 2,
|
||||
|
||||
ARM11_DSCR_STICKY_PRECISE_DATA_ABORT = 1 << 6,
|
||||
ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT = 1 << 7,
|
||||
ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE = 1 << 13,
|
||||
ARM11_DSCR_MODE_SELECT = 1 << 14,
|
||||
ARM11_DSCR_WDTR_FULL = 1 << 29,
|
||||
ARM11_DSCR_RDTR_FULL = 1 << 30,
|
||||
};
|
||||
|
||||
enum arm11_cpsr
|
||||
{
|
||||
ARM11_CPSR_T = 1 << 5,
|
||||
ARM11_CPSR_J = 1 << 24,
|
||||
};
|
||||
|
||||
enum arm11_sc7
|
||||
{
|
||||
ARM11_SC7_NULL = 0,
|
||||
ARM11_SC7_VCR = 7,
|
||||
ARM11_SC7_PC = 8,
|
||||
ARM11_SC7_BVR0 = 64,
|
||||
ARM11_SC7_BCR0 = 80,
|
||||
ARM11_SC7_WVR0 = 96,
|
||||
ARM11_SC7_WCR0 = 112,
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct arm11_reg_state_s
|
||||
{
|
||||
u32 def_index;
|
||||
target_t * target;
|
||||
} arm11_reg_state_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/* poll current target status */
|
||||
int arm11_poll(struct target_s *target);
|
||||
/* architecture specific status reply */
|
||||
int arm11_arch_state(struct target_s *target);
|
||||
|
||||
/* target request support */
|
||||
int arm11_target_request_data(struct target_s *target, u32 size, u8 *buffer);
|
||||
|
||||
/* target execution control */
|
||||
int arm11_halt(struct target_s *target);
|
||||
int arm11_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
|
||||
int arm11_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
|
||||
|
||||
/* target reset control */
|
||||
int arm11_assert_reset(struct target_s *target);
|
||||
int arm11_deassert_reset(struct target_s *target);
|
||||
int arm11_soft_reset_halt(struct target_s *target);
|
||||
int arm11_prepare_reset_halt(struct target_s *target);
|
||||
|
||||
/* target register access for gdb */
|
||||
int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);
|
||||
|
||||
/* target memory access
|
||||
* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
|
||||
* count: number of items of <size>
|
||||
*/
|
||||
int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
|
||||
int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
|
||||
|
||||
/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
|
||||
int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer);
|
||||
|
||||
int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
|
||||
|
||||
/* target break-/watchpoint control
|
||||
* rw: 0 = write, 1 = read, 2 = access
|
||||
*/
|
||||
int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
|
||||
int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
|
||||
int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
|
||||
int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
|
||||
|
||||
/* target algorithm support */
|
||||
int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info);
|
||||
|
||||
int arm11_register_commands(struct command_context_s *cmd_ctx);
|
||||
int arm11_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
|
||||
int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
|
||||
int arm11_quit(void);
|
||||
|
||||
|
||||
/* helpers */
|
||||
void arm11_build_reg_cache(target_t *target);
|
||||
|
||||
|
||||
/* internals */
|
||||
|
||||
void arm11_setup_field (arm11_common_t * arm11, int num_bits, void * in_data, void * out_data, scan_field_t * field);
|
||||
void arm11_add_IR (arm11_common_t * arm11, u8 instr, enum tap_state state);
|
||||
void arm11_add_debug_SCAN_N (arm11_common_t * arm11, u8 chain, enum tap_state state);
|
||||
void arm11_add_debug_INST (arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_state state);
|
||||
u32 arm11_read_DSCR (arm11_common_t * arm11);
|
||||
void arm11_write_DSCR (arm11_common_t * arm11, u32 dscr);
|
||||
|
||||
enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr);
|
||||
|
||||
void arm11_run_instr_data_prepare (arm11_common_t * arm11);
|
||||
void arm11_run_instr_data_finish (arm11_common_t * arm11);
|
||||
void arm11_run_instr_no_data (arm11_common_t * arm11, u32 * opcode, size_t count);
|
||||
void arm11_run_instr_no_data1 (arm11_common_t * arm11, u32 opcode);
|
||||
void arm11_run_instr_data_to_core (arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);
|
||||
void arm11_run_instr_data_to_core1 (arm11_common_t * arm11, u32 opcode, u32 data);
|
||||
void arm11_run_instr_data_from_core (arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);
|
||||
void arm11_run_instr_data_from_core_via_r0 (arm11_common_t * arm11, u32 opcode, u32 * data);
|
||||
void arm11_run_instr_data_to_core_via_r0 (arm11_common_t * arm11, u32 opcode, u32 data);
|
||||
|
||||
|
||||
typedef struct arm11_sc7_action_s
|
||||
{
|
||||
bool write;
|
||||
u8 address;
|
||||
u32 value;
|
||||
} arm11_sc7_action_t;
|
||||
|
||||
void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count);
|
||||
void arm11_sc7_clear_bw(arm11_common_t * arm11);
|
||||
|
||||
|
||||
|
||||
#endif /* ARM11_H */
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 digenius technology GmbH. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef ARM11_H
|
||||
#define ARM11_H
|
||||
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "embeddedice.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
|
||||
#define bool int
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define asizeof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define NEW(type, variable, items) \
|
||||
type * variable = malloc(sizeof(type) * items)
|
||||
|
||||
|
||||
#define ARM11_REGCACHE_MODEREGS 0
|
||||
#define ARM11_REGCACHE_FREGS 0
|
||||
|
||||
#define ARM11_REGCACHE_COUNT (20 + \
|
||||
23 * ARM11_REGCACHE_MODEREGS + \
|
||||
9 * ARM11_REGCACHE_FREGS)
|
||||
|
||||
|
||||
typedef struct arm11_register_history_s
|
||||
{
|
||||
u32 value;
|
||||
u8 valid;
|
||||
}arm11_register_history_t;
|
||||
|
||||
|
||||
|
||||
typedef struct arm11_common_s
|
||||
{
|
||||
target_t * target;
|
||||
|
||||
arm_jtag_t jtag_info;
|
||||
|
||||
/** \name Processor type detection */
|
||||
/*@{*/
|
||||
|
||||
u32 device_id; /**< IDCODE readout */
|
||||
u32 didr; /**< DIDR readout (debug capabilities) */
|
||||
u8 implementor; /**< DIDR Implementor readout */
|
||||
|
||||
size_t brp; /**< Number of Breakpoint Register Pairs */
|
||||
size_t wrp; /**< Number of Watchpoint Register Pairs */
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
u32 last_dscr; /**< Last retrieved DSCR value;
|
||||
* Can be used to detect changes */
|
||||
|
||||
u8 trst_active;
|
||||
u8 halt_requested;
|
||||
|
||||
/** \name Shadow registers to save processor state */
|
||||
/*@{*/
|
||||
|
||||
reg_t * reg_list; /**< target register list */
|
||||
u32 reg_values[ARM11_REGCACHE_COUNT]; /**< data for registers */
|
||||
|
||||
/*@}*/
|
||||
|
||||
arm11_register_history_t
|
||||
reg_history[ARM11_REGCACHE_COUNT]; /**< register state before last resume */
|
||||
|
||||
|
||||
} arm11_common_t;
|
||||
|
||||
|
||||
/**
|
||||
* ARM11 DBGTAP instructions
|
||||
*
|
||||
* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html
|
||||
*/
|
||||
enum arm11_instructions
|
||||
{
|
||||
ARM11_EXTEST = 0x00,
|
||||
ARM11_SCAN_N = 0x02,
|
||||
ARM11_RESTART = 0x04,
|
||||
ARM11_HALT = 0x08,
|
||||
ARM11_INTEST = 0x0C,
|
||||
ARM11_ITRSEL = 0x1D,
|
||||
ARM11_IDCODE = 0x1E,
|
||||
ARM11_BYPASS = 0x1F,
|
||||
};
|
||||
|
||||
enum arm11_dscr
|
||||
{
|
||||
ARM11_DSCR_CORE_HALTED = 1 << 0,
|
||||
ARM11_DSCR_CORE_RESTARTED = 1 << 1,
|
||||
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK = 0x0F << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT = 0x00 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT = 0x01 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT = 0x02 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION = 0x03 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ = 0x04 << 2,
|
||||
ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH = 0x05 << 2,
|
||||
|
||||
ARM11_DSCR_STICKY_PRECISE_DATA_ABORT = 1 << 6,
|
||||
ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT = 1 << 7,
|
||||
ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE = 1 << 13,
|
||||
ARM11_DSCR_MODE_SELECT = 1 << 14,
|
||||
ARM11_DSCR_WDTR_FULL = 1 << 29,
|
||||
ARM11_DSCR_RDTR_FULL = 1 << 30,
|
||||
};
|
||||
|
||||
enum arm11_cpsr
|
||||
{
|
||||
ARM11_CPSR_T = 1 << 5,
|
||||
ARM11_CPSR_J = 1 << 24,
|
||||
};
|
||||
|
||||
enum arm11_sc7
|
||||
{
|
||||
ARM11_SC7_NULL = 0,
|
||||
ARM11_SC7_VCR = 7,
|
||||
ARM11_SC7_PC = 8,
|
||||
ARM11_SC7_BVR0 = 64,
|
||||
ARM11_SC7_BCR0 = 80,
|
||||
ARM11_SC7_WVR0 = 96,
|
||||
ARM11_SC7_WCR0 = 112,
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct arm11_reg_state_s
|
||||
{
|
||||
u32 def_index;
|
||||
target_t * target;
|
||||
} arm11_reg_state_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/* poll current target status */
|
||||
int arm11_poll(struct target_s *target);
|
||||
/* architecture specific status reply */
|
||||
int arm11_arch_state(struct target_s *target);
|
||||
|
||||
/* target request support */
|
||||
int arm11_target_request_data(struct target_s *target, u32 size, u8 *buffer);
|
||||
|
||||
/* target execution control */
|
||||
int arm11_halt(struct target_s *target);
|
||||
int arm11_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
|
||||
int arm11_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
|
||||
|
||||
/* target reset control */
|
||||
int arm11_assert_reset(struct target_s *target);
|
||||
int arm11_deassert_reset(struct target_s *target);
|
||||
int arm11_soft_reset_halt(struct target_s *target);
|
||||
int arm11_prepare_reset_halt(struct target_s *target);
|
||||
|
||||
/* target register access for gdb */
|
||||
int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);
|
||||
|
||||
/* target memory access
|
||||
* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
|
||||
* count: number of items of <size>
|
||||
*/
|
||||
int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
|
||||
int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
|
||||
|
||||
/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
|
||||
int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer);
|
||||
|
||||
int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
|
||||
|
||||
/* target break-/watchpoint control
|
||||
* rw: 0 = write, 1 = read, 2 = access
|
||||
*/
|
||||
int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
|
||||
int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
|
||||
int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
|
||||
int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
|
||||
|
||||
/* target algorithm support */
|
||||
int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info);
|
||||
|
||||
int arm11_register_commands(struct command_context_s *cmd_ctx);
|
||||
int arm11_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
|
||||
int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
|
||||
int arm11_quit(void);
|
||||
|
||||
|
||||
/* helpers */
|
||||
void arm11_build_reg_cache(target_t *target);
|
||||
|
||||
|
||||
/* internals */
|
||||
|
||||
void arm11_setup_field (arm11_common_t * arm11, int num_bits, void * in_data, void * out_data, scan_field_t * field);
|
||||
void arm11_add_IR (arm11_common_t * arm11, u8 instr, enum tap_state state);
|
||||
void arm11_add_debug_SCAN_N (arm11_common_t * arm11, u8 chain, enum tap_state state);
|
||||
void arm11_add_debug_INST (arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_state state);
|
||||
u32 arm11_read_DSCR (arm11_common_t * arm11);
|
||||
void arm11_write_DSCR (arm11_common_t * arm11, u32 dscr);
|
||||
|
||||
enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr);
|
||||
|
||||
void arm11_run_instr_data_prepare (arm11_common_t * arm11);
|
||||
void arm11_run_instr_data_finish (arm11_common_t * arm11);
|
||||
void arm11_run_instr_no_data (arm11_common_t * arm11, u32 * opcode, size_t count);
|
||||
void arm11_run_instr_no_data1 (arm11_common_t * arm11, u32 opcode);
|
||||
void arm11_run_instr_data_to_core (arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);
|
||||
void arm11_run_instr_data_to_core1 (arm11_common_t * arm11, u32 opcode, u32 data);
|
||||
void arm11_run_instr_data_from_core (arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);
|
||||
void arm11_run_instr_data_from_core_via_r0 (arm11_common_t * arm11, u32 opcode, u32 * data);
|
||||
void arm11_run_instr_data_to_core_via_r0 (arm11_common_t * arm11, u32 opcode, u32 data);
|
||||
|
||||
|
||||
typedef struct arm11_sc7_action_s
|
||||
{
|
||||
bool write;
|
||||
u8 address;
|
||||
u32 value;
|
||||
} arm11_sc7_action_t;
|
||||
|
||||
void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count);
|
||||
void arm11_sc7_clear_bw(arm11_common_t * arm11);
|
||||
|
||||
|
||||
|
||||
#endif /* ARM11_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
1252
src/target/arm720t.c
1252
src/target/arm720t.c
File diff suppressed because it is too large
Load Diff
|
@ -676,7 +676,7 @@ int arm7_9_handle_target_request(void *priv)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm7_9_poll(target_t *target)
|
||||
int arm7_9_poll(target_t *target)
|
||||
{
|
||||
int retval;
|
||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||
|
@ -692,15 +692,15 @@ int arm7_9_poll(target_t *target)
|
|||
embeddedice_read_reg(dbg_stat);
|
||||
if ((retval = jtag_execute_queue()) != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
|
||||
{
|
||||
DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));
|
||||
if (target->state == TARGET_UNKNOWN)
|
||||
if (target->state == TARGET_UNKNOWN)
|
||||
{
|
||||
WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
|
||||
WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
|
||||
}
|
||||
if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
|
||||
{
|
||||
|
@ -718,18 +718,18 @@ int arm7_9_poll(target_t *target)
|
|||
|
||||
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
|
||||
}
|
||||
if (target->state != TARGET_HALTED)
|
||||
{
|
||||
WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);
|
||||
if (target->state != TARGET_HALTED)
|
||||
{
|
||||
WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target->state != TARGET_DEBUG_RUNNING)
|
||||
target->state = TARGET_RUNNING;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm7_9_assert_reset(target_t *target)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
2970
src/target/arm920t.c
2970
src/target/arm920t.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,364 +1,364 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "arm966e.h"
|
||||
|
||||
#include "arm7_9_common.h"
|
||||
#include "register.h"
|
||||
#include "target.h"
|
||||
#include "armv4_5.h"
|
||||
#include "embeddedice.h"
|
||||
#include "log.h"
|
||||
#include "jtag.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if 0
|
||||
#define _DEBUG_INSTRUCTION_EXECUTION_
|
||||
#endif
|
||||
|
||||
/* cli handling */
|
||||
int arm966e_register_commands(struct command_context_s *cmd_ctx);
|
||||
|
||||
/* forward declarations */
|
||||
int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
|
||||
int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
|
||||
int arm966e_quit(void);
|
||||
|
||||
target_type_t arm966e_target =
|
||||
{
|
||||
.name = "arm966e",
|
||||
|
||||
.poll = arm7_9_poll,
|
||||
.arch_state = armv4_5_arch_state,
|
||||
|
||||
.target_request_data = arm7_9_target_request_data,
|
||||
|
||||
.halt = arm7_9_halt,
|
||||
.resume = arm7_9_resume,
|
||||
.step = arm7_9_step,
|
||||
|
||||
.assert_reset = arm7_9_assert_reset,
|
||||
.deassert_reset = arm7_9_deassert_reset,
|
||||
.soft_reset_halt = arm7_9_soft_reset_halt,
|
||||
.prepare_reset_halt = arm7_9_prepare_reset_halt,
|
||||
|
||||
.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
|
||||
|
||||
.read_memory = arm7_9_read_memory,
|
||||
.write_memory = arm7_9_write_memory,
|
||||
.bulk_write_memory = arm7_9_bulk_write_memory,
|
||||
.checksum_memory = arm7_9_checksum_memory,
|
||||
|
||||
.run_algorithm = armv4_5_run_algorithm,
|
||||
|
||||
.add_breakpoint = arm7_9_add_breakpoint,
|
||||
.remove_breakpoint = arm7_9_remove_breakpoint,
|
||||
.add_watchpoint = arm7_9_add_watchpoint,
|
||||
.remove_watchpoint = arm7_9_remove_watchpoint,
|
||||
|
||||
.register_commands = arm966e_register_commands,
|
||||
.target_command = arm966e_target_command,
|
||||
.init_target = arm966e_init_target,
|
||||
.quit = arm966e_quit,
|
||||
};
|
||||
|
||||
int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
|
||||
{
|
||||
arm9tdmi_init_target(cmd_ctx, target);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_quit(void)
|
||||
{
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, int chain_pos, char *variant)
|
||||
{
|
||||
arm9tdmi_common_t *arm9tdmi = &arm966e->arm9tdmi_common;
|
||||
arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
|
||||
|
||||
arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
|
||||
|
||||
arm9tdmi->arch_info = arm966e;
|
||||
arm966e->common_magic = ARM966E_COMMON_MAGIC;
|
||||
|
||||
/* The ARM966E-S implements the ARMv5TE architecture which
|
||||
* has the BKPT instruction, so we don't have to use a watchpoint comparator
|
||||
*/
|
||||
arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
|
||||
arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
|
||||
|
||||
arm7_9->sw_bkpts_use_wp = 0;
|
||||
arm7_9->sw_bkpts_enabled = 1;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
|
||||
{
|
||||
int chain_pos;
|
||||
char *variant = NULL;
|
||||
arm966e_common_t *arm966e = malloc(sizeof(arm966e_common_t));
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
ERROR("'target arm966e' requires at least one additional argument");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
chain_pos = strtoul(args[3], NULL, 0);
|
||||
|
||||
if (argc >= 5)
|
||||
variant = args[4];
|
||||
|
||||
DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
|
||||
|
||||
arm966e_init_arch_info(target, arm966e, chain_pos, variant);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm966e_common_t **arm966e_p)
|
||||
{
|
||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||
arm7_9_common_t *arm7_9;
|
||||
arm9tdmi_common_t *arm9tdmi;
|
||||
arm966e_common_t *arm966e;
|
||||
|
||||
if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
arm7_9 = armv4_5->arch_info;
|
||||
if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
arm9tdmi = arm7_9->arch_info;
|
||||
if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
arm966e = arm9tdmi->arch_info;
|
||||
if (arm966e->common_magic != ARM966E_COMMON_MAGIC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*armv4_5_p = armv4_5;
|
||||
*arm7_9_p = arm7_9;
|
||||
*arm9tdmi_p = arm9tdmi;
|
||||
*arm966e_p = arm966e;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_read_cp15(target_t *target, int reg_addr, u32 *value)
|
||||
{
|
||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
|
||||
arm_jtag_t *jtag_info = &arm7_9->jtag_info;
|
||||
scan_field_t fields[3];
|
||||
u8 reg_addr_buf = reg_addr & 0x3f;
|
||||
u8 nr_w_buf = 0;
|
||||
|
||||
jtag_add_end_state(TAP_RTI);
|
||||
arm_jtag_scann(jtag_info, 0xf);
|
||||
arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
|
||||
|
||||
fields[0].device = jtag_info->chain_pos;
|
||||
fields[0].num_bits = 32;
|
||||
fields[0].out_value = NULL;
|
||||
fields[0].out_mask = NULL;
|
||||
fields[0].in_value = NULL;
|
||||
fields[0].in_check_value = NULL;
|
||||
fields[0].in_check_mask = NULL;
|
||||
fields[0].in_handler = NULL;
|
||||
fields[0].in_handler_priv = NULL;
|
||||
|
||||
fields[1].device = jtag_info->chain_pos;
|
||||
fields[1].num_bits = 6;
|
||||
fields[1].out_value = ®_addr_buf;
|
||||
fields[1].out_mask = NULL;
|
||||
fields[1].in_value = NULL;
|
||||
fields[1].in_check_value = NULL;
|
||||
fields[1].in_check_mask = NULL;
|
||||
fields[1].in_handler = NULL;
|
||||
fields[1].in_handler_priv = NULL;
|
||||
|
||||
fields[2].device = jtag_info->chain_pos;
|
||||
fields[2].num_bits = 1;
|
||||
fields[2].out_value = &nr_w_buf;
|
||||
fields[2].out_mask = NULL;
|
||||
fields[2].in_value = NULL;
|
||||
fields[2].in_check_value = NULL;
|
||||
fields[2].in_check_mask = NULL;
|
||||
fields[2].in_handler = NULL;
|
||||
fields[2].in_handler_priv = NULL;
|
||||
|
||||
jtag_add_dr_scan(3, fields, -1);
|
||||
|
||||
fields[0].in_handler_priv = value;
|
||||
fields[0].in_handler = arm_jtag_buf_to_u32;
|
||||
|
||||
jtag_add_dr_scan(3, fields, -1);
|
||||
|
||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||
jtag_execute_queue();
|
||||
DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_write_cp15(target_t *target, int reg_addr, u32 value)
|
||||
{
|
||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
|
||||
arm_jtag_t *jtag_info = &arm7_9->jtag_info;
|
||||
scan_field_t fields[3];
|
||||
u8 reg_addr_buf = reg_addr & 0x3f;
|
||||
u8 nr_w_buf = 1;
|
||||
u8 value_buf[4];
|
||||
|
||||
buf_set_u32(value_buf, 0, 32, value);
|
||||
|
||||
jtag_add_end_state(TAP_RTI);
|
||||
arm_jtag_scann(jtag_info, 0xf);
|
||||
arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
|
||||
|
||||
fields[0].device = jtag_info->chain_pos;
|
||||
fields[0].num_bits = 32;
|
||||
fields[0].out_value = value_buf;
|
||||
fields[0].out_mask = NULL;
|
||||
fields[0].in_value = NULL;
|
||||
fields[0].in_check_value = NULL;
|
||||
fields[0].in_check_mask = NULL;
|
||||
fields[0].in_handler = NULL;
|
||||
fields[0].in_handler_priv = NULL;
|
||||
|
||||
fields[1].device = jtag_info->chain_pos;
|
||||
fields[1].num_bits = 6;
|
||||
fields[1].out_value = ®_addr_buf;
|
||||
fields[1].out_mask = NULL;
|
||||
fields[1].in_value = NULL;
|
||||
fields[1].in_check_value = NULL;
|
||||
fields[1].in_check_mask = NULL;
|
||||
fields[1].in_handler = NULL;
|
||||
fields[1].in_handler_priv = NULL;
|
||||
|
||||
fields[2].device = jtag_info->chain_pos;
|
||||
fields[2].num_bits = 1;
|
||||
fields[2].out_value = &nr_w_buf;
|
||||
fields[2].out_mask = NULL;
|
||||
fields[2].in_value = NULL;
|
||||
fields[2].in_check_value = NULL;
|
||||
fields[2].in_check_mask = NULL;
|
||||
fields[2].in_handler = NULL;
|
||||
fields[2].in_handler_priv = NULL;
|
||||
|
||||
jtag_add_dr_scan(3, fields, -1);
|
||||
|
||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||
DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
int retval;
|
||||
target_t *target = get_current_target(cmd_ctx);
|
||||
armv4_5_common_t *armv4_5;
|
||||
arm7_9_common_t *arm7_9;
|
||||
arm9tdmi_common_t *arm9tdmi;
|
||||
arm966e_common_t *arm966e;
|
||||
arm_jtag_t *jtag_info;
|
||||
|
||||
if (arm966e_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm966e) != ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "current target isn't an ARM966e target");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
jtag_info = &arm7_9->jtag_info;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
{
|
||||
command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* one or more argument, access a single register (write if second argument is given */
|
||||
if (argc >= 1)
|
||||
{
|
||||
int address = strtoul(args[0], NULL, 0);
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
u32 value;
|
||||
if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "couldn't access reg %i", address);
|
||||
return ERROR_OK;
|
||||
}
|
||||
jtag_execute_queue();
|
||||
|
||||
command_print(cmd_ctx, "%i: %8.8x", address, value);
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
u32 value = strtoul(args[1], NULL, 0);
|
||||
if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "couldn't access reg %i", address);
|
||||
return ERROR_OK;
|
||||
}
|
||||
command_print(cmd_ctx, "%i: %8.8x", address, value);
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
int retval;
|
||||
command_t *arm966e_cmd;
|
||||
|
||||
retval = arm9tdmi_register_commands(cmd_ctx);
|
||||
arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e", NULL, COMMAND_ANY, "arm966e specific commands");
|
||||
register_command(cmd_ctx, arm966e_cmd, "cp15", arm966e_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "arm966e.h"
|
||||
|
||||
#include "arm7_9_common.h"
|
||||
#include "register.h"
|
||||
#include "target.h"
|
||||
#include "armv4_5.h"
|
||||
#include "embeddedice.h"
|
||||
#include "log.h"
|
||||
#include "jtag.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if 0
|
||||
#define _DEBUG_INSTRUCTION_EXECUTION_
|
||||
#endif
|
||||
|
||||
/* cli handling */
|
||||
int arm966e_register_commands(struct command_context_s *cmd_ctx);
|
||||
|
||||
/* forward declarations */
|
||||
int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
|
||||
int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
|
||||
int arm966e_quit(void);
|
||||
|
||||
target_type_t arm966e_target =
|
||||
{
|
||||
.name = "arm966e",
|
||||
|
||||
.poll = arm7_9_poll,
|
||||
.arch_state = armv4_5_arch_state,
|
||||
|
||||
.target_request_data = arm7_9_target_request_data,
|
||||
|
||||
.halt = arm7_9_halt,
|
||||
.resume = arm7_9_resume,
|
||||
.step = arm7_9_step,
|
||||
|
||||
.assert_reset = arm7_9_assert_reset,
|
||||
.deassert_reset = arm7_9_deassert_reset,
|
||||
.soft_reset_halt = arm7_9_soft_reset_halt,
|
||||
.prepare_reset_halt = arm7_9_prepare_reset_halt,
|
||||
|
||||
.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
|
||||
|
||||
.read_memory = arm7_9_read_memory,
|
||||
.write_memory = arm7_9_write_memory,
|
||||
.bulk_write_memory = arm7_9_bulk_write_memory,
|
||||
.checksum_memory = arm7_9_checksum_memory,
|
||||
|
||||
.run_algorithm = armv4_5_run_algorithm,
|
||||
|
||||
.add_breakpoint = arm7_9_add_breakpoint,
|
||||
.remove_breakpoint = arm7_9_remove_breakpoint,
|
||||
.add_watchpoint = arm7_9_add_watchpoint,
|
||||
.remove_watchpoint = arm7_9_remove_watchpoint,
|
||||
|
||||
.register_commands = arm966e_register_commands,
|
||||
.target_command = arm966e_target_command,
|
||||
.init_target = arm966e_init_target,
|
||||
.quit = arm966e_quit,
|
||||
};
|
||||
|
||||
int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
|
||||
{
|
||||
arm9tdmi_init_target(cmd_ctx, target);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_quit(void)
|
||||
{
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, int chain_pos, char *variant)
|
||||
{
|
||||
arm9tdmi_common_t *arm9tdmi = &arm966e->arm9tdmi_common;
|
||||
arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
|
||||
|
||||
arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
|
||||
|
||||
arm9tdmi->arch_info = arm966e;
|
||||
arm966e->common_magic = ARM966E_COMMON_MAGIC;
|
||||
|
||||
/* The ARM966E-S implements the ARMv5TE architecture which
|
||||
* has the BKPT instruction, so we don't have to use a watchpoint comparator
|
||||
*/
|
||||
arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
|
||||
arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
|
||||
|
||||
arm7_9->sw_bkpts_use_wp = 0;
|
||||
arm7_9->sw_bkpts_enabled = 1;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
|
||||
{
|
||||
int chain_pos;
|
||||
char *variant = NULL;
|
||||
arm966e_common_t *arm966e = malloc(sizeof(arm966e_common_t));
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
ERROR("'target arm966e' requires at least one additional argument");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
chain_pos = strtoul(args[3], NULL, 0);
|
||||
|
||||
if (argc >= 5)
|
||||
variant = args[4];
|
||||
|
||||
DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
|
||||
|
||||
arm966e_init_arch_info(target, arm966e, chain_pos, variant);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm966e_common_t **arm966e_p)
|
||||
{
|
||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||
arm7_9_common_t *arm7_9;
|
||||
arm9tdmi_common_t *arm9tdmi;
|
||||
arm966e_common_t *arm966e;
|
||||
|
||||
if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
arm7_9 = armv4_5->arch_info;
|
||||
if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
arm9tdmi = arm7_9->arch_info;
|
||||
if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
arm966e = arm9tdmi->arch_info;
|
||||
if (arm966e->common_magic != ARM966E_COMMON_MAGIC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*armv4_5_p = armv4_5;
|
||||
*arm7_9_p = arm7_9;
|
||||
*arm9tdmi_p = arm9tdmi;
|
||||
*arm966e_p = arm966e;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_read_cp15(target_t *target, int reg_addr, u32 *value)
|
||||
{
|
||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
|
||||
arm_jtag_t *jtag_info = &arm7_9->jtag_info;
|
||||
scan_field_t fields[3];
|
||||
u8 reg_addr_buf = reg_addr & 0x3f;
|
||||
u8 nr_w_buf = 0;
|
||||
|
||||
jtag_add_end_state(TAP_RTI);
|
||||
arm_jtag_scann(jtag_info, 0xf);
|
||||
arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
|
||||
|
||||
fields[0].device = jtag_info->chain_pos;
|
||||
fields[0].num_bits = 32;
|
||||
fields[0].out_value = NULL;
|
||||
fields[0].out_mask = NULL;
|
||||
fields[0].in_value = NULL;
|
||||
fields[0].in_check_value = NULL;
|
||||
fields[0].in_check_mask = NULL;
|
||||
fields[0].in_handler = NULL;
|
||||
fields[0].in_handler_priv = NULL;
|
||||
|
||||
fields[1].device = jtag_info->chain_pos;
|
||||
fields[1].num_bits = 6;
|
||||
fields[1].out_value = ®_addr_buf;
|
||||
fields[1].out_mask = NULL;
|
||||
fields[1].in_value = NULL;
|
||||
fields[1].in_check_value = NULL;
|
||||
fields[1].in_check_mask = NULL;
|
||||
fields[1].in_handler = NULL;
|
||||
fields[1].in_handler_priv = NULL;
|
||||
|
||||
fields[2].device = jtag_info->chain_pos;
|
||||
fields[2].num_bits = 1;
|
||||
fields[2].out_value = &nr_w_buf;
|
||||
fields[2].out_mask = NULL;
|
||||
fields[2].in_value = NULL;
|
||||
fields[2].in_check_value = NULL;
|
||||
fields[2].in_check_mask = NULL;
|
||||
fields[2].in_handler = NULL;
|
||||
fields[2].in_handler_priv = NULL;
|
||||
|
||||
jtag_add_dr_scan(3, fields, -1);
|
||||
|
||||
fields[0].in_handler_priv = value;
|
||||
fields[0].in_handler = arm_jtag_buf_to_u32;
|
||||
|
||||
jtag_add_dr_scan(3, fields, -1);
|
||||
|
||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||
jtag_execute_queue();
|
||||
DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_write_cp15(target_t *target, int reg_addr, u32 value)
|
||||
{
|
||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||
arm7_9_common_t *arm7_9 = armv4_5->arch_info;
|
||||
arm_jtag_t *jtag_info = &arm7_9->jtag_info;
|
||||
scan_field_t fields[3];
|
||||
u8 reg_addr_buf = reg_addr & 0x3f;
|
||||
u8 nr_w_buf = 1;
|
||||
u8 value_buf[4];
|
||||
|
||||
buf_set_u32(value_buf, 0, 32, value);
|
||||
|
||||
jtag_add_end_state(TAP_RTI);
|
||||
arm_jtag_scann(jtag_info, 0xf);
|
||||
arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
|
||||
|
||||
fields[0].device = jtag_info->chain_pos;
|
||||
fields[0].num_bits = 32;
|
||||
fields[0].out_value = value_buf;
|
||||
fields[0].out_mask = NULL;
|
||||
fields[0].in_value = NULL;
|
||||
fields[0].in_check_value = NULL;
|
||||
fields[0].in_check_mask = NULL;
|
||||
fields[0].in_handler = NULL;
|
||||
fields[0].in_handler_priv = NULL;
|
||||
|
||||
fields[1].device = jtag_info->chain_pos;
|
||||
fields[1].num_bits = 6;
|
||||
fields[1].out_value = ®_addr_buf;
|
||||
fields[1].out_mask = NULL;
|
||||
fields[1].in_value = NULL;
|
||||
fields[1].in_check_value = NULL;
|
||||
fields[1].in_check_mask = NULL;
|
||||
fields[1].in_handler = NULL;
|
||||
fields[1].in_handler_priv = NULL;
|
||||
|
||||
fields[2].device = jtag_info->chain_pos;
|
||||
fields[2].num_bits = 1;
|
||||
fields[2].out_value = &nr_w_buf;
|
||||
fields[2].out_mask = NULL;
|
||||
fields[2].in_value = NULL;
|
||||
fields[2].in_check_value = NULL;
|
||||
fields[2].in_check_mask = NULL;
|
||||
fields[2].in_handler = NULL;
|
||||
fields[2].in_handler_priv = NULL;
|
||||
|
||||
jtag_add_dr_scan(3, fields, -1);
|
||||
|
||||
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
||||
DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
int retval;
|
||||
target_t *target = get_current_target(cmd_ctx);
|
||||
armv4_5_common_t *armv4_5;
|
||||
arm7_9_common_t *arm7_9;
|
||||
arm9tdmi_common_t *arm9tdmi;
|
||||
arm966e_common_t *arm966e;
|
||||
arm_jtag_t *jtag_info;
|
||||
|
||||
if (arm966e_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm966e) != ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "current target isn't an ARM966e target");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
jtag_info = &arm7_9->jtag_info;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
{
|
||||
command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* one or more argument, access a single register (write if second argument is given */
|
||||
if (argc >= 1)
|
||||
{
|
||||
int address = strtoul(args[0], NULL, 0);
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
u32 value;
|
||||
if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "couldn't access reg %i", address);
|
||||
return ERROR_OK;
|
||||
}
|
||||
jtag_execute_queue();
|
||||
|
||||
command_print(cmd_ctx, "%i: %8.8x", address, value);
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
u32 value = strtoul(args[1], NULL, 0);
|
||||
if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "couldn't access reg %i", address);
|
||||
return ERROR_OK;
|
||||
}
|
||||
command_print(cmd_ctx, "%i: %8.8x", address, value);
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm966e_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
int retval;
|
||||
command_t *arm966e_cmd;
|
||||
|
||||
retval = arm9tdmi_register_commands(cmd_ctx);
|
||||
arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e", NULL, COMMAND_ANY, "arm966e specific commands");
|
||||
register_command(cmd_ctx, arm966e_cmd, "cp15", arm966e_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,207 +1,207 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "arm_jtag.h"
|
||||
|
||||
#include "binarybuffer.h"
|
||||
#include "log.h"
|
||||
#include "jtag.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if 0
|
||||
#define _ARM_JTAG_SCAN_N_CHECK_
|
||||
#endif
|
||||
|
||||
int arm_jtag_set_instr(arm_jtag_t *jtag_info, u32 new_instr, in_handler_t handler)
|
||||
{
|
||||
jtag_device_t *device = jtag_get_device(jtag_info->chain_pos);
|
||||
|
||||
if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
|
||||
{
|
||||
scan_field_t field;
|
||||
|
||||
field.device = jtag_info->chain_pos;
|
||||
field.num_bits = device->ir_length;
|
||||
field.out_value = calloc(CEIL(field.num_bits, 8), 1);
|
||||
buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
|
||||
field.out_mask = NULL;
|
||||
field.in_value = NULL;
|
||||
field.in_check_value = NULL;
|
||||
field.in_check_mask = NULL;
|
||||
field.in_handler = handler;
|
||||
field.in_handler_priv = NULL;
|
||||
jtag_add_ir_scan(1, &field, -1);
|
||||
|
||||
|
||||
free(field.out_value);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm_jtag_scann(arm_jtag_t *jtag_info, u32 new_scan_chain)
|
||||
{
|
||||
if(jtag_info->cur_scan_chain != new_scan_chain)
|
||||
{
|
||||
#ifdef _ARM_JTAG_SCAN_N_CHECK_
|
||||
u8 scan_n_check_value = 1 << (jtag_info->scann_size - 1);
|
||||
#endif
|
||||
scan_field_t field;
|
||||
|
||||
field.device = jtag_info->chain_pos;
|
||||
field.num_bits = jtag_info->scann_size;
|
||||
field.out_value = calloc(CEIL(field.num_bits, 8), 1);
|
||||
buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
|
||||
field.out_mask = NULL;
|
||||
field.in_value = NULL;
|
||||
#ifdef _ARM_JTAG_SCAN_N_CHECK_
|
||||
jtag_set_check_value(&field, &scan_n_check_value, NULL, NULL, NULL);
|
||||
#else
|
||||
field.in_handler = NULL;
|
||||
field.in_handler_priv = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL);
|
||||
jtag_add_dr_scan(1, &field, -1);
|
||||
|
||||
jtag_info->cur_scan_chain = new_scan_chain;
|
||||
|
||||
free(field.out_value);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm_jtag_reset_callback(enum jtag_event event, void *priv)
|
||||
{
|
||||
arm_jtag_t *jtag_info = priv;
|
||||
|
||||
if (event == JTAG_TRST_ASSERTED)
|
||||
{
|
||||
jtag_info->cur_scan_chain = 0;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm_jtag_setup_connection(arm_jtag_t *jtag_info)
|
||||
{
|
||||
jtag_info->scann_instr = 0x2;
|
||||
jtag_info->cur_scan_chain = 0;
|
||||
jtag_info->intest_instr = 0xc;
|
||||
|
||||
jtag_register_event_callback(arm_jtag_reset_callback, jtag_info);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into host-endian u32, flipping bit-order */
|
||||
int arm_jtag_buf_to_u32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u32 *dest = priv;
|
||||
*dest = flip_u32(le_to_h_u32(in_buf), 32);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into little-endian u32, flipping bit-order */
|
||||
int arm_jtag_buf_to_le32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u32_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into little-endian u16, flipping bit-order */
|
||||
int arm_jtag_buf_to_le16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u16_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into big-endian u32, flipping bit-order */
|
||||
int arm_jtag_buf_to_be32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u32_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into big-endian u16, flipping bit-order */
|
||||
int arm_jtag_buf_to_be16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u16_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into u8, flipping bit-order */
|
||||
int arm_jtag_buf_to_8_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u8 *dest = priv;
|
||||
*dest = flip_u32(le_to_h_u32(in_buf), 32) & 0xff;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* not-flipping variants */
|
||||
/* read JTAG buffer into host-endian u32 */
|
||||
int arm_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u32 *dest = priv;
|
||||
*dest = le_to_h_u32(in_buf);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into little-endian u32 */
|
||||
int arm_jtag_buf_to_le32(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u32_to_le(((u8*)priv), le_to_h_u32(in_buf));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into little-endian u16 */
|
||||
int arm_jtag_buf_to_le16(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u16_to_le(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into big-endian u32 */
|
||||
int arm_jtag_buf_to_be32(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u32_to_be(((u8*)priv), le_to_h_u32(in_buf));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into big-endian u16 */
|
||||
int arm_jtag_buf_to_be16(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u16_to_be(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into u8 */
|
||||
int arm_jtag_buf_to_8(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u8 *dest = priv;
|
||||
*dest = le_to_h_u32(in_buf) & 0xff;
|
||||
return ERROR_OK;
|
||||
}
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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 "arm_jtag.h"
|
||||
|
||||
#include "binarybuffer.h"
|
||||
#include "log.h"
|
||||
#include "jtag.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if 0
|
||||
#define _ARM_JTAG_SCAN_N_CHECK_
|
||||
#endif
|
||||
|
||||
int arm_jtag_set_instr(arm_jtag_t *jtag_info, u32 new_instr, in_handler_t handler)
|
||||
{
|
||||
jtag_device_t *device = jtag_get_device(jtag_info->chain_pos);
|
||||
|
||||
if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
|
||||
{
|
||||
scan_field_t field;
|
||||
|
||||
field.device = jtag_info->chain_pos;
|
||||
field.num_bits = device->ir_length;
|
||||
field.out_value = calloc(CEIL(field.num_bits, 8), 1);
|
||||
buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
|
||||
field.out_mask = NULL;
|
||||
field.in_value = NULL;
|
||||
field.in_check_value = NULL;
|
||||
field.in_check_mask = NULL;
|
||||
field.in_handler = handler;
|
||||
field.in_handler_priv = NULL;
|
||||
jtag_add_ir_scan(1, &field, -1);
|
||||
|
||||
|
||||
free(field.out_value);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm_jtag_scann(arm_jtag_t *jtag_info, u32 new_scan_chain)
|
||||
{
|
||||
if(jtag_info->cur_scan_chain != new_scan_chain)
|
||||
{
|
||||
#ifdef _ARM_JTAG_SCAN_N_CHECK_
|
||||
u8 scan_n_check_value = 1 << (jtag_info->scann_size - 1);
|
||||
#endif
|
||||
scan_field_t field;
|
||||
|
||||
field.device = jtag_info->chain_pos;
|
||||
field.num_bits = jtag_info->scann_size;
|
||||
field.out_value = calloc(CEIL(field.num_bits, 8), 1);
|
||||
buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
|
||||
field.out_mask = NULL;
|
||||
field.in_value = NULL;
|
||||
#ifdef _ARM_JTAG_SCAN_N_CHECK_
|
||||
jtag_set_check_value(&field, &scan_n_check_value, NULL, NULL, NULL);
|
||||
#else
|
||||
field.in_handler = NULL;
|
||||
field.in_handler_priv = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL);
|
||||
jtag_add_dr_scan(1, &field, -1);
|
||||
|
||||
jtag_info->cur_scan_chain = new_scan_chain;
|
||||
|
||||
free(field.out_value);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm_jtag_reset_callback(enum jtag_event event, void *priv)
|
||||
{
|
||||
arm_jtag_t *jtag_info = priv;
|
||||
|
||||
if (event == JTAG_TRST_ASSERTED)
|
||||
{
|
||||
jtag_info->cur_scan_chain = 0;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int arm_jtag_setup_connection(arm_jtag_t *jtag_info)
|
||||
{
|
||||
jtag_info->scann_instr = 0x2;
|
||||
jtag_info->cur_scan_chain = 0;
|
||||
jtag_info->intest_instr = 0xc;
|
||||
|
||||
jtag_register_event_callback(arm_jtag_reset_callback, jtag_info);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into host-endian u32, flipping bit-order */
|
||||
int arm_jtag_buf_to_u32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u32 *dest = priv;
|
||||
*dest = flip_u32(le_to_h_u32(in_buf), 32);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into little-endian u32, flipping bit-order */
|
||||
int arm_jtag_buf_to_le32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u32_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into little-endian u16, flipping bit-order */
|
||||
int arm_jtag_buf_to_le16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u16_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into big-endian u32, flipping bit-order */
|
||||
int arm_jtag_buf_to_be32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u32_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into big-endian u16, flipping bit-order */
|
||||
int arm_jtag_buf_to_be16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u16_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into u8, flipping bit-order */
|
||||
int arm_jtag_buf_to_8_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u8 *dest = priv;
|
||||
*dest = flip_u32(le_to_h_u32(in_buf), 32) & 0xff;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* not-flipping variants */
|
||||
/* read JTAG buffer into host-endian u32 */
|
||||
int arm_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u32 *dest = priv;
|
||||
*dest = le_to_h_u32(in_buf);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into little-endian u32 */
|
||||
int arm_jtag_buf_to_le32(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u32_to_le(((u8*)priv), le_to_h_u32(in_buf));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into little-endian u16 */
|
||||
int arm_jtag_buf_to_le16(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u16_to_le(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into big-endian u32 */
|
||||
int arm_jtag_buf_to_be32(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u32_to_be(((u8*)priv), le_to_h_u32(in_buf));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into big-endian u16 */
|
||||
int arm_jtag_buf_to_be16(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
h_u16_to_be(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* read JTAG buffer into u8 */
|
||||
int arm_jtag_buf_to_8(u8 *in_buf, void *priv, struct scan_field_s *field)
|
||||
{
|
||||
u8 *dest = priv;
|
||||
*dest = le_to_h_u32(in_buf) & 0xff;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1482
src/target/etb.c
1482
src/target/etb.c
File diff suppressed because it is too large
Load Diff
150
src/target/etb.h
150
src/target/etb.h
|
@ -1,75 +1,75 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef ETB_H
|
||||
#define ETB_H
|
||||
|
||||
#include "command.h"
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
#include "etb.h"
|
||||
#include "etm.h"
|
||||
|
||||
/* ETB registers */
|
||||
enum
|
||||
{
|
||||
ETB_ID = 0x00,
|
||||
ETB_RAM_DEPTH = 0x01,
|
||||
ETB_RAM_WIDTH = 0x02,
|
||||
ETB_STATUS = 0x03,
|
||||
ETB_RAM_DATA = 0x04,
|
||||
ETB_RAM_READ_POINTER = 0x05,
|
||||
ETB_RAM_WRITE_POINTER = 0x06,
|
||||
ETB_TRIGGER_COUNTER = 0x07,
|
||||
ETB_CTRL = 0x08,
|
||||
};
|
||||
|
||||
typedef struct etb_s
|
||||
{
|
||||
etm_context_t *etm_ctx;
|
||||
int chain_pos;
|
||||
int cur_scan_chain;
|
||||
reg_cache_t *reg_cache;
|
||||
|
||||
/* ETB parameters */
|
||||
int ram_depth;
|
||||
int ram_width;
|
||||
} etb_t;
|
||||
|
||||
typedef struct etb_reg_s
|
||||
{
|
||||
int addr;
|
||||
etb_t *etb;
|
||||
} etb_reg_t;
|
||||
|
||||
extern etm_capture_driver_t etb_capture_driver;
|
||||
|
||||
extern reg_cache_t* etb_build_reg_cache(etb_t *etb);
|
||||
extern int etb_read_reg(reg_t *reg);
|
||||
extern int etb_write_reg(reg_t *reg, u32 value);
|
||||
extern int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);
|
||||
extern int etb_store_reg(reg_t *reg);
|
||||
extern int etb_set_reg(reg_t *reg, u32 value);
|
||||
extern int etb_set_reg_w_exec(reg_t *reg, u8 *buf);
|
||||
|
||||
extern int etb_register_commands(struct command_context_s *cmd_ctx);
|
||||
|
||||
#endif /* ETB_H */
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef ETB_H
|
||||
#define ETB_H
|
||||
|
||||
#include "command.h"
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
#include "etb.h"
|
||||
#include "etm.h"
|
||||
|
||||
/* ETB registers */
|
||||
enum
|
||||
{
|
||||
ETB_ID = 0x00,
|
||||
ETB_RAM_DEPTH = 0x01,
|
||||
ETB_RAM_WIDTH = 0x02,
|
||||
ETB_STATUS = 0x03,
|
||||
ETB_RAM_DATA = 0x04,
|
||||
ETB_RAM_READ_POINTER = 0x05,
|
||||
ETB_RAM_WRITE_POINTER = 0x06,
|
||||
ETB_TRIGGER_COUNTER = 0x07,
|
||||
ETB_CTRL = 0x08,
|
||||
};
|
||||
|
||||
typedef struct etb_s
|
||||
{
|
||||
etm_context_t *etm_ctx;
|
||||
int chain_pos;
|
||||
int cur_scan_chain;
|
||||
reg_cache_t *reg_cache;
|
||||
|
||||
/* ETB parameters */
|
||||
int ram_depth;
|
||||
int ram_width;
|
||||
} etb_t;
|
||||
|
||||
typedef struct etb_reg_s
|
||||
{
|
||||
int addr;
|
||||
etb_t *etb;
|
||||
} etb_reg_t;
|
||||
|
||||
extern etm_capture_driver_t etb_capture_driver;
|
||||
|
||||
extern reg_cache_t* etb_build_reg_cache(etb_t *etb);
|
||||
extern int etb_read_reg(reg_t *reg);
|
||||
extern int etb_write_reg(reg_t *reg, u32 value);
|
||||
extern int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);
|
||||
extern int etb_store_reg(reg_t *reg);
|
||||
extern int etb_set_reg(reg_t *reg, u32 value);
|
||||
extern int etb_set_reg_w_exec(reg_t *reg, u8 *buf);
|
||||
|
||||
extern int etb_register_commands(struct command_context_s *cmd_ctx);
|
||||
|
||||
#endif /* ETB_H */
|
||||
|
|
3726
src/target/etm.c
3726
src/target/etm.c
File diff suppressed because it is too large
Load Diff
428
src/target/etm.h
428
src/target/etm.h
|
@ -1,214 +1,214 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007 by Vincent Palatin *
|
||||
* vincent.palatin_openocd@m4x.org *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef ETM_H
|
||||
#define ETM_H
|
||||
|
||||
#include "image.h"
|
||||
#include "trace.h"
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
#include "armv4_5.h"
|
||||
|
||||
/* ETM registers (V1.3 protocol) */
|
||||
enum
|
||||
{
|
||||
ETM_CTRL = 0x00,
|
||||
ETM_CONFIG = 0x01,
|
||||
ETM_TRIG_EVENT = 0x02,
|
||||
ETM_MMD_CTRL = 0x03,
|
||||
ETM_STATUS = 0x04,
|
||||
ETM_SYS_CONFIG = 0x05,
|
||||
ETM_TRACE_RESOURCE_CTRL = 0x06,
|
||||
ETM_TRACE_EN_CTRL2 = 0x07,
|
||||
ETM_TRACE_EN_EVENT = 0x08,
|
||||
ETM_TRACE_EN_CTRL1 = 0x09,
|
||||
ETM_FIFOFULL_REGION = 0x0a,
|
||||
ETM_FIFOFULL_LEVEL = 0x0b,
|
||||
ETM_VIEWDATA_EVENT = 0x0c,
|
||||
ETM_VIEWDATA_CTRL1 = 0x0d,
|
||||
ETM_VIEWDATA_CTRL2 = 0x0e,
|
||||
ETM_VIEWDATA_CTRL3 = 0x0f,
|
||||
ETM_ADDR_COMPARATOR_VALUE = 0x10,
|
||||
ETM_ADDR_ACCESS_TYPE = 0x20,
|
||||
ETM_DATA_COMPARATOR_VALUE = 0x30,
|
||||
ETM_DATA_COMPARATOR_MASK = 0x40,
|
||||
ETM_COUNTER_INITAL_VALUE = 0x50,
|
||||
ETM_COUNTER_ENABLE = 0x54,
|
||||
ETM_COUNTER_RELOAD_VALUE = 0x58,
|
||||
ETM_COUNTER_VALUE = 0x5c,
|
||||
ETM_SEQUENCER_CTRL = 0x60,
|
||||
ETM_SEQUENCER_STATE = 0x67,
|
||||
ETM_EXTERNAL_OUTPUT = 0x68,
|
||||
ETM_CONTEXTID_COMPARATOR_VALUE = 0x6c,
|
||||
ETM_CONTEXTID_COMPARATOR_MASK = 0x6f,
|
||||
};
|
||||
|
||||
typedef struct etm_reg_s
|
||||
{
|
||||
int addr;
|
||||
arm_jtag_t *jtag_info;
|
||||
} etm_reg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Port width */
|
||||
ETM_PORT_4BIT = 0x00,
|
||||
ETM_PORT_8BIT = 0x10,
|
||||
ETM_PORT_16BIT = 0x20,
|
||||
ETM_PORT_WIDTH_MASK = 0x70,
|
||||
/* Port modes */
|
||||
ETM_PORT_NORMAL = 0x00000,
|
||||
ETM_PORT_MUXED = 0x10000,
|
||||
ETM_PORT_DEMUXED = 0x20000,
|
||||
ETM_PORT_MODE_MASK = 0x30000,
|
||||
/* Clocking modes */
|
||||
ETM_PORT_FULL_CLOCK = 0x0000,
|
||||
ETM_PORT_HALF_CLOCK = 0x1000,
|
||||
ETM_PORT_CLOCK_MASK = 0x1000,
|
||||
} etm_portmode_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Data trace */
|
||||
ETMV1_TRACE_NONE = 0x00,
|
||||
ETMV1_TRACE_DATA = 0x01,
|
||||
ETMV1_TRACE_ADDR = 0x02,
|
||||
ETMV1_TRACE_MASK = 0x03,
|
||||
/* ContextID */
|
||||
ETMV1_CONTEXTID_NONE = 0x00,
|
||||
ETMV1_CONTEXTID_8 = 0x10,
|
||||
ETMV1_CONTEXTID_16 = 0x20,
|
||||
ETMV1_CONTEXTID_32 = 0x30,
|
||||
ETMV1_CONTEXTID_MASK = 0x30,
|
||||
/* Misc */
|
||||
ETMV1_CYCLE_ACCURATE = 0x100,
|
||||
ETMV1_BRANCH_OUTPUT = 0x200
|
||||
} etmv1_tracemode_t;
|
||||
|
||||
/* forward-declare ETM context */
|
||||
struct etm_context_s;
|
||||
|
||||
typedef struct etm_capture_driver_s
|
||||
{
|
||||
char *name;
|
||||
int (*register_commands)(struct command_context_s *cmd_ctx);
|
||||
int (*init)(struct etm_context_s *etm_ctx);
|
||||
trace_status_t (*status)(struct etm_context_s *etm_ctx);
|
||||
int (*read_trace)(struct etm_context_s *etm_ctx);
|
||||
int (*start_capture)(struct etm_context_s *etm_ctx);
|
||||
int (*stop_capture)(struct etm_context_s *etm_ctx);
|
||||
} etm_capture_driver_t;
|
||||
|
||||
enum
|
||||
{
|
||||
ETMV1_TRACESYNC_CYCLE = 0x1,
|
||||
ETMV1_TRIGGER_CYCLE = 0x2,
|
||||
};
|
||||
|
||||
typedef struct etmv1_trace_data_s
|
||||
{
|
||||
u8 pipestat; /* bits 0-2 pipeline status */
|
||||
u16 packet; /* packet data (4, 8 or 16 bit) */
|
||||
int flags; /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */
|
||||
} etmv1_trace_data_t;
|
||||
|
||||
/* describe a trace context
|
||||
* if support for ETMv2 or ETMv3 is to be implemented,
|
||||
* this will have to be split into version independent elements
|
||||
* and a version specific part
|
||||
*/
|
||||
typedef struct etm_context_s
|
||||
{
|
||||
target_t *target; /* target this ETM is connected to */
|
||||
reg_cache_t *reg_cache; /* ETM register cache */
|
||||
etm_capture_driver_t *capture_driver; /* driver used to access ETM data */
|
||||
void *capture_driver_priv; /* capture driver private data */
|
||||
u32 trigger_percent; /* percent of trace buffer to be filled after the trigger */
|
||||
trace_status_t capture_status; /* current state of capture run */
|
||||
etmv1_trace_data_t *trace_data; /* trace data */
|
||||
u32 trace_depth; /* number of trace cycles to be analyzed, 0 if no trace data available */
|
||||
etm_portmode_t portmode; /* normal, multiplexed or demultiplexed */
|
||||
etmv1_tracemode_t tracemode; /* type of information the trace contains (data, addres, contextID, ...) */
|
||||
armv4_5_state_t core_state; /* current core state (ARM, Thumb, Jazelle) */
|
||||
image_t *image; /* source for target opcodes */
|
||||
u32 pipe_index; /* current trace cycle */
|
||||
u32 data_index; /* cycle holding next data packet */
|
||||
int data_half; /* port half on a 16 bit port */
|
||||
u32 current_pc; /* current program counter */
|
||||
u32 pc_ok; /* full PC has been acquired */
|
||||
u32 last_branch; /* last branch address output */
|
||||
u32 last_branch_reason; /* branch reason code for the last branch encountered */
|
||||
u32 last_ptr; /* address of the last data access */
|
||||
u32 ptr_ok; /* whether last_ptr is valid */
|
||||
u32 context_id; /* context ID of the code being traced */
|
||||
u32 last_instruction; /* index of last instruction executed (to calculate cycle timings) */
|
||||
} etm_context_t;
|
||||
|
||||
/* PIPESTAT values */
|
||||
typedef enum
|
||||
{
|
||||
STAT_IE = 0x0,
|
||||
STAT_ID = 0x1,
|
||||
STAT_IN = 0x2,
|
||||
STAT_WT = 0x3,
|
||||
STAT_BE = 0x4,
|
||||
STAT_BD = 0x5,
|
||||
STAT_TR = 0x6,
|
||||
STAT_TD = 0x7
|
||||
} etmv1_pipestat_t;
|
||||
|
||||
/* branch reason values */
|
||||
typedef enum
|
||||
{
|
||||
BR_NORMAL = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */
|
||||
BR_ENABLE = 0x1, /* Trace has been enabled */
|
||||
BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */
|
||||
BR_NODEBUG = 0x3, /* ARM has exited for debug state */
|
||||
BR_PERIOD = 0x4, /* Peridioc synchronization point (ETM>=v1.2)*/
|
||||
BR_RSVD5 = 0x5, /* reserved */
|
||||
BR_RSVD6 = 0x6, /* reserved */
|
||||
BR_RSVD7 = 0x7, /* reserved */
|
||||
} etmv1_branch_reason_t;
|
||||
|
||||
extern char *etmv1v1_branch_reason_strings[];
|
||||
|
||||
extern reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx);
|
||||
extern int etm_read_reg(reg_t *reg);
|
||||
extern int etm_write_reg(reg_t *reg, u32 value);
|
||||
extern int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);
|
||||
extern int etm_store_reg(reg_t *reg);
|
||||
extern int etm_set_reg(reg_t *reg, u32 value);
|
||||
extern int etm_set_reg_w_exec(reg_t *reg, u8 *buf);
|
||||
|
||||
int etm_register_commands(struct command_context_s *cmd_ctx);
|
||||
int etm_register_user_commands(struct command_context_s *cmd_ctx);
|
||||
extern etm_context_t* etm_create_context(etm_portmode_t portmode, char *capture_driver_name);
|
||||
|
||||
#define ERROR_ETM_INVALID_DRIVER (-1300)
|
||||
#define ERROR_ETM_PORTMODE_NOT_SUPPORTED (-1301)
|
||||
#define ERROR_ETM_CAPTURE_INIT_FAILED (-1302)
|
||||
#define ERROR_ETM_ANALYSIS_FAILED (-1303)
|
||||
|
||||
#endif /* ETM_H */
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005, 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007 by Vincent Palatin *
|
||||
* vincent.palatin_openocd@m4x.org *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef ETM_H
|
||||
#define ETM_H
|
||||
|
||||
#include "image.h"
|
||||
#include "trace.h"
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
#include "armv4_5.h"
|
||||
|
||||
/* ETM registers (V1.3 protocol) */
|
||||
enum
|
||||
{
|
||||
ETM_CTRL = 0x00,
|
||||
ETM_CONFIG = 0x01,
|
||||
ETM_TRIG_EVENT = 0x02,
|
||||
ETM_MMD_CTRL = 0x03,
|
||||
ETM_STATUS = 0x04,
|
||||
ETM_SYS_CONFIG = 0x05,
|
||||
ETM_TRACE_RESOURCE_CTRL = 0x06,
|
||||
ETM_TRACE_EN_CTRL2 = 0x07,
|
||||
ETM_TRACE_EN_EVENT = 0x08,
|
||||
ETM_TRACE_EN_CTRL1 = 0x09,
|
||||
ETM_FIFOFULL_REGION = 0x0a,
|
||||
ETM_FIFOFULL_LEVEL = 0x0b,
|
||||
ETM_VIEWDATA_EVENT = 0x0c,
|
||||
ETM_VIEWDATA_CTRL1 = 0x0d,
|
||||
ETM_VIEWDATA_CTRL2 = 0x0e,
|
||||
ETM_VIEWDATA_CTRL3 = 0x0f,
|
||||
ETM_ADDR_COMPARATOR_VALUE = 0x10,
|
||||
ETM_ADDR_ACCESS_TYPE = 0x20,
|
||||
ETM_DATA_COMPARATOR_VALUE = 0x30,
|
||||
ETM_DATA_COMPARATOR_MASK = 0x40,
|
||||
ETM_COUNTER_INITAL_VALUE = 0x50,
|
||||
ETM_COUNTER_ENABLE = 0x54,
|
||||
ETM_COUNTER_RELOAD_VALUE = 0x58,
|
||||
ETM_COUNTER_VALUE = 0x5c,
|
||||
ETM_SEQUENCER_CTRL = 0x60,
|
||||
ETM_SEQUENCER_STATE = 0x67,
|
||||
ETM_EXTERNAL_OUTPUT = 0x68,
|
||||
ETM_CONTEXTID_COMPARATOR_VALUE = 0x6c,
|
||||
ETM_CONTEXTID_COMPARATOR_MASK = 0x6f,
|
||||
};
|
||||
|
||||
typedef struct etm_reg_s
|
||||
{
|
||||
int addr;
|
||||
arm_jtag_t *jtag_info;
|
||||
} etm_reg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Port width */
|
||||
ETM_PORT_4BIT = 0x00,
|
||||
ETM_PORT_8BIT = 0x10,
|
||||
ETM_PORT_16BIT = 0x20,
|
||||
ETM_PORT_WIDTH_MASK = 0x70,
|
||||
/* Port modes */
|
||||
ETM_PORT_NORMAL = 0x00000,
|
||||
ETM_PORT_MUXED = 0x10000,
|
||||
ETM_PORT_DEMUXED = 0x20000,
|
||||
ETM_PORT_MODE_MASK = 0x30000,
|
||||
/* Clocking modes */
|
||||
ETM_PORT_FULL_CLOCK = 0x0000,
|
||||
ETM_PORT_HALF_CLOCK = 0x1000,
|
||||
ETM_PORT_CLOCK_MASK = 0x1000,
|
||||
} etm_portmode_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Data trace */
|
||||
ETMV1_TRACE_NONE = 0x00,
|
||||
ETMV1_TRACE_DATA = 0x01,
|
||||
ETMV1_TRACE_ADDR = 0x02,
|
||||
ETMV1_TRACE_MASK = 0x03,
|
||||
/* ContextID */
|
||||
ETMV1_CONTEXTID_NONE = 0x00,
|
||||
ETMV1_CONTEXTID_8 = 0x10,
|
||||
ETMV1_CONTEXTID_16 = 0x20,
|
||||
ETMV1_CONTEXTID_32 = 0x30,
|
||||
ETMV1_CONTEXTID_MASK = 0x30,
|
||||
/* Misc */
|
||||
ETMV1_CYCLE_ACCURATE = 0x100,
|
||||
ETMV1_BRANCH_OUTPUT = 0x200
|
||||
} etmv1_tracemode_t;
|
||||
|
||||
/* forward-declare ETM context */
|
||||
struct etm_context_s;
|
||||
|
||||
typedef struct etm_capture_driver_s
|
||||
{
|
||||
char *name;
|
||||
int (*register_commands)(struct command_context_s *cmd_ctx);
|
||||
int (*init)(struct etm_context_s *etm_ctx);
|
||||
trace_status_t (*status)(struct etm_context_s *etm_ctx);
|
||||
int (*read_trace)(struct etm_context_s *etm_ctx);
|
||||
int (*start_capture)(struct etm_context_s *etm_ctx);
|
||||
int (*stop_capture)(struct etm_context_s *etm_ctx);
|
||||
} etm_capture_driver_t;
|
||||
|
||||
enum
|
||||
{
|
||||
ETMV1_TRACESYNC_CYCLE = 0x1,
|
||||
ETMV1_TRIGGER_CYCLE = 0x2,
|
||||
};
|
||||
|
||||
typedef struct etmv1_trace_data_s
|
||||
{
|
||||
u8 pipestat; /* bits 0-2 pipeline status */
|
||||
u16 packet; /* packet data (4, 8 or 16 bit) */
|
||||
int flags; /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */
|
||||
} etmv1_trace_data_t;
|
||||
|
||||
/* describe a trace context
|
||||
* if support for ETMv2 or ETMv3 is to be implemented,
|
||||
* this will have to be split into version independent elements
|
||||
* and a version specific part
|
||||
*/
|
||||
typedef struct etm_context_s
|
||||
{
|
||||
target_t *target; /* target this ETM is connected to */
|
||||
reg_cache_t *reg_cache; /* ETM register cache */
|
||||
etm_capture_driver_t *capture_driver; /* driver used to access ETM data */
|
||||
void *capture_driver_priv; /* capture driver private data */
|
||||
u32 trigger_percent; /* percent of trace buffer to be filled after the trigger */
|
||||
trace_status_t capture_status; /* current state of capture run */
|
||||
etmv1_trace_data_t *trace_data; /* trace data */
|
||||
u32 trace_depth; /* number of trace cycles to be analyzed, 0 if no trace data available */
|
||||
etm_portmode_t portmode; /* normal, multiplexed or demultiplexed */
|
||||
etmv1_tracemode_t tracemode; /* type of information the trace contains (data, addres, contextID, ...) */
|
||||
armv4_5_state_t core_state; /* current core state (ARM, Thumb, Jazelle) */
|
||||
image_t *image; /* source for target opcodes */
|
||||
u32 pipe_index; /* current trace cycle */
|
||||
u32 data_index; /* cycle holding next data packet */
|
||||
int data_half; /* port half on a 16 bit port */
|
||||
u32 current_pc; /* current program counter */
|
||||
u32 pc_ok; /* full PC has been acquired */
|
||||
u32 last_branch; /* last branch address output */
|
||||
u32 last_branch_reason; /* branch reason code for the last branch encountered */
|
||||
u32 last_ptr; /* address of the last data access */
|
||||
u32 ptr_ok; /* whether last_ptr is valid */
|
||||
u32 context_id; /* context ID of the code being traced */
|
||||
u32 last_instruction; /* index of last instruction executed (to calculate cycle timings) */
|
||||
} etm_context_t;
|
||||
|
||||
/* PIPESTAT values */
|
||||
typedef enum
|
||||
{
|
||||
STAT_IE = 0x0,
|
||||
STAT_ID = 0x1,
|
||||
STAT_IN = 0x2,
|
||||
STAT_WT = 0x3,
|
||||
STAT_BE = 0x4,
|
||||
STAT_BD = 0x5,
|
||||
STAT_TR = 0x6,
|
||||
STAT_TD = 0x7
|
||||
} etmv1_pipestat_t;
|
||||
|
||||
/* branch reason values */
|
||||
typedef enum
|
||||
{
|
||||
BR_NORMAL = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */
|
||||
BR_ENABLE = 0x1, /* Trace has been enabled */
|
||||
BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */
|
||||
BR_NODEBUG = 0x3, /* ARM has exited for debug state */
|
||||
BR_PERIOD = 0x4, /* Peridioc synchronization point (ETM>=v1.2)*/
|
||||
BR_RSVD5 = 0x5, /* reserved */
|
||||
BR_RSVD6 = 0x6, /* reserved */
|
||||
BR_RSVD7 = 0x7, /* reserved */
|
||||
} etmv1_branch_reason_t;
|
||||
|
||||
extern char *etmv1v1_branch_reason_strings[];
|
||||
|
||||
extern reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx);
|
||||
extern int etm_read_reg(reg_t *reg);
|
||||
extern int etm_write_reg(reg_t *reg, u32 value);
|
||||
extern int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);
|
||||
extern int etm_store_reg(reg_t *reg);
|
||||
extern int etm_set_reg(reg_t *reg, u32 value);
|
||||
extern int etm_set_reg_w_exec(reg_t *reg, u8 *buf);
|
||||
|
||||
int etm_register_commands(struct command_context_s *cmd_ctx);
|
||||
int etm_register_user_commands(struct command_context_s *cmd_ctx);
|
||||
extern etm_context_t* etm_create_context(etm_portmode_t portmode, char *capture_driver_name);
|
||||
|
||||
#define ERROR_ETM_INVALID_DRIVER (-1300)
|
||||
#define ERROR_ETM_PORTMODE_NOT_SUPPORTED (-1301)
|
||||
#define ERROR_ETM_CAPTURE_INIT_FAILED (-1302)
|
||||
#define ERROR_ETM_ANALYSIS_FAILED (-1303)
|
||||
|
||||
#endif /* ETM_H */
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef ETM_DUMMY_H
|
||||
#define ETM_DUMMY_H
|
||||
|
||||
#include "command.h"
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
#include "etm.h"
|
||||
|
||||
extern etm_capture_driver_t etm_dummy_capture_driver;
|
||||
extern int etm_dummy_register_commands(struct command_context_s *cmd_ctx);
|
||||
|
||||
#endif /* ETB_H */
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef ETM_DUMMY_H
|
||||
#define ETM_DUMMY_H
|
||||
|
||||
#include "command.h"
|
||||
#include "target.h"
|
||||
#include "register.h"
|
||||
#include "arm_jtag.h"
|
||||
|
||||
#include "etm.h"
|
||||
|
||||
extern etm_capture_driver_t etm_dummy_capture_driver;
|
||||
extern int etm_dummy_register_commands(struct command_context_s *cmd_ctx);
|
||||
|
||||
#endif /* ETB_H */
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef OOCD_TRACE_H
|
||||
#define OOCD_TRACE_H
|
||||
|
||||
#include "command.h"
|
||||
|
||||
#include "etm.h"
|
||||
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* registers */
|
||||
enum
|
||||
{
|
||||
OOCD_TRACE_ID = 0x7,
|
||||
OOCD_TRACE_ADDRESS = 0x0,
|
||||
OOCD_TRACE_TRIGGER_COUNTER = 0x01,
|
||||
OOCD_TRACE_CONTROL = 0x2,
|
||||
OOCD_TRACE_STATUS = 0x3,
|
||||
OOCD_TRACE_SDRAM_COUNTER = 0x4,
|
||||
};
|
||||
|
||||
/* commands */
|
||||
enum
|
||||
{
|
||||
OOCD_TRACE_NOP = 0x0,
|
||||
OOCD_TRACE_READ_REG = 0x10,
|
||||
OOCD_TRACE_WRITE_REG = 0x18,
|
||||
OOCD_TRACE_READ_RAM = 0x20,
|
||||
/* OOCD_TRACE_WRITE_RAM = 0x28, */
|
||||
OOCD_TRACE_RESYNC = 0xf0,
|
||||
};
|
||||
|
||||
typedef struct oocd_trace_s
|
||||
{
|
||||
etm_context_t *etm_ctx;
|
||||
char *tty;
|
||||
int tty_fd;
|
||||
struct termios oldtio, newtio;
|
||||
} oocd_trace_t;
|
||||
|
||||
extern etm_capture_driver_t oocd_trace_capture_driver;
|
||||
|
||||
extern int oocd_trace_register_commands(struct command_context_s *cmd_ctx);
|
||||
|
||||
#endif /* OOCD_TRACE_TRACE_H */
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#ifndef OOCD_TRACE_H
|
||||
#define OOCD_TRACE_H
|
||||
|
||||
#include "command.h"
|
||||
|
||||
#include "etm.h"
|
||||
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* registers */
|
||||
enum
|
||||
{
|
||||
OOCD_TRACE_ID = 0x7,
|
||||
OOCD_TRACE_ADDRESS = 0x0,
|
||||
OOCD_TRACE_TRIGGER_COUNTER = 0x01,
|
||||
OOCD_TRACE_CONTROL = 0x2,
|
||||
OOCD_TRACE_STATUS = 0x3,
|
||||
OOCD_TRACE_SDRAM_COUNTER = 0x4,
|
||||
};
|
||||
|
||||
/* commands */
|
||||
enum
|
||||
{
|
||||
OOCD_TRACE_NOP = 0x0,
|
||||
OOCD_TRACE_READ_REG = 0x10,
|
||||
OOCD_TRACE_WRITE_REG = 0x18,
|
||||
OOCD_TRACE_READ_RAM = 0x20,
|
||||
/* OOCD_TRACE_WRITE_RAM = 0x28, */
|
||||
OOCD_TRACE_RESYNC = 0xf0,
|
||||
};
|
||||
|
||||
typedef struct oocd_trace_s
|
||||
{
|
||||
etm_context_t *etm_ctx;
|
||||
char *tty;
|
||||
int tty_fd;
|
||||
struct termios oldtio, newtio;
|
||||
} oocd_trace_t;
|
||||
|
||||
extern etm_capture_driver_t oocd_trace_capture_driver;
|
||||
|
||||
extern int oocd_trace_register_commands(struct command_context_s *cmd_ctx);
|
||||
|
||||
#endif /* OOCD_TRACE_TRACE_H */
|
||||
|
|
4664
src/target/target.c
4664
src/target/target.c
File diff suppressed because it is too large
Load Diff
7598
src/target/xscale.c
7598
src/target/xscale.c
File diff suppressed because it is too large
Load Diff
1002
src/xsvf/xsvf.c
1002
src/xsvf/xsvf.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue