- 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-e2dbd0fdcd60tags/v0.1.0
@@ -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. | |||||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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(®_params[0], "r0", 32, PARAM_IN_OUT); | |||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT); | |||||
init_reg_param(®_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(®_params[0]); | |||||
destroy_reg_param(®_params[1]); | |||||
destroy_reg_param(®_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(®_params[0], "r0", 32, PARAM_IN_OUT); | |||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT); | |||||
init_reg_param(®_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(®_params[0]); | |||||
destroy_reg_param(®_params[1]); | |||||
destroy_reg_param(®_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; | |||||
} | |||||
@@ -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; | ||||
} | } |
@@ -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 |
@@ -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! */ | ||||
@@ -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; | ||||
} | } | ||||
@@ -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 | |||||
@@ -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 |
@@ -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 |
@@ -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> |