The indentation of various st-link source files is highly inconsistent.
Reindent all source files to 4 space indentions for consistency.
I went with 4 space indentations, as it was the most common style.
enum st_cmds {DO_WRITE = 0, DO_READ = 1, DO_ERASE = 2};
struct opts
{
- enum st_cmds cmd;
- const char* devname;
- const char* filename;
- stm32_addr_t addr;
- size_t size;
- int reset;
+ enum st_cmds cmd;
+ const char* devname;
+ const char* filename;
+ stm32_addr_t addr;
+ size_t size;
+ int reset;
};
static void usage(void)
static int get_opts(struct opts* o, int ac, char** av)
{
- /* stlinkv1 command line: ./flash {read|write} /dev/sgX path addr <size> */
- /* stlinkv2 command line: ./flash {read|write} path addr <size> */
-
- unsigned int i = 0;
-
- if (ac < 1) return -1;
-
- if (strcmp(av[0], "--reset") == 0)
- {
- o->reset = 1;
- ac--;
- av++;
- }
- else
- {
- o->reset = 0;
- }
-
- if (ac < 1) return -1;
-
- /* stlinkv2 */
- o->devname = NULL;
-
- if (strcmp(av[0], "erase") == 0)
- {
- o->cmd = DO_ERASE;
-
- /* stlinkv1 mode */
- if (ac == 2)
+ /* stlinkv1 command line: ./flash {read|write} /dev/sgX path addr <size> */
+ /* stlinkv2 command line: ./flash {read|write} path addr <size> */
+
+ unsigned int i = 0;
+
+ if (ac < 1) return -1;
+
+ if (strcmp(av[0], "--reset") == 0)
+ {
+ o->reset = 1;
+ ac--;
+ av++;
+ }
+ else
{
- o->devname = av[1];
- i = 1;
+ o->reset = 0;
}
- }
- else {
- if (ac < 3) return -1;
- if (strcmp(av[0], "read") == 0)
- {
- o->cmd = DO_READ;
-
- /* stlinkv1 mode */
- if (ac == 5)
- {
- o->devname = av[1];
- i = 1;
- }
- if (ac > 3)
- o->size = strtoul(av[i + 3], NULL, 16);
- }
- else if (strcmp(av[0], "write") == 0)
- {
- o->cmd = DO_WRITE;
-
- /* stlinkv1 mode */
- if (ac == 4)
- {
- o->devname = av[1];
- i = 1;
- }
- }
- else
- {
- return -1;
- }
- }
-
- o->filename = av[i + 1];
- o->addr = strtoul(av[i + 2], NULL, 16);
-
- return 0;
-}
+
+ if (ac < 1) return -1;
+
+ /* stlinkv2 */
+ o->devname = NULL;
+
+ if (strcmp(av[0], "erase") == 0)
+ {
+ o->cmd = DO_ERASE;
+
+ /* stlinkv1 mode */
+ if (ac == 2)
+ {
+ o->devname = av[1];
+ i = 1;
+ }
+ }
+ else {
+ if (ac < 3) return -1;
+ if (strcmp(av[0], "read") == 0)
+ {
+ o->cmd = DO_READ;
+
+ /* stlinkv1 mode */
+ if (ac == 5)
+ {
+ o->devname = av[1];
+ i = 1;
+ }
+ if (ac > 3)
+ o->size = strtoul(av[i + 3], NULL, 16);
+ }
+ else if (strcmp(av[0], "write") == 0)
+ {
+ o->cmd = DO_WRITE;
+
+ /* stlinkv1 mode */
+ if (ac == 4)
+ {
+ o->devname = av[1];
+ i = 1;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ o->filename = av[i + 1];
+ o->addr = strtoul(av[i + 2], NULL, 16);
+
+ return 0;
+}
int main(int ac, char** av)
{
- stlink_t* sl = NULL;
- struct opts o;
- 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(50, 1);
- if (sl == NULL) goto on_error;
- sl->verbose = 50;
- }
- else /* stlinkv2 */
- {
- sl = stlink_open_usb(50, 1);
- if (sl == NULL) goto on_error;
- sl->verbose = 50;
- }
-
- 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_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);
- }
- }
- 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;
- }
+ stlink_t* sl = NULL;
+ struct opts o;
+ int err = -1;
+
+ o.size = 0;
+ if (get_opts(&o, ac - 1, av + 1) == -1)
+ {
+ printf("invalid command line\n");
+ usage();
+ 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)
+
+ if (o.devname != NULL) /* stlinkv1 */
{
- printf("stlink_fwrite_flash() == -1\n");
- goto on_error;
+ sl = stlink_v1_open(50, 1);
+ if (sl == NULL) goto on_error;
+ sl->verbose = 50;
}
- }
- 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)
+ else /* stlinkv2 */
{
- printf("stlink_fread() == -1\n");
- goto on_error;
+ sl = stlink_open_usb(50, 1);
+ if (sl == NULL) goto on_error;
+ sl->verbose = 50;
}
- }
- if (o.reset)
- stlink_reset(sl);
+ if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE)
+ stlink_exit_dfu_mode(sl);
- /* success */
- err = 0;
+ if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
+ stlink_enter_swd_mode(sl);
- on_error:
- if (sl != NULL)
- {
- stlink_exit_debug_mode(sl);
- stlink_close(sl);
- }
+ if (o.reset)
+ 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);
+ }
+ }
+ 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_reset(sl);
+
+ /* success */
+ err = 0;
+
+on_error:
+ if (sl != NULL)
+ {
+ stlink_exit_debug_mode(sl);
+ stlink_close(sl);
+ }
- return err;
+ return err;
}
/* Adopted from STM AN4065 stm32f0xx_flash.c:FLASH_ProgramWord */
-write:
- ldr r4, STM32_FLASH_BASE
- mov r5, #1 /* FLASH_CR_PG, FLASH_SR_BUSY */
- mov r6, #4 /* PGERR */
+write:
+ ldr r4, STM32_FLASH_BASE
+ mov r5, #1 /* FLASH_CR_PG, FLASH_SR_BUSY */
+ mov r6, #4 /* PGERR */
write_half_word:
- ldr r3, [r4, #16] /* FLASH->CR */
- orr r3, r5
- str r3, [r4, #16] /* FLASH->CR |= FLASH_CR_PG */
- ldrh r3, [r0] /* r3 = *sram */
- strh r3, [r1] /* *flash = r3 */
+ ldr r3, [r4, #16] /* FLASH->CR */
+ orr r3, r5
+ str r3, [r4, #16] /* FLASH->CR |= FLASH_CR_PG */
+ ldrh r3, [r0] /* r3 = *sram */
+ strh r3, [r1] /* *flash = r3 */
busy:
- ldr r3, [r4, #12] /* FLASH->SR */
- tst r3, r5 /* FLASH_SR_BUSY */
- beq busy
+ ldr r3, [r4, #12] /* FLASH->SR */
+ tst r3, r5 /* FLASH_SR_BUSY */
+ beq busy
- tst r3, r6 /* PGERR */
- bne exit
+ tst r3, r6 /* PGERR */
+ bne exit
- add r0, r0, #2 /* sram += 2 */
- add r1, r1, #2 /* flash += 2 */
- sub r2, r2, #0x01 /* count-- */
- cmp r2, #0
- bne write_half_word
+ add r0, r0, #2 /* sram += 2 */
+ add r1, r1, #2 /* flash += 2 */
+ sub r2, r2, #0x01 /* count-- */
+ cmp r2, #0
+ bne write_half_word
exit:
- ldr r3, [r4, #16] /* FLASH->CR */
- bic r3, r5
- str r3, [r4, #16] /* FLASH->CR &= ~FLASH_CR_PG */
- bkpt #0x00
+ ldr r3, [r4, #16] /* FLASH->CR */
+ bic r3, r5
+ str r3, [r4, #16] /* FLASH->CR &= ~FLASH_CR_PG */
+ bkpt #0x00
STM32_FLASH_BASE: .word 0x40022000
@ r4 = temp
start:
- ldr r3, flash_base
+ ldr r3, flash_base
next:
- cbz r2, done
- ldr r4, [r0]
- str r4, [r1]
+ cbz r2, done
+ ldr r4, [r0]
+ str r4, [r1]
wait:
- ldrh r4, [r3, #0x0e]
- tst.w r4, #1
- bne wait
-
- add r0, #4
- add r1, #4
- sub r2, #1
- b next
+ ldrh r4, [r3, #0x0e]
+ tst.w r4, #1
+ bne wait
+
+ add r0, #4
+ add r1, #4
+ sub r2, #1
+ b next
done:
- bkpt
+ bkpt
.align 2
// Build : arm-eabi-gcc -c stm32lx.S
- .text
- .syntax unified
- .cpu cortex-m3
- .thumb
- .thumb_func
- .global write
+ .text
+ .syntax unified
+ .cpu cortex-m3
+ .thumb
+ .thumb_func
+ .global write
/*
- r0 - destination address
- r1 - source address
- r2 - count
+ r0 - destination address
+ r1 - source address
+ r2 - count
*/
- // Set 0 to r3
- movs r3, #0
- // Go to compare
- b.n test_done
+ // Set 0 to r3
+ movs r3, #0
+ // Go to compare
+ b.n test_done
write_word:
- // Load one word from address in r0, increment by 4
- ldr.w ip, [r1], #4
- // Store the word to address in r1, increment by 4
- str.w ip, [r0], #4
- // Increment r3
- adds r3, #1
+ // Load one word from address in r0, increment by 4
+ ldr.w ip, [r1], #4
+ // Store the word to address in r1, increment by 4
+ str.w ip, [r0], #4
+ // Increment r3
+ adds r3, #1
test_done:
- // Compare r3 and r2
- cmp r3, r2
- // Loop if not zero
- bcc.n write_word
-
- // Set breakpoint to exit
- bkpt #0x00
+ // Compare r3 and r2
+ cmp r3, r2
+ // Loop if not zero
+ bcc.n write_word
+ // Set breakpoint to exit
+ bkpt #0x00
-/* -*- tab-width:8 -*- */
-
/*
- Copyright (C) 2011 Peter Zotov <whitequark@whitequark.org>
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file.
-*/
+ * Copyright (C) 2011 Peter Zotov <whitequark@whitequark.org>
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
#include <stdio.h>
#include <string.h>
static const char hex[] = "0123456789abcdef";
int gdb_send_packet(int fd, char* data) {
- int length = strlen(data) + 5;
- char* packet = malloc(length); /* '$' data (hex) '#' cksum (hex) */
-
- memset(packet, 0, length);
-
- packet[0] = '$';
-
- uint8_t cksum = 0;
- for(unsigned int i = 0; i < strlen(data); i++) {
- packet[i + 1] = data[i];
- cksum += data[i];
- }
-
- packet[length - 4] = '#';
- packet[length - 3] = hex[cksum >> 4];
- packet[length - 2] = hex[cksum & 0xf];
-
- while(1) {
- if(write(fd, packet, length) != length) {
- free(packet);
- return -2;
- }
-
- char ack;
- if(read(fd, &ack, 1) != 1) {
- free(packet);
- return -2;
- }
-
- if(ack == '+') {
- free(packet);
- return 0;
- }
- }
+ int length = strlen(data) + 5;
+ char* packet = malloc(length); /* '$' data (hex) '#' cksum (hex) */
+
+ memset(packet, 0, length);
+
+ packet[0] = '$';
+
+ uint8_t cksum = 0;
+ for(unsigned int i = 0; i < strlen(data); i++) {
+ packet[i + 1] = data[i];
+ cksum += data[i];
+ }
+
+ packet[length - 4] = '#';
+ packet[length - 3] = hex[cksum >> 4];
+ packet[length - 2] = hex[cksum & 0xf];
+
+ while(1) {
+ if(write(fd, packet, length) != length) {
+ free(packet);
+ return -2;
+ }
+
+ char ack;
+ if(read(fd, &ack, 1) != 1) {
+ free(packet);
+ return -2;
+ }
+
+ if(ack == '+') {
+ free(packet);
+ return 0;
+ }
+ }
}
#define ALLOC_STEP 1024
int gdb_recv_packet(int fd, char** buffer) {
- unsigned packet_size = ALLOC_STEP + 1, packet_idx = 0;
- uint8_t cksum = 0;
- char recv_cksum[3] = {0};
- char* packet_buffer = malloc(packet_size);
- unsigned state;
+ unsigned packet_size = ALLOC_STEP + 1, packet_idx = 0;
+ uint8_t cksum = 0;
+ char recv_cksum[3] = {0};
+ char* packet_buffer = malloc(packet_size);
+ unsigned state;
start:
- state = 0;
- /*
- * 0: waiting $
- * 1: data, waiting #
- * 2: cksum 1
- * 3: cksum 2
- * 4: fin
- */
-
- char c;
- while(state != 4) {
- if(read(fd, &c, 1) != 1) {
- return -2;
- }
-
- switch(state) {
- case 0:
- if(c != '$') {
- // ignore
- } else {
- state = 1;
- }
- break;
-
- case 1:
- if(c == '#') {
- state = 2;
- } else {
- packet_buffer[packet_idx++] = c;
- cksum += c;
-
- if(packet_idx == packet_size) {
- packet_size += ALLOC_STEP;
- packet_buffer = realloc(packet_buffer, packet_size);
- }
- }
- break;
-
- case 2:
- recv_cksum[0] = c;
- state = 3;
- break;
-
- case 3:
- recv_cksum[1] = c;
- state = 4;
- break;
- }
- }
-
- uint8_t recv_cksum_int = strtoul(recv_cksum, NULL, 16);
- if(recv_cksum_int != cksum) {
- char nack = '-';
- if(write(fd, &nack, 1) != 1) {
- return -2;
- }
-
- goto start;
- } else {
- char ack = '+';
- if(write(fd, &ack, 1) != 1) {
- return -2;
- }
- }
-
- packet_buffer[packet_idx] = 0;
- *buffer = packet_buffer;
-
- return packet_idx;
+ state = 0;
+ /*
+ * 0: waiting $
+ * 1: data, waiting #
+ * 2: cksum 1
+ * 3: cksum 2
+ * 4: fin
+ */
+
+ char c;
+ while(state != 4) {
+ if(read(fd, &c, 1) != 1) {
+ return -2;
+ }
+
+ switch(state) {
+ case 0:
+ if(c != '$') {
+ // ignore
+ } else {
+ state = 1;
+ }
+ break;
+
+ case 1:
+ if(c == '#') {
+ state = 2;
+ } else {
+ packet_buffer[packet_idx++] = c;
+ cksum += c;
+
+ if(packet_idx == packet_size) {
+ packet_size += ALLOC_STEP;
+ packet_buffer = realloc(packet_buffer, packet_size);
+ }
+ }
+ break;
+
+ case 2:
+ recv_cksum[0] = c;
+ state = 3;
+ break;
+
+ case 3:
+ recv_cksum[1] = c;
+ state = 4;
+ break;
+ }
+ }
+
+ uint8_t recv_cksum_int = strtoul(recv_cksum, NULL, 16);
+ if(recv_cksum_int != cksum) {
+ char nack = '-';
+ if(write(fd, &nack, 1) != 1) {
+ return -2;
+ }
+
+ goto start;
+ } else {
+ char ack = '+';
+ if(write(fd, &ack, 1) != 1) {
+ return -2;
+ }
+ }
+
+ packet_buffer[packet_idx] = 0;
+ *buffer = packet_buffer;
+
+ return packet_idx;
}
// Here we skip any characters which are not \x03, GDB interrupt.
// As we use the mode with ACK, in a (very unlikely) situation of a packet
// lost because of this skipping, it will be resent anyway.
int gdb_check_for_interrupt(int fd) {
- struct pollfd pfd;
- pfd.fd = fd;
- pfd.events = POLLIN;
+ struct pollfd pfd;
+ pfd.fd = fd;
+ pfd.events = POLLIN;
- if(poll(&pfd, 1, 0) != 0) {
- char c;
+ if(poll(&pfd, 1, 0) != 0) {
+ char c;
- if(read(fd, &c, 1) != 1)
- return -2;
+ if(read(fd, &c, 1) != 1)
+ return -2;
- if(c == '\x03') // ^C
- return 1;
- }
+ if(c == '\x03') // ^C
+ return 1;
+ }
- return 0;
+ return 0;
}
-/* -*- tab-width:8 -*- */
#define DEBUG 0
/*
- Copyright (C) 2011 Peter Zotov <whitequark@whitequark.org>
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file.
-*/
+ * Copyright (C) 2011 Peter Zotov <whitequark@whitequark.org>
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
#include <getopt.h>
#include <signal.h>
{"verbose", optional_argument, NULL, 'v'},
{"stlink_version", required_argument, NULL, 's'},
{"stlinkv1", no_argument, NULL, '1'},
- {"listen_port", required_argument, NULL, 'p'},
- {"multi", optional_argument, NULL, 'm'},
- {"no-reset", optional_argument, NULL, 'n'},
+ {"listen_port", required_argument, NULL, 'p'},
+ {"multi", optional_argument, NULL, 'm'},
+ {"no-reset", optional_argument, NULL, 'n'},
{0, 0, 0, 0},
};
- const char * help_str = "%s - usage:\n\n"
- " -h, --help\t\tPrint this help\n"
- " -vXX, --verbose=XX\tSpecify a specific verbosity level (0..99)\n"
- " -v, --verbose\t\tSpecify generally verbose logging\n"
- " -s X, --stlink_version=X\n"
- "\t\t\tChoose what version of stlink to use, (defaults to 2)\n"
- " -1, --stlinkv1\tForce stlink version 1\n"
- " -p 4242, --listen_port=1234\n"
- "\t\t\tSet the gdb server listen port. "
- "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n"
- " -m, --multi\n"
- "\t\t\tSet gdb server to extended mode.\n"
- "\t\t\tst-util will continue listening for connections after disconnect.\n"
- " -n, --no-reset\n"
- "\t\t\tDo not reset board on connection.\n"
- "\n"
- "The STLINKv2 device to use can be specified in the environment\n"
- "variable STLINK_DEVICE on the format <USB_BUS>:<USB_ADDR>.\n"
- "\n"
- ;
+ const char * help_str = "%s - usage:\n\n"
+ " -h, --help\t\tPrint this help\n"
+ " -vXX, --verbose=XX\tSpecify a specific verbosity level (0..99)\n"
+ " -v, --verbose\t\tSpecify generally verbose logging\n"
+ " -s X, --stlink_version=X\n"
+ "\t\t\tChoose what version of stlink to use, (defaults to 2)\n"
+ " -1, --stlinkv1\tForce stlink version 1\n"
+ " -p 4242, --listen_port=1234\n"
+ "\t\t\tSet the gdb server listen port. "
+ "(default port: " STRINGIFY(DEFAULT_GDB_LISTEN_PORT) ")\n"
+ " -m, --multi\n"
+ "\t\t\tSet gdb server to extended mode.\n"
+ "\t\t\tst-util will continue listening for connections after disconnect.\n"
+ " -n, --no-reset\n"
+ "\t\t\tDo not reset board on connection.\n"
+ "\n"
+ "The STLINKv2 device to use can be specified in the environment\n"
+ "variable STLINK_DEVICE on the format <USB_BUS>:<USB_ADDR>.\n"
+ "\n"
+ ;
int option_index = 0;
int q;
while ((c = getopt_long(argc, argv, "hv::s:1p:mn", long_options, &option_index)) != -1) {
switch (c) {
- case 0:
- printf("XXXXX Shouldn't really normally come here, only if there's no corresponding option\n");
- printf("option %s", long_options[option_index].name);
- if (optarg) {
- printf(" with arg %s", optarg);
- }
- printf("\n");
- break;
- case 'h':
- printf(help_str, argv[0]);
- exit(EXIT_SUCCESS);
- break;
- case 'v':
- if (optarg) {
- st->logging_level = atoi(optarg);
- } else {
- st->logging_level = DEFAULT_LOGGING_LEVEL;
- }
- break;
- case '1':
- st->stlink_version = 1;
- break;
- case 's':
- sscanf(optarg, "%i", &q);
- if (q < 0 || q > 2) {
- fprintf(stderr, "stlink version %d unknown!\n", q);
- exit(EXIT_FAILURE);
- }
- st->stlink_version = q;
- break;
- case 'p':
- sscanf(optarg, "%i", &q);
- if (q < 0) {
- fprintf(stderr, "Can't use a negative port to listen on: %d\n", q);
- exit(EXIT_FAILURE);
- }
- st->listen_port = q;
- break;
- case 'm':
- st->persistent = 1;
- break;
- case 'n':
- st->reset = 0;
- break;
+ case 0:
+ printf("XXXXX Shouldn't really normally come here, only if there's no corresponding option\n");
+ printf("option %s", long_options[option_index].name);
+ if (optarg) {
+ printf(" with arg %s", optarg);
+ }
+ printf("\n");
+ break;
+ case 'h':
+ printf(help_str, argv[0]);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'v':
+ if (optarg) {
+ st->logging_level = atoi(optarg);
+ } else {
+ st->logging_level = DEFAULT_LOGGING_LEVEL;
+ }
+ break;
+ case '1':
+ st->stlink_version = 1;
+ break;
+ case 's':
+ sscanf(optarg, "%i", &q);
+ if (q < 0 || q > 2) {
+ fprintf(stderr, "stlink version %d unknown!\n", q);
+ exit(EXIT_FAILURE);
+ }
+ st->stlink_version = q;
+ break;
+ case 'p':
+ sscanf(optarg, "%i", &q);
+ if (q < 0) {
+ fprintf(stderr, "Can't use a negative port to listen on: %d\n", q);
+ exit(EXIT_FAILURE);
+ }
+ st->listen_port = q;
+ break;
+ case 'm':
+ st->persistent = 1;
+ break;
+ case 'n':
+ st->reset = 0;
+ break;
}
}
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;
+ 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(SIGTERM, &cleanup);
if (state.reset) {
- stlink_reset(sl);
+ stlink_reset(sl);
}
- printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id);
+ printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id);
- voltage = stlink_target_voltage(sl);
- if (voltage != -1) {
- printf("Target voltage is %d mV.\n", voltage);
- }
+ voltage = stlink_target_voltage(sl);
+ if (voltage != -1) {
+ printf("Target voltage is %d mV.\n", voltage);
+ }
- sl->verbose=0;
+ sl->verbose=0;
- current_memory_map = make_memory_map(sl);
+ current_memory_map = make_memory_map(sl);
#ifdef __MINGW32__
- WSADATA wsadata;
- if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) {
- goto winsock_error;
- }
+ WSADATA wsadata;
+ if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) {
+ goto winsock_error;
+ }
#endif
- do {
- serve(sl, &state);
+ do {
+ serve(sl, &state);
- /* Continue */
- stlink_run(sl);
- } while (state.persistent);
+ /* Continue */
+ stlink_run(sl);
+ } while (state.persistent);
#ifdef __MINGW32__
winsock_error:
- WSACleanup();
+ WSACleanup();
#endif
- /* Switch back to mass storage mode before closing. */
- stlink_exit_debug_mode(sl);
- stlink_close(sl);
+ /* Switch back to mass storage mode before closing. */
+ stlink_exit_debug_mode(sl);
+ stlink_close(sl);
- return 0;
+ return 0;
}
static const char* const target_description_F4 =
"</target>";
static const char* const memory_map_template_F4 =
- "<?xml version=\"1.0\"?>"
- "<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
- " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"
- "<memory-map>"
- " <memory type=\"rom\" start=\"0x00000000\" length=\"0x100000\"/>" // code = sram, bootrom or flash; flash is bigger
- " <memory type=\"ram\" start=\"0x10000000\" length=\"0x10000\"/>" // ccm ram
- " <memory type=\"ram\" start=\"0x20000000\" length=\"0x20000\"/>" // sram
- " <memory type=\"flash\" start=\"0x08000000\" length=\"0x10000\">" //Sectors 0..3
- " <property name=\"blocksize\">0x4000</property>" //16kB
- " </memory>"
- " <memory type=\"flash\" start=\"0x08010000\" length=\"0x10000\">" //Sector 4
- " <property name=\"blocksize\">0x10000</property>" //64kB
- " </memory>"
- " <memory type=\"flash\" start=\"0x08020000\" length=\"0x70000\">" //Sectors 5..11
- " <property name=\"blocksize\">0x20000</property>" //128kB
- " </memory>"
- " <memory type=\"ram\" start=\"0x40000000\" length=\"0x1fffffff\"/>" // peripheral regs
- " <memory type=\"ram\" start=\"0xe0000000\" length=\"0x1fffffff\"/>" // cortex regs
- " <memory type=\"rom\" start=\"0x1fff0000\" length=\"0x7800\"/>" // bootrom
- " <memory type=\"rom\" start=\"0x1fffc000\" length=\"0x10\"/>" // option byte area
- "</memory-map>";
+ "<?xml version=\"1.0\"?>"
+ "<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
+ " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"
+ "<memory-map>"
+ " <memory type=\"rom\" start=\"0x00000000\" length=\"0x100000\"/>" // code = sram, bootrom or flash; flash is bigger
+ " <memory type=\"ram\" start=\"0x10000000\" length=\"0x10000\"/>" // ccm ram
+ " <memory type=\"ram\" start=\"0x20000000\" length=\"0x20000\"/>" // sram
+ " <memory type=\"flash\" start=\"0x08000000\" length=\"0x10000\">" //Sectors 0..3
+ " <property name=\"blocksize\">0x4000</property>" //16kB
+ " </memory>"
+ " <memory type=\"flash\" start=\"0x08010000\" length=\"0x10000\">" //Sector 4
+ " <property name=\"blocksize\">0x10000</property>" //64kB
+ " </memory>"
+ " <memory type=\"flash\" start=\"0x08020000\" length=\"0x70000\">" //Sectors 5..11
+ " <property name=\"blocksize\">0x20000</property>" //128kB
+ " </memory>"
+ " <memory type=\"ram\" start=\"0x40000000\" length=\"0x1fffffff\"/>" // peripheral regs
+ " <memory type=\"ram\" start=\"0xe0000000\" length=\"0x1fffffff\"/>" // cortex regs
+ " <memory type=\"rom\" start=\"0x1fff0000\" length=\"0x7800\"/>" // bootrom
+ " <memory type=\"rom\" start=\"0x1fffc000\" length=\"0x10\"/>" // option byte area
+ "</memory-map>";
static const char* const memory_map_template =
- "<?xml version=\"1.0\"?>"
- "<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
- " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"
- "<memory-map>"
- " <memory type=\"rom\" start=\"0x00000000\" length=\"0x%zx\"/>" // code = sram, bootrom or flash; flash is bigger
- " <memory type=\"ram\" start=\"0x20000000\" length=\"0x%zx\"/>" // sram 8k
- " <memory type=\"flash\" start=\"0x08000000\" length=\"0x%zx\">"
- " <property name=\"blocksize\">0x%zx</property>"
- " </memory>"
- " <memory type=\"ram\" start=\"0x40000000\" length=\"0x1fffffff\"/>" // peripheral regs
- " <memory type=\"ram\" start=\"0xe0000000\" length=\"0x1fffffff\"/>" // cortex regs
- " <memory type=\"rom\" start=\"0x%08x\" length=\"0x%zx\"/>" // bootrom
- " <memory type=\"rom\" start=\"0x1ffff800\" length=\"0x10\"/>" // option byte area
- "</memory-map>";
+ "<?xml version=\"1.0\"?>"
+ "<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
+ " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"
+ "<memory-map>"
+ " <memory type=\"rom\" start=\"0x00000000\" length=\"0x%zx\"/>" // code = sram, bootrom or flash; flash is bigger
+ " <memory type=\"ram\" start=\"0x20000000\" length=\"0x%zx\"/>" // sram 8k
+ " <memory type=\"flash\" start=\"0x08000000\" length=\"0x%zx\">"
+ " <property name=\"blocksize\">0x%zx</property>"
+ " </memory>"
+ " <memory type=\"ram\" start=\"0x40000000\" length=\"0x1fffffff\"/>" // peripheral regs
+ " <memory type=\"ram\" start=\"0xe0000000\" length=\"0x1fffffff\"/>" // cortex regs
+ " <memory type=\"rom\" start=\"0x%08x\" length=\"0x%zx\"/>" // bootrom
+ " <memory type=\"rom\" start=\"0x1ffff800\" length=\"0x10\"/>" // option byte area
+ "</memory-map>";
char* make_memory_map(stlink_t *sl) {
- /* This will be freed in serve() */
- char* map = malloc(4096);
- map[0] = '\0';
+ /* This will be freed in serve() */
+ char* map = malloc(4096);
+ map[0] = '\0';
- if(sl->chip_id==STM32_CHIPID_F4) {
- strcpy(map, memory_map_template_F4);
+ if(sl->chip_id==STM32_CHIPID_F4) {
+ strcpy(map, memory_map_template_F4);
} else {
snprintf(map, 4096, memory_map_template,
- sl->flash_size,
- sl->sram_size,
- sl->flash_size, sl->flash_pgsz,
- sl->sys_base, sl->sys_size);
+ sl->flash_size,
+ sl->sram_size,
+ sl->flash_size, sl->flash_pgsz,
+ sl->sys_base, sl->sys_size);
}
- return map;
+ return map;
}
enum watchfun { WATCHDISABLED = 0, WATCHREAD = 5, WATCHWRITE = 6, WATCHACCESS = 7 };
struct code_hw_watchpoint {
- stm32_addr_t addr;
- uint8_t mask;
- enum watchfun fun;
+ stm32_addr_t addr;
+ uint8_t mask;
+ enum watchfun fun;
};
struct code_hw_watchpoint data_watches[DATA_WATCH_NUM];
static void init_data_watchpoints(stlink_t *sl) {
- #if DEBUG
- printf("init watchpoints\n");
- #endif
-
- // set trcena in debug command to turn on dwt unit
- stlink_write_debug32(sl, 0xE000EDFC,
- stlink_read_debug32(sl, 0xE000EDFC) | (1<<24));
-
- // 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);
- }
+#if DEBUG
+ printf("init watchpoints\n");
+#endif
+
+ // set trcena in debug command to turn on dwt unit
+ stlink_write_debug32(sl, 0xE000EDFC,
+ stlink_read_debug32(sl, 0xE000EDFC) | (1<<24));
+
+ // 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);
+ }
}
static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr, unsigned int len)
{
- int i = 0;
- uint32_t mask;
-
- // computer mask
- // find a free watchpoint
- // configure
-
- mask = -1;
- i = len;
- while(i) {
- i >>= 1;
- mask++;
- }
-
- if((mask != (uint32_t)-1) && (mask < 16)) {
- for(i = 0; i < DATA_WATCH_NUM; i++) {
- // is this an empty slot ?
- if(data_watches[i].fun == WATCHDISABLED) {
- #if DEBUG
- printf("insert watchpoint %d addr %x wf %u mask %u len %d\n", i, addr, wf, mask, len);
- #endif
-
- data_watches[i].fun = wf;
- data_watches[i].addr = addr;
- data_watches[i].mask = mask;
-
- // insert comparator address
- stlink_write_debug32(sl, 0xE0001020 + i * 16, addr);
-
- // insert mask
- stlink_write_debug32(sl, 0xE0001024 + i * 16, mask);
-
- // insert function
- stlink_write_debug32(sl, 0xE0001028 + i * 16, wf);
-
- // just to make sure the matched bit is clear !
- stlink_read_debug32(sl, 0xE0001028 + i * 16);
- return 0;
- }
- }
- }
-
- #if DEBUG
- printf("failure: add watchpoints addr %x wf %u len %u\n", addr, wf, len);
- #endif
- return -1;
+ int i = 0;
+ uint32_t mask;
+
+ // computer mask
+ // find a free watchpoint
+ // configure
+
+ mask = -1;
+ i = len;
+ while(i) {
+ i >>= 1;
+ mask++;
+ }
+
+ if((mask != (uint32_t)-1) && (mask < 16)) {
+ for(i = 0; i < DATA_WATCH_NUM; i++) {
+ // is this an empty slot ?
+ if(data_watches[i].fun == WATCHDISABLED) {
+#if DEBUG
+ printf("insert watchpoint %d addr %x wf %u mask %u len %d\n", i, addr, wf, mask, len);
+#endif
+
+ data_watches[i].fun = wf;
+ data_watches[i].addr = addr;
+ data_watches[i].mask = mask;
+
+ // insert comparator address
+ stlink_write_debug32(sl, 0xE0001020 + i * 16, addr);
+
+ // insert mask
+ stlink_write_debug32(sl, 0xE0001024 + i * 16, mask);
+
+ // insert function
+ stlink_write_debug32(sl, 0xE0001028 + i * 16, wf);
+
+ // just to make sure the matched bit is clear !
+ stlink_read_debug32(sl, 0xE0001028 + i * 16);
+ return 0;
+ }
+ }
+ }
+
+#if DEBUG
+ printf("failure: add watchpoints addr %x wf %u len %u\n", addr, wf, len);
+#endif
+ return -1;
}
static int delete_data_watchpoint(stlink_t *sl, stm32_addr_t addr)
{
- int i;
+ int i;
- for(i = 0 ; i < DATA_WATCH_NUM; i++) {
- if((data_watches[i].addr == addr) && (data_watches[i].fun != WATCHDISABLED)) {
- #if DEBUG
- printf("delete watchpoint %d addr %x\n", i, addr);
- #endif
+ for(i = 0 ; i < DATA_WATCH_NUM; i++) {
+ if((data_watches[i].addr == addr) && (data_watches[i].fun != WATCHDISABLED)) {
+#if DEBUG
+ printf("delete watchpoint %d addr %x\n", i, addr);
+#endif
- data_watches[i].fun = WATCHDISABLED;
- stlink_write_debug32(sl, 0xe0001028 + i * 16, 0);
+ data_watches[i].fun = WATCHDISABLED;
+ stlink_write_debug32(sl, 0xe0001028 + i * 16, 0);
- return 0;
- }
- }
+ return 0;
+ }
+ }
- #if DEBUG
- printf("failure: delete watchpoint addr %x\n", addr);
- #endif
+#if DEBUG
+ printf("failure: delete watchpoint addr %x\n", addr);
+#endif
- return -1;
+ return -1;
}
#define CODE_BREAK_NUM 6
#define CODE_BREAK_HIGH 0x02
struct code_hw_breakpoint {
- stm32_addr_t addr;
- int type;
+ stm32_addr_t addr;
+ int type;
};
struct code_hw_breakpoint code_breaks[CODE_BREAK_NUM];
static void init_code_breakpoints(stlink_t *sl) {
- memset(sl->q_buf, 0, 4);
- stlink_write_debug32(sl, CM3_REG_FP_CTRL, 0x03 /*KEY | ENABLE4*/);
- unsigned int val = stlink_read_debug32(sl, CM3_REG_FP_CTRL);
- if (((val & 3) != 1) ||
+ memset(sl->q_buf, 0, 4);
+ stlink_write_debug32(sl, CM3_REG_FP_CTRL, 0x03 /*KEY | ENABLE4*/);
+ unsigned int val = stlink_read_debug32(sl, CM3_REG_FP_CTRL);
+ if (((val & 3) != 1) ||
((((val >> 8) & 0x70) | ((val >> 4) & 0xf)) != CODE_BREAK_NUM) ||
(((val >> 8) & 0xf) != CODE_LIT_NUM)){
- fprintf(stderr, "[FP_CTRL] = 0x%08x expecting 0x%08x\n", val,
- ((CODE_BREAK_NUM & 0x70) << 8) | (CODE_LIT_NUM << 8) | ((CODE_BREAK_NUM & 0xf) << 4) | 1);
- }
-
+ fprintf(stderr, "[FP_CTRL] = 0x%08x expecting 0x%08x\n", val,
+ ((CODE_BREAK_NUM & 0x70) << 8) | (CODE_LIT_NUM << 8) | ((CODE_BREAK_NUM & 0xf) << 4) | 1);
+ }
+
- for(int i = 0; i < CODE_BREAK_NUM; i++) {
- code_breaks[i].type = 0;
- stlink_write_debug32(sl, CM3_REG_FP_COMP0 + i * 4, 0);
- }
+ for(int i = 0; i < CODE_BREAK_NUM; i++) {
+ code_breaks[i].type = 0;
+ stlink_write_debug32(sl, CM3_REG_FP_COMP0 + i * 4, 0);
+ }
}
static int update_code_breakpoint(stlink_t *sl, stm32_addr_t addr, int set) {
- stm32_addr_t fpb_addr = addr & ~0x3;
- int type = addr & 0x2 ? CODE_BREAK_HIGH : CODE_BREAK_LOW;
-
- if(addr & 1) {
- fprintf(stderr, "update_code_breakpoint: unaligned address %08x\n", addr);
- return -1;
- }
-
- 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
- }
-
- struct code_hw_breakpoint* brk = &code_breaks[id];
-
- brk->addr = fpb_addr;
-
- if(set) brk->type |= type;
- else brk->type &= ~type;
-
- if(brk->type == 0) {
- #if DEBUG
- printf("clearing hw break %d\n", id);
- #endif
-
- stlink_write_debug32(sl, 0xe0002008 + id * 4, 0);
- } else {
- uint32_t mask = (brk->addr) | 1 | (brk->type << 30);
-
- #if DEBUG
- printf("setting hw break %d at %08x (%d)\n",
- id, brk->addr, brk->type);
- printf("reg %08x \n",
- mask);
- #endif
-
- stlink_write_debug32(sl, 0xe0002008 + id * 4, mask);
- }
-
- return 0;
+ stm32_addr_t fpb_addr = addr & ~0x3;
+ int type = addr & 0x2 ? CODE_BREAK_HIGH : CODE_BREAK_LOW;
+
+ if(addr & 1) {
+ fprintf(stderr, "update_code_breakpoint: unaligned address %08x\n", addr);
+ return -1;
+ }
+
+ 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
+ }
+
+ struct code_hw_breakpoint* brk = &code_breaks[id];
+
+ brk->addr = fpb_addr;
+
+ if(set) brk->type |= type;
+ else brk->type &= ~type;
+
+ if(brk->type == 0) {
+#if DEBUG
+ printf("clearing hw break %d\n", id);
+#endif
+
+ stlink_write_debug32(sl, 0xe0002008 + id * 4, 0);
+ } else {
+ uint32_t mask = (brk->addr) | 1 | (brk->type << 30);
+
+#if DEBUG
+ printf("setting hw break %d at %08x (%d)\n",
+ id, brk->addr, brk->type);
+ printf("reg %08x \n",
+ mask);
+#endif
+
+ stlink_write_debug32(sl, 0xe0002008 + id * 4, mask);
+ }
+
+ return 0;
}
struct flash_block {
- stm32_addr_t addr;
- unsigned length;
- uint8_t* data;
+ stm32_addr_t addr;
+ unsigned length;
+ uint8_t* data;
- struct flash_block* next;
+ struct flash_block* next;
};
static struct flash_block* flash_root;
static int flash_add_block(stm32_addr_t addr, unsigned length, stlink_t *sl) {
- if(addr < FLASH_BASE || addr + length > FLASH_BASE + sl->flash_size) {
- fprintf(stderr, "flash_add_block: incorrect bounds\n");
- return -1;
- }
+ if(addr < FLASH_BASE || addr + length > FLASH_BASE + sl->flash_size) {
+ fprintf(stderr, "flash_add_block: incorrect bounds\n");
+ return -1;
+ }
- stlink_calculate_pagesize(sl, addr);
- if(addr % FLASH_PAGE != 0 || length % FLASH_PAGE != 0) {
- fprintf(stderr, "flash_add_block: unaligned block\n");
- return -1;
- }
+ stlink_calculate_pagesize(sl, addr);
+ if(addr % FLASH_PAGE != 0 || length % FLASH_PAGE != 0) {
+ fprintf(stderr, "flash_add_block: unaligned block\n");
+ return -1;
+ }
- struct flash_block* new = malloc(sizeof(struct flash_block));
- new->next = flash_root;
+ struct flash_block* new = malloc(sizeof(struct flash_block));
+ new->next = flash_root;
- new->addr = addr;
- new->length = length;
- new->data = calloc(length, 1);
+ new->addr = addr;
+ new->length = length;
+ new->data = calloc(length, 1);
- flash_root = new;
+ flash_root = new;
- return 0;
+ return 0;
}
static int flash_populate(stm32_addr_t addr, uint8_t* data, unsigned length) {
- unsigned int fit_blocks = 0, fit_length = 0;
-
- for(struct flash_block* fb = flash_root; fb; fb = fb->next) {
- /* Block: ------X------Y--------
- * Data: a-----b
- * a--b
- * a-----------b
- * Block intersects with data, if:
- * a < Y && b > x
- */
-
- unsigned X = fb->addr, Y = fb->addr + fb->length;
- unsigned a = addr, b = addr + length;
- if(a < Y && b > X) {
- // from start of the block
- unsigned start = (a > X ? a : X) - X;
- unsigned end = (b > Y ? Y : b) - X;
-
- memcpy(fb->data + start, data, end - start);
-
- fit_blocks++;
- fit_length += end - start;
- }
- }
-
- if(fit_blocks == 0) {
- fprintf(stderr, "Unfit data block %08x -> %04x\n", addr, length);
- return -1;
- }
-
- if(fit_length != length) {
- fprintf(stderr, "warning: data block %08x -> %04x truncated to %04x\n",
- addr, length, fit_length);
- fprintf(stderr, "(this is not an error, just a GDB glitch)\n");
- }
-
- return 0;
+ unsigned int fit_blocks = 0, fit_length = 0;
+
+ for(struct flash_block* fb = flash_root; fb; fb = fb->next) {
+ /* Block: ------X------Y--------
+ * Data: a-----b
+ * a--b
+ * a-----------b
+ * Block intersects with data, if:
+ * a < Y && b > x
+ */
+
+ unsigned X = fb->addr, Y = fb->addr + fb->length;
+ unsigned a = addr, b = addr + length;
+ if(a < Y && b > X) {
+ // from start of the block
+ unsigned start = (a > X ? a : X) - X;
+ unsigned end = (b > Y ? Y : b) - X;
+
+ memcpy(fb->data + start, data, end - start);
+
+ fit_blocks++;
+ fit_length += end - start;
+ }
+ }
+
+ if(fit_blocks == 0) {
+ fprintf(stderr, "Unfit data block %08x -> %04x\n", addr, length);
+ return -1;
+ }
+
+ if(fit_length != length) {
+ fprintf(stderr, "warning: data block %08x -> %04x truncated to %04x\n",
+ addr, length, fit_length);
+ fprintf(stderr, "(this is not an error, just a GDB glitch)\n");
+ }
+
+ return 0;
}
static int flash_go(stlink_t *sl) {
- int error = -1;
+ int error = -1;
- // Some kinds of clock settings do not allow writing to flash.
- stlink_reset(sl);
+ // Some kinds of clock settings do not allow writing to flash.
+ stlink_reset(sl);
- for(struct flash_block* fb = flash_root; fb; fb = fb->next) {
- #if DEBUG
- printf("flash_do: block %08x -> %04x\n", fb->addr, fb->length);
- #endif
+ for(struct flash_block* fb = flash_root; fb; fb = fb->next) {
+#if DEBUG
+ printf("flash_do: block %08x -> %04x\n", fb->addr, fb->length);
+#endif
- unsigned length = fb->length;
- for(stm32_addr_t page = fb->addr; page < fb->addr + fb->length; page += FLASH_PAGE) {
+ unsigned length = fb->length;
+ for(stm32_addr_t page = fb->addr; page < fb->addr + fb->length; page += FLASH_PAGE) {
- //Update FLASH_PAGE
- stlink_calculate_pagesize(sl, page);
+ //Update FLASH_PAGE
+ stlink_calculate_pagesize(sl, page);
- #if DEBUG
- printf("flash_do: page %08x\n", page);
- #endif
+#if DEBUG
+ printf("flash_do: page %08x\n", page);
+#endif
- if(stlink_write_flash(sl, page, fb->data + (page - fb->addr),
- length > FLASH_PAGE ? FLASH_PAGE : length) < 0)
- goto error;
- }
- }
+ if(stlink_write_flash(sl, page, fb->data + (page - fb->addr),
+ length > FLASH_PAGE ? FLASH_PAGE : length) < 0)
+ goto error;
+ }
+ }
- stlink_reset(sl);
+ stlink_reset(sl);
- error = 0;
+ error = 0;
error:
- for(struct flash_block* fb = flash_root, *next; fb; fb = next) {
- next = fb->next;
- free(fb->data);
- free(fb);
- }
+ for(struct flash_block* fb = flash_root, *next; fb; fb = next) {
+ next = fb->next;
+ free(fb->data);
+ free(fb);
+ }
- flash_root = NULL;
+ flash_root = NULL;
- return error;
+ return error;
}
int serve(stlink_t *sl, st_state_t *st) {
- int sock = socket(AF_INET, SOCK_STREAM, 0);
- if(sock < 0) {
- perror("socket");
- return 1;
- }
-
- unsigned int val = 1;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
-
- struct sockaddr_in serv_addr;
- memset(&serv_addr,0,sizeof(struct sockaddr_in));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = INADDR_ANY;
- serv_addr.sin_port = htons(st->listen_port);
-
- if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
- perror("bind");
- return 1;
- }
-
- if(listen(sock, 5) < 0) {
- perror("listen");
- return 1;
- }
-
- printf("Listening at *:%d...\n", st->listen_port);
-
- int client = accept(sock, NULL, NULL);
- //signal (SIGINT, SIG_DFL);
- if(client < 0) {
- perror("accept");
- return 1;
- }
-
- close(sock);
-
- stlink_force_debug(sl);
- if (st->reset) {
- stlink_reset(sl);
+ int sock = socket(AF_INET, SOCK_STREAM, 0);
+ if(sock < 0) {
+ perror("socket");
+ return 1;
+ }
+
+ unsigned int val = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+
+ struct sockaddr_in serv_addr;
+ memset(&serv_addr,0,sizeof(struct sockaddr_in));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = INADDR_ANY;
+ serv_addr.sin_port = htons(st->listen_port);
+
+ if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
+ perror("bind");
+ return 1;
+ }
+
+ if(listen(sock, 5) < 0) {
+ perror("listen");
+ return 1;
+ }
+
+ printf("Listening at *:%d...\n", st->listen_port);
+
+ int client = accept(sock, NULL, NULL);
+ //signal (SIGINT, SIG_DFL);
+ if(client < 0) {
+ perror("accept");
+ return 1;
+ }
+
+ close(sock);
+
+ stlink_force_debug(sl);
+ if (st->reset) {
+ stlink_reset(sl);
}
- init_code_breakpoints(sl);
- init_data_watchpoints(sl);
-
- printf("GDB connected.\n");
-
- /*
- * To allow resetting the chip from GDB it is required to
- * emulate attaching and detaching to target.
- */
- unsigned int attached = 1;
-
- while(1) {
- char* packet;
-
- int status = gdb_recv_packet(client, &packet);
- if(status < 0) {
- fprintf(stderr, "cannot recv: %d\n", status);
- return 1;
- }
-
- #if DEBUG
- printf("recv: %s\n", packet);
- #endif
-
- char* reply = NULL;
- reg regp;
-
- switch(packet[0]) {
- case 'q': {
- if(packet[1] == 'P' || packet[1] == 'C' || packet[1] == 'L') {
- reply = strdup("");
- break;
- }
-
- char *separator = strstr(packet, ":"), *params = "";
- if(separator == NULL) {
- separator = packet + strlen(packet);
- } else {
- params = separator + 1;
- }
-
- unsigned queryNameLength = (separator - &packet[1]);
- char* queryName = calloc(queryNameLength + 1, 1);
- strncpy(queryName, &packet[1], queryNameLength);
-
- #if DEBUG
- printf("query: %s;%s\n", queryName, params);
- #endif
-
- if(!strcmp(queryName, "Supported")) {
- if(sl->chip_id==STM32_CHIPID_F4) {
- reply = strdup("PacketSize=3fff;qXfer:memory-map:read+;qXfer:features:read+");
+ init_code_breakpoints(sl);
+ init_data_watchpoints(sl);
+
+ printf("GDB connected.\n");
+
+ /*
+ * To allow resetting the chip from GDB it is required to
+ * emulate attaching and detaching to target.
+ */
+ unsigned int attached = 1;
+
+ while(1) {
+ char* packet;
+
+ int status = gdb_recv_packet(client, &packet);
+ if(status < 0) {
+ fprintf(stderr, "cannot recv: %d\n", status);
+ return 1;
+ }
+
+#if DEBUG
+ printf("recv: %s\n", packet);
+#endif
+
+ char* reply = NULL;
+ reg regp;
+
+ switch(packet[0]) {
+ case 'q': {
+ if(packet[1] == 'P' || packet[1] == 'C' || packet[1] == 'L') {
+ reply = strdup("");
+ break;
}
- else {
- reply = strdup("PacketSize=3fff;qXfer:memory-map:read+");
+
+ char *separator = strstr(packet, ":"), *params = "";
+ if(separator == NULL) {
+ separator = packet + strlen(packet);
+ } else {
+ params = separator + 1;
}
- } else if(!strcmp(queryName, "Xfer")) {
- char *type, *op, *__s_addr, *s_length;
- char *tok = params;
- char *annex __attribute__((unused));
-
- type = strsep(&tok, ":");
- op = strsep(&tok, ":");
- annex = strsep(&tok, ":");
- __s_addr = strsep(&tok, ",");
- s_length = tok;
-
- unsigned addr = strtoul(__s_addr, NULL, 16),
- length = strtoul(s_length, NULL, 16);
-
- #if DEBUG
- printf("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n",
- type, op, annex, addr, length);
- #endif
-
- const char* data = NULL;
-
- if(!strcmp(type, "memory-map") && !strcmp(op, "read"))
- data = current_memory_map;
-
- if(!strcmp(type, "features") && !strcmp(op, "read"))
- data = target_description_F4;
-
- if(data) {
- unsigned data_length = strlen(data);
- if(addr + length > data_length)
- length = data_length - addr;
-
- if(length == 0) {
- reply = strdup("l");
- } else {
- reply = calloc(length + 2, 1);
- reply[0] = 'm';
- strncpy(&reply[1], data, length);
- }
- }
- } else if(!strncmp(queryName, "Rcmd,",4)) {
- // Rcmd uses the wrong separator
- char *separator = strstr(packet, ","), *params = "";
- if(separator == NULL) {
- separator = packet + strlen(packet);
- } else {
- params = separator + 1;
- }
-
-
- if (!strncmp(params,"726573756d65",12)) {// resume
+
+ unsigned queryNameLength = (separator - &packet[1]);
+ char* queryName = calloc(queryNameLength + 1, 1);
+ strncpy(queryName, &packet[1], queryNameLength);
+
+#if DEBUG
+ printf("query: %s;%s\n", queryName, params);
+#endif
+
+ if(!strcmp(queryName, "Supported")) {
+ if(sl->chip_id==STM32_CHIPID_F4) {
+ reply = strdup("PacketSize=3fff;qXfer:memory-map:read+;qXfer:features:read+");
+ }
+ else {
+ reply = strdup("PacketSize=3fff;qXfer:memory-map:read+");
+ }
+ } else if(!strcmp(queryName, "Xfer")) {
+ char *type, *op, *__s_addr, *s_length;
+ char *tok = params;
+ char *annex __attribute__((unused));
+
+ type = strsep(&tok, ":");
+ op = strsep(&tok, ":");
+ annex = strsep(&tok, ":");
+ __s_addr = strsep(&tok, ",");
+ s_length = tok;
+
+ unsigned addr = strtoul(__s_addr, NULL, 16),
+ length = strtoul(s_length, NULL, 16);
+
+#if DEBUG
+ printf("Xfer: type:%s;op:%s;annex:%s;addr:%d;length:%d\n",
+ type, op, annex, addr, length);
+#endif
+
+ const char* data = NULL;
+
+ if(!strcmp(type, "memory-map") && !strcmp(op, "read"))
+ data = current_memory_map;
+
+ if(!strcmp(type, "features") && !strcmp(op, "read"))
+ data = target_description_F4;
+
+ if(data) {
+ unsigned data_length = strlen(data);
+ if(addr + length > data_length)
+ length = data_length - addr;
+
+ if(length == 0) {
+ reply = strdup("l");
+ } else {
+ reply = calloc(length + 2, 1);
+ reply[0] = 'm';
+ strncpy(&reply[1], data, length);
+ }
+ }
+ } else if(!strncmp(queryName, "Rcmd,",4)) {
+ // Rcmd uses the wrong separator
+ char *separator = strstr(packet, ","), *params = "";
+ if(separator == NULL) {
+ separator = packet + strlen(packet);
+ } else {
+ params = separator + 1;
+ }
+
+
+ if (!strncmp(params,"726573756d65",12)) {// resume
#if DEBUG
- printf("Rcmd: resume\n");
+ printf("Rcmd: resume\n");
#endif
- stlink_run(sl);
+ stlink_run(sl);
+
+ reply = strdup("OK");
+ } else if (!strncmp(params,"68616c74",8)) { //halt
+ reply = strdup("OK");
- reply = strdup("OK");
- } else if (!strncmp(params,"68616c74",8)) { //halt
- reply = strdup("OK");
+ stlink_force_debug(sl);
- stlink_force_debug(sl);
+#if DEBUG
+ printf("Rcmd: halt\n");
+#endif
+ } else if (!strncmp(params,"6a7461675f7265736574",20)) { //jtag_reset
+ reply = strdup("OK");
+
+ stlink_jtag_reset(sl, 1);
+ stlink_jtag_reset(sl, 0);
+ stlink_force_debug(sl);
#if DEBUG
- printf("Rcmd: halt\n");
+ printf("Rcmd: jtag_reset\n");
#endif
- } else if (!strncmp(params,"6a7461675f7265736574",20)) { //jtag_reset
- reply = strdup("OK");
+ } else if (!strncmp(params,"7265736574",10)) { //reset
+ reply = strdup("OK");
- stlink_jtag_reset(sl, 1);
- stlink_jtag_reset(sl, 0);
- stlink_force_debug(sl);
+ stlink_force_debug(sl);
+ stlink_reset(sl);
+ init_code_breakpoints(sl);
+ init_data_watchpoints(sl);
#if DEBUG
- printf("Rcmd: jtag_reset\n");
+ printf("Rcmd: reset\n");
+#endif
+ } else {
+#if DEBUG
+ printf("Rcmd: %s\n", params);
#endif
- } else if (!strncmp(params,"7265736574",10)) { //reset
- reply = strdup("OK");
- stlink_force_debug(sl);
- stlink_reset(sl);
- init_code_breakpoints(sl);
- init_data_watchpoints(sl);
+ }
+
+ }
+
+ if(reply == NULL)
+ reply = strdup("");
+
+ free(queryName);
+
+ break;
+ }
+
+ case 'v': {
+ char *params = NULL;
+ char *cmdName = strtok_r(packet, ":;", ¶ms);
+
+ cmdName++; // vCommand -> Command
+
+ if(!strcmp(cmdName, "FlashErase")) {
+ char *__s_addr, *s_length;
+ char *tok = params;
+
+ __s_addr = strsep(&tok, ",");
+ s_length = tok;
+
+ unsigned addr = strtoul(__s_addr, NULL, 16),
+ length = strtoul(s_length, NULL, 16);
#if DEBUG
- printf("Rcmd: reset\n");
+ printf("FlashErase: addr:%08x,len:%04x\n",
+ addr, length);
#endif
- } else {
+
+ if(flash_add_block(addr, length, sl) < 0) {
+ reply = strdup("E00");
+ } else {
+ reply = strdup("OK");
+ }
+ } else if(!strcmp(cmdName, "FlashWrite")) {
+ char *__s_addr, *data;
+ char *tok = params;
+
+ __s_addr = strsep(&tok, ":");
+ data = tok;
+
+ unsigned addr = strtoul(__s_addr, NULL, 16);
+ unsigned data_length = status - (data - packet);
+
+ // Length of decoded data cannot be more than
+ // encoded, as escapes are removed.
+ // Additional byte is reserved for alignment fix.
+ uint8_t *decoded = calloc(data_length + 1, 1);
+ unsigned dec_index = 0;
+ for(unsigned int i = 0; i < data_length; i++) {
+ if(data[i] == 0x7d) {
+ i++;
+ decoded[dec_index++] = data[i] ^ 0x20;
+ } else {
+ decoded[dec_index++] = data[i];
+ }
+ }
+
+ // Fix alignment
+ if(dec_index % 2 != 0)
+ dec_index++;
+
#if DEBUG
- printf("Rcmd: %s\n", params);
+ printf("binary packet %d -> %d\n", data_length, dec_index);
#endif
- }
-
- }
-
- if(reply == NULL)
- reply = strdup("");
-
- free(queryName);
-
- break;
- }
-
- case 'v': {
- char *params = NULL;
- char *cmdName = strtok_r(packet, ":;", ¶ms);
-
- cmdName++; // vCommand -> Command
-
- if(!strcmp(cmdName, "FlashErase")) {
- char *__s_addr, *s_length;
- char *tok = params;
-
- __s_addr = strsep(&tok, ",");
- s_length = tok;
-
- unsigned addr = strtoul(__s_addr, NULL, 16),
- length = strtoul(s_length, NULL, 16);
-
- #if DEBUG
- printf("FlashErase: addr:%08x,len:%04x\n",
- addr, length);
- #endif
-
- if(flash_add_block(addr, length, sl) < 0) {
- reply = strdup("E00");
- } else {
- reply = strdup("OK");
- }
- } else if(!strcmp(cmdName, "FlashWrite")) {
- char *__s_addr, *data;
- char *tok = params;
-
- __s_addr = strsep(&tok, ":");
- data = tok;
-
- unsigned addr = strtoul(__s_addr, NULL, 16);
- unsigned data_length = status - (data - packet);
-
- // Length of decoded data cannot be more than
- // encoded, as escapes are removed.
- // Additional byte is reserved for alignment fix.
- uint8_t *decoded = calloc(data_length + 1, 1);
- unsigned dec_index = 0;
- for(unsigned int i = 0; i < data_length; i++) {
- if(data[i] == 0x7d) {
- i++;
- decoded[dec_index++] = data[i] ^ 0x20;
- } else {
- decoded[dec_index++] = data[i];
- }
- }
-
- // Fix alignment
- if(dec_index % 2 != 0)
- dec_index++;
-
- #if DEBUG
- printf("binary packet %d -> %d\n", data_length, dec_index);
- #endif
-
- if(flash_populate(addr, decoded, dec_index) < 0) {
- reply = strdup("E00");
- } else {
- reply = strdup("OK");
- }
- } else if(!strcmp(cmdName, "FlashDone")) {
- if(flash_go(sl) < 0) {
- reply = strdup("E00");
- } else {
- reply = strdup("OK");
- }
- } else if(!strcmp(cmdName, "Kill")) {
- attached = 0;
-
- reply = strdup("OK");
- }
-
- if(reply == NULL)
- reply = strdup("");
-
- break;
- }
-
- case 'c':
- stlink_run(sl);
-
- while(1) {
- int status = gdb_check_for_interrupt(client);
- if(status < 0) {
- fprintf(stderr, "cannot check for int: %d\n", status);
- return 1;
- }
-
- if(status == 1) {
- stlink_force_debug(sl);
- break;
- }
-
- stlink_status(sl);
- if(sl->core_stat == STLINK_CORE_HALTED) {
- break;
- }
-
- usleep(100000);
- }
-
- reply = strdup("S05"); // TRAP
- break;
-
- case 's':
- stlink_step(sl);
-
- reply = strdup("S05"); // TRAP
- break;
-
- case '?':
- if(attached) {
- reply = strdup("S05"); // TRAP
- } else {
- /* Stub shall reply OK if not attached. */
- reply = strdup("OK");
- }
- break;
-
- case 'g':
- stlink_read_all_regs(sl, ®p);
-
- reply = calloc(8 * 16 + 1, 1);
- for(int i = 0; i < 16; i++)
- sprintf(&reply[i * 8], "%08x", htonl(regp.r[i]));
-
- break;
-
- case 'p': {
- unsigned id = strtoul(&packet[1], NULL, 16);
- unsigned myreg = 0xDEADDEAD;
-
- if(id < 16) {
- stlink_read_reg(sl, id, ®p);
- myreg = htonl(regp.r[id]);
- } else if(id == 0x19) {
- stlink_read_reg(sl, 16, ®p);
- myreg = htonl(regp.xpsr);
- } else if(id == 0x1A) {
- stlink_read_reg(sl, 17, ®p);
- myreg = htonl(regp.main_sp);
- } else if(id == 0x1B) {
- stlink_read_reg(sl, 18, ®p);
- myreg = htonl(regp.process_sp);
- } else if(id == 0x1C) {
- stlink_read_unsupported_reg(sl, id, ®p);
- myreg = htonl(regp.control);
- } else if(id == 0x1D) {
- stlink_read_unsupported_reg(sl, id, ®p);
- myreg = htonl(regp.faultmask);
- } else if(id == 0x1E) {
- stlink_read_unsupported_reg(sl, id, ®p);
- myreg = htonl(regp.basepri);
- } else if(id == 0x1F) {
- stlink_read_unsupported_reg(sl, id, ®p);
- myreg = htonl(regp.primask);
- } else if(id >= 0x20 && id < 0x40) {
- stlink_read_unsupported_reg(sl, id, ®p);
- myreg = htonl(regp.s[id-0x20]);
- } else if(id == 0x40) {
- stlink_read_unsupported_reg(sl, id, ®p);
- myreg = htonl(regp.fpscr);
- } else {
- reply = strdup("E00");
- }
-
- reply = calloc(8 + 1, 1);
- sprintf(reply, "%08x", myreg);
-
- break;
- }
-
- case 'P': {
- char* s_reg = &packet[1];
- char* s_value = strstr(&packet[1], "=") + 1;
-
- unsigned reg = strtoul(s_reg, NULL, 16);
- unsigned value = strtoul(s_value, NULL, 16);
-
- if(reg < 16) {
- stlink_write_reg(sl, ntohl(value), reg);
- } else if(reg == 0x19) {
- stlink_write_reg(sl, ntohl(value), 16);
- } else if(reg == 0x1A) {
- stlink_write_reg(sl, ntohl(value), 17);
- } else if(reg == 0x1B) {
- stlink_write_reg(sl, ntohl(value), 18);
- } else if(reg == 0x1C) {
- stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
- } else if(reg == 0x1D) {
- stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
- } else if(reg == 0x1E) {
- stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
- } else if(reg == 0x1F) {
- stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
- } else if(reg >= 0x20 && reg < 0x40) {
- stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
- } else if(reg == 0x40) {
- stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
- } else {
- reply = strdup("E00");
- }
-
- if(!reply) {
- reply = strdup("OK");
- }
-
- break;
- }
-
- case 'G':
- for(int i = 0; i < 16; i++) {
- char str[9] = {0};
- strncpy(str, &packet[1 + i * 8], 8);
- uint32_t reg = strtoul(str, NULL, 16);
- stlink_write_reg(sl, ntohl(reg), i);
- }
-
- reply = strdup("OK");
- break;
-
- case 'm': {
- char* s_start = &packet[1];
- char* s_count = strstr(&packet[1], ",") + 1;
-
- stm32_addr_t start = strtoul(s_start, NULL, 16);
- unsigned count = strtoul(s_count, NULL, 16);
-
- unsigned adj_start = start % 4;
- unsigned count_rnd = (count + adj_start + 4 - 1) / 4 * 4;
-
- stlink_read_mem32(sl, start - adj_start, count_rnd);
-
- reply = calloc(count * 2 + 1, 1);
- for(unsigned int i = 0; i < count; i++) {
- reply[i * 2 + 0] = hex[sl->q_buf[i + adj_start] >> 4];
- reply[i * 2 + 1] = hex[sl->q_buf[i + adj_start] & 0xf];
- }
-
- break;
- }
-
- case 'M': {
- char* s_start = &packet[1];
- char* s_count = strstr(&packet[1], ",") + 1;
- char* hexdata = strstr(packet, ":") + 1;
-
- stm32_addr_t start = strtoul(s_start, NULL, 16);
- unsigned count = strtoul(s_count, NULL, 16);
-
- if(start % 4) {
- unsigned align_count = 4 - start % 4;
- if (align_count > count) align_count = count;
- for(unsigned int i = 0; i < align_count; i ++) {
- char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
- uint8_t byte = strtoul(hex, NULL, 16);
- sl->q_buf[i] = byte;
- }
- stlink_write_mem8(sl, start, align_count);
- start += align_count;
- count -= align_count;
- hexdata += 2*align_count;
- }
-
- if(count - count % 4) {
- unsigned aligned_count = count - count % 4;
-
- for(unsigned int i = 0; i < aligned_count; i ++) {
- char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
- uint8_t byte = strtoul(hex, NULL, 16);
- sl->q_buf[i] = byte;
- }
- stlink_write_mem32(sl, start, aligned_count);
- count -= aligned_count;
- start += aligned_count;
- hexdata += 2*aligned_count;
- }
-
- if(count) {
- for(unsigned int i = 0; i < count; i ++) {
- char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
- uint8_t byte = strtoul(hex, NULL, 16);
- sl->q_buf[i] = byte;
- }
- stlink_write_mem8(sl, start, count);
- }
- reply = strdup("OK");
- break;
- }
-
- case 'Z': {
- char *endptr;
- stm32_addr_t addr = strtoul(&packet[3], &endptr, 16);
- stm32_addr_t len = strtoul(&endptr[1], NULL, 16);
-
- switch (packet[1]) {
- case '1':
- if(update_code_breakpoint(sl, addr, 1) < 0) {
- reply = strdup("E00");
- } else {
- reply = strdup("OK");
- }
- break;
-
- case '2': // insert write watchpoint
- case '3': // insert read watchpoint
- case '4': // insert access watchpoint
- {
- enum watchfun wf;
- if(packet[1] == '2') {
- wf = WATCHWRITE;
- } else if(packet[1] == '3') {
- wf = WATCHREAD;
- } else {
- wf = WATCHACCESS;
- }
-
- if(add_data_watchpoint(sl, wf, addr, len) < 0) {
+ if(flash_populate(addr, decoded, dec_index) < 0) {
+ reply = strdup("E00");
+ } else {
+ reply = strdup("OK");
+ }
+ } else if(!strcmp(cmdName, "FlashDone")) {
+ if(flash_go(sl) < 0) {
reply = strdup("E00");
} else {
reply = strdup("OK");
+ }
+ } else if(!strcmp(cmdName, "Kill")) {
+ attached = 0;
+
+ reply = strdup("OK");
+ }
+
+ if(reply == NULL)
+ reply = strdup("");
+
+ break;
+ }
+
+ case 'c':
+ stlink_run(sl);
+
+ while(1) {
+ int status = gdb_check_for_interrupt(client);
+ if(status < 0) {
+ fprintf(stderr, "cannot check for int: %d\n", status);
+ return 1;
+ }
+
+ if(status == 1) {
+ stlink_force_debug(sl);
+ break;
+ }
+
+ stlink_status(sl);
+ if(sl->core_stat == STLINK_CORE_HALTED) {
+ break;
+ }
+
+ usleep(100000);
+ }
+
+ reply = strdup("S05"); // TRAP
+ break;
+
+ case 's':
+ stlink_step(sl);
+
+ reply = strdup("S05"); // TRAP
+ break;
+
+ case '?':
+ if(attached) {
+ reply = strdup("S05"); // TRAP
+ } else {
+ /* Stub shall reply OK if not attached. */
+ reply = strdup("OK");
+ }
+ break;
+
+ case 'g':
+ stlink_read_all_regs(sl, ®p);
+
+ reply = calloc(8 * 16 + 1, 1);
+ for(int i = 0; i < 16; i++)
+ sprintf(&reply[i * 8], "%08x", htonl(regp.r[i]));
+
+ break;
+
+ case 'p': {
+ unsigned id = strtoul(&packet[1], NULL, 16);
+ unsigned myreg = 0xDEADDEAD;
+
+ if(id < 16) {
+ stlink_read_reg(sl, id, ®p);
+ myreg = htonl(regp.r[id]);
+ } else if(id == 0x19) {
+ stlink_read_reg(sl, 16, ®p);
+ myreg = htonl(regp.xpsr);
+ } else if(id == 0x1A) {
+ stlink_read_reg(sl, 17, ®p);
+ myreg = htonl(regp.main_sp);
+ } else if(id == 0x1B) {
+ stlink_read_reg(sl, 18, ®p);
+ myreg = htonl(regp.process_sp);
+ } else if(id == 0x1C) {
+ stlink_read_unsupported_reg(sl, id, ®p);
+ myreg = htonl(regp.control);
+ } else if(id == 0x1D) {
+ stlink_read_unsupported_reg(sl, id, ®p);
+ myreg = htonl(regp.faultmask);
+ } else if(id == 0x1E) {
+ stlink_read_unsupported_reg(sl, id, ®p);
+ myreg = htonl(regp.basepri);
+ } else if(id == 0x1F) {
+ stlink_read_unsupported_reg(sl, id, ®p);
+ myreg = htonl(regp.primask);
+ } else if(id >= 0x20 && id < 0x40) {
+ stlink_read_unsupported_reg(sl, id, ®p);
+ myreg = htonl(regp.s[id-0x20]);
+ } else if(id == 0x40) {
+ stlink_read_unsupported_reg(sl, id, ®p);
+ myreg = htonl(regp.fpscr);
+ } else {
+ reply = strdup("E00");
+ }
+
+ reply = calloc(8 + 1, 1);
+ sprintf(reply, "%08x", myreg);
+
+ break;
+ }
+
+ case 'P': {
+ char* s_reg = &packet[1];
+ char* s_value = strstr(&packet[1], "=") + 1;
+
+ unsigned reg = strtoul(s_reg, NULL, 16);
+ unsigned value = strtoul(s_value, NULL, 16);
+
+ if(reg < 16) {
+ stlink_write_reg(sl, ntohl(value), reg);
+ } else if(reg == 0x19) {
+ stlink_write_reg(sl, ntohl(value), 16);
+ } else if(reg == 0x1A) {
+ stlink_write_reg(sl, ntohl(value), 17);
+ } else if(reg == 0x1B) {
+ stlink_write_reg(sl, ntohl(value), 18);
+ } else if(reg == 0x1C) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
+ } else if(reg == 0x1D) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
+ } else if(reg == 0x1E) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
+ } else if(reg == 0x1F) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
+ } else if(reg >= 0x20 && reg < 0x40) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
+ } else if(reg == 0x40) {
+ stlink_write_unsupported_reg(sl, ntohl(value), reg, ®p);
+ } else {
+ reply = strdup("E00");
+ }
+
+ if(!reply) {
+ reply = strdup("OK");
+ }
+
+ break;
+ }
+
+ case 'G':
+ for(int i = 0; i < 16; i++) {
+ char str[9] = {0};
+ strncpy(str, &packet[1 + i * 8], 8);
+ uint32_t reg = strtoul(str, NULL, 16);
+ stlink_write_reg(sl, ntohl(reg), i);
+ }
+
+ reply = strdup("OK");
+ break;
+
+ case 'm': {
+ char* s_start = &packet[1];
+ char* s_count = strstr(&packet[1], ",") + 1;
+
+ stm32_addr_t start = strtoul(s_start, NULL, 16);
+ unsigned count = strtoul(s_count, NULL, 16);
+
+ unsigned adj_start = start % 4;
+ unsigned count_rnd = (count + adj_start + 4 - 1) / 4 * 4;
+
+ stlink_read_mem32(sl, start - adj_start, count_rnd);
+
+ reply = calloc(count * 2 + 1, 1);
+ for(unsigned int i = 0; i < count; i++) {
+ reply[i * 2 + 0] = hex[sl->q_buf[i + adj_start] >> 4];
+ reply[i * 2 + 1] = hex[sl->q_buf[i + adj_start] & 0xf];
+ }
+
+ break;
+ }
+
+ case 'M': {
+ char* s_start = &packet[1];
+ char* s_count = strstr(&packet[1], ",") + 1;
+ char* hexdata = strstr(packet, ":") + 1;
+
+ stm32_addr_t start = strtoul(s_start, NULL, 16);
+ unsigned count = strtoul(s_count, NULL, 16);
+
+ if(start % 4) {
+ unsigned align_count = 4 - start % 4;
+ if (align_count > count) align_count = count;
+ for(unsigned int i = 0; i < align_count; i ++) {
+ char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
+ uint8_t byte = strtoul(hex, NULL, 16);
+ sl->q_buf[i] = byte;
+ }
+ stlink_write_mem8(sl, start, align_count);
+ start += align_count;
+ count -= align_count;
+ hexdata += 2*align_count;
+ }
+
+ if(count - count % 4) {
+ unsigned aligned_count = count - count % 4;
+
+ for(unsigned int i = 0; i < aligned_count; i ++) {
+ char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
+ uint8_t byte = strtoul(hex, NULL, 16);
+ sl->q_buf[i] = byte;
+ }
+ stlink_write_mem32(sl, start, aligned_count);
+ count -= aligned_count;
+ start += aligned_count;
+ hexdata += 2*aligned_count;
+ }
+
+ if(count) {
+ for(unsigned int i = 0; i < count; i ++) {
+ char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
+ uint8_t byte = strtoul(hex, NULL, 16);
+ sl->q_buf[i] = byte;
+ }
+ stlink_write_mem8(sl, start, count);
+ }
+ reply = strdup("OK");
+ break;
+ }
+
+ case 'Z': {
+ char *endptr;
+ stm32_addr_t addr = strtoul(&packet[3], &endptr, 16);
+ stm32_addr_t len = strtoul(&endptr[1], NULL, 16);
+
+ switch (packet[1]) {
+ case '1':
+ if(update_code_breakpoint(sl, addr, 1) < 0) {
+ reply = strdup("E00");
+ } else {
+ reply = strdup("OK");
+ }
break;
+
+ case '2': // insert write watchpoint
+ case '3': // insert read watchpoint
+ case '4': { // insert access watchpoint
+ enum watchfun wf;
+ if(packet[1] == '2') {
+ wf = WATCHWRITE;
+ } else if(packet[1] == '3') {
+ wf = WATCHREAD;
+ } else {
+ wf = WATCHACCESS;
+ }
+
+ if(add_data_watchpoint(sl, wf, addr, len) < 0) {
+ reply = strdup("E00");
+ } else {
+ reply = strdup("OK");
+ break;
+ }
}
- }
-
- default:
- reply = strdup("");
- }
- break;
- }
- case 'z': {
- char *endptr;
- stm32_addr_t addr = strtoul(&packet[3], &endptr, 16);
- //stm32_addr_t len = strtoul(&endptr[1], NULL, 16);
-
- switch (packet[1]) {
- case '1': // remove breakpoint
- update_code_breakpoint(sl, addr, 0);
- reply = strdup("OK");
- break;
-
- case '2' : // remove write watchpoint
- case '3' : // remove read watchpoint
- case '4' : // remove access watchpoint
- if(delete_data_watchpoint(sl, addr) < 0) {
- reply = strdup("E00");
- } else {
- reply = strdup("OK");
- break;
- }
-
- default:
- reply = strdup("");
- }
- break;
- }
-
- case '!': {
- /*
- * Enter extended mode which allows restarting.
- * We do support that always.
- */
-
- /*
- * Also, set to persistent mode
- * to allow GDB disconnect.
- */
- st->persistent = 1;
-
- reply = strdup("OK");
-
- break;
- }
-
- case 'R': {
- /* Reset the core. */
-
- stlink_reset(sl);
- init_code_breakpoints(sl);
- init_data_watchpoints(sl);
-
- attached = 1;
-
- reply = strdup("OK");
-
- break;
- }
-
- default:
- reply = strdup("");
- }
-
- if(reply) {
- #if DEBUG
- printf("send: %s\n", reply);
- #endif
-
- int result = gdb_send_packet(client, reply);
- if(result != 0) {
- fprintf(stderr, "cannot send: %d\n", result);
- free(reply);
- free(packet);
- return 1;
- }
-
- free(reply);
- }
-
- free(packet);
- }
-
- return 0;
+
+ default:
+ reply = strdup("");
+ }
+ break;
+ }
+ case 'z': {
+ char *endptr;
+ stm32_addr_t addr = strtoul(&packet[3], &endptr, 16);
+ //stm32_addr_t len = strtoul(&endptr[1], NULL, 16);
+
+ switch (packet[1]) {
+ case '1': // remove breakpoint
+ update_code_breakpoint(sl, addr, 0);
+ reply = strdup("OK");
+ break;
+
+ case '2' : // remove write watchpoint
+ case '3' : // remove read watchpoint
+ case '4' : // remove access watchpoint
+ if(delete_data_watchpoint(sl, addr) < 0) {
+ reply = strdup("E00");
+ } else {
+ reply = strdup("OK");
+ break;
+ }
+
+ default:
+ reply = strdup("");
+ }
+ break;
+ }
+
+ case '!': {
+ /*
+ * Enter extended mode which allows restarting.
+ * We do support that always.
+ */
+
+ /*
+ * Also, set to persistent mode
+ * to allow GDB disconnect.
+ */
+ st->persistent = 1;
+
+ reply = strdup("OK");
+
+ break;
+ }
+
+ case 'R': {
+ /* Reset the core. */
+
+ stlink_reset(sl);
+ init_code_breakpoints(sl);
+ init_data_watchpoints(sl);
+
+ attached = 1;
+
+ reply = strdup("OK");
+
+ break;
+ }
+
+ default:
+ reply = strdup("");
+ }
+
+ if(reply) {
+#if DEBUG
+ printf("send: %s\n", reply);
+#endif
+
+ int result = gdb_send_packet(client, reply);
+ if(result != 0) {
+ fprintf(stderr, "cannot send: %d\n", result);
+ free(reply);
+ free(packet);
+ return 1;
+ }
+
+ free(reply);
+ }
+
+ free(packet);
+ }
+
+ return 0;
}
static void
stlink_gui_dispose (GObject *gobject)
{
- G_OBJECT_CLASS (stlink_gui_parent_class)->dispose (gobject);
+ G_OBJECT_CLASS (stlink_gui_parent_class)->dispose (gobject);
}
static void
stlink_gui_finalize (GObject *gobject)
{
- G_OBJECT_CLASS (stlink_gui_parent_class)->finalize (gobject);
+ G_OBJECT_CLASS (stlink_gui_parent_class)->finalize (gobject);
}
static void
stlink_gui_class_init (STlinkGUIClass *klass)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->dispose = stlink_gui_dispose;
- gobject_class->finalize = stlink_gui_finalize;
+ gobject_class->dispose = stlink_gui_dispose;
+ gobject_class->finalize = stlink_gui_finalize;
}
static void
stlink_gui_init (STlinkGUI *self)
{
- self->sl = NULL;
- self->filename = NULL;
+ self->sl = NULL;
+ self->filename = NULL;
- self->progress.activity_mode = FALSE;
- self->progress.fraction = 0;
+ self->progress.activity_mode = FALSE;
+ self->progress.fraction = 0;
- self->flash_mem.memory = NULL;
- self->flash_mem.size = 0;
- self->flash_mem.base = 0;
+ self->flash_mem.memory = NULL;
+ self->flash_mem.size = 0;
+ self->flash_mem.base = 0;
- self->file_mem.memory = NULL;
- self->file_mem.size = 0;
- self->file_mem.base = 0;
+ self->file_mem.memory = NULL;
+ self->file_mem.size = 0;
+ self->file_mem.base = 0;
}
static gboolean
set_info_error_message_idle (STlinkGUI *gui)
{
- if (gui->error_message != NULL) {
- gchar *markup;
+ if (gui->error_message != NULL) {
+ gchar *markup;
- markup = g_markup_printf_escaped ("<b>%s</b>", gui->error_message);
- gtk_label_set_markup (gui->infolabel, markup);
- gtk_info_bar_set_message_type (gui->infobar, GTK_MESSAGE_ERROR);
- gtk_widget_show (GTK_WIDGET (gui->infobar));
+ markup = g_markup_printf_escaped ("<b>%s</b>", gui->error_message);
+ gtk_label_set_markup (gui->infolabel, markup);
+ gtk_info_bar_set_message_type (gui->infobar, GTK_MESSAGE_ERROR);
+ gtk_widget_show (GTK_WIDGET (gui->infobar));
- g_free (markup);
- g_free (gui->error_message);
- gui->error_message = NULL;
- }
- return FALSE;
+ g_free (markup);
+ g_free (gui->error_message);
+ gui->error_message = NULL;
+ }
+ return FALSE;
}
static void
stlink_gui_set_info_error_message (STlinkGUI *gui, const gchar *message)
{
- gui->error_message = g_strdup (message);
- g_idle_add ((GSourceFunc) set_info_error_message_idle, gui);
+ gui->error_message = g_strdup (message);
+ g_idle_add ((GSourceFunc) set_info_error_message_idle, gui);
}
static void
stlink_gui_set_sensitivity (STlinkGUI *gui, gboolean sensitivity)
{
- gtk_widget_set_sensitive (GTK_WIDGET (gui->open_button), sensitivity);
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->open_button), sensitivity);
- if (sensitivity && gui->sl)
- gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), sensitivity);
+ if (sensitivity && gui->sl)
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), sensitivity);
- if (sensitivity && !gui->sl)
- gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), sensitivity);
+ if (sensitivity && !gui->sl)
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), sensitivity);
- if (sensitivity && gui->sl && gui->filename)
- gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), sensitivity);
+ if (sensitivity && gui->sl && gui->filename)
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), sensitivity);
}
static void
mem_view_init_headers (GtkTreeView *view)
{
- GtkCellRenderer *renderer;
- gint i;
-
- g_return_if_fail (view != NULL);
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_insert_column_with_attributes (view,
- -1,
- "Address",
- renderer,
- "text",
- 0, /* column */
- NULL);
- for (i = 0; i < 4; i++) {
- gchar *label;
-
- label = g_strdup_printf ("%X", i * 4);
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_insert_column_with_attributes (view,
- -1,
- label,
- renderer,
- "text",
- (i + 1), /* column */
- NULL);
- g_free (label);
- }
-
- for (i = 0; i < 5; i++) {
- GtkTreeViewColumn *column = gtk_tree_view_get_column (view, i);
- gtk_tree_view_column_set_expand (column, TRUE);
- }
+ GtkCellRenderer *renderer;
+ gint i;
+
+ g_return_if_fail (view != NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (view,
+ -1,
+ "Address",
+ renderer,
+ "text",
+ 0, /* column */
+ NULL);
+ for (i = 0; i < 4; i++) {
+ gchar *label;
+
+ label = g_strdup_printf ("%X", i * 4);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (view,
+ -1,
+ label,
+ renderer,
+ "text",
+ (i + 1), /* column */
+ NULL);
+ g_free (label);
+ }
+
+ for (i = 0; i < 5; i++) {
+ GtkTreeViewColumn *column = gtk_tree_view_get_column (view, i);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ }
}
static void
gint column,
guint32 value)
{
- gchar *hex_str;
+ gchar *hex_str;
- hex_str = g_strdup_printf ("0x%08X", value);
- gtk_list_store_set (store, iter, column, hex_str, -1);
- g_free (hex_str);
+ hex_str = g_strdup_printf ("0x%08X", value);
+ gtk_list_store_set (store, iter, column, hex_str, -1);
+ g_free (hex_str);
}
static void
guchar *buffer,
gint len)
{
- guint32 *word;
- gint i, step;
- gint column = 0;
+ guint32 *word;
+ gint i, step;
+ gint column = 0;
- step = sizeof (*word);
+ step = sizeof (*word);
- for (i = 0; i < len; i += step) {
- word = (guint *) &buffer[i];
+ for (i = 0; i < len; i += step) {
+ word = (guint *) &buffer[i];
- if (column == 0) {
- /* new row */
- gtk_list_store_append (store, iter);
+ if (column == 0) {
+ /* new row */
+ gtk_list_store_append (store, iter);
- /* add address */
- mem_view_add_as_hex (store, iter, column, (address + i));
- }
- mem_view_add_as_hex (store, iter, (column + 1), *word);
- column = (column + 1) % step;
- }
+ /* add address */
+ mem_view_add_as_hex (store, iter, column, (address + i));
+ }
+ mem_view_add_as_hex (store, iter, (column + 1), *word);
+ column = (column + 1) % step;
+ }
}
static guint32
hexstr_to_guint32 (const gchar *str, GError **err)
{
- guint32 val;
- gchar *end_ptr;
+ guint32 val;
+ gchar *end_ptr;
- val = strtoul (str, &end_ptr, 16);
- if ((errno == ERANGE && val == LONG_MAX) || (errno != 0 && val == 0)) {
- g_set_error (err,
- g_quark_from_string ("hextou32"),
- 1,
- "Invalid hexstring");
- return LONG_MAX;
- }
- if (end_ptr == str) {
- g_set_error (err,
- g_quark_from_string ("hextou32"),
- 2,
- "Invalid hexstring");
- return LONG_MAX;
- }
- return val;
+ val = strtoul (str, &end_ptr, 16);
+ if ((errno == ERANGE && val == LONG_MAX) || (errno != 0 && val == 0)) {
+ g_set_error (err,
+ g_quark_from_string ("hextou32"),
+ 1,
+ "Invalid hexstring");
+ return LONG_MAX;
+ }
+ if (end_ptr == str) {
+ g_set_error (err,
+ g_quark_from_string ("hextou32"),
+ 2,
+ "Invalid hexstring");
+ return LONG_MAX;
+ }
+ return val;
}
static void
stlink_gui_update_mem_view (STlinkGUI *gui, struct mem_t *mem, GtkTreeView *view) {
- GtkListStore *store;
- GtkTreeIter iter;
+ GtkListStore *store;
+ GtkTreeIter iter;
- store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
+ store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
- mem_view_add_buffer (store,
- &iter,
- mem->base,
- mem->memory,
- mem->size);
+ mem_view_add_buffer (store,
+ &iter,
+ mem->base,
+ mem->memory,
+ mem->size);
- gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
- gtk_progress_bar_set_fraction (gui->progress.bar, 0);
- stlink_gui_set_sensitivity (gui, TRUE);
+ gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
+ gtk_progress_bar_set_fraction (gui->progress.bar, 0);
+ stlink_gui_set_sensitivity (gui, TRUE);
}
static gboolean
stlink_gui_update_devmem_view (STlinkGUI *gui)
{
- stlink_gui_update_mem_view (gui, &gui->flash_mem, gui->devmem_treeview);
- return FALSE;
+ stlink_gui_update_mem_view (gui, &gui->flash_mem, gui->devmem_treeview);
+ return FALSE;
}
static void
stlink_gui_populate_devmem_view (STlinkGUI *gui)
{
- guint off;
- stm32_addr_t addr;
-
- g_return_if_fail (gui != NULL);
- g_return_if_fail (gui->sl != NULL);
-
- addr = gui->sl->flash_base;
-
- if (gui->flash_mem.memory) {
- g_free (gui->flash_mem.memory);
- }
- gui->flash_mem.memory = g_malloc (gui->sl->flash_size);
- gui->flash_mem.size = gui->sl->flash_size;
- gui->flash_mem.base = gui->sl->flash_base;
-
- for (off = 0; off < gui->sl->flash_size; off += MEM_READ_SIZE) {
- guint n_read = MEM_READ_SIZE;
-
- if (off + MEM_READ_SIZE > gui->sl->flash_size) {
- n_read = gui->sl->flash_size - off;
-
- /* align if needed */
- if (n_read & 3) {
- n_read = (n_read + 4) & ~(3);
- }
- }
- /* reads to sl->q_buf */
- stlink_read_mem32(gui->sl, addr + off, n_read);
- if (gui->sl->q_len < 0) {
- stlink_gui_set_info_error_message (gui, "Failed to read memory");
- g_free (gui->flash_mem.memory);
- gui->flash_mem.memory = NULL;
- return;
- }
- memcpy (gui->flash_mem.memory + off, gui->sl->q_buf, n_read);
- gui->progress.fraction = (gdouble) (off + n_read) / gui->sl->flash_size;
- }
- g_idle_add ((GSourceFunc) stlink_gui_update_devmem_view, gui);
+ guint off;
+ stm32_addr_t addr;
+
+ g_return_if_fail (gui != NULL);
+ g_return_if_fail (gui->sl != NULL);
+
+ addr = gui->sl->flash_base;
+
+ if (gui->flash_mem.memory) {
+ g_free (gui->flash_mem.memory);
+ }
+ gui->flash_mem.memory = g_malloc (gui->sl->flash_size);
+ gui->flash_mem.size = gui->sl->flash_size;
+ gui->flash_mem.base = gui->sl->flash_base;
+
+ for (off = 0; off < gui->sl->flash_size; off += MEM_READ_SIZE) {
+ guint n_read = MEM_READ_SIZE;
+
+ if (off + MEM_READ_SIZE > gui->sl->flash_size) {
+ n_read = gui->sl->flash_size - off;
+
+ /* align if needed */
+ if (n_read & 3) {
+ n_read = (n_read + 4) & ~(3);
+ }
+ }
+ /* reads to sl->q_buf */
+ stlink_read_mem32(gui->sl, addr + off, n_read);
+ if (gui->sl->q_len < 0) {
+ stlink_gui_set_info_error_message (gui, "Failed to read memory");
+ g_free (gui->flash_mem.memory);
+ gui->flash_mem.memory = NULL;
+ return;
+ }
+ memcpy (gui->flash_mem.memory + off, gui->sl->q_buf, n_read);
+ gui->progress.fraction = (gdouble) (off + n_read) / gui->sl->flash_size;
+ }
+ g_idle_add ((GSourceFunc) stlink_gui_update_devmem_view, gui);
}
static gboolean
stlink_gui_update_filemem_view (STlinkGUI *gui)
{
- gchar *basename;
+ gchar *basename;
- basename = g_path_get_basename (gui->filename);
- gtk_notebook_set_tab_label_text (gui->notebook,
- GTK_WIDGET (gtk_notebook_get_nth_page (gui->notebook, 1)),
- basename);
- g_free (basename);
+ basename = g_path_get_basename (gui->filename);
+ gtk_notebook_set_tab_label_text (gui->notebook,
+ GTK_WIDGET (gtk_notebook_get_nth_page (gui->notebook, 1)),
+ basename);
+ g_free (basename);
- stlink_gui_update_mem_view (gui, &gui->file_mem, gui->filemem_treeview);
+ stlink_gui_update_mem_view (gui, &gui->file_mem, gui->filemem_treeview);
- return FALSE;
+ return FALSE;
}
static gpointer
stlink_gui_populate_filemem_view (STlinkGUI *gui)
{
- guchar buffer[MEM_READ_SIZE];
- GFile *file;
- GFileInfo *file_info;
- GInputStream *input_stream;
- gint off;
- GError *err = NULL;
-
- g_return_val_if_fail (gui != NULL, NULL);
- g_return_val_if_fail (gui->filename != NULL, NULL);
-
- file = g_file_new_for_path (gui->filename);
- input_stream = G_INPUT_STREAM (g_file_read (file, NULL, &err));
- if (err) {
- stlink_gui_set_info_error_message (gui, err->message);
- g_error_free (err);
- goto out;
- }
-
- file_info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (input_stream),
- G_FILE_ATTRIBUTE_STANDARD_SIZE, NULL, &err);
- if (err) {
- stlink_gui_set_info_error_message (gui, err->message);
- g_error_free (err);
- goto out_input;
- }
- if (gui->file_mem.memory) {
- g_free (gui->file_mem.memory);
- }
- gui->file_mem.size = g_file_info_get_size (file_info);
- gui->file_mem.memory = g_malloc (gui->file_mem.size);
-
- for (off = 0; off < gui->file_mem.size; off += MEM_READ_SIZE) {
- guint n_read = MEM_READ_SIZE;
-
- if (off + MEM_READ_SIZE > gui->file_mem.size) {
- n_read = gui->file_mem.size - off;
- }
-
- if (g_input_stream_read (G_INPUT_STREAM (input_stream),
- &buffer, n_read, NULL, &err) == -1) {
- stlink_gui_set_info_error_message (gui, err->message);
- g_error_free (err);
- goto out_input;
- }
- memcpy (gui->file_mem.memory + off, buffer, n_read);
- gui->progress.fraction = (gdouble) (off + n_read) / gui->file_mem.size;
- }
- g_idle_add ((GSourceFunc) stlink_gui_update_filemem_view, gui);
-
- out_input:
- g_object_unref (input_stream);
- out:
- g_object_unref (file);
- return NULL;
+ guchar buffer[MEM_READ_SIZE];
+ GFile *file;
+ GFileInfo *file_info;
+ GInputStream *input_stream;
+ gint off;
+ GError *err = NULL;
+
+ g_return_val_if_fail (gui != NULL, NULL);
+ g_return_val_if_fail (gui->filename != NULL, NULL);
+
+ file = g_file_new_for_path (gui->filename);
+ input_stream = G_INPUT_STREAM (g_file_read (file, NULL, &err));
+ if (err) {
+ stlink_gui_set_info_error_message (gui, err->message);
+ g_error_free (err);
+ goto out;
+ }
+
+ file_info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (input_stream),
+ G_FILE_ATTRIBUTE_STANDARD_SIZE, NULL, &err);
+ if (err) {
+ stlink_gui_set_info_error_message (gui, err->message);
+ g_error_free (err);
+ goto out_input;
+ }
+ if (gui->file_mem.memory) {
+ g_free (gui->file_mem.memory);
+ }
+ gui->file_mem.size = g_file_info_get_size (file_info);
+ gui->file_mem.memory = g_malloc (gui->file_mem.size);
+
+ for (off = 0; off < gui->file_mem.size; off += MEM_READ_SIZE) {
+ guint n_read = MEM_READ_SIZE;
+
+ if (off + MEM_READ_SIZE > gui->file_mem.size) {
+ n_read = gui->file_mem.size - off;
+ }
+
+ if (g_input_stream_read (G_INPUT_STREAM (input_stream),
+ &buffer, n_read, NULL, &err) == -1) {
+ stlink_gui_set_info_error_message (gui, err->message);
+ g_error_free (err);
+ goto out_input;
+ }
+ memcpy (gui->file_mem.memory + off, buffer, n_read);
+ gui->progress.fraction = (gdouble) (off + n_read) / gui->file_mem.size;
+ }
+ g_idle_add ((GSourceFunc) stlink_gui_update_filemem_view, gui);
+
+out_input:
+ g_object_unref (input_stream);
+out:
+ g_object_unref (file);
+ return NULL;
}
static void mem_jmp (GtkTreeView *view,
gsize size,
GError **err)
{
- GtkTreeModel *model;
- guint32 jmp_addr;
- GtkTreeIter iter;
-
- jmp_addr = hexstr_to_guint32 (gtk_entry_get_text (entry), err);
- if (err && *err) {
- return;
- }
-
- if (jmp_addr < base_addr || jmp_addr > base_addr + size) {
- g_set_error (err,
- g_quark_from_string ("mem_jmp"),
- 1,
- "Invalid address");
- return;
- }
-
- model = gtk_tree_view_get_model (view);
- if (!model) {
- return;
- }
-
- if (gtk_tree_model_get_iter_first (model, &iter)) {
- do {
- guint32 addr;
- GValue value = G_VALUE_INIT;
- GError *err = NULL;
-
- gtk_tree_model_get_value (model, &iter, 0, &value);
- if (G_VALUE_HOLDS_STRING (&value)) {
- addr = hexstr_to_guint32 (g_value_get_string (&value), &err);
- if (!err) {
- if (addr == (jmp_addr & 0xFFFFFFF0)) {
- GtkTreeSelection *selection;
- GtkTreePath *path;
-
- selection = gtk_tree_view_get_selection (view);
- path = gtk_tree_model_get_path (model, &iter);
-
- gtk_tree_selection_select_iter (selection, &iter);
- gtk_tree_view_scroll_to_cell (view,
- path,
- NULL,
- TRUE,
- 0.0,
- 0.0);
- gtk_tree_path_free (path);
- }
- }
- }
- g_value_unset (&value);
- } while (gtk_tree_model_iter_next (model, &iter));
- }
+ GtkTreeModel *model;
+ guint32 jmp_addr;
+ GtkTreeIter iter;
+
+ jmp_addr = hexstr_to_guint32 (gtk_entry_get_text (entry), err);
+ if (err && *err) {
+ return;
+ }
+
+ if (jmp_addr < base_addr || jmp_addr > base_addr + size) {
+ g_set_error (err,
+ g_quark_from_string ("mem_jmp"),
+ 1,
+ "Invalid address");
+ return;
+ }
+
+ model = gtk_tree_view_get_model (view);
+ if (!model) {
+ return;
+ }
+
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ guint32 addr;
+ GValue value = G_VALUE_INIT;
+ GError *err = NULL;
+
+ gtk_tree_model_get_value (model, &iter, 0, &value);
+ if (G_VALUE_HOLDS_STRING (&value)) {
+ addr = hexstr_to_guint32 (g_value_get_string (&value), &err);
+ if (!err) {
+ if (addr == (jmp_addr & 0xFFFFFFF0)) {
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+
+ selection = gtk_tree_view_get_selection (view);
+ path = gtk_tree_model_get_path (model, &iter);
+
+ gtk_tree_selection_select_iter (selection, &iter);
+ gtk_tree_view_scroll_to_cell (view,
+ path,
+ NULL,
+ TRUE,
+ 0.0,
+ 0.0);
+ gtk_tree_path_free (path);
+ }
+ }
+ }
+ g_value_unset (&value);
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
}
static void
devmem_jmp_cb (GtkWidget *widget, gpointer data)
{
- STlinkGUI *gui;
- GError *err = NULL;
+ STlinkGUI *gui;
+ GError *err = NULL;
- gui = STLINK_GUI (data);
+ gui = STLINK_GUI (data);
- mem_jmp (gui->devmem_treeview,
- gui->devmem_jmp_entry,
- gui->sl->flash_base,
- gui->sl->flash_size,
- &err);
+ mem_jmp (gui->devmem_treeview,
+ gui->devmem_jmp_entry,
+ gui->sl->flash_base,
+ gui->sl->flash_size,
+ &err);
- if (err) {
- stlink_gui_set_info_error_message (gui, err->message);
- g_error_free (err);
- }
+ if (err) {
+ stlink_gui_set_info_error_message (gui, err->message);
+ g_error_free (err);
+ }
}
static void
filemem_jmp_cb (GtkWidget *widget, gpointer data)
{
- STlinkGUI *gui;
- GError *err = NULL;
+ STlinkGUI *gui;
+ GError *err = NULL;
- gui = STLINK_GUI (data);
+ gui = STLINK_GUI (data);
- g_return_if_fail (gui->filename != NULL);
+ g_return_if_fail (gui->filename != NULL);
- mem_jmp (gui->filemem_treeview,
- gui->filemem_jmp_entry,
- 0,
- gui->file_mem.size,
- &err);
+ mem_jmp (gui->filemem_treeview,
+ gui->filemem_jmp_entry,
+ 0,
+ gui->file_mem.size,
+ &err);
- if (err) {
- stlink_gui_set_info_error_message (gui, err->message);
- g_error_free (err);
- }
+ if (err) {
+ stlink_gui_set_info_error_message (gui, err->message);
+ g_error_free (err);
+ }
}
static gchar *
dev_format_chip_id (guint32 chip_id)
{
- gint i;
+ gint i;
- for (i = 0; i < sizeof (devices) / sizeof (devices[0]); i++) {
- if (chip_id == devices[i].chip_id) {
- return g_strdup (devices[i].description);
- }
- }
- return g_strdup_printf ("0x%x", chip_id);
+ for (i = 0; i < sizeof (devices) / sizeof (devices[0]); i++) {
+ if (chip_id == devices[i].chip_id) {
+ return g_strdup (devices[i].description);
+ }
+ }
+ return g_strdup_printf ("0x%x", chip_id);
}
static gchar *
dev_format_mem_size (gsize flash_size)
{
- return g_strdup_printf ("%u kB", flash_size / 1024);
+ return g_strdup_printf ("%u kB", flash_size / 1024);
}
static void
stlink_gui_set_connected (STlinkGUI *gui)
{
- gchar *tmp_str;
- GtkListStore *store;
- GtkTreeIter iter;
+ gchar *tmp_str;
+ GtkListStore *store;
+ GtkTreeIter iter;
- gtk_statusbar_push (gui->statusbar,
- gtk_statusbar_get_context_id (gui->statusbar, "conn"),
- "Connected");
+ gtk_statusbar_push (gui->statusbar,
+ gtk_statusbar_get_context_id (gui->statusbar, "conn"),
+ "Connected");
- gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), TRUE);
- gtk_widget_set_sensitive (GTK_WIDGET (gui->devmem_box), TRUE);
- gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->devmem_box), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), FALSE);
- if (gui->filename) {
- gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), TRUE);
- }
+ if (gui->filename) {
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), TRUE);
+ }
- tmp_str = dev_format_chip_id (gui->sl->chip_id);
- gtk_label_set_text (gui->chip_id_label, tmp_str);
- g_free (tmp_str);
+ tmp_str = dev_format_chip_id (gui->sl->chip_id);
+ gtk_label_set_text (gui->chip_id_label, tmp_str);
+ g_free (tmp_str);
- tmp_str = g_strdup_printf ("0x%x", gui->sl->core_id);
- gtk_label_set_text (gui->core_id_label, tmp_str);
- g_free (tmp_str);
+ tmp_str = g_strdup_printf ("0x%x", gui->sl->core_id);
+ gtk_label_set_text (gui->core_id_label, tmp_str);
+ g_free (tmp_str);
- tmp_str = dev_format_mem_size (gui->sl->flash_size);
- gtk_label_set_text (gui->flash_size_label, tmp_str);
- g_free (tmp_str);
+ tmp_str = dev_format_mem_size (gui->sl->flash_size);
+ gtk_label_set_text (gui->flash_size_label, tmp_str);
+ g_free (tmp_str);
- tmp_str = dev_format_mem_size (gui->sl->sram_size);
- gtk_label_set_text (gui->ram_size_label, tmp_str);
- g_free (tmp_str);
+ tmp_str = dev_format_mem_size (gui->sl->sram_size);
+ gtk_label_set_text (gui->ram_size_label, tmp_str);
+ g_free (tmp_str);
- tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base);
- gtk_entry_set_text (gui->devmem_jmp_entry, tmp_str);
- gtk_editable_set_editable (GTK_EDITABLE (gui->devmem_jmp_entry), TRUE);
- g_free (tmp_str);
+ tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base);
+ gtk_entry_set_text (gui->devmem_jmp_entry, tmp_str);
+ gtk_editable_set_editable (GTK_EDITABLE (gui->devmem_jmp_entry), TRUE);
+ g_free (tmp_str);
- store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview));
- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
- gtk_list_store_clear (store);
- }
+ store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview));
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+ gtk_list_store_clear (store);
+ }
- stlink_gui_set_sensitivity (gui, FALSE);
- gtk_notebook_set_current_page (gui->notebook, PAGE_DEVMEM);
- gtk_widget_show (GTK_WIDGET (gui->progress.bar));
- gtk_progress_bar_set_text (gui->progress.bar, "Reading memory");
+ stlink_gui_set_sensitivity (gui, FALSE);
+ gtk_notebook_set_current_page (gui->notebook, PAGE_DEVMEM);
+ gtk_widget_show (GTK_WIDGET (gui->progress.bar));
+ gtk_progress_bar_set_text (gui->progress.bar, "Reading memory");
- g_thread_new ("devmem", (GThreadFunc) stlink_gui_populate_devmem_view, gui);
+ g_thread_new ("devmem", (GThreadFunc) stlink_gui_populate_devmem_view, gui);
}
static void
connect_button_cb (GtkWidget *widget, gpointer data)
{
- STlinkGUI *gui;
- gint i;
+ STlinkGUI *gui;
+ gint i;
- gui = STLINK_GUI (data);
+ gui = STLINK_GUI (data);
- if (gui->sl != NULL)
- return;
+ if (gui->sl != NULL)
+ return;
- /* try version 1 then version 2 */
- gui->sl = stlink_v1_open(0, 1);
- if (gui->sl == NULL) {
- gui->sl = stlink_open_usb(0, 1);
- }
- if (gui->sl == NULL) {
- stlink_gui_set_info_error_message (gui, "Failed to connect to STLink."); return;
- }
+ /* try version 1 then version 2 */
+ gui->sl = stlink_v1_open(0, 1);
+ if (gui->sl == NULL) {
+ gui->sl = stlink_open_usb(0, 1);
+ }
+ if (gui->sl == NULL) {
+ stlink_gui_set_info_error_message (gui, "Failed to connect to STLink."); return;
+ }
- /* code below taken from flash/main.c, refactoring might be in order */
- if (stlink_current_mode(gui->sl) == STLINK_DEV_DFU_MODE)
- stlink_exit_dfu_mode(gui->sl);
+ /* code below taken from flash/main.c, refactoring might be in order */
+ if (stlink_current_mode(gui->sl) == STLINK_DEV_DFU_MODE)
+ stlink_exit_dfu_mode(gui->sl);
- if (stlink_current_mode(gui->sl) != STLINK_DEV_DEBUG_MODE)
- stlink_enter_swd_mode(gui->sl);
+ if (stlink_current_mode(gui->sl) != STLINK_DEV_DEBUG_MODE)
+ stlink_enter_swd_mode(gui->sl);
- /* Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 */
- if (gui->sl->chip_id == STM32_CHIPID_F4) {
- memset(gui->sl->q_buf, 0, 4);
- for (i = 0; i < 8; i++) {
- stlink_write_mem32(gui->sl, 0x40026000 + 0x10 + 0x18 * i, 4);
- stlink_write_mem32(gui->sl, 0x40026400 + 0x10 + 0x18 * i, 4);
- stlink_write_mem32(gui->sl, 0x40026000 + 0x24 + 0x18 * i, 4);
- stlink_write_mem32(gui->sl, 0x40026400 + 0x24 + 0x18 * i, 4);
- }
- }
- stlink_gui_set_connected (gui);
+ /* Disable DMA - Set All DMA CCR Registers to zero. - AKS 1/7/2013 */
+ if (gui->sl->chip_id == STM32_CHIPID_F4) {
+ memset(gui->sl->q_buf, 0, 4);
+ for (i = 0; i < 8; i++) {
+ stlink_write_mem32(gui->sl, 0x40026000 + 0x10 + 0x18 * i, 4);
+ stlink_write_mem32(gui->sl, 0x40026400 + 0x10 + 0x18 * i, 4);
+ stlink_write_mem32(gui->sl, 0x40026000 + 0x24 + 0x18 * i, 4);
+ stlink_write_mem32(gui->sl, 0x40026400 + 0x24 + 0x18 * i, 4);
+ }
+ }
+ stlink_gui_set_connected (gui);
}
static void stlink_gui_set_disconnected (STlinkGUI *gui)
{
- gtk_statusbar_push (gui->statusbar,
- gtk_statusbar_get_context_id (gui->statusbar, "conn"),
- "Disconnected");
+ gtk_statusbar_push (gui->statusbar,
+ gtk_statusbar_get_context_id (gui->statusbar, "conn"),
+ "Disconnected");
- gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), FALSE);
- gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), FALSE);
- gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), FALSE);
- gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->device_frame), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->flash_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->disconnect_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (gui->connect_button), TRUE);
}
static void
disconnect_button_cb (GtkWidget *widget, gpointer data)
{
- STlinkGUI *gui;
+ STlinkGUI *gui;
- gui = STLINK_GUI (data);
+ 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);
+ if (gui->sl != NULL) {
+ stlink_exit_debug_mode(gui->sl);
+ stlink_close(gui->sl);
+ gui->sl = NULL;
+ }
+ stlink_gui_set_disconnected (gui);
}
static void
stlink_gui_open_file (STlinkGUI *gui)
{
- GtkWidget *dialog;
- GtkListStore *store;
- GtkTreeIter iter;
+ GtkWidget *dialog;
+ GtkListStore *store;
+ GtkTreeIter iter;
- dialog = gtk_file_chooser_dialog_new ("Open file",
- gui->window,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
- NULL);
+ dialog = gtk_file_chooser_dialog_new ("Open file",
+ gui->window,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
- if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
- gui->filename =
- gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+ gui->filename =
+ gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
- store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->filemem_treeview));
- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
- gtk_list_store_clear (store);
- }
+ store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->filemem_treeview));
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+ gtk_list_store_clear (store);
+ }
- stlink_gui_set_sensitivity (gui, FALSE);
- gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM);
- gtk_widget_show (GTK_WIDGET (gui->progress.bar));
- gtk_progress_bar_set_text (gui->progress.bar, "Reading file");
- g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui);
- }
- gtk_widget_destroy (dialog);
+ stlink_gui_set_sensitivity (gui, FALSE);
+ gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM);
+ gtk_widget_show (GTK_WIDGET (gui->progress.bar));
+ gtk_progress_bar_set_text (gui->progress.bar, "Reading file");
+ g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui);
+ }
+ gtk_widget_destroy (dialog);
}
static void
open_button_cb (GtkWidget *widget, gpointer data)
{
- STlinkGUI *gui;
+ STlinkGUI *gui;
- gui = STLINK_GUI (data);
+ gui = STLINK_GUI (data);
- stlink_gui_open_file (gui);
+ stlink_gui_open_file (gui);
}
static gboolean
stlink_gui_write_flash_update (STlinkGUI *gui)
{
- stlink_gui_set_sensitivity (gui, TRUE);
- gui->progress.activity_mode = FALSE;
- gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
+ stlink_gui_set_sensitivity (gui, TRUE);
+ gui->progress.activity_mode = FALSE;
+ gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
- return FALSE;
+ return FALSE;
}
static void
stlink_gui_write_flash (STlinkGUI *gui)
{
- g_return_if_fail (gui->sl != NULL);
- g_return_if_fail (gui->filename != NULL);
+ g_return_if_fail (gui->sl != NULL);
+ g_return_if_fail (gui->filename != NULL);
- if (stlink_fwrite_flash(gui->sl, gui->filename, gui->sl->flash_base) < 0) {
- stlink_gui_set_info_error_message (gui, "Failed to write to flash");
- }
+ if (stlink_fwrite_flash(gui->sl, gui->filename, gui->sl->flash_base) < 0) {
+ stlink_gui_set_info_error_message (gui, "Failed to write to flash");
+ }
- g_idle_add ((GSourceFunc) stlink_gui_write_flash_update, gui);
+ g_idle_add ((GSourceFunc) stlink_gui_write_flash_update, gui);
}
static void
flash_button_cb (GtkWidget *widget, gpointer data)
{
- STlinkGUI *gui;
- gchar *tmp_str;
- guint32 address;
- gint result;
- GError *err = NULL;
-
- gui = STLINK_GUI (data);
- g_return_if_fail (gui->sl != NULL);
-
- if (!g_strcmp0 (gtk_entry_get_text (gui->flash_dialog_entry), "")) {
- tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base);
- gtk_entry_set_text (gui->flash_dialog_entry, tmp_str);
- g_free (tmp_str);
- }
-
- result = gtk_dialog_run (gui->flash_dialog);
- if (result == GTK_RESPONSE_OK) {
- address = hexstr_to_guint32 (gtk_entry_get_text (gui->flash_dialog_entry),
- &err);
- if (err) {
- stlink_gui_set_info_error_message (gui, err->message);
- } else {
- if (address > gui->sl->flash_base + gui->sl->flash_size ||
- address < gui->sl->flash_base) {
- stlink_gui_set_info_error_message (gui, "Invalid address");
- }
- else if (address + gui->file_mem.size >
- gui->sl->flash_base + gui->sl->flash_size) {
- stlink_gui_set_info_error_message (gui, "Binary overwrites flash");
- } else {
- stlink_gui_set_sensitivity (gui, FALSE);
- gtk_progress_bar_set_text (gui->progress.bar,
- "Writing to flash");
- gui->progress.activity_mode = TRUE;
- gtk_widget_show (GTK_WIDGET (gui->progress.bar));
- g_thread_new ("flash",
- (GThreadFunc) stlink_gui_write_flash, gui);
- }
- }
- }
+ STlinkGUI *gui;
+ gchar *tmp_str;
+ guint32 address;
+ gint result;
+ GError *err = NULL;
+
+ gui = STLINK_GUI (data);
+ g_return_if_fail (gui->sl != NULL);
+
+ if (!g_strcmp0 (gtk_entry_get_text (gui->flash_dialog_entry), "")) {
+ tmp_str = g_strdup_printf ("0x%08X", gui->sl->flash_base);
+ gtk_entry_set_text (gui->flash_dialog_entry, tmp_str);
+ g_free (tmp_str);
+ }
+
+ result = gtk_dialog_run (gui->flash_dialog);
+ if (result == GTK_RESPONSE_OK) {
+ address = hexstr_to_guint32 (gtk_entry_get_text (gui->flash_dialog_entry),
+ &err);
+ if (err) {
+ stlink_gui_set_info_error_message (gui, err->message);
+ } else {
+ if (address > gui->sl->flash_base + gui->sl->flash_size ||
+ address < gui->sl->flash_base) {
+ stlink_gui_set_info_error_message (gui, "Invalid address");
+ }
+ else if (address + gui->file_mem.size >
+ gui->sl->flash_base + gui->sl->flash_size) {
+ stlink_gui_set_info_error_message (gui, "Binary overwrites flash");
+ } else {
+ stlink_gui_set_sensitivity (gui, FALSE);
+ gtk_progress_bar_set_text (gui->progress.bar,
+ "Writing to flash");
+ gui->progress.activity_mode = TRUE;
+ gtk_widget_show (GTK_WIDGET (gui->progress.bar));
+ g_thread_new ("flash",
+ (GThreadFunc) stlink_gui_write_flash, gui);
+ }
+ }
+ }
}
static gboolean
progress_pulse_timeout (STlinkGUI *gui) {
- if (gui->progress.activity_mode) {
- gtk_progress_bar_pulse (gui->progress.bar);
- } else {
- gtk_progress_bar_set_fraction (gui->progress.bar, gui->progress.fraction);
- }
- return TRUE;
+ if (gui->progress.activity_mode) {
+ gtk_progress_bar_pulse (gui->progress.bar);
+ } else {
+ gtk_progress_bar_set_fraction (gui->progress.bar, gui->progress.fraction);
+ }
+ return TRUE;
}
static void
guint page_num,
gpointer data)
{
- STlinkGUI *gui;
+ STlinkGUI *gui;
- gui = STLINK_GUI (data);
+ gui = STLINK_GUI (data);
- if (page_num == 1) {
- if (gui->filename == NULL) {
- stlink_gui_open_file (gui);
- }
- }
+ if (page_num == 1) {
+ if (gui->filename == NULL) {
+ stlink_gui_open_file (gui);
+ }
+ }
}
static void
guint time,
gpointer data)
{
- GFile *file_uri;
- gchar **file_list;
- const guchar *file_data;
- STlinkGUI *gui = STLINK_GUI (data);
- GtkListStore *store;
- GtkTreeIter iter;
+ GFile *file_uri;
+ gchar **file_list;
+ const guchar *file_data;
+ STlinkGUI *gui = STLINK_GUI (data);
+ GtkListStore *store;
+ GtkTreeIter iter;
- if (selection_data != NULL &&
- gtk_selection_data_get_length (selection_data) > 0) {
- switch (target_type) {
- case TARGET_FILENAME:
+ if (selection_data != NULL &&
+ gtk_selection_data_get_length (selection_data) > 0) {
+ switch (target_type) {
+ case TARGET_FILENAME:
- if (gui->filename) {
- g_free (gui->filename);
- }
+ if (gui->filename) {
+ g_free (gui->filename);
+ }
- file_data = gtk_selection_data_get_data (selection_data);
- file_list = g_strsplit ((gchar *)file_data, "\r\n", 0);
+ file_data = gtk_selection_data_get_data (selection_data);
+ file_list = g_strsplit ((gchar *)file_data, "\r\n", 0);
- file_uri = g_file_new_for_uri (file_list[0]);
- gui->filename = g_file_get_path (file_uri);
+ file_uri = g_file_new_for_uri (file_list[0]);
+ gui->filename = g_file_get_path (file_uri);
- g_strfreev (file_list);
- g_object_unref (file_uri);
+ g_strfreev (file_list);
+ g_object_unref (file_uri);
- store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview));
- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
- gtk_list_store_clear (store);
- }
+ store = GTK_LIST_STORE (gtk_tree_view_get_model (gui->devmem_treeview));
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
+ gtk_list_store_clear (store);
+ }
- stlink_gui_set_sensitivity (gui, FALSE);
- gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM);
- gtk_widget_show (GTK_WIDGET (gui->progress.bar));
- gtk_progress_bar_set_text (gui->progress.bar, "Reading file");
- g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui);
- break;
- }
- }
- gtk_drag_finish (context,
- TRUE,
- gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE,
- time);
+ stlink_gui_set_sensitivity (gui, FALSE);
+ gtk_notebook_set_current_page (gui->notebook, PAGE_FILEMEM);
+ gtk_widget_show (GTK_WIDGET (gui->progress.bar));
+ gtk_progress_bar_set_text (gui->progress.bar, "Reading file");
+ g_thread_new ("file", (GThreadFunc) stlink_gui_populate_filemem_view, gui);
+ break;
+ }
+ }
+ gtk_drag_finish (context,
+ TRUE,
+ gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE,
+ time);
}
void
stlink_gui_init_dnd (STlinkGUI *gui)
{
- GtkTargetEntry target_list[] = {
- { "text/uri-list", 0, TARGET_FILENAME },
- };
+ GtkTargetEntry target_list[] = {
+ { "text/uri-list", 0, TARGET_FILENAME },
+ };
- gtk_drag_dest_set (GTK_WIDGET (gui->window),
- GTK_DEST_DEFAULT_ALL,
- target_list,
- G_N_ELEMENTS (target_list),
- GDK_ACTION_COPY);
+ gtk_drag_dest_set (GTK_WIDGET (gui->window),
+ GTK_DEST_DEFAULT_ALL,
+ target_list,
+ G_N_ELEMENTS (target_list),
+ GDK_ACTION_COPY);
- g_signal_connect (gui->window, "drag-data-received",
- G_CALLBACK (dnd_received_cb), gui);
+ g_signal_connect (gui->window, "drag-data-received",
+ G_CALLBACK (dnd_received_cb), gui);
}
static void
stlink_gui_build_ui (STlinkGUI *gui) {
- GtkBuilder *builder;
- GtkListStore *devmem_store;
- GtkListStore *filemem_store;
- gchar *ui_file = STLINK_UI_DIR "/stlink-gui.ui";
-
- if (!g_file_test (ui_file, G_FILE_TEST_EXISTS)) {
- ui_file = "stlink-gui.ui";
- }
- builder = gtk_builder_new ();
- if (!gtk_builder_add_from_file (builder, ui_file, NULL)) {
- g_printerr ("Failed to load UI file: %s\n", ui_file);
- exit (1);
- }
-
- gui->window = GTK_WINDOW (gtk_builder_get_object (builder, "window"));
- g_signal_connect (G_OBJECT (gui->window), "destroy",
- G_CALLBACK (gtk_main_quit), NULL);
-
- /* set up toolutton clicked callbacks */
- gui->open_button =
- GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "open_button"));
- g_signal_connect (G_OBJECT (gui->open_button), "clicked",
- G_CALLBACK (open_button_cb), gui);
-
- gui->connect_button =
- GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "connect_button"));
- g_signal_connect (G_OBJECT (gui->connect_button), "clicked",
- G_CALLBACK (connect_button_cb), gui);
-
- gui->disconnect_button =
- GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "disconnect_button"));
- g_signal_connect (G_OBJECT (gui->disconnect_button), "clicked",
- G_CALLBACK (disconnect_button_cb), gui);
-
- gui->flash_button =
- GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "flash_button"));
- g_signal_connect (G_OBJECT (gui->flash_button), "clicked",
- G_CALLBACK (flash_button_cb), gui);
-
- gui->devmem_treeview =
- GTK_TREE_VIEW (gtk_builder_get_object (builder, "devmem_treeview"));
- gtk_tree_view_set_rules_hint (gui->devmem_treeview, TRUE);
- mem_view_init_headers (gui->devmem_treeview);
- devmem_store = gtk_list_store_new (5,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING);
- gtk_tree_view_set_model (gui->devmem_treeview, GTK_TREE_MODEL (devmem_store));
- g_object_unref (devmem_store);
-
- gui->filemem_treeview =
- GTK_TREE_VIEW (gtk_builder_get_object (builder, "filemem_treeview"));
- gtk_tree_view_set_rules_hint (gui->filemem_treeview, TRUE);
- mem_view_init_headers (gui->filemem_treeview);
- filemem_store = gtk_list_store_new (5,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_STRING);
- gtk_tree_view_set_model (gui->filemem_treeview, GTK_TREE_MODEL (filemem_store));
- g_object_unref (filemem_store);
-
- gui->core_id_label =
- GTK_LABEL (gtk_builder_get_object (builder, "core_id_value"));
-
- gui->chip_id_label =
- GTK_LABEL (gtk_builder_get_object (builder, "chip_id_value"));
-
- gui->flash_size_label =
- GTK_LABEL (gtk_builder_get_object (builder, "flash_size_value"));
-
- gui->ram_size_label =
- GTK_LABEL (gtk_builder_get_object (builder, "ram_size_value"));
-
- gui->device_frame =
- GTK_FRAME (gtk_builder_get_object (builder, "device_frame"));
-
- gui->notebook =
- GTK_NOTEBOOK (gtk_builder_get_object (builder, "mem_notebook"));
- g_signal_connect (gui->notebook, "switch-page",
- G_CALLBACK (notebook_switch_page_cb), gui);
-
- gui->devmem_box =
- GTK_BOX (gtk_builder_get_object (builder, "devmem_box"));
-
- gui->filemem_box =
- GTK_BOX (gtk_builder_get_object (builder, "filemem_box"));
-
- gui->devmem_jmp_entry =
- GTK_ENTRY (gtk_builder_get_object (builder, "devmem_jmp_entry"));
- g_signal_connect (gui->devmem_jmp_entry, "activate",
- G_CALLBACK (devmem_jmp_cb), gui);
-
- gui->filemem_jmp_entry =
- GTK_ENTRY (gtk_builder_get_object (builder, "filemem_jmp_entry"));
- g_signal_connect (gui->filemem_jmp_entry, "activate",
- G_CALLBACK (filemem_jmp_cb), gui);
- gtk_editable_set_editable (GTK_EDITABLE (gui->filemem_jmp_entry), TRUE);
-
- gui->progress.bar =
- GTK_PROGRESS_BAR (gtk_builder_get_object (builder, "progressbar"));
- gtk_progress_bar_set_show_text (gui->progress.bar, TRUE);
- gui->progress.timer = g_timeout_add (100,
- (GSourceFunc) progress_pulse_timeout,
- gui);
-
- gui->statusbar =
- GTK_STATUSBAR (gtk_builder_get_object (builder, "statusbar"));
-
- gui->infobar =
- GTK_INFO_BAR (gtk_builder_get_object (builder, "infobar"));
- gtk_info_bar_add_button (gui->infobar, GTK_STOCK_OK, GTK_RESPONSE_OK);
- gui->infolabel = GTK_LABEL (gtk_label_new (""));
- gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (gui->infobar)),
- GTK_WIDGET (gui->infolabel));
- g_signal_connect (gui->infobar, "response", G_CALLBACK (gtk_widget_hide), NULL);
-
- /* flash dialog */
- gui->flash_dialog =
- GTK_DIALOG (gtk_builder_get_object (builder, "flash_dialog"));
- g_signal_connect_swapped (gui->flash_dialog, "response",
- G_CALLBACK (gtk_widget_hide), gui->flash_dialog);
-
- gui->flash_dialog_ok =
- GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_ok_button"));
-
- gui->flash_dialog_cancel =
- GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_cancel_button"));
-
- gui->flash_dialog_entry =
- GTK_ENTRY (gtk_builder_get_object (builder, "flash_dialog_entry"));
-
- /* make it so */
- gtk_widget_show_all (GTK_WIDGET (gui->window));
- gtk_widget_hide (GTK_WIDGET (gui->infobar));
- gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
-
- stlink_gui_set_disconnected (gui);
+ GtkBuilder *builder;
+ GtkListStore *devmem_store;
+ GtkListStore *filemem_store;
+ gchar *ui_file = STLINK_UI_DIR "/stlink-gui.ui";
+
+ if (!g_file_test (ui_file, G_FILE_TEST_EXISTS)) {
+ ui_file = "stlink-gui.ui";
+ }
+ builder = gtk_builder_new ();
+ if (!gtk_builder_add_from_file (builder, ui_file, NULL)) {
+ g_printerr ("Failed to load UI file: %s\n", ui_file);
+ exit (1);
+ }
+
+ gui->window = GTK_WINDOW (gtk_builder_get_object (builder, "window"));
+ g_signal_connect (G_OBJECT (gui->window), "destroy",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ /* set up toolutton clicked callbacks */
+ gui->open_button =
+ GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "open_button"));
+ g_signal_connect (G_OBJECT (gui->open_button), "clicked",
+ G_CALLBACK (open_button_cb), gui);
+
+ gui->connect_button =
+ GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "connect_button"));
+ g_signal_connect (G_OBJECT (gui->connect_button), "clicked",
+ G_CALLBACK (connect_button_cb), gui);
+
+ gui->disconnect_button =
+ GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "disconnect_button"));
+ g_signal_connect (G_OBJECT (gui->disconnect_button), "clicked",
+ G_CALLBACK (disconnect_button_cb), gui);
+
+ gui->flash_button =
+ GTK_TOOL_BUTTON (gtk_builder_get_object (builder, "flash_button"));
+ g_signal_connect (G_OBJECT (gui->flash_button), "clicked",
+ G_CALLBACK (flash_button_cb), gui);
+
+ gui->devmem_treeview =
+ GTK_TREE_VIEW (gtk_builder_get_object (builder, "devmem_treeview"));
+ gtk_tree_view_set_rules_hint (gui->devmem_treeview, TRUE);
+ mem_view_init_headers (gui->devmem_treeview);
+ devmem_store = gtk_list_store_new (5,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+ gtk_tree_view_set_model (gui->devmem_treeview, GTK_TREE_MODEL (devmem_store));
+ g_object_unref (devmem_store);
+
+ gui->filemem_treeview =
+ GTK_TREE_VIEW (gtk_builder_get_object (builder, "filemem_treeview"));
+ gtk_tree_view_set_rules_hint (gui->filemem_treeview, TRUE);
+ mem_view_init_headers (gui->filemem_treeview);
+ filemem_store = gtk_list_store_new (5,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+ gtk_tree_view_set_model (gui->filemem_treeview, GTK_TREE_MODEL (filemem_store));
+ g_object_unref (filemem_store);
+
+ gui->core_id_label =
+ GTK_LABEL (gtk_builder_get_object (builder, "core_id_value"));
+
+ gui->chip_id_label =
+ GTK_LABEL (gtk_builder_get_object (builder, "chip_id_value"));
+
+ gui->flash_size_label =
+ GTK_LABEL (gtk_builder_get_object (builder, "flash_size_value"));
+
+ gui->ram_size_label =
+ GTK_LABEL (gtk_builder_get_object (builder, "ram_size_value"));
+
+ gui->device_frame =
+ GTK_FRAME (gtk_builder_get_object (builder, "device_frame"));
+
+ gui->notebook =
+ GTK_NOTEBOOK (gtk_builder_get_object (builder, "mem_notebook"));
+ g_signal_connect (gui->notebook, "switch-page",
+ G_CALLBACK (notebook_switch_page_cb), gui);
+
+ gui->devmem_box =
+ GTK_BOX (gtk_builder_get_object (builder, "devmem_box"));
+
+ gui->filemem_box =
+ GTK_BOX (gtk_builder_get_object (builder, "filemem_box"));
+
+ gui->devmem_jmp_entry =
+ GTK_ENTRY (gtk_builder_get_object (builder, "devmem_jmp_entry"));
+ g_signal_connect (gui->devmem_jmp_entry, "activate",
+ G_CALLBACK (devmem_jmp_cb), gui);
+
+ gui->filemem_jmp_entry =
+ GTK_ENTRY (gtk_builder_get_object (builder, "filemem_jmp_entry"));
+ g_signal_connect (gui->filemem_jmp_entry, "activate",
+ G_CALLBACK (filemem_jmp_cb), gui);
+ gtk_editable_set_editable (GTK_EDITABLE (gui->filemem_jmp_entry), TRUE);
+
+ gui->progress.bar =
+ GTK_PROGRESS_BAR (gtk_builder_get_object (builder, "progressbar"));
+ gtk_progress_bar_set_show_text (gui->progress.bar, TRUE);
+ gui->progress.timer = g_timeout_add (100,
+ (GSourceFunc) progress_pulse_timeout,
+ gui);
+
+ gui->statusbar =
+ GTK_STATUSBAR (gtk_builder_get_object (builder, "statusbar"));
+
+ gui->infobar =
+ GTK_INFO_BAR (gtk_builder_get_object (builder, "infobar"));
+ gtk_info_bar_add_button (gui->infobar, GTK_STOCK_OK, GTK_RESPONSE_OK);
+ gui->infolabel = GTK_LABEL (gtk_label_new (""));
+ gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (gui->infobar)),
+ GTK_WIDGET (gui->infolabel));
+ g_signal_connect (gui->infobar, "response", G_CALLBACK (gtk_widget_hide), NULL);
+
+ /* flash dialog */
+ gui->flash_dialog =
+ GTK_DIALOG (gtk_builder_get_object (builder, "flash_dialog"));
+ g_signal_connect_swapped (gui->flash_dialog, "response",
+ G_CALLBACK (gtk_widget_hide), gui->flash_dialog);
+
+ gui->flash_dialog_ok =
+ GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_ok_button"));
+
+ gui->flash_dialog_cancel =
+ GTK_BUTTON (gtk_builder_get_object (builder, "flash_dialog_cancel_button"));
+
+ gui->flash_dialog_entry =
+ GTK_ENTRY (gtk_builder_get_object (builder, "flash_dialog_entry"));
+
+ /* make it so */
+ gtk_widget_show_all (GTK_WIDGET (gui->window));
+ gtk_widget_hide (GTK_WIDGET (gui->infobar));
+ gtk_widget_hide (GTK_WIDGET (gui->progress.bar));
+
+ stlink_gui_set_disconnected (gui);
}
int
main (int argc, char **argv)
{
- STlinkGUI *gui;
+ STlinkGUI *gui;
- gtk_init (&argc, &argv);
+ gtk_init (&argc, &argv);
- gui = g_object_new (STLINK_TYPE_GUI, NULL);
- stlink_gui_build_ui (gui);
- stlink_gui_init_dnd (gui);
+ gui = g_object_new (STLINK_TYPE_GUI, NULL);
+ stlink_gui_build_ui (gui);
+ stlink_gui_init_dnd (gui);
- gtk_main ();
+ gtk_main ();
- return 0;
+ return 0;
}
typedef struct _STlinkGUIPrivate STlinkGUIPrivate;
enum stlink_gui_pages_t {
- PAGE_DEVMEM,
- PAGE_FILEMEM
+ PAGE_DEVMEM,
+ PAGE_FILEMEM
};
enum stlink_gui_dnd_targets_t {
- TARGET_FILENAME,
- TARGET_ROOTWIN
+ TARGET_FILENAME,
+ TARGET_ROOTWIN
};
struct progress_t {
- GtkProgressBar *bar;
- guint timer;
- gboolean activity_mode;
- gdouble fraction;
+ GtkProgressBar *bar;
+ guint timer;
+ gboolean activity_mode;
+ gdouble fraction;
};
struct mem_t {
- guchar *memory;
- gsize size;
- guint32 base;
+ guchar *memory;
+ gsize size;
+ guint32 base;
};
struct _STlinkGUI
{
- GObject parent_instance;
-
- /*< private >*/
- GtkWindow *window;
- GtkTreeView *devmem_treeview;
- GtkTreeView *filemem_treeview;
- GtkSpinner *spinner;
- GtkStatusbar *statusbar;
- GtkInfoBar *infobar;
- GtkLabel *infolabel;
- GtkNotebook *notebook;
- GtkFrame *device_frame;
- GtkLabel *chip_id_label;
- GtkLabel *core_id_label;
- GtkLabel *flash_size_label;
- GtkLabel *ram_size_label;
- GtkBox *devmem_box;
- GtkEntry *devmem_jmp_entry;
- GtkBox *filemem_box;
- GtkEntry *filemem_jmp_entry;
- GtkToolButton *connect_button;
- GtkToolButton *disconnect_button;
- GtkToolButton *flash_button;
- GtkToolButton *open_button;
-
- /* flash dialog */
- GtkDialog *flash_dialog;
- GtkButton *flash_dialog_ok;
- GtkButton *flash_dialog_cancel;
- GtkEntry *flash_dialog_entry;
-
- struct progress_t progress;
- struct mem_t flash_mem;
- struct mem_t file_mem;
-
- gchar *error_message;
- gchar *filename;
- stlink_t *sl;
+ GObject parent_instance;
+
+ /*< private >*/
+ GtkWindow *window;
+ GtkTreeView *devmem_treeview;
+ GtkTreeView *filemem_treeview;
+ GtkSpinner *spinner;
+ GtkStatusbar *statusbar;
+ GtkInfoBar *infobar;
+ GtkLabel *infolabel;
+ GtkNotebook *notebook;
+ GtkFrame *device_frame;
+ GtkLabel *chip_id_label;
+ GtkLabel *core_id_label;
+ GtkLabel *flash_size_label;
+ GtkLabel *ram_size_label;
+ GtkBox *devmem_box;
+ GtkEntry *devmem_jmp_entry;
+ GtkBox *filemem_box;
+ GtkEntry *filemem_jmp_entry;
+ GtkToolButton *connect_button;
+ GtkToolButton *disconnect_button;
+ GtkToolButton *flash_button;
+ GtkToolButton *open_button;
+
+ /* flash dialog */
+ GtkDialog *flash_dialog;
+ GtkButton *flash_dialog_ok;
+ GtkButton *flash_dialog_cancel;
+ GtkEntry *flash_dialog_entry;
+
+ struct progress_t progress;
+ struct mem_t flash_mem;
+ struct mem_t file_mem;
+
+ gchar *error_message;
+ gchar *filename;
+ stlink_t *sl;
};
struct _STlinkGUIClass
{
- GObjectClass parent_class;
+ GObjectClass parent_class;
- /* class members */
+ /* class members */
};
GType stlink_gui_get_type (void);
FD_ZERO(&ofds);
FD_ZERO(&efds);
for (i = 0, op = ip = 0; i < nfds; ++i) {
- fds[i].revents = 0;
- if(fds[i].events & (POLLIN|POLLPRI)) {
- ip = &ifds;
- FD_SET(fds[i].fd, ip);
- }
- if(fds[i].events & POLLOUT) {
- op = &ofds;
- FD_SET(fds[i].fd, op);
- }
- FD_SET(fds[i].fd, &efds);
+ fds[i].revents = 0;
+ if(fds[i].events & (POLLIN|POLLPRI)) {
+ ip = &ifds;
+ FD_SET(fds[i].fd, ip);
+ }
+ if(fds[i].events & POLLOUT) {
+ op = &ofds;
+ FD_SET(fds[i].fd, op);
+ }
+ FD_SET(fds[i].fd, &efds);
}
/* Set up the timeval structure for the timeout parameter */
if(timo < 0) {
- toptr = 0;
+ toptr = 0;
} else {
- toptr = &timeout;
- timeout.tv_sec = timo / 1000;
- timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
+ toptr = &timeout;
+ timeout.tv_sec = timo / 1000;
+ timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
}
#ifdef DEBUG_POLL
printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n",
- (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op);
+ (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op);
#endif
rc = select(0, ip, op, &efds, toptr);
#ifdef DEBUG_POLL
#endif
if(rc <= 0)
- return rc;
+ return rc;
if(rc > 0) {
for ( i = 0; i < nfds; ++i) {
int fd = fds[i].fd;
- if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds))
- fds[i].revents |= POLLIN;
- if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
- fds[i].revents |= POLLOUT;
- if(FD_ISSET(fd, &efds))
- /* Some error was detected ... should be some way to know. */
- fds[i].revents |= POLLHUP;
+ if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds))
+ fds[i].revents |= POLLIN;
+ if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
+ fds[i].revents |= POLLOUT;
+ if(FD_ISSET(fd, &efds))
+ /* Some error was detected ... should be some way to know. */
+ fds[i].revents |= POLLHUP;
#ifdef DEBUG_POLL
- printf("%d %d %d revent = %x\n",
- FD_ISSET(fd, &ifds), FD_ISSET(fd, &ofds), FD_ISSET(fd, &efds),
- fds[i].revents
- );
+ printf("%d %d %d revent = %x\n",
+ FD_ISSET(fd, &ifds), FD_ISSET(fd, &ofds), FD_ISSET(fd, &efds),
+ fds[i].revents
+ );
#endif
}
}
set_connect_errno(int winsock_err)
{
switch(winsock_err) {
- case WSAEINVAL:
- case WSAEALREADY:
- case WSAEWOULDBLOCK:
- errno = EINPROGRESS;
- break;
- default:
- errno = winsock_err;
- break;
+ case WSAEINVAL:
+ case WSAEALREADY:
+ case WSAEWOULDBLOCK:
+ errno = EINPROGRESS;
+ break;
+ default:
+ errno = winsock_err;
+ break;
}
}
set_socket_errno(int winsock_err)
{
switch(winsock_err) {
- case WSAEWOULDBLOCK:
- errno = EAGAIN;
- break;
- default:
- errno = winsock_err;
- break;
+ case WSAEWOULDBLOCK:
+ errno = EAGAIN;
+ break;
+ default:
+ errno = winsock_err;
+ break;
}
}
/*
char * win32_strtok_r(char *s, const char *delim, char **lasts)
{
- register char *spanp;
- register int c, sc;
- char *tok;
+ register char *spanp;
+ register int c, sc;
+ char *tok;
- if (s == NULL && (s = *lasts) == NULL)
- return (NULL);
+ if (s == NULL && (s = *lasts) == NULL)
+ return (NULL);
- /*
- * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
- */
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
cont:
- c = *s++;
- for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
- if (c == sc)
- goto cont;
- }
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+ if (c == sc)
+ goto cont;
+ }
- if (c == 0) { /* no non-delimiter characters */
- *lasts = NULL;
- return (NULL);
- }
- tok = s - 1;
+ if (c == 0) { /* no non-delimiter characters */
+ *lasts = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
- /*
- * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
- * Note that delim must have one NUL; we stop if we see that, too.
- */
- for (;;) {
- c = *s++;
- spanp = (char *)delim;
- do {
- if ((sc = *spanp++) == c) {
- if (c == 0)
- s = NULL;
- else
- s[-1] = 0;
- *lasts = s;
- return (tok);
- }
- } while (sc != 0);
- }
- /* NOTREACHED */
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *lasts = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
}
char *win32_strsep (char **stringp, const char *delim)
{
- register char *s;
- register const char *spanp;
- register int c, sc;
- char *tok;
+ register char *s;
+ register const char *spanp;
+ register int c, sc;
+ char *tok;
- if ((s = *stringp) == NULL)
- return (NULL);
- for (tok = s;;) {
- c = *s++;
- spanp = delim;
- do {
- if ((sc = *spanp++) == c) {
- if (c == 0)
- s = NULL;
- else
- s[-1] = 0;
- *stringp = s;
- return (tok);
- }
- } while (sc != 0);
- }
- /* NOTREACHED */
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
}
#endif
void *mmap (void *addr, size_t len, int prot, int flags, int fd, long long offset) {
- void *buf;
- ssize_t count;
+ void *buf;
+ ssize_t count;
- if ( addr || fd == -1 || (prot & PROT_WRITE)) return MAP_FAILED;
+ if ( addr || fd == -1 || (prot & PROT_WRITE)) return MAP_FAILED;
- buf = malloc(len);
- if ( NULL == buf ) return MAP_FAILED;
+ buf = malloc(len);
+ if ( NULL == buf ) return MAP_FAILED;
- if (lseek(fd,offset,SEEK_SET) != offset) return MAP_FAILED;
+ if (lseek(fd,offset,SEEK_SET) != offset) return MAP_FAILED;
- count = read(fd, buf, len);
+ count = read(fd, buf, len);
- if (count != len) {
- free (buf);
- return MAP_FAILED;
- }
+ if (count != len) {
+ free (buf);
+ return MAP_FAILED;
+ }
- return buf;
+ return buf;
}
int munmap (void *addr, size_t len) {
- free (addr);
- return 0;
+ free (addr);
+ return 0;
}
extern "C" {
#endif
-void *mmap(void *addr, size_t len, int prot, int flags, int fd, long long offset);
-int munmap(void *addr, size_t len);
+ void *mmap(void *addr, size_t len, int prot, int flags, int fd, long long offset);
+ int munmap(void *addr, size_t len);
#ifdef __cplusplus
}
static void usage(void)
{
- puts("st-info --flash");
- puts("st-info --sram");
- puts("st-info --descr");
- puts("st-info --pagesize");
- puts("st-info --chipid");
+ puts("st-info --flash");
+ puts("st-info --sram");
+ puts("st-info --descr");
+ puts("st-info --pagesize");
+ puts("st-info --chipid");
}
static int print_data(stlink_t* sl, char** av)
{
- int ret = 0;
- if (strcmp(av[1], "--flash") == 0)
- printf("0x%zx\n", sl->flash_size);
- else if (strcmp(av[1], "--sram") == 0)
- printf("0x%zx\n", sl->sram_size);
- else if (strcmp(av[1], "--pagesize") == 0)
- printf("0x%zx\n", sl->flash_pgsz);
- else if (strcmp(av[1], "--chipid") == 0)
- printf("0x%.4x\n", sl->chip_id);
- else if (strcmp(av[1], "--descr")==0) {
- const chip_params_t *params = NULL;
- for (size_t i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
- if(devices[i].chip_id == sl->chip_id) {
- params = &devices[i];
- break;
- }
- }
- if (params == NULL) {
- return -1;
- }
- printf("%s\n", params->description);
- }
- return ret;
-}
+ int ret = 0;
+ if (strcmp(av[1], "--flash") == 0)
+ printf("0x%zx\n", sl->flash_size);
+ else if (strcmp(av[1], "--sram") == 0)
+ printf("0x%zx\n", sl->sram_size);
+ else if (strcmp(av[1], "--pagesize") == 0)
+ printf("0x%zx\n", sl->flash_pgsz);
+ else if (strcmp(av[1], "--chipid") == 0)
+ printf("0x%.4x\n", sl->chip_id);
+ else if (strcmp(av[1], "--descr")==0) {
+ const chip_params_t *params = NULL;
+ for (size_t i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
+ if(devices[i].chip_id == sl->chip_id) {
+ params = &devices[i];
+ break;
+ }
+ }
+ if (params == NULL) {
+ return -1;
+ }
+ printf("%s\n", params->description);
+ }
+ return ret;
+}
-stlink_t* open_sl(void)
+stlink_t* open_sl(void)
{
- stlink_t* sl;
- sl = stlink_v1_open(0, 1);
- if (sl == NULL)
- sl = stlink_open_usb(0, 1);
- return sl;
+ stlink_t* sl;
+ sl = stlink_v1_open(0, 1);
+ if (sl == NULL)
+ sl = stlink_open_usb(0, 1);
+ return sl;
}
int main(int ac, char** av)
{
- stlink_t* sl = NULL;
- int err = -1;
- if (ac < 2) {
- usage();
- return -1;
- }
+ 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);
- 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);
- if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
- stlink_enter_swd_mode(sl);
+ err = print_data(sl, av);
- err = print_data(sl, av);
-
- if (sl != NULL)
- {
- stlink_exit_debug_mode(sl);
- stlink_close(sl);
- }
+ if (sl != NULL)
+ {
+ stlink_exit_debug_mode(sl);
+ stlink_close(sl);
+ }
- return err;
+ return err;
}
#define STLINKY_MAGIC 0xDEADF00D
-#define READ_UINT32_LE(buf) ((uint32_t) ( buf[0] \
- | buf[1] << 8 \
- | buf[2] << 16 \
- | buf[3] << 24))
+#define READ_UINT32_LE(buf) ((uint32_t) ( buf[0] \
+ | buf[1] << 8 \
+ | buf[2] << 16 \
+ | buf[3] << 24))
static stlink_t* sl;
sigset_t sig_mask;
struct stlinky {
- stlink_t *sl;
- uint32_t off;
- size_t bufsize;
+ stlink_t *sl;
+ uint32_t off;
+ size_t bufsize;
};
void nonblock(int state);
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);
+ 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);
}
void sig_init() {
- sigemptyset(&sig_mask);
- sigaddset(&sig_mask, SIGINT);
- sigaddset(&sig_mask, SIGTERM);
- signal(SIGINT, &cleanup);
- signal(SIGTERM, &cleanup);
- sigprocmask(SIG_BLOCK, &sig_mask, NULL);
+ sigemptyset(&sig_mask);
+ sigaddset(&sig_mask, SIGINT);
+ sigaddset(&sig_mask, SIGTERM);
+ signal(SIGINT, &cleanup);
+ signal(SIGTERM, &cleanup);
+ sigprocmask(SIG_BLOCK, &sig_mask, NULL);
}
void sig_process() {
- sigset_t pending;
- sigpending(&pending);
- if (sigismember(&pending, SIGINT) || sigismember(&pending, SIGTERM)) {
- sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
- sigsuspend(&pending);
- sigprocmask(SIG_BLOCK, &sig_mask, NULL);
- }
+ sigset_t pending;
+ sigpending(&pending);
+ if (sigismember(&pending, SIGINT) || sigismember(&pending, SIGTERM)) {
+ sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
+ sigsuspend(&pending);
+ sigprocmask(SIG_BLOCK, &sig_mask, NULL);
+ }
}
/* Detects stlinky in RAM, returns handler */
struct stlinky* stlinky_detect(stlink_t* sl)
{
- static const uint32_t sram_base = 0x20000000;
- struct stlinky* st = malloc(sizeof(struct stlinky));
- int multiple=0;
- st->sl = sl;
- printf("sram: 0x%x bytes @ 0x%zx\n", sl->sram_base, sl->sram_size);
- uint32_t off;
- for (off = 0; off < sl->sram_size; off += 4) {
- if (off % 1024 == 0) sig_process();
- stlink_read_mem32(sl, sram_base + off, 4);
- if (STLINKY_MAGIC == READ_UINT32_LE(sl->q_buf))
- {
- if (multiple > 0) printf("WARNING: another ");
- printf("stlinky detected at 0x%x\n", sram_base + off);
- st->off = sram_base + off;
- stlink_read_mem32(sl, st->off + 4, 4);
- st->bufsize = (size_t) *(unsigned char*) sl->q_buf;
- printf("stlinky buffer size 0x%zu \n", st->bufsize);
- multiple++;
- }
- }
- if (multiple > 0) {
- if (multiple > 1) {
- printf("Using last stlinky structure detected\n");
- }
- return st;
- }
- return NULL;
+ static const uint32_t sram_base = 0x20000000;
+ struct stlinky* st = malloc(sizeof(struct stlinky));
+ int multiple=0;
+ st->sl = sl;
+ printf("sram: 0x%x bytes @ 0x%zx\n", sl->sram_base, sl->sram_size);
+ uint32_t off;
+ for (off = 0; off < sl->sram_size; off += 4) {
+ if (off % 1024 == 0) sig_process();
+ stlink_read_mem32(sl, sram_base + off, 4);
+ if (STLINKY_MAGIC == READ_UINT32_LE(sl->q_buf))
+ {
+ if (multiple > 0) printf("WARNING: another ");
+ printf("stlinky detected at 0x%x\n", sram_base + off);
+ st->off = sram_base + off;
+ stlink_read_mem32(sl, st->off + 4, 4);
+ st->bufsize = (size_t) *(unsigned char*) sl->q_buf;
+ printf("stlinky buffer size 0x%zu \n", st->bufsize);
+ multiple++;
+ }
+ }
+ if (multiple > 0) {
+ if (multiple > 1) {
+ printf("Using last stlinky structure detected\n");
+ }
+ return st;
+ }
+ return NULL;
}
int stlinky_canrx(struct stlinky *st)
{
- stlink_read_mem32(st->sl, st->off+4, 4);
- unsigned char tx = (unsigned char) st->sl->q_buf[1];
- return (int) tx;
+ stlink_read_mem32(st->sl, st->off+4, 4);
+ unsigned char tx = (unsigned char) st->sl->q_buf[1];
+ return (int) tx;
}
size_t stlinky_rx(struct stlinky *st, char* buffer)
{
- unsigned char tx = 0;
- while(tx == 0) {
- stlink_read_mem32(st->sl, st->off+4, 4);
- tx = (unsigned char) st->sl->q_buf[1];
- }
- size_t rs = tx + (4 - (tx % 4)); /* voodoo */
- stlink_read_mem32(st->sl, st->off+8, rs);
- memcpy(buffer, st->sl->q_buf, (size_t) tx);
- *st->sl->q_buf=0x0;
- stlink_write_mem8(st->sl, st->off+5, 1);
- return (size_t) tx;
+ unsigned char tx = 0;
+ while(tx == 0) {
+ stlink_read_mem32(st->sl, st->off+4, 4);
+ tx = (unsigned char) st->sl->q_buf[1];
+ }
+ size_t rs = tx + (4 - (tx % 4)); /* voodoo */
+ stlink_read_mem32(st->sl, st->off+8, rs);
+ memcpy(buffer, st->sl->q_buf, (size_t) tx);
+ *st->sl->q_buf=0x0;
+ stlink_write_mem8(st->sl, st->off+5, 1);
+ return (size_t) tx;
}
size_t stlinky_tx(struct stlinky *st, char* buffer, size_t sz)
{
- unsigned char rx = 1;
- while(rx != 0) {
- stlink_read_mem32(st->sl, st->off+4, 4);
- rx = (unsigned char) st->sl->q_buf[2];
- }
- memcpy(st->sl->q_buf, buffer, sz);
- size_t rs = sz + (4 - (sz % 4)); /* voodoo */
- stlink_write_mem32(st->sl, st->off+8+st->bufsize, rs);
- *st->sl->q_buf=(unsigned char) sz;
- stlink_write_mem8(st->sl, st->off+6, 1);
- return (size_t) rx;
+ unsigned char rx = 1;
+ while(rx != 0) {
+ stlink_read_mem32(st->sl, st->off+4, 4);
+ rx = (unsigned char) st->sl->q_buf[2];
+ }
+ memcpy(st->sl->q_buf, buffer, sz);
+ size_t rs = sz + (4 - (sz % 4)); /* voodoo */
+ stlink_write_mem32(st->sl, st->off+8+st->bufsize, rs);
+ *st->sl->q_buf=(unsigned char) sz;
+ stlink_write_mem8(st->sl, st->off+6, 1);
+ return (size_t) rx;
}
int kbhit()
{
- struct timeval tv;
- fd_set fds;
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- FD_ZERO(&fds);
- FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
- select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
- return FD_ISSET(STDIN_FILENO, &fds);
+ struct timeval tv;
+ fd_set fds;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
+ select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
+ return FD_ISSET(STDIN_FILENO, &fds);
}
void nonblock(int state)
{
- struct termios ttystate;
-
- //get the terminal state
- tcgetattr(STDIN_FILENO, &ttystate);
-
- if (state==1)
- {
- //turn off canonical mode
- ttystate.c_lflag &= ~ICANON;
- ttystate.c_lflag &= ~ECHO;
- //minimum of number input read.
- ttystate.c_cc[VMIN] = 1;
- }
- else if (state==0)
- {
- //turn on canonical mode
- ttystate.c_lflag |= ICANON | ECHO;
- }
- //set the terminal attributes.
- tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
+ struct termios ttystate;
+
+ //get the terminal state
+ tcgetattr(STDIN_FILENO, &ttystate);
+
+ if (state==1)
+ {
+ //turn off canonical mode
+ ttystate.c_lflag &= ~ICANON;
+ ttystate.c_lflag &= ~ECHO;
+ //minimum of number input read.
+ ttystate.c_cc[VMIN] = 1;
+ }
+ else if (state==0)
+ {
+ //turn on canonical mode
+ ttystate.c_lflag |= ICANON | ECHO;
+ }
+ //set the terminal attributes.
+ tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}
int main(int ac, char** av) {
- struct stlinky *st=NULL;
-
- sig_init();
-
- 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);
-
- if(ac == 1){
- st = stlinky_detect(sl);
- }else if(ac == 2){
- st = malloc(sizeof(struct stlinky));
- st->sl = sl;
- st->off = (int)strtol(av[1], NULL, 16);
- printf("using stlinky at 0x%x\n", st->off);
- stlink_read_mem32(sl, st->off + 4, 4);
- st->bufsize = (size_t) *(unsigned char*) sl->q_buf;
- printf("stlinky buffer size 0x%zu \n", st->bufsize);
- }else{
- cleanup(0);
- }
- if (st == NULL)
- {
- printf("stlinky magic not found in sram :(\n");
- cleanup(0);
- }
- 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);
- printf("Entering interactive terminal. CTRL+C to exit\n\n\n");
- while(1) {
- sig_process();
- 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);
- }
- }
- }
- return 0;
+ struct stlinky *st=NULL;
+
+ sig_init();
+
+ 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);
+
+ if(ac == 1){
+ st = stlinky_detect(sl);
+ }else if(ac == 2){
+ st = malloc(sizeof(struct stlinky));
+ st->sl = sl;
+ st->off = (int)strtol(av[1], NULL, 16);
+ printf("using stlinky at 0x%x\n", st->off);
+ stlink_read_mem32(sl, st->off + 4, 4);
+ st->bufsize = (size_t) *(unsigned char*) sl->q_buf;
+ printf("stlinky buffer size 0x%zu \n", st->bufsize);
+ }else{
+ cleanup(0);
+ }
+ if (st == NULL)
+ {
+ printf("stlinky magic not found in sram :(\n");
+ cleanup(0);
+ }
+ 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);
+ printf("Entering interactive terminal. CTRL+C to exit\n\n\n");
+ while(1) {
+ sig_process();
+ 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);
+ }
+ }
+ }
+ return 0;
}
static inline uint32_t read_flash_cr(stlink_t *sl) {
uint32_t res;
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) ||(sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
res = stlink_read_debug32(sl, FLASH_F4_CR);
else
res = stlink_read_debug32(sl, FLASH_CR);
static inline unsigned int is_flash_locked(stlink_t *sl) {
/* return non zero for true */
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
return read_flash_cr(sl) & (1 << FLASH_F4_CR_LOCK);
else
return read_flash_cr(sl) & (1 << FLASH_CR_LOCK);
2 key values are written to the FLASH_KEYR register.
an invalid sequence results in a definitive lock of
the FPEC block until next reset.
- */
+ */
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
- stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY1);
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
+ stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY1);
stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY2);
} else {
- stlink_write_debug32(sl, FLASH_KEYR, FLASH_KEY1);
+ stlink_write_debug32(sl, FLASH_KEYR, FLASH_KEY1);
stlink_write_debug32(sl, FLASH_KEYR, FLASH_KEY2);
}
static void lock_flash(stlink_t *sl) {
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
- const uint32_t n = read_flash_cr(sl) | (1 << FLASH_F4_CR_LOCK);
- stlink_write_debug32(sl, FLASH_F4_CR, n);
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
+ const uint32_t n = read_flash_cr(sl) | (1 << FLASH_F4_CR_LOCK);
+ stlink_write_debug32(sl, FLASH_F4_CR, n);
} else {
/* write to 1 only. reset by hw at unlock sequence */
const uint32_t n = read_flash_cr(sl) | (1 << FLASH_CR_LOCK);
static void set_flash_cr_pg(stlink_t *sl) {
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
- uint32_t x = read_flash_cr(sl);
- x |= (1 << FLASH_CR_PG);
- stlink_write_debug32(sl, FLASH_F4_CR, x);
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
+ uint32_t x = read_flash_cr(sl);
+ x |= (1 << FLASH_CR_PG);
+ stlink_write_debug32(sl, FLASH_F4_CR, x);
} else {
const uint32_t n = 1 << FLASH_CR_PG;
stlink_write_debug32(sl, FLASH_CR, n);
static void __attribute__((unused)) clear_flash_cr_pg(stlink_t *sl) {
const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG);
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
- stlink_write_debug32(sl, FLASH_F4_CR, n);
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
+ stlink_write_debug32(sl, FLASH_F4_CR, n);
else
stlink_write_debug32(sl, FLASH_CR, n);
}
static void set_flash_cr_mer(stlink_t *sl) {
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
stlink_write_debug32(sl, FLASH_F4_CR,
- stlink_read_debug32(sl, FLASH_F4_CR) | (1 << FLASH_CR_MER));
+ stlink_read_debug32(sl, FLASH_F4_CR) | (1 << FLASH_CR_MER));
else
stlink_write_debug32(sl, FLASH_CR,
- stlink_read_debug32(sl, FLASH_CR) | (1 << FLASH_CR_MER));
+ stlink_read_debug32(sl, FLASH_CR) | (1 << FLASH_CR_MER));
}
static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) {
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
stlink_write_debug32(sl, FLASH_F4_CR,
- stlink_read_debug32(sl, FLASH_F4_CR) & ~(1 << FLASH_CR_MER));
+ stlink_read_debug32(sl, FLASH_F4_CR) & ~(1 << FLASH_CR_MER));
else
stlink_write_debug32(sl, FLASH_CR,
- stlink_read_debug32(sl, FLASH_CR) & ~(1 << FLASH_CR_MER));
+ stlink_read_debug32(sl, FLASH_CR) & ~(1 << FLASH_CR_MER));
}
static void set_flash_cr_strt(stlink_t *sl) {
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
uint32_t x = read_flash_cr(sl);
x |= (1 << FLASH_F4_CR_STRT);
stlink_write_debug32(sl, FLASH_F4_CR, x);
} else {
stlink_write_debug32(sl, FLASH_CR,
- stlink_read_debug32(sl, FLASH_CR) | (1 << FLASH_CR_STRT) );
+ stlink_read_debug32(sl, FLASH_CR) | (1 << FLASH_CR_STRT) );
}
}
static inline uint32_t read_flash_sr(stlink_t *sl) {
uint32_t res;
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
res = stlink_read_debug32(sl, FLASH_F4_SR);
else
res = stlink_read_debug32(sl, FLASH_SR);
static inline unsigned int is_flash_busy(stlink_t *sl) {
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
return read_flash_sr(sl) & (1 << FLASH_F4_SR_BSY);
else
return read_flash_sr(sl) & (1 << FLASH_SR_BSY);
flash_size = flash_size & 0xffff;
if ((sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS) && ( flash_size == 0 )) {
- sl->flash_size = 128 * 1024;
+ sl->flash_size = 128 * 1024;
} else if ((sl->chip_id & 0xFFF) == STM32_CHIPID_L1_HIGH) {
// 0 is 384k and 1 is 256k
if ( flash_size == 0 ) {
ILOG("Device connected is: %s, id %#x\n", params->description, chip_id);
// TODO make note of variable page size here.....
ILOG("SRAM size: %#x bytes (%d KiB), Flash: %#x bytes (%d KiB) in pages of %zd bytes\n",
- sl->sram_size, sl->sram_size / 1024, sl->flash_size, sl->flash_size / 1024,
- sl->flash_pgsz);
+ sl->sram_size, sl->sram_size / 1024, sl->flash_size, sl->flash_size / 1024,
+ sl->flash_pgsz);
return 0;
}
DLOG("*** reading target voltage\n");
if (sl->backend->target_voltage != NULL) {
voltage = sl->backend->target_voltage(sl);
- if (voltage != -1) {
+ if (voltage != -1) {
DLOG("target voltage = %ldmV\n", voltage);
- } else {
+ } else {
DLOG("error reading target voltage\n");
- }
+ }
} else {
DLOG("reading voltage not supported by backend\n");
}
int stlink_current_mode(stlink_t *sl) {
int mode = sl->backend->current_mode(sl);
switch (mode) {
- case STLINK_DEV_DFU_MODE:
- DLOG("stlink current mode: dfu\n");
- return mode;
- case STLINK_DEV_DEBUG_MODE:
- DLOG("stlink current mode: debug (jtag or swd)\n");
- return mode;
- case STLINK_DEV_MASS_MODE:
- DLOG("stlink current mode: mass\n");
- return mode;
+ case STLINK_DEV_DFU_MODE:
+ DLOG("stlink current mode: dfu\n");
+ return mode;
+ case STLINK_DEV_DEBUG_MODE:
+ DLOG("stlink current mode: debug (jtag or swd)\n");
+ return mode;
+ case STLINK_DEV_MASS_MODE:
+ DLOG("stlink current mode: mass\n");
+ return mode;
}
DLOG("stlink mode: unknown!\n");
return STLINK_DEV_UNKNOWN_MODE;
return;
switch (sl->q_buf[0]) {
- case STLINK_CORE_RUNNING:
- sl->core_stat = STLINK_CORE_RUNNING;
- DLOG(" core status: running\n");
- return;
- case STLINK_CORE_HALTED:
- sl->core_stat = STLINK_CORE_HALTED;
- DLOG(" core status: halted\n");
- return;
- default:
- sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
- fprintf(stderr, " core status: unknown\n");
+ case STLINK_CORE_RUNNING:
+ sl->core_stat = STLINK_CORE_RUNNING;
+ DLOG(" core status: running\n");
+ return;
+ case STLINK_CORE_HALTED:
+ sl->core_stat = STLINK_CORE_HALTED;
+ DLOG(" core status: halted\n");
+ return;
+ default:
+ sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
+ fprintf(stderr, " core status: unknown\n");
}
}
for (int i = 0; i < sl->q_len; i++) {
if (i % 16 == 0) {
/*
- if (sl->q_data_dir == Q_DATA_OUT)
- fprintf(stdout, "\n<- 0x%08x ", sl->q_addr + i);
- else
- fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i);
- */
+ if (sl->q_data_dir == Q_DATA_OUT)
+ fprintf(stdout, "\n<- 0x%08x ", sl->q_addr + i);
+ else
+ fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i);
+ */
}
fprintf(stdout, " %02x", (unsigned int) sl->q_buf[i]);
}
size_t off;
int num_empty = 0;
unsigned char erased_pattern = (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
- || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) ? 0:0xff;
+ || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) ? 0:0xff;
const int fd = open(path, O_RDWR | O_TRUNC | O_CREAT, 00700);
if (fd == -1) {
}
if (size <1)
- size = sl->flash_size;
+ size = sl->flash_size;
if (size > sl->flash_size)
- size = sl->flash_size;
+ size = sl->flash_size;
/* do the copy by 1k blocks */
for (off = 0; off < size; off += 1024) {
size_t read_size = 1024;
- size_t rounded_size;
- size_t index;
+ size_t rounded_size;
+ size_t index;
if ((off + read_size) > size)
- read_size = size - off;
+ read_size = size - off;
/* round size if needed */
- rounded_size = read_size;
+ rounded_size = read_size;
if (rounded_size & 3)
- rounded_size = (rounded_size + 4) & ~(3);
+ rounded_size = (rounded_size + 4) & ~(3);
stlink_read_mem32(sl, addr + off, rounded_size);
- for(index = 0; index < read_size; index ++) {
- if (sl->q_buf[index] == erased_pattern)
- num_empty ++;
- else
- num_empty = 0;
- }
+ for(index = 0; index < read_size; index ++) {
+ if (sl->q_buf[index] == erased_pattern)
+ num_empty ++;
+ else
+ num_empty = 0;
+ }
if (write(fd, sl->q_buf, read_size) != (ssize_t) read_size) {
fprintf(stderr, "write() != read_size\n");
goto on_error;
}
uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){
- if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
- uint32_t sector=calculate_F4_sectornum(flashaddr);
- if (sector<4) sl->flash_pgsz=0x4000;
- else if(sector<5) sl->flash_pgsz=0x10000;
- else sl->flash_pgsz=0x20000;
- }
- return (sl->flash_pgsz);
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
+ uint32_t sector=calculate_F4_sectornum(flashaddr);
+ if (sector<4) sl->flash_pgsz=0x4000;
+ else if(sector<5) sl->flash_pgsz=0x10000;
+ else sl->flash_pgsz=0x20000;
+ }
+ return (sl->flash_pgsz);
}
/**
int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
{
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
- /* wait for ongoing op to finish */
- wait_flash_busy(sl);
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
+ /* wait for ongoing op to finish */
+ wait_flash_busy(sl);
- /* unlock if locked */
- unlock_flash_if(sl);
+ /* unlock if locked */
+ unlock_flash_if(sl);
- /* select the page to erase */
- // calculate the actual page from the address
- uint32_t sector=calculate_F4_sectornum(flashaddr);
+ /* select the page to erase */
+ // calculate the actual page from the address
+ uint32_t sector=calculate_F4_sectornum(flashaddr);
- fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x\n", sector, stlink_calculate_pagesize(sl, flashaddr));
- write_flash_cr_snb(sl, sector);
+ fprintf(stderr, "EraseFlash - Sector:0x%x Size:0x%x\n", sector, stlink_calculate_pagesize(sl, flashaddr));
+ write_flash_cr_snb(sl, sector);
- /* start erase operation */
- set_flash_cr_strt(sl);
+ /* start erase operation */
+ set_flash_cr_strt(sl);
- /* wait for completion */
- wait_flash_busy(sl);
+ /* wait for completion */
+ wait_flash_busy(sl);
- /* relock the flash */
- //todo: fails to program if this is in
- lock_flash(sl);
+ /* relock the flash */
+ //todo: fails to program if this is in
+ lock_flash(sl);
#if DEBUG_FLASH
- fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl));
+ fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl));
#endif
- } else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
- || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) {
+ } else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
+ || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) {
- uint32_t val;
+ uint32_t val;
- /* check if the locks are set */
- val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if((val & (1<<0))||(val & (1<<1))) {
- /* disable pecr protection */
- stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x89abcdef);
- stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x02030405);
-
- /* check pecr.pelock is cleared */
+ /* check if the locks are set */
val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if (val & (1 << 0)) {
- WLOG("pecr.pelock not clear (%#x)\n", val);
- return -1;
- }
+ if((val & (1<<0))||(val & (1<<1))) {
+ /* disable pecr protection */
+ stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x89abcdef);
+ stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x02030405);
- /* unlock program memory */
- stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x8c9daebf);
- stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x13141516);
+ /* check pecr.pelock is cleared */
+ val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+ if (val & (1 << 0)) {
+ WLOG("pecr.pelock not clear (%#x)\n", val);
+ return -1;
+ }
- /* check pecr.prglock is cleared */
- val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if (val & (1 << 1)) {
- WLOG("pecr.prglock not clear (%#x)\n", val);
- return -1;
+ /* unlock program memory */
+ stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x8c9daebf);
+ stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x13141516);
+
+ /* check pecr.prglock is cleared */
+ val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+ if (val & (1 << 1)) {
+ WLOG("pecr.prglock not clear (%#x)\n", val);
+ return -1;
+ }
}
- }
- /* unused: unlock the option byte block */
+ /* unused: unlock the option byte block */
#if 0
- stlink_write_debug32(sl, STM32L_FLASH_OPTKEYR, 0xfbead9c8);
- stlink_write_debug32(sl, STM32L_FLASH_OPTKEYR, 0x24252627);
+ stlink_write_debug32(sl, STM32L_FLASH_OPTKEYR, 0xfbead9c8);
+ stlink_write_debug32(sl, STM32L_FLASH_OPTKEYR, 0x24252627);
- /* check pecr.optlock is cleared */
- val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if (val & (1 << 2)) {
- fprintf(stderr, "pecr.prglock not clear\n");
- return -1;
- }
+ /* check pecr.optlock is cleared */
+ val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+ if (val & (1 << 2)) {
+ fprintf(stderr, "pecr.prglock not clear\n");
+ return -1;
+ }
#endif
- /* set pecr.{erase,prog} */
- val |= (1 << 9) | (1 << 3);
- stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+ /* set pecr.{erase,prog} */
+ val |= (1 << 9) | (1 << 3);
+ stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
#if 0 /* fix_to_be_confirmed */
- /* wait for sr.busy to be cleared
- MP: Test shows that busy bit is not set here. Perhaps, PM0062 is
- wrong and we do not need to wait here for clearing the busy bit.
- TEXANE: ok, if experience says so and it works for you, we comment
- it. If someone has a problem, please drop an email.
- */
- while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0)
- ;
+ /* wait for sr.busy to be cleared
+ * MP: Test shows that busy bit is not set here. Perhaps, PM0062 is
+ * wrong and we do not need to wait here for clearing the busy bit.
+ * TEXANE: ok, if experience says so and it works for you, we comment
+ * it. If someone has a problem, please drop an email.
+ */
+ while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0)
+ ;
#endif /* fix_to_be_confirmed */
- /* write 0 to the first word of the page to be erased */
- stlink_write_debug32(sl, flashaddr, 0);
-
- /* MP: It is better to wait for clearing the busy bit after issuing
- page erase command, even though PM0062 recommends to wait before it.
- Test shows that a few iterations is performed in the following loop
- before busy bit is cleared.*/
- while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0)
- ;
-
- /* reset lock bits */
- val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
- | (1 << 0) | (1 << 1) | (1 << 2);
- stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
- } else if (sl->core_id == STM32VL_CORE_ID
- || sl->core_id == STM32F0_CORE_ID
- || sl->chip_id == STM32_CHIPID_F3
- || sl->chip_id == STM32_CHIPID_F37x) {
- /* wait for ongoing op to finish */
- wait_flash_busy(sl);
+ /* write 0 to the first word of the page to be erased */
+ stlink_write_debug32(sl, flashaddr, 0);
+
+ /* MP: It is better to wait for clearing the busy bit after issuing
+ page erase command, even though PM0062 recommends to wait before it.
+ Test shows that a few iterations is performed in the following loop
+ before busy bit is cleared.*/
+ while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0)
+ ;
+
+ /* reset lock bits */
+ val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
+ | (1 << 0) | (1 << 1) | (1 << 2);
+ stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+ } else if (sl->core_id == STM32VL_CORE_ID
+ || sl->core_id == STM32F0_CORE_ID
+ || sl->chip_id == STM32_CHIPID_F3
+ || sl->chip_id == STM32_CHIPID_F37x) {
+ /* wait for ongoing op to finish */
+ wait_flash_busy(sl);
- /* unlock if locked */
- unlock_flash_if(sl);
+ /* unlock if locked */
+ unlock_flash_if(sl);
- /* set the page erase bit */
- set_flash_cr_per(sl);
+ /* set the page erase bit */
+ set_flash_cr_per(sl);
- /* select the page to erase */
- write_flash_ar(sl, flashaddr);
+ /* select the page to erase */
+ write_flash_ar(sl, flashaddr);
- /* start erase operation, reset by hw with bsy bit */
- set_flash_cr_strt(sl);
+ /* start erase operation, reset by hw with bsy bit */
+ set_flash_cr_strt(sl);
- /* wait for completion */
- wait_flash_busy(sl);
+ /* wait for completion */
+ wait_flash_busy(sl);
- /* relock the flash */
- lock_flash(sl);
- } else {
- WLOG("unknown coreid %x, page erase failed\n", sl->core_id);
- return -1;
- }
+ /* relock the flash */
+ lock_flash(sl);
+ } else {
+ WLOG("unknown coreid %x, page erase failed\n", sl->core_id);
+ return -1;
+ }
- /* todo: verify the erased page */
+ /* todo: verify the erased page */
- return 0;
+ return 0;
}
int stlink_erase_flash_mass(stlink_t *sl) {
if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
- || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) {
+ || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) {
/* erase each page */
int i = 0, num_pages = sl->flash_size/sl->flash_pgsz;
for (i = 0; i < num_pages; i++) {
0x0A, 0x4C, // ldr r4, STM32_FLASH_BASE
0x01, 0x25, // mov r5, #1 /* FLASH_CR_PG, FLASH_SR_BUSY */
0x04, 0x26, // mov r6, #4 /* PGERR */
- // write_half_word:
+ // write_half_word:
0x23, 0x69, // ldr r3, [r4, #16] /* FLASH->CR */
0x2B, 0x43, // orr r3, r5
0x23, 0x61, // str r3, [r4, #16] /* FLASH->CR |= FLASH_CR_PG */
0x03, 0x88, // ldrh r3, [r0] /* r3 = *sram */
0x0B, 0x80, // strh r3, [r1] /* *flash = r3 */
- // busy:
+ // busy:
0xE3, 0x68, // ldr r3, [r4, #12] /* FLASH->SR */
0x2B, 0x42, // tst r3, r5 /* FLASH_SR_BUSY */
0xFC, 0xD0, // beq busy
0x01, 0x3A, // sub r2, r2, #0x01 /* count-- */
0x00, 0x2A, // cmp r2, #0
0xF0, 0xD1, // bne write_half_word
- // exit:
+ // exit:
0x23, 0x69, // ldr r3, [r4, #16] /* FLASH->CR */
0xAB, 0x43, // bic r3, r5
0x23, 0x61, // str r3, [r4, #16] /* FLASH->CR &= ~FLASH_CR_PG */
r1, input, source addr
r2, input, word count
r3, output, word count
- */
+ */
0x00, 0x23,
0x04, 0xe0,
size_t loader_size;
if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
- || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) { /* stm32l */
+ || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) { /* stm32l */
loader_code = loader_code_stm32l;
loader_size = sizeof(loader_code_stm32l);
} else if (sl->core_id == STM32VL_CORE_ID || sl->chip_id == STM32_CHIPID_F3 || sl->chip_id == STM32_CHIPID_F37x) {
loader_code = loader_code_stm32vl;
loader_size = sizeof(loader_code_stm32vl);
} else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4 || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD){
+ sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD){
loader_code = loader_code_stm32f4;
loader_size = sizeof(loader_code_stm32f4);
} else if (sl->chip_id == STM32_CHIPID_F0 || sl->chip_id == STM32_CHIPID_F0_CAN || sl->chip_id == STM32_CHIPID_F0_SMALL) {
size_t off;
flash_loader_t fl;
ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n",
- len, len, addr, addr);
+ len, len, addr, addr);
/* check addr range is inside the flash */
stlink_calculate_pagesize(sl, addr);
if (addr < sl->flash_base) {
return -1;
}
fprintf(stdout,"\rFlash page at addr: 0x%08lx erased",
- (unsigned long)addr + off);
+ (unsigned long)addr + off);
fflush(stdout);
page_count++;
}
fprintf(stdout,"\n");
ILOG("Finished erasing %d pages of %d (%#x) bytes\n",
- page_count, sl->flash_pgsz, sl->flash_pgsz);
+ page_count, sl->flash_pgsz, sl->flash_pgsz);
if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
- /* todo: check write operation */
+ (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
+ /* todo: check write operation */
ILOG("Starting Flash write for F2/F4\n");
/* flash loader initialization */
return -1;
}
- /* First unlock the cr */
- unlock_flash_if(sl);
+ /* First unlock the cr */
+ unlock_flash_if(sl);
- /* TODO: Check that Voltage range is 2.7 - 3.6 V */
- /* set parallelisim to 32 bit*/
- write_flash_cr_psiz(sl, 2);
+ /* TODO: Check that Voltage range is 2.7 - 3.6 V */
+ /* set parallelisim to 32 bit*/
+ write_flash_cr_psiz(sl, 2);
- /* set programming mode */
- set_flash_cr_pg(sl);
+ /* set programming mode */
+ set_flash_cr_pg(sl);
for(off = 0; off < len;) {
size_t size = len - off > 0x8000 ? 0x8000 : len - off;
#if 0
#define PROGRESS_CHUNK_SIZE 0x1000
- /* write a word in program memory */
- for (off = 0; off < len; off += sizeof(uint32_t)) {
+ /* write a word in program memory */
+ for (off = 0; off < len; off += sizeof(uint32_t)) {
uint32_t data;
if (sl->verbose >= 1) {
if ((off & (PROGRESS_CHUNK_SIZE - 1)) == 0) {
stlink_write_debug32(sl, addr + off, data);
/* wait for sr.busy to be cleared */
- wait_flash_busy(sl);
+ wait_flash_busy(sl);
- }
+ }
#endif
- /* Relock flash */
- lock_flash(sl);
+ /* Relock flash */
+ lock_flash(sl);
#if 0 /* todo: debug mode */
- fprintf(stdout, "Final CR:0x%x\n", read_flash_cr(sl));
+ fprintf(stdout, "Final CR:0x%x\n", read_flash_cr(sl));
#endif
} //STM32F4END
else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
- || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
- /* use fast word write. todo: half page. */
- uint32_t val;
+ || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
+ /* use fast word write. todo: half page. */
+ uint32_t val;
#if 0 /* todo: check write operation */
- uint32_t nwrites = sl->flash_pgsz;
+ uint32_t nwrites = sl->flash_pgsz;
- redo_write:
+redo_write:
#endif /* todo: check write operation */
- /* disable pecr protection */
- stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x89abcdef);
- stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x02030405);
-
- /* check pecr.pelock is cleared */
- val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if (val & (1 << 0)) {
- fprintf(stderr, "pecr.pelock not clear\n");
- return -1;
- }
-
- /* unlock program memory */
- stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x8c9daebf);
- stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x13141516);
-
- /* check pecr.prglock is cleared */
- val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if (val & (1 << 1)) {
- fprintf(stderr, "pecr.prglock not clear\n");
- return -1;
- }
- off = 0;
+ /* disable pecr protection */
+ stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x89abcdef);
+ stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x02030405);
+
+ /* check pecr.pelock is cleared */
+ val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+ if (val & (1 << 0)) {
+ fprintf(stderr, "pecr.pelock not clear\n");
+ return -1;
+ }
+
+ /* unlock program memory */
+ stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x8c9daebf);
+ stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x13141516);
+
+ /* check pecr.prglock is cleared */
+ val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+ if (val & (1 << 1)) {
+ fprintf(stderr, "pecr.prglock not clear\n");
+ return -1;
+ }
+ off = 0;
if (len > L1_WRITE_BLOCK_SIZE) {
if (stm32l1_write_half_pages(sl, addr, base, len/L1_WRITE_BLOCK_SIZE) == -1) {
- /* This may happen on a blank device! */
+ /* This may happen on a blank device! */
WLOG("\nwrite_half_pages failed == -1\n");
- } else {
- off = (len /L1_WRITE_BLOCK_SIZE)*L1_WRITE_BLOCK_SIZE;
- }
- }
+ } else {
+ off = (len /L1_WRITE_BLOCK_SIZE)*L1_WRITE_BLOCK_SIZE;
+ }
+ }
- /* write remainingword in program memory */
- for ( ; off < len; off += sizeof(uint32_t)) {
+ /* write remainingword in program memory */
+ for ( ; off < len; off += sizeof(uint32_t)) {
uint32_t data;
if (off > 254)
fprintf(stdout, "\r");
++nwrites;
#endif /* todo: check redo write operation */
- }
+ }
fprintf(stdout, "\n");
- /* reset lock bits */
- val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
- | (1 << 0) | (1 << 1) | (1 << 2);
- stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+ /* reset lock bits */
+ val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
+ | (1 << 0) | (1 << 1) | (1 << 2);
+ stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
} else if (sl->core_id == STM32VL_CORE_ID || sl->core_id == STM32F0_CORE_ID || sl->chip_id == STM32_CHIPID_F3 || sl->chip_id == STM32_CHIPID_F37x) {
ILOG("Starting Flash write for VL/F0 core id\n");
/* flash loader initialization */
if (sl->verbose >= 1) {
/* show progress. writing procedure is slow
and previous errors are misleading */
- fprintf(stdout, "\r%3u/%lu pages written", write_block_count++, (unsigned long)len/sl->flash_pgsz);
+ fprintf(stdout, "\r%3u/%lu pages written", write_block_count++, (unsigned long)len/sl->flash_pgsz);
fflush(stdout);
}
}
int err;
unsigned int num_empty = 0, index;
unsigned char erased_pattern =(sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
- || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE )?0:0xff;
+ || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE )?0:0xff;
mapped_file_t mf = MAPPED_FILE_INITIALIZER;
if (map_file(&mf, path) == -1) {
ELOG("map_file() == -1\n");
return -1;
}
for(index = 0; index < mf.len; index ++) {
- if (mf.base[index] == erased_pattern)
- num_empty ++;
- else
- num_empty = 0;
+ if (mf.base[index] == erased_pattern)
+ num_empty ++;
+ else
+ num_empty = 0;
}
/* Round down to words */
num_empty -= (num_empty & 3);
if(num_empty != 0) {
- ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, erased_pattern);
- mf.len -= num_empty;
+ ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, erased_pattern);
+ mf.len -= num_empty;
}
err = stlink_write_flash(sl, addr, mf.base, mf.len);
/* set stack*/
}
if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
- || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
+ || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
size_t count = size / sizeof(uint32_t);
if (size % sizeof(uint32_t)) ++count;
stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
} else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4 || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD) {
+ sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD) {
size_t count = size / sizeof(uint32_t);
if (size % sizeof(uint32_t)) ++count;
/* check written byte count */
if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
- || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
+ || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
- size_t count = size / sizeof(uint32_t);
- if (size % sizeof(uint32_t)) ++count;
+ size_t count = size / sizeof(uint32_t);
+ if (size % sizeof(uint32_t)) ++count;
- stlink_read_reg(sl, 3, &rr);
- if (rr.r[3] != count) {
- fprintf(stderr, "write error, count == %u\n", rr.r[3]);
- return -1;
- }
+ stlink_read_reg(sl, 3, &rr);
+ if (rr.r[3] != count) {
+ fprintf(stderr, "write error, count == %u\n", rr.r[3]);
+ return -1;
+ }
} else if (sl->core_id == STM32VL_CORE_ID || sl->core_id == STM32F0_CORE_ID || sl->chip_id == STM32_CHIPID_F3 || sl->chip_id == STM32_CHIPID_F37x) {
- stlink_read_reg(sl, 2, &rr);
- if (rr.r[2] != 0) {
- fprintf(stderr, "write error, count == %u\n", rr.r[2]);
- return -1;
- }
+ stlink_read_reg(sl, 2, &rr);
+ if (rr.r[2] != 0) {
+ fprintf(stderr, "write error, count == %u\n", rr.r[2]);
+ return -1;
+ }
} else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4 || (sl->chip_id == STM32_CHIPID_F4_DE) ||
- sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD) {
+ sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD) {
stlink_read_reg(sl, 2, &rr);
if (rr.r[2] != 0) {
} else {
- fprintf(stderr, "unknown coreid 0x%x, can't check written byte count\n", sl->core_id);
- return -1;
+ fprintf(stderr, "unknown coreid 0x%x, can't check written byte count\n", sl->core_id);
+ return -1;
}
*/
#ifndef STLINK_COMMON_H
-#define STLINK_COMMON_H
+#define STLINK_COMMON_H
#ifdef __cplusplus
extern "C" {
#define STLINK_JTAG_DRIVE_NRST 0x3c
#define STLINK_JTAG_DRIVE_NRST 0x3c
-// cortex m3 technical reference manual
+ // cortex m3 technical reference manual
#define CM3_REG_CPUID 0xE000ED00
#define CM3_REG_FP_CTRL 0xE0002000
#define CM3_REG_FP_COMP0 0xE0002008
-/* cortex core ids */
+ /* cortex core ids */
// TODO clean this up...
#define STM32VL_CORE_ID 0x1ba01477
#define STM32L_CORE_ID 0x2ba01477
#define CORE_M3_R2 0x4BA00477
#define CORE_M4_R0 0x2BA01477
-/*
- * Chip IDs are explained in the appropriate programming manual for the
- * DBGMCU_IDCODE register (0xE0042000)
- */
-// stm32 chipids, only lower 12 bits..
+ /*
+ * Chip IDs are explained in the appropriate programming manual for the
+ * DBGMCU_IDCODE register (0xE0042000)
+ */
+ // stm32 chipids, only lower 12 bits..
#define STM32_CHIPID_F1_MEDIUM 0x410
#define STM32_CHIPID_F2 0x411
#define STM32_CHIPID_F1_LOW 0x412
#define STM32_CHIPID_F0_CAN 0x448
-/*
- * 0x436 is actually assigned to some L1 chips that are called "Medium-Plus"
- * and some that are called "High". 0x427 is assigned to the other "Medium-
- * plus" chips. To make it a bit simpler we just call 427 MEDIUM_PLUS and
- * 0x436 HIGH.
- */
+ /*
+ * 0x436 is actually assigned to some L1 chips that are called "Medium-Plus"
+ * and some that are called "High". 0x427 is assigned to the other "Medium-
+ * plus" chips. To make it a bit simpler we just call 427 MEDIUM_PLUS and
+ * 0x436 HIGH.
+ */
-// Constant STM32 memory map figures
+ // Constant STM32 memory map figures
#define STM32_FLASH_BASE 0x08000000
#define STM32_SRAM_BASE 0x20000000
-/* Cortexâ„¢-M3 Technical Reference Manual */
-/* Debug Halting Control and Status Register */
+ /* Cortexâ„¢-M3 Technical Reference Manual */
+ /* Debug Halting Control and Status Register */
#define DHCSR 0xe000edf0
#define DCRSR 0xe000edf4
#define DCRDR 0xe000edf8
#define DBGKEY 0xa05f0000
-/* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/
+ /* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/
#define C_BUF_LEN 32
typedef struct chip_params_ {
- uint32_t chip_id;
- char* description;
+ uint32_t chip_id;
+ char* description;
uint32_t flash_size_reg;
- uint32_t flash_pagesize;
- uint32_t sram_size;
- uint32_t bootrom_base, bootrom_size;
+ uint32_t flash_pagesize;
+ uint32_t sram_size;
+ uint32_t bootrom_base, bootrom_size;
} chip_params_t;
-// These maps are from a combination of the Programming Manuals, and
-// also the Reference manuals. (flash size reg is normally in ref man)
-static const chip_params_t devices[] = {
+ // These maps are from a combination of the Programming Manuals, and
+ // also the Reference manuals. (flash size reg is normally in ref man)
+ static const chip_params_t devices[] = {
{ // table 2, PM0063
.chip_id = STM32_CHIPID_F1_MEDIUM,
.description = "F1 Medium-density device",
.flash_size_reg = 0x1ffff7e0,
- .flash_pagesize = 0x400,
- .sram_size = 0x5000,
- .bootrom_base = 0x1ffff000,
- .bootrom_size = 0x800
+ .flash_pagesize = 0x400,
+ .sram_size = 0x5000,
+ .bootrom_base = 0x1ffff000,
+ .bootrom_size = 0x800
},
{ // table 1, PM0059
.chip_id = STM32_CHIPID_F2,
- .description = "F2 device",
- .flash_size_reg = 0x1fff7a22, /* As in RM0033 Rev 5*/
- .flash_pagesize = 0x20000,
- .sram_size = 0x20000,
- .bootrom_base = 0x1fff0000,
- .bootrom_size = 0x7800
+ .description = "F2 device",
+ .flash_size_reg = 0x1fff7a22, /* As in RM0033 Rev 5*/
+ .flash_pagesize = 0x20000,
+ .sram_size = 0x20000,
+ .bootrom_base = 0x1fff0000,
+ .bootrom_size = 0x7800
},
{ // PM0063
.chip_id = STM32_CHIPID_F1_LOW,
- .description = "F1 Low-density device",
- .flash_size_reg = 0x1ffff7e0,
- .flash_pagesize = 0x400,
- .sram_size = 0x2800,
- .bootrom_base = 0x1ffff000,
- .bootrom_size = 0x800
+ .description = "F1 Low-density device",
+ .flash_size_reg = 0x1ffff7e0,
+ .flash_pagesize = 0x400,
+ .sram_size = 0x2800,
+ .bootrom_base = 0x1ffff000,
+ .bootrom_size = 0x800
},
{
.chip_id = STM32_CHIPID_F4,
- .description = "F4 device",
- .flash_size_reg = 0x1FFF7A22, /* As in rm0090 since Rev 2*/
- .flash_pagesize = 0x4000,
- .sram_size = 0x30000,
- .bootrom_base = 0x1fff0000,
- .bootrom_size = 0x7800
+ .description = "F4 device",
+ .flash_size_reg = 0x1FFF7A22, /* As in rm0090 since Rev 2*/
+ .flash_pagesize = 0x4000,
+ .sram_size = 0x30000,
+ .bootrom_base = 0x1fff0000,
+ .bootrom_size = 0x7800
},
{
.chip_id = STM32_CHIPID_F4_HD,
- .description = "F42x and F43x device",
- .flash_size_reg = 0x1FFF7A22, /* As in rm0090 since Rev 2*/
- .flash_pagesize = 0x4000,
- .sram_size = 0x30000,
- .bootrom_base = 0x1fff0000,
- .bootrom_size = 0x7800
+ .description = "F42x and F43x device",
+ .flash_size_reg = 0x1FFF7A22, /* As in rm0090 since Rev 2*/
+ .flash_pagesize = 0x4000,
+ .sram_size = 0x30000,
+ .bootrom_base = 0x1fff0000,
+ .bootrom_size = 0x7800
},
{
.chip_id = STM32_CHIPID_F4_LP,
- .description = "F4 device (low power)",
- .flash_size_reg = 0x1FFF7A22,
- .flash_pagesize = 0x4000,
- .sram_size = 0x10000,
- .bootrom_base = 0x1fff0000,
- .bootrom_size = 0x7800
+ .description = "F4 device (low power)",
+ .flash_size_reg = 0x1FFF7A22,
+ .flash_pagesize = 0x4000,
+ .sram_size = 0x10000,
+ .bootrom_base = 0x1fff0000,
+ .bootrom_size = 0x7800
},
{
.chip_id = STM32_CHIPID_F4_DE,
- .description = "F4 device (Dynamic Efficency)",
- .flash_size_reg = 0x1FFF7A22,
- .flash_pagesize = 0x4000,
- .sram_size = 0x18000,
- .bootrom_base = 0x1fff0000,
- .bootrom_size = 0x7800
+ .description = "F4 device (Dynamic Efficency)",
+ .flash_size_reg = 0x1FFF7A22,
+ .flash_pagesize = 0x4000,
+ .sram_size = 0x18000,
+ .bootrom_base = 0x1fff0000,
+ .bootrom_size = 0x7800
},
{
.chip_id = STM32_CHIPID_F1_HIGH,
- .description = "F1 High-density device",
- .flash_size_reg = 0x1ffff7e0,
- .flash_pagesize = 0x800,
- .sram_size = 0x10000,
- .bootrom_base = 0x1ffff000,
- .bootrom_size = 0x800
+ .description = "F1 High-density device",
+ .flash_size_reg = 0x1ffff7e0,
+ .flash_pagesize = 0x800,
+ .sram_size = 0x10000,
+ .bootrom_base = 0x1ffff000,
+ .bootrom_size = 0x800
},
{
- // This ignores the EEPROM! (and uses the page erase size,
- // not the sector write protection...)
+ // This ignores the EEPROM! (and uses the page erase size,
+ // not the sector write protection...)
.chip_id = STM32_CHIPID_L1_MEDIUM,
- .description = "L1 Med-density device",
- .flash_size_reg = 0x1ff8004c,
- .flash_pagesize = 0x100,
- .sram_size = 0x4000,
- .bootrom_base = 0x1ff00000,
- .bootrom_size = 0x1000
+ .description = "L1 Med-density device",
+ .flash_size_reg = 0x1ff8004c,
+ .flash_pagesize = 0x100,
+ .sram_size = 0x4000,
+ .bootrom_base = 0x1ff00000,
+ .bootrom_size = 0x1000
},
{
.chip_id = STM32_CHIPID_L1_MEDIUM_PLUS,
- .description = "L1 Medium-Plus-density device",
- .flash_size_reg = 0x1ff800cc,
- .flash_pagesize = 0x100,
- .sram_size = 0x8000,/*Not completely clear if there are some with 48K*/
- .bootrom_base = 0x1ff00000,
- .bootrom_size = 0x1000
+ .description = "L1 Medium-Plus-density device",
+ .flash_size_reg = 0x1ff800cc,
+ .flash_pagesize = 0x100,
+ .sram_size = 0x8000,/*Not completely clear if there are some with 48K*/
+ .bootrom_base = 0x1ff00000,
+ .bootrom_size = 0x1000
},
{
.chip_id = STM32_CHIPID_L1_HIGH,
- .description = "L1 High-density device",
- .flash_size_reg = 0x1ff800cc,
- .flash_pagesize = 0x100,
- .sram_size = 0xC000, /*Not completely clear if there are some with 32K*/
- .bootrom_base = 0x1ff00000,
- .bootrom_size = 0x1000
+ .description = "L1 High-density device",
+ .flash_size_reg = 0x1ff800cc,
+ .flash_pagesize = 0x100,
+ .sram_size = 0xC000, /*Not completely clear if there are some with 32K*/
+ .bootrom_base = 0x1ff00000,
+ .bootrom_size = 0x1000
},
{
.chip_id = STM32_CHIPID_L152_RE,
- .description = "L152RE",
- .flash_size_reg = 0x1ff800cc,
- .flash_pagesize = 0x100,
- .sram_size = 0x14000, /*Not completely clear if there are some with 32K*/
- .bootrom_base = 0x1ff00000,
- .bootrom_size = 0x1000
+ .description = "L152RE",
+ .flash_size_reg = 0x1ff800cc,
+ .flash_pagesize = 0x100,
+ .sram_size = 0x14000, /*Not completely clear if there are some with 32K*/
+ .bootrom_base = 0x1ff00000,
+ .bootrom_size = 0x1000
},
{
.chip_id = STM32_CHIPID_F1_CONN,
- .description = "F1 Connectivity line device",
- .flash_size_reg = 0x1ffff7e0,
- .flash_pagesize = 0x800,
- .sram_size = 0x10000,
- .bootrom_base = 0x1fffb000,
- .bootrom_size = 0x4800
+ .description = "F1 Connectivity line device",
+ .flash_size_reg = 0x1ffff7e0,
+ .flash_pagesize = 0x800,
+ .sram_size = 0x10000,
+ .bootrom_base = 0x1fffb000,
+ .bootrom_size = 0x4800
},
{
.chip_id = STM32_CHIPID_F1_VL_MEDIUM,
- .description = "F1 Medium-density Value Line device",
- .flash_size_reg = 0x1ffff7e0,
- .flash_pagesize = 0x400,
- .sram_size = 0x2000,
- .bootrom_base = 0x1ffff000,
- .bootrom_size = 0x800
+ .description = "F1 Medium-density Value Line device",
+ .flash_size_reg = 0x1ffff7e0,
+ .flash_pagesize = 0x400,
+ .sram_size = 0x2000,
+ .bootrom_base = 0x1ffff000,
+ .bootrom_size = 0x800
},
{
- // This is STK32F303VCT6 device from STM32 F3 Discovery board.
- // Support based on DM00043574.pdf (RM0316) document.
+ // This is STK32F303VCT6 device from STM32 F3 Discovery board.
+ // Support based on DM00043574.pdf (RM0316) document.
.chip_id = STM32_CHIPID_F3,
- .description = "F3 device",
- .flash_size_reg = 0x1ffff7cc,
- .flash_pagesize = 0x800,
- .sram_size = 0xa000,
- .bootrom_base = 0x1ffff000,
- .bootrom_size = 0x800
+ .description = "F3 device",
+ .flash_size_reg = 0x1ffff7cc,
+ .flash_pagesize = 0x800,
+ .sram_size = 0xa000,
+ .bootrom_base = 0x1ffff000,
+ .bootrom_size = 0x800
},
{
- // This is STK32F373VCT6 device from STM32 F373 eval board
- // Support based on 303 above (37x and 30x have same memory map)
+ // This is STK32F373VCT6 device from STM32 F373 eval board
+ // Support based on 303 above (37x and 30x have same memory map)
.chip_id = STM32_CHIPID_F37x,
- .description = "F3 device",
- .flash_size_reg = 0x1ffff7cc,
- .flash_pagesize = 0x800,
- .sram_size = 0xa000,
- .bootrom_base = 0x1ffff000,
- .bootrom_size = 0x800
+ .description = "F3 device",
+ .flash_size_reg = 0x1ffff7cc,
+ .flash_pagesize = 0x800,
+ .sram_size = 0xa000,
+ .bootrom_base = 0x1ffff000,
+ .bootrom_size = 0x800
},
{
.chip_id = STM32_CHIPID_F1_VL_HIGH,
- .description = "F1 High-density value line device",
- .flash_size_reg = 0x1ffff7e0,
- .flash_pagesize = 0x800,
- .sram_size = 0x8000,
- .bootrom_base = 0x1ffff000,
- .bootrom_size = 0x800
+ .description = "F1 High-density value line device",
+ .flash_size_reg = 0x1ffff7e0,
+ .flash_pagesize = 0x800,
+ .sram_size = 0x8000,
+ .bootrom_base = 0x1ffff000,
+ .bootrom_size = 0x800
},
{
.chip_id = STM32_CHIPID_F1_XL,
- .description = "F1 XL-density device",
- .flash_size_reg = 0x1ffff7e0,
- .flash_pagesize = 0x800,
- .sram_size = 0x18000,
- .bootrom_base = 0x1fffe000,
- .bootrom_size = 0x1800
+ .description = "F1 XL-density device",
+ .flash_size_reg = 0x1ffff7e0,
+ .flash_pagesize = 0x800,
+ .sram_size = 0x18000,
+ .bootrom_base = 0x1fffe000,
+ .bootrom_size = 0x1800
},
- {
- //Use this as an example for mapping future chips:
- //RM0091 document was used to find these paramaters
+ {
+ //Use this as an example for mapping future chips:
+ //RM0091 document was used to find these paramaters
.chip_id = STM32_CHIPID_F0_CAN,
- .description = "F07x device",
- .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735)
- .flash_pagesize = 0x800, // Page sizes listed in Table 4
- .sram_size = 0x4000, // "SRAM" byte size in hex from Table 2
- .bootrom_base = 0x1fffC800, // "System memory" starting address from Table 2
- .bootrom_size = 0x3000 // "System memory" byte size in hex from Table 2
+ .description = "F07x device",
+ .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735)
+ .flash_pagesize = 0x800, // Page sizes listed in Table 4
+ .sram_size = 0x4000, // "SRAM" byte size in hex from Table 2
+ .bootrom_base = 0x1fffC800, // "System memory" starting address from Table 2
+ .bootrom_size = 0x3000 // "System memory" byte size in hex from Table 2
},
{
//Use this as an example for mapping future chips:
//RM0091 document was used to find these paramaters
.chip_id = STM32_CHIPID_F0,
- .description = "F0 device",
- .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735)
- .flash_pagesize = 0x400, // Page sizes listed in Table 4
- .sram_size = 0x2000, // "SRAM" byte size in hex from Table 2
- .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2
- .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2
+ .description = "F0 device",
+ .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735)
+ .flash_pagesize = 0x400, // Page sizes listed in Table 4
+ .sram_size = 0x2000, // "SRAM" byte size in hex from Table 2
+ .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2
+ .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2
},
{
//Use this as an example for mapping future chips:
//RM0091 document was used to find these paramaters
.chip_id = STM32_CHIPID_F0_SMALL,
- .description = "F0 small device",
- .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735)
- .flash_pagesize = 0x400, // Page sizes listed in Table 4
- .sram_size = 0x1000, // "SRAM" byte size in hex from Table 2
- .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2
- .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2
+ .description = "F0 small device",
+ .flash_size_reg = 0x1ffff7cc, // "Flash size data register" (pg735)
+ .flash_pagesize = 0x400, // Page sizes listed in Table 4
+ .sram_size = 0x1000, // "SRAM" byte size in hex from Table 2
+ .bootrom_base = 0x1fffec00, // "System memory" starting address from Table 2
+ .bootrom_size = 0xC00 // "System memory" byte size in hex from Table 2
},
{
- // STM32F30x
+ // STM32F30x
.chip_id = STM32_CHIPID_F3_SMALL,
- .description = "F3 small device",
- .flash_size_reg = 0x1ffff7cc,
- .flash_pagesize = 0x800,
- .sram_size = 0xa000,
- .bootrom_base = 0x1fffd800,
- .bootrom_size = 0x2000
+ .description = "F3 small device",
+ .flash_size_reg = 0x1ffff7cc,
+ .flash_pagesize = 0x800,
+ .sram_size = 0xa000,
+ .bootrom_base = 0x1fffd800,
+ .bootrom_size = 0x2000
},
- };
+ };
typedef struct {
#endif
#endif /* STLINK_COMMON_H */
-
/*
- Copyright (c) 2010 "Capt'ns Missing Link" Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file.
-
- A linux stlink access demo. The purpose of this file is to mitigate the usual
- "reinventing the wheel" force by incompatible licenses and give you an idea,
- how to access the stlink device. That doesn't mean you should be a free-loader
- and not contribute your improvements to this code.
-
- Author: Martin Capitanio <m@capitanio.org>
- The stlink related constants kindly provided by Oliver Spencer (OpenOCD)
- for use in a GPL compatible license.
-
- Tested compatibility: linux, gcc >= 4.3.3
-
- The communication is based on standard USB mass storage device
- BOT (Bulk Only Transfer)
- - Endpoint 1: BULK_IN, 64 bytes max
- - Endpoint 2: BULK_OUT, 64 bytes max
-
- All CBW transfers are ordered with the LSB (byte 0) first (little endian).
- Any command must be answered before sending the next command.
- Each USB transfer must complete in less than 1s.
-
- SB Device Class Definition for Mass Storage Devices:
- www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf
-
- dt - Data Transfer (IN/OUT)
- CBW - Command Block Wrapper
- CSW - Command Status Wrapper
- RFU - Reserved for Future Use
-
- Originally, this driver used scsi pass through commands, which required the
- usb-storage module to be loaded, providing the /dev/sgX links. The USB mass
- storage implementation on the STLinkv1 is however terribly broken, and it can
- take many minutes for the kernel to give up.
-
- However, in Nov 2011, the scsi pass through was replaced by raw libusb, so
- instead of having to let usb-storage struggle with the device, and also greatly
- limiting the portability of the driver, you can now tell usb-storage to simply
- ignore this device completely.
-
- usb-storage.quirks
- http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob_plain;f=Documentation/kernel-parameters.txt
- Each entry has the form VID:PID:Flags where VID and PID are Vendor and Product
- ID values (4-digit hex numbers) and Flags is a set of characters, each corresponding
- to a common usb-storage quirk flag as follows:
-
- a = SANE_SENSE (collect more than 18 bytes of sense data);
- b = BAD_SENSE (don't collect more than 18 bytes of sense data);
- c = FIX_CAPACITY (decrease the reported device capacity by one sector);
- h = CAPACITY_HEURISTICS (decrease the reported device capacity by one sector if the number is odd);
- i = IGNORE_DEVICE (don't bind to this device);
- l = NOT_LOCKABLE (don't try to lock and unlock ejectable media);
- m = MAX_SECTORS_64 (don't transfer more than 64 sectors = 32 KB at a time);
- o = CAPACITY_OK (accept the capacity reported by the device);
- r = IGNORE_RESIDUE (the device reports bogus residue values);
- s = SINGLE_LUN (the device has only one Logical Unit);
- w = NO_WP_DETECT (don't test whether the medium is write-protected).
-
- Example: quirks=0419:aaf5:rl,0421:0433:rc
- http://permalink.gmane.org/gmane.linux.usb.general/35053
-
- For the stlinkv1, you just want the following
-
- modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i
-
- Equivalently, you can add a line saying
-
- options usb-storage quirks=483:3744:i
-
- to your /etc/modprobe.conf or /etc/modprobe.d/local.conf (or add the "quirks=..."
- part to an existing options line for usb-storage).
+ * Copyright (c) 2010 "Capt'ns Missing Link" Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ *
+ * A linux stlink access demo. The purpose of this file is to mitigate the usual
+ * "reinventing the wheel" force by incompatible licenses and give you an idea,
+ * how to access the stlink device. That doesn't mean you should be a free-loader
+ * and not contribute your improvements to this code.
+ *
+ * Author: Martin Capitanio <m@capitanio.org>
+ * The stlink related constants kindly provided by Oliver Spencer (OpenOCD)
+ * for use in a GPL compatible license.
+ *
+ * Tested compatibility: linux, gcc >= 4.3.3
+ *
+ * The communication is based on standard USB mass storage device
+ * BOT (Bulk Only Transfer)
+ * - Endpoint 1: BULK_IN, 64 bytes max
+ * - Endpoint 2: BULK_OUT, 64 bytes max
+ *
+ * All CBW transfers are ordered with the LSB (byte 0) first (little endian).
+ * Any command must be answered before sending the next command.
+ * Each USB transfer must complete in less than 1s.
+ *
+ * SB Device Class Definition for Mass Storage Devices:
+ * www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf
+ *
+ * dt - Data Transfer (IN/OUT)
+ * CBW - Command Block Wrapper
+ * CSW - Command Status Wrapper
+ * RFU - Reserved for Future Use
+ *
+ * Originally, this driver used scsi pass through commands, which required the
+ * usb-storage module to be loaded, providing the /dev/sgX links. The USB mass
+ * storage implementation on the STLinkv1 is however terribly broken, and it can
+ * take many minutes for the kernel to give up.
+ *
+ * However, in Nov 2011, the scsi pass through was replaced by raw libusb, so
+ * instead of having to let usb-storage struggle with the device, and also greatly
+ * limiting the portability of the driver, you can now tell usb-storage to simply
+ * ignore this device completely.
+ *
+ * usb-storage.quirks
+ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob_plain;f=Documentation/kernel-parameters.txt
+ * Each entry has the form VID:PID:Flags where VID and PID are Vendor and Product
+ * ID values (4-digit hex numbers) and Flags is a set of characters, each corresponding
+ * to a common usb-storage quirk flag as follows:
+ *
+ * a = SANE_SENSE (collect more than 18 bytes of sense data);
+ * b = BAD_SENSE (don't collect more than 18 bytes of sense data);
+ * c = FIX_CAPACITY (decrease the reported device capacity by one sector);
+ * h = CAPACITY_HEURISTICS (decrease the reported device capacity by one sector if the number is odd);
+ * i = IGNORE_DEVICE (don't bind to this device);
+ * l = NOT_LOCKABLE (don't try to lock and unlock ejectable media);
+ * m = MAX_SECTORS_64 (don't transfer more than 64 sectors = 32 KB at a time);
+ * o = CAPACITY_OK (accept the capacity reported by the device);
+ * r = IGNORE_RESIDUE (the device reports bogus residue values);
+ * s = SINGLE_LUN (the device has only one Logical Unit);
+ * w = NO_WP_DETECT (don't test whether the medium is write-protected).
+ *
+ * Example: quirks=0419:aaf5:rl,0421:0433:rc
+ * http://permalink.gmane.org/gmane.linux.usb.general/35053
+ *
+ * For the stlinkv1, you just want the following
+ *
+ * modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i
+ *
+ * Equivalently, you can add a line saying
+ *
+ * options usb-storage quirks=483:3744:i
+ *
+ * to your /etc/modprobe.conf or /etc/modprobe.d/local.conf (or add the "quirks=..."
+ * part to an existing options line for usb-storage).
*/
/**
* Close and free any _backend_ related information...
* @param sl
- */void _stlink_sg_close(stlink_t *sl) {
+ */
+void _stlink_sg_close(stlink_t *sl) {
if (sl) {
struct stlink_libsg *slsg = sl->backend_data;
libusb_close(slsg->usb_handle);
int try = 0;
do {
ret = libusb_bulk_transfer(handle, endpoint, (unsigned char *)&csw, sizeof(csw),
- &transferred, SG_TIMEOUT_MSEC);
+ &transferred, SG_TIMEOUT_MSEC);
if (ret == LIBUSB_ERROR_PIPE) {
libusb_clear_halt(handle, endpoint);
}
* @param lun
* @param flags
* @param expected_rx_size
- * @return
+ * @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) {
+ 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);
// Now the actual CDB request
assert(cdb_length <= CDB_SL);
memcpy(&(c_buf[i]), cdb, cdb_length);
-
+
int sending_length = STLINK_SG_SIZE;
-
+
// send....
do {
ret = libusb_bulk_transfer(handle, endpoint_out, c_buf, sending_length,
- &real_transferred, SG_TIMEOUT_MSEC);
+ &real_transferred, SG_TIMEOUT_MSEC);
if (ret == LIBUSB_ERROR_PIPE) {
libusb_clear_halt(handle, endpoint_out);
}
* @param endpoint_in
* @param endpoint_out
*/
-static void
+ static void
get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out)
{
DLOG("Fetching sense...\n");
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);
+ LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH);
if (tag == 0) {
WLOG("refusing to send request sense with tag 0\n");
return;
int try = 0;
do {
ret = libusb_bulk_transfer(handle, endpoint_in, sense, sizeof(sense),
- &transferred, SG_TIMEOUT_MSEC);
+ &transferred, SG_TIMEOUT_MSEC);
if (ret == LIBUSB_ERROR_PIPE) {
libusb_clear_halt(handle, endpoint_in);
}
* 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 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) {
+ unsigned char endpoint_in, unsigned char *cbuf, unsigned int length) {
int ret;
int real_transferred;
int try = 0;
do {
ret = libusb_bulk_transfer(handle, endpoint_out, cbuf, length,
- &real_transferred, SG_TIMEOUT_MSEC);
+ &real_transferred, SG_TIMEOUT_MSEC);
if (ret == LIBUSB_ERROR_PIPE) {
libusb_clear_halt(handle, endpoint_out);
}
WLOG("sending failed: %d\n", ret);
return -1;
}
-
+
// 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
get_sense(handle, endpoint_in, endpoint_out);
return -1;
}
-
+
return real_transferred;
}
//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);
-
-
+ 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 ret;
if (rx_length > 0) {
do {
- ret = libusb_bulk_transfer(sg->usb_handle, sg->ep_rep, sl->q_buf, rx_length,
- &real_transferred, SG_TIMEOUT_MSEC);
+ 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);
}
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);
+ case STLINK_OK:
+ DLOG(" %s: ok\n", txt);
+ return;
+ case STLINK_FALSE:
+ DLOG(" %s: false\n", txt);
+ return;
+ default:
+ DLOG(" %s: unknown\n", txt);
}
}
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
- */
+ [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) {
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++) {
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;
+ 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;
}
}
};
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));
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");
free(slsg);
return NULL;
}
-
- // TODO
+
+ // 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);
return NULL;
}
-
+
// assumption: bConfigurationValue is always 1
if (config != 1) {
WLOG("Your stlink got into a real weird configuration, trying to fix it!\n");
// 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;
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");
+ 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;
+ 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);
-
+
// re-query device info (and retest)
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");
+ ugly_log(UERROR, LOG_TAG,
+ "WTF? successfully opened, but unable to read version details. BROKEN!\n");
return NULL;
}
return NULL;
}
// by now, it _must_ be fully open and in a useful mode....
- stlink_enter_swd_mode(sl);
+ stlink_enter_swd_mode(sl);
/* Now we are ready to read the parameters */
if (reset) {
stlink_reset(sl);
-/*
+/*
* File: stlink-sg.h
* Author: karl
*
#ifdef __cplusplus
extern "C" {
#endif
-
+
#include <libusb.h>
#include "stlink-common.h"
-
- // device access
+
+ // device access
#define RDWR 0
#define RO 1
#define SG_TIMEOUT_SEC 1 // actually 1 is about 2 sec
libusb_device_handle *usb_handle;
unsigned ep_rep;
unsigned ep_req;
-
+
int sg_fd;
int do_scsi_pt_err;
#define WLOG(format, args...) ugly_log(UWARN, LOG_TAG, format, ## args)
#define fatal(format, args...) ugly_log(UFATAL, LOG_TAG, format, ## args)
-/* code from bsd timersub.h
+/* code from bsd timersub.h
http://www.gnu-darwin.org/www001/src/ports/net/libevnet/work/libevnet-0.3.8/libnostd/bsd/sys/time/timersub.h.html
*/
#if !defined timersub
#define timersub(a, b, r) do { \
- (r)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
- (r)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
- if ((r)->tv_usec < 0) { \
- --(r)->tv_sec; \
- (r)->tv_usec += 1000000; \
- } \
+ (r)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (r)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((r)->tv_usec < 0) { \
+ --(r)->tv_sec; \
+ (r)->tv_usec += 1000000; \
+ } \
} while (0)
#endif
if (rxsize != 0) {
/* read the response */
-
+
libusb_fill_bulk_transfer(handle->rep_trans, handle->usb_handle,
- handle->ep_rep, rxbuf, rxsize, NULL, NULL, 0);
-
+ handle->ep_rep, rxbuf, rxsize, NULL, NULL, 0);
+
if (submit_wait(handle, handle->rep_trans)) return -1;
res = handle->rep_trans->actual_length;
}
-
+
if ((handle->protocoll == 1) && terminate) {
/* Read the SG reply */
unsigned char sg_buf[13];
unsigned char* const cmd = sl->c_buf;
ssize_t size;
const int rep_len = 8;
-
+
int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_JTAG_READDEBUG_32BIT;
unsigned char* const cmd = sl->c_buf;
ssize_t size;
const int rep_len = 2;
-
+
int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
cmd[i++] = STLINK_DEBUG_COMMAND;
cmd[i++] = STLINK_JTAG_WRITEDEBUG_32BIT;
ssize_t size;
int rep_len = 2;
int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
-
+
cmd[i++] = STLINK_GET_CURRENT_MODE;
size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
stlink_print_data(sl);
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;
DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r);
switch (r_idx) {
- case 0x14:
- regp->primask = (uint8_t) (r & 0xFF);
- regp->basepri = (uint8_t) ((r>>8) & 0xFF);
- regp->faultmask = (uint8_t) ((r>>16) & 0xFF);
- regp->control = (uint8_t) ((r>>24) & 0xFF);
- break;
- case 0x21:
- regp->fpscr = r;
- break;
- default:
- regp->s[r_idx - 0x40] = r;
- break;
+ case 0x14:
+ regp->primask = (uint8_t) (r & 0xFF);
+ regp->basepri = (uint8_t) ((r>>8) & 0xFF);
+ regp->faultmask = (uint8_t) ((r>>16) & 0xFF);
+ regp->control = (uint8_t) ((r>>24) & 0xFF);
+ break;
+ case 0x21:
+ regp->fpscr = r;
+ break;
+ default:
+ regp->s[r_idx - 0x40] = r;
+ break;
}
}
val = (uint8_t) (val>>24);
switch (r_idx) {
- case 0x1C: /* control */
- val = (((uint32_t) val) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) regp->primask);
- break;
- case 0x1D: /* faultmask */
- val = (((uint32_t) regp->control) << 24) | (((uint32_t) val) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) regp->primask);
- break;
- case 0x1E: /* basepri */
- val = (((uint32_t) regp->control) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) val) << 8) | ((uint32_t) regp->primask);
- break;
- case 0x1F: /* primask */
- val = (((uint32_t) regp->control) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) val);
- break;
+ case 0x1C: /* control */
+ val = (((uint32_t) val) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) regp->primask);
+ break;
+ case 0x1D: /* faultmask */
+ val = (((uint32_t) regp->control) << 24) | (((uint32_t) val) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) regp->primask);
+ break;
+ case 0x1E: /* basepri */
+ val = (((uint32_t) regp->control) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) val) << 8) | ((uint32_t) regp->primask);
+ break;
+ case 0x1F: /* primask */
+ val = (((uint32_t) regp->control) << 24) | (((uint32_t) regp->faultmask) << 16) | (((uint32_t) regp->basepri) << 8) | ((uint32_t) val);
+ break;
}
r_idx = 0x14;
ugly_init(verbose);
sl->backend = &_stlink_usb_backend;
sl->backend_data = slu;
-
+
sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
if (libusb_init(&(slu->libusb_ctx))) {
WLOG("failed to init libusb context, wrong version of libraries?\n");
goto on_error;
}
-
+
libusb_device **list;
int cnt = libusb_get_device_list(slu->libusb_ctx, &list);
struct libusb_device_descriptor desc;
int devBus =0;
int devAddr=0;
-
+
char *device = getenv("STLINK_DEVICE");
if (device) {
char *c = strchr(device,':');
break;
}
}
-
+
if (cnt < 0) {
WLOG ("Couldn't find %s ST-Link/V2 devices\n",(devBus && devAddr)?"matched":"any");
goto on_error;
goto on_error;
}
}
-
+
libusb_free_device_list(list, 1);
-
+
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));
// TODO - could use the scanning techniq from stm8 code here...
slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN;
if (desc.idProduct == USB_STLINK_NUCLEO_PID) {
- slu->ep_req = 1 /* ep req */ | LIBUSB_ENDPOINT_OUT;
+ slu->ep_req = 1 /* ep req */ | LIBUSB_ENDPOINT_OUT;
} else {
- slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT;
+ slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT;
}
slu->sg_transfer_idx = 0;
/* success */
if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
- ILOG("-- exit_dfu_mode\n");
- stlink_exit_dfu_mode(sl);
+ ILOG("-- exit_dfu_mode\n");
+ stlink_exit_dfu_mode(sl);
}
if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) {
- stlink_enter_swd_mode(sl);
+ stlink_enter_swd_mode(sl);
}
if (reset) {
on_error:
if( slu->libusb_ctx)
- libusb_exit(slu->libusb_ctx);
+ libusb_exit(slu->libusb_ctx);
if (sl != NULL) free(sl);
if (slu != NULL) free(slu);
return 0;
-/*
+/*
* File: stlink-usb.h
* Author: karl
*
#include <libusb.h>
#include "stlink-common.h"
-
+
#define STLINK_SG_SIZE 31
#define STLINK_CMD_SIZE 16
unsigned int sg_transfer_idx;
unsigned int cmd_len;
};
-
+
stlink_t* stlink_open_usb(const int verbose, int reset);
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:
+ /* 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));
+ }
+
+ 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, 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));
+ 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"
+ // 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
+ 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);
- }
- write_uint32(sl->q_buf, io_conf); // set old state
+
+ 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);
+ // 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);
+ // 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, 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);
+ //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);
+ // 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);
+ 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);
+ // 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);
+ 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);
+ 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_run(sl);
+ stlink_status(sl);
- stlink_force_debug(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);
+ 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);
+ 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);
+ 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);
- }
+ 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);
+ 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);
+ 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;
+ //fflush(stderr); fflush(stdout);
+ return EXIT_SUCCESS;
}
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("FP_CTRL\n");
stlink_read_mem32(sl, CM3_REG_FP_CTRL, 4);
-
+
// no idea what reg this is.. */
// stlink_read_mem32(sl, 0xe000ed90, 4);
// no idea what register this is...
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);
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");
-/*
- * UglyLogging. Slow, yet another wheel reinvented, but enough to make the
+/*
+ * UglyLogging. Slow, yet another wheel reinvented, but enough to make the
* rest of our code pretty enough.
- *
+ *
*/
#include <stddef.h>
tt = localtime(&mytt);
fprintf(stderr, "%d-%02d-%02dT%02d:%02d:%02d ", tt->tm_year + 1900, tt->tm_mon + 1, tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec);
switch (level) {
- case UDEBUG:
- fprintf(stderr, "DEBUG %s: ", tag);
- break;
- case UINFO:
- fprintf(stderr, "INFO %s: ", tag);
- break;
- case UWARN:
- fprintf(stderr, "WARN %s: ", tag);
- break;
- case UERROR:
- fprintf(stderr, "ERROR %s: ", tag);
- break;
- case UFATAL:
- fprintf(stderr, "FATAL %s: ", tag);
- vfprintf(stderr, format, args);
- exit(EXIT_FAILURE);
- // NEVER GETS HERE!!!
- break;
- default:
- fprintf(stderr, "%d %s: ", level, tag);
- break;
+ case UDEBUG:
+ fprintf(stderr, "DEBUG %s: ", tag);
+ break;
+ case UINFO:
+ fprintf(stderr, "INFO %s: ", tag);
+ break;
+ case UWARN:
+ fprintf(stderr, "WARN %s: ", tag);
+ break;
+ case UERROR:
+ fprintf(stderr, "ERROR %s: ", tag);
+ break;
+ case UFATAL:
+ fprintf(stderr, "FATAL %s: ", tag);
+ vfprintf(stderr, format, args);
+ exit(EXIT_FAILURE);
+ // NEVER GETS HERE!!!
+ break;
+ default:
+ fprintf(stderr, "%d %s: ", level, tag);
+ break;
}
- vfprintf(stderr, format, args);
+ vfprintf(stderr, format, args);
va_end(args);
return 1;
-}
\ No newline at end of file
+}
-/*
+/*
* Ugly, low performance, configurable level, logging "framework"
*/
#ifdef __cplusplus
extern "C" {
#endif
-
+
#define UDEBUG 90
#define UINFO 50
#define UWARN 30