kopia lustrzana https://github.com/stlink-org/stlink
Reindent all source files
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.pull/248/head
rodzic
2a4466ec4e
commit
3b443dc1c8
330
flash/main.c
330
flash/main.c
|
@ -12,12 +12,12 @@
|
|||
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)
|
||||
|
@ -31,183 +31,183 @@ 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> */
|
||||
/* stlinkv1 command line: ./flash {read|write} /dev/sgX path addr <size> */
|
||||
/* stlinkv2 command line: ./flash {read|write} path addr <size> */
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (ac < 1) return -1;
|
||||
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)
|
||||
if (strcmp(av[0], "--reset") == 0)
|
||||
{
|
||||
o->devname = av[1];
|
||||
i = 1;
|
||||
o->reset = 1;
|
||||
ac--;
|
||||
av++;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
if (ac < 1) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
o.size = 0;
|
||||
if (get_opts(&o, ac - 1, av + 1) == -1)
|
||||
{
|
||||
printf("stlink_fwrite_flash() == -1\n");
|
||||
goto on_error;
|
||||
printf("invalid command line\n");
|
||||
usage();
|
||||
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)
|
||||
|
||||
if (o.devname != NULL) /* stlinkv1 */
|
||||
{
|
||||
printf("stlink_fread() == -1\n");
|
||||
goto on_error;
|
||||
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 (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);
|
||||
|
||||
return err;
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
/* 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
|
||||
|
|
|
@ -8,23 +8,23 @@
|
|||
@ 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
|
||||
|
||||
|
|
|
@ -26,38 +26,37 @@
|
|||
|
||||
|
||||
// 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
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
/* -*- 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>
|
||||
|
@ -20,141 +18,141 @@
|
|||
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) */
|
||||
int length = strlen(data) + 5;
|
||||
char* packet = malloc(length); /* '$' data (hex) '#' cksum (hex) */
|
||||
|
||||
memset(packet, 0, length);
|
||||
memset(packet, 0, length);
|
||||
|
||||
packet[0] = '$';
|
||||
packet[0] = '$';
|
||||
|
||||
uint8_t cksum = 0;
|
||||
for(unsigned int i = 0; i < strlen(data); i++) {
|
||||
packet[i + 1] = data[i];
|
||||
cksum += data[i];
|
||||
}
|
||||
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];
|
||||
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;
|
||||
}
|
||||
while(1) {
|
||||
if(write(fd, packet, length) != length) {
|
||||
free(packet);
|
||||
return -2;
|
||||
}
|
||||
|
||||
char ack;
|
||||
if(read(fd, &ack, 1) != 1) {
|
||||
free(packet);
|
||||
return -2;
|
||||
}
|
||||
char ack;
|
||||
if(read(fd, &ack, 1) != 1) {
|
||||
free(packet);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(ack == '+') {
|
||||
free(packet);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
char c;
|
||||
while(state != 4) {
|
||||
if(read(fd, &c, 1) != 1) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
switch(state) {
|
||||
case 0:
|
||||
if(c != '$') {
|
||||
// ignore
|
||||
} else {
|
||||
state = 1;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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 2:
|
||||
recv_cksum[0] = c;
|
||||
state = 3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
recv_cksum[1] = c;
|
||||
state = 4;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
goto start;
|
||||
} else {
|
||||
char ack = '+';
|
||||
if(write(fd, &ack, 1) != 1) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
packet_buffer[packet_idx] = 0;
|
||||
*buffer = packet_buffer;
|
||||
packet_buffer[packet_idx] = 0;
|
||||
*buffer = packet_buffer;
|
||||
|
||||
return packet_idx;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
1224
gui/stlink-gui.c
1224
gui/stlink-gui.c
Plik diff jest za duży
Load Diff
|
@ -17,75 +17,75 @@ typedef struct _STlinkGUIClass STlinkGUIClass;
|
|||
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;
|
||||
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;
|
||||
/*< 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;
|
||||
/* 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;
|
||||
struct progress_t progress;
|
||||
struct mem_t flash_mem;
|
||||
struct mem_t file_mem;
|
||||
|
||||
gchar *error_message;
|
||||
gchar *filename;
|
||||
stlink_t *sl;
|
||||
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);
|
||||
|
|
198
mingw/mingw.c
198
mingw/mingw.c
|
@ -22,30 +22,30 @@ int win32_poll(struct pollfd *fds, unsigned int nfds, int timo)
|
|||
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
|
||||
|
@ -53,23 +53,23 @@ int win32_poll(struct pollfd *fds, unsigned int nfds, int timo)
|
|||
#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
|
||||
}
|
||||
}
|
||||
|
@ -79,14 +79,14 @@ static void
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,12 +94,12 @@ static void
|
|||
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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -192,75 +192,75 @@ ssize_t win32_read_socket(SOCKET fd, void *buf, int n)
|
|||
|
||||
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
|
||||
|
|
28
src/mmap.c
28
src/mmap.c
|
@ -7,27 +7,27 @@
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
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
|
||||
}
|
||||
|
|
118
src/st-info.c
118
src/st-info.c
|
@ -11,79 +11,79 @@
|
|||
|
||||
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 (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
|
||||
stlink_enter_swd_mode(sl);
|
||||
if (sl == NULL) {
|
||||
return -1;
|
||||
}
|
||||
sl->verbose=0;
|
||||
if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE)
|
||||
stlink_exit_dfu_mode(sl);
|
||||
|
||||
err = print_data(sl, av);
|
||||
|
||||
if (sl != NULL)
|
||||
{
|
||||
stlink_exit_debug_mode(sl);
|
||||
stlink_close(sl);
|
||||
}
|
||||
if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
|
||||
stlink_enter_swd_mode(sl);
|
||||
|
||||
return err;
|
||||
err = print_data(sl, av);
|
||||
|
||||
if (sl != NULL)
|
||||
{
|
||||
stlink_exit_debug_mode(sl);
|
||||
stlink_close(sl);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
336
src/st-term.c
336
src/st-term.c
|
@ -13,225 +13,225 @@
|
|||
|
||||
#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);
|
||||
}
|
||||
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);
|
||||
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;
|
||||
struct termios ttystate;
|
||||
|
||||
//get the terminal state
|
||||
tcgetattr(STDIN_FILENO, &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);
|
||||
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();
|
||||
struct stlinky *st=NULL;
|
||||
|
||||
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);
|
||||
sig_init();
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
stlink_reset(sl);
|
||||
stlink_force_debug(sl);
|
||||
stlink_run(sl);
|
||||
stlink_status(sl);
|
||||
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);
|
||||
|
||||
/* wait for device to boot */
|
||||
/* TODO: Make timeout adjustable via command line */
|
||||
sleep(1);
|
||||
stlink_reset(sl);
|
||||
stlink_force_debug(sl);
|
||||
stlink_run(sl);
|
||||
stlink_status(sl);
|
||||
|
||||
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;
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ static inline uint32_t read_flash_obr(stlink_t *sl) {
|
|||
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);
|
||||
|
@ -157,7 +157,7 @@ static inline uint32_t read_flash_cr(stlink_t *sl) {
|
|||
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);
|
||||
|
@ -168,13 +168,13 @@ static void unlock_flash(stlink_t *sl) {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -196,9 +196,9 @@ static int unlock_flash_if(stlink_t *sl) {
|
|||
|
||||
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);
|
||||
|
@ -209,10 +209,10 @@ static void lock_flash(stlink_t *sl) {
|
|||
|
||||
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);
|
||||
|
@ -222,8 +222,8 @@ static void set_flash_cr_pg(stlink_t *sl) {
|
|||
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);
|
||||
}
|
||||
|
@ -240,33 +240,33 @@ static void __attribute__((unused)) clear_flash_cr_per(stlink_t *sl) {
|
|||
|
||||
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) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ static inline uint32_t read_flash_acr(stlink_t *sl) {
|
|||
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);
|
||||
|
@ -287,7 +287,7 @@ static inline uint32_t read_flash_sr(stlink_t *sl) {
|
|||
|
||||
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);
|
||||
|
@ -464,7 +464,7 @@ int stlink_load_device_params(stlink_t *sl) {
|
|||
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 ) {
|
||||
|
@ -483,8 +483,8 @@ int stlink_load_device_params(stlink_t *sl) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -557,11 +557,11 @@ int stlink_target_voltage(stlink_t *sl) {
|
|||
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");
|
||||
}
|
||||
|
@ -691,15 +691,15 @@ void stlink_step(stlink_t *sl) {
|
|||
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;
|
||||
|
@ -750,17 +750,17 @@ void stlink_core_stat(stlink_t *sl) {
|
|||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -773,11 +773,11 @@ void stlink_print_data(stlink_t * sl) {
|
|||
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]);
|
||||
}
|
||||
|
@ -931,7 +931,7 @@ int stlink_fread(stlink_t* sl, const char* path, stm32_addr_t addr, size_t size)
|
|||
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) {
|
||||
|
@ -940,32 +940,32 @@ int stlink_fread(stlink_t* sl, const char* path, stm32_addr_t addr, size_t size)
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -1013,14 +1013,14 @@ uint32_t calculate_F4_sectornum(uint32_t flashaddr){
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1032,144 +1032,144 @@ uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){
|
|||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* 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)
|
||||
;
|
||||
/* 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);
|
||||
/* 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++) {
|
||||
|
@ -1266,13 +1266,13 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
|
|||
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
|
||||
|
@ -1285,7 +1285,7 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
|
|||
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 */
|
||||
|
@ -1300,7 +1300,7 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
|
|||
r1, input, source addr
|
||||
r2, input, word count
|
||||
r3, output, word count
|
||||
*/
|
||||
*/
|
||||
|
||||
0x00, 0x23,
|
||||
0x04, 0xe0,
|
||||
|
@ -1340,14 +1340,14 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
|
|||
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) {
|
||||
|
@ -1473,7 +1473,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
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) {
|
||||
|
@ -1507,17 +1507,17 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
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 */
|
||||
|
@ -1526,15 +1526,15 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
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;
|
||||
|
@ -1551,8 +1551,8 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
|
||||
#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) {
|
||||
|
@ -1569,65 +1569,65 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
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);
|
||||
/* 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;
|
||||
}
|
||||
/* 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);
|
||||
/* 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;
|
||||
/* 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");
|
||||
|
@ -1683,12 +1683,12 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
++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 */
|
||||
|
@ -1715,7 +1715,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1740,23 +1740,23 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) {
|
|||
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*/
|
||||
|
@ -1781,7 +1781,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -1805,7 +1805,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
|
|||
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;
|
||||
|
@ -1839,27 +1839,27 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
|
|||
|
||||
/* 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) {
|
||||
|
@ -1869,8 +1869,8 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
|
|||
|
||||
} 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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
#ifndef STLINK_COMMON_H
|
||||
#define STLINK_COMMON_H
|
||||
#define STLINK_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -77,12 +77,12 @@ 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
|
||||
|
@ -93,11 +93,11 @@ extern "C" {
|
|||
#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
|
||||
|
@ -132,252 +132,252 @@ extern "C" {
|
|||
|
||||
#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 {
|
||||
|
@ -566,4 +566,3 @@ static const chip_params_t devices[] = {
|
|||
#endif
|
||||
|
||||
#endif /* STLINK_COMMON_H */
|
||||
|
||||
|
|
363
src/stlink-sg.c
363
src/stlink-sg.c
|
@ -1,77 +1,77 @@
|
|||
/*
|
||||
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).
|
||||
*/
|
||||
|
||||
|
||||
|
@ -108,7 +108,8 @@ static void clear_cdb(struct stlink_libsg *sl) {
|
|||
/**
|
||||
* 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);
|
||||
|
@ -126,7 +127,7 @@ static int get_usb_mass_storage_status(libusb_device_handle *handle, uint8_t end
|
|||
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);
|
||||
}
|
||||
|
@ -175,11 +176,11 @@ static int dump_CDB_command(uint8_t *cdb, uint8_t cdb_len) {
|
|||
* @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);
|
||||
|
||||
|
@ -211,13 +212,13 @@ int send_usb_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint
|
|||
// 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);
|
||||
}
|
||||
|
@ -237,7 +238,7 @@ int send_usb_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint
|
|||
* @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");
|
||||
|
@ -248,7 +249,7 @@ get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_ou
|
|||
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;
|
||||
|
@ -259,7 +260,7 @@ get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_ou
|
|||
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);
|
||||
}
|
||||
|
@ -289,20 +290,20 @@ get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_ou
|
|||
* 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);
|
||||
}
|
||||
|
@ -312,7 +313,7 @@ int send_usb_data_only(libusb_device_handle *handle, unsigned char 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
|
||||
|
@ -328,7 +329,7 @@ int send_usb_data_only(libusb_device_handle *handle, unsigned char endpoint_out,
|
|||
get_sense(handle, endpoint_in, endpoint_out);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return real_transferred;
|
||||
}
|
||||
|
||||
|
@ -338,10 +339,10 @@ int stlink_q(stlink_t *sl) {
|
|||
//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;
|
||||
|
@ -350,8 +351,8 @@ int stlink_q(stlink_t *sl) {
|
|||
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);
|
||||
}
|
||||
|
@ -401,14 +402,14 @@ void stlink_stat(stlink_t *stl, char *txt) {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,48 +472,48 @@ void _stlink_sg_exit_dfu_mode(stlink_t *sl) {
|
|||
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) {
|
||||
|
@ -586,7 +587,7 @@ void _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) {
|
|||
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++) {
|
||||
|
@ -630,23 +631,23 @@ void _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -883,7 +884,7 @@ stlink_backend_t _stlink_sg_backend = {
|
|||
};
|
||||
|
||||
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));
|
||||
|
@ -891,16 +892,16 @@ static stlink_t* stlink_open(const int verbose) {
|
|||
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");
|
||||
|
@ -910,10 +911,10 @@ static stlink_t* stlink_open(const int verbose) {
|
|||
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);
|
||||
|
@ -939,7 +940,7 @@ static stlink_t* stlink_open(const int verbose) {
|
|||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// assumption: bConfigurationValue is always 1
|
||||
if (config != 1) {
|
||||
WLOG("Your stlink got into a real weird configuration, trying to fix it!\n");
|
||||
|
@ -967,9 +968,9 @@ static stlink_t* stlink_open(const int verbose) {
|
|||
// 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;
|
||||
|
@ -991,15 +992,15 @@ stlink_t* stlink_v1_open_inner(const int verbose) {
|
|||
|
||||
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;
|
||||
|
@ -1010,12 +1011,12 @@ stlink_t* stlink_v1_open_inner(const int verbose) {
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1029,7 +1030,7 @@ stlink_t* stlink_v1_open(const int verbose, int reset) {
|
|||
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);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* File: stlink-sg.h
|
||||
* Author: karl
|
||||
*
|
||||
|
@ -11,11 +11,11 @@
|
|||
#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
|
||||
|
@ -46,7 +46,7 @@ extern "C" {
|
|||
libusb_device_handle *usb_handle;
|
||||
unsigned ep_rep;
|
||||
unsigned ep_req;
|
||||
|
||||
|
||||
int sg_fd;
|
||||
int do_scsi_pt_err;
|
||||
|
||||
|
|
104
src/stlink-usb.c
104
src/stlink-usb.c
|
@ -16,17 +16,17 @@
|
|||
#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
|
||||
|
||||
|
@ -135,14 +135,14 @@ ssize_t send_recv(struct stlink_libusb* handle, int terminate,
|
|||
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];
|
||||
|
@ -237,7 +237,7 @@ uint32_t _stlink_usb_read_debug32(stlink_t *sl, uint32_t addr) {
|
|||
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;
|
||||
|
@ -256,7 +256,7 @@ void _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
|
|||
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;
|
||||
|
@ -306,7 +306,7 @@ int _stlink_usb_current_mode(stlink_t * sl) {
|
|||
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) {
|
||||
|
@ -582,7 +582,7 @@ void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
|
|||
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;
|
||||
|
@ -620,18 +620,18 @@ void _stlink_usb_read_unsupported_reg(stlink_t *sl, int r_idx, reg *regp) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,18 +653,18 @@ void _stlink_usb_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, re
|
|||
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;
|
||||
|
@ -750,20 +750,20 @@ stlink_t* stlink_open_usb(const int verbose, int reset) {
|
|||
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,':');
|
||||
|
@ -788,7 +788,7 @@ stlink_t* stlink_open_usb(const int verbose, int reset) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (cnt < 0) {
|
||||
WLOG ("Couldn't find %s ST-Link/V2 devices\n",(devBus && devAddr)?"matched":"any");
|
||||
goto on_error;
|
||||
|
@ -799,13 +799,13 @@ stlink_t* stlink_open_usb(const int verbose, int reset) {
|
|||
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));
|
||||
|
@ -848,9 +848,9 @@ stlink_t* stlink_open_usb(const int verbose, int reset) {
|
|||
// 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;
|
||||
|
@ -860,12 +860,12 @@ stlink_t* stlink_open_usb(const int verbose, int reset) {
|
|||
/* 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) {
|
||||
|
@ -891,7 +891,7 @@ on_libusb_error:
|
|||
|
||||
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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* File: stlink-usb.h
|
||||
* Author: karl
|
||||
*
|
||||
|
@ -14,7 +14,7 @@ extern "C" {
|
|||
|
||||
#include <libusb.h>
|
||||
#include "stlink-common.h"
|
||||
|
||||
|
||||
#define STLINK_SG_SIZE 31
|
||||
#define STLINK_CMD_SIZE 16
|
||||
|
||||
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
unsigned int sg_transfer_idx;
|
||||
unsigned int cmd_len;
|
||||
};
|
||||
|
||||
|
||||
stlink_t* stlink_open_usb(const int verbose, int reset);
|
||||
|
||||
|
||||
|
|
272
src/test_sg.c
272
src/test_sg.c
|
@ -33,196 +33,196 @@ static void __attribute__((unused)) mark_buf(stlink_t *sl) {
|
|||
|
||||
|
||||
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
|
||||
/* 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:
|
||||
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_t *sl = stlink_v1_open(99, 1);
|
||||
if (sl == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
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));
|
||||
// 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);
|
||||
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);
|
||||
// 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
|
||||
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
|
||||
// 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);
|
||||
//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, 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, 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_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_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;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ int main(int ac, char** av) {
|
|||
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) {
|
||||
|
@ -43,7 +43,7 @@ int main(int ac, char** av) {
|
|||
|
||||
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...
|
||||
|
@ -58,7 +58,7 @@ int main(int ac, char** av) {
|
|||
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);
|
||||
|
@ -79,8 +79,8 @@ int main(int ac, char** av) {
|
|||
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");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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>
|
||||
|
@ -30,29 +30,29 @@ int ugly_log(int level, const char *tag, const char *format, ...) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Ugly, low performance, configurable level, logging "framework"
|
||||
*/
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define UDEBUG 90
|
||||
#define UINFO 50
|
||||
#define UWARN 30
|
||||
|
|
Ładowanie…
Reference in New Issue