Skip to content

Commit

Permalink
at32f43x: Implement read unprotect over SWD transport
Browse files Browse the repository at this point in the history
  • Loading branch information
ALTracer committed Oct 24, 2024
1 parent 00e2311 commit 4cb8013
Showing 1 changed file with 82 additions and 1 deletion.
83 changes: 82 additions & 1 deletion src/target/at32f43x.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,84 @@ static bool at32f43_mass_erase(target_s *target)
return true;
}

static bool at32f43x_swd_raw_access_noabort(adiv5_debug_port_s *dp, uint8_t rnw, uint16_t addr, uint32_t value)
{
const uint8_t request = make_packet_request(rnw, addr);
uint32_t response = 0;
uint8_t ack = SWDP_ACK_WAIT;
platform_timeout_s timeout_progressbar;
platform_timeout_set(&timeout_progressbar, 500U);
platform_timeout_s timeout_erase;
platform_timeout_set(&timeout_erase, 15000U);
while ((ack == SWDP_ACK_WAIT) && !platform_timeout_is_expired(&timeout_erase)) {
swd_proc.seq_out(request, 8U);
ack = swd_proc.seq_in(3U);
/* No data phase */
platform_delay(5U);
target_print_progress(&timeout_progressbar);
}

if (ack != SWDP_ACK_OK) {
DEBUG_ERROR("SWD access has invalid ack %x\n", ack);
raise_exception(EXCEPTION_ERROR, "SWD invalid ACK");
}

if (platform_timeout_is_expired(&timeout_erase)) {
DEBUG_ERROR("%s timed out after %u ms\n", __func__, 15000U);
raise_exception(EXCEPTION_TIMEOUT, "SWD WAIT");
}

if (rnw) {
if (!swd_proc.seq_in_parity(&response, 32U)) {
dp->fault = 1U;
DEBUG_ERROR("SWD access resulted in parity error\n");
raise_exception(EXCEPTION_ERROR, "SWD parity error");
}
} else
swd_proc.seq_out_parity(value, 32U);
/* Idle cycles */
swd_proc.seq_out(0, 8U);
return response;
}

static bool at32f43x_mem_write_noabort(target_s *target, target_addr32_t dest, uint16_t val)
{
const uint32_t src_bytes = val;
const void *src = &src_bytes;
const align_e align = ALIGN_16BIT;
adiv5_access_port_s *ap = cortex_ap(target);

//adi_ap_mem_access_setup(ap, dest, align);
uint32_t csw = ap->csw | ADIV5_AP_CSW_ADDRINC_SINGLE | ADIV5_AP_CSW_SIZE_HALFWORD;
adiv5_ap_write(ap, ADIV5_AP_CSW, csw);
adiv5_dp_write(ap->dp, ADIV5_AP_TAR_LOW, (uint32_t)dest);

uint32_t value = 0;
adiv5_pack_data(dest, src, &value, align);
/* Submit the memory write */
adiv5_dp_write(ap->dp, ADIV5_AP_DRW, value);

/* Poll for completion (RDBUFF will be responding with WAITs) */
volatile uint32_t rdbuff = 0;
TRY (EXCEPTION_ALL) {
//ack = ap->dp->low_access(dp, rnw, addr, value)
rdbuff = at32f43x_swd_raw_access_noabort(ap->dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0);
}
CATCH () {
case EXCEPTION_TIMEOUT:
DEBUG_TARGET("Timeout during scan. Is target stuck in WFI?\n");
break;
case EXCEPTION_ERROR:
DEBUG_TARGET("Exception: %s\n", exception_frame.msg);
break;
default:
return false;
}
(void)rdbuff;

return true;
}

static bool at32f43_option_erase(target_s *target)
{
/* bank_reg_offset is 0, option bytes belong to first bank */
Expand Down Expand Up @@ -680,8 +758,11 @@ static bool at32f43_cmd_option(target_s *target, int argc, const char **argv)
* FIXME: this transaction only completes after typ. 15 seconds (mass erase of both banks of 4032 KiB chip)
* and if BMD ABORTs it after 250 ms, then chip considers erase as incomplete and stays read-protected.
*/
if (!at32f43_option_write_erased(target, 0U, AT32F43x_USD_RDP_KEY))
at32f43_flash_clear_eop(target, 0);
target_mem32_write32(target, AT32F43x_FLASH_CTRL, AT32F43x_FLASH_CTRL_USDPRGM | AT32F43x_FLASH_CTRL_USDULKS);
if (!at32f43x_mem_write_noabort(target, AT32F43x_USD_BASE, AT32F43x_USD_RDP_KEY))
return false;

/* Set EOPB0 to default 0b010 for 384 KB SRAM */
if (!at32f43_option_write_erased(target, 8U, AT32F43x_USD_EOPB0_DEFAULT))
return false;
Expand Down

0 comments on commit 4cb8013

Please sign in to comment.