Beispiel #1
0
static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, uint32_t pagesize)
{
	ADIv5_AP_t *ap = adiv5_target_ap(target);
	uint16_t sr;

	addr &= ~(pagesize - 1);
	len &= ~(pagesize - 1);

	stm32f1_flash_unlock(ap);

	while(len) {
		/* Flash page erase instruction */
		adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_PER);
		/* write address to FMA */
		adiv5_ap_mem_write(ap, FLASH_AR, addr);
		/* Flash page erase start instruction */
		adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER);

		/* Read FLASH_SR to poll for BSY bit */
		while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
			if(target_check_error(target))
				return -1;

		len -= pagesize;
		addr += pagesize;
	}

	/* Check for error */
	sr = adiv5_ap_mem_read(ap, FLASH_SR);
	if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP))
		return -1;

	return 0;
}
Beispiel #2
0
bool stm32f1_probe(struct target_s *target)
{

	target->idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE) & 0xfff;
	switch(target->idcode) {
	case 0x410:  /* Medium density */
	case 0x412:  /* Low denisty */
	case 0x420:  /* Value Line, Low-/Medium density */
		target->driver = stm32f1_driver_str;
		target->xml_mem_map = stm32f1_xml_memory_map;
		target->flash_erase = stm32md_flash_erase;
		target->flash_write = stm32f1_flash_write;
		target_add_commands(target, stm32f1_cmd_list, "STM32 LD/MD");
		return true;
	case 0x414:	 /* High density */
	case 0x418:  /* Connectivity Line */
	case 0x428:	 /* Value Line, High Density */
		target->driver = stm32hd_driver_str;
		target->xml_mem_map = stm32hd_xml_memory_map;
		target->flash_erase = stm32hd_flash_erase;
		target->flash_write = stm32f1_flash_write;
		target_add_commands(target, stm32f1_cmd_list, "STM32 HD/CL");
		return true;
	case 0x422:  /* STM32F30x */
	case 0x432:  /* STM32F37x */
		target->driver = stm32f3_driver_str;
		target->xml_mem_map = stm32hd_xml_memory_map;
		target->flash_erase = stm32hd_flash_erase;
		target->flash_write = stm32f1_flash_write;
		target_add_commands(target, stm32f1_cmd_list, "STM32F3");
		return true;
	}

	target->idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE_F0) & 0xfff;
	switch(target->idcode) {
	case 0x444:  /* STM32F03 */
	case 0x440:  /* STM32F05 */
	case 0x448:  /* STM32F07 */
		switch(target->idcode) {
		case 0x444:  /* STM32F03 */
			target->driver = stm32f03_driver_str;
			break;
		case 0x440:  /* STM32F05 */
			target->driver = stm32f05_driver_str;
			break;
		case 0x448:  /* STM32F07 */
			target->driver = stm32f07_driver_str;
			break;
		}
		target->xml_mem_map = stm32f1_xml_memory_map;
		target->flash_erase = stm32md_flash_erase;
		target->flash_write = stm32f1_flash_write;
		target_add_commands(target, stm32f1_cmd_list, "STM32F0");
		return true;
	}

	return false;
}
Beispiel #3
0
static bool stm32f1_cmd_option(target *t, int argc, char *argv[])
{
	uint32_t addr, val;
	uint32_t flash_obp_rdp_key;
	ADIv5_AP_t *ap = adiv5_target_ap(t);
	uint32_t rdprt;

	switch(t->idcode) {
	case 0x422:  /* STM32F30x */
	case 0x432:  /* STM32F37x */
	case 0x440:  /* STM32F0 */
		flash_obp_rdp_key = FLASH_OBP_RDP_KEY_F3;
		break;
	default: flash_obp_rdp_key = FLASH_OBP_RDP_KEY;
	}
	rdprt = (adiv5_ap_mem_read(ap, FLASH_OBR) & FLASH_OBR_RDPRT);
	stm32f1_flash_unlock(ap);
	adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY1);
	adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY2);

	if ((argc == 2) && !strcmp(argv[1], "erase")) {
		stm32f1_option_erase(t);
		stm32f1_option_write_erased(t, FLASH_OBP_RDP, flash_obp_rdp_key);
	} else if (rdprt) {
		gdb_out("Device is Read Protected\n");
		gdb_out("Use \"monitor option erase\" to unprotect, erasing device\n");
		return true;
	} else if (argc == 3) {
		addr = strtol(argv[1], NULL, 0);
		val = strtol(argv[2], NULL, 0);
		stm32f1_option_write(t, addr, val);
	} else {
		gdb_out("usage: monitor option erase\n");
		gdb_out("usage: monitor option <addr> <value>\n");
	}

	if (0 && flash_obp_rdp_key == FLASH_OBP_RDP_KEY_F3) {
		/* Reload option bytes on F0 and F3*/
		val = adiv5_ap_mem_read(ap, FLASH_CR);
		val |= FLASH_CR_OBL_LAUNCH;
		stm32f1_option_write(t, FLASH_CR, val);
		val &= ~FLASH_CR_OBL_LAUNCH;
		stm32f1_option_write(t, FLASH_CR, val);
	}

	for (int i = 0; i < 0xf; i += 4) {
		addr = 0x1ffff800 + i;
		val = adiv5_ap_mem_read(ap, addr);
		gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF);
		gdb_outf("0x%08X: 0x%04X\n", addr + 2, val >> 16);
	}
	return true;
}
Beispiel #4
0
static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value)
{
	ADIv5_AP_t *ap = adiv5_target_ap(t);
	uint16_t opt_val[8];
	int i, index;

	index = (addr - FLASH_OBP_RDP) / 2;
	if ((index < 0) || (index > 7))
		 return false;
	/* Retrieve old values */
	for (i = 0; i < 16; i = i +4) {
		 uint32_t val = adiv5_ap_mem_read(ap, FLASH_OBP_RDP + i);
		 opt_val[i/2] = val & 0xffff;
		 opt_val[i/2 +1] = val >> 16;
	}
	if (opt_val[index] == value)
		return true;
	/* Check for erased value */
	if (opt_val[index] != 0xffff)
		if (!(stm32f1_option_erase(t)))
			return false;
	opt_val[index] = value;
	/* Write changed values*/
	for (i = 0; i < 8; i++)
		if (!(stm32f1_option_write_erased
			(t, FLASH_OBP_RDP + i*2,opt_val[i])))
			return false;
	return true;
}
Beispiel #5
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;
}
Beispiel #6
0
static void stm32f4_flash_unlock(ADIv5_AP_t *ap)
{
	if (adiv5_ap_mem_read(ap, FLASH_CR) & FLASH_CR_LOCK) {
		/* Enable FPEC controller access */
		adiv5_ap_mem_write(ap, FLASH_KEYR, KEY1);
		adiv5_ap_mem_write(ap, FLASH_KEYR, KEY2);
	}
}
Beispiel #7
0
static bool stm32f1_cmd_erase_mass(target *t)
{
	ADIv5_AP_t *ap = adiv5_target_ap(t);

	stm32f1_flash_unlock(ap);

	/* Flash mass erase start instruction */
	adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER);
	adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER);

	/* Read FLASH_SR to poll for BSY bit */
	while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
		if(target_check_error(t))
			return false;

	/* Check for error */
	uint16_t sr = adiv5_ap_mem_read(ap, FLASH_SR);
	if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP))
		return false;

	return true;
}
Beispiel #8
0
static bool stm32f1_option_erase(target *t)
{
	ADIv5_AP_t *ap = adiv5_target_ap(t);

	/* Erase option bytes instruction */
	adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE);
	adiv5_ap_mem_write(ap, FLASH_CR,
			FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE);
	/* Read FLASH_SR to poll for BSY bit */
	while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
		if(target_check_error(t))
			return false;
	return true;
}
Beispiel #9
0
static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value)
{
	ADIv5_AP_t *ap = adiv5_target_ap(t);

	if (value == 0xffff)
		return true;
	/* Erase option bytes instruction */
	adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE);
	adiv5_ap_mem_write_halfword(ap, addr, value);
	/* Read FLASH_SR to poll for BSY bit */
	while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
		if(target_check_error(t))
			return false;
	return true;
}
Beispiel #10
0
bool stm32f4_probe(struct target_s *target)
{
	uint32_t idcode;

	idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE);
	switch(idcode & 0xFFF) {
	case 0x411: /* Documented to be 0x413! This is what I read... */
	case 0x413:
	case 0x423: /* F401 */
	case 0x419: /* 427/437 */
		target->driver = stm32f4_driver_str;
		target->xml_mem_map = stm32f4_xml_memory_map;
		target->flash_erase = stm32f4_flash_erase;
		target->flash_write = stm32f4_flash_write;
		target_add_commands(target, stm32f4_cmd_list, "STM32F4");
		return true;
	}
	return false;
}