Browse Source

- added svn props

- fixed mixed line endings on flash.c, log.c, gdb_server.c

git-svn-id: svn://svn.berlios.de/openocd/trunk@371 b42882b7-edfa-0310-969c-e2dbd0fdcd60
tags/v0.1.0
ntfreak 16 years ago
parent
commit
9e5a6679ca
16 changed files with 1015 additions and 1015 deletions
  1. +5
    -5
      NEWS
  2. +28
    -28
      doc/configs/fury_ft2232.cfg
  3. +9
    -9
      doc/scripts/tms470r1a288_startup.script
  4. +0
    -0
      ecosflash/at91eb40a.elf
  5. +0
    -0
      ecosflash/debug_at91eb40a.elf
  6. +110
    -110
      ecosflash/notes.txt
  7. +485
    -485
      src/flash/ecos.c
  8. +97
    -97
      src/flash/flash.c
  9. +8
    -8
      src/helper/Makefile.am
  10. +12
    -12
      src/helper/log.c
  11. +116
    -116
      src/server/gdb_server.c
  12. +23
    -23
      src/target/Makefile.am
  13. +8
    -8
      src/target/event/at91eb40a_reset.cfg
  14. +34
    -34
      src/target/target/at91eb40a.cfg
  15. +0
    -0
      src/target/xscale/build.sh
  16. +80
    -80
      testing/index.html

+ 5
- 5
NEWS View File

@@ -1,5 +1,5 @@
2008-01-21 :
xscale big-endian branch closed and all changes moved to
trunk.
2008-01-21 :
xscale big-endian branch closed and all changes moved to
trunk.

+ 28
- 28
doc/configs/fury_ft2232.cfg View File

@@ -1,28 +1,28 @@
#daemon configuration
telnet_port 4444
gdb_port 3333
#interface
interface ft2232
ft2232_device_desc "Stellaris Evaluation Board A"
ft2232_layout evb_lm3s811
ft2232_vid_pid 0x0403 0xbcd9
jtag_speed 40
#LM3S811 Evaluation Board has only srst
reset_config srst_only separate
#jtag scan chain
#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
jtag_device 4 0x1 0xf 0xe
#target configuration
daemon_startup attach
#target <type> <startup mode>
#target arm7tdmi <reset mode> <chainpos> <endianness> <variant>
target cortex_m3 little run_and_halt 0
# 4k working area at base of ram
working_area 0 0x20000800 0x1200 nobackup
#target_script 0 reset ../doc/scripts/evb_lm3s811_test.script
#flash configuration
flash bank stellaris 0 0 0 0 0
#daemon configuration
telnet_port 4444
gdb_port 3333
#interface
interface ft2232
ft2232_device_desc "Stellaris Evaluation Board A"
ft2232_layout evb_lm3s811
ft2232_vid_pid 0x0403 0xbcd9
jtag_speed 40
#LM3S811 Evaluation Board has only srst
reset_config srst_only separate
#jtag scan chain
#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
jtag_device 4 0x1 0xf 0xe
#target configuration
daemon_startup attach
#target <type> <startup mode>
#target arm7tdmi <reset mode> <chainpos> <endianness> <variant>
target cortex_m3 little run_and_halt 0
# 4k working area at base of ram
working_area 0 0x20000800 0x1200 nobackup
#target_script 0 reset ../doc/scripts/evb_lm3s811_test.script
#flash configuration
flash bank stellaris 0 0 0 0 0

+ 9
- 9
doc/scripts/tms470r1a288_startup.script View File

@@ -1,9 +1,9 @@
# Resets and unlocks the MSM of TMS470R1A288 (an others with an MSM).
# Assumes default MSM keys (all 0xFFFFFFFF).
#
resume
jtag_reset 0 1
halt
jtag_reset 0 0
poll # hack-ish, but effective version of 'reset halt'
mdw 0x1fe0 4 # unlock MSM
# Resets and unlocks the MSM of TMS470R1A288 (an others with an MSM).
# Assumes default MSM keys (all 0xFFFFFFFF).
#
resume
jtag_reset 0 1
halt
jtag_reset 0 0
poll # hack-ish, but effective version of 'reset halt'
mdw 0x1fe0 4 # unlock MSM

+ 0
- 0
ecosflash/at91eb40a.elf View File


+ 0
- 0
ecosflash/debug_at91eb40a.elf View File


+ 110
- 110
ecosflash/notes.txt View File

@@ -1,111 +1,111 @@
1. GDB startup script for debugging purposes.
# startup script for debugging flash erase
target remote 10.0.0.56:2001
monitor halt
monitor reset
load
# stack
monitor rm 13 0x7000
# pc
monitor rm 15 0x8000
# arg1 to erase()
monitor rm 0 0x1030000
# arg2 to erase()
monitor rm 1 0x10000
stepi
2. Uploading flash driver via tftp
$ tftp 10.0.0.108
tftp> binary
tftp> put at91fr40162.bin 10.0.0.108:/config/flashdriver.bin
Sent 4048 bytes in 0.1 seconds
tftp>
4. Programming flash
eCosBoard_prog 0x1000000 /config/testdata.bin
tftp> put /cygdrive/c/workspace/ecosboard/ecosboard/phi/bootloader/images/bootloader.bin 10.0.0.108:/config/test.bin
Sent 165724 bytes in 3.9 seconds
halt
reg cpsr 0x000000D3
mww 0xFFE00020 0x1
mww 0xFFE00024 0x00000000
mww 0xFFE00000 0x01002539
eCosBoard_profile
eCosBoard_prog /config/test.bin 0x1000000
eCosBoard_profile_done
set remote memory-write-packet-size fixed
set remote memory-write-packet-size 8192
set remote memory-map-packet on
target remote 10.0.0.108:3333
monitor halt
monitor reg cpsr 0x000000D3
monitor mww 0xFFE00020 0x1
monitor mww 0xFFE00024 0x00000000
monitor mww 0xFFE00000 0x01002539
monitor eCosBoard_profile
load
monitor eCosBoard_profile_done
source /tmp/ecosboard/packages/services/profile/gprof/current/host/gprof.gdb
gprof_dump
shell cp gmon.out /tmp/ecosboard/build/src
echo To view: cd /tmp/ecosboard/build/src && gprof openocd
Performance problems:
It seems the problem is that the actual flash programming takes time.
hal_delay_us() is invoked between each time the
CPU is polled for whether flash programming has completed.
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls Ts/call Ts/call name
35.82 37.66 37.66 hal_delay_us
11.90 50.17 12.51 arm7tdmi_clock_out
9.86 60.54 10.37 gdb_get_packet
5.36 66.17 5.63 memcpy
4.34 70.73 4.56 target_buffer_get_u32
3.34 74.25 3.51 embeddedice_read_reg_w_che
ck
1.39 75.71 1.46 arm7_9_write_memory
1.34 77.11 1.40 cyg_tcp_output
1.33 78.51 1.40 __udivsi3
1.11 79.68 1.17 cyg_tcp_input
1.07 80.80 1.13 arm7tdmi_store_word_regs
0.95 81.81 1.00 __udivdi3
0.95 82.80 1.00 __umodsi3
0.93 83.78 0.98 arm7tdmi_write_core_regs
0.86 84.68 0.91 arm7_9_poll
0.85 85.57 0.89 memset
0.77 86.38 0.81 cyg_splx
0.64 87.05 0.67 cyg_in_cksumdata
0.63 87.71 0.66 openeth_deliver
0.57 88.31 0.60 strstr
0.51 88.85 0.53 eth_drv_recv
0.49 89.36 0.52 cyg_splinternal
0.49 89.88 0.52 cyg_splimp
1. GDB startup script for debugging purposes.
# startup script for debugging flash erase
target remote 10.0.0.56:2001
monitor halt
monitor reset
load
# stack
monitor rm 13 0x7000
# pc
monitor rm 15 0x8000
# arg1 to erase()
monitor rm 0 0x1030000
# arg2 to erase()
monitor rm 1 0x10000
stepi
2. Uploading flash driver via tftp
$ tftp 10.0.0.108
tftp> binary
tftp> put at91fr40162.bin 10.0.0.108:/config/flashdriver.bin
Sent 4048 bytes in 0.1 seconds
tftp>
4. Programming flash
eCosBoard_prog 0x1000000 /config/testdata.bin
tftp> put /cygdrive/c/workspace/ecosboard/ecosboard/phi/bootloader/images/bootloader.bin 10.0.0.108:/config/test.bin
Sent 165724 bytes in 3.9 seconds
halt
reg cpsr 0x000000D3
mww 0xFFE00020 0x1
mww 0xFFE00024 0x00000000
mww 0xFFE00000 0x01002539
eCosBoard_profile
eCosBoard_prog /config/test.bin 0x1000000
eCosBoard_profile_done
set remote memory-write-packet-size fixed
set remote memory-write-packet-size 8192
set remote memory-map-packet on
target remote 10.0.0.108:3333
monitor halt
monitor reg cpsr 0x000000D3
monitor mww 0xFFE00020 0x1
monitor mww 0xFFE00024 0x00000000
monitor mww 0xFFE00000 0x01002539
monitor eCosBoard_profile
load
monitor eCosBoard_profile_done
source /tmp/ecosboard/packages/services/profile/gprof/current/host/gprof.gdb
gprof_dump
shell cp gmon.out /tmp/ecosboard/build/src
echo To view: cd /tmp/ecosboard/build/src && gprof openocd
Performance problems:
It seems the problem is that the actual flash programming takes time.
hal_delay_us() is invoked between each time the
CPU is polled for whether flash programming has completed.
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls Ts/call Ts/call name
35.82 37.66 37.66 hal_delay_us
11.90 50.17 12.51 arm7tdmi_clock_out
9.86 60.54 10.37 gdb_get_packet
5.36 66.17 5.63 memcpy
4.34 70.73 4.56 target_buffer_get_u32
3.34 74.25 3.51 embeddedice_read_reg_w_che
ck
1.39 75.71 1.46 arm7_9_write_memory
1.34 77.11 1.40 cyg_tcp_output
1.33 78.51 1.40 __udivsi3
1.11 79.68 1.17 cyg_tcp_input
1.07 80.80 1.13 arm7tdmi_store_word_regs
0.95 81.81 1.00 __udivdi3
0.95 82.80 1.00 __umodsi3
0.93 83.78 0.98 arm7tdmi_write_core_regs
0.86 84.68 0.91 arm7_9_poll
0.85 85.57 0.89 memset
0.77 86.38 0.81 cyg_splx
0.64 87.05 0.67 cyg_in_cksumdata
0.63 87.71 0.66 openeth_deliver
0.57 88.31 0.60 strstr
0.51 88.85 0.53 eth_drv_recv
0.49 89.36 0.52 cyg_splinternal
0.49 89.88 0.52 cyg_splimp
0.46 90.36 0.48 cyg_ip_input 0.46 90.36 0.48 cyg_ip_input

+ 485
- 485
src/flash/ecos.c View File

@@ -1,485 +1,485 @@
/***************************************************************************
* Copyright (C) 2008 Øyvind Harboe *
* oyvind.harboe@zylin.com *
* *
* 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 "flash.h"
#include "target.h"
#include "flash.h"
#include "target.h"
#include "log.h"
#include "binarybuffer.h"
#include "../target/embeddedice.h"
#include "types.h"
int ecosflash_register_commands(struct command_context_s *cmd_ctx);
int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
int ecosflash_erase(struct flash_bank_s *bank, int first, int last);
int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last);
int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
int ecosflash_probe(struct flash_bank_s *bank);
int ecosflash_erase_check(struct flash_bank_s *bank);
int ecosflash_protect_check(struct flash_bank_s *bank);
int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size);
u32 ecosflash_get_flash_status(flash_bank_t *bank);
void ecosflash_set_flash_mode(flash_bank_t *bank,int mode);
u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);
int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
flash_driver_t ecosflash_flash =
{
.name = "ecosflash",
.register_commands = ecosflash_register_commands,
.flash_bank_command = ecosflash_flash_bank_command,
.erase = ecosflash_erase,
.protect = ecosflash_protect,
.write = ecosflash_write,
.probe = ecosflash_probe,
.auto_probe = ecosflash_probe,
.erase_check = ecosflash_erase_check,
.protect_check = ecosflash_protect_check,
.info = ecosflash_info
};
typedef struct ecosflash_flash_bank_s
{
struct target_s *target;
working_area_t *write_algorithm;
working_area_t *erase_check_algorithm;
char *driverPath;
u32 start_address;
} ecosflash_flash_bank_t;
static const int sectorSize=0x10000;
char *
flash_errmsg(int err);
#ifndef __ECOS
#define FLASH_ERR_OK 0x00 // No error - operation complete
#define FLASH_ERR_INVALID 0x01 // Invalid FLASH address
#define FLASH_ERR_ERASE 0x02 // Error trying to erase
#define FLASH_ERR_LOCK 0x03 // Error trying to lock/unlock
#define FLASH_ERR_PROGRAM 0x04 // Error trying to program
#define FLASH_ERR_PROTOCOL 0x05 // Generic error
#define FLASH_ERR_PROTECT 0x06 // Device/region is write-protected
#define FLASH_ERR_NOT_INIT 0x07 // FLASH info not yet initialized
#define FLASH_ERR_HWR 0x08 // Hardware (configuration?) problem
#define FLASH_ERR_ERASE_SUSPEND 0x09 // Device is in erase suspend mode
#define FLASH_ERR_PROGRAM_SUSPEND 0x0a // Device is in in program suspend mode
#define FLASH_ERR_DRV_VERIFY 0x0b // Driver failed to verify data
#define FLASH_ERR_DRV_TIMEOUT 0x0c // Driver timed out waiting for device
#define FLASH_ERR_DRV_WRONG_PART 0x0d // Driver does not support device
#define FLASH_ERR_LOW_VOLTAGE 0x0e // Not enough juice to complete job
char *
flash_errmsg(int err)
{
switch (err) {
case FLASH_ERR_OK:
return "No error - operation complete";
case FLASH_ERR_ERASE_SUSPEND:
return "Device is in erase suspend state";
case FLASH_ERR_PROGRAM_SUSPEND:
return "Device is in program suspend state";
case FLASH_ERR_INVALID:
return "Invalid FLASH address";
case FLASH_ERR_ERASE:
return "Error trying to erase";
case FLASH_ERR_LOCK:
return "Error trying to lock/unlock";
case FLASH_ERR_PROGRAM:
return "Error trying to program";
case FLASH_ERR_PROTOCOL:
return "Generic error";
case FLASH_ERR_PROTECT:
return "Device/region is write-protected";
case FLASH_ERR_NOT_INIT:
return "FLASH sub-system not initialized";
case FLASH_ERR_DRV_VERIFY:
return "Data verify failed after operation";
case FLASH_ERR_DRV_TIMEOUT:
return "Driver timed out waiting for device";
case FLASH_ERR_DRV_WRONG_PART:
return "Driver does not support device";
case FLASH_ERR_LOW_VOLTAGE:
return "Device reports low voltage";
default:
return "Unknown error";
}
}
#endif
/* flash bank ecosflash <base> <size> <chip_width> <bus_width> <target#> <driverPath>
*/
int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
{
ecosflash_flash_bank_t *info;
if (argc < 7)
{
WARNING("incomplete flash_bank ecosflash configuration");
return ERROR_FLASH_BANK_INVALID;
}
info = malloc(sizeof(ecosflash_flash_bank_t));
if(info == NULL)
{
ERROR("no memory for flash bank info");
exit(-1);
}
bank->driver_priv = info;
info->driverPath=strdup(args[6]);
// eCos flash sector sizes are not exposed to OpenOCD, use 0x10000 as
// a way to improve impeadance matach between OpenOCD and eCos flash
// driver
int i = 0;
u32 offset = 0;
bank->num_sectors=bank->size/sectorSize;
bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].offset = offset;
bank->sectors[i].size = sectorSize;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 0;
}
info->target = get_target_by_num(strtoul(args[5], NULL, 0));
if (info->target == NULL)
{
ERROR("no target '%i' configured", (int)strtoul(args[5], NULL, 0));
exit(-1);
}
return ERROR_OK;
}
int loadDriver(ecosflash_flash_bank_t *info)
{
u32 buf_cnt;
u32 image_size;
image_t image;
image.base_address_set = 0;
image.start_address_set = 0;
target_t *target=info->target;
if (image_open(&image, info->driverPath, NULL) != ERROR_OK)
{
ERROR("load_image error: %s", image.error_str);
return ERROR_FLASH_BANK_INVALID;
}
info->start_address=image.start_address;
image_size = 0x0;
int i;
for (i = 0; i < image.num_sections; i++)
{
void *buffer = malloc(image.sections[i].size);
int retval;
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
{
ERROR("image_read_section failed with error code: %i", retval);
free(buffer);
image_close(&image);
return ERROR_FLASH_BANK_INVALID;
}
target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
image_size += buf_cnt;
DEBUG("%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
free(buffer);
}
image_close(&image);
return ERROR_OK;
}
static int const OFFSET_ERASE=0x0;
static int const OFFSET_ERASE_SIZE=0x8;
static int const OFFSET_FLASH=0xc;
static int const OFFSET_FLASH_SIZE=0x8;
static int const OFFSET_GET_WORKAREA=0x18;
static int const OFFSET_GET_WORKAREA_SIZE=0x4;
int runCode(ecosflash_flash_bank_t *info,
u32 codeStart, u32 codeStop, u32 r0, u32 r1, u32 r2,
u32 *result,
// timeout in ms
int timeout)
{
target_t *target=info->target;
reg_param_t reg_params[3];
armv4_5_algorithm_t armv4_5_info;
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, r0);
buf_set_u32(reg_params[1].value, 0, 32, r1);
buf_set_u32(reg_params[2].value, 0, 32, r2);
int retval;
if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params,
codeStart,
codeStop, timeout,
&armv4_5_info)) != ERROR_OK)
{
ERROR("error executing eCos flash algorithm");
return retval;
}
*result=buf_get_u32(reg_params[0].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
return ERROR_OK;
}
int eCosBoard_erase(ecosflash_flash_bank_t *info, u32 address, u32 len)
{
int retval;
int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/
retval=loadDriver(info);
if (retval!=ERROR_OK)
return retval;
u32 flashErr;
retval=runCode(info,
info->start_address+OFFSET_ERASE,
info->start_address+OFFSET_ERASE+OFFSET_ERASE_SIZE,
address,
len,
0,
&flashErr,
timeout
);
if (retval!=ERROR_OK)
return retval;
if (flashErr != 0x0)
{
ERROR("Flash erase failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
return ERROR_JTAG_DEVICE_ERROR;
}
return ERROR_OK;
}
int eCosBoard_flash(ecosflash_flash_bank_t *info, void *data, u32 address, u32 len)
{
target_t *target=info->target;
const int chunk=8192;
int retval=ERROR_OK;
int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/
retval=loadDriver(info);
if (retval!=ERROR_OK)
return retval;
u32 buffer;
retval=runCode(info,
info->start_address+OFFSET_GET_WORKAREA,
info->start_address+OFFSET_GET_WORKAREA+OFFSET_GET_WORKAREA_SIZE,
0,
0,
0,
&buffer,
1000);
if (retval!=ERROR_OK)
return retval;
int i;
for (i=0; i<len; i+=chunk)
{
int t=len-i;
if (t>chunk)
{
t=chunk;
}
int retval;
retval=target_write_buffer(target, buffer, t, ((char *)data)+i);
if (retval != ERROR_OK)
return retval;
u32 flashErr;
retval=runCode(info,
info->start_address+OFFSET_FLASH,
info->start_address+OFFSET_FLASH+OFFSET_FLASH_SIZE,
buffer,
address+i,
t,
&flashErr,
timeout);
if (retval != ERROR_OK)
return retval;
if (flashErr != 0x0)
{
ERROR("Flash prog failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
return ERROR_JTAG_DEVICE_ERROR;
}
}
return ERROR_OK;
}
int ecosflash_probe(struct flash_bank_s *bank)
{
return ERROR_OK;
}
int ecosflash_register_commands(struct command_context_s *cmd_ctx)
{
register_command(cmd_ctx, NULL, "ecosflash", NULL, COMMAND_ANY, NULL);
return ERROR_OK;
}
/*
static void command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)
{
ecosflash_flash_bank_t *info = bank->driver_priv;
int i;
if (info->target->endianness == TARGET_LITTLE_ENDIAN)
{
for (i = bank->bus_width; i > 0; i--)
{
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
}
}
else
{
for (i = 1; i <= bank->bus_width; i++)
{
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
}
}
}
*/
u32 ecosflash_address(struct flash_bank_s *bank, u32 address)
{
u32 retval = 0;
switch(bank->bus_width)
{
case 4:
retval = address & 0xfffffffc;
case 2:
retval = address & 0xfffffffe;
case 1:
retval = address;
}
return retval + bank->base;
}
int ecosflash_erase(struct flash_bank_s *bank, int first, int last)
{
struct flash_bank_s *c=bank;
ecosflash_flash_bank_t *info = bank->driver_priv;
return eCosBoard_erase(info, c->base+first*sectorSize, sectorSize*(last-first+1));
}
int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last)
{
return ERROR_OK;
}
int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
{
ecosflash_flash_bank_t *info = bank->driver_priv;
struct flash_bank_s *c=bank;
return eCosBoard_flash(info, buffer, c->base+offset, count);
}
int ecosflash_erase_check(struct flash_bank_s *bank)
{
return ERROR_OK;
}
int ecosflash_protect_check(struct flash_bank_s *bank)
{
return ERROR_OK;
}
int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size)
{
ecosflash_flash_bank_t *info = bank->driver_priv;
snprintf(buf, buf_size, "eCos flash driver: %s", info->driverPath);
return ERROR_OK;
}
u32 ecosflash_get_flash_status(flash_bank_t *bank)
{
return ERROR_OK;
}
void ecosflash_set_flash_mode(flash_bank_t *bank,int mode)
{
}
u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
{
return ERROR_OK;
}
int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
return ERROR_OK;
}
/***************************************************************************
* Copyright (C) 2008 Øyvind Harboe *
* oyvind.harboe@zylin.com *
* *
* 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 "flash.h"
#include "target.h"
#include "flash.h"
#include "target.h"
#include "log.h"
#include "binarybuffer.h"
#include "../target/embeddedice.h"
#include "types.h"
int ecosflash_register_commands(struct command_context_s *cmd_ctx);
int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
int ecosflash_erase(struct flash_bank_s *bank, int first, int last);
int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last);
int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
int ecosflash_probe(struct flash_bank_s *bank);
int ecosflash_erase_check(struct flash_bank_s *bank);
int ecosflash_protect_check(struct flash_bank_s *bank);
int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size);
u32 ecosflash_get_flash_status(flash_bank_t *bank);
void ecosflash_set_flash_mode(flash_bank_t *bank,int mode);
u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);
int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
flash_driver_t ecosflash_flash =
{
.name = "ecosflash",
.register_commands = ecosflash_register_commands,
.flash_bank_command = ecosflash_flash_bank_command,
.erase = ecosflash_erase,
.protect = ecosflash_protect,
.write = ecosflash_write,
.probe = ecosflash_probe,
.auto_probe = ecosflash_probe,
.erase_check = ecosflash_erase_check,
.protect_check = ecosflash_protect_check,
.info = ecosflash_info
};
typedef struct ecosflash_flash_bank_s
{
struct target_s *target;
working_area_t *write_algorithm;
working_area_t *erase_check_algorithm;
char *driverPath;
u32 start_address;
} ecosflash_flash_bank_t;
static const int sectorSize=0x10000;
char *
flash_errmsg(int err);
#ifndef __ECOS
#define FLASH_ERR_OK 0x00 // No error - operation complete
#define FLASH_ERR_INVALID 0x01 // Invalid FLASH address
#define FLASH_ERR_ERASE 0x02 // Error trying to erase
#define FLASH_ERR_LOCK 0x03 // Error trying to lock/unlock
#define FLASH_ERR_PROGRAM 0x04 // Error trying to program
#define FLASH_ERR_PROTOCOL 0x05 // Generic error
#define FLASH_ERR_PROTECT 0x06 // Device/region is write-protected
#define FLASH_ERR_NOT_INIT 0x07 // FLASH info not yet initialized
#define FLASH_ERR_HWR 0x08 // Hardware (configuration?) problem
#define FLASH_ERR_ERASE_SUSPEND 0x09 // Device is in erase suspend mode
#define FLASH_ERR_PROGRAM_SUSPEND 0x0a // Device is in in program suspend mode
#define FLASH_ERR_DRV_VERIFY 0x0b // Driver failed to verify data
#define FLASH_ERR_DRV_TIMEOUT 0x0c // Driver timed out waiting for device
#define FLASH_ERR_DRV_WRONG_PART 0x0d // Driver does not support device
#define FLASH_ERR_LOW_VOLTAGE 0x0e // Not enough juice to complete job
char *
flash_errmsg(int err)
{
switch (err) {
case FLASH_ERR_OK:
return "No error - operation complete";
case FLASH_ERR_ERASE_SUSPEND:
return "Device is in erase suspend state";
case FLASH_ERR_PROGRAM_SUSPEND:
return "Device is in program suspend state";
case FLASH_ERR_INVALID:
return "Invalid FLASH address";
case FLASH_ERR_ERASE:
return "Error trying to erase";
case FLASH_ERR_LOCK:
return "Error trying to lock/unlock";
case FLASH_ERR_PROGRAM:
return "Error trying to program";
case FLASH_ERR_PROTOCOL:
return "Generic error";
case FLASH_ERR_PROTECT:
return "Device/region is write-protected";
case FLASH_ERR_NOT_INIT:
return "FLASH sub-system not initialized";
case FLASH_ERR_DRV_VERIFY:
return "Data verify failed after operation";
case FLASH_ERR_DRV_TIMEOUT:
return "Driver timed out waiting for device";
case FLASH_ERR_DRV_WRONG_PART:
return "Driver does not support device";
case FLASH_ERR_LOW_VOLTAGE:
return "Device reports low voltage";
default:
return "Unknown error";
}
}
#endif
/* flash bank ecosflash <base> <size> <chip_width> <bus_width> <target#> <driverPath>
*/
int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
{
ecosflash_flash_bank_t *info;
if (argc < 7)
{
WARNING("incomplete flash_bank ecosflash configuration");
return ERROR_FLASH_BANK_INVALID;
}
info = malloc(sizeof(ecosflash_flash_bank_t));
if(info == NULL)
{
ERROR("no memory for flash bank info");
exit(-1);
}
bank->driver_priv = info;
info->driverPath=strdup(args[6]);
// eCos flash sector sizes are not exposed to OpenOCD, use 0x10000 as
// a way to improve impeadance matach between OpenOCD and eCos flash
// driver
int i = 0;
u32 offset = 0;
bank->num_sectors=bank->size/sectorSize;
bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
for (i = 0; i < bank->num_sectors; i++)
{
bank->sectors[i].offset = offset;
bank->sectors[i].size = sectorSize;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 0;
}
info->target = get_target_by_num(strtoul(args[5], NULL, 0));
if (info->target == NULL)
{
ERROR("no target '%i' configured", (int)strtoul(args[5], NULL, 0));
exit(-1);
}
return ERROR_OK;
}
int loadDriver(ecosflash_flash_bank_t *info)
{
u32 buf_cnt;
u32 image_size;
image_t image;
image.base_address_set = 0;
image.start_address_set = 0;
target_t *target=info->target;
if (image_open(&image, info->driverPath, NULL) != ERROR_OK)
{
ERROR("load_image error: %s", image.error_str);
return ERROR_FLASH_BANK_INVALID;
}
info->start_address=image.start_address;
image_size = 0x0;
int i;
for (i = 0; i < image.num_sections; i++)
{
void *buffer = malloc(image.sections[i].size);
int retval;
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
{
ERROR("image_read_section failed with error code: %i", retval);
free(buffer);
image_close(&image);
return ERROR_FLASH_BANK_INVALID;
}
target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
image_size += buf_cnt;
DEBUG("%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
free(buffer);
}
image_close(&image);
return ERROR_OK;
}
static int const OFFSET_ERASE=0x0;
static int const OFFSET_ERASE_SIZE=0x8;
static int const OFFSET_FLASH=0xc;
static int const OFFSET_FLASH_SIZE=0x8;
static int const OFFSET_GET_WORKAREA=0x18;
static int const OFFSET_GET_WORKAREA_SIZE=0x4;
int runCode(ecosflash_flash_bank_t *info,
u32 codeStart, u32 codeStop, u32 r0, u32 r1, u32 r2,
u32 *result,
// timeout in ms
int timeout)
{
target_t *target=info->target;
reg_param_t reg_params[3];
armv4_5_algorithm_t armv4_5_info;
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, r0);
buf_set_u32(reg_params[1].value, 0, 32, r1);
buf_set_u32(reg_params[2].value, 0, 32, r2);
int retval;
if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params,
codeStart,
codeStop, timeout,
&armv4_5_info)) != ERROR_OK)
{
ERROR("error executing eCos flash algorithm");
return retval;
}
*result=buf_get_u32(reg_params[0].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
return ERROR_OK;
}
int eCosBoard_erase(ecosflash_flash_bank_t *info, u32 address, u32 len)
{
int retval;
int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/
retval=loadDriver(info);
if (retval!=ERROR_OK)
return retval;
u32 flashErr;
retval=runCode(info,
info->start_address+OFFSET_ERASE,
info->start_address+OFFSET_ERASE+OFFSET_ERASE_SIZE,
address,
len,
0,
&flashErr,
timeout
);
if (retval!=ERROR_OK)
return retval;
if (flashErr != 0x0)
{
ERROR("Flash erase failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
return ERROR_JTAG_DEVICE_ERROR;
}
return ERROR_OK;
}
int eCosBoard_flash(ecosflash_flash_bank_t *info, void *data, u32 address, u32 len)
{
target_t *target=info->target;
const int chunk=8192;
int retval=ERROR_OK;
int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/
retval=loadDriver(info);
if (retval!=ERROR_OK)
return retval;
u32 buffer;
retval=runCode(info,
info->start_address+OFFSET_GET_WORKAREA,
info->start_address+OFFSET_GET_WORKAREA+OFFSET_GET_WORKAREA_SIZE,
0,
0,
0,
&buffer,
1000);
if (retval!=ERROR_OK)
return retval;
int i;
for (i=0; i<len; i+=chunk)
{
int t=len-i;
if (t>chunk)
{
t=chunk;
}
int retval;
retval=target_write_buffer(target, buffer, t, ((char *)data)+i);
if (retval != ERROR_OK)
return retval;
u32 flashErr;
retval=runCode(info,
info->start_address+OFFSET_FLASH,
info->start_address+OFFSET_FLASH+OFFSET_FLASH_SIZE,
buffer,
address+i,
t,
&flashErr,
timeout);
if (retval != ERROR_OK)
return retval;
if (flashErr != 0x0)
{
ERROR("Flash prog failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
return ERROR_JTAG_DEVICE_ERROR;
}
}
return ERROR_OK;
}
int ecosflash_probe(struct flash_bank_s *bank)
{
return ERROR_OK;
}
int ecosflash_register_commands(struct command_context_s *cmd_ctx)
{
register_command(cmd_ctx, NULL, "ecosflash", NULL, COMMAND_ANY, NULL);
return ERROR_OK;
}
/*
static void command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)
{
ecosflash_flash_bank_t *info = bank->driver_priv;
int i;
if (info->target->endianness == TARGET_LITTLE_ENDIAN)
{
for (i = bank->bus_width; i > 0; i--)
{
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
}
}
else
{
for (i = 1; i <= bank->bus_width; i++)
{
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
}
}
}
*/
u32 ecosflash_address(struct flash_bank_s *bank, u32 address)
{
u32 retval = 0;
switch(bank->bus_width)
{
case 4:
retval = address & 0xfffffffc;
case 2:
retval = address & 0xfffffffe;
case 1:
retval = address;
}
return retval + bank->base;
}
int ecosflash_erase(struct flash_bank_s *bank, int first, int last)
{
struct flash_bank_s *c=bank;
ecosflash_flash_bank_t *info = bank->driver_priv;
return eCosBoard_erase(info, c->base+first*sectorSize, sectorSize*(last-first+1));
}
int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last)
{
return ERROR_OK;
}
int ecosflash_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
{
ecosflash_flash_bank_t *info = bank->driver_priv;
struct flash_bank_s *c=bank;
return eCosBoard_flash(info, buffer, c->base+offset, count);
}
int ecosflash_erase_check(struct flash_bank_s *bank)
{
return ERROR_OK;
}
int ecosflash_protect_check(struct flash_bank_s *bank)
{
return ERROR_OK;
}
int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size)
{
ecosflash_flash_bank_t *info = bank->driver_priv;
snprintf(buf, buf_size, "eCos flash driver: %s", info->driverPath);
return ERROR_OK;
}
u32 ecosflash_get_flash_status(flash_bank_t *bank)
{
return ERROR_OK;
}
void ecosflash_set_flash_mode(flash_bank_t *bank,int mode)
{
}
u32 ecosflash_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
{
return ERROR_OK;
}
int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
return ERROR_OK;
}

+ 97
- 97
src/flash/flash.c View File

@@ -64,7 +64,7 @@ extern flash_driver_t stellaris_flash;
extern flash_driver_t str9xpec_flash; extern flash_driver_t str9xpec_flash;
extern flash_driver_t stm32x_flash; extern flash_driver_t stm32x_flash;
extern flash_driver_t tms470_flash; extern flash_driver_t tms470_flash;
extern flash_driver_t ecosflash_flash;
extern flash_driver_t ecosflash_flash;


flash_driver_t *flash_drivers[] = flash_driver_t *flash_drivers[] =
{ {
@@ -77,7 +77,7 @@ flash_driver_t *flash_drivers[] =
&str9xpec_flash, &str9xpec_flash,
&stm32x_flash, &stm32x_flash,
&tms470_flash, &tms470_flash,
&ecosflash_flash,
&ecosflash_flash,
NULL, NULL,
}; };


@@ -115,7 +115,7 @@ static int flash_driver_erase(struct flash_bank_s *bank, int first, int last)
{ {
ERROR("invalid flash sector"); ERROR("invalid flash sector");
retval=ERROR_FLASH_SECTOR_INVALID; retval=ERROR_FLASH_SECTOR_INVALID;
} else
} else
{ {
retval=bank->driver->erase(bank, first, last); retval=bank->driver->erase(bank, first, last);
} }
@@ -137,7 +137,7 @@ int flash_driver_protect(struct flash_bank_s *bank, int set, int first, int last
{ {
ERROR("invalid flash sector"); ERROR("invalid flash sector");
retval=ERROR_FLASH_SECTOR_INVALID; retval=ERROR_FLASH_SECTOR_INVALID;
} else
} else
{ {
retval=bank->driver->protect(bank, set, first, last); retval=bank->driver->protect(bank, set, first, last);
} }
@@ -152,7 +152,7 @@ int flash_driver_protect(struct flash_bank_s *bank, int set, int first, int last
int flash_register_commands(struct command_context_s *cmd_ctx) int flash_register_commands(struct command_context_s *cmd_ctx)
{ {
flash_cmd = register_command(cmd_ctx, NULL, "flash", NULL, COMMAND_ANY, NULL); flash_cmd = register_command(cmd_ctx, NULL, "flash", NULL, COMMAND_ANY, NULL);
register_command(cmd_ctx, flash_cmd, "bank", handle_flash_bank_command, COMMAND_CONFIG, "flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]"); register_command(cmd_ctx, flash_cmd, "bank", handle_flash_bank_command, COMMAND_CONFIG, "flash_bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...]");
register_command(cmd_ctx, flash_cmd, "auto_erase", handle_flash_auto_erase_command, COMMAND_ANY, register_command(cmd_ctx, flash_cmd, "auto_erase", handle_flash_auto_erase_command, COMMAND_ANY,
"auto erase flash sectors <on|off>"); "auto erase flash sectors <on|off>");
@@ -184,7 +184,7 @@ int flash_init_drivers(struct command_context_s *cmd_ctx)
register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC, register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC,
"set protection of sectors at <bank> <first> <last> <on|off>"); "set protection of sectors at <bank> <first> <last> <on|off>");
} }
return ERROR_OK; return ERROR_OK;
} }


@@ -208,12 +208,12 @@ flash_bank_t *get_flash_bank_by_num(int num)
{ {
flash_bank_t *p = get_flash_bank_by_num_noprobe(num); flash_bank_t *p = get_flash_bank_by_num_noprobe(num);
int retval; int retval;
if (p == NULL) if (p == NULL)
return NULL; return NULL;
retval = p->driver->auto_probe(p); retval = p->driver->auto_probe(p);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{ {
ERROR("auto_probe failed %d\n", retval); ERROR("auto_probe failed %d\n", retval);
@@ -227,31 +227,31 @@ int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char
int i; int i;
int found = 0; int found = 0;
target_t *target; target_t *target;
if (argc < 6) if (argc < 6)
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
if ((target = get_target_by_num(strtoul(args[5], NULL, 0))) == NULL) if ((target = get_target_by_num(strtoul(args[5], NULL, 0))) == NULL)
{ {
ERROR("target %lu not defined", strtoul(args[5], NULL, 0)); ERROR("target %lu not defined", strtoul(args[5], NULL, 0));
return ERROR_OK; return ERROR_OK;
} }
for (i = 0; flash_drivers[i]; i++) for (i = 0; flash_drivers[i]; i++)
{ {
if (strcmp(args[0], flash_drivers[i]->name) == 0) if (strcmp(args[0], flash_drivers[i]->name) == 0)
{ {
flash_bank_t *p, *c; flash_bank_t *p, *c;
/* register flash specific commands */ /* register flash specific commands */
if (flash_drivers[i]->register_commands(cmd_ctx) != ERROR_OK) if (flash_drivers[i]->register_commands(cmd_ctx) != ERROR_OK)
{ {
ERROR("couldn't register '%s' commands", args[0]); ERROR("couldn't register '%s' commands", args[0]);
exit(-1); exit(-1);
} }
c = malloc(sizeof(flash_bank_t)); c = malloc(sizeof(flash_bank_t));
c->target = target; c->target = target;
c->driver = flash_drivers[i]; c->driver = flash_drivers[i];
@@ -263,14 +263,14 @@ int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char
c->num_sectors = 0; c->num_sectors = 0;
c->sectors = NULL; c->sectors = NULL;
c->next = NULL; c->next = NULL;
if (flash_drivers[i]->flash_bank_command(cmd_ctx, cmd, args, argc, c) != ERROR_OK) if (flash_drivers[i]->flash_bank_command(cmd_ctx, cmd, args, argc, c) != ERROR_OK)
{ {
ERROR("'%s' driver rejected flash bank at 0x%8.8x", args[0], c->base); ERROR("'%s' driver rejected flash bank at 0x%8.8x", args[0], c->base);
free(c); free(c);
return ERROR_OK; return ERROR_OK;
} }
/* put flash bank in linked list */ /* put flash bank in linked list */
if (flash_banks) if (flash_banks)
{ {
@@ -283,18 +283,18 @@ int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char
{ {
flash_banks = c; flash_banks = c;
} }
found = 1; found = 1;
} }
} }
/* no matching flash driver found */ /* no matching flash driver found */
if (!found) if (!found)
{ {
ERROR("flash driver '%s' not found", args[0]); ERROR("flash driver '%s' not found", args[0]);
exit(-1); exit(-1);
} }
return ERROR_OK; return ERROR_OK;
} }


@@ -302,19 +302,19 @@ int handle_flash_banks_command(struct command_context_s *cmd_ctx, char *cmd, cha
{ {
flash_bank_t *p; flash_bank_t *p;
int i = 0; int i = 0;
if (!flash_banks) if (!flash_banks)
{ {
command_print(cmd_ctx, "no flash banks configured"); command_print(cmd_ctx, "no flash banks configured");
return ERROR_OK; return ERROR_OK;
} }
for (p = flash_banks; p; p = p->next) for (p = flash_banks; p; p = p->next)
{ {
command_print(cmd_ctx, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i", command_print(cmd_ctx, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
i++, p->driver->name, p->base, p->size, p->bus_width, p->chip_width); i++, p->driver->name, p->base, p->size, p->bus_width, p->chip_width);
} }
return ERROR_OK; return ERROR_OK;
} }


@@ -323,34 +323,34 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char
flash_bank_t *p; flash_bank_t *p;
int i = 0; int i = 0;
int j = 0; int j = 0;
if (argc != 1) if (argc != 1)
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
for (p = flash_banks; p; p = p->next, i++) for (p = flash_banks; p; p = p->next, i++)
{ {
if (i == strtoul(args[0], NULL, 0)) if (i == strtoul(args[0], NULL, 0))
{ {
char buf[1024]; char buf[1024];
/* attempt auto probe */ /* attempt auto probe */
p->driver->auto_probe(p); p->driver->auto_probe(p);
command_print(cmd_ctx, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i", command_print(cmd_ctx, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
i, p->driver->name, p->base, p->size, p->bus_width, p->chip_width); i, p->driver->name, p->base, p->size, p->bus_width, p->chip_width);
for (j = 0; j < p->num_sectors; j++) for (j = 0; j < p->num_sectors; j++)
{ {
char *erase_state, *protect_state; char *erase_state, *protect_state;
if (p->sectors[j].is_erased == 0) if (p->sectors[j].is_erased == 0)
erase_state = "not erased"; erase_state = "not erased";
else if (p->sectors[j].is_erased == 1) else if (p->sectors[j].is_erased == 1)
erase_state = "erased"; erase_state = "erased";
else else
erase_state = "erase state unknown"; erase_state = "erase state unknown";
if (p->sectors[j].is_protected == 0) if (p->sectors[j].is_protected == 0)
protect_state = "not protected"; protect_state = "not protected";
else if (p->sectors[j].is_protected == 1) else if (p->sectors[j].is_protected == 1)
@@ -362,12 +362,12 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char
j, p->sectors[j].offset, p->sectors[j].size, p->sectors[j].size>>10, j, p->sectors[j].offset, p->sectors[j].size, p->sectors[j].size>>10,
erase_state, protect_state); erase_state, protect_state);
} }
p->driver->info(p, buf, 1024); p->driver->info(p, buf, 1024);
command_print(cmd_ctx, "%s", buf); command_print(cmd_ctx, "%s", buf);
} }
} }
return ERROR_OK; return ERROR_OK;
} }


@@ -375,12 +375,12 @@ int handle_flash_probe_command(struct command_context_s *cmd_ctx, char *cmd, cha
{ {
flash_bank_t *p; flash_bank_t *p;
int retval; int retval;
if (argc != 1) if (argc != 1)
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
p = get_flash_bank_by_num_noprobe(strtoul(args[0], NULL, 0)); p = get_flash_bank_by_num_noprobe(strtoul(args[0], NULL, 0));
if (p) if (p)
{ {
@@ -403,7 +403,7 @@ int handle_flash_probe_command(struct command_context_s *cmd_ctx, char *cmd, cha
{ {
command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
} }
return ERROR_OK; return ERROR_OK;
} }


@@ -411,12 +411,12 @@ int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cm
{ {
flash_bank_t *p; flash_bank_t *p;
int retval; int retval;
if (argc != 1) if (argc != 1)
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
if (p) if (p)
{ {
@@ -430,7 +430,7 @@ int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cm
args[0], p->base); args[0], p->base);
} }
} }
return ERROR_OK; return ERROR_OK;
} }


@@ -442,14 +442,14 @@ int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char *
int length; int length;
duration_t duration; duration_t duration;
char *duration_text; char *duration_text;
target_t *target = get_current_target(cmd_ctx); target_t *target = get_current_target(cmd_ctx);


if (argc != 2) if (argc != 2)
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
address = strtoul(args[0], NULL, 0); address = strtoul(args[0], NULL, 0);
length = strtoul(args[1], NULL, 0); length = strtoul(args[1], NULL, 0);
if (length <= 0) if (length <= 0)
@@ -463,19 +463,19 @@ int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char *
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
/* We can't know if we did a resume + halt, in which case we no longer know the erased state */ /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
flash_set_dirty(); flash_set_dirty();
duration_start_measure(&duration); duration_start_measure(&duration);
if ((retval = flash_erase_address_range(target, address, length)) == ERROR_OK) if ((retval = flash_erase_address_range(target, address, length)) == ERROR_OK)
{ {
duration_stop_measure(&duration, &duration_text);
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "erased address 0x%8.8x length %i in %s", address, length, duration_text); command_print(cmd_ctx, "erased address 0x%8.8x length %i in %s", address, length, duration_text);
free(duration_text); free(duration_text);
} }
return retval; return retval;
} }


@@ -483,12 +483,12 @@ int handle_flash_protect_check_command(struct command_context_s *cmd_ctx, char *
{ {
flash_bank_t *p; flash_bank_t *p;
int retval; int retval;
if (argc != 1) if (argc != 1)
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
if (p) if (p)
{ {
@@ -509,7 +509,7 @@ int handle_flash_protect_check_command(struct command_context_s *cmd_ctx, char *
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
return ERROR_OK; return ERROR_OK;
} }


@@ -523,18 +523,18 @@ int handle_flash_erase_command(struct command_context_s *cmd_ctx, char *cmd, cha
flash_bank_t *p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); flash_bank_t *p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
duration_t duration; duration_t duration;
char *duration_text; char *duration_text;
duration_start_measure(&duration); duration_start_measure(&duration);
if (!p) if (!p)
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
if ((retval = flash_driver_erase(p, first, last)) == ERROR_OK) if ((retval = flash_driver_erase(p, first, last)) == ERROR_OK)
{ {
duration_stop_measure(&duration, &duration_text);
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "erased sectors %i through %i on flash bank %i in %s", first, last, strtoul(args[0], 0, 0), duration_text); command_print(cmd_ctx, "erased sectors %i through %i on flash bank %i in %s", first, last, strtoul(args[0], 0, 0), duration_text);
free(duration_text); free(duration_text);
} }
@@ -561,7 +561,7 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c
command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
return ERROR_OK; return ERROR_OK;
} }
if (strcmp(args[3], "on") == 0) if (strcmp(args[3], "on") == 0)
set = 1; set = 1;
else if (strcmp(args[3], "off") == 0) else if (strcmp(args[3], "off") == 0)
@@ -570,7 +570,7 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
retval = flash_driver_protect(p, set, first, last); retval = flash_driver_protect(p, set, first, last);
if (retval == ERROR_OK) if (retval == ERROR_OK)
{ {
@@ -589,13 +589,13 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c
int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{ {
target_t *target = get_current_target(cmd_ctx); target_t *target = get_current_target(cmd_ctx);
image_t image; image_t image;
u32 written; u32 written;
duration_t duration; duration_t duration;
char *duration_text; char *duration_text;
int retval; int retval;


if (argc < 1) if (argc < 1)
@@ -603,15 +603,15 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;


} }
if (!target) if (!target)
{ {
ERROR("no target selected"); ERROR("no target selected");
return ERROR_OK; return ERROR_OK;
} }
duration_start_measure(&duration); duration_start_measure(&duration);
if (argc >= 2) if (argc >= 2)
{ {
image.base_address_set = 1; image.base_address_set = 1;
@@ -622,7 +622,7 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
image.base_address_set = 0; image.base_address_set = 0;
image.base_address = 0x0; image.base_address = 0x0;
} }
image.start_address_set = 0; image.start_address_set = 0;


retval = image_open(&image, args[0], (argc == 3) ? args[2] : NULL); retval = image_open(&image, args[0], (argc == 3) ? args[2] : NULL);
@@ -631,7 +631,7 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
command_print(cmd_ctx, "image_open error: %s", image.error_str); command_print(cmd_ctx, "image_open error: %s", image.error_str);
return retval; return retval;
} }
retval = flash_write(target, &image, &written, auto_erase); retval = flash_write(target, &image, &written, auto_erase);


if (retval != ERROR_OK) if (retval != ERROR_OK)
@@ -639,7 +639,7 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
image_close(&image); image_close(&image);
return retval; return retval;
} }
duration_stop_measure(&duration, &duration_text); duration_stop_measure(&duration, &duration_text);
if (retval == ERROR_OK) if (retval == ERROR_OK)
{ {
@@ -650,7 +650,7 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
free(duration_text); free(duration_text);


image_close(&image); image_close(&image);
return retval; return retval;
} }


@@ -661,10 +661,10 @@ int handle_flash_write_bank_command(struct command_context_s *cmd_ctx, char *cmd
u32 buf_cnt; u32 buf_cnt;


fileio_t fileio; fileio_t fileio;
duration_t duration; duration_t duration;
char *duration_text; char *duration_text;
int retval; int retval;
flash_bank_t *p; flash_bank_t *p;


@@ -672,9 +672,9 @@ int handle_flash_write_bank_command(struct command_context_s *cmd_ctx, char *cmd
{ {
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
duration_start_measure(&duration); duration_start_measure(&duration);
offset = strtoul(args[2], NULL, 0); offset = strtoul(args[2], NULL, 0);
p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
if (!p) if (!p)
@@ -682,24 +682,24 @@ int handle_flash_write_bank_command(struct command_context_s *cmd_ctx, char *cmd
command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
return ERROR_OK; return ERROR_OK;
} }
if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
{ {
command_print(cmd_ctx, "flash write_binary error: %s", fileio.error_str); command_print(cmd_ctx, "flash write_binary error: %s", fileio.error_str);
return ERROR_OK; return ERROR_OK;
} }
buffer = malloc(fileio.size); buffer = malloc(fileio.size);
if (fileio_read(&fileio, fileio.size, buffer, &buf_cnt) != ERROR_OK) if (fileio_read(&fileio, fileio.size, buffer, &buf_cnt) != ERROR_OK)
{ {
command_print(cmd_ctx, "flash write_binary error: %s", fileio.error_str); command_print(cmd_ctx, "flash write_binary error: %s", fileio.error_str);
return ERROR_OK; return ERROR_OK;
} }
retval = flash_driver_write(p, buffer, offset, buf_cnt); retval = flash_driver_write(p, buffer, offset, buf_cnt);
free(buffer); free(buffer);
duration_stop_measure(&duration, &duration_text); duration_stop_measure(&duration, &duration_text);
if (retval!=ERROR_OK) if (retval!=ERROR_OK)
{ {
@@ -710,7 +710,7 @@ int handle_flash_write_bank_command(struct command_context_s *cmd_ctx, char *cmd
free(duration_text); free(duration_text);


fileio_close(&fileio); fileio_close(&fileio);
return retval; return retval;
} }


@@ -718,13 +718,13 @@ void flash_set_dirty(void)
{ {
flash_bank_t *c; flash_bank_t *c;
int i; int i;
/* set all flash to require erasing */ /* set all flash to require erasing */
for (c = flash_banks; c; c = c->next) for (c = flash_banks; c; c = c->next)
{ {
for (i = 0; i < c->num_sectors; i++) for (i = 0; i < c->num_sectors; i++)
{ {
c->sectors[i].is_erased = 0;
c->sectors[i].is_erased = 0;
} }
} }
} }
@@ -739,7 +739,7 @@ flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr)
{ {
int retval; int retval;
retval = c->driver->auto_probe(c); retval = c->driver->auto_probe(c);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{ {
ERROR("auto_probe failed %d\n", retval); ERROR("auto_probe failed %d\n", retval);
@@ -760,30 +760,30 @@ int flash_erase_address_range(target_t *target, u32 addr, u32 length)
int first = -1; int first = -1;
int last = -1; int last = -1;
int i; int i;
if ((c = get_flash_bank_by_addr(target, addr)) == NULL) if ((c = get_flash_bank_by_addr(target, addr)) == NULL)
return ERROR_FLASH_DST_OUT_OF_BANK; /* no corresponding bank found */ return ERROR_FLASH_DST_OUT_OF_BANK; /* no corresponding bank found */


if (c->size == 0 || c->num_sectors == 0) if (c->size == 0 || c->num_sectors == 0)
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
if (length == 0) if (length == 0)
{ {
/* special case, erase whole bank when length is zero */ /* special case, erase whole bank when length is zero */
if (addr != c->base) if (addr != c->base)
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
return flash_driver_erase(c, 0, c->num_sectors - 1); return flash_driver_erase(c, 0, c->num_sectors - 1);
} }


/* check whether it fits */ /* check whether it fits */
if (addr + length > c->base + c->size) if (addr + length > c->base + c->size)
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
addr -= c->base; addr -= c->base;
for (i = 0; i < c->num_sectors; i++) for (i = 0; i < c->num_sectors; i++)
{
{
/* check whether sector overlaps with the given range and is not yet erased */ /* check whether sector overlaps with the given range and is not yet erased */
if (addr < c->sectors[i].offset + c->sectors[i].size && addr + length > c->sectors[i].offset && c->sectors[i].is_erased != 1) { if (addr < c->sectors[i].offset + c->sectors[i].size && addr + length > c->sectors[i].offset && c->sectors[i].is_erased != 1) {
/* if first is not set yet then this is the first sector */ /* if first is not set yet then this is the first sector */
@@ -792,10 +792,10 @@ int flash_erase_address_range(target_t *target, u32 addr, u32 length)
last = i; /* and it is the last one so far in any case */ last = i; /* and it is the last one so far in any case */
} }
} }
if( first == -1 || last == -1 ) if( first == -1 || last == -1 )
return ERROR_OK; return ERROR_OK;
return flash_driver_erase(c, first, last); return flash_driver_erase(c, first, last);
} }


@@ -807,21 +807,21 @@ int flash_write(target_t *target, image_t *image, u32 *written, int erase)
int section; int section;
u32 section_offset; u32 section_offset;
flash_bank_t *c; flash_bank_t *c;
section = 0; section = 0;
section_offset = 0; section_offset = 0;


if (written) if (written)
*written = 0; *written = 0;
if (erase) if (erase)
{ {
/* assume all sectors need erasing - stops any problems /* assume all sectors need erasing - stops any problems
* when flash_write is called multiple times */ * when flash_write is called multiple times */
flash_set_dirty(); flash_set_dirty();
} }
/* loop until we reach end of the image */ /* loop until we reach end of the image */
while (section < image->num_sections) while (section < image->num_sections)
{ {
@@ -876,17 +876,17 @@ int flash_write(target_t *target, image_t *image, u32 *written, int erase)
while (buffer_size < run_size) while (buffer_size < run_size)
{ {
u32 size_read; u32 size_read;
if (buffer_size - run_size <= image->sections[section].size - section_offset) if (buffer_size - run_size <= image->sections[section].size - section_offset)
size_read = buffer_size - run_size; size_read = buffer_size - run_size;
else else
size_read = image->sections[section].size - section_offset; size_read = image->sections[section].size - section_offset;
if ((retval = image_read_section(image, section, section_offset, if ((retval = image_read_section(image, section, section_offset,
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0) size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
{ {
free(buffer); free(buffer);
return retval; return retval;
} }


@@ -901,19 +901,19 @@ int flash_write(target_t *target, image_t *image, u32 *written, int erase)
} }


retval = ERROR_OK; retval = ERROR_OK;
if (erase) if (erase)
{ {
/* calculate and erase sectors */ /* calculate and erase sectors */
retval = flash_erase_address_range( target, run_address, run_size ); retval = flash_erase_address_range( target, run_address, run_size );
} }
if (retval == ERROR_OK) if (retval == ERROR_OK)
{ {
/* write flash sectors */ /* write flash sectors */
retval = flash_driver_write(c, buffer, run_address - c->base, run_size); retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
} }
free(buffer); free(buffer);


if (retval != ERROR_OK) if (retval != ERROR_OK)
@@ -935,13 +935,13 @@ int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;


} }
if (strcmp(args[0], "on") == 0) if (strcmp(args[0], "on") == 0)
auto_erase = 1; auto_erase = 1;
else if (strcmp(args[0], "off") == 0) else if (strcmp(args[0], "off") == 0)
auto_erase = 0; auto_erase = 0;
else
else
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
return ERROR_OK; return ERROR_OK;
} }

+ 8
- 8
src/helper/Makefile.am View File

@@ -1,8 +1,8 @@
INCLUDES = $(all_includes)
METASOURCES = AUTO
AM_CPPFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" -DPKGLIBDIR=\"$(pkglibdir)\" @CPPFLAGS@
noinst_LIBRARIES = libhelper.a
libhelper_a_SOURCES = binarybuffer.c configuration.c options.c log.c interpreter.c command.c time_support.c \
replacements.c fileio.c
noinst_HEADERS = binarybuffer.h configuration.h types.h log.h command.h \
interpreter.h time_support.h replacements.h fileio.h
INCLUDES = $(all_includes)
METASOURCES = AUTO
AM_CPPFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" -DPKGLIBDIR=\"$(pkglibdir)\" @CPPFLAGS@
noinst_LIBRARIES = libhelper.a
libhelper_a_SOURCES = binarybuffer.c configuration.c options.c log.c interpreter.c command.c time_support.c \
replacements.c fileio.c
noinst_HEADERS = binarybuffer.h configuration.h types.h log.h command.h \
interpreter.h time_support.h replacements.h fileio.h

+ 12
- 12
src/helper/log.c View File

@@ -70,8 +70,8 @@ static void log_printfv(enum log_levels level, const char *file, int line, const
if (debug_level >= LOG_DEBUG) if (debug_level >= LOG_DEBUG)
{ {
/* print with count and time information */ /* print with count and time information */
int t=(int)(time(NULL)-start);
fprintf(log_output, "%s %d %d %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer);
int t=(int)(time(NULL)-start);
fprintf(log_output, "%s %d %d %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer);
} }
else else
{ {
@@ -80,7 +80,7 @@ static void log_printfv(enum log_levels level, const char *file, int line, const
} }


fflush(log_output); fflush(log_output);
/* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */ /* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */
if (level <= LOG_INFO) if (level <= LOG_INFO)
{ {
@@ -101,7 +101,7 @@ void log_printf(enum log_levels level, const char *file, int line, const char *f
va_start(args, format); va_start(args, format);
log_printfv(level, file, line, function, format, args); log_printfv(level, file, line, function, format, args);
va_end(args); va_end(args);
} }


void log_printfnl(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) void log_printfnl(enum log_levels level, const char *file, int line, const char *function, const char *format, ...)
@@ -109,11 +109,11 @@ void log_printfnl(enum log_levels level, const char *file, int line, const char
count++; count++;
if (level > debug_level) if (level > debug_level)
return; return;
char *t=malloc(strlen(format)+2); char *t=malloc(strlen(format)+2);
strcpy(t, format); strcpy(t, format);
strcat(t, "\n"); strcat(t, "\n");
va_list args; va_list args;
va_start(args, format); va_start(args, format);
log_printfv(level, file, line, function, t, args); log_printfv(level, file, line, function, t, args);
@@ -148,7 +148,7 @@ int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char
if (argc == 1) if (argc == 1)
{ {
FILE* file = fopen(args[0], "w"); FILE* file = fopen(args[0], "w");
if (file) if (file)
{ {
log_output = file; log_output = file;
@@ -174,15 +174,15 @@ int log_init(struct command_context_s *cmd_ctx)
/* set defaults for daemon configuration, if not set by cmdline or cfgfile */ /* set defaults for daemon configuration, if not set by cmdline or cfgfile */
if (debug_level == -1) if (debug_level == -1)
debug_level = LOG_INFO; debug_level = LOG_INFO;
if (log_output == NULL) if (log_output == NULL)
{ {
log_output = stderr; log_output = stderr;
} }
return ERROR_OK; return ERROR_OK;
} }
int set_log_output(struct command_context_s *cmd_ctx, FILE *output) int set_log_output(struct command_context_s *cmd_ctx, FILE *output)
{ {
log_output = output; log_output = output;
@@ -236,7 +236,7 @@ int log_remove_callback(log_callback_fn fn, void *priv)
char *alloc_printf(const char *fmt, va_list ap) char *alloc_printf(const char *fmt, va_list ap)
{ {
char *string = NULL; char *string = NULL;
/* start by 0 to exercise all the code paths. Need minimum 2 bytes to /* start by 0 to exercise all the code paths. Need minimum 2 bytes to
* fit 1 char and 0 terminator. */ * fit 1 char and 0 terminator. */
int size = 0; int size = 0;
@@ -255,7 +255,7 @@ char *alloc_printf(const char *fmt, va_list ap)
return NULL; return NULL;
} }
} }
int ret; int ret;
ret = vsnprintf(string, size, fmt, ap); ret = vsnprintf(string, size, fmt, ap);
/* NB! The result of the vsnprintf() might be an *EMPTY* string! */ /* NB! The result of the vsnprintf() might be an *EMPTY* string! */


+ 116
- 116
src/server/gdb_server.c View File

@@ -46,7 +46,7 @@
static unsigned short gdb_port; static unsigned short gdb_port;
static const char *DIGITS = "0123456789abcdef"; static const char *DIGITS = "0123456789abcdef";


static void gdb_log_callback(void *priv, const char *file, int line,
static void gdb_log_callback(void *priv, const char *file, int line,
const char *function, const char *format, va_list args); const char *function, const char *format, va_list args);


enum gdb_detach_mode enum gdb_detach_mode
@@ -120,10 +120,10 @@ int gdb_get_char(connection_t *connection, int* next_char)
*/ */
struct timeval tv; struct timeval tv;
fd_set read_fds; fd_set read_fds;
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_SET(connection->fd, &read_fds); FD_SET(connection->fd, &read_fds);
tv.tv_sec = 1; tv.tv_sec = 1;
tv.tv_usec = 0; tv.tv_usec = 0;
if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0) if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
@@ -131,7 +131,7 @@ int gdb_get_char(connection_t *connection, int* next_char)
/* This can typically be because a "monitor" command took too long /* This can typically be because a "monitor" command took too long
* before printing any progress messages * before printing any progress messages
*/ */
return ERROR_GDB_TIMEOUT;
return ERROR_GDB_TIMEOUT;
} }
#endif #endif
gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE); gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
@@ -192,7 +192,7 @@ int gdb_get_char(connection_t *connection, int* next_char)
if (gdb_con->buf_cnt > 0) if (gdb_con->buf_cnt > 0)
connection->input_pending = 1; connection->input_pending = 1;
else else
connection->input_pending = 0;
connection->input_pending = 0;
#ifdef _DEBUG_GDB_IO_ #ifdef _DEBUG_GDB_IO_
DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
#endif #endif
@@ -211,7 +211,7 @@ int gdb_putback_char(connection_t *connection, int last_char)
} }
else else
{ {
ERROR("BUG: couldn't put character back");
ERROR("BUG: couldn't put character back");
} }


return ERROR_OK; return ERROR_OK;
@@ -263,9 +263,9 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
if (len > 0) if (len > 0)
gdb_write(connection, buffer, len); gdb_write(connection, buffer, len);
gdb_write(connection, "#", 1); gdb_write(connection, "#", 1);
snprintf(checksum, 3, "%2.2x", my_checksum); snprintf(checksum, 3, "%2.2x", my_checksum);
gdb_write(connection, checksum, 2); gdb_write(connection, checksum, 2);
#else #else
void *allocated = NULL; void *allocated = NULL;
@@ -287,9 +287,9 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
t[1 + len] = '#'; t[1 + len] = '#';
t[1 + len + 1] = DIGITS[(my_checksum >> 4) & 0xf]; t[1 + len + 1] = DIGITS[(my_checksum >> 4) & 0xf];
t[1 + len + 2] = DIGITS[my_checksum & 0xf]; t[1 + len + 2] = DIGITS[my_checksum & 0xf];
gdb_write(connection, t, totalLen); gdb_write(connection, t, totalLen);
if (allocated) if (allocated)
{ {
free(allocated); free(allocated);
@@ -387,21 +387,21 @@ int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
} while (character != '$'); } while (character != '$');


my_checksum = 0; my_checksum = 0;
count = 0; count = 0;
gdb_connection_t *gdb_con = connection->priv; gdb_connection_t *gdb_con = connection->priv;
for (;;) for (;;)
{ {
/* The common case is that we have an entire packet with no escape chars. /* The common case is that we have an entire packet with no escape chars.
* We need to leave at least 2 bytes in the buffer to have * We need to leave at least 2 bytes in the buffer to have
* gdb_get_char() update various bits and bobs correctly.
* gdb_get_char() update various bits and bobs correctly.
*/ */
if ((gdb_con->buf_cnt > 2) && ((gdb_con->buf_cnt+count) < *len)) if ((gdb_con->buf_cnt > 2) && ((gdb_con->buf_cnt+count) < *len))
{ {
/* The compiler will struggle a bit with constant propagation and /* The compiler will struggle a bit with constant propagation and
* aliasing, so we help it by showing that these values do not * aliasing, so we help it by showing that these values do not
* change inside the loop
*/
* change inside the loop
*/
int i; int i;
char *buf = gdb_con->buf_p; char *buf = gdb_con->buf_p;
int run = gdb_con->buf_cnt - 2; int run = gdb_con->buf_cnt - 2;
@@ -413,13 +413,13 @@ int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
i++; i++;
if (character == '#') if (character == '#')
{ {
/* Danger! character can be '#' when esc is
/* Danger! character can be '#' when esc is
* used so we need an explicit boolean for done here. * used so we need an explicit boolean for done here.
*/ */
done = 1; done = 1;
break; break;
} }
if (character == '}') if (character == '}')
{ {
/* data transmitted in binary mode (X packet) /* data transmitted in binary mode (X packet)
@@ -437,15 +437,15 @@ int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
} }
gdb_con->buf_p += i; gdb_con->buf_p += i;
gdb_con->buf_cnt -= i; gdb_con->buf_cnt -= i;
if (done)
if (done)
break; break;
}
}
if (count > *len) if (count > *len)
{ {
ERROR("packet buffer too small"); ERROR("packet buffer too small");
return ERROR_GDB_BUFFER_TOO_SMALL; return ERROR_GDB_BUFFER_TOO_SMALL;
} }
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK) if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
return retval; return retval;


@@ -503,7 +503,7 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
gdb_con->busy = 0; gdb_con->busy = 0;
return retval; return retval;
} }
int gdb_output_con(connection_t *connection, char* line) int gdb_output_con(connection_t *connection, char* line)
{ {
char *hex_buffer; char *hex_buffer;
@@ -527,7 +527,7 @@ int gdb_output_con(connection_t *connection, char* line)
int gdb_output(struct command_context_s *context, char* line) int gdb_output(struct command_context_s *context, char* line)
{ {
/* this will be dumped to the log and also sent as an O packet if possible */ /* this will be dumped to the log and also sent as an O packet if possible */
USER_SAMELINE(line);
USER_SAMELINE(line);
return ERROR_OK; return ERROR_OK;
} }


@@ -535,7 +535,7 @@ int gdb_program_handler(struct target_s *target, enum target_event event, void *
{ {
FILE *script; FILE *script;
struct command_context_s *cmd_ctx = priv; struct command_context_s *cmd_ctx = priv;
if (target->gdb_program_script) if (target->gdb_program_script)
{ {
script = open_file_from_path(cmd_ctx, target->gdb_program_script, "r"); script = open_file_from_path(cmd_ctx, target->gdb_program_script, "r");
@@ -548,10 +548,10 @@ int gdb_program_handler(struct target_s *target, enum target_event event, void *
INFO("executing gdb_program script '%s'", target->gdb_program_script); INFO("executing gdb_program script '%s'", target->gdb_program_script);
command_run_file(cmd_ctx, script, COMMAND_EXEC); command_run_file(cmd_ctx, script, COMMAND_EXEC);
fclose(script); fclose(script);
jtag_execute_queue(); jtag_execute_queue();
} }
return ERROR_OK; return ERROR_OK;
} }


@@ -566,10 +566,10 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
{ {
case TARGET_EVENT_HALTED: case TARGET_EVENT_HALTED:
/* In the GDB protocol when we are stepping or coninuing execution, /* In the GDB protocol when we are stepping or coninuing execution,
* we have a lingering reply. Upon receiving a halted event
* we have a lingering reply. Upon receiving a halted event
* when we have that lingering packet, we reply to the original * when we have that lingering packet, we reply to the original
* step or continue packet. * step or continue packet.
*
*
* Executing monitor commands can bring the target in and * Executing monitor commands can bring the target in and
* out of the running state so we'll see lots of TARGET_EVENT_XXX * out of the running state so we'll see lots of TARGET_EVENT_XXX
* that are to be ignored. * that are to be ignored.
@@ -578,7 +578,7 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
{ {
/* stop forwarding log packets! */ /* stop forwarding log packets! */
log_remove_callback(gdb_log_callback, connection); log_remove_callback(gdb_log_callback, connection);
if (gdb_connection->ctrl_c) if (gdb_connection->ctrl_c)
{ {
signal = 0x2; signal = 0x2;
@@ -603,8 +603,8 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event


return ERROR_OK; return ERROR_OK;
} }
int gdb_new_connection(connection_t *connection) int gdb_new_connection(connection_t *connection)
{ {
gdb_connection_t *gdb_connection = malloc(sizeof(gdb_connection_t)); gdb_connection_t *gdb_connection = malloc(sizeof(gdb_connection_t));
@@ -622,12 +622,12 @@ int gdb_new_connection(connection_t *connection)
gdb_connection->vflash_image = NULL; gdb_connection->vflash_image = NULL;
gdb_connection->closed = 0; gdb_connection->closed = 0;
gdb_connection->busy = 0; gdb_connection->busy = 0;
/* output goes through gdb connection */ /* output goes through gdb connection */
command_set_output_handler(connection->cmd_ctx, gdb_output, connection); command_set_output_handler(connection->cmd_ctx, gdb_output, connection);


/* register callback to be informed about target events */ /* register callback to be informed about target events */
target_register_event_callback(gdb_target_callback_event_handler, connection);
target_register_event_callback(gdb_target_callback_event_handler, connection);


/* a gdb session just attached, put the target in halt mode */ /* a gdb session just attached, put the target in halt mode */
if (((retval = gdb_service->target->type->halt(gdb_service->target)) != ERROR_OK) && if (((retval = gdb_service->target->type->halt(gdb_service->target)) != ERROR_OK) &&
@@ -665,7 +665,7 @@ int gdb_connection_closed(connection_t *connection)


/* if this connection registered a debug-message receiver delete it */ /* if this connection registered a debug-message receiver delete it */
delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target); delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target);
if (connection->priv) if (connection->priv)
{ {
free(connection->priv); free(connection->priv);
@@ -712,7 +712,7 @@ void gdb_str_to_target(target_t *target, char *tstr, reg_t *reg)
u8 *buf; u8 *buf;
int buf_len; int buf_len;
buf = reg->value; buf = reg->value;
buf_len = CEIL(reg->size, 8);
buf_len = CEIL(reg->size, 8);


if (target->endianness == TARGET_LITTLE_ENDIAN) if (target->endianness == TARGET_LITTLE_ENDIAN)
{ {
@@ -729,7 +729,7 @@ void gdb_str_to_target(target_t *target, char *tstr, reg_t *reg)
tstr[(buf_len-1-i)*2] = DIGITS[(buf[i]>>4)&0xf]; tstr[(buf_len-1-i)*2] = DIGITS[(buf[i]>>4)&0xf];
tstr[(buf_len-1-i)*2+1] = DIGITS[buf[i]&0xf]; tstr[(buf_len-1-i)*2+1] = DIGITS[buf[i]&0xf];
} }
}
}
} }


void gdb_target_to_str(target_t *target, char *tstr, char *str) void gdb_target_to_str(target_t *target, char *tstr, char *str)
@@ -757,7 +757,7 @@ void gdb_target_to_str(target_t *target, char *tstr, char *str)
{ {
str[i] = tstr[i]; str[i] = tstr[i];
} }
}
}
} }


int gdb_get_registers_packet(connection_t *connection, target_t *target, char* packet, int packet_size) int gdb_get_registers_packet(connection_t *connection, target_t *target, char* packet, int packet_size)
@@ -870,7 +870,7 @@ int gdb_set_registers_packet(connection_t *connection, target_t *target, char *p
bin_buf = malloc(CEIL(reg_list[i]->size, 8)); bin_buf = malloc(CEIL(reg_list[i]->size, 8));
str_to_buf(hex_buf, CEIL(reg_list[i]->size, 8) * 2, bin_buf, reg_list[i]->size, 16); str_to_buf(hex_buf, CEIL(reg_list[i]->size, 8) * 2, bin_buf, reg_list[i]->size, 16);


/* get register arch_type, and call set method */
/* get register arch_type, and call set method */
arch_type = register_get_arch_type(reg_list[i]->arch_type); arch_type = register_get_arch_type(reg_list[i]->arch_type);
if (arch_type == NULL) if (arch_type == NULL)
{ {
@@ -879,14 +879,14 @@ int gdb_set_registers_packet(connection_t *connection, target_t *target, char *p
} }
arch_type->set(reg_list[i], bin_buf); arch_type->set(reg_list[i], bin_buf);


/* advance packet pointer */
/* advance packet pointer */
packet_p += (CEIL(reg_list[i]->size, 8) * 2); packet_p += (CEIL(reg_list[i]->size, 8) * 2);


free(bin_buf); free(bin_buf);
free(hex_buf); free(hex_buf);
} }


/* free reg_t *reg_list[] array allocated by get_gdb_reg_list */
/* free reg_t *reg_list[] array allocated by get_gdb_reg_list */
free(reg_list); free(reg_list);


gdb_put_packet(connection, "OK", 2); gdb_put_packet(connection, "OK", 2);
@@ -985,7 +985,7 @@ int gdb_set_register_packet(connection_t *connection, target_t *target, char *pa
bin_buf = malloc(CEIL(reg_list[reg_num]->size, 8)); bin_buf = malloc(CEIL(reg_list[reg_num]->size, 8));
str_to_buf(hex_buf, CEIL(reg_list[reg_num]->size, 8) * 2, bin_buf, reg_list[reg_num]->size, 16); str_to_buf(hex_buf, CEIL(reg_list[reg_num]->size, 8) * 2, bin_buf, reg_list[reg_num]->size, 16);


/* get register arch_type, and call set method */
/* get register arch_type, and call set method */
arch_type = register_get_arch_type(reg_list[reg_num]->arch_type); arch_type = register_get_arch_type(reg_list[reg_num]->arch_type);
if (arch_type == NULL) if (arch_type == NULL)
{ {
@@ -1030,7 +1030,7 @@ int gdb_memory_packet_error(connection_t *connection, int retval)


/* We don't have to worry about the default 2 second timeout for GDB packets, /* We don't have to worry about the default 2 second timeout for GDB packets,
* because GDB breaks up large memory reads into smaller reads. * because GDB breaks up large memory reads into smaller reads.
*
*
* 8191 bytes by the looks of it. Why 8191 bytes instead of 8192????? * 8191 bytes by the looks of it. Why 8191 bytes instead of 8192?????
*/ */
int gdb_read_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size) int gdb_read_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
@@ -1067,11 +1067,11 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac
{ {
/* TODO : Here we have to lie and send back all zero's lest stack traces won't work. /* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
* At some point this might be fixed in GDB, in which case this code can be removed. * At some point this might be fixed in GDB, in which case this code can be removed.
*
*
* OpenOCD developers are acutely aware of this problem, but there is nothing * OpenOCD developers are acutely aware of this problem, but there is nothing
* gained by involving the user in this problem that hopefully will get resolved * gained by involving the user in this problem that hopefully will get resolved
* eventually * eventually
*
*
* http://sourceware.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=2395 * http://sourceware.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=2395
* *
* For now, the default is to fix up things to make current GDB versions work. * For now, the default is to fix up things to make current GDB versions work.
@@ -1157,7 +1157,7 @@ int gdb_write_memory_packet(connection_t *connection, target_t *target, char *pa
else else
{ {
if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK) if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
return retval;
return retval;
} }


free(buffer); free(buffer);
@@ -1207,7 +1207,7 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c
else else
{ {
if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK) if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
return retval;
return retval;
} }


return ERROR_OK; return ERROR_OK;
@@ -1362,14 +1362,14 @@ void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, .
return; return;
} }
int first = 1; int first = 1;
for (;;) for (;;)
{ {
if ((*xml == NULL) || (!first)) if ((*xml == NULL) || (!first))
{ {
/* start by 0 to exercise all the code paths. /* start by 0 to exercise all the code paths.
* Need minimum 2 bytes to fit 1 char and 0 terminator. */ * Need minimum 2 bytes to fit 1 char and 0 terminator. */
*size = *size * 2 + 2; *size = *size * 2 + 2;
char *t = *xml; char *t = *xml;
*xml = realloc(*xml, *size); *xml = realloc(*xml, *size);
@@ -1381,7 +1381,7 @@ void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, .
return; return;
} }
} }
va_list ap; va_list ap;
int ret; int ret;
va_start(ap, fmt); va_start(ap, fmt);
@@ -1400,7 +1400,7 @@ void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, .
static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len) static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len)
{ {
char *separator; char *separator;
/* Extract and NUL-terminate the annex. */ /* Extract and NUL-terminate the annex. */
*annex = buf; *annex = buf;
while (*buf && *buf != ':') while (*buf && *buf != ':')
@@ -1408,17 +1408,17 @@ static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len
if (*buf == '\0') if (*buf == '\0')
return -1; return -1;
*buf++ = 0; *buf++ = 0;
/* After the read marker and annex, qXfer looks like a /* After the read marker and annex, qXfer looks like a
* traditional 'm' packet. */ * traditional 'm' packet. */
*ofs = strtoul(buf, &separator, 16); *ofs = strtoul(buf, &separator, 16);


if (*separator != ',') if (*separator != ',')
return -1; return -1;


*len = strtoul(separator+1, NULL, 16); *len = strtoul(separator+1, NULL, 16);
return 0; return 0;
} }


@@ -1426,22 +1426,22 @@ int gdb_calc_blocksize(flash_bank_t *bank)
{ {
int i; int i;
int block_size = 0xffffffff; int block_size = 0xffffffff;
/* loop through all sectors and return smallest sector size */ /* loop through all sectors and return smallest sector size */
for (i = 0; i < bank->num_sectors; i++) for (i = 0; i < bank->num_sectors; i++)
{ {
if (bank->sectors[i].size < block_size) if (bank->sectors[i].size < block_size)
block_size = bank->sectors[i].size; block_size = bank->sectors[i].size;
} }
return block_size; return block_size;
} }


int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size) int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
{ {
command_context_t *cmd_ctx = connection->cmd_ctx; command_context_t *cmd_ctx = connection->cmd_ctx;
if (strstr(packet, "qRcmd,")) if (strstr(packet, "qRcmd,"))
{ {
if (packet_size > 6) if (packet_size > 6)
@@ -1456,7 +1456,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
cmd[i] = tmp; cmd[i] = tmp;
} }
cmd[(packet_size - 6)/2] = 0x0; cmd[(packet_size - 6)/2] = 0x0;
/* We want to print all debug output to GDB connection */ /* We want to print all debug output to GDB connection */
log_add_callback(gdb_log_callback, connection); log_add_callback(gdb_log_callback, connection);
target_call_timer_callbacks(); target_call_timer_callbacks();
@@ -1476,22 +1476,22 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
u32 checksum; u32 checksum;
u32 addr = 0; u32 addr = 0;
u32 len = 0; u32 len = 0;
/* skip command character */ /* skip command character */
packet += 5; packet += 5;
addr = strtoul(packet, &separator, 16); addr = strtoul(packet, &separator, 16);
if (*separator != ',') if (*separator != ',')
{ {
ERROR("incomplete read memory packet received, dropping connection"); ERROR("incomplete read memory packet received, dropping connection");
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
} }
len = strtoul(separator + 1, NULL, 16); len = strtoul(separator + 1, NULL, 16);
retval = target_checksum_memory(target, addr, len, &checksum); retval = target_checksum_memory(target, addr, len, &checksum);
if (retval == ERROR_OK) if (retval == ERROR_OK)
{ {
snprintf(gdb_reply, 10, "C%8.8x", checksum); snprintf(gdb_reply, 10, "C%8.8x", checksum);
@@ -1500,9 +1500,9 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
else else
{ {
if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK) if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
return retval;
return retval;
} }
return ERROR_OK; return ERROR_OK;
} }
} }
@@ -1515,66 +1515,66 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
int pos = 0; int pos = 0;
int size = 0; int size = 0;


xml_printf(&retval, &buffer, &pos, &size,
xml_printf(&retval, &buffer, &pos, &size,
"PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-", "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-",
(GDB_BUFFER_SIZE - 1), gdb_use_memory_map == 1 ? '+' : '-'); (GDB_BUFFER_SIZE - 1), gdb_use_memory_map == 1 ? '+' : '-');
if (retval != ERROR_OK) if (retval != ERROR_OK)
{ {
gdb_send_error(connection, 01); gdb_send_error(connection, 01);
return ERROR_OK; return ERROR_OK;
} }
gdb_put_packet(connection, buffer, strlen(buffer)); gdb_put_packet(connection, buffer, strlen(buffer));
free(buffer); free(buffer);
return ERROR_OK; return ERROR_OK;
} }
else if (strstr(packet, "qXfer:memory-map:read::")) else if (strstr(packet, "qXfer:memory-map:read::"))
{ {
/* We get away with only specifying flash here. Regions that are not /* We get away with only specifying flash here. Regions that are not
* specified are treated as if we provided no memory map(if not we
* specified are treated as if we provided no memory map(if not we
* could detect the holes and mark them as RAM). * could detect the holes and mark them as RAM).
* Normally we only execute this code once, but no big deal if we * Normally we only execute this code once, but no big deal if we
* have to regenerate it a couple of times. */ * have to regenerate it a couple of times. */
flash_bank_t *p; flash_bank_t *p;
char *xml = NULL; char *xml = NULL;
int size = 0; int size = 0;
int pos = 0; int pos = 0;
int retval = ERROR_OK; int retval = ERROR_OK;
int offset; int offset;
int length; int length;
char *separator; char *separator;
int blocksize; int blocksize;
/* skip command character */ /* skip command character */
packet += 23; packet += 23;
offset = strtoul(packet, &separator, 16); offset = strtoul(packet, &separator, 16);
length = strtoul(separator + 1, &separator, 16); length = strtoul(separator + 1, &separator, 16);
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n"); xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
int i = 0; int i = 0;
for (;;) for (;;)
{ {
p = get_flash_bank_by_num(i); p = get_flash_bank_by_num(i);
if (p == NULL) if (p == NULL)
break; break;
/* if device has uneven sector sizes, eg. str7, lpc /* if device has uneven sector sizes, eg. str7, lpc
* we pass the smallest sector size to gdb memory map */ * we pass the smallest sector size to gdb memory map */
blocksize = gdb_calc_blocksize(p); blocksize = gdb_calc_blocksize(p);
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \ xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
"<property name=\"blocksize\">0x%x</property>\n" \ "<property name=\"blocksize\">0x%x</property>\n" \
"</memory>\n", \ "</memory>\n", \
p->base, p->size, blocksize); p->base, p->size, blocksize);
i++; i++;
} }
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n"); xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");


if (retval != ERROR_OK) if (retval != ERROR_OK)
@@ -1582,7 +1582,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
gdb_send_error(connection, retval); gdb_send_error(connection, retval);
return retval; return retval;
} }
if (offset + length > pos) if (offset + length > pos)
{ {
length = pos - offset; length = pos - offset;
@@ -1592,52 +1592,52 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
t[0] = 'l'; t[0] = 'l';
memcpy(t + 1, xml + offset, length); memcpy(t + 1, xml + offset, length);
gdb_put_packet(connection, t, length + 1); gdb_put_packet(connection, t, length + 1);
free(t); free(t);
free(xml); free(xml);
return ERROR_OK; return ERROR_OK;
} }
else if (strstr(packet, "qXfer:features:read:")) else if (strstr(packet, "qXfer:features:read:"))
{
{
char *xml = NULL; char *xml = NULL;
int size = 0; int size = 0;
int pos = 0; int pos = 0;
int retval = ERROR_OK; int retval = ERROR_OK;
int offset; int offset;
unsigned int length; unsigned int length;
char *annex; char *annex;
/* skip command character */ /* skip command character */
packet += 20; packet += 20;
if (decode_xfer_read(packet, &annex, &offset, &length) < 0) if (decode_xfer_read(packet, &annex, &offset, &length) < 0)
{ {
gdb_send_error(connection, 01); gdb_send_error(connection, 01);
return ERROR_OK; return ERROR_OK;
} }
if (strcmp(annex, "target.xml") != 0) if (strcmp(annex, "target.xml") != 0)
{ {
gdb_send_error(connection, 01); gdb_send_error(connection, 01);
return ERROR_OK; return ERROR_OK;
} }
xml_printf(&retval, &xml, &pos, &size, \ xml_printf(&retval, &xml, &pos, &size, \
"l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n"); "l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n");
if (retval != ERROR_OK) if (retval != ERROR_OK)
{ {
gdb_send_error(connection, retval); gdb_send_error(connection, retval);
return retval; return retval;
} }
gdb_put_packet(connection, xml, strlen(xml) + 1); gdb_put_packet(connection, xml, strlen(xml) + 1);
free(xml); free(xml);
return ERROR_OK; return ERROR_OK;
} }
gdb_put_packet(connection, "", 0); gdb_put_packet(connection, "", 0);
return ERROR_OK; return ERROR_OK;
} }
@@ -1649,18 +1649,18 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
int result; int result;


/* if flash programming disabled - send a empty reply */ /* if flash programming disabled - send a empty reply */
if (gdb_flash_program == 0) if (gdb_flash_program == 0)
{ {
gdb_put_packet(connection, "", 0); gdb_put_packet(connection, "", 0);
return ERROR_OK; return ERROR_OK;
} }
if (strstr(packet, "vFlashErase:")) if (strstr(packet, "vFlashErase:"))
{ {
unsigned long addr; unsigned long addr;
unsigned long length; unsigned long length;
char *parse = packet + 12; char *parse = packet + 12;
if (*parse == '\0') if (*parse == '\0')
{ {
@@ -1683,14 +1683,14 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
ERROR("incomplete vFlashErase packet received, dropping connection"); ERROR("incomplete vFlashErase packet received, dropping connection");
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
} }
/* assume all sectors need erasing - stops any problems /* assume all sectors need erasing - stops any problems
* when flash_write is called multiple times */ * when flash_write is called multiple times */
flash_set_dirty(); flash_set_dirty();
/* perform any target specific operations before the erase */ /* perform any target specific operations before the erase */
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_PROGRAM); target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_PROGRAM);
/* perform erase */ /* perform erase */
if ((result = flash_erase_address_range(gdb_service->target, addr, length)) != ERROR_OK) if ((result = flash_erase_address_range(gdb_service->target, addr, length)) != ERROR_OK)
{ {
@@ -1702,7 +1702,7 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
} }
else else
gdb_put_packet(connection, "OK", 2); gdb_put_packet(connection, "OK", 2);
return ERROR_OK; return ERROR_OK;
} }


@@ -1724,7 +1724,7 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
} }
length = packet_size - (parse - packet); length = packet_size - (parse - packet);
/* create a new image if there isn't already one */ /* create a new image if there isn't already one */
if (gdb_connection->vflash_image == NULL) if (gdb_connection->vflash_image == NULL)
{ {
@@ -1758,11 +1758,11 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
DEBUG("wrote %u bytes from vFlash image to flash", written); DEBUG("wrote %u bytes from vFlash image to flash", written);
gdb_put_packet(connection, "OK", 2); gdb_put_packet(connection, "OK", 2);
} }
image_close(gdb_connection->vflash_image); image_close(gdb_connection->vflash_image);
free(gdb_connection->vflash_image); free(gdb_connection->vflash_image);
gdb_connection->vflash_image = NULL; gdb_connection->vflash_image = NULL;
return ERROR_OK; return ERROR_OK;
} }


@@ -1777,30 +1777,30 @@ int gdb_detach(connection_t *connection, target_t *target)
case GDB_DETACH_RESUME: case GDB_DETACH_RESUME:
target->type->resume(target, 1, 0, 1, 0); target->type->resume(target, 1, 0, 1, 0);
break; break;
case GDB_DETACH_RESET: case GDB_DETACH_RESET:
target_process_reset(connection->cmd_ctx); target_process_reset(connection->cmd_ctx);
break; break;
case GDB_DETACH_HALT: case GDB_DETACH_HALT:
target->type->halt(target); target->type->halt(target);
break; break;
case GDB_DETACH_NOTHING: case GDB_DETACH_NOTHING:
break; break;
} }
gdb_put_packet(connection, "OK", 2); gdb_put_packet(connection, "OK", 2);
return ERROR_OK; return ERROR_OK;
} }


static void gdb_log_callback(void *priv, const char *file, int line,
static void gdb_log_callback(void *priv, const char *file, int line,
const char *function, const char *format, va_list args) const char *function, const char *format, va_list args)
{ {
connection_t *connection = priv; connection_t *connection = priv;
gdb_connection_t *gdb_con = connection->priv; gdb_connection_t *gdb_con = connection->priv;
if (gdb_con->busy) if (gdb_con->busy)
{ {
/* do not reply this using the O packet */ /* do not reply this using the O packet */
@@ -1810,9 +1810,9 @@ static void gdb_log_callback(void *priv, const char *file, int line,
char *t = alloc_printf(format, args); char *t = alloc_printf(format, args);
if (t == NULL) if (t == NULL)
return; return;
gdb_output_con(connection, t);
gdb_output_con(connection, t);
free(t); free(t);
} }


@@ -1846,7 +1846,7 @@ int gdb_input_inner(connection_t *connection)
switch (packet[0]) switch (packet[0])
{ {
case 'H': case 'H':
/* Hct... -- set thread
/* Hct... -- set thread
* we don't have threads, send empty reply */ * we don't have threads, send empty reply */
gdb_put_packet(connection, NULL, 0); gdb_put_packet(connection, NULL, 0);
break; break;
@@ -1881,7 +1881,7 @@ int gdb_input_inner(connection_t *connection)
case 'c': case 'c':
case 's': case 's':
{ {
/* We're running/stepping, in which case we can
/* We're running/stepping, in which case we can
* forward log output until the target is halted */ * forward log output until the target is halted */
gdb_connection_t *gdb_con = connection->priv; gdb_connection_t *gdb_con = connection->priv;
gdb_con->frontend_state = TARGET_RUNNING; gdb_con->frontend_state = TARGET_RUNNING;
@@ -2025,7 +2025,7 @@ int handle_gdb_detach_command(struct command_context_s *cmd_ctx, char *cmd, char
return ERROR_OK; return ERROR_OK;
} }
} }
WARNING("invalid gdb_detach configuration directive: %s", args[0]); WARNING("invalid gdb_detach configuration directive: %s", args[0]);
return ERROR_OK; return ERROR_OK;
} }
@@ -2045,7 +2045,7 @@ int handle_gdb_memory_map_command(struct command_context_s *cmd_ctx, char *cmd,
return ERROR_OK; return ERROR_OK;
} }
} }
WARNING("invalid gdb_memory_map configuration directive: %s", args[0]); WARNING("invalid gdb_memory_map configuration directive: %s", args[0]);
return ERROR_OK; return ERROR_OK;
} }
@@ -2065,7 +2065,7 @@ int handle_gdb_flash_program_command(struct command_context_s *cmd_ctx, char *cm
return ERROR_OK; return ERROR_OK;
} }
} }
WARNING("invalid gdb_memory_map configuration directive: %s", args[0]); WARNING("invalid gdb_memory_map configuration directive: %s", args[0]);
return ERROR_OK; return ERROR_OK;
} }
@@ -2085,7 +2085,7 @@ int handle_gdb_report_data_abort_command(struct command_context_s *cmd_ctx, char
return ERROR_OK; return ERROR_OK;
} }
} }
WARNING("invalid gdb_report_data_abort configuration directive: %s", args[0]); WARNING("invalid gdb_report_data_abort configuration directive: %s", args[0]);
return ERROR_OK; return ERROR_OK;
} }


+ 23
- 23
src/target/Makefile.am View File

@@ -1,23 +1,23 @@
if OOCD_TRACE
OOCD_TRACE_FILES = oocd_trace.c
else
OOCD_TRACE_FILES =
endif
INCLUDES = -I$(top_srcdir)/src/gdb -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/xsvf $(all_includes)
METASOURCES = AUTO
AM_CPPFLAGS = -DPKGLIBDIR=\"$(pkglibdir)\" @CPPFLAGS@
noinst_LIBRARIES = libtarget.a
libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \
arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \
arm966e.c arm926ejs.c feroceon.c etb.c xscale.c arm_simulator.c image.c armv7m.c cortex_m3.c cortex_swjdp.c \
etm_dummy.c $(OOCD_TRACE_FILES) target_request.c trace.c
noinst_HEADERS = target.h trace.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \
arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \
arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h image.h armv7m.h cortex_m3.h cortex_swjdp.h \
etm_dummy.h oocd_trace.h target_request.h trace.h
nobase_dist_pkglib_DATA = xscale/debug_handler.bin event/at91eb40a_reset.cfg target/at91eb40a.cfg
if OOCD_TRACE
OOCD_TRACE_FILES = oocd_trace.c
else
OOCD_TRACE_FILES =
endif
INCLUDES = -I$(top_srcdir)/src/gdb -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/xsvf $(all_includes)
METASOURCES = AUTO
AM_CPPFLAGS = -DPKGLIBDIR=\"$(pkglibdir)\" @CPPFLAGS@
noinst_LIBRARIES = libtarget.a
libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \
arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \
arm966e.c arm926ejs.c feroceon.c etb.c xscale.c arm_simulator.c image.c armv7m.c cortex_m3.c cortex_swjdp.c \
etm_dummy.c $(OOCD_TRACE_FILES) target_request.c trace.c
noinst_HEADERS = target.h trace.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \
arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \
arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h image.h armv7m.h cortex_m3.h cortex_swjdp.h \
etm_dummy.h oocd_trace.h target_request.h trace.h
nobase_dist_pkglib_DATA = xscale/debug_handler.bin event/at91eb40a_reset.cfg target/at91eb40a.cfg

+ 8
- 8
src/target/event/at91eb40a_reset.cfg View File

@@ -1,8 +1,8 @@
# Reset script for AT91EB40a
reg cpsr 0x000000D3
mww 0xFFE00020 0x1
mww 0xFFE00024 0x00000000
mww 0xFFE00000 0x01002539
mww 0xFFFFF124 0xFFFFFFFF
mww 0xffff0010 0x100
mww 0xffff0034 0x100
# Reset script for AT91EB40a
reg cpsr 0x000000D3
mww 0xFFE00020 0x1
mww 0xFFE00024 0x00000000
mww 0xFFE00000 0x01002539
mww 0xFFFFF124 0xFFFFFFFF
mww 0xffff0010 0x100
mww 0xffff0034 0x100

+ 34
- 34
src/target/target/at91eb40a.cfg View File

@@ -1,34 +1,34 @@
#Script for AT91EB40a
#Atmel ties SRST & TRST together, at which point it makes
#no sense to use TRST, but use TMS instead.
#
#The annoying thing with tying SRST & TRST together is that
#there is no way to halt the CPU *before and during* the
#SRST reset, which means that the CPU will run a number
#of cycles before it can be halted(as much as milliseconds).
reset_config srst_only srst_pulls_trst
#jtag scan chain
#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
jtag_device 4 0x1 0xf 0xe
#target configuration
#target arm7tdmi <endianness> <reset mode> <chainpos> <variant>
target arm7tdmi little reset_init 0 arm7tdmi-s_r4
# speed up memory downloads
arm7 fast_memory_access enable
arm7_9 dcc_downloads enable
# OpenOCD does not have a flash driver for for AT91FR40162S
target_script 0 reset event/at91eb40a_reset.cfg
# required for usable performance. Used for lots of
# other things than flash programming.
working_area 0 0x00000000 0x20000 nobackup
#force hardware values - we're running out of flash more
#often than not. The user can disable this in his
#subsequent config script.
arm7_9 force_hw_bkpts enable
#Script for AT91EB40a
#Atmel ties SRST & TRST together, at which point it makes
#no sense to use TRST, but use TMS instead.
#
#The annoying thing with tying SRST & TRST together is that
#there is no way to halt the CPU *before and during* the
#SRST reset, which means that the CPU will run a number
#of cycles before it can be halted(as much as milliseconds).
reset_config srst_only srst_pulls_trst
#jtag scan chain
#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
jtag_device 4 0x1 0xf 0xe
#target configuration
#target arm7tdmi <endianness> <reset mode> <chainpos> <variant>
target arm7tdmi little reset_init 0 arm7tdmi-s_r4
# speed up memory downloads
arm7 fast_memory_access enable
arm7_9 dcc_downloads enable
# OpenOCD does not have a flash driver for for AT91FR40162S
target_script 0 reset event/at91eb40a_reset.cfg
# required for usable performance. Used for lots of
# other things than flash programming.
working_area 0 0x00000000 0x20000 nobackup
#force hardware values - we're running out of flash more
#often than not. The user can disable this in his
#subsequent config script.
arm7_9 force_hw_bkpts enable

+ 0
- 0
src/target/xscale/build.sh View File


+ 80
- 80
testing/index.html View File

@@ -1,80 +1,80 @@
<html>
<body>
<h1>Testing</h1>
A test should be done on code committed to svn. Commit, then test. That way
one can know for sure *what* code was actually tested.
<h1>Release procedure</h1>
OpenOCD trunk is work in progress. Expect it to change daily and to have
some work in progress.
<p>
If you need the latest released and tested version, look for binary snapshots of
OpenOCD. Worst case look up the test result table below for the features
that are important to you and extract and build the version that has the right
cocktail of working features for you. You can also work with the community
to address the problems you are seing. Testing work and bug reports are
highly appreciated.
<p>
The OpenOCD community may decide to create release branches. If
this happens, then a branch will be created from OpenOCD trunk. The particular
version to create that branch might be an older version rather than the latest
and greatest. Fixes are then ported to that release branch from OpenOCD trunk.
<h2>Vocabulary</h2>
<table border=1>
<tr><td>Passed version</td><td>The latest version on which the test is known to pass</td></tr>
<tr><td>Broken version</td><td>The latest version on which the test is known to fail. n/a when older than passed version.</td></tr>
<tr><td>ID</td><td>A unqiue ID to refer to a test. The unique numbers are maintained in this file.</td></tr>
</table>
<h1>OpenOCD test results</h1>
These tests can be performed on any JTAG device as long
as they are executed using the unmodified code from SVN.
<p>
The latest version in which the test is known to have
passed is in the table below.
<table border=1>
<tr><th>ID</th><th>Synopsis</th><th>Passed version</th><th>Broken version</th></tr>
<tr><td>ocd1</td><td>Telnet Windows</td><td>291</td><td>n/a</td></tr>
<tr><td>ocd2</td><td>Telnet Linux</td><td>291</td><td>n/a</td></tr>
<tr><td>ocd3</td><td>Telnet Cygwin</td><td>291</td><td>n/a</td></tr>
<tr><td><a href="#test_ocd4">ocd4</a></td><td>ARM7 debugging</td><td>291</td></tr>
<tr><td>xscale1</a></td><td>XScale debugging</td><td>291</td></tr>
<tr><td>xscale2</a></td><td>XScale MMU</td><td>291</td></tr>
</table>
<h1>OpenOCD JTAG device test results</h1>
Each JTAG device must be tested
<table border=1>
<tr><th>ID</th><th>Synopsis</th><th>Passed version</th><th>Broken version</th></tr>
<tr><td>jtag1</td><td>Wiggler</td><td>291</td><td>n/a</td></tr>
<tr><td>jtag2</td><td>Parport</td><td>291</td><td>n/a</td></tr>
<tr><td>jtag3</td><td>...</td><td>291</td><td>n/a</td></tr>
</table>
<h1>Policy on removing features from OpenOCD</h1>
If a feature in OpenOCD is known to be broken and nobody has
submitted a fix and the feature is causing trouble for
maintainence, it can be removed from OpenOCD trunk. The threshold
for temporarily removing something from OpenOCD trunk is low to
ease maintainence and place the burden of maintainence on
those that care about a feature.
<p>
Note that code is never deleted from OpenOCD svn, it remains
in svn so if somebody sees a feature removed that they would
like kept, they have but to port and fix that feature
back up to main trunk. This document can be helpful in this
regard in that the latest working version and the known broken
version may be listed.
<h1>Policy on adding features from OpenOCD</h1>
To add a feature to OpenOCD, generally it should not break any existing
features and it should be functional and the code reasonably readable
and useful to others in the OpenOCD community. The code does not
have to be completed. Work in progress is fine for OpenOCD trunk.
<p>
Also new tests should be defined. Note that the code does not have
to pass all the tests. In fact it can be helpful to have tests
to describe facets that really should be working, but aren't
done yet.
<a name="test_ocd4">
<h1>ocd4 - ARM7 debugging</h1>
Connect to ARM7 device(any), use GDB load to load a program into RAM and single halt, resume and single step.
</body>
</html>
<html>
<body>
<h1>Testing</h1>
A test should be done on code committed to svn. Commit, then test. That way
one can know for sure *what* code was actually tested.
<h1>Release procedure</h1>
OpenOCD trunk is work in progress. Expect it to change daily and to have
some work in progress.
<p>
If you need the latest released and tested version, look for binary snapshots of
OpenOCD. Worst case look up the test result table below for the features
that are important to you and extract and build the version that has the right
cocktail of working features for you. You can also work with the community
to address the problems you are seing. Testing work and bug reports are
highly appreciated.
<p>
The OpenOCD community may decide to create release branches. If
this happens, then a branch will be created from OpenOCD trunk. The particular
version to create that branch might be an older version rather than the latest
and greatest. Fixes are then ported to that release branch from OpenOCD trunk.
<h2>Vocabulary</h2>
<table border=1>
<tr><td>Passed version</td><td>The latest version on which the test is known to pass</td></tr>
<tr><td>Broken version</td><td>The latest version on which the test is known to fail. n/a when older than passed version.</td></tr>
<tr><td>ID</td><td>A unqiue ID to refer to a test. The unique numbers are maintained in this file.</td></tr>
</table>
<h1>OpenOCD test results</h1>
These tests can be performed on any JTAG device as long
as they are executed using the unmodified code from SVN.
<p>
The latest version in which the test is known to have
passed is in the table below.
<table border=1>
<tr><th>ID</th><th>Synopsis</th><th>Passed version</th><th>Broken version</th></tr>
<tr><td>ocd1</td><td>Telnet Windows</td><td>291</td><td>n/a</td></tr>
<tr><td>ocd2</td><td>Telnet Linux</td><td>291</td><td>n/a</td></tr>
<tr><td>ocd3</td><td>Telnet Cygwin</td><td>291</td><td>n/a</td></tr>
<tr><td><a href="#test_ocd4">ocd4</a></td><td>ARM7 debugging</td><td>291</td></tr>
<tr><td>xscale1</a></td><td>XScale debugging</td><td>291</td></tr>
<tr><td>xscale2</a></td><td>XScale MMU</td><td>291</td></tr>
</table>
<h1>OpenOCD JTAG device test results</h1>
Each JTAG device must be tested
<table border=1>
<tr><th>ID</th><th>Synopsis</th><th>Passed version</th><th>Broken version</th></tr>
<tr><td>jtag1</td><td>Wiggler</td><td>291</td><td>n/a</td></tr>
<tr><td>jtag2</td><td>Parport</td><td>291</td><td>n/a</td></tr>
<tr><td>jtag3</td><td>...</td><td>291</td><td>n/a</td></tr>
</table>
<h1>Policy on removing features from OpenOCD</h1>
If a feature in OpenOCD is known to be broken and nobody has
submitted a fix and the feature is causing trouble for
maintainence, it can be removed from OpenOCD trunk. The threshold
for temporarily removing something from OpenOCD trunk is low to
ease maintainence and place the burden of maintainence on
those that care about a feature.
<p>
Note that code is never deleted from OpenOCD svn, it remains
in svn so if somebody sees a feature removed that they would
like kept, they have but to port and fix that feature
back up to main trunk. This document can be helpful in this
regard in that the latest working version and the known broken
version may be listed.
<h1>Policy on adding features from OpenOCD</h1>
To add a feature to OpenOCD, generally it should not break any existing
features and it should be functional and the code reasonably readable
and useful to others in the OpenOCD community. The code does not
have to be completed. Work in progress is fine for OpenOCD trunk.
<p>
Also new tests should be defined. Note that the code does not have
to pass all the tests. In fact it can be helpful to have tests
to describe facets that really should be working, but aren't
done yet.
<a name="test_ocd4">
<h1>ocd4 - ARM7 debugging</h1>
Connect to ARM7 device(any), use GDB load to load a program into RAM and single halt, resume and single step.
</body>
</html>

Loading…
Cancel
Save