int main(int ac, char** av) { stlink_t* sl = NULL; int err = -1; if (ac < 2) { usage(); return -1; } sl = open_sl(); if (sl == NULL) { return -1; } sl->verbose=0; if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) stlink_exit_dfu_mode(sl); if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) stlink_enter_swd_mode(sl); err = print_data(sl, av); if (sl != NULL) { stlink_exit_debug_mode(sl); stlink_close(sl); } return err; }
int main(int ac, char** av) { stlink_t* sl = NULL; struct opts o; int err = -1; if (get_opts(&o, ac - 1, av + 1) == -1) { printf("invalid command line\n"); usage(); goto on_error; } if (o.devname != NULL) /* stlinkv1 */ { sl = stlink_v1_open(100); if (sl == NULL) goto on_error; } else /* stlinkv2 */ { sl = stlink_open_usb(100); if (sl == NULL) goto on_error; } if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) stlink_exit_dfu_mode(sl); if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) stlink_enter_swd_mode(sl); stlink_reset(sl); if (o.do_read == 0) /* write */ { err = stlink_fwrite_flash(sl, o.filename, o.addr); if (err == -1) { printf("stlink_fwrite_flash() == -1\n"); goto on_error; } } else /* read */ { err = stlink_fread(sl, o.filename, o.addr, o.size); if (err == -1) { printf("stlink_fread() == -1\n"); goto on_error; } } /* success */ err = 0; on_error: if (sl != NULL) stlink_close(sl); return err; }
int main(int argc, char** argv) { if(argc != 3) { fprintf(stderr, "Usage: %s <port> /dev/sgX\n", argv[0]); return 1; } struct stlink *sl = stlink_quirk_open(argv[2], 0); if (sl == NULL) return 1; if(stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) stlink_enter_swd_mode(sl); uint32_t chip_id; stlink_read_mem32(sl, 0xE0042000, 4); chip_id = sl->q_buf[0] | (sl->q_buf[1] << 8) | (sl->q_buf[2] << 16) | (sl->q_buf[3] << 24); printf("Chip ID is %08x.\n", chip_id); const struct chip_params* params = NULL; for(int i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) { if(devices[i].chip_id == (chip_id & 0xFFF)) { params = &devices[i]; break; } } if(params == NULL) { fprintf(stderr, "Cannot recognize the connected device!\n"); return 0; } printf("Device connected: %s\n", params->description); printf("Device parameters: SRAM: 0x%x bytes, Flash: up to 0x%x bytes in pages of 0x%x bytes\n", params->sram_size, params->max_flash_size, params->flash_pagesize); FLASH_PAGE = params->flash_pagesize; uint32_t flash_size; stlink_read_mem32(sl, 0x1FFFF7E0, 4); flash_size = sl->q_buf[0] | (sl->q_buf[1] << 8); printf("Flash size is %d KiB.\n", flash_size); // memory map is in 1k blocks. current_memory_map = make_memory_map(params, flash_size * 0x400); int port = atoi(argv[1]); while(serve(sl, port) == 0); stlink_close(sl); return 0; }
static void cleanup(int signal __attribute__((unused))) { if (connected_stlink) { /* Switch back to mass storage mode before closing. */ stlink_run(connected_stlink); stlink_exit_debug_mode(connected_stlink); stlink_close(connected_stlink); } exit(1); }
static int print_data(char **av) { stlink_t* sl = NULL; // Probe needs all devices unclaimed if (strcmp(av[1], "--probe") == 0) { stlink_probe(); return 0; } else if (strcmp(av[1], "--version") == 0) { printf("v%s\n", STLINK_VERSION); return 0; } sl = stlink_open_first(); if (sl == NULL) { return -1; } sl->verbose = 0; if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) stlink_exit_dfu_mode(sl); if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) stlink_enter_swd_mode(sl); if (strcmp(av[1], "--flash") == 0) printf("0x%x\n", (unsigned int)sl->flash_size); else if (strcmp(av[1], "--sram") == 0) printf("0x%x\n", (unsigned int)sl->sram_size); else if (strcmp(av[1], "--pagesize") == 0) printf("0x%x\n", (unsigned int)sl->flash_pgsz); else if (strcmp(av[1], "--chipid") == 0) printf("0x%.4x\n", sl->chip_id); else if (strcmp(av[1], "--serial") == 0) stlink_print_serial(sl, false); else if (strcmp(av[1], "--hla-serial") == 0) stlink_print_serial(sl, true); else if (strcmp(av[1], "--descr") == 0) { const struct stlink_chipid_params *params = stlink_chipid_get_params(sl->chip_id); if (params == NULL) return -1; printf("%s\n", params->description); } if (sl) { stlink_exit_debug_mode(sl); stlink_close(sl); } return 0; }
static void cleanup(int signum) { (void)signum; if (connected_stlink) { /* Switch back to mass storage mode before closing. */ stlink_run(connected_stlink); stlink_exit_debug_mode(connected_stlink); stlink_close(connected_stlink); } exit(1); }
static void cleanup(int signal __attribute__((unused))) { if (sl) { /* Switch back to mass storage mode before closing. */ stlink_run(sl); stlink_exit_debug_mode(sl); stlink_close(sl); } printf("\n"); nonblock(0); exit(1); }
int main() { stlink_t* sl = NULL; sl = stlink_open_first(); if (sl == NULL) { fprintf(stderr, "Failed to open stlink device ;(\n"); exit(1); } fprintf(stderr, "STlink device opened, that's cool!\n"); stlink_close(sl); return 0; }
static void disconnect_button_cb (GtkWidget *widget, gpointer data) { STlinkGUI *gui; gui = STLINK_GUI (data); if (gui->sl != NULL) { stlink_exit_debug_mode(gui->sl); stlink_close(gui->sl); gui->sl = NULL; } stlink_gui_set_disconnected (gui); }
int main(int argc, char** argv) { stlink_t *sl = NULL; st_state_t state; memset(&state, 0, sizeof(state)); // set defaults... state.stlink_version = 2; state.logging_level = DEFAULT_LOGGING_LEVEL; state.listen_port = DEFAULT_GDB_LISTEN_PORT; parse_options(argc, argv, &state); switch (state.stlink_version) { case 2: sl = stlink_open_usb(state.logging_level); if(sl == NULL) return 1; break; case 1: sl = stlink_v1_open(state.logging_level); if(sl == NULL) return 1; break; } printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id); sl->verbose=0; current_memory_map = make_memory_map(sl); #ifdef __MINGW32__ WSADATA wsadata; if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) { goto winsock_error; } #endif while(serve(sl, state.listen_port, state.elf_filename) == 0); #ifdef __MINGW32__ winsock_error: WSACleanup(); #endif /* Switch back to mass storage mode before closing. */ stlink_run(sl); stlink_exit_debug_mode(sl); stlink_close(sl); return 0; }
int main(int argc, char** argv) { sl = NULL; st_state_t state; memset(&state, 0, sizeof(state)); // set defaults... state.stlink_version = 2; state.logging_level = DEFAULT_LOGGING_LEVEL; state.listen_port = DEFAULT_GDB_LISTEN_PORT; parse_options(argc, argv, &state); switch (state.stlink_version) { case 2: sl = stlink_open_usb(state.logging_level); if(sl == NULL) return 1; break; case 1: sl = stlink_v1_open(state.logging_level); if(sl == NULL) return 1; break; } signal(SIGINT, catcher); printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id); sl->verbose=0; current_memory_map = make_memory_map(sl); while(serve(sl, state.listen_port) == state.perist_mode); /* Switch back to mass storage mode before closing. */ stlink_reset(sl); stlink_run(sl); stlink_exit_debug_mode(sl); stlink_close(sl); return 0; }
int main(int argc, char *argv[]) { // set scpi lib debug level: 0 for no debug info, 10 for lots const int scsi_verbose = 2; char *dev_name; switch (argc) { case 1: fputs( "\nUsage: stlink-access-test /dev/sg0, sg1, ...\n" "\n*** Notice: The stlink firmware violates the USB standard.\n" "*** If you plug-in the discovery's stlink, wait a several\n" "*** minutes to let the kernel driver swallow the broken device.\n" "*** Watch:\ntail -f /var/log/messages\n" "*** This command sequence can shorten the waiting time and fix some issues.\n" "*** Unplug the stlink and execute once as root:\n" "modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:lrwsro\n\n", stderr); return EXIT_FAILURE; case 2: dev_name = argv[1]; break; default: return EXIT_FAILURE; } fputs("*** stlink access test ***\n", stderr); fprintf(stderr, "Using sg_lib %s : scsi_pt %s\n", sg_lib_version(), scsi_pt_version()); stlink_t *sl = stlink_quirk_open(dev_name, scsi_verbose); if (sl == NULL) return EXIT_FAILURE; // we are in mass mode, go to swd stlink_enter_swd_mode(sl); stlink_current_mode(sl); stlink_core_id(sl); //---------------------------------------------------------------------- stlink_status(sl); //stlink_force_debug(sl); stlink_reset(sl); stlink_status(sl); #if 0 // core system control block stlink_read_mem32(sl, 0xe000ed00, 4); DD(sl, "cpu id base register: SCB_CPUID = got 0x%08x expect 0x411fc231", read_uint32(sl->q_buf, 0)); // no MPU stlink_read_mem32(sl, 0xe000ed90, 4); DD(sl, "mpu type register: MPU_TYPER = got 0x%08x expect 0x0", read_uint32(sl->q_buf, 0)); stlink_read_mem32(sl, 0xe000edf0, 4); DD(sl, "DHCSR = 0x%08x", read_uint32(sl->q_buf, 0)); stlink_read_mem32(sl, 0x4001100c, 4); DD(sl, "GPIOC_ODR = 0x%08x", read_uint32(sl->q_buf, 0)); #endif #if 0 // happy new year 2011: let blink all the leds // see "RM0041 Reference manual - STM32F100xx advanced ARM-based 32-bit MCUs" #define GPIOC 0x40011000 // port C #define GPIOC_CRH (GPIOC + 0x04) // port configuration register high #define GPIOC_ODR (GPIOC + 0x0c) // port output data register #define LED_BLUE (1<<8) // pin 8 #define LED_GREEN (1<<9) // pin 9 stlink_read_mem32(sl, GPIOC_CRH, 4); uint32_t io_conf = read_uint32(sl->q_buf, 0); DD(sl, "GPIOC_CRH = 0x%08x", io_conf); // set: general purpose output push-pull, output mode, max speed 10 MHz. write_uint32(sl->q_buf, 0x44444411); stlink_write_mem32(sl, GPIOC_CRH, 4); clear_buf(sl); for (int i = 0; i < 100; i++) { write_uint32(sl->q_buf, LED_BLUE | LED_GREEN); stlink_write_mem32(sl, GPIOC_ODR, 4); /* stlink_read_mem32(sl, 0x4001100c, 4); */ /* DD(sl, "GPIOC_ODR = 0x%08x", read_uint32(sl->q_buf, 0)); */ delay(100); clear_buf(sl); stlink_write_mem32(sl, GPIOC_ODR, 4); // PC lo delay(100); } write_uint32(sl->q_buf, io_conf); // set old state #endif #if 0 // TODO rtfm: stlink doesn't have flash write routines // writing to the flash area confuses the fw for the next read access //stlink_read_mem32(sl, 0, 1024*6); // flash 0x08000000 128kB fputs("++++++++++ read a flash at 0x0800 0000\n", stderr); stlink_read_mem32(sl, 0x08000000, 1024 * 6); //max 6kB clear_buf(sl); stlink_read_mem32(sl, 0x08000c00, 5); stlink_read_mem32(sl, 0x08000c00, 4); mark_buf(sl); stlink_write_mem32(sl, 0x08000c00, 4); stlink_read_mem32(sl, 0x08000c00, 256); stlink_read_mem32(sl, 0x08000c00, 256); #endif #if 0 // sram 0x20000000 8kB fputs("\n++++++++++ read/write 8bit, sram at 0x2000 0000 ++++++++++++++++\n\n", stderr); clear_buf(sl); stlink_write_mem8(sl, 0x20000000, 16); mark_buf(sl); stlink_write_mem8(sl, 0x20000000, 1); stlink_write_mem8(sl, 0x20000001, 1); stlink_write_mem8(sl, 0x2000000b, 3); stlink_read_mem32(sl, 0x20000000, 16); #endif #if 0 // a not aligned mem32 access doesn't work indeed fputs("\n++++++++++ read/write 32bit, sram at 0x2000 0000 ++++++++++++++++\n\n", stderr); clear_buf(sl); stlink_write_mem8(sl, 0x20000000, 32); mark_buf(sl); stlink_write_mem32(sl, 0x20000000, 1); stlink_read_mem32(sl, 0x20000000, 16); mark_buf(sl); stlink_write_mem32(sl, 0x20000001, 1); stlink_read_mem32(sl, 0x20000000, 16); mark_buf(sl); stlink_write_mem32(sl, 0x2000000b, 3); stlink_read_mem32(sl, 0x20000000, 16); mark_buf(sl); stlink_write_mem32(sl, 0x20000000, 17); stlink_read_mem32(sl, 0x20000000, 32); #endif #if 0 // sram 0x20000000 8kB fputs("++++++++++ read/write 32bit, sram at 0x2000 0000 ++++++++++++\n", stderr); mark_buf(sl); stlink_write_mem8(sl, 0x20000000, 64); stlink_read_mem32(sl, 0x20000000, 64); mark_buf(sl); stlink_write_mem32(sl, 0x20000000, 1024 * 8); //8kB stlink_read_mem32(sl, 0x20000000, 1024 * 6); stlink_read_mem32(sl, 0x20000000 + 1024 * 6, 1024 * 2); #endif #if 0 stlink_read_all_regs(sl); stlink_step(sl); fputs("++++++++++ write r0 = 0x12345678\n", stderr); stlink_write_reg(sl, 0x12345678, 0); stlink_read_reg(sl, 0); stlink_read_all_regs(sl); #endif #if 0 stlink_run(sl); stlink_status(sl); stlink_force_debug(sl); stlink_status(sl); #endif #if 1 /* read the system bootloader */ fputs("\n++++++++++ reading bootloader ++++++++++++++++\n\n", stderr); stlink_fread(sl, "/tmp/barfoo", sl->sys_base, sl->sys_size); #endif #if 0 /* read the flash memory */ fputs("\n+++++++ read flash memory\n\n", stderr); /* mark_buf(sl); */ stlink_read_mem32(sl, 0x08000000, 4); #endif #if 0 /* flash programming */ fputs("\n+++++++ program flash memory\n\n", stderr); stlink_fwrite_flash(sl, "/tmp/foobar", 0x08000000); #endif #if 0 /* check file contents */ fputs("\n+++++++ check flash memory\n\n", stderr); { const int res = stlink_fcheck_flash(sl, "/tmp/foobar", 0x08000000); printf("_____ stlink_fcheck_flash() == %d\n", res); } #endif #if 0 fputs("\n+++++++ sram write and execute\n\n", stderr); stlink_fwrite_sram(sl, "/tmp/foobar", sl->sram_base); stlink_run_at(sl, sl->sram_base); #endif stlink_run(sl); stlink_status(sl); //---------------------------------------------------------------------- // back to mass mode, just in case ... stlink_exit_debug_mode(sl); stlink_current_mode(sl); stlink_close(sl); //fflush(stderr); fflush(stdout); return EXIT_SUCCESS; }
int main(int argc, char** argv) { int32_t voltage; stlink_t *sl = NULL; st_state_t state; memset(&state, 0, sizeof(state)); // set defaults... state.stlink_version = 2; state.logging_level = DEFAULT_LOGGING_LEVEL; state.listen_port = DEFAULT_GDB_LISTEN_PORT; state.reset = 1; /* By default, reset board */ parse_options(argc, argv, &state); switch (state.stlink_version) { case 2: sl = stlink_open_usb(state.logging_level, 0); if(sl == NULL) return 1; break; case 1: sl = stlink_v1_open(state.logging_level, 0); if(sl == NULL) return 1; break; } connected_stlink = sl; signal(SIGINT, &cleanup); signal(SIGTERM, &cleanup); if (state.reset) { stlink_reset(sl); } ILOG("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id); voltage = stlink_target_voltage(sl); if (voltage != -1) { ILOG("Target voltage is %d mV.\n", voltage); } sl->verbose=0; current_memory_map = make_memory_map(sl); #ifdef __MINGW32__ WSADATA wsadata; if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) { goto winsock_error; } #endif do { serve(sl, &state); /* Continue */ stlink_run(sl); } while (state.persistent); #ifdef __MINGW32__ winsock_error: WSACleanup(); #endif /* Switch back to mass storage mode before closing. */ stlink_exit_debug_mode(sl); stlink_close(sl); return 0; }
int main(int ac, char** av) { stlink_t* sl = NULL; struct opts o; char serial_buffer[13] = {0}; o.serial = serial_buffer; int err = -1; o.size = 0; if (get_opts(&o, ac - 1, av + 1) == -1) { printf("invalid command line\n"); usage(); goto on_error; } if (o.devname != NULL) /* stlinkv1 */ { sl = stlink_v1_open(o.log_level, 1); if (sl == NULL) goto on_error; sl->verbose = o.log_level; } else /* stlinkv2 */ { sl = stlink_open_usb(o.log_level, 1, o.serial); if (sl == NULL) goto on_error; sl->verbose = o.log_level; } if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) stlink_exit_dfu_mode(sl); if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) stlink_enter_swd_mode(sl); if (o.reset) { stlink_jtag_reset(sl,2); stlink_reset(sl); } // Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 if (sl->chip_id == STM32_CHIPID_F4) { memset(sl->q_buf,0,4); for (int i=0; i<8; i++) { stlink_write_mem32(sl,0x40026000+0x10+0x18*i,4); stlink_write_mem32(sl,0x40026400+0x10+0x18*i,4); stlink_write_mem32(sl,0x40026000+0x24+0x18*i,4); stlink_write_mem32(sl,0x40026400+0x24+0x18*i,4); } } // Core must be halted to use RAM based flashloaders stlink_force_debug(sl); stlink_status(sl); if (o.cmd == DO_WRITE) /* write */ { if ((o.addr >= sl->flash_base) && (o.addr < sl->flash_base + sl->flash_size)) { err = stlink_fwrite_flash(sl, o.filename, o.addr); if (err == -1) { printf("stlink_fwrite_flash() == -1\n"); goto on_error; } } else if ((o.addr >= sl->sram_base) && (o.addr < sl->sram_base + sl->sram_size)) { err = stlink_fwrite_sram(sl, o.filename, o.addr); if (err == -1) { printf("stlink_sram_flash() == -1\n"); goto on_error; } } } else if (o.cmd == DO_ERASE) { err = stlink_erase_flash_mass(sl); if (err == -1) { printf("stlink_fwrite_flash() == -1\n"); goto on_error; } } else /* read */ { if ((o.addr >= sl->flash_base) && (o.size == 0) && (o.addr < sl->flash_base + sl->flash_size)) o.size = sl->flash_size; else if ((o.addr >= sl->sram_base) && (o.size == 0) && (o.addr < sl->sram_base + sl->sram_size)) o.size = sl->sram_size; err = stlink_fread(sl, o.filename, o.addr, o.size); if (err == -1) { printf("stlink_fread() == -1\n"); goto on_error; } } if (o.reset) { stlink_jtag_reset(sl,2); stlink_reset(sl); } /* success */ err = 0; on_error: if (sl != NULL) { stlink_exit_debug_mode(sl); stlink_close(sl); } return err; }
int main(int ac, char** av) { sl = NULL; struct opts o; int err = -1; signal(SIGINT, catcher); o.size = 0; if (get_opts(&o, ac - 1, av + 1) == -1) { printf("invalid command line\n"); usage(); goto on_error; } if (o.devname != NULL) /* stlinkv1 */ { sl = stlink_v1_open(50); sl->verbose = 50; if (sl == NULL) goto on_error; } else /* stlinkv2 */ { sl = stlink_open_usb(50); sl->verbose = 50; if (sl == NULL) goto on_error; } if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) stlink_exit_dfu_mode(sl); if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) stlink_enter_swd_mode(sl); stlink_reset(sl); printf("Erasing chip entirely..."); stlink_erase_flash_mass(sl); printf(" Done\n"); stlink_force_debug(sl); stlink_reset(sl); if (o.do_read == 0) /* write */ { err = stlink_fwrite_flash(sl, o.filename, o.addr); if (err == -1) { printf("stlink_fwrite_flash() == -1\n"); goto on_error; } } else /* read */ { err = stlink_fread(sl, o.filename, o.addr, o.size); if (err == -1) { printf("stlink_fread() == -1\n"); goto on_error; } } /* success */ err = 0; on_error: if (sl != NULL) { stlink_reset(sl); stlink_run(sl); stlink_close(sl); } return err; }
int main(int ac, char** av) { stlink_t* sl; /* unused */ ac = ac; av = av; sl = stlink_open_usb(10, 1); if (sl != NULL) { printf("ST-Linky proof-of-concept terminal :: Created by Necromant for lulz\n"); stlink_version(sl); stlink_enter_swd_mode(sl); printf("chip id: %#x\n", sl->chip_id); printf("core_id: %#x\n", sl->core_id); cortex_m3_cpuid_t cpuid; stlink_cpu_id(sl, &cpuid); printf("cpuid:impl_id = %0#x, variant = %#x\n", cpuid.implementer_id, cpuid.variant); printf("cpuid:part = %#x, rev = %#x\n", cpuid.part, cpuid.revision); stlink_reset(sl); stlink_force_debug(sl); stlink_run(sl); stlink_status(sl); /* wait for device to boot */ /* TODO: Make timeout adjustable via command line */ sleep(1); struct stlinky *st = stlinky_detect(sl); if (st == NULL) { printf("stlinky magic not found in sram :(\n"); goto bailout; } char* rxbuf = malloc(st->bufsize); char* txbuf = malloc(st->bufsize); size_t tmp; nonblock(1); int fd = fileno(stdin); int saved_flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK); signal(SIGINT, cleanup); printf("Entering interactive terminal. CTRL+C to exit\n\n\n"); while(1) { if (stlinky_canrx(st)) { tmp = stlinky_rx(st, rxbuf); fwrite(rxbuf,tmp,1,stdout); fflush(stdout); } if (kbhit()) { tmp = read(fd, txbuf, st->bufsize); stlinky_tx(st,txbuf,tmp); } if (!keep_running) break; } bailout: nonblock(0); stlink_exit_debug_mode(sl); stlink_close(sl); } return 0; }
void catcher(int sig) { if(sl != NULL) stlink_close(sl); exit(1); }
int main(int argc, char *argv[]) { /* Avoid unused parameter warning */ (void)argv; // set scpi lib debug level: 0 for no debug info, 10 for lots switch (argc) { case 1: fputs( "\nUsage: stlink-access-test [anything at all] ...\n" "\n*** Notice: The stlink firmware violates the USB standard.\n" "*** Because we just use libusb, we can just tell the kernel's\n" "*** driver to simply ignore the device...\n" "*** Unplug the stlink and execute once as root:\n" "modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i\n\n", stderr); return EXIT_FAILURE; default: break; } stlink_t *sl = stlink_v1_open(99, 1); if (sl == NULL) return EXIT_FAILURE; // we are in mass mode, go to swd stlink_enter_swd_mode(sl); stlink_current_mode(sl); stlink_core_id(sl); //---------------------------------------------------------------------- stlink_status(sl); //stlink_force_debug(sl); stlink_reset(sl); stlink_status(sl); // core system control block stlink_read_mem32(sl, 0xe000ed00, 4); DLOG("cpu id base register: SCB_CPUID = got 0x%08x expect 0x411fc231\n", read_uint32(sl->q_buf, 0)); // no MPU stlink_read_mem32(sl, 0xe000ed90, 4); DLOG("mpu type register: MPU_TYPER = got 0x%08x expect 0x0\n", read_uint32(sl->q_buf, 0)); #if 0 stlink_read_mem32(sl, 0xe000edf0, 4); DD(sl, "DHCSR = 0x%08x", read_uint32(sl->q_buf, 0)); stlink_read_mem32(sl, 0x4001100c, 4); DD(sl, "GPIOC_ODR = 0x%08x", read_uint32(sl->q_buf, 0)); #endif #if 0 // happy new year 2011: let blink all the leds // see "RM0041 Reference manual - STM32F100xx advanced ARM-based 32-bit MCUs" #define GPIOC 0x40011000 // port C #define GPIOC_CRH (GPIOC + 0x04) // port configuration register high #define GPIOC_ODR (GPIOC + 0x0c) // port output data register #define LED_BLUE (1<<8) // pin 8 #define LED_GREEN (1<<9) // pin 9 stlink_read_mem32(sl, GPIOC_CRH, 4); uint32_t io_conf = read_uint32(sl->q_buf, 0); DLOG("GPIOC_CRH = 0x%08x\n", io_conf); // set: general purpose output push-pull, output mode, max speed 10 MHz. write_uint32(sl->q_buf, 0x44444411); stlink_write_mem32(sl, GPIOC_CRH, 4); memset(sl->q_buf, 0, sizeof(sl->q_buf)); for (int i = 0; i < 100; i++) { write_uint32(sl->q_buf, LED_BLUE | LED_GREEN); stlink_write_mem32(sl, GPIOC_ODR, 4); /* stlink_read_mem32(sl, 0x4001100c, 4); */ /* DD(sl, "GPIOC_ODR = 0x%08x", read_uint32(sl->q_buf, 0)); */ usleep(100 * 1000); memset(sl->q_buf, 0, sizeof(sl->q_buf)); stlink_write_mem32(sl, GPIOC_ODR, 4); // PC lo usleep(100 * 1000); } write_uint32(sl->q_buf, io_conf); // set old state #endif #if 0 // TODO rtfm: stlink doesn't have flash write routines // writing to the flash area confuses the fw for the next read access //stlink_read_mem32(sl, 0, 1024*6); // flash 0x08000000 128kB fputs("++++++++++ read a flash at 0x0800 0000\n", stderr); stlink_read_mem32(sl, 0x08000000, 1024 * 6); //max 6kB clear_buf(sl); stlink_read_mem32(sl, 0x08000c00, 5); stlink_read_mem32(sl, 0x08000c00, 4); mark_buf(sl); stlink_write_mem32(sl, 0x08000c00, 4); stlink_read_mem32(sl, 0x08000c00, 256); stlink_read_mem32(sl, 0x08000c00, 256); #endif #if 0 // sram 0x20000000 8kB fputs("\n++++++++++ read/write 8bit, sram at 0x2000 0000 ++++++++++++++++\n\n", stderr); memset(sl->q_buf, 0, sizeof(sl->q_buf)); mark_buf(sl); //stlink_write_mem8(sl, 0x20000000, 16); //stlink_write_mem8(sl, 0x20000000, 1); //stlink_write_mem8(sl, 0x20000001, 1); stlink_write_mem8(sl, 0x2000000b, 3); stlink_read_mem32(sl, 0x20000000, 16); #endif #if 0 // a not aligned mem32 access doesn't work indeed fputs("\n++++++++++ read/write 32bit, sram at 0x2000 0000 ++++++++++++++++\n\n", stderr); memset(sl->q_buf, 0, sizeof(sl->q_buf)); mark_buf(sl); stlink_write_mem32(sl, 0x20000000, 1); stlink_read_mem32(sl, 0x20000000, 16); mark_buf(sl); stlink_write_mem32(sl, 0x20000001, 1); stlink_read_mem32(sl, 0x20000000, 16); mark_buf(sl); stlink_write_mem32(sl, 0x2000000b, 3); stlink_read_mem32(sl, 0x20000000, 16); mark_buf(sl); stlink_write_mem32(sl, 0x20000000, 17); stlink_read_mem32(sl, 0x20000000, 32); #endif #if 0 // sram 0x20000000 8kB fputs("++++++++++ read/write 32bit, sram at 0x2000 0000 ++++++++++++\n", stderr); memset(sl->q_buf, 0, sizeof(sl->q_buf)); mark_buf(sl); stlink_write_mem8(sl, 0x20000000, 64); stlink_read_mem32(sl, 0x20000000, 64); mark_buf(sl); stlink_write_mem32(sl, 0x20000000, 1024 * 8); //8kB stlink_read_mem32(sl, 0x20000000, 1024 * 6); stlink_read_mem32(sl, 0x20000000 + 1024 * 6, 1024 * 2); #endif #if 1 reg regs; stlink_read_all_regs(sl, ®s); stlink_step(sl); fputs("++++++++++ write r0 = 0x12345678\n", stderr); stlink_write_reg(sl, 0x12345678, 0); stlink_read_reg(sl, 0, ®s); stlink_read_all_regs(sl, ®s); #endif #if 0 stlink_run(sl); stlink_status(sl); stlink_force_debug(sl); stlink_status(sl); #endif #if 0 /* read the system bootloader */ fputs("\n++++++++++ reading bootloader ++++++++++++++++\n\n", stderr); stlink_fread(sl, "/tmp/barfoo", sl->sys_base, sl->sys_size); #endif #if 0 /* read the flash memory */ fputs("\n+++++++ read flash memory\n\n", stderr); /* mark_buf(sl); */ stlink_read_mem32(sl, 0x08000000, 4); #endif #if 0 /* flash programming */ fputs("\n+++++++ program flash memory\n\n", stderr); stlink_fwrite_flash(sl, "/tmp/foobar", 0x08000000); #endif #if 0 /* check file contents */ fputs("\n+++++++ check flash memory\n\n", stderr); { const int res = stlink_fcheck_flash(sl, "/tmp/foobar", 0x08000000); printf("_____ stlink_fcheck_flash() == %d\n", res); } #endif #if 0 fputs("\n+++++++ sram write and execute\n\n", stderr); stlink_fwrite_sram(sl, "/tmp/foobar", sl->sram_base); stlink_run_at(sl, sl->sram_base); #endif #if 0 stlink_run(sl); stlink_status(sl); //---------------------------------------------------------------------- // back to mass mode, just in case ... stlink_exit_debug_mode(sl); stlink_current_mode(sl); stlink_close(sl); #endif //fflush(stderr); fflush(stdout); return EXIT_SUCCESS; }
int main(int ac, char** av) { stlink_t* sl = NULL; struct flash_opts o; int err = -1; uint8_t * mem = NULL; o.size = 0; if (flash_get_opts(&o, ac - 1, av + 1) == -1) { printf("invalid command line\n"); usage(); return -1; } printf("st-flash %s\n", STLINK_VERSION); if (o.devname != NULL) /* stlinkv1 */ sl = stlink_v1_open(o.log_level, 1); else /* stlinkv2 */ sl = stlink_open_usb(o.log_level, 1, (char *)o.serial); if (sl == NULL) return -1; if ( o.flash_size != 0u && o.flash_size != sl->flash_size ) { sl->flash_size = o.flash_size; printf("Forcing flash size: --flash=0x%08X\n",(unsigned int)sl->flash_size); } sl->verbose = o.log_level; connected_stlink = sl; signal(SIGINT, &cleanup); signal(SIGTERM, &cleanup); signal(SIGSEGV, &cleanup); if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { if (stlink_exit_dfu_mode(sl)) { printf("Failed to exit DFU mode\n"); goto on_error; } } if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { if (stlink_enter_swd_mode(sl)) { printf("Failed to enter SWD mode\n"); goto on_error; } } if (o.reset){ if (stlink_jtag_reset(sl, 2)) { printf("Failed to reset JTAG\n"); goto on_error; } if (stlink_reset(sl)) { printf("Failed to reset device\n"); goto on_error; } } // Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 if (sl->chip_id == STLINK_CHIPID_STM32_F4) { memset(sl->q_buf,0,4); for (int i=0;i<8;i++) { stlink_write_mem32(sl,0x40026000+0x10+0x18*i,4); stlink_write_mem32(sl,0x40026400+0x10+0x18*i,4); stlink_write_mem32(sl,0x40026000+0x24+0x18*i,4); stlink_write_mem32(sl,0x40026400+0x24+0x18*i,4); } } // Core must be halted to use RAM based flashloaders if (stlink_force_debug(sl)) { printf("Failed to halt the core\n"); goto on_error; } if (stlink_status(sl)) { printf("Failed to get Core's status\n"); goto on_error; } if (o.cmd == FLASH_CMD_WRITE) /* write */ { size_t size = 0; if(o.format == FLASH_FORMAT_IHEX) { err = stlink_parse_ihex(o.filename, stlink_get_erased_pattern(sl), &mem, &size, &o.addr); if (err == -1) { printf("Cannot parse %s as Intel-HEX file\n", o.filename); goto on_error; } } if ((o.addr >= sl->flash_base) && (o.addr < sl->flash_base + sl->flash_size)) { if(o.format == FLASH_FORMAT_IHEX) err = stlink_mwrite_flash(sl, mem, (uint32_t)size, o.addr); else err = stlink_fwrite_flash(sl, o.filename, o.addr); if (err == -1) { printf("stlink_fwrite_flash() == -1\n"); goto on_error; } } else if ((o.addr >= sl->sram_base) && (o.addr < sl->sram_base + sl->sram_size)) { if(o.format == FLASH_FORMAT_IHEX) err = stlink_mwrite_sram(sl, mem, (uint32_t)size, o.addr); else err = stlink_fwrite_sram(sl, o.filename, o.addr); if (err == -1) { printf("stlink_fwrite_sram() == -1\n"); goto on_error; } } else { err = -1; printf("Unknown memory region\n"); goto on_error; } } else if (o.cmd == FLASH_CMD_LOCK) { err = stlink_set_read_protection(sl, true); if(err != 0) { printf("stlink_set_read_protection(true) != 0\n"); goto on_error; } } else if (o.cmd == FLASH_CMD_UNLOCK) { err = stlink_set_read_protection(sl, false); if(err != 0) { printf("stlink_set_read_protection(false) != 0\n"); goto on_error; } } else if (o.cmd == FLASH_CMD_ERASE) { err = stlink_erase_flash_mass(sl); if (err == -1) { printf("stlink_erase_flash_mass() == -1\n"); goto on_error; } } else if (o.cmd == CMD_RESET) { if (stlink_jtag_reset(sl, 2)) { printf("Failed to reset JTAG\n"); goto on_error; } if (stlink_reset(sl)) { printf("Failed to reset device\n"); goto on_error; } } else /* read */ { if ((o.addr >= sl->flash_base) && (o.size == 0) && (o.addr < sl->flash_base + sl->flash_size)) o.size = sl->flash_size; else if ((o.addr >= sl->sram_base) && (o.size == 0) && (o.addr < sl->sram_base + sl->sram_size)) o.size = sl->sram_size; err = stlink_fread(sl, o.filename, o.format == FLASH_FORMAT_IHEX, o.addr, o.size); if (err == -1) { printf("stlink_fread() == -1\n"); goto on_error; } } if (o.reset){ stlink_jtag_reset(sl,2); stlink_reset(sl); } /* success */ err = 0; on_error: stlink_exit_debug_mode(sl); stlink_close(sl); free(mem); return err; }
int main(int ac, char** av) { (void)ac; (void)av; stlink_t* sl; reg regs; sl = stlink_open_usb(10, 1, NULL); if (sl != NULL) { printf("-- version\n"); stlink_version(sl); printf("mode before doing anything: %d\n", stlink_current_mode(sl)); if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { printf("-- exit_dfu_mode\n"); stlink_exit_dfu_mode(sl); } printf("-- enter_swd_mode\n"); stlink_enter_swd_mode(sl); printf("-- mode after entering swd mode: %d\n", stlink_current_mode(sl)); printf("-- chip id: %#x\n", sl->chip_id); printf("-- core_id: %#x\n", sl->core_id); cortex_m3_cpuid_t cpuid; stlink_cpu_id(sl, &cpuid); printf("cpuid:impl_id = %0#x, variant = %#x\n", cpuid.implementer_id, cpuid.variant); printf("cpuid:part = %#x, rev = %#x\n", cpuid.part, cpuid.revision); printf("-- read_sram\n"); static const uint32_t sram_base = STM32_SRAM_BASE; uint32_t off; for (off = 0; off < 16; off += 4) stlink_read_mem32(sl, sram_base + off, 4); printf("FP_CTRL\n"); stlink_read_mem32(sl, STLINK_REG_CM3_FP_CTRL, 4); // no idea what reg this is.. */ // stlink_read_mem32(sl, 0xe000ed90, 4); // no idea what register this is... // stlink_read_mem32(sl, 0xe000edf0, 4); // offset 0xC into TIM11 register? TIMx_DIER? // stlink_read_mem32(sl, 0x4001100c, 4); */ /* Test 32 bit Write */ write_uint32(sl->q_buf,0x01234567); stlink_write_mem32(sl,0x200000a8,4); write_uint32(sl->q_buf,0x89abcdef); stlink_write_mem32(sl,0x200000ac, 4); stlink_read_mem32(sl, 0x200000a8, 4); stlink_read_mem32(sl, 0x200000ac, 4); /* Test 8 bit write */ write_uint32(sl->q_buf,0x01234567); stlink_write_mem8(sl,0x200001a8,3); write_uint32(sl->q_buf,0x89abcdef); stlink_write_mem8(sl, 0x200001ac, 3); stlink_read_mem32(sl, 0x200001a8, 4); stlink_read_mem32(sl, 0x200001ac, 4); printf("-- status\n"); stlink_status(sl); printf("-- reset\n"); stlink_reset(sl); stlink_force_debug(sl); /* Test reg write*/ stlink_write_reg(sl, 0x01234567, 3); stlink_write_reg(sl, 0x89abcdef, 4); stlink_write_reg(sl, 0x12345678, 15); for (off = 0; off < 21; off += 1) stlink_read_reg(sl, off, ®s); stlink_read_all_regs(sl, ®s); printf("-- status\n"); stlink_status(sl); printf("-- step\n"); stlink_step(sl); printf("-- run\n"); stlink_run(sl); printf("-- exit_debug_mode\n"); stlink_exit_debug_mode(sl); stlink_close(sl); } return 0; }
int main ( int argc, char *argv[] ) { stlink_t* sl; unsigned int ra; unsigned int rb; unsigned int flen; int ret; if(argc<2) { printf(".bin file not specified\n"); return(1); } fp=fopen(argv[1],"rb"); if(fp==NULL) { printf("Error opening file [%s]\n",argv[1]); return(1); } memset(pdata,0xFF,sizeof(pdata)); flen=fread(pdata,1,sizeof(pdata),fp); flen+=3; flen>>=2; fclose(fp); sl = stlink_open_usb(10); if(sl==NULL) { printf("stlink_open_usb failed\n"); return(1); } printf("-- version\n"); stlink_version(sl); printf("mode before doing anything: %d\n", stlink_current_mode(sl)); if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { printf("-- exit_dfu_mode\n"); stlink_exit_dfu_mode(sl); } printf("-- enter_swd_mode\n"); stlink_enter_swd_mode(sl); printf("-- mode after entering swd mode: %d\n", stlink_current_mode(sl)); printf("-- chip id: %#x\n", sl->chip_id); printf("-- core_id: %#x\n", sl->core_id); cortex_m3_cpuid_t cpuid; stlink_cpu_id(sl, &cpuid); printf("cpuid:impl_id = %0#x, variant = %#x\n", cpuid.implementer_id, cpuid.variant); printf("cpuid:part = %#x, rev = %#x\n", cpuid.part, cpuid.revision); // printf("-- status\n"); //stlink_status(sl); printf("-- reset\n"); stlink_reset(sl); stlink_force_debug(sl); // printf("-- status\n"); // stlink_status(sl); #ifdef LOAD_RAM printf("-- load\n"); for(ra=0;ra<flen;ra++) { write_uint32(sl->q_buf,pdata[ra]); stlink_write_mem32(sl, 0x20000000+(ra<<2), 4); } for(ra=0;ra<8;ra++) { stlink_read_mem32(sl, 0x20000000+(ra<<2), 4); rb=read_uint32(sl->q_buf,0); printf("[0x%08X] 0x%08X 0x%08X\n",ra,rb,pdata[ra]); } printf("-- run\n"); stlink_write_reg(sl, 0x20020000, 13); /* pc register */ stlink_write_reg(sl, 0x20000000, 15); /* pc register */ stlink_run(sl); ret =0; #endif //LOAD_RAM #ifdef LOAD_FLASH ra=0; rb=0; ret=stlink_write_flash(sl,0x08000000,(unsigned char *)pdata,0x4000); if(ret) { printf("stlink_write_flasin error\n"); } #endif //LOAD_FLASH printf("-- exit_debug_mode\n"); stlink_exit_debug_mode(sl); stlink_close(sl); return 0; }
/** * Wraps a CDB mass storage command in the appropriate gunk to get it down * @param handle * @param endpoint * @param cdb * @param cdb_length * @param lun * @param flags * @param expected_rx_size * @return */ int send_usb_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint_out, uint8_t *cdb, uint8_t cdb_length, uint8_t lun, uint8_t flags, uint32_t expected_rx_size) { DLOG("Sending usb m-s cmd: cdblen:%d, rxsize=%d\n", cdb_length, expected_rx_size); dump_CDB_command(cdb, cdb_length); static uint32_t tag; if (tag == 0) { tag = 1; } int try = 0; int ret = 0; int real_transferred; int i = 0; uint8_t c_buf[STLINK_SG_SIZE]; // tag is allegedly ignored... TODO - verify c_buf[i++] = 'U'; c_buf[i++] = 'S'; c_buf[i++] = 'B'; c_buf[i++] = 'C'; write_uint32(&c_buf[i], tag); uint32_t this_tag = tag++; write_uint32(&c_buf[i+4], expected_rx_size); i+= 8; c_buf[i++] = flags; c_buf[i++] = lun; c_buf[i++] = cdb_length; // Now the actual CDB request assert(cdb_length <= CDB_SL); memcpy(&(c_buf[i]), cdb, cdb_length); int sending_length = STLINK_SG_SIZE; DLOG("sending length set to: %d\n", sending_length); // send.... do { DLOG("attempting tx...\n"); ret = libusb_bulk_transfer(handle, endpoint_out, c_buf, sending_length, &real_transferred, SG_TIMEOUT_MSEC); if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_out); } try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("sending failed: %d\n", ret); return -1; } DLOG("Actually sent: %d, returning tag: %d\n", real_transferred, tag); return this_tag; } /** * Straight from stm8 stlink code... * @param handle * @param endpoint_in * @param endpoint_out */ static void get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out) { DLOG("Fetching sense...\n"); uint8_t cdb[16]; memset(cdb, 0, sizeof(cdb)); #define REQUEST_SENSE 0x03 #define REQUEST_SENSE_LENGTH 18 cdb[0] = REQUEST_SENSE; cdb[4] = REQUEST_SENSE_LENGTH; uint32_t tag = send_usb_mass_storage_command(handle, endpoint_out, cdb, sizeof(cdb), 0, LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH); if (tag == 0) { WLOG("refusing to send request sense with tag 0\n"); return; } unsigned char sense[REQUEST_SENSE_LENGTH]; int transferred; int ret; int try = 0; do { ret = libusb_bulk_transfer(handle, endpoint_in, sense, sizeof(sense), &transferred, SG_TIMEOUT_MSEC); if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_in); } try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("receiving sense failed: %d\n", ret); return; } if (transferred != sizeof(sense)) { WLOG("received unexpected amount of sense: %d != %d\n", transferred, sizeof(sense)); } uint32_t received_tag; int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag); if (status != 0) { WLOG("receiving sense failed with status: %02x\n", status); return; } if (sense[0] != 0x70 && sense[0] != 0x71) { WLOG("No sense data\n"); } else { WLOG("Sense KCQ: %02X %02X %02X\n", sense[2] & 0x0f, sense[12], sense[13]); } } //TODO rewrite/cleanup, save the error in sl #if FINISHED_WITH_SG static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) { struct stlink_libsg *sl = stl->backend_data; const int e = sl->do_scsi_pt_err; if (e < 0) { fprintf(stderr, "scsi_pt error: pass through os error: %s\n", safe_strerror(-e)); return; } else if (e == SCSI_PT_DO_BAD_PARAMS) { fprintf(stderr, "scsi_pt error: bad pass through setup\n"); return; } else if (e == SCSI_PT_DO_TIMEOUT) { fprintf(stderr, " pass through timeout\n"); return; } const int duration = get_scsi_pt_duration_ms(ptvp); if ((stl->verbose > 1) && (duration >= 0)) DLOG(" duration=%d ms\n", duration); // XXX stlink fw sends broken residue, so ignore it and use the known q_len // "usb-storage quirks=483:3744:r" // forces residue to be ignored and calculated, but this causes aboard if // data_len = 0 and by some other data_len values. const int resid = get_scsi_pt_resid(ptvp); const int dsize = stl->q_len - resid; const int cat = get_scsi_pt_result_category(ptvp); char buf[512]; unsigned int slen; switch (cat) { case SCSI_PT_RESULT_GOOD: if (stl->verbose && (resid > 0)) DLOG(" notice: requested %d bytes but " "got %d bytes, ignore [broken] residue = %d\n", stl->q_len, dsize, resid); break; case SCSI_PT_RESULT_STATUS: if (stl->verbose) { sg_get_scsi_status_str( get_scsi_pt_status_response(ptvp), sizeof (buf), buf); DLOG(" scsi status: %s\n", buf); } return; case SCSI_PT_RESULT_SENSE: slen = get_scsi_pt_sense_len(ptvp); if (stl->verbose) { sg_get_sense_str("", sl->sense_buf, slen, (stl->verbose > 1), sizeof (buf), buf); DLOG("%s", buf); } if (stl->verbose && (resid > 0)) { if ((stl->verbose) || (stl->q_len > 0)) DLOG(" requested %d bytes but " "got %d bytes\n", stl->q_len, dsize); } return; case SCSI_PT_RESULT_TRANSPORT_ERR: if (stl->verbose) { get_scsi_pt_transport_err_str(ptvp, sizeof (buf), buf); // http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html // These codes potentially come from the firmware on a host adapter // or from one of several hosts that an adapter driver controls. // The 'host_status' field has the following values: // [0x07] Internal error detected in the host adapter. // This may not be fatal (and the command may have succeeded). DLOG(" transport: %s", buf); } return; case SCSI_PT_RESULT_OS_ERR: if (stl->verbose) { get_scsi_pt_os_err_str(ptvp, sizeof (buf), buf); DLOG(" os: %s", buf); } return; default: fprintf(stderr, " unknown pass through result " "category (%d)\n", cat); } } #endif /** * Just send a buffer on an endpoint, no questions asked. * Handles repeats, and time outs. Also handles reading status reports and sense * @param handle libusb device * * @param endpoint_out sends * @param endpoint_in used to read status reports back in * @param cbuf what to send * @param length how much to send * @return number of bytes actually sent, or -1 for failures. */ int send_usb_data_only(libusb_device_handle *handle, unsigned char endpoint_out, unsigned char endpoint_in, unsigned char *cbuf, unsigned int length) { int ret; int real_transferred; int try; do { DLOG("attempting tx...\n"); ret = libusb_bulk_transfer(handle, endpoint_out, cbuf, length, &real_transferred, SG_TIMEOUT_MSEC); if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_out); } try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("sending failed: %d\n", ret); return -1; } DLOG("Actually sent: %d\n", real_transferred); // now, swallow up the status, so that things behave nicely... uint32_t received_tag; // -ve is for my errors, 0 is good, +ve is libusb sense status bytes int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag); if (status < 0) { WLOG("receiving status failed: %d\n", status); return -1; } if (status != 0) { WLOG("receiving status not passed :(: %02x\n", status); } if (status == 1) { get_sense(handle, endpoint_in, endpoint_out); return -1; } return real_transferred; } int stlink_q(stlink_t *sl) { struct stlink_libsg* sg = sl->backend_data; //uint8_t cdb_len = 6; // FIXME varies!!! uint8_t cdb_len = 10; // FIXME varies!!! uint8_t lun = 0; // always zero... uint32_t tag = send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, cdb_len, lun, LIBUSB_ENDPOINT_IN, sl->q_len); // now wait for our response... // length copied from stlink-usb... int rx_length = sl->q_len; int try = 0; int real_transferred; int ret; if (rx_length > 0) { do { DLOG("attempting rx\n"); ret = libusb_bulk_transfer(sg->usb_handle, sg->ep_rep, sl->q_buf, rx_length, &real_transferred, SG_TIMEOUT_MSEC); if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(sg->usb_handle, sg->ep_req); } try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("Receiving failed: %d\n", ret); return -1; } if (real_transferred != rx_length) { WLOG("received unexpected amount: %d != %d\n", real_transferred, rx_length); } } uint32_t received_tag; // -ve is for my errors, 0 is good, +ve is libusb sense status bytes int status = get_usb_mass_storage_status(sg->usb_handle, sg->ep_rep, &received_tag); if (status < 0) { WLOG("receiving status failed: %d\n", status); return -1; } if (status != 0) { WLOG("receiving status not passed :(: %02x\n", status); } if (status == 1) { get_sense(sg->usb_handle, sg->ep_rep, sg->ep_req); return -1; } if (received_tag != tag) { WLOG("received tag %d but expected %d\n", received_tag, tag); //return -1; } if (rx_length > 0 && real_transferred != rx_length) { return -1; } return 0; DLOG("Actually received: %d\n", real_transferred); #if FINISHED_WITH_SG // Get control command descriptor of scsi structure, // (one object per command!!) struct sg_pt_base *ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { fprintf(stderr, "construct_scsi_pt_obj: out of memory\n"); return; } set_scsi_pt_cdb(ptvp, sg->cdb_cmd_blk, sizeof (sg->cdb_cmd_blk)); // set buffer for sense (error information) data set_scsi_pt_sense(ptvp, sg->sense_buf, sizeof (sg->sense_buf)); // Set a buffer to be used for data transferred from device if (sg->q_data_dir == Q_DATA_IN) { //clear_buf(sl); set_scsi_pt_data_in(ptvp, sl->q_buf, sl->q_len); } else { set_scsi_pt_data_out(ptvp, sl->q_buf, sl->q_len); } // Executes SCSI command (or at least forwards it to lower layers). sg->do_scsi_pt_err = do_scsi_pt(ptvp, sg->sg_fd, SG_TIMEOUT_SEC, sl->verbose); // check for scsi errors stlink_confirm_inq(sl, ptvp); // TODO recycle: clear_scsi_pt_obj(struct sg_pt_base * objp); destruct_scsi_pt_obj(ptvp); #endif } // TODO thinking, cleanup void stlink_stat(stlink_t *stl, char *txt) { if (stl->q_len <= 0) return; stlink_print_data(stl); switch (stl->q_buf[0]) { case STLINK_OK: DLOG(" %s: ok\n", txt); return; case STLINK_FALSE: DLOG(" %s: false\n", txt); return; default: DLOG(" %s: unknown\n", txt); } } void _stlink_sg_version(stlink_t *stl) { struct stlink_libsg *sl = stl->backend_data; DLOG("\n*** stlink_version ***\n"); clear_cdb(sl); sl->cdb_cmd_blk[0] = STLINK_GET_VERSION; stl->q_len = 6; sl->q_addr = 0; stlink_q(stl); // HACK use my own private version right now... } // Get stlink mode: // STLINK_DEV_DFU_MODE || STLINK_DEV_MASS_MODE || STLINK_DEV_DEBUG_MODE // usb dfu || usb mass || jtag or swd int _stlink_sg_current_mode(stlink_t *stl) { struct stlink_libsg *sl = stl->backend_data; clear_cdb(sl); sl->cdb_cmd_blk[0] = STLINK_GET_CURRENT_MODE; stl->q_len = 2; sl->q_addr = 0; stlink_q(stl); return stl->q_buf[0]; } // Exit the mass mode and enter the swd debug mode. void _stlink_sg_enter_swd_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER; sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_SWD; sl->q_len = 0; // >0 -> aboard stlink_q(sl); } // Exit the mass mode and enter the jtag debug mode. // (jtag is disabled in the discovery's stlink firmware) void _stlink_sg_enter_jtag_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_enter_jtag_mode ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER; sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_JTAG; sl->q_len = 0; stlink_q(sl); } // XXX kernel driver performs reset, the device temporally disappears void _stlink_sg_exit_dfu_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_exit_dfu_mode ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[0] = STLINK_DFU_COMMAND; sg->cdb_cmd_blk[1] = STLINK_DFU_EXIT; sl->q_len = 0; // ?? stlink_q(sl); /* [135121.844564] sd 19:0:0:0: [sdb] Unhandled error code [135121.844569] sd 19:0:0:0: [sdb] Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK [135121.844574] sd 19:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 10 00 00 00 08 00 [135121.844584] end_request: I/O error, dev sdb, sector 4096 [135121.844590] Buffer I/O error on device sdb, logical block 512 [135130.122567] usb 6-1: reset full speed USB device using uhci_hcd and address 7 [135130.274551] usb 6-1: device firmware changed [135130.274618] usb 6-1: USB disconnect, address 7 [135130.275186] VFS: busy inodes on changed media or resized disk sdb [135130.275424] VFS: busy inodes on changed media or resized disk sdb [135130.286758] VFS: busy inodes on changed media or resized disk sdb [135130.292796] VFS: busy inodes on changed media or resized disk sdb [135130.301481] VFS: busy inodes on changed media or resized disk sdb [135130.304316] VFS: busy inodes on changed media or resized disk sdb [135130.431113] usb 6-1: new full speed USB device using uhci_hcd and address 8 [135130.629444] usb-storage 6-1:1.0: Quirks match for vid 0483 pid 3744: 102a1 [135130.629492] scsi20 : usb-storage 6-1:1.0 [135131.625600] scsi 20:0:0:0: Direct-Access STM32 PQ: 0 ANSI: 0 [135131.627010] sd 20:0:0:0: Attached scsi generic sg2 type 0 [135131.633603] sd 20:0:0:0: [sdb] 64000 512-byte logical blocks: (32.7 MB/31.2 MiB) [135131.633613] sd 20:0:0:0: [sdb] Assuming Write Enabled [135131.633620] sd 20:0:0:0: [sdb] Assuming drive cache: write through [135131.640584] sd 20:0:0:0: [sdb] Assuming Write Enabled [135131.640592] sd 20:0:0:0: [sdb] Assuming drive cache: write through [135131.640609] sdb: [135131.652634] sd 20:0:0:0: [sdb] Assuming Write Enabled [135131.652639] sd 20:0:0:0: [sdb] Assuming drive cache: write through [135131.652645] sd 20:0:0:0: [sdb] Attached SCSI removable disk [135131.671536] sd 20:0:0:0: [sdb] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [135131.671548] sd 20:0:0:0: [sdb] Sense Key : Illegal Request [current] [135131.671553] sd 20:0:0:0: [sdb] Add. Sense: Logical block address out of range [135131.671560] sd 20:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 f9 80 00 00 08 00 [135131.671570] end_request: I/O error, dev sdb, sector 63872 [135131.671575] Buffer I/O error on device sdb, logical block 7984 [135131.678527] sd 20:0:0:0: [sdb] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [135131.678532] sd 20:0:0:0: [sdb] Sense Key : Illegal Request [current] [135131.678537] sd 20:0:0:0: [sdb] Add. Sense: Logical block address out of range [135131.678542] sd 20:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 f9 80 00 00 08 00 [135131.678551] end_request: I/O error, dev sdb, sector 63872 ... [135131.853565] end_request: I/O error, dev sdb, sector 4096 */ } void _stlink_sg_core_id(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_READCOREID; sl->q_len = 4; sg->q_addr = 0; stlink_q(sl); sl->core_id = read_uint32(sl->q_buf, 0); } // Arm-core reset -> halted state. void _stlink_sg_reset(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_RESETSYS; sl->q_len = 2; sg->q_addr = 0; stlink_q(sl); stlink_stat(sl, "core reset"); } // Arm-core status: halted or running. void _stlink_sg_status(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_status ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_GETSTATUS; sl->q_len = 2; sg->q_addr = 0; stlink_q(sl); } // Force the core into the debug mode -> halted state. void _stlink_sg_force_debug(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_force_debug ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_FORCEDEBUG; sl->q_len = 2; sg->q_addr = 0; stlink_q(sl); stlink_stat(sl, "force debug"); } // Read all arm-core registers. void _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_READALLREGS; sl->q_len = 84; sg->q_addr = 0; stlink_q(sl); stlink_print_data(sl); // TODO - most of this should be re-extracted up.... // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71 | 72-75 | 76-79 | 80-83 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 for (int i = 0; i < 16; i++) { regp->r[i] = read_uint32(sl->q_buf, 4 * i); if (sl->verbose > 1) DLOG("r%2d = 0x%08x\n", i, regp->r[i]); } regp->xpsr = read_uint32(sl->q_buf, 64); regp->main_sp = read_uint32(sl->q_buf, 68); regp->process_sp = read_uint32(sl->q_buf, 72); regp->rw = read_uint32(sl->q_buf, 76); regp->rw2 = read_uint32(sl->q_buf, 80); if (sl->verbose < 2) return; 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); } // Read an arm-core register, the index must be in the range 0..20. // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 void _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_READREG; sg->cdb_cmd_blk[2] = r_idx; sl->q_len = 4; sg->q_addr = 0; stlink_q(sl); // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71 | 72-75 | 76-79 | 80-83 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 stlink_print_data(sl); uint32_t r = read_uint32(sl->q_buf, 0); DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r); switch (r_idx) { case 16: regp->xpsr = r; break; case 17: regp->main_sp = r; break; case 18: regp->process_sp = r; break; case 19: regp->rw = r; //XXX ?(primask, basemask etc.) break; case 20: regp->rw2 = r; //XXX ?(primask, basemask etc.) break; default: regp->r[r_idx] = r; } } // Write an arm-core register. Index: // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 void _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEREG; // 2: reg index // 3-6: reg content sg->cdb_cmd_blk[2] = idx; write_uint32(sg->cdb_cmd_blk + 3, reg); sl->q_len = 2; sg->q_addr = 0; stlink_q(sl); stlink_stat(sl, "write reg"); } // Write a register of the debug module of the core. // XXX ?(atomic writes) // TODO test void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_write_dreg ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEDEBUGREG; // 2-5: address of reg of the debug module // 6-9: reg content write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint32(sg->cdb_cmd_blk + 6, reg); sl->q_len = 2; sg->q_addr = addr; stlink_q(sl); stlink_stat(sl, "write debug reg"); } // Force the core exit the debug mode. void _stlink_sg_run(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_run ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE; sl->q_len = 2; sg->q_addr = 0; stlink_q(sl); stlink_stat(sl, "run core"); } // Step the arm-core. void _stlink_sg_step(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_STEPCORE; sl->q_len = 2; sg->q_addr = 0; stlink_q(sl); stlink_stat(sl, "step core"); } // TODO test // see Cortex-M3 Technical Reference Manual // TODO make delegate! void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) { DLOG("\n*** stlink_set_hw_bp ***\n"); struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_SETFP; // 2:The number of the flash patch used to set the breakpoint // 3-6: Address of the breakpoint (LSB) // 7: FP_ALL (0x02) / FP_UPPER (0x01) / FP_LOWER (0x00) sl->q_buf[2] = fp_nr; write_uint32(sl->q_buf, addr); sl->q_buf[7] = fp; sl->q_len = 2; stlink_q(sl); stlink_stat(sl, "set flash breakpoint"); } // TODO test // TODO make delegate! void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_clr_hw_bp ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_CLEARFP; sg->cdb_cmd_blk[2] = fp_nr; sl->q_len = 2; stlink_q(sl); stlink_stat(sl, "clear flash breakpoint"); } // Read a "len" bytes to the sl->q_buf from the memory, max 6kB (6144 bytes) void _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_READMEM_32BIT; // 2-5: addr // 6-7: len write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint16(sg->cdb_cmd_blk + 6, len); // data_in 0-0x40-len // !!! len _and_ q_len must be max 6k, // i.e. >1024 * 6 = 6144 -> aboard) // !!! if len < q_len: 64*k, 1024*n, n=1..5 -> aboard // (broken residue issue) sl->q_len = len; sg->q_addr = addr; stlink_q(sl); stlink_print_data(sl); } // Write a "len" bytes from the sl->q_buf to the memory, max 64 Bytes. void _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_8BIT; // 2-5: addr // 6-7: len (>0x40 (64) -> aboard) write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint16(sg->cdb_cmd_blk + 6, len); // this sends the command... send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0); // This sends the data... send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len); stlink_print_data(sl); } // Write a "len" bytes from the sl->q_buf to the memory, max Q_BUF_LEN bytes. void _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_32BIT; // 2-5: addr // 6-7: len "unlimited" write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint16(sg->cdb_cmd_blk + 6, len); // this sends the command... send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0); // This sends the data... send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len); stlink_print_data(sl); } #if 0 /* not working */ static int write_flash_mem16 (struct stlink* sl, uint32_t addr, uint16_t val) { /* half word writes */ if (addr % 2) return -1; /* unlock if locked */ unlock_flash_if(sl); /* set flash programming chosen bit */ set_flash_cr_pg(sl); write_uint16(sl->q_buf, val); stlink_write_mem16(sl, addr, 2); /* wait for non business */ wait_flash_busy(sl); lock_flash(sl); /* check the programmed value back */ stlink_read_mem16(sl, addr, 2); if (*(const uint16_t*) sl->q_buf != val) { /* values differ at i * sizeof(uint16_t) */ return -1; } /* success */ return 0; } #endif /* not working */ // Exit the jtag or swd mode and enter the mass mode. void _stlink_sg_exit_debug_mode(stlink_t *stl) { if (stl) { struct stlink_libsg* sl = stl->backend_data; clear_cdb(sl); sl->cdb_cmd_blk[1] = STLINK_DEBUG_EXIT; stl->q_len = 0; // >0 -> aboard stlink_q(stl); } } // 1) open a sg device, switch the stlink from dfu to mass mode // 2) wait 5s until the kernel driver stops reseting the broken device // 3) reopen the device // 4) the device driver is now ready for a switch to jtag/swd mode // TODO thinking, better error handling, wait until the kernel driver stops reseting the plugged-in device stlink_backend_t _stlink_sg_backend = { _stlink_sg_close, _stlink_sg_exit_debug_mode, _stlink_sg_enter_swd_mode, _stlink_sg_enter_jtag_mode, _stlink_sg_exit_dfu_mode, _stlink_sg_core_id, _stlink_sg_reset, _stlink_sg_run, _stlink_sg_status, _stlink_sg_version, _stlink_sg_read_mem32, _stlink_sg_write_mem32, _stlink_sg_write_mem8, _stlink_sg_read_all_regs, _stlink_sg_read_reg, _stlink_sg_write_reg, _stlink_sg_step, _stlink_sg_current_mode, _stlink_sg_force_debug }; static stlink_t* stlink_open(const int verbose) { stlink_t *sl = malloc(sizeof (stlink_t)); memset(sl, 0, sizeof(stlink_t)); struct stlink_libsg *slsg = malloc(sizeof (struct stlink_libsg)); if (sl == NULL || slsg == NULL) { WLOG("Couldn't malloc stlink and stlink_sg structures out of memory!\n"); return NULL; } if (libusb_init(&(slsg->libusb_ctx))) { WLOG("failed to init libusb context, wrong version of libraries?\n"); free(sl); free(slsg); return NULL; } libusb_set_debug(slsg->libusb_ctx, 3); slsg->usb_handle = libusb_open_device_with_vid_pid(slsg->libusb_ctx, USB_ST_VID, USB_STLINK_PID); if (slsg->usb_handle == NULL) { WLOG("Failed to find an stlink v1 by VID:PID\n"); libusb_close(slsg->usb_handle); free(sl); free(slsg); return NULL; } // TODO // Could read the interface config descriptor, and assert lots of the assumptions // assumption: numInterfaces is always 1... if (libusb_kernel_driver_active(slsg->usb_handle, 0) == 1) { int r = libusb_detach_kernel_driver(slsg->usb_handle, 0); if (r < 0) { WLOG("libusb_detach_kernel_driver(() error %s\n", strerror(-r)); libusb_close(slsg->usb_handle); free(sl); free(slsg); return NULL; } DLOG("Kernel driver was successfully detached\n"); } int config; if (libusb_get_configuration(slsg->usb_handle, &config)) { /* this may fail for a previous configured device */ WLOG("libusb_get_configuration()\n"); libusb_close(slsg->usb_handle); free(sl); free(slsg); return NULL; } // assumption: bConfigurationValue is always 1 if (config != 1) { WLOG("Your stlink got into a real weird configuration, trying to fix it!\n"); DLOG("setting new configuration (%d -> 1)\n", config); if (libusb_set_configuration(slsg->usb_handle, 1)) { /* this may fail for a previous configured device */ WLOG("libusb_set_configuration() failed\n"); libusb_close(slsg->usb_handle); free(sl); free(slsg); return NULL; } } if (libusb_claim_interface(slsg->usb_handle, 0)) { WLOG("libusb_claim_interface() failed\n"); libusb_close(slsg->usb_handle); free(sl); free(slsg); return NULL; } // assumption: endpoint config is fixed mang. really. slsg->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN; slsg->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT; DLOG("Successfully opened stlinkv1 by libusb :)\n"); sl->verbose = verbose; sl->backend_data = slsg; sl->backend = &_stlink_sg_backend; sl->core_stat = STLINK_CORE_STAT_UNKNOWN; slsg->q_addr = 0; /* flash memory settings */ sl->flash_base = STM32_FLASH_BASE; sl->flash_size = STM32_FLASH_SIZE; sl->flash_pgsz = STM32_FLASH_PGSZ; /* system memory */ sl->sys_base = STM32_SYSTEM_BASE; sl->sys_size = STM32_SYSTEM_SIZE; /* sram memory settings */ sl->sram_base = STM32_SRAM_BASE; sl->sram_size = STM32_SRAM_SIZE; return sl; } stlink_t* stlink_v1_open(const int verbose) { ugly_init(verbose); stlink_t *sl = stlink_open(verbose); if (sl == NULL) { fputs("Error: could not open stlink device\n", stderr); return NULL; } stlink_version(sl); if ((sl->version.st_vid != USB_ST_VID) || (sl->version.stlink_pid != USB_STLINK_PID)) { ugly_log(UERROR, LOG_TAG, "WTF? successfully opened, but unable to read version details. BROKEN!\n"); return NULL; } DLOG("Reading current mode...\n"); switch (stlink_current_mode(sl)) { case STLINK_DEV_MASS_MODE: return sl; case STLINK_DEV_DEBUG_MODE: // TODO go to mass? return sl; } DLOG("Attempting to exit DFU mode\n"); _stlink_sg_exit_dfu_mode(sl); // exit the dfu mode -> the device is gone DLOG("\n*** reopen the stlink device ***\n"); delay(1000); stlink_close(sl); delay(5000); DLOG("Attempting to reopen the stlink...\n"); sl = stlink_open(verbose); if (sl == NULL) { fputs("Error: could not open stlink device\n", stderr); return NULL; } // re-query device info stlink_version(sl); return sl; }
stlink_t* stlink_open_usb(const int verbose) { stlink_t* sl = NULL; struct stlink_libusb* slu = NULL; int error = -1; libusb_device** devs = NULL; libusb_device* dev; ssize_t i; ssize_t count; int config; char *iSerial = NULL; sl = malloc(sizeof (stlink_t)); slu = malloc(sizeof (struct stlink_libusb)); if (sl == NULL) goto on_error; if (slu == NULL) goto on_error; memset(sl, 0, sizeof (stlink_t)); memset(slu, 0, sizeof (struct stlink_libusb)); ugly_init(verbose); sl->backend = &_stlink_usb_backend; sl->backend_data = slu; sl->core_stat = STLINK_CORE_STAT_UNKNOWN; /* flash memory settings */ sl->flash_base = STM32_FLASH_BASE; sl->flash_size = STM32_FLASH_SIZE; sl->flash_pgsz = STM32_FLASH_PGSZ; /* system memory */ sl->sys_base = STM32_SYSTEM_BASE; sl->sys_size = STM32_SYSTEM_SIZE; /* sram memory settings */ sl->sram_base = STM32_SRAM_BASE; sl->sram_size = STM32L_SRAM_SIZE; if (libusb_init(&(slu->libusb_ctx))) { WLOG("failed to init libusb context, wrong version of libraries?\n"); goto on_error; } slu->usb_handle = libusb_open_device_with_vid_pid(slu->libusb_ctx, USB_ST_VID, USB_STLINK_32L_PID); if (slu->usb_handle == NULL) { // TODO - free usb context too... free(slu); WLOG("Couldn't find any ST-Link/V2 devices"); return NULL; } if (libusb_kernel_driver_active(slu->usb_handle, 0) == 1) { int r; r = libusb_detach_kernel_driver(slu->usb_handle, 0); if (r<0) { WLOG("libusb_detach_kernel_driver(() error %s\n", strerror(-r)); goto on_libusb_error; } } if (libusb_get_configuration(slu->usb_handle, &config)) { /* this may fail for a previous configured device */ WLOG("libusb_get_configuration()\n"); goto on_libusb_error; } if (config != 1) { printf("setting new configuration (%d -> 1)\n", config); if (libusb_set_configuration(slu->usb_handle, 1)) { /* this may fail for a previous configured device */ WLOG("libusb_set_configuration() failed\n"); goto on_libusb_error; } } if (libusb_claim_interface(slu->usb_handle, 0)) { WLOG("libusb_claim_interface() failed\n"); goto on_libusb_error; } slu->req_trans = libusb_alloc_transfer(0); if (slu->req_trans == NULL) { WLOG("libusb_alloc_transfer failed\n"); goto on_libusb_error; } slu->rep_trans = libusb_alloc_transfer(0); if (slu->rep_trans == NULL) { WLOG("libusb_alloc_transfer failed\n"); goto on_libusb_error; } // TODO - could use the scanning techniq from stm8 code here... slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN; slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT; slu->sg_transfer_idx = 0; // TODO - never used at the moment, always CMD_SIZE slu->cmd_len = (slu->protocoll == 1)? STLINK_SG_SIZE: STLINK_CMD_SIZE; /* success */ if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { ILOG("-- exit_dfu_mode\n"); stlink_exit_dfu_mode(sl); } stlink_version(sl); error = 0; on_libusb_error: if (devs != NULL) { libusb_free_device_list(devs, 1); } if (error == -1) { stlink_close(sl); return NULL; } /* success */ return sl; on_error: if (sl != NULL) free(sl); if (slu != NULL) free(slu); return 0; }
int main(int argc, char** argv) { stlink_t *sl = NULL; st_state_t state; memset(&state, 0, sizeof(state)); // set defaults... state.stlink_version = 2; state.logging_level = DEFAULT_LOGGING_LEVEL; state.listen_port = DEFAULT_GDB_LISTEN_PORT; parse_options(argc, argv, &state); switch (state.stlink_version) { case 2: sl = stlink_open_usb(state.logging_level); if(sl == NULL) return 1; break; case 1: sl = stlink_v1_open(state.logging_level); if(sl == NULL) return 1; break; } if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { stlink_exit_dfu_mode(sl); } stlink_enter_swd_mode(sl); } uint32_t chip_id = stlink_chip_id(sl); uint32_t core_id = stlink_core_id(sl); /* Fix chip_id for F4 */ if (((chip_id & 0xFFF) == 0x411) && (core_id == CORE_M4_R0)) { printf("Fixing wrong chip_id for STM32F4 Rev A errata\n"); chip_id = 0x413; } printf("Chip ID is %08x, Core ID is %08x.\n", chip_id, core_id); const struct chip_params* params = NULL; for(int i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) { if(devices[i].chip_id == (chip_id & 0xFFF)) { params = &devices[i]; break; } } if(params == NULL) { fprintf(stderr, "Cannot recognize the connected device!\n"); return 0; } printf("Device connected: %s\n", params->description); printf("Device parameters: SRAM: 0x%x bytes, Flash: up to 0x%x bytes in pages of 0x%x bytes\n", params->sram_size, params->max_flash_size, params->flash_pagesize); FLASH_PAGE = params->flash_pagesize; uint32_t flash_size; stlink_read_mem32(sl, params->flash_size_reg, 4); flash_size = sl->q_buf[0] | (sl->q_buf[1] << 8); printf("Flash size is %d KiB.\n", flash_size); // memory map is in 1k blocks. current_memory_map = make_memory_map(params, flash_size * 0x400); while(serve(sl, state.listen_port) == 0); /* Switch back to mass storage mode before closing. */ stlink_run(sl); stlink_exit_debug_mode(sl); stlink_close(sl); return 0; }