Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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, &regs);
    stlink_step(sl);
    fputs("++++++++++ write r0 = 0x12345678\n", stderr);
    stlink_write_reg(sl, 0x12345678, 0);
    stlink_read_reg(sl, 0, &regs);
    stlink_read_all_regs(sl, &regs);
#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;
}