kopia lustrzana https://github.com/stlink-org/stlink
Add simple read/write support for STM32WB55 chips. (#786)
* Add simple read/write support for STM32WB55 chips. * Clean up and unify G0/WB erase/program operations.pull/789/head
rodzic
c6836b4ac9
commit
4ff515ef68
|
@ -77,6 +77,7 @@ extern "C" {
|
|||
STLINK_FLASH_TYPE_L4,
|
||||
STLINK_FLASH_TYPE_F1_XL,
|
||||
STLINK_FLASH_TYPE_G0,
|
||||
STLINK_FLASH_TYPE_WB
|
||||
};
|
||||
|
||||
struct stlink_reg {
|
||||
|
|
|
@ -71,7 +71,8 @@ enum stlink_stm32_chipids {
|
|||
STLINK_CHIPID_STM32_F410 = 0x458,
|
||||
STLINK_CHIPID_STM32_F413 = 0x463,
|
||||
STLINK_CHIPID_STM32_L4RX = 0x470, // taken from the STM32L4R9I-DISCO board
|
||||
STLINK_CHIPID_STM32_G0X1 = 0x460
|
||||
STLINK_CHIPID_STM32_G0X1 = 0x460,
|
||||
STLINK_CHIPID_STM32_WB55 = 0x495
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
11
src/chipid.c
11
src/chipid.c
|
@ -518,6 +518,17 @@ static const struct stlink_chipid_params devices[] = {
|
|||
.bootrom_base = 0x1fff0000,
|
||||
.bootrom_size = 0x7800 // 30K (table 2)
|
||||
},
|
||||
{
|
||||
// STM32WB55 (from RM0434)
|
||||
.chip_id = STLINK_CHIPID_STM32_WB55,
|
||||
.description = "WB55 device",
|
||||
.flash_type = STLINK_FLASH_TYPE_WB,
|
||||
.flash_size_reg = 0x1FFF75E0,
|
||||
.flash_pagesize = 0x1000, // 4K
|
||||
.sram_size = 0x40000,
|
||||
.bootrom_base = 0x1fff0000, // See the memory map
|
||||
.bootrom_size = 0x7000
|
||||
},
|
||||
{
|
||||
// unknown
|
||||
.chip_id = STLINK_CHIPID_UNKNOWN,
|
||||
|
|
243
src/common.c
243
src/common.c
|
@ -103,7 +103,37 @@
|
|||
#define STM32G0_FLASH_CR_ERRIE 25 /* Error interrupt enable */
|
||||
#define STM32G0_FLASH_CR_OBL_LAUNCH 27 /* Forces the option byte loading */
|
||||
#define STM32G0_FLASH_CR_OPTLOCK 30 /* Options Lock */
|
||||
#define STM32G0_FLASH_CR_LOCK 31 /* FLASH_CR Lock*/
|
||||
#define STM32G0_FLASH_CR_LOCK 31 /* FLASH_CR Lock */
|
||||
// GO FLASH status register
|
||||
#define STM32G0_FLASH_SR_BSY 16 /* FLASH_SR Busy */
|
||||
|
||||
// WB (RM0434)
|
||||
#define STM32WB_FLASH_REGS_ADDR ((uint32_t)0x58004000)
|
||||
#define STM32WB_FLASH_ACR (STM32WB_FLASH_REGS_ADDR + 0x00)
|
||||
#define STM32WB_FLASH_KEYR (STM32WB_FLASH_REGS_ADDR + 0x08)
|
||||
#define STM32WB_FLASH_OPT_KEYR (STM32WB_FLASH_REGS_ADDR + 0x0C)
|
||||
#define STM32WB_FLASH_SR (STM32WB_FLASH_REGS_ADDR + 0x10)
|
||||
#define STM32WB_FLASH_CR (STM32WB_FLASH_REGS_ADDR + 0x14)
|
||||
#define STM32WB_FLASH_ECCR (STM32WB_FLASH_REGS_ADDR + 0x18)
|
||||
#define STM32WB_FLASH_OPTR (STM32WB_FLASH_REGS_ADDR + 0x20)
|
||||
#define STM32WB_FLASH_PCROP1ASR (STM32WB_FLASH_REGS_ADDR + 0x24)
|
||||
#define STM32WB_FLASH_PCROP1AER (STM32WB_FLASH_REGS_ADDR + 0x28)
|
||||
#define STM32WB_FLASH_WRP1AR (STM32WB_FLASH_REGS_ADDR + 0x2C)
|
||||
#define STM32WB_FLASH_WRP1BR (STM32WB_FLASH_REGS_ADDR + 0x30)
|
||||
#define STM32WB_FLASH_PCROP1BSR (STM32WB_FLASH_REGS_ADDR + 0x34)
|
||||
#define STM32WB_FLASH_PCROP1BER (STM32WB_FLASH_REGS_ADDR + 0x38)
|
||||
#define STM32WB_FLASH_IPCCBR (STM32WB_FLASH_REGS_ADDR + 0x3C)
|
||||
#define STM32WB_FLASH_C2ACR (STM32WB_FLASH_REGS_ADDR + 0x5C)
|
||||
#define STM32WB_FLASH_C2SR (STM32WB_FLASH_REGS_ADDR + 0x60)
|
||||
#define STM32WB_FLASH_C2CR (STM32WB_FLASH_REGS_ADDR + 0x64)
|
||||
#define STM32WB_FLASH_SFR (STM32WB_FLASH_REGS_ADDR + 0x80)
|
||||
#define STM32WB_FLASH_SRRVR (STM32WB_FLASH_REGS_ADDR + 0x84)
|
||||
|
||||
// WB Flash control register.
|
||||
#define STM32WB_FLASH_CR_STRT (16) /* FLASH_CR Start */
|
||||
#define STM32WB_FLASH_CR_LOCK (31) /* FLASH_CR Lock */
|
||||
// WB Flash status register.
|
||||
#define STM32WB_FLASH_SR_BSY (16) /* FLASH_SR Busy */
|
||||
|
||||
//32L4 register base is at FLASH_REGS_ADDR (0x40022000)
|
||||
#define STM32L4_FLASH_KEYR (FLASH_REGS_ADDR + 0x08)
|
||||
|
@ -219,6 +249,10 @@ static inline uint32_t read_flash_cr(stlink_t *sl) {
|
|||
reg = FLASH_F4_CR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_L4)
|
||||
reg = STM32L4_FLASH_CR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_G0)
|
||||
reg = STM32G0_FLASH_CR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB)
|
||||
reg = STM32WB_FLASH_CR;
|
||||
else
|
||||
reg = FLASH_CR;
|
||||
|
||||
|
@ -247,6 +281,10 @@ static inline unsigned int is_flash_locked(stlink_t *sl) {
|
|||
cr_lock_shift = FLASH_F4_CR_LOCK;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_L4)
|
||||
cr_lock_shift = STM32L4_FLASH_CR_LOCK;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_G0)
|
||||
cr_lock_shift = STM32G0_FLASH_CR_LOCK;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB)
|
||||
cr_lock_shift = STM32WB_FLASH_CR_LOCK;
|
||||
else
|
||||
cr_lock_shift = FLASH_CR_LOCK;
|
||||
|
||||
|
@ -264,6 +302,10 @@ static void unlock_flash(stlink_t *sl) {
|
|||
key_reg = FLASH_F4_KEYR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_L4)
|
||||
key_reg = STM32L4_FLASH_KEYR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_G0)
|
||||
key_reg = STM32G0_FLASH_KEYR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB)
|
||||
key_reg = STM32WB_FLASH_KEYR;
|
||||
else
|
||||
key_reg = FLASH_KEYR;
|
||||
|
||||
|
@ -299,6 +341,12 @@ static void lock_flash(stlink_t *sl) {
|
|||
} else if (sl->flash_type == STLINK_FLASH_TYPE_L4) {
|
||||
cr_reg = STM32L4_FLASH_CR;
|
||||
cr_lock_shift = STM32L4_FLASH_CR_LOCK;
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
cr_reg = STM32G0_FLASH_CR;
|
||||
cr_lock_shift = STM32G0_FLASH_CR_LOCK;
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_WB) {
|
||||
cr_reg = STM32WB_FLASH_CR;
|
||||
cr_lock_shift = STM32WB_FLASH_CR_LOCK;
|
||||
} else {
|
||||
cr_reg = FLASH_CR;
|
||||
cr_lock_shift = FLASH_CR_LOCK;
|
||||
|
@ -326,6 +374,12 @@ static void set_flash_cr_pg(stlink_t *sl) {
|
|||
cr_reg = STM32L4_FLASH_CR;
|
||||
x &= ~STM32L4_FLASH_CR_OPBITS;
|
||||
x |= 1 << STM32L4_FLASH_CR_PG;
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
cr_reg = STM32G0_FLASH_CR;
|
||||
x |= (1 << FLASH_CR_PG);
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_WB) {
|
||||
cr_reg = STM32WB_FLASH_CR;
|
||||
x |= (1 << FLASH_CR_PG);
|
||||
} else {
|
||||
cr_reg = FLASH_CR;
|
||||
x = 1 << FLASH_CR_PG;
|
||||
|
@ -341,6 +395,10 @@ static void clear_flash_cr_pg(stlink_t *sl) {
|
|||
cr_reg = FLASH_F4_CR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_L4)
|
||||
cr_reg = STM32L4_FLASH_CR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_G0)
|
||||
cr_reg = STM32G0_FLASH_CR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB)
|
||||
cr_reg = STM32WB_FLASH_CR;
|
||||
else
|
||||
cr_reg = FLASH_CR;
|
||||
|
||||
|
@ -349,8 +407,18 @@ static void clear_flash_cr_pg(stlink_t *sl) {
|
|||
}
|
||||
|
||||
static void set_flash_cr_per(stlink_t *sl) {
|
||||
const uint32_t n = 1 << FLASH_CR_PER;
|
||||
stlink_write_debug32(sl, FLASH_CR, n);
|
||||
uint32_t cr_reg, val;
|
||||
|
||||
if (sl->flash_type == STLINK_FLASH_TYPE_G0)
|
||||
cr_reg = STM32G0_FLASH_CR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB)
|
||||
cr_reg = STM32WB_FLASH_CR;
|
||||
else
|
||||
cr_reg = FLASH_CR;
|
||||
|
||||
stlink_read_debug32(sl, cr_reg, &val);
|
||||
val |= (1 << FLASH_CR_PER);
|
||||
stlink_write_debug32(sl, cr_reg, val);
|
||||
}
|
||||
|
||||
static void set_flash_cr2_per(stlink_t *sl) {
|
||||
|
@ -358,9 +426,18 @@ static void set_flash_cr2_per(stlink_t *sl) {
|
|||
stlink_write_debug32(sl, FLASH_CR2, n);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) clear_flash_cr_per(stlink_t *sl) {
|
||||
static void clear_flash_cr_per(stlink_t *sl) {
|
||||
uint32_t cr_reg;
|
||||
|
||||
if (sl->flash_type == STLINK_FLASH_TYPE_G0)
|
||||
cr_reg = STM32G0_FLASH_CR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB)
|
||||
cr_reg = STM32WB_FLASH_CR;
|
||||
else
|
||||
cr_reg = FLASH_CR;
|
||||
|
||||
const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PER);
|
||||
stlink_write_debug32(sl, FLASH_CR, n);
|
||||
stlink_write_debug32(sl, cr_reg, n);
|
||||
}
|
||||
|
||||
static void set_flash_cr_mer(stlink_t *sl, bool v) {
|
||||
|
@ -374,6 +451,14 @@ static void set_flash_cr_mer(stlink_t *sl, bool v) {
|
|||
cr_reg = STM32L4_FLASH_CR;
|
||||
cr_mer = (1 << STM32L4_FLASH_CR_MER1) | (1 << STM32L4_FLASH_CR_MER2);
|
||||
cr_pg = 1 << STM32L4_FLASH_CR_PG;
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
cr_reg = STM32G0_FLASH_CR;
|
||||
cr_mer = (1 << FLASH_CR_MER);
|
||||
cr_pg = (1 << FLASH_CR_PG);
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_WB) {
|
||||
cr_reg = STM32WB_FLASH_CR;
|
||||
cr_mer = (1 << FLASH_CR_MER);
|
||||
cr_pg = (1 << FLASH_CR_PG);
|
||||
} else {
|
||||
cr_reg = FLASH_CR;
|
||||
cr_mer = 1 << FLASH_CR_MER;
|
||||
|
@ -436,6 +521,12 @@ static void set_flash_cr_strt(stlink_t *sl) {
|
|||
} else if (sl->flash_type == STLINK_FLASH_TYPE_L4) {
|
||||
cr_reg = STM32L4_FLASH_CR;
|
||||
cr_strt = 1 << STM32L4_FLASH_CR_STRT;
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
cr_reg = STM32G0_FLASH_CR;
|
||||
cr_strt = 1 << STM32G0_FLASH_CR_STRT;
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_WB) {
|
||||
cr_reg = STM32WB_FLASH_CR;
|
||||
cr_strt = 1 << STM32WB_FLASH_CR_STRT;
|
||||
} else {
|
||||
cr_reg = FLASH_CR;
|
||||
cr_strt = 1 << FLASH_CR_STRT;
|
||||
|
@ -461,6 +552,10 @@ static inline uint32_t read_flash_sr(stlink_t *sl) {
|
|||
sr_reg = FLASH_F4_SR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_L4)
|
||||
sr_reg = STM32L4_FLASH_SR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_G0)
|
||||
sr_reg = STM32G0_FLASH_SR;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB)
|
||||
sr_reg = STM32WB_FLASH_SR;
|
||||
else
|
||||
sr_reg = FLASH_SR;
|
||||
|
||||
|
@ -483,6 +578,10 @@ static inline unsigned int is_flash_busy(stlink_t *sl) {
|
|||
sr_busy_shift = FLASH_F4_SR_BSY;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_L4)
|
||||
sr_busy_shift = STM32L4_FLASH_SR_BSY;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_G0)
|
||||
sr_busy_shift = STM32G0_FLASH_SR_BSY;
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB)
|
||||
sr_busy_shift = STM32WB_FLASH_SR_BSY;
|
||||
else
|
||||
sr_busy_shift = FLASH_SR_BSY;
|
||||
|
||||
|
@ -1646,47 +1745,39 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
|
|||
stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val);
|
||||
val |= (1 << 0) | (1 << 1) | (1 << 2);
|
||||
stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val);
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_WB ||
|
||||
sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
uint32_t val;
|
||||
/* check if the locks are set */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
if ((val & (1<<31))) {
|
||||
/* disable flash write protection. */
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_KEYR, 0x45670123);
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_KEYR, 0xCDEF89AB);
|
||||
/* check that the lock is no longer set. */
|
||||
// Wait for any ongoing Flash operation to finish.
|
||||
wait_flash_busy(sl);
|
||||
// Unlock Flash if necessary.
|
||||
unlock_flash_if(sl);
|
||||
// Set the 'enable Flash erase' bit.
|
||||
set_flash_cr_per(sl);
|
||||
|
||||
// Set the page to erase.
|
||||
if (sl->flash_type == STLINK_FLASH_TYPE_WB) {
|
||||
uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / sl->flash_pgsz);
|
||||
stlink_read_debug32(sl, STM32WB_FLASH_CR, &val);
|
||||
// sec 3.10.5 - PNB[7:0] is offset by 3.
|
||||
val |= ((flash_page & 0xFF) << 3);
|
||||
stlink_write_debug32(sl, STM32WB_FLASH_CR, val);
|
||||
} else if (sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / sl->flash_pgsz);
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
if ((val & (1 << 31))) {
|
||||
WLOG("pecr.pelock not clear (%#x)\n", val);
|
||||
return -1;
|
||||
}
|
||||
// sec 3.7.5 - PNB[5:0] is offset by 3. PER is 0x2.
|
||||
val |= ((flash_page & 0x3F) << 3);
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
}
|
||||
/* Set PER (erase) bit. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
val |= 0x00000002;
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
/* Set the page to erase. */
|
||||
uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / sl->flash_pgsz);
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
// sec 3.7.5 - PNB[5:0] is offset by 3. PER is 0x2.
|
||||
val = ((flash_page & 0x3F) << 3) | (2);
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
/* Set the 'start' bit. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
val |= (1 << 16);
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
/* Wait for 'busy' bit in FLASH_SR to clear. */
|
||||
do {
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_SR, &val);
|
||||
} while ((val & (1 << 16)) != 0);
|
||||
/* Clear PER ('erase enable') bit. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
val &= ~(0x00000002);
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
/* Re-lock the flash. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
val |= 0x80000000;
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
|
||||
// Set the 'start operation' bit.
|
||||
set_flash_cr_strt(sl);
|
||||
// Wait for the 'busy' bit to clear.
|
||||
wait_flash_busy(sl);
|
||||
// Clear the 'enable page erase' bit.
|
||||
clear_flash_cr_per(sl);
|
||||
// Re-lock the flash.
|
||||
lock_flash(sl);
|
||||
} else if ((sl->flash_type == STLINK_FLASH_TYPE_F0) || ((sl->flash_type == STLINK_FLASH_TYPE_F1_XL) && (flashaddr < FLASH_BANK2_START_ADDR))) {
|
||||
/* wait for ongoing op to finish */
|
||||
wait_flash_busy(sl);
|
||||
|
@ -1740,8 +1831,8 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
|
|||
}
|
||||
|
||||
int stlink_erase_flash_mass(stlink_t *sl) {
|
||||
/* TODO: User MER bit to mass-erase G0 series. */
|
||||
if (sl->flash_type == STLINK_FLASH_TYPE_L0 || sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
/* TODO: User MER bit to mass-erase G0, WB series. */
|
||||
if (sl->flash_type == STLINK_FLASH_TYPE_L0 || sl->flash_type == STLINK_FLASH_TYPE_G0 || sl->flash_type == STLINK_FLASH_TYPE_WB) {
|
||||
/* erase each page */
|
||||
int i = 0, num_pages = (int) sl->flash_size/sl->flash_pgsz;
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
|
@ -2026,27 +2117,20 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
lock_flash(sl);
|
||||
|
||||
} //STM32F4END
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
uint32_t val;
|
||||
/* Unlock flash. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
if ((val & (1<<31))) {
|
||||
/* disable flash write protection. */
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_KEYR, 0x45670123);
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_KEYR, 0xCDEF89AB);
|
||||
/* check that the lock is no longer set. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
if ((val & (1 << 31))) {
|
||||
WLOG("pecr.pelock not clear (%#x)\n", val);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Set PG 'allow programming' bit. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
val |= 0x00000001;
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
/* Write all words. */
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_WB ||
|
||||
sl->flash_type == STLINK_FLASH_TYPE_G0) {
|
||||
fprintf(stdout, "Writing\r\n");
|
||||
fflush(stdout);
|
||||
// Wait for any ongoing operations to finish.
|
||||
wait_flash_busy(sl);
|
||||
// Unlock flash if necessary.
|
||||
unlock_flash_if(sl);
|
||||
// Set PG 'allow programming' bit.
|
||||
set_flash_cr_pg(sl);
|
||||
// Write all words.
|
||||
off = 0;
|
||||
fprintf(stdout, "Starting %3u page write\r\n", (unsigned int)(len/sl->flash_pgsz));
|
||||
fflush(stdout);
|
||||
for ( ; off < len; off += sizeof(uint32_t)) {
|
||||
uint32_t data;
|
||||
if (off > 254)
|
||||
|
@ -2060,29 +2144,20 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
|
|||
}
|
||||
write_uint32((unsigned char*) &data, *(uint32_t*) (base + off));
|
||||
stlink_write_debug32(sl, addr + (uint32_t) off, data);
|
||||
/* Wait for 'busy' bit in FLASH_SR to clear. */
|
||||
do {
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_SR, &val);
|
||||
} while ((val & (1 << 16)) != 0);
|
||||
// Wait for 'busy' bit in FLASH_SR to clear.
|
||||
wait_flash_busy(sl);
|
||||
}
|
||||
/* Do we need a dummy write? See sec 3.3.8 of RM0444. */
|
||||
/* (Flash writes happen 2 words at a time.) */
|
||||
// (Flash writes happen 2 words at a time.)
|
||||
if ((off / sizeof(uint32_t)) % 2 != 0) {
|
||||
/* Write a single word of zeros. */
|
||||
// Write a single word of zeros.
|
||||
stlink_write_debug32(sl, addr + (uint32_t) off, 0);
|
||||
/* Wait for 'busy' bit in FLASH_SR to clear. */
|
||||
do {
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_SR, &val);
|
||||
} while ((val & (1 << 16)) != 0);
|
||||
// Wait for 'busy' bit in FLASH_SR to clear.
|
||||
wait_flash_busy(sl);
|
||||
}
|
||||
/* Reset PG bit. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
val &= ~(0x00000001);
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
/* Re-lock flash. */
|
||||
stlink_read_debug32(sl, STM32G0_FLASH_CR, &val);
|
||||
val |= 0x80000000;
|
||||
stlink_write_debug32(sl, STM32G0_FLASH_CR, val);
|
||||
// Reset PG bit.
|
||||
clear_flash_cr_pg(sl);
|
||||
// Re-lock flash.
|
||||
lock_flash(sl);
|
||||
}
|
||||
else if (sl->flash_type == STLINK_FLASH_TYPE_L0) {
|
||||
/* use fast word write. todo: half page. */
|
||||
|
|
Ładowanie…
Reference in New Issue