diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.am | 2 | ||||
| -rw-r--r-- | lib/ccdbg-debug.c | 5 | ||||
| -rw-r--r-- | lib/ccdbg-debug.h | 2 | ||||
| -rw-r--r-- | lib/ccdbg-flash.c | 8 | ||||
| -rw-r--r-- | lib/ccdbg-memory.c | 54 | ||||
| -rw-r--r-- | lib/ccdbg-rom.c | 63 | ||||
| -rw-r--r-- | lib/ccdbg-state.c | 128 | ||||
| -rw-r--r-- | lib/ccdbg.h | 43 | 
8 files changed, 268 insertions, 37 deletions
| diff --git a/lib/Makefile.am b/lib/Makefile.am index 16f5b921..ba6f9725 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -11,5 +11,7 @@ libcc_a_SOURCES = \  	ccdbg-io.c \  	ccdbg-manual.c \  	ccdbg-memory.c \ +	ccdbg-rom.c \ +	ccdbg-state.c \  	cp-usb.c \  	cp-usb-async.c diff --git a/lib/ccdbg-debug.c b/lib/ccdbg-debug.c index 8f6f9e11..847361c7 100644 --- a/lib/ccdbg-debug.c +++ b/lib/ccdbg-debug.c @@ -47,7 +47,8 @@ ccdbg_debug(int level, char *format, ...)  }  void -ccdbg_flush(void) +ccdbg_flush(int level)  { -	fflush(stdout); +	if (ccdbg_level & level) +		fflush(stdout);  } diff --git a/lib/ccdbg-debug.h b/lib/ccdbg-debug.h index a09148d3..0b5b44c1 100644 --- a/lib/ccdbg-debug.h +++ b/lib/ccdbg-debug.h @@ -39,6 +39,6 @@ void  ccdbg_clear_debug(int level);  void -ccdbg_flush(void); +ccdbg_flush(int level);  #endif /* _CCDBG_DEBUG_H_ */ diff --git a/lib/ccdbg-flash.c b/lib/ccdbg-flash.c index 8b3390c7..8a586a21 100644 --- a/lib/ccdbg-flash.c +++ b/lib/ccdbg-flash.c @@ -288,13 +288,14 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)  		ccdbg_debug(CC_DEBUG_FLASH, "Upload %d bytes at 0x%04x\n", this_time, ram_addr);  		ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time); - +#if 0  		ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in ram\n", this_time);  		ccdbg_read_memory(dbg, ram_addr, verify, this_time);  		if (memcmp (image->data + start, verify, this_time) != 0) {  			fprintf(stderr, "ram verify failed\n");  			return 1;  		} +#endif  		flash_addr = image->address + start;  		flash_word_addr = flash_addr >> 1; @@ -324,10 +325,13 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)  		status = ccdbg_resume(dbg);  		for (times = 0; times < 10; times++) {  			status = ccdbg_read_status(dbg); -			ccdbg_debug(CC_DEBUG_FLASH, "chip status is 0x%02x\n", status); +			ccdbg_debug(CC_DEBUG_FLASH, "."); +			ccdbg_flush(CC_DEBUG_FLASH);  			if ((status & CC_STATUS_CPU_HALTED) != 0)  				break; +			usleep(10000);  		} +		ccdbg_debug(CC_DEBUG_FLASH, "\n");  		if (times == 10) {  			fprintf(stderr, "flash page timed out\n");  			return 1; diff --git a/lib/ccdbg-memory.c b/lib/ccdbg-memory.c index d74726fb..20a24799 100644 --- a/lib/ccdbg-memory.c +++ b/lib/ccdbg-memory.c @@ -23,14 +23,9 @@   */  static uint8_t	memory_init[] = { -	2,	MOV_direct_A,		0x7f, -	3,	MOV_direct1_direct2,	0x7e, SFR_DPL0, -	3,	MOV_direct1_direct2,	0x7d, SFR_DPH0, -	3,	MOV_direct1_direct2,	0x7c, SFR_DPL1, -	3,	MOV_direct1_direct2,	0x7b, SFR_DPH1,  	3,	MOV_DPTR_data16,	0,	0, -#define HIGH_START	21 -#define LOW_START	22 +#define HIGH_START	2 +#define LOW_START	3  	0,  }; @@ -49,19 +44,13 @@ static uint8_t read8[] = {  	0,  }; -static uint8_t	memory_fini[] = { -	2,	MOV_A_direct,		0x7f, -	3,	MOV_direct1_direct2,	SFR_DPL0, 0x7e, -	3,	MOV_direct1_direct2,	SFR_DPH0, 0x7d, -	3,	MOV_direct1_direct2,	SFR_DPL1, 0x7c, -	3,	MOV_direct1_direct2,	SFR_DPH1, 0x7b, -	0, -}; -  uint8_t  ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  {  	int i, nl = 0; +	struct ccstate state; + +	ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP);  	memory_init[HIGH_START] = addr >> 8;  	memory_init[LOW_START] = addr;  	(void) ccdbg_execute(dbg, memory_init); @@ -70,7 +59,7 @@ ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  		ccdbg_execute(dbg, write8);  		if ((i & 0xf) == 0xf) {  			ccdbg_debug(CC_DEBUG_MEMORY, "."); -			ccdbg_flush(); +			ccdbg_flush(CC_DEBUG_MEMORY);  			nl = 1;  		}  		if ((i & 0xff) == 0xff) { @@ -78,7 +67,7 @@ ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  			nl = 0;  		}  	} -	(void) ccdbg_execute(dbg, memory_fini); +	ccdbg_state_restore(dbg, &state);  	if (nl)  		ccdbg_debug(CC_DEBUG_MEMORY, "\n");  	return 0; @@ -88,6 +77,13 @@ uint8_t  ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  {  	int i, nl = 0; +	struct ccstate state; + +	if (ccdbg_rom_contains(dbg, addr, nbytes)) { +		ccdbg_rom_replace_xmem(dbg, addr, bytes, nbytes); +		return 0; +	} +	ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP);  	memory_init[HIGH_START] = addr >> 8;  	memory_init[LOW_START] = addr;  	(void) ccdbg_execute(dbg, memory_init); @@ -95,7 +91,7 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  		*bytes++ = ccdbg_execute(dbg, read8);  		if ((i & 0xf) == 0xf) {  			ccdbg_debug(CC_DEBUG_MEMORY, "."); -			ccdbg_flush(); +			ccdbg_flush(CC_DEBUG_MEMORY);  			nl = 1;  		}  		if ((i & 0xff) == 0xff) { @@ -103,7 +99,8 @@ ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)  			nl = 0;  		}  	} -	(void) ccdbg_execute(dbg, memory_fini); +	ccdbg_state_replace_xmem(dbg, &state, addr, bytes, nbytes); +	ccdbg_state_restore(dbg, &state);  	if (nl)  		ccdbg_debug(CC_DEBUG_MEMORY, "\n");  	return 0; @@ -135,16 +132,6 @@ ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length)  	return image;  } -static uint8_t sfr_init[] = { -	2,	MOV_direct_A,		0x7f, -	0, -}; - -static uint8_t sfr_fini[] = { -	2,	MOV_A_direct,		0x7f, -	0, -}; -  static uint8_t sfr_read[] = {  	2,	MOV_A_direct,		0,  #define SFR_READ_ADDR	2 @@ -162,12 +149,15 @@ uint8_t  ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes)  {  	int	i; -	(void) ccdbg_execute(dbg, sfr_init); +	struct ccstate state; + +	ccdbg_state_save(dbg, &state, CC_STATE_ACC);  	for (i = 0; i < nbytes; i++) {  		sfr_read[SFR_READ_ADDR] = addr + i;  		*bytes++ = ccdbg_execute(dbg, sfr_read);  	} -	(void) ccdbg_execute(dbg, sfr_fini); +	ccdbg_state_replace_sfr(dbg, &state, addr, bytes, nbytes); +	ccdbg_state_restore(dbg, &state);  	return 0;  } diff --git a/lib/ccdbg-rom.c b/lib/ccdbg-rom.c new file mode 100644 index 00000000..4559b4e7 --- /dev/null +++ b/lib/ccdbg-rom.c @@ -0,0 +1,63 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.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. + */ + +#include "ccdbg.h" + +uint8_t +ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom) +{ +	if (dbg->rom) +		ccdbg_hex_image_free(dbg->rom); +	dbg->rom = rom; +	return 0; +} + +uint8_t +ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes) +{ +	struct hex_image *rom = dbg->rom; +	if (!rom) +		return 0; +	if (addr < rom->address || rom->address + rom->length < addr + nbytes) +		return 0; +	return 1; +} + +uint8_t +ccdbg_rom_replace_xmem(struct ccdbg *dbg, +		       uint16_t addr, uint8_t *bytes, int nbytes) +{ +	struct hex_image *rom = dbg->rom; +	if (!rom) +		return 0; +	 +	if (rom->address < addr + nbytes && addr < rom->address + rom->length) { +		int	start, stop; + +		start = addr; +		if (addr < rom->address) +			start = rom->address; +		stop = addr + nbytes; +		if (rom->address + rom->length < stop) +			stop = rom->address + rom->length; +		memcpy(bytes + start - addr, rom->data + start - rom->address, +		       stop - start); +		return 1; +	} +	return 0; +} diff --git a/lib/ccdbg-state.c b/lib/ccdbg-state.c new file mode 100644 index 00000000..9aca8d2e --- /dev/null +++ b/lib/ccdbg-state.c @@ -0,0 +1,128 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.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. + */ + +#include "ccdbg.h" + +static uint8_t save_acc[] = { +	1,	NOP, +	0 +}; + +static uint8_t save_sfr[] = { +	2,	MOV_A_direct,	0, +#define SAVE_SFR_ADDR	2 +	0, +}; + +struct sfr_state { +	uint8_t		address; +	uint16_t	mask; +	char		*name; +}; + +static struct sfr_state	sfrs[CC_STATE_NSFR] = { +	{ SFR_DPL0,	CC_STATE_DP,	"dpl0" }, +	{ SFR_DPH0,	CC_STATE_DP,	"dph0" }, +	{ SFR_DPL1,	CC_STATE_DP,	"dpl1" }, +	{ SFR_DPH1,	CC_STATE_DP,	"dph1" }, +	{ PSW(0),	CC_STATE_PSW,	"psw"  }, +}; + +uint8_t +ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask) +{ +	int	i; + +	mask |= CC_STATE_ACC; +	if (mask & CC_STATE_ACC) +		state->acc = ccdbg_execute(dbg, save_acc); +	for (i = 0; i < CC_STATE_NSFR; i++) { +		if (sfrs[i].mask & mask) { +			save_sfr[SAVE_SFR_ADDR] = sfrs[i].address; +			state->sfr[i] = ccdbg_execute(dbg, save_sfr); +		} +	} +	state->mask = mask; +	return 0; +} + +static uint8_t restore_sfr[] = { +	3,	MOV_direct_data,	0,	0, +#define RESTORE_SFR_ADDR	2 +#define RESTORE_SFR_DATA	3 +	0 +}; + +static uint8_t restore_acc[] = { +	2,	MOV_A_data,	0, +#define RESTORE_ACC_DATA	2 +	0 +}; + +uint8_t +ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state) +{ +	int i; +	for (i = CC_STATE_NSFR - 1; i >= 0; i--) { +		if (sfrs[i].mask & state->mask) { +			restore_sfr[RESTORE_SFR_ADDR] = sfrs[i].address; +			restore_sfr[RESTORE_SFR_DATA] = state->sfr[i]; +			ccdbg_execute(dbg, restore_sfr); +		} +	} +	if (state->mask & CC_STATE_ACC) { +		restore_acc[RESTORE_ACC_DATA] = state->acc; +		ccdbg_execute(dbg, restore_acc); +	} +	state->mask = 0; +	return 0; +} + +static void +ccdbg_state_replace(uint16_t sfr_addr, uint8_t sfr, char *name, +		    uint16_t addr, uint8_t *bytes, int nbytes) +{ +	sfr_addr += 0xdf00; + +	if (addr <= sfr_addr && sfr_addr < addr + nbytes) { +		fprintf(stderr, "replacing %s at 0x%04x - read 0x%02x saved 0x%02x\n", +			name, sfr_addr, bytes[sfr_addr - addr], sfr); +		bytes[sfr_addr - addr] = sfr; +	} +} + +void +ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state, +			 uint16_t addr, uint8_t *bytes, int nbytes) +{ +	int i; +	if (state->mask & CC_STATE_ACC) +		ccdbg_state_replace(ACC(0), state->acc, "acc", +				    addr, bytes, nbytes); +	for (i = 0; i < CC_STATE_NSFR; i++) +		if (state->mask & sfrs[i].mask) +			ccdbg_state_replace(sfrs[i].address, state->sfr[i], +					    sfrs[i].name, addr, bytes, nbytes); +} + +void +ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state, +			uint8_t addr, uint8_t *bytes, int nbytes) +{ +	ccdbg_state_replace_xmem(dbg, state, (uint16_t) addr + 0xdf00, bytes, nbytes); +} diff --git a/lib/ccdbg.h b/lib/ccdbg.h index 203b5aeb..241c4eec 100644 --- a/lib/ccdbg.h +++ b/lib/ccdbg.h @@ -39,6 +39,7 @@  /* 8051 instructions   */ +#define NOP			0x00  #define MOV_direct_data		0x75  #define LJMP			0x02  #define MOV_Rn_data(n)		(0x78 | (n)) @@ -99,6 +100,9 @@  /* Bit-addressable accumulator */  #define ACC(bit)		(0xE0 | (bit)) +/* Bit-addressable status word */ +#define PSW(bit)		(0xD0 | (bit)) +  #define CP_USB_ASYNC  struct ccdbg { @@ -107,6 +111,7 @@ struct ccdbg {  #else  	struct cp_usb *cp;  #endif +	struct hex_image *rom;  };  /* Intel hex file format data @@ -130,6 +135,18 @@ struct hex_image {  	uint8_t		data[0];  }; +#define CC_STATE_ACC	0x1 +#define CC_STATE_PSW	0x2 +#define CC_STATE_DP	0x4 + +#define CC_STATE_NSFR	5 + +struct ccstate { +	uint16_t	mask; +	uint8_t		acc; +	uint8_t		sfr[CC_STATE_NSFR]; +}; +  #define HEX_RECORD_NORMAL		0x00  #define HEX_RECORD_EOF			0x01  #define HEX_RECORD_EXTENDED_ADDRESS	0x02 @@ -337,4 +354,30 @@ ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes);  uint8_t  ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes); +/* ccdbg-rom.c */ +uint8_t +ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom); + +uint8_t +ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes); + +uint8_t +ccdbg_rom_replace_xmem(struct ccdbg *dbg, +		       uint16_t addrp, uint8_t *bytesp, int nbytes); + +/* ccdbg-state.c */ +uint8_t +ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask); + +uint8_t +ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state); + +void +ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state, +			 uint16_t addr, uint8_t *bytes, int nbytes); + +void +ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state, +			uint8_t addr, uint8_t *bytes, int nbytes); +  #endif /* _CCDBG_H_ */ | 
