kopia lustrzana https://github.com/stlink-org/stlink
Merge pull request #1071 from Ant-ON/try_h7_debug
[feature] Improved support for STM32H7pull/1073/head
commit
b47f083736
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_
|
||||
|
|
26
inc/stlink.h
26
inc/stlink.h
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
1037
src/common.c
1037
src/common.c
Plik diff jest za duży
Load Diff
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef SYS_HELPER_H
|
||||
#define SYS_HELPER_H
|
||||
|
||||
unsigned time_ms();
|
||||
|
||||
#endif /* SYS_HELPER_H */
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
Ładowanie…
Reference in New Issue