Example #1
0
static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
			  const uint8_t *src, int len)
{
	ADIv5_AP_t *ap = adiv5_target_ap(target);
	uint32_t offset = dest % 4;
	uint32_t words = (offset + len + 3) / 4;
	uint32_t data[2 + words];

	/* Construct data buffer used by stub */
	data[0] = dest - offset;
	data[1] = words * 4;		/* length must always be a multiple of 4 */
	data[2] = 0xFFFFFFFF;		/* pad partial words with all 1s to avoid */
	data[words + 1] = 0xFFFFFFFF;	/* damaging overlapping areas */
	memcpy((uint8_t *)&data[2] + offset, src, len);

	/* Write stub and data to target ram and set PC */
	target_mem_write_words(target, 0x20000000, (void*)stm32f1_flash_write_stub, 0x2C);
	target_mem_write_words(target, 0x2000002C, data, len + 8);
	target_pc_write(target, 0x20000000);
	if(target_check_error(target))
		return -1;

	/* Execute the stub */
	target_halt_resume(target, 0);
	while(!target_halt_wait(target));

	/* Check for error */
	if (adiv5_ap_mem_read(ap, FLASH_SR) & SR_ERROR_MASK)
		return -1;

	return 0;
}
Example #2
0
static int rsp_break_signal(struct tcp_pcb * tp, char * pkt)
{
//	int state;

	DCC_LOG(LOG_TRACE, "break received, stopping...");

	if (target_halt(0) < 0) {
		return rsp_error(tp, 1);
	}

	return 0;
#if 0
	if ((state = target_halt_wait(500)) == ERR_TIMEOUT) {
		DCC_LOG(LOG_TRACE, "timeout...");
	}

	if (state == DBG_ST_HALTED) {
		DCC_LOG(LOG_TRACE, "halted");
		return rsp_signal(tp, pkt, SIGTRAP);
	}

	return rsp_msg(tp, pkt, "YARD-ICE: target_halt failed!");
#endif
}
Example #3
0
static int rsp_last_signal(struct gdb_rspd * gdb, struct tcp_pcb * tp, 
						   char * pkt, int len)
{
	int state;

	state = target_status();
	if (state < DBG_ST_CONNECTED) {
		DCC_LOG(LOG_WARNING, "target not connected!");
		return rsp_error(tp, state);
	}

	if (state != DBG_ST_HALTED) {
		DCC_LOG(LOG_TRACE, "running");

		if ((state = target_halt(0)) < 0) {
			DCC_LOG(LOG_WARNING, "target_halt() failed!");
			rsp_msg(tp, pkt, "YARD-ICE: halt fail\n");
			return rsp_error(tp, 1);
		}

		if ((state = target_halt_wait(500)) == ERR_TIMEOUT) {
			DCC_LOG(LOG_TRACE, "timeout...");
			rsp_msg(tp, pkt, "YARD-ICE: target_halt failed!");
			return rsp_error(tp, 1);
		}
	 } 
	
	if (state == DBG_ST_HALTED) {
		DCC_LOG(LOG_TRACE, "halted");
		thinkos_flag_clr(gdb->run_flag);
		return rsp_signal(tp, pkt, SIGTRAP);
	}

	switch (state) {
	case DBG_ST_ERROR:
		rsp_msg(tp, pkt, "YARD-ICE: error state\n");
		break;
	case DBG_ST_OUTOFSYNC:
		DCC_LOG(LOG_TRACE, "out of sync");
		rsp_msg(tp, pkt, "YARD-ICE: Out of sync\n");
		break;
	case DBG_ST_BUSY:
		DCC_LOG(LOG_TRACE, "busy...");
		rsp_msg(tp, pkt, "YARD-ICE: busy ... \n");
		break;
	case DBG_ST_UNDEF:
		rsp_msg(tp, pkt, "YARD-ICE: undefined state\n");
		break;
	case DBG_ST_UNCONNECTED:
		DCC_LOG(LOG_TRACE, "unconnected");
		rsp_msg(tp, pkt, "YARD-ICE: unconnected ?\n");
		break;
	case DBG_ST_CONNECTED:
		DCC_LOG(LOG_TRACE, "connected");
		rsp_msg(tp, pkt, "YARD-ICE: connected (busy)\n");
		break;
	case DBG_ST_RUNNING:
		DCC_LOG(LOG_TRACE, "running");
		rsp_msg(tp, pkt, "YARD-ICE: running\n");
		thinkos_flag_set(gdb->run_flag);
		break;
	default:
		DCC_LOG1(LOG_WARNING, "unknown state: %d", state);
		rsp_msg(tp, pkt, "YARD-ICE: unknown state, bailing out!\n");
		return -1;
	}

	return rsp_error(tp, 1);
}
Example #4
0
void
gdb_main(void)
{
	int size;
	bool single_step = false;
	char last_activity = 0;

	DEBUG("Entring GDB protocol main loop\n");
	/* GDB protocol main loop */
	while(1) {
		SET_IDLE_STATE(1);
		size = gdb_getpacket(pbuf, BUF_SIZE);
		SET_IDLE_STATE(0);
	continue_activity:
		switch(pbuf[0]) {
		/* Implementation of these is mandatory! */
		case 'g': { /* 'g': Read general registers */
			ERROR_IF_NO_TARGET();
			uint8_t arm_regs[target_regs_size(cur_target)];
			target_regs_read(cur_target, arm_regs);
			gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)),
			              sizeof(arm_regs) * 2);
			break;
			}
		case 'm': {	/* 'm addr,len': Read len bytes from addr */
			uint32_t addr, len;
			ERROR_IF_NO_TARGET();
			sscanf(pbuf, "m%" SCNx32 ",%" SCNx32, &addr, &len);
			DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
			uint8_t mem[len];
			target_mem_read(cur_target, mem, addr, len);
			if(target_check_error(cur_target))
				gdb_putpacketz("E01");
			else
				gdb_putpacket(hexify(pbuf, mem, len), len*2);
			break;
			}
		case 'G': {	/* 'G XX': Write general registers */
			ERROR_IF_NO_TARGET();
			uint8_t arm_regs[target_regs_size(cur_target)];
			unhexify(arm_regs, &pbuf[1], sizeof(arm_regs));
			target_regs_write(cur_target, arm_regs);
			gdb_putpacketz("OK");
			break;
			}
		case 'M': { /* 'M addr,len:XX': Write len bytes to addr */
			uint32_t addr, len;
			int hex;
			ERROR_IF_NO_TARGET();
			sscanf(pbuf, "M%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &hex);
			DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
			uint8_t mem[len];
			unhexify(mem, pbuf + hex, len);
			target_mem_write(cur_target, addr, mem, len);
			if(target_check_error(cur_target))
				gdb_putpacketz("E01");
			else
				gdb_putpacketz("OK");
			break;
			}
		case 's':	/* 's [addr]': Single step [start at addr] */
			single_step = true;
			// Fall through to resume target
		case 'c':	/* 'c [addr]': Continue [at addr] */
			if(!cur_target) {
				gdb_putpacketz("X1D");
				break;
			}

			target_halt_resume(cur_target, single_step);
			SET_RUN_STATE(1);
			single_step = false;
			// Fall through to wait for target halt
		case '?': {	/* '?': Request reason for target halt */
			/* This packet isn't documented as being mandatory,
			 * but GDB doesn't work without it. */
			uint32_t watch_addr;
			int sig;

			if(!cur_target) {
				/* Report "target exited" if no target */
				gdb_putpacketz("W00");
				break;
			}

			last_activity = pbuf[0];
			/* Wait for target halt */
			while(!(sig = target_halt_wait(cur_target))) {
				unsigned char c = gdb_if_getchar_to(0);
				if((c == '\x03') || (c == '\x04')) {
					target_halt_request(cur_target);
					last_activity = 's';
				}
			}
			SET_RUN_STATE(0);

			/* Negative signal indicates we're in a syscall */
			if (sig < 0)
				break;

			/* Target disappeared */
			if (cur_target == NULL) {
				gdb_putpacket_f("X%02X", sig);
				break;
			}

			/* Report reason for halt */
			if(target_check_hw_wp(cur_target, &watch_addr)) {
				/* Watchpoint hit */
				gdb_putpacket_f("T%02Xwatch:%08X;", sig, watch_addr);
			} else {
				gdb_putpacket_f("T%02X", sig);
			}
			break;
			}
		case 'F': {	/* Semihosting call finished */
			int retcode, errcode, items;
			char c, *p;
			if (pbuf[1] == '-')
				p = &pbuf[2];
			else
				p = &pbuf[1];
			items = sscanf(p, "%x,%x,%c", &retcode, &errcode, &c);
			if (pbuf[1] == '-')
				retcode = -retcode;

			target_hostio_reply(cur_target, retcode, errcode);

			/* if break is requested */
			if (items == 3 && c == 'C') {
				gdb_putpacketz("T02");
				break;
			}

			pbuf[0] = last_activity;
			goto continue_activity;
		}

		/* Optional GDB packet support */
		case '!':	/* Enable Extended GDB Protocol. */
			/* This doesn't do anything, we support the extended
			 * protocol anyway, but GDB will never send us a 'R'
			 * packet unless we answer 'OK' here.
			 */
			gdb_putpacketz("OK");
			break;

		case 0x04:
		case 'D':	/* GDB 'detach' command. */
			if(cur_target)
				target_detach(cur_target);
			last_target = cur_target;
			cur_target = NULL;
			gdb_putpacketz("OK");
			break;

		case 'k':	/* Kill the target */
			if(cur_target) {
				target_reset(cur_target);
				target_detach(cur_target);
				last_target = cur_target;
				cur_target = NULL;
			}
			break;

		case 'r':	/* Reset the target system */
		case 'R':	/* Restart the target program */
			if(cur_target)
				target_reset(cur_target);
			else if(last_target) {
				cur_target = target_attach(last_target,
						gdb_target_destroy_callback);
				target_reset(cur_target);
			}
			break;

		case 'X': { /* 'X addr,len:XX': Write binary data to addr */
			uint32_t addr, len;
			int bin;
			ERROR_IF_NO_TARGET();
			sscanf(pbuf, "X%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &bin);
			DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
			target_mem_write(cur_target, addr, pbuf+bin, len);
			if(target_check_error(cur_target))
				gdb_putpacketz("E01");
			else
				gdb_putpacketz("OK");
			break;
			}

		case 'q':	/* General query packet */
			handle_q_packet(pbuf, size);
			break;

		case 'v':	/* General query packet */
			handle_v_packet(pbuf, size);
			break;

		/* These packet implement hardware break-/watchpoints */
		case 'Z':	/* Z type,addr,len: Set breakpoint packet */
		case 'z':	/* z type,addr,len: Clear breakpoint packet */
			ERROR_IF_NO_TARGET();
			handle_z_packet(pbuf, size);
			break;

		default: 	/* Packet not implemented */
			DEBUG("*** Unsupported packet: %s\n", pbuf);
			gdb_putpacketz("");
		}
	}
}