/**
* @file SWD_flash.c
* @brief Program target flash through SWD
*/
#include "swd_host.h"
#include "SWD_flash.h"
extern const program_target_t flash_algo;
error_t target_flash_init(uint32_t flash_start)
{
if (0 == swd_set_target_state_hw(RESET_PROGRAM)) {
return ERROR_RESET;
}
// Download flash programming algorithm to target and initialise.
if (0 == swd_write_memory(flash_algo.algo_start, (uint8_t *)flash_algo.algo_blob, flash_algo.algo_size)) {
return ERROR_ALGO_DL;
}
if (0 == swd_flash_syscall_exec(&flash_algo.sys_call_s, flash_algo.init, flash_start, 0, 0, 0)) {
return ERROR_INIT;
}
return ERROR_SUCCESS;
}
error_t target_flash_uninit(void)
{
swd_set_target_state_hw(RESET_RUN);
swd_off();
return ERROR_SUCCESS;
}
error_t target_flash_program_page(uint32_t addr, const uint8_t *buf, uint32_t size)
{
while (size > 0) {
uint32_t write_size = size > flash_algo.program_buffer_size ? flash_algo.program_buffer_size : size;
// Write page to buffer
if (!swd_write_memory(flash_algo.program_buffer, (uint8_t *)buf, write_size)) {
return ERROR_ALGO_DATA_SEQ;
}
// Run flash programming
if (!swd_flash_syscall_exec(&flash_algo.sys_call_s,
flash_algo.program_page,
addr,
flash_algo.program_buffer_size,
flash_algo.program_buffer,
0)) {
return ERROR_WRITE;
}
addr += write_size;
buf += write_size;
size -= write_size;
}
return ERROR_SUCCESS;
}
error_t target_flash_erase_sector(uint32_t addr)
{
if (0 == swd_flash_syscall_exec(&flash_algo.sys_call_s, flash_algo.erase_sector, addr, 0, 0, 0)) {
return ERROR_ERASE_SECTOR;
}
return ERROR_SUCCESS;
}
error_t target_flash_erase_chip(void)
{
error_t status = ERROR_SUCCESS;
if (0 == swd_flash_syscall_exec(&flash_algo.sys_call_s, flash_algo.erase_chip, 0, 0, 0, 0)) {
return ERROR_ERASE_ALL;
}
return status;
}
swd_host.c
#include "DAP_config.h"
#include "DAP.h"
#include "debug_cm.h"
extern uint32_t Flash_Page_Size;
#define NVIC_Addr (0xe000e000)
#define DBG_Addr (0xe000edf0)
// AP CSW register, base value
#define CSW_VALUE (CSW_RESERVED | CSW_MSTRDBG | CSW_HPROT | CSW_DBGSTAT | CSW_SADDRINC)
// SWD register access
#define SWD_REG_AP (1)
#define SWD_REG_DP (0)
#define SWD_REG_R (1<<1)
#define SWD_REG_W (0<<1)
#define SWD_REG_ADR(a) (a & 0x0c)
#define DCRDR 0xE000EDF8
#define DCRSR 0xE000EDF4
#define DHCSR 0xE000EDF0
#define REGWnR (1 << 16)
#define MAX_SWD_RETRY 10
#define MAX_TIMEOUT 1000000 // Timeout for syscalls on target
#define SCB_AIRCR_PRIGROUP_Pos 8
#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos)
typedef struct {
uint32_t select;
uint32_t csw;
} DAP_STATE;
typedef struct {
uint32_t r[16];
uint32_t xpsr;
} DEBUG_STATE;
static DAP_STATE dap_state;
static uint8_t swd_read_core_register(uint32_t n, uint32_t *val);
static uint8_t swd_write_core_register(uint32_t n, uint32_t val);
void delaymS(uint32_t ms)
{
uint32_t cnt = SystemCoreClock/4/1000 * ms;
for(uint32_t i = 0; i < cnt; i++) __NOP();
}
static void int2array(uint8_t *res, uint32_t data, uint8_t len)
{
uint8_t i = 0;
for(i = 0; i < len; i++) {
res[i] = (data >> 8 * i) & 0xFF;
}
}
static uint8_t swd_transfer_retry(uint32_t req, uint32_t *data)
{
uint8_t i, ack;
for (i = 0; i < MAX_SWD_RETRY; i++) {
ack = SWD_Transfer(req, data);
if (ack != DAP_TRANSFER_WAIT) {
return ack;
}
}
return ack;
}
uint8_t swd_init(void)
{
DAP_Setup();
PORT_SWD_SETUP();
return 1;
}
uint8_t swd_off(void)
{
PORT_OFF();
return 1;
}
// Read debug port register.
uint8_t swd_read_dp(uint8_t adr, uint32_t *val)
{
uint32_t tmp_in;
uint8_t tmp_out[4];
uint8_t ack;
uint32_t tmp;
tmp_in = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(adr);
ack = swd_transfer_retry(tmp_in, (uint32_t *)tmp_out);
*val = 0;
tmp = tmp_out[3];
*val |= (tmp << 24);
tmp = tmp_out[2];
*val |= (tmp << 16);
tmp = tmp_out[1];
*val |= (tmp << 8);
tmp = tmp_out[0];
*val |= (tmp << 0);
return (ack == 0x01);
}
// Write debug port register
uint8_t swd_write_dp(uint8_t adr, uint32_t val)
{
uint32_t req;
uint8_t data[4];
uint8_t ack;
switch (adr) {
case DP_SELECT:
if (dap_state.select == val) {
return 1;
}
dap_state.select = val;
break;
default:
break;
}
req = SWD_REG_DP | SWD_REG_W | SWD_REG_ADR(adr);
int2array(data, val, 4);
ack = swd_transfer_retry(req, (uint32_t *)data);
return (ack == 0x01);
}
// Read access port register.
uint8_t swd_read_ap(uint32_t adr, uint32_t *val)
{
uint8_t tmp_in, ack;
uint8_t tmp_out[4];
uint32_t tmp;
uint32_t apsel = adr & 0xff000000;
uint32_t bank_sel = adr & APBANKSEL;
if (!swd_write_dp(DP_SELECT, apsel | bank_sel)) {
return 0;
}
tmp_in = SWD_REG_AP | SWD_REG_R | SWD_REG_ADR(adr);
// first dummy read
swd_transfer_retry(tmp_in, (uint32_t *)tmp_out);
ack = swd_transfer_retry(tmp_in, (uint32_t *)tmp_out);
*val = 0;
tmp = tmp_out[3];
*val |= (tmp << 24);
tmp = tmp_out[2];
*val |= (tmp << 16);
tmp = tmp_out[1];
*val |= (tmp << 8);
tmp = tmp_out[0];
*val |= (tmp << 0);
&nbs

该代码实现了一套基于SWD(SerialWireDebug)协议的接口,用于通过硬件调试端口对目标设备的闪存进行初始化、编程、擦除以及读写操作。它包括了目标闪存的初始化和卸载函数,以及页编程、扇区擦除和芯片擦除功能。此外,还提供了读写核心寄存器和目标内存的低级别函数。
8483

被折叠的 条评论
为什么被折叠?



