Merge pull request #1071 from Ant-ON/try_h7_debug

[feature] Improved support for STM32H7
pull/1073/head
nightwalker-87 2020-12-05 11:48:44 +01:00 zatwierdzone przez GitHub
commit b47f083736
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
17 zmienionych plików z 980 dodań i 655 usunięć

Wyświetl plik

@ -60,6 +60,11 @@ if (STLINK_HAVE_SYS_MMAN_H)
add_definitions(-DSTLINK_HAVE_SYS_MMAN_H)
endif()
CHECK_INCLUDE_FILE(sys/time.h STLINK_HAVE_SYS_TIME_H)
if (STLINK_HAVE_SYS_TIME_H)
add_definitions(-DSTLINK_HAVE_SYS_TIME_H)
endif()
CHECK_INCLUDE_FILE(unistd.h STLINK_HAVE_UNISTD_H)
if (STLINK_HAVE_UNISTD_H)
add_definitions(-DSTLINK_HAVE_UNISTD_H)
@ -104,6 +109,7 @@ set(STLINK_HEADERS
src/stlink-lib/md5.h
src/stlink-lib/sg.h
src/stlink-lib/usb.h
src/stlink-lib/helper.h
)
set(STLINK_SOURCE
@ -114,6 +120,7 @@ set(STLINK_SOURCE
src/stlink-lib/md5.c
src/stlink-lib/sg.c
src/stlink-lib/usb.c
src/stlink-lib/helper.c
)
if (WIN32)
@ -132,6 +139,11 @@ if (WIN32)
set(STLINK_SOURCE "${STLINK_SOURCE};src/win32/mmap.c")
set(STLINK_HEADERS "${STLINK_HEADERS};src/win32/mmap.h")
endif()
if (NOT STLINK_HAVE_SYS_TIME_H)
set(STLINK_SOURCE "${STLINK_SOURCE};src/win32/sys_time.c")
set(STLINK_HEADERS "${STLINK_HEADERS};src/win32/sys_time.h")
endif()
endif ()
## Include test execution for test-targets for target Debug

Wyświetl plik

@ -300,7 +300,7 @@ Return: -1 for error. 0 for success.
int stlink_current_mode(stlink_t *sl);
int stlink_force_debug(stlink_t *sl);
int stlink_target_voltage(stlink_t *sl);
int stlink_set_swdclk(stlink_t *sl, uint16_t divisor);
int stlink_set_swdclk(stlink_t *sl, int freq_khz);
int stlink_erase_flash_mass(stlink_t* sl);
int stlink_write_flash(stlink_t* sl, stm32_addr_t address, uint8_t* data, uint32_t length, uint8_t eraseonly);

Wyświetl plik

@ -28,7 +28,7 @@
int (*current_mode) (stlink_t * stl);
int (*force_debug) (stlink_t *sl);
int32_t (*target_voltage) (stlink_t *sl);
int (*set_swdclk) (stlink_t * stl, uint16_t divisor);
int (*set_swdclk) (stlink_t * stl, int freq_khz);
} stlink_backend_t;
#endif // STLINK_BACKEND_H_

Wyświetl plik

@ -83,25 +83,6 @@ enum target_state {
#define STLINK_V3_MAX_FREQ_NB 10
/* Cortex Debug Control Block */
#define DCB_DHCSR 0xE000EDF0
#define DCB_DCRSR 0xE000EDF4
#define DCB_DCRDR 0xE000EDF8
#define DCB_DEMCR 0xE000EDFC
/* DCB_DHCSR bit and field definitions */
#define DBGKEY (0xA05F << 16)
#define C_DEBUGEN (1 << 0)
#define C_HALT (1 << 1)
#define C_STEP (1 << 2)
#define C_MASKINTS (1 << 3)
#define S_REGRDY (1 << 16)
#define S_HALT (1 << 17)
#define S_SLEEP (1 << 18)
#define S_LOCKUP (1 << 19)
#define S_RETIRE_ST (1 << 24)
#define S_RESET_ST (1 << 25)
/* Map the relevant features, quirks and workaround for specific firmware version of stlink */
#define STLINK_F_HAS_TRACE (1 << 0)
#define STLINK_F_HAS_SWD_SET_FREQ (1 << 1)
@ -242,6 +223,7 @@ void stlink_close(stlink_t *sl);
int stlink_core_id(stlink_t *sl);
int stlink_reset(stlink_t *sl);
int stlink_jtag_reset(stlink_t *sl, int value);
int stlink_soft_reset(stlink_t *sl, int halt_on_reset);
int stlink_run(stlink_t *sl);
int stlink_status(stlink_t *sl);
int stlink_version(stlink_t *sl);
@ -260,7 +242,7 @@ int stlink_step(stlink_t *sl);
int stlink_current_mode(stlink_t *sl);
int stlink_force_debug(stlink_t *sl);
int stlink_target_voltage(stlink_t *sl);
int stlink_set_swdclk(stlink_t *sl, uint16_t divisor);
int stlink_set_swdclk(stlink_t *sl, int freq_khz);
int stlink_erase_flash_mass(stlink_t* sl);
int stlink_write_flash(stlink_t* sl, stm32_addr_t address, uint8_t* data, uint32_t length, uint8_t eraseonly);
@ -303,6 +285,10 @@ int stlink_write_option_control_register1_32(stlink_t *sl, uint32_t option_contr
int stlink_write_option_bytes(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len);
int stlink_fwrite_option_bytes(stlink_t *sl, const char* path, stm32_addr_t addr);
int stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl);
int stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl, stm32_addr_t addr, uint8_t* base, uint32_t len);
int stlink_flashloader_stop(stlink_t *sl);
#include <sg.h>
#include <usb.h>
#include <reg.h>

Wyświetl plik

@ -10,9 +10,12 @@
/* Cortex core ids */
#define STM32VL_CORE_ID 0x1ba01477
#define STM32F7_CORE_ID 0x5ba02477
#define STM32H7_CORE_ID 0x6ba02477 // STM32H7 JTAG ID Code (RM0433 pg3065)
/* Constant STM32 memory map figures */
#define STM32_FLASH_BASE ((uint32_t)0x08000000)
#define STM32_F1_FLASH_BANK2_BASE ((uint32_t)0x08080000)
#define STM32_H7_FLASH_BANK2_BASE ((uint32_t)0x08100000)
#define STM32_SRAM_BASE ((uint32_t)0x20000000)
#define STM32_G0_OPTION_BYTES_BASE ((uint32_t)0x1FFF7800)
#define STM32_G4_OPTION_BYTES_BASE ((uint32_t)0x1FFFF800)

Plik diff jest za duży Load Diff

Wyświetl plik

@ -35,23 +35,36 @@ static void stlink_print_serial(stlink_t *sl, bool openocd) {
printf("\n");
}
static void stlink_print_version(stlink_t *sl) {
// Implementation of version printing is minimalistic
// but contains all available information from sl->version
printf("V%u", sl->version.stlink_v);
if (sl->version.jtag_v > 0)
printf("J%u", sl->version.jtag_v);
if (sl->version.swim_v > 0)
printf("S%u", sl->version.swim_v);
printf("\n");
}
static void stlink_print_info(stlink_t *sl) {
const struct stlink_chipid_params *params = NULL;
if (!sl) { return; }
printf(" serial: ");
printf(" version: ");
stlink_print_version(sl);
printf(" serial: ");
stlink_print_serial(sl, false);
printf(" hla-serial: ");
printf(" hla-serial: ");
stlink_print_serial(sl, true);
printf(" flash: %u (pagesize: %u)\n",
printf(" flash: %u (pagesize: %u)\n",
(uint32_t)sl->flash_size, (uint32_t)sl->flash_pgsz);
printf(" sram: %u\n", (uint32_t)sl->sram_size);
printf(" chipid: 0x%.4x\n", sl->chip_id);
printf(" sram: %u\n", (uint32_t)sl->sram_size);
printf(" chipid: 0x%.4x\n", sl->chip_id);
params = stlink_chipid_get_params(sl->chip_id);
if (params) { printf(" descr: %s\n", params->description); }
if (params) { printf(" descr: %s\n", params->description); }
}
static void stlink_probe(void) {
@ -62,7 +75,10 @@ static void stlink_probe(void) {
printf("Found %u stlink programmers\n", (unsigned int)size);
for (size_t n = 0; n < size; n++) { stlink_print_info(stdevs[n]); }
for (size_t n = 0; n < size; n++) {
if (size>1) printf("%lu.\n", n+1);
stlink_print_info(stdevs[n]);
}
stlink_probe_usb_free(&stdevs, size);
}

Wyświetl plik

@ -597,21 +597,6 @@ char* make_memory_map(stlink_t *sl) {
return(map);
}
/*
* DWT_COMP0 0xE0001020
* DWT_MASK0 0xE0001024
* DWT_FUNCTION0 0xE0001028
* DWT_COMP1 0xE0001030
* DWT_MASK1 0xE0001034
* DWT_FUNCTION1 0xE0001038
* DWT_COMP2 0xE0001040
* DWT_MASK2 0xE0001044
* DWT_FUNCTION2 0xE0001048
* DWT_COMP3 0xE0001050
* DWT_MASK3 0xE0001054
* DWT_FUNCTION3 0xE0001058
*/
#define DATA_WATCH_NUM 4
enum watchfun { WATCHDISABLED = 0, WATCHREAD = 5, WATCHWRITE = 6, WATCHACCESS = 7 };
@ -628,15 +613,15 @@ static void init_data_watchpoints(stlink_t *sl) {
uint32_t data;
DLOG("init watchpoints\n");
stlink_read_debug32(sl, 0xE000EDFC, &data);
data |= 1 << 24;
// set trcena in debug command to turn on dwt unit
stlink_write_debug32(sl, 0xE000EDFC, data);
// set TRCENA in debug command to turn on DWT unit
stlink_read_debug32(sl, STLINK_REG_CM3_DEMCR, &data);
data |= STLINK_REG_CM3_DEMCR_TRCENA;
stlink_write_debug32(sl, STLINK_REG_CM3_DEMCR, data);
// make sure all watchpoints are cleared
for (int i = 0; i < DATA_WATCH_NUM; i++) {
data_watches[i].fun = WATCHDISABLED;
stlink_write_debug32(sl, 0xe0001028 + i * 16, 0);
stlink_write_debug32(sl, STLINK_REG_CM3_DWT_FUNn(i), 0);
}
}
@ -667,16 +652,16 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr
data_watches[i].mask = mask;
// insert comparator address
stlink_write_debug32(sl, 0xE0001020 + i * 16, addr);
stlink_write_debug32(sl, STLINK_REG_CM3_DWT_COMPn(i), addr);
// insert mask
stlink_write_debug32(sl, 0xE0001024 + i * 16, mask);
stlink_write_debug32(sl, STLINK_REG_CM3_DWT_MASKn(i), mask);
// insert function
stlink_write_debug32(sl, 0xE0001028 + i * 16, wf);
stlink_write_debug32(sl, STLINK_REG_CM3_DWT_FUNn(i), wf);
// just to make sure the matched bit is clear !
stlink_read_debug32(sl, 0xE0001028 + i * 16, &dummy);
stlink_read_debug32(sl, STLINK_REG_CM3_DWT_FUNn(i), &dummy);
return(0);
}
}
@ -693,7 +678,7 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr) {
DLOG("delete watchpoint %d addr %x\n", i, addr);
data_watches[i].fun = WATCHDISABLED;
stlink_write_debug32(sl, 0xe0001028 + i * 16, 0);
stlink_write_debug32(sl, STLINK_REG_CM3_DWT_FUNn(i), 0);
return(0);
}
@ -706,9 +691,13 @@ static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr) {
static int code_break_num;
static int code_lit_num;
static int code_break_rev;
#define CODE_BREAK_NUM_MAX 15
#define CODE_BREAK_LOW 0x01
#define CODE_BREAK_HIGH 0x02
#define CODE_BREAK_REMAP 0x04
#define CODE_BREAK_REV_V1 0x00
#define CODE_BREAK_REV_V2 0x01
struct code_hw_breakpoint {
stm32_addr_t addr;
@ -720,16 +709,24 @@ static struct code_hw_breakpoint code_breaks[CODE_BREAK_NUM_MAX];
static void init_code_breakpoints(stlink_t *sl) {
unsigned int val;
memset(sl->q_buf, 0, 4);
stlink_write_debug32(sl, STLINK_REG_CM3_FP_CTRL, 0x03 /* KEY | ENABLE4 */);
stlink_write_debug32(sl, STLINK_REG_CM3_FP_CTRL, 0x03 /* KEY | ENABLE */);
stlink_read_debug32(sl, STLINK_REG_CM3_FP_CTRL, &val);
code_break_num = ((val >> 4) & 0xf);
code_lit_num = ((val >> 8) & 0xf);
code_break_rev = ((val >> 28) & 0xf);
ILOG("Found %i hw breakpoint registers\n", code_break_num);
stlink_read_debug32(sl, STLINK_REG_CM3_CPUID, &val);
if (((val>>4) & 0xFFF) == 0xC27) {
// Cortex-M7 can have locked to write FP_* registers
// IHI0029D, p. 48, Lock Access Register
stlink_write_debug32(sl, STLINK_REG_CM7_FP_LAR, STLINK_REG_CM7_FP_LAR_KEY);
}
for (int i = 0; i < code_break_num; i++) {
code_breaks[i].type = 0;
stlink_write_debug32(sl, STLINK_REG_CM3_FP_COMP0 + i * 4, 0);
stlink_write_debug32(sl, STLINK_REG_CM3_FP_COMPn(i), 0);
}
}
@ -741,69 +738,54 @@ static int has_breakpoint(stm32_addr_t addr) {
}
static int update_code_breakpoint(stlink_t *sl, stm32_addr_t addr, int set) {
stm32_addr_t fpb_addr;
uint32_t mask;
int type = (addr & 0x2) ? CODE_BREAK_HIGH : CODE_BREAK_LOW;
int type;
stm32_addr_t fpb_addr;
if (addr & 1) {
ELOG("update_code_breakpoint: unaligned address %08x\n", addr);
return(-1);
}
if (sl->core_id == STM32F7_CORE_ID) {
fpb_addr = addr;
if (code_break_rev == CODE_BREAK_REV_V1) {
type = (addr & 0x2) ? CODE_BREAK_HIGH : CODE_BREAK_LOW;
fpb_addr = addr & 0x1FFFFFFC;
} else {
fpb_addr = addr & ~0x3;
type = CODE_BREAK_REMAP;
fpb_addr = addr;
}
int id = -1;
for (int i = 0; i < code_break_num; i++)
if (fpb_addr == code_breaks[i].addr || (set && code_breaks[i].type == 0)) {
id = i;
break;
}
if (id == -1) {
if (set) {
return(-1);
} // free slot not found
else {
return(0);
} // breakpoint is already removed
if (set)
return(-1); // free slot not found
else
return(0); // breakpoint is already removed
}
struct code_hw_breakpoint* bp = &code_breaks[id];
bp->addr = fpb_addr;
if (sl->core_id == STM32F7_CORE_ID) {
if (set) {
bp->type = type;
} else {
bp->type = 0;
}
mask = (bp->addr) | 1;
} else {
if (set) {
bp->type |= type;
} else {
bp->type &= ~type;
}
mask = (bp->addr) | 1 | (bp->type << 30);
}
if (set)
bp->type |= type;
else
bp->type &= ~type;
// DDI0403E, p. 759, FP_COMPn register description
mask = ((bp->type&0x03) << 30) | bp->addr | 1;
if (bp->type == 0) {
DLOG("clearing hw break %d\n", id);
stlink_write_debug32(sl, 0xe0002008 + id * 4, 0);
stlink_write_debug32(sl, STLINK_REG_CM3_FP_COMPn(id), 0);
} else {
DLOG("setting hw break %d at %08x (%d)\n", id, bp->addr, bp->type);
DLOG("reg %08x \n", mask);
stlink_write_debug32(sl, 0xe0002008 + id * 4, mask);
stlink_write_debug32(sl, STLINK_REG_CM3_FP_COMPn(id), mask);
}
return(0);
@ -887,13 +869,33 @@ static int flash_populate(stm32_addr_t addr, uint8_t* data, unsigned length) {
static int flash_go(stlink_t *sl) {
int error = -1;
int ret;
flash_loader_t fl;
// some kinds of clock settings do not allow writing to flash.
stlink_reset(sl);
stlink_force_debug(sl);
// delay to ensure that STM32 HSI clock and others have started up fully
usleep(10000);
for (struct flash_block* fb = flash_root; fb; fb = fb->next) {
DLOG("flash_do: block %08x -> %04x\n", fb->addr, fb->length);
ILOG("flash_erase: block %08x -> %04x\n", fb->addr, fb->length);
for (stm32_addr_t page = fb->addr; page < fb->addr + fb->length; page += (uint32_t)FLASH_PAGE) {
// update FLASH_PAGE
stlink_calculate_pagesize(sl, page);
ILOG("flash_erase: page %08x\n", page);
ret = stlink_erase_flash_page(sl, page);
if (ret) { goto error; }
}
}
ret = stlink_flashloader_start(sl, &fl);
if (ret) { goto error; }
for (struct flash_block* fb = flash_root; fb; fb = fb->next) {
ILOG("flash_do: block %08x -> %04x\n", fb->addr, fb->length);
for (stm32_addr_t page = fb->addr; page < fb->addr + fb->length; page += (uint32_t)FLASH_PAGE) {
unsigned length = fb->length - (page - fb->addr);
@ -901,15 +903,15 @@ static int flash_go(stlink_t *sl) {
// update FLASH_PAGE
stlink_calculate_pagesize(sl, page);
DLOG("flash_do: page %08x\n", page);
ILOG("flash_do: page %08x\n", page);
unsigned len = (length > FLASH_PAGE) ? (unsigned int)FLASH_PAGE : length;
int ret = stlink_write_flash(sl, page, fb->data + (page - fb->addr), len, 0);
if (ret < 0) { goto error; }
ret = stlink_flashloader_write(sl, &fl, page, fb->data + (page - fb->addr), len);
if (ret) { goto error; }
}
}
stlink_reset(sl);
stlink_flashloader_stop(sl);
stlink_soft_reset(sl, 1 /* halt on reset */);
error = 0;
error:
@ -924,16 +926,6 @@ error:
return(error);
}
#define CLIDR 0xE000ED78
#define CTR 0xE000ED7C
#define CCSIDR 0xE000ED80
#define CSSELR 0xE000ED84
#define CCR 0xE000ED14
#define CCR_DC (1 << 16)
#define CCR_IC (1 << 17)
#define DCCSW 0xE000EF6C
#define ICIALLU 0xE000EF50
struct cache_level_desc {
unsigned int nsets;
unsigned int nways;
@ -942,6 +934,8 @@ struct cache_level_desc {
};
struct cache_desc_t {
unsigned used;
// minimal line size in bytes
unsigned int dminline;
unsigned int iminline;
@ -968,7 +962,7 @@ static void read_cache_level_desc(stlink_t *sl, struct cache_level_desc *desc) {
unsigned int ccsidr;
unsigned int log2_nsets;
stlink_read_debug32(sl, CCSIDR, &ccsidr);
stlink_read_debug32(sl, STLINK_REG_CM7_CCSIDR, &ccsidr);
desc->nsets = ((ccsidr >> 13) & 0x3fff) + 1;
desc->nways = ((ccsidr >> 3) & 0x1ff) + 1;
desc->log2_nways = ceil_log2 (desc->nways);
@ -984,18 +978,22 @@ static void init_cache (stlink_t *sl) {
unsigned int ctr;
int i;
// assume only F7 has a cache
if (sl->core_id != STM32F7_CORE_ID) { return; }
stlink_read_debug32(sl, CLIDR, &clidr);
stlink_read_debug32(sl, CCR, &ccr);
stlink_read_debug32(sl, CTR, &ctr);
// Check have cache
stlink_read_debug32(sl, STLINK_REG_CM7_CTR, &ctr);
if ((ctr >> 29) != 0x04) {
cache_desc.used = 0;
return;
} else
cache_desc.used = 1;
cache_desc.dminline = 4 << ((ctr >> 16) & 0x0f);
cache_desc.iminline = 4 << (ctr & 0x0f);
stlink_read_debug32(sl, STLINK_REG_CM7_CLIDR, &clidr);
cache_desc.louu = (clidr >> 27) & 7;
stlink_read_debug32(sl, STLINK_REG_CM7_CCR, &ccr);
ILOG("Chip clidr: %08x, I-Cache: %s, D-Cache: %s\n",
clidr, ccr & CCR_IC ? "on" : "off", ccr & CCR_DC ? "on" : "off");
clidr, ccr & STLINK_REG_CM7_CCR_IC ? "on" : "off", ccr & STLINK_REG_CM7_CCR_DC ? "on" : "off");
ILOG(" cache: LoUU: %u, LoC: %u, LoUIS: %u\n",
(clidr >> 27) & 7, (clidr >> 24) & 7, (clidr >> 21) & 7);
ILOG(" cache: ctr: %08x, DminLine: %u bytes, IminLine: %u bytes\n", ctr,
@ -1007,13 +1005,13 @@ static void init_cache (stlink_t *sl) {
cache_desc.icache[i].width = 0;
if (ct == 2 || ct == 3 || ct == 4) { // data
stlink_write_debug32(sl, CSSELR, i << 1);
stlink_write_debug32(sl, STLINK_REG_CM7_CSSELR, i << 1);
ILOG("D-Cache L%d: ", i);
read_cache_level_desc(sl, &cache_desc.dcache[i]);
}
if (ct == 1 || ct == 3) { // instruction
stlink_write_debug32(sl, CSSELR, (i << 1) | 1);
stlink_write_debug32(sl, STLINK_REG_CM7_CSSELR, (i << 1) | 1);
ILOG("I-Cache L%d: ", i);
read_cache_level_desc(sl, &cache_desc.icache[i]);
}
@ -1023,7 +1021,7 @@ static void init_cache (stlink_t *sl) {
static void cache_flush(stlink_t *sl, unsigned ccr) {
int level;
if (ccr & CCR_DC) {
if (ccr & STLINK_REG_CM7_CCR_DC) {
for (level = cache_desc.louu - 1; level >= 0; level--) {
struct cache_level_desc *desc = &cache_desc.dcache[level];
unsigned addr;
@ -1035,15 +1033,15 @@ static void cache_flush(stlink_t *sl, unsigned ccr) {
unsigned int way;
for (way = 0; way < desc->nways; way++) {
stlink_write_debug32(sl, DCCSW, addr | (way << way_sh));
stlink_write_debug32(sl, STLINK_REG_CM7_DCCSW, addr | (way << way_sh));
}
}
}
}
// invalidate all I-cache to oPU
if (ccr & CCR_IC) {
stlink_write_debug32(sl, ICIALLU, 0);
if (ccr & STLINK_REG_CM7_CCR_IC) {
stlink_write_debug32(sl, STLINK_REG_CM7_ICIALLU, 0);
}
}
@ -1059,14 +1057,13 @@ static void cache_change(stm32_addr_t start, unsigned count) {
static void cache_sync(stlink_t *sl) {
unsigned ccr;
if (sl->core_id != STM32F7_CORE_ID) { return; }
if (!cache_desc.used) { return; }
if (!cache_modified) { return; }
cache_modified = 0;
stlink_read_debug32(sl, CCR, &ccr);
if (ccr & (CCR_IC | CCR_DC)) { cache_flush(sl, ccr); }
stlink_read_debug32(sl, STLINK_REG_CM7_CCR, &ccr);
if (ccr & (STLINK_REG_CM7_CCR_IC | STLINK_REG_CM7_CCR_DC)) { cache_flush(sl, ccr); }
}
static size_t unhexify(const char *in, char *out, size_t out_count) {
@ -1417,8 +1414,8 @@ int serve(stlink_t *sl, st_state_t *st) {
free(decoded);
} else if (!strcmp(cmdName, "FlashDone")) {
if (flash_go(sl) < 0) {
reply = strdup("E00");
if (flash_go(sl)) {
reply = strdup("E08");
} else {
reply = strdup("OK");
}
@ -1832,7 +1829,6 @@ int serve(stlink_t *sl, st_state_t *st) {
case 'R': {
// reset the core.
ret = stlink_reset(sl);
if (ret) { DLOG("R packet : stlink_reset failed\n"); }
init_code_breakpoints(sl);

Wyświetl plik

@ -619,8 +619,9 @@ static const struct stlink_chipid_params devices[] = {
{
// STM32H742/743/753 (from RM0433)
.chip_id = STLINK_CHIPID_STM32_H74XXX,
.description = "H742/743/753",
.description = "H74x/H75x",
.flash_type = STLINK_FLASH_TYPE_H7,
.has_dual_bank = true,
.flash_size_reg = 0x1ff1e880, // "Flash size register" (pg3272)
.flash_pagesize = 0x20000, // 128k sector (pg147)
.sram_size = 0x20000, // 128k "DTCM" from Table 7
@ -629,6 +630,34 @@ static const struct stlink_chipid_params devices[] = {
.option_base = STM32_H7_OPTION_BYTES_BASE,
.option_size = 44, // FLASH_OPTSR_CUR to FLASH_BOOT_PRGR from Table 28
},
{
// STM32H7A3/7B3 (from RM0455)
.chip_id = STLINK_CHIPID_STM32_H7AX,
.description = "H7Ax/H7Bx",
.flash_type = STLINK_FLASH_TYPE_H7,
.has_dual_bank = true,
.flash_size_reg = 0x08FFF80C, // "Flash size register" (p.2949)
.flash_pagesize = 0x2000, // 8k sector (p.146)
.sram_size = 0x20000, // 128k "DTCM" (Figure 1)
.bootrom_base = 0x1FF00000, // "System memory" starting address (Table 12-14)
.bootrom_size = 0x20000, // "System memory" byte size in hex splitted to two banks (Table 12-14)
.option_base = STM32_H7_OPTION_BYTES_BASE,
.option_size = 44,
},
{
// STM32H72x/H73x (from RM0468)
.chip_id = STLINK_CHIPID_STM32_H72X,
.description = "H72x/H73x",
.flash_type = STLINK_FLASH_TYPE_H7,
.flash_size_reg = 0x1FF1E880, // "Flash size register" (p.3286)
.flash_pagesize = 0x20000, // 128k sector (p.152)
.sram_size = 0x20000, // 128k "DTCM" (Figure 1)
.bootrom_base = 0x1FF00000, // "System memory" starting address (Table 6)
.bootrom_size = 0x20000, // "System memory" byte size in hex (Table 6)
.option_base = STM32_H7_OPTION_BYTES_BASE,
.option_size = 44,
},
{
// unknown
.chip_id = STLINK_CHIPID_UNKNOWN,

Wyświetl plik

@ -64,6 +64,8 @@ enum stlink_stm32_chipids {
STLINK_CHIPID_STM32_G4_CAT2 = 0x468, /* See: RM 0440 s46.6.1 "MCU device ID code" */
STLINK_CHIPID_STM32_G4_CAT3 = 0x469,
STLINK_CHIPID_STM32_L4RX = 0x470, /* ID found on the STM32L4R9I-DISCO board */
STLINK_CHIPID_STM32_H7AX = 0x480, /* RM0455, p. 2863 */
STLINK_CHIPID_STM32_H72X = 0x483, /* RM0468, p. 3199 */
STLINK_CHIPID_STM32_WB55 = 0x495
};

Wyświetl plik

@ -316,6 +316,8 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe
int i = 0;
size_t count = 0;
uint32_t flash_base = 0;
const char *error = NULL;
uint32_t dhcsr, dfsr;
DLOG("Running flash loader, write address:%#x, size: %u\n", target, (unsigned int)size);
@ -376,17 +378,26 @@ int stlink_flash_loader_run(stlink_t *sl, flash_loader_t* fl, stm32_addr_t targe
}
if (i >= WAIT_ROUNDS) {
ELOG("flash loader run error\n");
return(-1);
error = "Flash loader run error";
goto error;
}
// check written byte count
stlink_read_reg(sl, 2, &rr);
if (rr.r[2] != 0) {
ELOG("write error, count == %u\n", rr.r[2]);
return(-1);
error = "Write error";
goto error;
}
return(0);
error:
dhcsr = dfsr = 0;
stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr);
stlink_read_debug32(sl, STLINK_REG_DFSR, &dfsr);
stlink_read_all_regs(sl, &rr);
ELOG("%s (R2 0x%08X R15 0x%08X DHCSR 0x%08X DFSR 0x%08X)\n", error, rr.r[2], rr.r[15], dhcsr, dfsr);
return(-1);
}

Wyświetl plik

@ -0,0 +1,15 @@
#include <helper.h>
#include <stddef.h>
#ifdef STLINK_HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <sys_time.h>
#endif
unsigned time_ms() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (unsigned)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

Wyświetl plik

@ -0,0 +1,6 @@
#ifndef SYS_HELPER_H
#define SYS_HELPER_H
unsigned time_ms();
#endif /* SYS_HELPER_H */

Wyświetl plik

@ -2,19 +2,60 @@
#define STLINK_REG_H_
#define STLINK_REG_CM3_CPUID 0xE000ED00
#define STLINK_REG_CM3_FP_CTRL 0xE0002000
#define STLINK_REG_CM3_FP_COMP0 0xE0002008
#define STLINK_REG_CM3_FP_COMPn(n) (0xE0002008 + n*4)
#define STLINK_REG_CM7_FP_LAR 0xE0000FB0
#define STLINK_REG_CM7_FP_LAR_KEY 0xC5ACCE55
#define STLINK_REG_CM3_DEMCR 0xE000EDFC
#define STLINK_REG_CM3_DEMCR_TRCENA (1 << 24)
#define STLINK_REG_CM3_DEMCR_VC_HARDERR (1 << 10)
#define STLINK_REG_CM3_DEMCR_VC_BUSERR (1 << 8)
#define STLINK_REG_CM3_DEMCR_VC_CORERESET (1 << 0)
#define STLINK_REG_CM3_DWT_COMPn(n) (0xE0001020 + n*16)
#define STLINK_REG_CM3_DWT_MASKn(n) (0xE0001024 + n*16)
#define STLINK_REG_CM3_DWT_FUNn(n) (0xE0001028 + n*16)
/* Cortex™-M3 Technical Reference Manual */
/* Debug Halting Control and Status Register */
#define STLINK_REG_DFSR 0xE000ED30
#define STLINK_REG_DFSR_HALT (1 << 0)
#define STLINK_REG_DFSR_BKPT (1 << 1)
#define STLINK_REG_DFSR_VCATCH (1 << 3)
#define STLINK_REG_DFSR_EXTERNAL (1 << 4)
#define STLINK_REG_DFSR_CLEAR 0x0000001F
#define STLINK_REG_DHCSR 0xe000edf0
#define STLINK_REG_DHCSR_DBGKEY 0xa05f0000
#define STLINK_REG_DHCSR_DBGKEY (0xA05F << 16)
#define STLINK_REG_DHCSR_C_DEBUGEN (1 << 0)
#define STLINK_REG_DHCSR_C_HALT (1 << 1)
#define STLINK_REG_DHCSR_C_STEP (1 << 2)
#define STLINK_REG_DHCSR_C_MASKINTS (1 << 3)
#define STLINK_REG_DHCSR_S_REGRDY (1 << 16)
#define STLINK_REG_DHCSR_S_HALT (1 << 17)
#define STLINK_REG_DHCSR_S_SLEEP (1 << 18)
#define STLINK_REG_DHCSR_S_LOCKUP (1 << 19)
#define STLINK_REG_DHCSR_S_RETIRE_ST (1 << 24)
#define STLINK_REG_DHCSR_S_RESET_ST (1 << 25)
#define STLINK_REG_DCRSR 0xe000edf4
#define STLINK_REG_DCRDR 0xe000edf8
/* Application Interrupt and Reset Control Register */
#define STLINK_REG_AIRCR 0xe000ed0c
#define STLINK_REG_AIRCR_VECTKEY 0x05fa0000
#define STLINK_REG_AIRCR_SYSRESETREQ 0x00000004
#define STLINK_REG_AIRCR_VECTKEY 0x05fa0000
#define STLINK_REG_AIRCR_SYSRESETREQ 0x00000004
#define STLINK_REG_AIRCR_VECTRESET 0x00000001
/* ARM Cortex-M7 Processor Technical Reference Manual */
/* Cache Control and Status Register */
#define STLINK_REG_CM7_CTR 0xE000ED7C
#define STLINK_REG_CM7_CLIDR 0xE000ED78
#define STLINK_REG_CM7_CCR 0xE000ED14
#define STLINK_REG_CM7_CCR_DC (1 << 16)
#define STLINK_REG_CM7_CCR_IC (1 << 17)
#define STLINK_REG_CM7_CSSELR 0xE000ED84
#define STLINK_REG_CM7_DCCSW 0xE000EF6C
#define STLINK_REG_CM7_ICIALLU 0xE000EF50
#define STLINK_REG_CM7_CCSIDR 0xE000ED80
#endif // STLINK_REG_H_

Wyświetl plik

@ -17,6 +17,7 @@
#endif
#include <stlink.h>
#include <helper.h>
#include "usb.h"
enum SCSI_Generic_Direction {SG_DXFER_TO_DEV = 0, SG_DXFER_FROM_DEV = 0x80};
@ -261,7 +262,7 @@ int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
}
int _stlink_usb_get_rw_status(stlink_t *sl) {
if (sl->version.jtag_api == STLINK_JTAG_API_V1) { return(-1); }
if (sl->version.jtag_api == STLINK_JTAG_API_V1) { return(0); }
unsigned char* const rdata = sl->q_buf;
struct stlink_libusb * const slu = sl->backend_data;
@ -354,15 +355,17 @@ int _stlink_usb_core_id(stlink_t * sl) {
unsigned char* const cmd = sl->c_buf;
unsigned char* const data = sl->q_buf;
ssize_t size;
int rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 4 : 12;
int offset, rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 4 : 12;
int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
if (sl->version.jtag_api == STLINK_JTAG_API_V1) {
cmd[i++] = STLINK_DEBUG_READCOREID;
offset = 0;
} else {
cmd[i++] = STLINK_DEBUG_APIV2_READ_IDCODES;
offset = 4;
}
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
@ -372,11 +375,7 @@ int _stlink_usb_core_id(stlink_t * sl) {
return(-1);
}
if (sl->version.jtag_api == STLINK_JTAG_API_V1) {
sl->core_id = read_uint32(data, 0);
} else {
sl->core_id = read_uint32(data, 4);
}
sl->core_id = read_uint32(data, offset);
return(0);
}
@ -385,15 +384,15 @@ int _stlink_usb_status_v2(stlink_t *sl) {
int result;
uint32_t status = 0;
result = _stlink_usb_read_debug32(sl, DCB_DHCSR, &status);
result = _stlink_usb_read_debug32(sl, STLINK_REG_DHCSR, &status);
DLOG("core status: %08X\n", status);
if (result != 0) {
sl->core_stat = TARGET_UNKNOWN;
} else {
if (status & S_HALT) {
if (status & STLINK_REG_DHCSR_C_HALT) {
sl->core_stat = TARGET_HALTED;
} else if (status & S_RESET_ST) {
} else if (status & STLINK_REG_DHCSR_S_RESET_ST) {
sl->core_stat = TARGET_RESET;
} else {
sl->core_stat = TARGET_RUNNING;
@ -439,6 +438,14 @@ int _stlink_usb_status(stlink_t * sl) {
int _stlink_usb_force_debug(stlink_t *sl) {
struct stlink_libusb *slu = sl->backend_data;
int res;
if (sl->version.jtag_api != STLINK_JTAG_API_V1) {
res = _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_HALT | STLINK_REG_DHCSR_C_DEBUGEN);
return(res);
}
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
@ -508,9 +515,15 @@ int _stlink_usb_reset(stlink_t * sl) {
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
int rep_len = 2;
int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
uint32_t dhcsr;
unsigned timeout;
int i, rep_len = 2;
// clear S_RESET_ST in DHCSR registr
_stlink_usb_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr);
// send reset command
i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
if (sl->version.jtag_api == STLINK_JTAG_API_V1) {
@ -526,9 +539,30 @@ int _stlink_usb_reset(stlink_t * sl) {
return((int)size);
}
// reset through AIRCR so that NRST does not need to be connected
return(stlink_write_debug32(sl, STLINK_REG_AIRCR, STLINK_REG_AIRCR_VECTKEY |
STLINK_REG_AIRCR_SYSRESETREQ));
usleep(10000);
dhcsr = 0;
_stlink_usb_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr);
if ((dhcsr & STLINK_REG_DHCSR_S_RESET_ST) == 0) {
// reset not done yet
// try reset through AIRCR so that NRST does not need to be connected
WLOG("NRST is not connected\n");
DLOG("Using reset through SYSRESETREQ\n");
return stlink_soft_reset(sl, 0);
}
// waiting for a reset within 500ms
timeout = time_ms() + 500;
while (time_ms() < timeout) {
// DDI0337E, p. 10-4, Debug Halting Control and Status Register
dhcsr = STLINK_REG_DHCSR_S_RESET_ST;
_stlink_usb_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr);
if ((dhcsr&STLINK_REG_DHCSR_S_RESET_ST) == 0)
return(0);
}
return(-1);
}
int _stlink_usb_jtag_reset(stlink_t * sl, int value) {
@ -555,6 +589,17 @@ int _stlink_usb_jtag_reset(stlink_t * sl, int value) {
int _stlink_usb_step(stlink_t* sl) {
struct stlink_libusb * const slu = sl->backend_data;
if (sl->version.jtag_api != STLINK_JTAG_API_V1) {
// emulates the JTAG v1 API by using DHCSR
_stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_HALT |
STLINK_REG_DHCSR_C_MASKINTS | STLINK_REG_DHCSR_C_DEBUGEN);
_stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_STEP |
STLINK_REG_DHCSR_C_MASKINTS | STLINK_REG_DHCSR_C_DEBUGEN);
return _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_HALT |
STLINK_REG_DHCSR_C_DEBUGEN);
}
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
@ -583,7 +628,7 @@ int _stlink_usb_run(stlink_t* sl) {
int res;
if (sl->version.jtag_api != STLINK_JTAG_API_V1) {
res = _stlink_usb_write_debug32(sl, DCB_DHCSR, DBGKEY | C_DEBUGEN);
res = _stlink_usb_write_debug32(sl, STLINK_REG_DHCSR, STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN);
return(res);
}
@ -606,7 +651,7 @@ int _stlink_usb_run(stlink_t* sl) {
return(0);
}
int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) {
int _stlink_usb_set_swdclk(stlink_t* sl, int clk_freq) {
struct stlink_libusb * const slu = sl->backend_data;
unsigned char* const data = sl->q_buf;
unsigned char* const cmd = sl->c_buf;
@ -616,6 +661,28 @@ int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) {
// clock speed only supported by stlink/v2 and for firmware >= 22
if (sl->version.stlink_v == 2 && sl->version.jtag_v >= 22) {
uint16_t clk_divisor;
if (clk_freq) {
const uint32_t map[] = {5, 15, 25, 50, 100, 125, 240, 480, 950, 1200, 1800, 4000};
int speed_index = _stlink_match_speed_map(map, STLINK_ARRAY_SIZE(map), clk_freq);
switch (map[speed_index]) {
case 5: clk_divisor = STLINK_SWDCLK_5KHZ_DIVISOR; break;
case 15: clk_divisor = STLINK_SWDCLK_15KHZ_DIVISOR; break;
case 25: clk_divisor = STLINK_SWDCLK_25KHZ_DIVISOR; break;
case 50: clk_divisor = STLINK_SWDCLK_50KHZ_DIVISOR; break;
case 100: clk_divisor = STLINK_SWDCLK_100KHZ_DIVISOR; break;
case 125: clk_divisor = STLINK_SWDCLK_125KHZ_DIVISOR; break;
case 240: clk_divisor = STLINK_SWDCLK_240KHZ_DIVISOR; break;
case 480: clk_divisor = STLINK_SWDCLK_480KHZ_DIVISOR; break;
case 950: clk_divisor = STLINK_SWDCLK_950KHZ_DIVISOR; break;
case 1200: clk_divisor = STLINK_SWDCLK_1P2MHZ_DIVISOR; break;
default:
case 1800: clk_divisor = STLINK_SWDCLK_1P8MHZ_DIVISOR; break;
case 4000: clk_divisor = STLINK_SWDCLK_4MHZ_DIVISOR; break;
}
} else
clk_divisor = STLINK_SWDCLK_1P8MHZ_DIVISOR;
i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
@ -646,7 +713,6 @@ int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) {
}
int speeds_size = data[8];
if (speeds_size > STLINK_V3_MAX_FREQ_NB) {
speeds_size = STLINK_V3_MAX_FREQ_NB;
}
@ -656,7 +722,8 @@ int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) {
// Set to zero all the next entries
for (i = speeds_size; i < STLINK_V3_MAX_FREQ_NB; i++) map[i] = 0;
speed_index = _stlink_match_speed_map(map, STLINK_ARRAY_SIZE(map), 1800);
if (!clk_freq) clk_freq = 1800; // set default frequency
speed_index = _stlink_match_speed_map(map, STLINK_ARRAY_SIZE(map), clk_freq);
i = fill_command(sl, SG_DXFER_FROM_DEV, 16);
@ -764,11 +831,11 @@ int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
if (sl->verbose < 2) { return(0); }
DLOG("xpsr = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 64));
DLOG("main_sp = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 68));
DLOG("process_sp = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 72));
DLOG("rw = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 76));
DLOG("rw2 = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 80));
DLOG("xpsr = 0x%08x\n", regp->xpsr);
DLOG("main_sp = 0x%08x\n", regp->main_sp);
DLOG("process_sp = 0x%08x\n", regp->process_sp);
DLOG("rw = 0x%08x\n", regp->rw);
DLOG("rw2 = 0x%08x\n", regp->rw2);
return(0);
}
@ -1183,45 +1250,7 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, int reset, char serial[STL
// should be done at this speed too
// set the stlink clock speed (default is 1800kHz)
DLOG("JTAG/SWD freq set to %d\n", freq);
switch (freq) {
case 5:
stlink_set_swdclk(sl, STLINK_SWDCLK_5KHZ_DIVISOR);
break;
case 15:
stlink_set_swdclk(sl, STLINK_SWDCLK_15KHZ_DIVISOR);
break;
case 25:
stlink_set_swdclk(sl, STLINK_SWDCLK_25KHZ_DIVISOR);
break;
case 50:
stlink_set_swdclk(sl, STLINK_SWDCLK_50KHZ_DIVISOR);
break;
case 100:
stlink_set_swdclk(sl, STLINK_SWDCLK_100KHZ_DIVISOR);
break;
case 125:
stlink_set_swdclk(sl, STLINK_SWDCLK_125KHZ_DIVISOR);
break;
case 240:
stlink_set_swdclk(sl, STLINK_SWDCLK_240KHZ_DIVISOR);
break;
case 480:
stlink_set_swdclk(sl, STLINK_SWDCLK_480KHZ_DIVISOR);
break;
case 950:
stlink_set_swdclk(sl, STLINK_SWDCLK_950KHZ_DIVISOR);
break;
case 1200:
stlink_set_swdclk(sl, STLINK_SWDCLK_1P2MHZ_DIVISOR);
break;
case 0: case 1800:
stlink_set_swdclk(sl, STLINK_SWDCLK_1P8MHZ_DIVISOR);
break;
case 4000:
stlink_set_swdclk(sl, STLINK_SWDCLK_4MHZ_DIVISOR);
break;
}
stlink_set_swdclk(sl, freq);
if (reset == 2) {
stlink_jtag_reset(sl, 0);

Wyświetl plik

@ -0,0 +1,20 @@
#include <stdlib.h>
#include <unistd.h>
#include "sys_time.h"
/* Simple gettimeofday implementation without converting Windows time to Linux time */
int gettimeofday(struct timeval *tv, struct timezone *tz) {
FILETIME ftime;
ULARGE_INTEGER ulint;
GetSystemTimeAsFileTime(&ftime);
ulint.LowPart = ftime.dwLowDateTime;
ulint.HighPart = ftime.dwHighDateTime;
tv->tv_sec = (long)(ulint.QuadPart / 10000000L);
tv->tv_usec = (long)(ulint.QuadPart % 10000000L);
return 0;
(void)tz;
}

Wyświetl plik

@ -0,0 +1,30 @@
#ifndef STLINK_TIME_H
#define STLINK_TIME_H
#ifdef STLINK_HAVE_SYS_TIME_H
#include <sys/time.h>
#else
struct timeval {
long tv_sec;
long tv_usec;
};
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
#ifdef __cplusplus
extern "C" {
#endif
int gettimeofday(struct timeval *tv, struct timezone *tz);
#ifdef __cplusplus
}
#endif
#endif /* STLINK_HAVE_SYS_TIME_H */
#endif /* STLINK_TIME_H */