- 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 |
@@ -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 stm32x_flash; | |||
extern flash_driver_t tms470_flash; | |||
extern flash_driver_t ecosflash_flash; | |||
extern flash_driver_t ecosflash_flash; | |||
flash_driver_t *flash_drivers[] = | |||
{ | |||
@@ -77,7 +77,7 @@ flash_driver_t *flash_drivers[] = | |||
&str9xpec_flash, | |||
&stm32x_flash, | |||
&tms470_flash, | |||
&ecosflash_flash, | |||
&ecosflash_flash, | |||
NULL, | |||
}; | |||
@@ -115,7 +115,7 @@ static int flash_driver_erase(struct flash_bank_s *bank, int first, int last) | |||
{ | |||
ERROR("invalid flash sector"); | |||
retval=ERROR_FLASH_SECTOR_INVALID; | |||
} else | |||
} else | |||
{ | |||
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"); | |||
retval=ERROR_FLASH_SECTOR_INVALID; | |||
} else | |||
} else | |||
{ | |||
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) | |||
{ | |||
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, "auto_erase", handle_flash_auto_erase_command, COMMAND_ANY, | |||
"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, | |||
"set protection of sectors at <bank> <first> <last> <on|off>"); | |||
} | |||
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); | |||
int retval; | |||
if (p == NULL) | |||
return NULL; | |||
retval = p->driver->auto_probe(p); | |||
if (retval != ERROR_OK) | |||
{ | |||
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 found = 0; | |||
target_t *target; | |||
if (argc < 6) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
if ((target = get_target_by_num(strtoul(args[5], NULL, 0))) == NULL) | |||
{ | |||
ERROR("target %lu not defined", strtoul(args[5], NULL, 0)); | |||
return ERROR_OK; | |||
} | |||
for (i = 0; flash_drivers[i]; i++) | |||
{ | |||
if (strcmp(args[0], flash_drivers[i]->name) == 0) | |||
{ | |||
flash_bank_t *p, *c; | |||
/* register flash specific commands */ | |||
if (flash_drivers[i]->register_commands(cmd_ctx) != ERROR_OK) | |||
{ | |||
ERROR("couldn't register '%s' commands", args[0]); | |||
exit(-1); | |||
} | |||
c = malloc(sizeof(flash_bank_t)); | |||
c->target = target; | |||
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->sectors = NULL; | |||
c->next = NULL; | |||
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); | |||
free(c); | |||
return ERROR_OK; | |||
} | |||
/* put flash bank in linked list */ | |||
if (flash_banks) | |||
{ | |||
@@ -283,18 +283,18 @@ int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char | |||
{ | |||
flash_banks = c; | |||
} | |||
found = 1; | |||
} | |||
} | |||
/* no matching flash driver found */ | |||
if (!found) | |||
{ | |||
ERROR("flash driver '%s' not found", args[0]); | |||
exit(-1); | |||
} | |||
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; | |||
int i = 0; | |||
if (!flash_banks) | |||
{ | |||
command_print(cmd_ctx, "no flash banks configured"); | |||
return ERROR_OK; | |||
} | |||
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", | |||
i++, p->driver->name, p->base, p->size, p->bus_width, p->chip_width); | |||
} | |||
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; | |||
int i = 0; | |||
int j = 0; | |||
if (argc != 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
for (p = flash_banks; p; p = p->next, i++) | |||
{ | |||
if (i == strtoul(args[0], NULL, 0)) | |||
{ | |||
char buf[1024]; | |||
/* attempt auto probe */ | |||
p->driver->auto_probe(p); | |||
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); | |||
for (j = 0; j < p->num_sectors; j++) | |||
{ | |||
char *erase_state, *protect_state; | |||
if (p->sectors[j].is_erased == 0) | |||
erase_state = "not erased"; | |||
else if (p->sectors[j].is_erased == 1) | |||
erase_state = "erased"; | |||
else | |||
erase_state = "erase state unknown"; | |||
if (p->sectors[j].is_protected == 0) | |||
protect_state = "not protected"; | |||
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, | |||
erase_state, protect_state); | |||
} | |||
p->driver->info(p, buf, 1024); | |||
command_print(cmd_ctx, "%s", buf); | |||
} | |||
} | |||
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; | |||
int retval; | |||
if (argc != 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
p = get_flash_bank_by_num_noprobe(strtoul(args[0], NULL, 0)); | |||
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]); | |||
} | |||
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; | |||
int retval; | |||
if (argc != 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); | |||
if (p) | |||
{ | |||
@@ -430,7 +430,7 @@ int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cm | |||
args[0], p->base); | |||
} | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -442,14 +442,14 @@ int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char * | |||
int length; | |||
duration_t duration; | |||
char *duration_text; | |||
target_t *target = get_current_target(cmd_ctx); | |||
if (argc != 2) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
address = strtoul(args[0], NULL, 0); | |||
length = strtoul(args[1], NULL, 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; | |||
} | |||
/* We can't know if we did a resume + halt, in which case we no longer know the erased state */ | |||
flash_set_dirty(); | |||
duration_start_measure(&duration); | |||
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); | |||
free(duration_text); | |||
} | |||
return retval; | |||
} | |||
@@ -483,12 +483,12 @@ int handle_flash_protect_check_command(struct command_context_s *cmd_ctx, char * | |||
{ | |||
flash_bank_t *p; | |||
int retval; | |||
if (argc != 1) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); | |||
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_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)); | |||
duration_t duration; | |||
char *duration_text; | |||
duration_start_measure(&duration); | |||
if (!p) | |||
{ | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
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); | |||
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]); | |||
return ERROR_OK; | |||
} | |||
if (strcmp(args[3], "on") == 0) | |||
set = 1; | |||
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; | |||
} | |||
retval = flash_driver_protect(p, set, first, last); | |||
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) | |||
{ | |||
target_t *target = get_current_target(cmd_ctx); | |||
image_t image; | |||
u32 written; | |||
duration_t duration; | |||
char *duration_text; | |||
int retval; | |||
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; | |||
} | |||
if (!target) | |||
{ | |||
ERROR("no target selected"); | |||
return ERROR_OK; | |||
} | |||
duration_start_measure(&duration); | |||
if (argc >= 2) | |||
{ | |||
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 = 0x0; | |||
} | |||
image.start_address_set = 0; | |||
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); | |||
return retval; | |||
} | |||
retval = flash_write(target, &image, &written, auto_erase); | |||
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); | |||
return retval; | |||
} | |||
duration_stop_measure(&duration, &duration_text); | |||
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); | |||
image_close(&image); | |||
return retval; | |||
} | |||
@@ -661,10 +661,10 @@ int handle_flash_write_bank_command(struct command_context_s *cmd_ctx, char *cmd | |||
u32 buf_cnt; | |||
fileio_t fileio; | |||
duration_t duration; | |||
char *duration_text; | |||
int retval; | |||
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; | |||
} | |||
duration_start_measure(&duration); | |||
offset = strtoul(args[2], NULL, 0); | |||
p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); | |||
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]); | |||
return 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); | |||
return ERROR_OK; | |||
} | |||
buffer = malloc(fileio.size); | |||
if (fileio_read(&fileio, fileio.size, buffer, &buf_cnt) != ERROR_OK) | |||
{ | |||
command_print(cmd_ctx, "flash write_binary error: %s", fileio.error_str); | |||
return ERROR_OK; | |||
} | |||
retval = flash_driver_write(p, buffer, offset, buf_cnt); | |||
free(buffer); | |||
duration_stop_measure(&duration, &duration_text); | |||
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); | |||
fileio_close(&fileio); | |||
return retval; | |||
} | |||
@@ -718,13 +718,13 @@ void flash_set_dirty(void) | |||
{ | |||
flash_bank_t *c; | |||
int i; | |||
/* set all flash to require erasing */ | |||
for (c = flash_banks; c; c = c->next) | |||
{ | |||
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; | |||
retval = c->driver->auto_probe(c); | |||
if (retval != ERROR_OK) | |||
{ | |||
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 last = -1; | |||
int i; | |||
if ((c = get_flash_bank_by_addr(target, addr)) == NULL) | |||
return ERROR_FLASH_DST_OUT_OF_BANK; /* no corresponding bank found */ | |||
if (c->size == 0 || c->num_sectors == 0) | |||
return ERROR_FLASH_BANK_INVALID; | |||
if (length == 0) | |||
{ | |||
/* special case, erase whole bank when length is zero */ | |||
if (addr != c->base) | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
return flash_driver_erase(c, 0, c->num_sectors - 1); | |||
} | |||
/* check whether it fits */ | |||
if (addr + length > c->base + c->size) | |||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; | |||
addr -= c->base; | |||
for (i = 0; i < c->num_sectors; i++) | |||
{ | |||
{ | |||
/* 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 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 */ | |||
} | |||
} | |||
if( first == -1 || last == -1 ) | |||
return ERROR_OK; | |||
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; | |||
u32 section_offset; | |||
flash_bank_t *c; | |||
section = 0; | |||
section_offset = 0; | |||
if (written) | |||
*written = 0; | |||
if (erase) | |||
{ | |||
/* assume all sectors need erasing - stops any problems | |||
* when flash_write is called multiple times */ | |||
flash_set_dirty(); | |||
} | |||
/* loop until we reach end of the image */ | |||
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) | |||
{ | |||
u32 size_read; | |||
if (buffer_size - run_size <= image->sections[section].size - section_offset) | |||
size_read = buffer_size - run_size; | |||
else | |||
size_read = image->sections[section].size - section_offset; | |||
if ((retval = image_read_section(image, section, section_offset, | |||
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0) | |||
{ | |||
free(buffer); | |||
return retval; | |||
} | |||
@@ -901,19 +901,19 @@ int flash_write(target_t *target, image_t *image, u32 *written, int erase) | |||
} | |||
retval = ERROR_OK; | |||
if (erase) | |||
{ | |||
/* calculate and erase sectors */ | |||
retval = flash_erase_address_range( target, run_address, run_size ); | |||
} | |||
if (retval == ERROR_OK) | |||
{ | |||
/* write flash sectors */ | |||
retval = flash_driver_write(c, buffer, run_address - c->base, run_size); | |||
} | |||
free(buffer); | |||
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; | |||
} | |||
if (strcmp(args[0], "on") == 0) | |||
auto_erase = 1; | |||
else if (strcmp(args[0], "off") == 0) | |||
auto_erase = 0; | |||
else | |||
else | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
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) | |||
{ | |||
/* 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 | |||
{ | |||
@@ -80,7 +80,7 @@ static void log_printfv(enum log_levels level, const char *file, int line, const | |||
} | |||
fflush(log_output); | |||
/* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */ | |||
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); | |||
log_printfv(level, file, line, function, format, args); | |||
va_end(args); | |||
} | |||
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++; | |||
if (level > debug_level) | |||
return; | |||
char *t=malloc(strlen(format)+2); | |||
strcpy(t, format); | |||
strcat(t, "\n"); | |||
va_list args; | |||
va_start(args, format); | |||
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) | |||
{ | |||
FILE* file = fopen(args[0], "w"); | |||
if (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 */ | |||
if (debug_level == -1) | |||
debug_level = LOG_INFO; | |||
if (log_output == NULL) | |||
{ | |||
log_output = stderr; | |||
} | |||
return ERROR_OK; | |||
} | |||
int set_log_output(struct command_context_s *cmd_ctx, FILE *output) | |||
{ | |||
log_output = output; | |||
@@ -236,7 +236,7 @@ int log_remove_callback(log_callback_fn fn, void *priv) | |||
char *alloc_printf(const char *fmt, va_list ap) | |||
{ | |||
char *string = NULL; | |||
/* start by 0 to exercise all the code paths. Need minimum 2 bytes to | |||
* fit 1 char and 0 terminator. */ | |||
int size = 0; | |||
@@ -255,7 +255,7 @@ char *alloc_printf(const char *fmt, va_list ap) | |||
return NULL; | |||
} | |||
} | |||
int ret; | |||
ret = vsnprintf(string, size, fmt, ap); | |||
/* NB! The result of the vsnprintf() might be an *EMPTY* string! */ | |||
@@ -46,7 +46,7 @@ | |||
static unsigned short gdb_port; | |||
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); | |||
enum gdb_detach_mode | |||
@@ -120,10 +120,10 @@ int gdb_get_char(connection_t *connection, int* next_char) | |||
*/ | |||
struct timeval tv; | |||
fd_set read_fds; | |||
FD_ZERO(&read_fds); | |||
FD_SET(connection->fd, &read_fds); | |||
tv.tv_sec = 1; | |||
tv.tv_usec = 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 | |||
* before printing any progress messages | |||
*/ | |||
return ERROR_GDB_TIMEOUT; | |||
return ERROR_GDB_TIMEOUT; | |||
} | |||
#endif | |||
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) | |||
connection->input_pending = 1; | |||
else | |||
connection->input_pending = 0; | |||
connection->input_pending = 0; | |||
#ifdef _DEBUG_GDB_IO_ | |||
DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); | |||
#endif | |||
@@ -211,7 +211,7 @@ int gdb_putback_char(connection_t *connection, int last_char) | |||
} | |||
else | |||
{ | |||
ERROR("BUG: couldn't put character back"); | |||
ERROR("BUG: couldn't put character back"); | |||
} | |||
return ERROR_OK; | |||
@@ -263,9 +263,9 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len) | |||
if (len > 0) | |||
gdb_write(connection, buffer, len); | |||
gdb_write(connection, "#", 1); | |||
snprintf(checksum, 3, "%2.2x", my_checksum); | |||
gdb_write(connection, checksum, 2); | |||
#else | |||
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 + 1] = DIGITS[(my_checksum >> 4) & 0xf]; | |||
t[1 + len + 2] = DIGITS[my_checksum & 0xf]; | |||
gdb_write(connection, t, totalLen); | |||
if (allocated) | |||
{ | |||
free(allocated); | |||
@@ -387,21 +387,21 @@ int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len) | |||
} while (character != '$'); | |||
my_checksum = 0; | |||
count = 0; | |||
gdb_connection_t *gdb_con = connection->priv; | |||
for (;;) | |||
{ | |||
/* 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 | |||
* 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)) | |||
{ | |||
/* The compiler will struggle a bit with constant propagation and | |||
* aliasing, so we help it by showing that these values do not | |||
* change inside the loop | |||
*/ | |||
* change inside the loop | |||
*/ | |||
int i; | |||
char *buf = gdb_con->buf_p; | |||
int run = gdb_con->buf_cnt - 2; | |||
@@ -413,13 +413,13 @@ int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len) | |||
i++; | |||
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. | |||
*/ | |||
done = 1; | |||
break; | |||
} | |||
if (character == '}') | |||
{ | |||
/* 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_cnt -= i; | |||
if (done) | |||
if (done) | |||
break; | |||
} | |||
} | |||
if (count > *len) | |||
{ | |||
ERROR("packet buffer too small"); | |||
return ERROR_GDB_BUFFER_TOO_SMALL; | |||
} | |||
if ((retval = gdb_get_char(connection, &character)) != ERROR_OK) | |||
return retval; | |||
@@ -503,7 +503,7 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len) | |||
gdb_con->busy = 0; | |||
return retval; | |||
} | |||
int gdb_output_con(connection_t *connection, char* line) | |||
{ | |||
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) | |||
{ | |||
/* 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; | |||
} | |||
@@ -535,7 +535,7 @@ int gdb_program_handler(struct target_s *target, enum target_event event, void * | |||
{ | |||
FILE *script; | |||
struct command_context_s *cmd_ctx = priv; | |||
if (target->gdb_program_script) | |||
{ | |||
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); | |||
command_run_file(cmd_ctx, script, COMMAND_EXEC); | |||
fclose(script); | |||
jtag_execute_queue(); | |||
} | |||
return ERROR_OK; | |||
} | |||
@@ -566,10 +566,10 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event | |||
{ | |||
case TARGET_EVENT_HALTED: | |||
/* 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 | |||
* step or continue packet. | |||
* | |||
* | |||
* Executing monitor commands can bring the target in and | |||
* out of the running state so we'll see lots of TARGET_EVENT_XXX | |||
* 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! */ | |||
log_remove_callback(gdb_log_callback, connection); | |||
if (gdb_connection->ctrl_c) | |||
{ | |||
signal = 0x2; | |||
@@ -603,8 +603,8 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event | |||
return ERROR_OK; | |||
} | |||
int gdb_new_connection(connection_t *connection) | |||
{ | |||
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->closed = 0; | |||
gdb_connection->busy = 0; | |||
/* output goes through gdb connection */ | |||
command_set_output_handler(connection->cmd_ctx, gdb_output, connection); | |||
/* 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 */ | |||
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 */ | |||
delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target); | |||
if (connection->priv) | |||
{ | |||
free(connection->priv); | |||
@@ -712,7 +712,7 @@ void gdb_str_to_target(target_t *target, char *tstr, reg_t *reg) | |||
u8 *buf; | |||
int buf_len; | |||
buf = reg->value; | |||
buf_len = CEIL(reg->size, 8); | |||
buf_len = CEIL(reg->size, 8); | |||
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+1] = DIGITS[buf[i]&0xf]; | |||
} | |||
} | |||
} | |||
} | |||
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]; | |||
} | |||
} | |||
} | |||
} | |||
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)); | |||
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); | |||
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); | |||
/* advance packet pointer */ | |||
/* advance packet pointer */ | |||
packet_p += (CEIL(reg_list[i]->size, 8) * 2); | |||
free(bin_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); | |||
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)); | |||
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); | |||
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, | |||
* because GDB breaks up large memory reads into smaller reads. | |||
* | |||
* | |||
* 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) | |||
@@ -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. | |||
* 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 | |||
* gained by involving the user in this problem that hopefully will get resolved | |||
* eventually | |||
* | |||
* | |||
* 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. | |||
@@ -1157,7 +1157,7 @@ int gdb_write_memory_packet(connection_t *connection, target_t *target, char *pa | |||
else | |||
{ | |||
if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK) | |||
return retval; | |||
return retval; | |||
} | |||
free(buffer); | |||
@@ -1207,7 +1207,7 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c | |||
else | |||
{ | |||
if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK) | |||
return retval; | |||
return retval; | |||
} | |||
return ERROR_OK; | |||
@@ -1362,14 +1362,14 @@ void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, . | |||
return; | |||
} | |||
int first = 1; | |||
for (;;) | |||
{ | |||
if ((*xml == NULL) || (!first)) | |||
{ | |||
/* start by 0 to exercise all the code paths. | |||
* Need minimum 2 bytes to fit 1 char and 0 terminator. */ | |||
*size = *size * 2 + 2; | |||
char *t = *xml; | |||
*xml = realloc(*xml, *size); | |||
@@ -1381,7 +1381,7 @@ void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, . | |||
return; | |||
} | |||
} | |||
va_list ap; | |||
int ret; | |||
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) | |||
{ | |||
char *separator; | |||
/* Extract and NUL-terminate the annex. */ | |||
*annex = 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') | |||
return -1; | |||
*buf++ = 0; | |||
/* After the read marker and annex, qXfer looks like a | |||
* traditional 'm' packet. */ | |||
*ofs = strtoul(buf, &separator, 16); | |||
if (*separator != ',') | |||
return -1; | |||
*len = strtoul(separator+1, NULL, 16); | |||
return 0; | |||
} | |||
@@ -1426,22 +1426,22 @@ int gdb_calc_blocksize(flash_bank_t *bank) | |||
{ | |||
int i; | |||
int block_size = 0xffffffff; | |||
/* loop through all sectors and return smallest sector size */ | |||
for (i = 0; i < bank->num_sectors; i++) | |||
{ | |||
if (bank->sectors[i].size < block_size) | |||
block_size = bank->sectors[i].size; | |||
} | |||
return block_size; | |||
} | |||
int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size) | |||
{ | |||
command_context_t *cmd_ctx = connection->cmd_ctx; | |||
if (strstr(packet, "qRcmd,")) | |||
{ | |||
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[(packet_size - 6)/2] = 0x0; | |||
/* We want to print all debug output to GDB connection */ | |||
log_add_callback(gdb_log_callback, connection); | |||
target_call_timer_callbacks(); | |||
@@ -1476,22 +1476,22 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i | |||
u32 checksum; | |||
u32 addr = 0; | |||
u32 len = 0; | |||
/* skip command character */ | |||
packet += 5; | |||
addr = strtoul(packet, &separator, 16); | |||
if (*separator != ',') | |||
{ | |||
ERROR("incomplete read memory packet received, dropping connection"); | |||
return ERROR_SERVER_REMOTE_CLOSED; | |||
} | |||
len = strtoul(separator + 1, NULL, 16); | |||
retval = target_checksum_memory(target, addr, len, &checksum); | |||
if (retval == ERROR_OK) | |||
{ | |||
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 | |||
{ | |||
if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK) | |||
return retval; | |||
return retval; | |||
} | |||
return ERROR_OK; | |||
} | |||
} | |||
@@ -1515,66 +1515,66 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i | |||
int pos = 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-", | |||
(GDB_BUFFER_SIZE - 1), gdb_use_memory_map == 1 ? '+' : '-'); | |||
if (retval != ERROR_OK) | |||
{ | |||
gdb_send_error(connection, 01); | |||
return ERROR_OK; | |||
} | |||
gdb_put_packet(connection, buffer, strlen(buffer)); | |||
free(buffer); | |||
return ERROR_OK; | |||
} | |||
else if (strstr(packet, "qXfer:memory-map:read::")) | |||
{ | |||
/* 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). | |||
* Normally we only execute this code once, but no big deal if we | |||
* have to regenerate it a couple of times. */ | |||
flash_bank_t *p; | |||
char *xml = NULL; | |||
int size = 0; | |||
int pos = 0; | |||
int retval = ERROR_OK; | |||
int offset; | |||
int length; | |||
char *separator; | |||
int blocksize; | |||
/* skip command character */ | |||
packet += 23; | |||
offset = strtoul(packet, &separator, 16); | |||
length = strtoul(separator + 1, &separator, 16); | |||
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n"); | |||
int i = 0; | |||
for (;;) | |||
{ | |||
p = get_flash_bank_by_num(i); | |||
if (p == NULL) | |||
break; | |||
/* if device has uneven sector sizes, eg. str7, lpc | |||
* we pass the smallest sector size to gdb memory map */ | |||
blocksize = gdb_calc_blocksize(p); | |||
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \ | |||
"<property name=\"blocksize\">0x%x</property>\n" \ | |||
"</memory>\n", \ | |||
p->base, p->size, blocksize); | |||
i++; | |||
} | |||
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n"); | |||
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); | |||
return retval; | |||
} | |||
if (offset + length > pos) | |||
{ | |||
length = pos - offset; | |||
@@ -1592,52 +1592,52 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i | |||
t[0] = 'l'; | |||
memcpy(t + 1, xml + offset, length); | |||
gdb_put_packet(connection, t, length + 1); | |||
free(t); | |||
free(xml); | |||
return ERROR_OK; | |||
} | |||
else if (strstr(packet, "qXfer:features:read:")) | |||
{ | |||
{ | |||
char *xml = NULL; | |||
int size = 0; | |||
int pos = 0; | |||
int retval = ERROR_OK; | |||
int offset; | |||
unsigned int length; | |||
char *annex; | |||
/* skip command character */ | |||
packet += 20; | |||
if (decode_xfer_read(packet, &annex, &offset, &length) < 0) | |||
{ | |||
gdb_send_error(connection, 01); | |||
return ERROR_OK; | |||
} | |||
if (strcmp(annex, "target.xml") != 0) | |||
{ | |||
gdb_send_error(connection, 01); | |||
return ERROR_OK; | |||
} | |||
xml_printf(&retval, &xml, &pos, &size, \ | |||
"l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n"); | |||
if (retval != ERROR_OK) | |||
{ | |||
gdb_send_error(connection, retval); | |||
return retval; | |||
} | |||
gdb_put_packet(connection, xml, strlen(xml) + 1); | |||
free(xml); | |||
return ERROR_OK; | |||
} | |||
gdb_put_packet(connection, "", 0); | |||
return ERROR_OK; | |||
} | |||
@@ -1649,18 +1649,18 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p | |||
int result; | |||
/* if flash programming disabled - send a empty reply */ | |||
if (gdb_flash_program == 0) | |||
{ | |||
gdb_put_packet(connection, "", 0); | |||
return ERROR_OK; | |||
} | |||
if (strstr(packet, "vFlashErase:")) | |||
{ | |||
unsigned long addr; | |||
unsigned long length; | |||
char *parse = packet + 12; | |||
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"); | |||
return ERROR_SERVER_REMOTE_CLOSED; | |||
} | |||
/* assume all sectors need erasing - stops any problems | |||
* when flash_write is called multiple times */ | |||
flash_set_dirty(); | |||
/* perform any target specific operations before the erase */ | |||
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_PROGRAM); | |||
/* perform erase */ | |||
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 | |||
gdb_put_packet(connection, "OK", 2); | |||
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; | |||
} | |||
length = packet_size - (parse - packet); | |||
/* create a new image if there isn't already one */ | |||
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); | |||
gdb_put_packet(connection, "OK", 2); | |||
} | |||
image_close(gdb_connection->vflash_image); | |||
free(gdb_connection->vflash_image); | |||
gdb_connection->vflash_image = NULL; | |||
return ERROR_OK; | |||
} | |||
@@ -1777,30 +1777,30 @@ int gdb_detach(connection_t *connection, target_t *target) | |||
case GDB_DETACH_RESUME: | |||
target->type->resume(target, 1, 0, 1, 0); | |||
break; | |||
case GDB_DETACH_RESET: | |||
target_process_reset(connection->cmd_ctx); | |||
break; | |||
case GDB_DETACH_HALT: | |||
target->type->halt(target); | |||
break; | |||
case GDB_DETACH_NOTHING: | |||
break; | |||
} | |||
gdb_put_packet(connection, "OK", 2); | |||
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) | |||
{ | |||
connection_t *connection = priv; | |||
gdb_connection_t *gdb_con = connection->priv; | |||
if (gdb_con->busy) | |||
{ | |||
/* 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); | |||
if (t == NULL) | |||
return; | |||
gdb_output_con(connection, t); | |||
gdb_output_con(connection, t); | |||
free(t); | |||
} | |||
@@ -1846,7 +1846,7 @@ int gdb_input_inner(connection_t *connection) | |||
switch (packet[0]) | |||
{ | |||
case 'H': | |||
/* Hct... -- set thread | |||
/* Hct... -- set thread | |||
* we don't have threads, send empty reply */ | |||
gdb_put_packet(connection, NULL, 0); | |||
break; | |||
@@ -1881,7 +1881,7 @@ int gdb_input_inner(connection_t *connection) | |||
case 'c': | |||
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 */ | |||
gdb_connection_t *gdb_con = connection->priv; | |||
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; | |||
} | |||
} | |||
WARNING("invalid gdb_detach configuration directive: %s", args[0]); | |||
return ERROR_OK; | |||
} | |||
@@ -2045,7 +2045,7 @@ int handle_gdb_memory_map_command(struct command_context_s *cmd_ctx, char *cmd, | |||
return ERROR_OK; | |||
} | |||
} | |||
WARNING("invalid gdb_memory_map configuration directive: %s", args[0]); | |||
return ERROR_OK; | |||
} | |||
@@ -2065,7 +2065,7 @@ int handle_gdb_flash_program_command(struct command_context_s *cmd_ctx, char *cm | |||
return ERROR_OK; | |||
} | |||
} | |||
WARNING("invalid gdb_memory_map configuration directive: %s", args[0]); | |||
return ERROR_OK; | |||
} | |||
@@ -2085,7 +2085,7 @@ int handle_gdb_report_data_abort_command(struct command_context_s *cmd_ctx, char | |||
return ERROR_OK; | |||
} | |||
} | |||
WARNING("invalid gdb_report_data_abort configuration directive: %s", args[0]); | |||
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> |