Merge pull request #357 from UweBonnes/write_access_size1

Write access size1
This commit is contained in:
Gareth McMullin 2018-06-21 10:05:45 -07:00 committed by GitHub
commit 1799ea3b71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 116 additions and 257 deletions

View File

@ -457,11 +457,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
adiv5_dp_unref(dp); adiv5_dp_unref(dp);
} }
enum align {
ALIGN_BYTE = 0,
ALIGN_HALFWORD = 1,
ALIGN_WORD = 2
};
#define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \ #define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \
(((x) & 1) == 0 ? ALIGN_HALFWORD : ALIGN_BYTE)) (((x) & 1) == 0 ? ALIGN_HALFWORD : ALIGN_BYTE))
@ -477,6 +472,7 @@ static void ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align)
case ALIGN_HALFWORD: case ALIGN_HALFWORD:
csw |= ADIV5_AP_CSW_SIZE_HALFWORD; csw |= ADIV5_AP_CSW_SIZE_HALFWORD;
break; break;
case ALIGN_DWORD:
case ALIGN_WORD: case ALIGN_WORD:
csw |= ADIV5_AP_CSW_SIZE_WORD; csw |= ADIV5_AP_CSW_SIZE_WORD;
break; break;
@ -495,6 +491,7 @@ static void * extract(void *dest, uint32_t src, uint32_t val, enum align align)
case ALIGN_HALFWORD: case ALIGN_HALFWORD:
*(uint16_t *)dest = (val >> ((src & 0x2) << 3) & 0xFFFF); *(uint16_t *)dest = (val >> ((src & 0x2) << 3) & 0xFFFF);
break; break;
case ALIGN_DWORD:
case ALIGN_WORD: case ALIGN_WORD:
*(uint32_t *)dest = val; *(uint32_t *)dest = val;
break; break;
@ -534,10 +531,10 @@ adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
} }
void void
adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len) adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
{ {
uint32_t odest = dest; uint32_t odest = dest;
enum align align = MIN(ALIGNOF(dest), ALIGNOF(len));
len >>= align; len >>= align;
ap_mem_access_setup(ap, dest, align); ap_mem_access_setup(ap, dest, align);
@ -551,6 +548,7 @@ adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len)
case ALIGN_HALFWORD: case ALIGN_HALFWORD:
tmp = ((uint32_t)*(uint16_t *)src) << ((dest & 2) << 3); tmp = ((uint32_t)*(uint16_t *)src) << ((dest & 2) << 3);
break; break;
case ALIGN_DWORD:
case ALIGN_WORD: case ALIGN_WORD:
tmp = *(uint32_t *)src; tmp = *(uint32_t *)src;
break; break;
@ -568,6 +566,13 @@ adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len)
} }
} }
void
adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len)
{
enum align align = MIN(ALIGNOF(dest), ALIGNOF(len));
adiv5_mem_write_sized(ap, dest, src, len, align);
}
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value) void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{ {
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,

View File

@ -100,6 +100,13 @@
#define ADIV5_LOW_WRITE 0 #define ADIV5_LOW_WRITE 0
#define ADIV5_LOW_READ 1 #define ADIV5_LOW_READ 1
enum align {
ALIGN_BYTE = 0,
ALIGN_HALFWORD = 1,
ALIGN_WORD = 2,
ALIGN_DWORD = 3
};
/* Try to keep this somewhat absract for later adding SW-DP */ /* Try to keep this somewhat absract for later adding SW-DP */
typedef struct ADIv5_DP_s { typedef struct ADIv5_DP_s {
int refcnt; int refcnt;
@ -167,6 +174,8 @@ void adiv5_jtag_dp_handler(jtag_dev_t *dev);
void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len); void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len);
void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len); void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len);
void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align);
#endif #endif

View File

@ -459,6 +459,14 @@ static void cortexm_regs_write(target *t, const void *data)
} }
} }
int cortexm_mem_write_sized(
target *t, target_addr dest, const void *src, size_t len, enum align align)
{
cortexm_cache_clean(t, dest, len, true);
adiv5_mem_write_sized(cortexm_ap(t), dest, src, len, align);
return target_check_error(t);
}
static uint32_t cortexm_pc_read(target *t) static uint32_t cortexm_pc_read(target *t)
{ {
target_mem_write32(t, CORTEXM_DCRSR, 0x0F); target_mem_write32(t, CORTEXM_DCRSR, 0x0F);

View File

@ -175,6 +175,8 @@ void cortexm_detach(target *t);
void cortexm_halt_resume(target *t, bool step); void cortexm_halt_resume(target *t, bool step);
int cortexm_run_stub(target *t, uint32_t loadaddr, int cortexm_run_stub(target *t, uint32_t loadaddr,
uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3);
int cortexm_mem_write_sized(
target *t, target_addr dest, const void *src, size_t len, enum align align);
#endif #endif

View File

@ -11,12 +11,7 @@ endif
CFLAGS=-Os -std=gnu99 -mcpu=cortex-m0 -mthumb -I../../../libopencm3/include CFLAGS=-Os -std=gnu99 -mcpu=cortex-m0 -mthumb -I../../../libopencm3/include
ASFLAGS=-mcpu=cortex-m3 -mthumb ASFLAGS=-mcpu=cortex-m3 -mthumb
all: lmi.stub stm32f4_x8.stub stm32f4_x32.stub stm32l4.stub nrf51.stub \ all: lmi.stub stm32l4.stub nrf51.stub efm32.stub
stm32f1.stub efm32.stub
stm32f1.o: CFLAGS += -DSTM32F1
stm32f4_x8.o: CFLAGS += -DSTM32F4
stm32f4_x32.o: CFLAGS += -DSTM32F4
%.o: %.c %.o: %.c
$(Q)echo " CC $<" $(Q)echo " CC $<"

View File

@ -1,40 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2015 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libopencm3/stm32/flash.h"
#include "stub.h"
#define SR_ERROR_MASK 0x14
void __attribute__((naked))
stm32f1_flash_write_stub(uint16_t *dest, uint16_t *src, uint32_t size)
{
for (int i; i < size; i += 2) {
FLASH_CR = FLASH_CR_PG;
*dest++ = *src++;
while (FLASH_SR & FLASH_SR_BSY)
;
}
if (FLASH_SR & SR_ERROR_MASK)
stub_exit(1);
stub_exit(0);
}

View File

@ -1 +0,0 @@
0x2300, 0x4C09, 0x4293, 0xD209, 0x2601, 0x4D08, 0x602E, 0x5ACD, 0x52C5, 0x6825, 0x07ED, 0xD4FC, 0x3302, 0xE7F2, 0x2314, 0x6822, 0x421A, 0xD000, 0xBE01, 0xBE00, 0x200C, 0x4002, 0x2010, 0x4002,

View File

@ -1,41 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2015 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libopencm3/stm32/flash.h"
#include "stub.h"
#define SR_ERROR_MASK 0xF2
void __attribute__((naked))
stm32f4_flash_write_x32_stub(uint32_t *dest, uint32_t *src, uint32_t size)
{
for (int i = 0; i < size; i += 4) {
FLASH_CR = FLASH_CR_PROGRAM_X32 | FLASH_CR_PG;
*dest++ = *src++;
__asm("dsb");
while (FLASH_SR & FLASH_SR_BSY)
;
}
if (FLASH_SR & SR_ERROR_MASK)
stub_exit(1);
stub_exit(0);
}

View File

@ -1 +0,0 @@
0x2300, 0x4C0A, 0x4293, 0xD20B, 0x4E09, 0x4D0A, 0x602E, 0x58CD, 0x50C5, 0xF3BF, 0x8F4F, 0x6825, 0x03ED, 0xD4FC, 0x3304, 0xE7F0, 0x23F2, 0x6822, 0x421A, 0xD000, 0xBE01, 0xBE00, 0x3C0C, 0x4002, 0x0201, 0x0000, 0x3C10, 0x4002,

View File

@ -1,44 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2017 Black Sphere Technologies Ltd.
* Written by Gordon Smith <gordonhj.smith@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libopencm3/stm32/flash.h"
#include "stub.h"
#define SR_ERROR_MASK 0xF2
void __attribute__((naked))
stm32f4_flash_write_x8_stub(uint32_t *dest, uint32_t *src, uint32_t size)
{
uint8_t *b_dest, *b_src;
b_dest = (void *)dest;
b_src = (void *)src;
for (int i = 0; i < size; i += 1) {
FLASH_CR = FLASH_CR_PROGRAM_X8 | FLASH_CR_PG;
*b_dest++ = *b_src++;
__asm("dsb");
while (FLASH_SR & FLASH_SR_BSY)
;
}
if (FLASH_SR & SR_ERROR_MASK)
stub_exit(1);
stub_exit(0);
}

View File

@ -1 +0,0 @@
0x2300, 0x4C0A, 0x4293, 0xD00B, 0x2601, 0x4D09, 0x602E, 0x5CCD, 0x54C5, 0xF3BF, 0x8F4F, 0x6825, 0x03ED, 0xD4FC, 0x3301, 0xE7F0, 0x23F2, 0x6822, 0x421A, 0xD000, 0xBE01, 0xBE00, 0x3C0C, 0x4002, 0x3C10, 0x4002,

View File

@ -1,53 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2015 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stub.h"
#include <stdint.h>
/* No STM32L4 definitions in libopencm3 yet */
#define FLASH_SR ((volatile uint32_t *) 0x40022010)
#define FLASH_SR_EOP (1 << 0)
#define SR_ERROR_MASK 0xC3FA
#define FLASH_SR_BSY (1 << 16)
#define FLASH_CR ((volatile uint32_t *) 0x40022014)
#define FLASH_CR_PG (1 << 0)
#define FLASH_CR_EOPIE (1 << 24)
#define FLASH_CR_ERRIE (1 << 25)
#define FLASH_SR_EOP (1 << 0)
void __attribute__((naked))
stm32l4_flash_write_stub(uint32_t *dest, uint32_t *src, uint32_t size)
{
if ((size & 7) || ((uint32_t)dest & 7))
stub_exit(1);
for (int i = 0; i < size; i += 8) {
*FLASH_CR = FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_PG;
*dest++ = *src++;
*dest++ = *src++;
__asm("dsb");
while (*FLASH_SR & FLASH_SR_BSY)
;
if ((*FLASH_SR & SR_ERROR_MASK) || !(*FLASH_SR & FLASH_SR_EOP))
stub_exit(1);
*FLASH_SR |= FLASH_SR_EOP;
}
*FLASH_CR = 0;
stub_exit(0);
}

View File

@ -1 +0,0 @@
0x1C04, 0x4314, 0x2300, 0x0764, 0xD011, 0xBE01, 0xE00F, 0x4C11, 0x6825, 0x03ED, 0xD4FB, 0x6826, 0x4D0F, 0x422E, 0xD115, 0x6825, 0x07ED, 0xD512, 0x2601, 0x6825, 0x3308, 0x4335, 0x6025, 0x4C0B, 0x4293, 0xD20C, 0x4D0A, 0x6025, 0x58CC, 0x50C4, 0x18CC, 0x6865, 0x18C4, 0x6065, 0xF3BF, 0x8F4F, 0xE7E1, 0xBE01, 0xE7EA, 0x2300, 0x6023, 0xBE00, 0x2010, 0x4002, 0xC3FA, 0x0000, 0x2014, 0x4002, 0x0001, 0x0300,

View File

@ -72,6 +72,7 @@ static int stm32f1_flash_write(struct target_flash *f,
#define FLASH_CR_OPTPG (1 << 4) #define FLASH_CR_OPTPG (1 << 4)
#define FLASH_CR_MER (1 << 2) #define FLASH_CR_MER (1 << 2)
#define FLASH_CR_PER (1 << 1) #define FLASH_CR_PER (1 << 1)
#define FLASH_CR_PG (1 << 0)
#define FLASH_OBR_RDPRT (1 << 1) #define FLASH_OBR_RDPRT (1 << 1)
@ -93,13 +94,6 @@ static int stm32f1_flash_write(struct target_flash *f,
#define FLASHSIZE 0x1FFFF7E0 #define FLASHSIZE 0x1FFFF7E0
#define FLASHSIZE_F0 0x1FFFF7CC #define FLASHSIZE_F0 0x1FFFF7CC
static const uint16_t stm32f1_flash_write_stub[] = {
#include "flashstub/stm32f1.stub"
};
#define SRAM_BASE 0x20000000
#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f1_flash_write_stub), 4)
static void stm32f1_add_flash(target *t, static void stm32f1_add_flash(target *t,
uint32_t addr, size_t length, size_t erasesize) uint32_t addr, size_t length, size_t erasesize)
{ {
@ -109,6 +103,7 @@ static void stm32f1_add_flash(target *t,
f->blocksize = erasesize; f->blocksize = erasesize;
f->erase = stm32f1_flash_erase; f->erase = stm32f1_flash_erase;
f->write = stm32f1_flash_write; f->write = stm32f1_flash_write;
f->buf_size = erasesize;
f->erased = 0xff; f->erased = 0xff;
target_add_flash(t, f); target_add_flash(t, f);
} }
@ -226,11 +221,24 @@ static int stm32f1_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len) target_addr dest, const void *src, size_t len)
{ {
target *t = f->t; target *t = f->t;
/* Write stub and data to target ram and set PC */ uint32_t sr;
target_mem_write(t, SRAM_BASE, stm32f1_flash_write_stub, target_mem_write32(t, FLASH_CR, FLASH_CR_PG);
sizeof(stm32f1_flash_write_stub)); cortexm_mem_write_sized(t, dest, src, len, ALIGN_HALFWORD);
target_mem_write(t, STUB_BUFFER_BASE, src, len); /* Read FLASH_SR to poll for BSY bit */
return cortexm_run_stub(t, SRAM_BASE, dest, STUB_BUFFER_BASE, len, 0); /* Wait for completion or an error */
do {
sr = target_mem_read32(t, FLASH_SR);
if(target_check_error(t)) {
DEBUG("stm32f1 flash write: comm error\n");
return -1;
}
} while (sr & FLASH_SR_BSY);
if (sr & SR_ERROR_MASK) {
DEBUG("stm32f1 flash write error 0x%" PRIx32 "\n", sr);
return -1;
}
return 0;
} }
static bool stm32f1_cmd_erase_mass(target *t) static bool stm32f1_cmd_erase_mass(target *t)

View File

@ -3,6 +3,8 @@
* *
* Copyright (C) 2011 Black Sphere Technologies Ltd. * Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz> * Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2017, 2018 Uwe Bonnes
* <bon@elektron.ikp.physik.tu-darmstadt.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -44,7 +46,7 @@ const struct command_s stm32f4_cmd_list[] = {
"Erase entire flash memory"}, "Erase entire flash memory"},
{"option", (cmd_handler)stm32f4_cmd_option, "Manipulate option bytes"}, {"option", (cmd_handler)stm32f4_cmd_option, "Manipulate option bytes"},
{"psize", (cmd_handler)stm32f4_cmd_psize, {"psize", (cmd_handler)stm32f4_cmd_psize,
"Configure flash write parallelism: (x8|x32(default))"}, "Configure flash write parallelism: (x8|x16|x32(default)|x64)"},
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };
@ -108,28 +110,13 @@ static int stm32f4_flash_write(struct target_flash *f,
#define DBG_WWDG_STOP (1 << 11) #define DBG_WWDG_STOP (1 << 11)
#define DBG_IWDG_STOP (1 << 12) #define DBG_IWDG_STOP (1 << 12)
/* This routine uses word access. Only usable on target voltage >2.7V */
static const uint16_t stm32f4_flash_write_x32_stub[] = {
#include "flashstub/stm32f4_x32.stub"
};
/* This routine uses byte access. Usable on target voltage <2.2V */
static const uint16_t stm32f4_flash_write_x8_stub[] = {
#include "flashstub/stm32f4_x8.stub"
};
#define SRAM_BASE 0x20000000
#define STUB_BUFFER_BASE \
ALIGN(SRAM_BASE + MAX(sizeof(stm32f4_flash_write_x8_stub), \
sizeof(stm32f4_flash_write_x32_stub)), 4)
#define AXIM_BASE 0x8000000 #define AXIM_BASE 0x8000000
#define ITCM_BASE 0x0200000 #define ITCM_BASE 0x0200000
struct stm32f4_flash { struct stm32f4_flash {
struct target_flash f; struct target_flash f;
enum align psize;
uint8_t base_sector; uint8_t base_sector;
uint8_t psize;
uint8_t bank_split; uint8_t bank_split;
}; };
@ -161,10 +148,11 @@ static void stm32f4_add_flash(target *t,
f->blocksize = blocksize; f->blocksize = blocksize;
f->erase = stm32f4_flash_erase; f->erase = stm32f4_flash_erase;
f->write = stm32f4_flash_write; f->write = stm32f4_flash_write;
f->buf_size = 1024;
f->erased = 0xff; f->erased = 0xff;
sf->base_sector = base_sector; sf->base_sector = base_sector;
sf->psize = 32;
sf->bank_split = split; sf->bank_split = split;
sf->psize = ALIGN_WORD;
target_add_flash(t, f); target_add_flash(t, f);
} }
@ -381,9 +369,15 @@ static int stm32f4_flash_erase(struct target_flash *f, target_addr addr,
uint8_t sector = sf->base_sector + (addr - f->start)/f->blocksize; uint8_t sector = sf->base_sector + (addr - f->start)/f->blocksize;
stm32f4_flash_unlock(t); stm32f4_flash_unlock(t);
enum align psize = ALIGN_WORD;
for (struct target_flash *f = t->flash; f; f = f->next) {
if (f->write == stm32f4_flash_write) {
psize = ((struct stm32f4_flash *)f)->psize;
}
}
while(len) { while(len) {
uint32_t cr = FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER | uint32_t cr = FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER |
(sector << 3); (psize * FLASH_CR_PSIZE16) | (sector << 3);
/* Flash page erase instruction */ /* Flash page erase instruction */
target_mem_write32(t, FLASH_CR, cr); target_mem_write32(t, FLASH_CR, cr);
/* write address to FMA */ /* write address to FMA */
@ -417,17 +411,27 @@ static int stm32f4_flash_write(struct target_flash *f,
if ((dest >= ITCM_BASE) && (dest < AXIM_BASE)) { if ((dest >= ITCM_BASE) && (dest < AXIM_BASE)) {
dest = AXIM_BASE + (dest - ITCM_BASE); dest = AXIM_BASE + (dest - ITCM_BASE);
} }
target *t = f->t;
uint32_t sr;
enum align psize = ((struct stm32f4_flash *)f)->psize;
target_mem_write32(t, FLASH_CR,
(psize * FLASH_CR_PSIZE16) | FLASH_CR_PG);
cortexm_mem_write_sized(t, dest, src, len, psize);
/* Read FLASH_SR to poll for BSY bit */
/* Wait for completion or an error */
do {
sr = target_mem_read32(t, FLASH_SR);
if(target_check_error(t)) {
DEBUG("stm32f4 flash write: comm error\n");
return -1;
}
} while (sr & FLASH_SR_BSY);
/* Write buffer to target ram call stub */ if (sr & SR_ERROR_MASK) {
if (((struct stm32f4_flash *)f)->psize == 32) DEBUG("stm32f4 flash write error 0x%" PRIx32 "\n", sr);
target_mem_write(f->t, SRAM_BASE, stm32f4_flash_write_x32_stub, return -1;
sizeof(stm32f4_flash_write_x32_stub)); }
else return 0;
target_mem_write(f->t, SRAM_BASE, stm32f4_flash_write_x8_stub,
sizeof(stm32f4_flash_write_x8_stub));
target_mem_write(f->t, STUB_BUFFER_BASE, src, len);
return cortexm_run_stub(f->t, SRAM_BASE, dest,
STUB_BUFFER_BASE, len, 0);
} }
static bool stm32f4_cmd_erase_mass(target *t) static bool stm32f4_cmd_erase_mass(target *t)
@ -665,22 +669,28 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[])
static bool stm32f4_cmd_psize(target *t, int argc, char *argv[]) static bool stm32f4_cmd_psize(target *t, int argc, char *argv[])
{ {
if (argc == 1) { if (argc == 1) {
uint8_t psize = 8; enum align psize = ALIGN_WORD;
for (struct target_flash *f = t->flash; f; f = f->next) { for (struct target_flash *f = t->flash; f; f = f->next) {
if (f->write == stm32f4_flash_write) { if (f->write == stm32f4_flash_write) {
psize = ((struct stm32f4_flash *)f)->psize; psize = ((struct stm32f4_flash *)f)->psize;
} }
} }
tc_printf(t, "Flash write parallelism: %s\n", tc_printf(t, "Flash write parallelism: %s\n",
psize == 32 ? "x32" : "x8"); psize == ALIGN_DWORD ? "x64" :
psize == ALIGN_WORD ? "x32" :
psize == ALIGN_HALFWORD ? "x16" : "x8");
} else { } else {
uint8_t psize; enum align psize;
if (!strcmp(argv[1], "x8")) { if (!strcmp(argv[1], "x8")) {
psize = 8; psize = ALIGN_BYTE;
} else if (!strcmp(argv[1], "x16")) {
psize = ALIGN_HALFWORD;
} else if (!strcmp(argv[1], "x32")) { } else if (!strcmp(argv[1], "x32")) {
psize = 32; psize = ALIGN_WORD;
} else if (!strcmp(argv[1], "x64")) {
psize = ALIGN_DWORD;
} else { } else {
tc_printf(t, "usage: monitor psize (x8|x32)\n"); tc_printf(t, "usage: monitor psize (x8|x16|x32|x32)\n");
return false; return false;
} }
for (struct target_flash *f = t->flash; f; f = f->next) { for (struct target_flash *f = t->flash; f; f = f->next) {

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2015, 2017 Uwe Bonnes * Copyright (C) 2015, 2017, 2018 Uwe Bonnes
* Written by Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de> * Written by Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -112,14 +112,6 @@ static const char stm32l4_driver_str[] = "STM32L4xx";
#define DBGMCU_IDCODE 0xE0042000 #define DBGMCU_IDCODE 0xE0042000
#define FLASH_SIZE_REG 0x1FFF75E0 #define FLASH_SIZE_REG 0x1FFF75E0
/* This routine is uses double word access.*/
static const uint16_t stm32l4_flash_write_stub[] = {
#include "flashstub/stm32l4.stub"
};
#define SRAM_BASE 0x20000000
#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32l4_flash_write_stub), 8)
struct stm32l4_flash { struct stm32l4_flash {
struct target_flash f; struct target_flash f;
uint32_t bank1_start; uint32_t bank1_start;
@ -258,12 +250,24 @@ static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t
static int stm32l4_flash_write(struct target_flash *f, static int stm32l4_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len) target_addr dest, const void *src, size_t len)
{ {
/* Write buffer to target ram call stub */ target *t = f->t;
target_mem_write(f->t, SRAM_BASE, stm32l4_flash_write_stub, target_mem_write32(t, FLASH_CR, FLASH_CR_PG);
sizeof(stm32l4_flash_write_stub)); target_mem_write(t, dest, src, len);
target_mem_write(f->t, STUB_BUFFER_BASE, src, len); /* Wait for completion or an error */
return cortexm_run_stub(f->t, SRAM_BASE, dest, uint32_t sr;
STUB_BUFFER_BASE, len, 0); do {
sr = target_mem_read32(t, FLASH_SR);
if (target_check_error(t)) {
DEBUG("stm32l4 flash write: comm error\n");
return -1;
}
} while (sr & FLASH_SR_BSY);
if(sr & FLASH_SR_ERROR_MASK) {
DEBUG("stm32l4 flash write error: sr 0x%" PRIu32 "\n", sr);
return -1;
}
return 0;
} }
static bool stm32l4_cmd_erase(target *t, uint32_t action) static bool stm32l4_cmd_erase(target *t, uint32_t action)