kopia lustrzana https://github.com/stlink-org/stlink
Merge pull request #1218 from hydroconstructor/common-c-refactor
Refactoring for sourcefile 'common.c'pull/1220/head
commit
849503b76b
|
@ -110,6 +110,8 @@ add_subdirectory(inc)
|
|||
set(STLINK_HEADERS
|
||||
inc/backend.h
|
||||
inc/stlink.h
|
||||
src/common_flash.h
|
||||
src/calculate.h
|
||||
src/stlink-lib/commands.h
|
||||
src/stlink-lib/libusb_settings.h
|
||||
src/stlink-lib/reg.h
|
||||
|
@ -123,7 +125,13 @@ set(STLINK_HEADERS
|
|||
)
|
||||
|
||||
set(STLINK_SOURCE
|
||||
src/read_write.c
|
||||
src/common.c
|
||||
src/option_bytes.c
|
||||
src/common_flash.c
|
||||
src/map_file.c
|
||||
src/flashloader.c
|
||||
src/calculate.c
|
||||
src/stlink-lib/chipid.c
|
||||
src/stlink-lib/flash_loader.c
|
||||
src/stlink-lib/logging.c
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/*
|
||||
* File: stlink.h
|
||||
*
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "stm32.h"
|
||||
#include "stm32flash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -274,7 +276,7 @@ int stlink_mwrite_sram(stlink_t *sl, uint8_t* data, uint32_t length, stm32_addr_
|
|||
int stlink_fwrite_sram(stlink_t *sl, const char* path, stm32_addr_t addr);
|
||||
int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, uint32_t length);
|
||||
|
||||
int stlink_chip_id(stlink_t *sl, uint32_t *chip_id);
|
||||
//int stlink_chip_id(stlink_t *sl, uint32_t *chip_id);
|
||||
int stlink_cpu_id(stlink_t *sl, cortex_m3_cpuid_t *cpuid);
|
||||
|
||||
int stlink_erase_flash_page(stlink_t* sl, stm32_addr_t flashaddr);
|
||||
|
@ -282,7 +284,7 @@ uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr);
|
|||
int stlink_check_address_range_validity(stlink_t *sl, stm32_addr_t addr, size_t size);
|
||||
int stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr);
|
||||
uint16_t read_uint16(const unsigned char *c, const int pt);
|
||||
void stlink_core_stat(stlink_t *sl);
|
||||
//void stlink_core_stat(stlink_t *sl);
|
||||
void stlink_print_data(stlink_t *sl);
|
||||
unsigned int is_bigendian(void);
|
||||
uint32_t read_uint32(const unsigned char *c, const int pt);
|
||||
|
|
334
inc/stm32.h
334
inc/stm32.h
|
@ -155,340 +155,6 @@ enum stm32_chipids {
|
|||
#define STM32_F1_FLASH_BANK2_BASE ((uint32_t)0x08080000)
|
||||
#define STM32_H7_FLASH_BANK2_BASE ((uint32_t)0x08100000)
|
||||
|
||||
/* stm32f FPEC flash controller interface, pm0063 manual */
|
||||
// STM32F05x is identical, based on RM0091 (DM00031936, Doc ID 018940 Rev 2, August 2012)
|
||||
#define FLASH_REGS_ADDR 0x40022000
|
||||
#define FLASH_REGS_SIZE 0x28
|
||||
|
||||
#define FLASH_ACR (FLASH_REGS_ADDR + 0x00)
|
||||
#define FLASH_KEYR (FLASH_REGS_ADDR + 0x04)
|
||||
#define FLASH_OPTKEYR (FLASH_REGS_ADDR + 0x08)
|
||||
#define FLASH_SR (FLASH_REGS_ADDR + 0x0c)
|
||||
#define FLASH_CR (FLASH_REGS_ADDR + 0x10)
|
||||
#define FLASH_AR (FLASH_REGS_ADDR + 0x14)
|
||||
#define FLASH_OBR (FLASH_REGS_ADDR + 0x1c)
|
||||
#define FLASH_WRPR (FLASH_REGS_ADDR + 0x20)
|
||||
|
||||
// STM32F10x_XL has two flash memory banks with separate registers to control
|
||||
// the second bank.
|
||||
#define FLASH_KEYR2 (FLASH_REGS_ADDR + 0x44)
|
||||
#define FLASH_SR2 (FLASH_REGS_ADDR + 0x4c)
|
||||
#define FLASH_CR2 (FLASH_REGS_ADDR + 0x50)
|
||||
#define FLASH_AR2 (FLASH_REGS_ADDR + 0x54)
|
||||
|
||||
// For STM32F05x, the RDPTR_KEY may be wrong, but as it is not used anywhere...
|
||||
#define FLASH_RDPTR_KEY 0x00a5
|
||||
#define FLASH_KEY1 0x45670123
|
||||
#define FLASH_KEY2 0xcdef89ab
|
||||
|
||||
#define FLASH_L0_PRGKEY1 0x8c9daebf
|
||||
#define FLASH_L0_PRGKEY2 0x13141516
|
||||
|
||||
#define FLASH_L0_PEKEY1 0x89abcdef
|
||||
#define FLASH_L0_PEKEY2 0x02030405
|
||||
|
||||
#define FLASH_OPTKEY1 0x08192A3B
|
||||
#define FLASH_OPTKEY2 0x4C5D6E7F
|
||||
|
||||
#define FLASH_F0_OPTKEY1 0x45670123
|
||||
#define FLASH_F0_OPTKEY2 0xCDEF89AB
|
||||
|
||||
#define FLASH_L0_OPTKEY1 0xFBEAD9C8
|
||||
#define FLASH_L0_OPTKEY2 0x24252627
|
||||
|
||||
#define FLASH_SR_BSY 0
|
||||
#define FLASH_SR_PG_ERR 2
|
||||
#define FLASH_SR_WRPRT_ERR 4
|
||||
#define FLASH_SR_EOP 5
|
||||
|
||||
#define FLASH_SR_ERROR_MASK ((1 << FLASH_SR_PG_ERR) | (1 << FLASH_SR_WRPRT_ERR))
|
||||
|
||||
#define FLASH_CR_PG 0
|
||||
#define FLASH_CR_PER 1
|
||||
#define FLASH_CR_MER 2
|
||||
#define FLASH_CR_OPTPG 4
|
||||
#define FLASH_CR_OPTER 5
|
||||
#define FLASH_CR_STRT 6
|
||||
#define FLASH_CR_LOCK 7
|
||||
#define FLASH_CR_OPTWRE 9
|
||||
#define FLASH_CR_OBL_LAUNCH 13
|
||||
|
||||
#define STM32L_FLASH_REGS_ADDR ((uint32_t)0x40023c00)
|
||||
#define STM32L_FLASH_ACR (STM32L_FLASH_REGS_ADDR + 0x00)
|
||||
#define STM32L_FLASH_PECR (STM32L_FLASH_REGS_ADDR + 0x04)
|
||||
#define STM32L_FLASH_PDKEYR (STM32L_FLASH_REGS_ADDR + 0x08)
|
||||
#define STM32L_FLASH_PEKEYR (STM32L_FLASH_REGS_ADDR + 0x0c)
|
||||
#define STM32L_FLASH_PRGKEYR (STM32L_FLASH_REGS_ADDR + 0x10)
|
||||
#define STM32L_FLASH_OPTKEYR (STM32L_FLASH_REGS_ADDR + 0x14)
|
||||
#define STM32L_FLASH_SR (STM32L_FLASH_REGS_ADDR + 0x18)
|
||||
#define STM32L_FLASH_OBR (STM32L_FLASH_REGS_ADDR + 0x1c)
|
||||
#define STM32L_FLASH_WRPR (STM32L_FLASH_REGS_ADDR + 0x20)
|
||||
#define FLASH_L1_FPRG 10
|
||||
#define FLASH_L1_PROG 3
|
||||
|
||||
// Flash registers common to STM32G0 and STM32G4 series.
|
||||
#define STM32Gx_FLASH_REGS_ADDR ((uint32_t)0x40022000)
|
||||
#define STM32Gx_FLASH_ACR (STM32Gx_FLASH_REGS_ADDR + 0x00)
|
||||
#define STM32Gx_FLASH_KEYR (STM32Gx_FLASH_REGS_ADDR + 0x08)
|
||||
#define STM32Gx_FLASH_OPTKEYR (STM32Gx_FLASH_REGS_ADDR + 0x0c)
|
||||
#define STM32Gx_FLASH_SR (STM32Gx_FLASH_REGS_ADDR + 0x10)
|
||||
#define STM32Gx_FLASH_CR (STM32Gx_FLASH_REGS_ADDR + 0x14)
|
||||
#define STM32Gx_FLASH_ECCR (STM32Gx_FLASH_REGS_ADDR + 0x18)
|
||||
#define STM32Gx_FLASH_OPTR (STM32Gx_FLASH_REGS_ADDR + 0x20)
|
||||
|
||||
// G0 (RM0444 Table 1, sec 3.7)
|
||||
// Mostly the same as G4 chips, but the notation
|
||||
// varies a bit after the 'OPTR' register.
|
||||
#define STM32G0_FLASH_REGS_ADDR (STM32Gx_FLASH_REGS_ADDR)
|
||||
#define STM32G0_FLASH_PCROP1ASR (STM32G0_FLASH_REGS_ADDR + 0x24)
|
||||
#define STM32G0_FLASH_PCROP1AER (STM32G0_FLASH_REGS_ADDR + 0x28)
|
||||
#define STM32G0_FLASH_WRP1AR (STM32G0_FLASH_REGS_ADDR + 0x2C)
|
||||
#define STM32G0_FLASH_WRP1BR (STM32G0_FLASH_REGS_ADDR + 0x30)
|
||||
#define STM32G0_FLASH_PCROP1BSR (STM32G0_FLASH_REGS_ADDR + 0x34)
|
||||
#define STM32G0_FLASH_PCROP1BER (STM32G0_FLASH_REGS_ADDR + 0x38)
|
||||
#define STM32G0_FLASH_SECR (STM32G0_FLASH_REGS_ADDR + 0x80)
|
||||
|
||||
// G4 (RM0440 Table 17, sec 3.7.19)
|
||||
// Mostly the same as STM32G0 chips, but there are a few extra
|
||||
// registers because 'cat 3' devices can have two Flash banks.
|
||||
#define STM32G4_FLASH_REGS_ADDR (STM32Gx_FLASH_REGS_ADDR)
|
||||
#define STM32G4_FLASH_PDKEYR (STM32G4_FLASH_REGS_ADDR + 0x04)
|
||||
#define STM32G4_FLASH_PCROP1SR (STM32G4_FLASH_REGS_ADDR + 0x24)
|
||||
#define STM32G4_FLASH_PCROP1ER (STM32G4_FLASH_REGS_ADDR + 0x28)
|
||||
#define STM32G4_FLASH_WRP1AR (STM32G4_FLASH_REGS_ADDR + 0x2C)
|
||||
#define STM32G4_FLASH_WRP1BR (STM32G4_FLASH_REGS_ADDR + 0x30)
|
||||
#define STM32G4_FLASH_PCROP2SR (STM32G4_FLASH_REGS_ADDR + 0x44)
|
||||
#define STM32G4_FLASH_PCROP2ER (STM32G4_FLASH_REGS_ADDR + 0x48)
|
||||
#define STM32G4_FLASH_WRP2AR (STM32G4_FLASH_REGS_ADDR + 0x4C)
|
||||
#define STM32G4_FLASH_WRP2BR (STM32G4_FLASH_REGS_ADDR + 0x50)
|
||||
#define STM32G4_FLASH_SEC1R (STM32G4_FLASH_REGS_ADDR + 0x70)
|
||||
#define STM32G4_FLASH_SEC2R (STM32G4_FLASH_REGS_ADDR + 0x74)
|
||||
|
||||
// G0/G4 FLASH control register
|
||||
#define STM32Gx_FLASH_CR_PG (0) /* Program */
|
||||
#define STM32Gx_FLASH_CR_PER (1) /* Page erase */
|
||||
#define STM32Gx_FLASH_CR_MER1 (2) /* Mass erase */
|
||||
#define STM32Gx_FLASH_CR_PNB (3) /* Page number */
|
||||
#define STM32G0_FLASH_CR_PNG_LEN (5) /* STM32G0: 5 page number bits */
|
||||
#define STM32G4_FLASH_CR_PNG_LEN (7) /* STM32G4: 7 page number bits */
|
||||
#define STM32Gx_FLASH_CR_MER2 (15) /* Mass erase (2nd bank)*/
|
||||
#define STM32Gx_FLASH_CR_STRT (16) /* Start */
|
||||
#define STM32Gx_FLASH_CR_OPTSTRT \
|
||||
(17) /* Start of modification of option bytes */
|
||||
#define STM32Gx_FLASH_CR_FSTPG (18) /* Fast programming */
|
||||
#define STM32Gx_FLASH_CR_EOPIE (24) /* End of operation interrupt enable */
|
||||
#define STM32Gx_FLASH_CR_ERRIE (25) /* Error interrupt enable */
|
||||
#define STM32Gx_FLASH_CR_OBL_LAUNCH (27) /* Forces the option byte loading */
|
||||
#define STM32Gx_FLASH_CR_OPTLOCK (30) /* Options Lock */
|
||||
#define STM32Gx_FLASH_CR_LOCK (31) /* FLASH_CR Lock */
|
||||
|
||||
// G0/G4 FLASH status register
|
||||
#define STM32Gx_FLASH_SR_ERROR_MASK (0x3fa)
|
||||
#define STM32Gx_FLASH_SR_PROGERR (3)
|
||||
#define STM32Gx_FLASH_SR_WRPERR (4)
|
||||
#define STM32Gx_FLASH_SR_PGAERR (5)
|
||||
#define STM32Gx_FLASH_SR_BSY (16) /* FLASH_SR Busy */
|
||||
#define STM32Gx_FLASH_SR_EOP (0) /* FLASH_EOP End of Operation */
|
||||
|
||||
// G4 FLASH option register
|
||||
#define STM32G4_FLASH_OPTR_DBANK (22) /* FLASH_OPTR Dual Bank Mode */
|
||||
|
||||
// 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) /* Start */
|
||||
#define STM32WB_FLASH_CR_OPTLOCK (30) /* Option Lock */
|
||||
#define STM32WB_FLASH_CR_LOCK (31) /* Lock */
|
||||
// WB Flash status register.
|
||||
#define STM32WB_FLASH_SR_ERROR_MASK (0x3f8) /* SR [9:3] */
|
||||
#define STM32WB_FLASH_SR_PROGERR (3) /* Programming alignment error */
|
||||
#define STM32WB_FLASH_SR_WRPERR (4) /* Write protection error */
|
||||
#define STM32WB_FLASH_SR_PGAERR (5) /* Programming error */
|
||||
#define STM32WB_FLASH_SR_BSY (16) /* Busy */
|
||||
|
||||
// 32L4 register base is at FLASH_REGS_ADDR (0x40022000)
|
||||
#define STM32L4_FLASH_KEYR (FLASH_REGS_ADDR + 0x08)
|
||||
#define STM32L4_FLASH_OPTKEYR (FLASH_REGS_ADDR + 0x0C)
|
||||
#define STM32L4_FLASH_SR (FLASH_REGS_ADDR + 0x10)
|
||||
#define STM32L4_FLASH_CR (FLASH_REGS_ADDR + 0x14)
|
||||
#define STM32L4_FLASH_OPTR (FLASH_REGS_ADDR + 0x20)
|
||||
|
||||
#define STM32L4_FLASH_SR_ERROR_MASK 0x3f8 /* SR [9:3] */
|
||||
#define STM32L4_FLASH_SR_PROGERR 3
|
||||
#define STM32L4_FLASH_SR_WRPERR 4
|
||||
#define STM32L4_FLASH_SR_PGAERR 5
|
||||
#define STM32L4_FLASH_SR_BSY 16
|
||||
|
||||
#define STM32L4_FLASH_CR_LOCK 31 /* Lock control register */
|
||||
#define STM32L4_FLASH_CR_OPTLOCK 30 /* Lock option bytes */
|
||||
#define STM32L4_FLASH_CR_PG 0 /* Program */
|
||||
#define STM32L4_FLASH_CR_PER 1 /* Page erase */
|
||||
#define STM32L4_FLASH_CR_MER1 2 /* Bank 1 erase */
|
||||
#define STM32L4_FLASH_CR_MER2 15 /* Bank 2 erase */
|
||||
#define STM32L4_FLASH_CR_STRT 16 /* Start command */
|
||||
#define STM32L4_FLASH_CR_OPTSTRT 17 /* Start writing option bytes */
|
||||
#define STM32L4_FLASH_CR_BKER 11 /* Bank select for page erase */
|
||||
#define STM32L4_FLASH_CR_PNB 3 /* Page number (8 bits) */
|
||||
#define STM32L4_FLASH_CR_OBL_LAUNCH 27 /* Option bytes reload */
|
||||
// Bits requesting flash operations (useful when we want to clear them)
|
||||
#define STM32L4_FLASH_CR_OPBITS \
|
||||
(uint32_t)((1lu << STM32L4_FLASH_CR_PG) | (1lu << STM32L4_FLASH_CR_PER) | \
|
||||
(1lu << STM32L4_FLASH_CR_MER1) | (1lu << STM32L4_FLASH_CR_MER1))
|
||||
// Page is fully specified by BKER and PNB
|
||||
#define STM32L4_FLASH_CR_PAGEMASK (uint32_t)(0x1fflu << STM32L4_FLASH_CR_PNB)
|
||||
|
||||
#define STM32L4_FLASH_OPTR_DUALBANK 21
|
||||
|
||||
// STM32L0x flash register base and offsets RM0090 - DM00031020.pdf
|
||||
#define STM32L0_FLASH_REGS_ADDR ((uint32_t)0x40022000)
|
||||
|
||||
#define STM32L0_FLASH_PELOCK (0)
|
||||
#define STM32L0_FLASH_OPTLOCK (2)
|
||||
#define STM32L0_FLASH_OBL_LAUNCH (18)
|
||||
|
||||
#define STM32L0_FLASH_SR_ERROR_MASK 0x00013F00
|
||||
#define STM32L0_FLASH_SR_WRPERR 8
|
||||
#define STM32L0_FLASH_SR_PGAERR 9
|
||||
#define STM32L0_FLASH_SR_NOTZEROERR 16
|
||||
|
||||
#define FLASH_ACR_OFF ((uint32_t)0x00)
|
||||
#define FLASH_PECR_OFF ((uint32_t)0x04)
|
||||
#define FLASH_PDKEYR_OFF ((uint32_t)0x08)
|
||||
#define FLASH_PEKEYR_OFF ((uint32_t)0x0c)
|
||||
#define FLASH_PRGKEYR_OFF ((uint32_t)0x10)
|
||||
#define FLASH_OPTKEYR_OFF ((uint32_t)0x14)
|
||||
#define FLASH_SR_OFF ((uint32_t)0x18)
|
||||
#define FLASH_OBR_OFF ((uint32_t)0x1c)
|
||||
#define FLASH_WRPR_OFF ((uint32_t)0x20)
|
||||
|
||||
// STM32F7
|
||||
#define FLASH_F7_REGS_ADDR ((uint32_t)0x40023c00)
|
||||
#define FLASH_F7_KEYR (FLASH_F7_REGS_ADDR + 0x04)
|
||||
#define FLASH_F7_OPT_KEYR (FLASH_F7_REGS_ADDR + 0x08)
|
||||
#define FLASH_F7_SR (FLASH_F7_REGS_ADDR + 0x0c)
|
||||
#define FLASH_F7_CR (FLASH_F7_REGS_ADDR + 0x10)
|
||||
#define FLASH_F7_OPTCR (FLASH_F7_REGS_ADDR + 0x14)
|
||||
#define FLASH_F7_OPTCR1 (FLASH_F7_REGS_ADDR + 0x18)
|
||||
#define FLASH_F7_OPTCR_LOCK 0
|
||||
#define FLASH_F7_OPTCR_START 1
|
||||
#define FLASH_F7_CR_STRT 16
|
||||
#define FLASH_F7_CR_LOCK 31
|
||||
#define FLASH_F7_CR_SER 1
|
||||
#define FLASH_F7_CR_SNB 3
|
||||
#define FLASH_F7_CR_SNB_MASK 0xf8
|
||||
#define FLASH_F7_SR_BSY 16
|
||||
#define FLASH_F7_SR_ERS_ERR 7 /* Erase Sequence Error */
|
||||
#define FLASH_F7_SR_PGP_ERR 6 /* Programming parallelism error */
|
||||
#define FLASH_F7_SR_PGA_ERR 5 /* Programming alignment error */
|
||||
#define FLASH_F7_SR_WRP_ERR 4 /* Write protection error */
|
||||
#define FLASH_F7_SR_OP_ERR 1 /* Operation error */
|
||||
#define FLASH_F7_SR_EOP 0 /* End of operation */
|
||||
#define FLASH_F7_OPTCR1_BOOT_ADD0 0
|
||||
#define FLASH_F7_OPTCR1_BOOT_ADD1 16
|
||||
|
||||
#define FLASH_F7_SR_ERROR_MASK \
|
||||
((1 << FLASH_F7_SR_ERS_ERR) | (1 << FLASH_F7_SR_PGP_ERR) | \
|
||||
(1 << FLASH_F7_SR_PGA_ERR) | (1 << FLASH_F7_SR_WRP_ERR) | \
|
||||
(1 << FLASH_F7_SR_OP_ERR))
|
||||
|
||||
// STM32F4
|
||||
#define FLASH_F4_REGS_ADDR ((uint32_t)0x40023c00)
|
||||
#define FLASH_F4_KEYR (FLASH_F4_REGS_ADDR + 0x04)
|
||||
#define FLASH_F4_OPT_KEYR (FLASH_F4_REGS_ADDR + 0x08)
|
||||
#define FLASH_F4_SR (FLASH_F4_REGS_ADDR + 0x0c)
|
||||
#define FLASH_F4_CR (FLASH_F4_REGS_ADDR + 0x10)
|
||||
#define FLASH_F4_OPTCR (FLASH_F4_REGS_ADDR + 0x14)
|
||||
#define FLASH_F4_OPTCR_LOCK 0
|
||||
#define FLASH_F4_OPTCR_START 1
|
||||
#define FLASH_F4_CR_STRT 16
|
||||
#define FLASH_F4_CR_LOCK 31
|
||||
#define FLASH_F4_CR_SER 1
|
||||
#define FLASH_F4_CR_SNB 3
|
||||
#define FLASH_F4_CR_SNB_MASK 0xf8
|
||||
#define FLASH_F4_SR_ERROR_MASK 0x000000F0
|
||||
#define FLASH_F4_SR_PGAERR 5
|
||||
#define FLASH_F4_SR_WRPERR 4
|
||||
#define FLASH_F4_SR_BSY 16
|
||||
|
||||
// STM32F2
|
||||
#define FLASH_F2_REGS_ADDR ((uint32_t)0x40023c00)
|
||||
#define FLASH_F2_KEYR (FLASH_F2_REGS_ADDR + 0x04)
|
||||
#define FLASH_F2_OPT_KEYR (FLASH_F2_REGS_ADDR + 0x08)
|
||||
#define FLASH_F2_SR (FLASH_F2_REGS_ADDR + 0x0c)
|
||||
#define FLASH_F2_CR (FLASH_F2_REGS_ADDR + 0x10)
|
||||
#define FLASH_F2_OPT_CR (FLASH_F2_REGS_ADDR + 0x14)
|
||||
#define FLASH_F2_OPT_LOCK_BIT (1u << 0)
|
||||
#define FLASH_F2_CR_STRT 16
|
||||
#define FLASH_F2_CR_LOCK 31
|
||||
|
||||
#define FLASH_F2_CR_SER 1
|
||||
#define FLASH_F2_CR_SNB 3
|
||||
#define FLASH_F2_CR_SNB_MASK 0x78
|
||||
#define FLASH_F2_SR_BSY 16
|
||||
|
||||
// STM32H7xx
|
||||
#define FLASH_H7_CR_LOCK 0
|
||||
#define FLASH_H7_CR_PG 1
|
||||
#define FLASH_H7_CR_SER 2
|
||||
#define FLASH_H7_CR_BER 3
|
||||
#define FLASH_H7_CR_PSIZE 4
|
||||
#define FLASH_H7_CR_START(chipid) (chipid == STM32_CHIPID_H7Ax ? 5 : 7)
|
||||
#define FLASH_H7_CR_SNB 8
|
||||
#define FLASH_H7_CR_SNB_MASK 0x700
|
||||
|
||||
#define FLASH_H7_SR_QW 2
|
||||
#define FLASH_H7_SR_WRPERR 17
|
||||
#define FLASH_H7_SR_PGSERR 18
|
||||
#define FLASH_H7_SR_STRBERR 19
|
||||
#define FLASH_H7_SR_ERROR_MASK \
|
||||
((1 << FLASH_H7_SR_PGSERR) | (1 << FLASH_H7_SR_STRBERR) | \
|
||||
(1 << FLASH_H7_SR_WRPERR))
|
||||
|
||||
#define FLASH_H7_OPTCR_OPTLOCK 0
|
||||
#define FLASH_H7_OPTCR_OPTSTART 1
|
||||
#define FLASH_H7_OPTCR_MER 4
|
||||
|
||||
#define FLASH_H7_OPTSR_OPT_BUSY 0
|
||||
#define FLASH_H7_OPTSR_OPTCHANGEERR 30
|
||||
|
||||
#define FLASH_H7_OPTCCR_CLR_OPTCHANGEERR 30
|
||||
|
||||
#define FLASH_H7_REGS_ADDR ((uint32_t)0x52002000)
|
||||
#define FLASH_H7_KEYR1 (FLASH_H7_REGS_ADDR + 0x04)
|
||||
#define FLASH_H7_KEYR2 (FLASH_H7_REGS_ADDR + 0x104)
|
||||
#define FLASH_H7_OPT_KEYR (FLASH_H7_REGS_ADDR + 0x08)
|
||||
#define FLASH_H7_OPT_KEYR2 (FLASH_H7_REGS_ADDR + 0x108)
|
||||
#define FLASH_H7_CR1 (FLASH_H7_REGS_ADDR + 0x0c)
|
||||
#define FLASH_H7_CR2 (FLASH_H7_REGS_ADDR + 0x10c)
|
||||
#define FLASH_H7_SR1 (FLASH_H7_REGS_ADDR + 0x10)
|
||||
#define FLASH_H7_SR2 (FLASH_H7_REGS_ADDR + 0x110)
|
||||
#define FLASH_H7_CCR1 (FLASH_H7_REGS_ADDR + 0x14)
|
||||
#define FLASH_H7_CCR2 (FLASH_H7_REGS_ADDR + 0x114)
|
||||
#define FLASH_H7_OPTCR (FLASH_H7_REGS_ADDR + 0x18)
|
||||
#define FLASH_H7_OPTCR2 (FLASH_H7_REGS_ADDR + 0x118)
|
||||
#define FLASH_H7_OPTSR_CUR (FLASH_H7_REGS_ADDR + 0x1c)
|
||||
#define FLASH_H7_OPTCCR (FLASH_H7_REGS_ADDR + 0x24)
|
||||
|
||||
#define STM32F0_DBGMCU_CR 0xE0042004
|
||||
#define STM32F0_DBGMCU_CR_IWDG_STOP 8
|
||||
#define STM32F0_DBGMCU_CR_WWDG_STOP 9
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
#ifndef STM32FLASH_H
|
||||
#define STM32FLASH_H
|
||||
|
||||
/* stm32f FPEC flash controller interface, pm0063 manual */
|
||||
// TODO - all of this needs to be abstracted out....
|
||||
// STM32F05x is identical, based on RM0091 (DM00031936, Doc ID 018940 Rev 2,
|
||||
// August 2012)
|
||||
#define FLASH_REGS_ADDR 0x40022000
|
||||
#define FLASH_REGS_SIZE 0x28
|
||||
|
||||
#define FLASH_ACR (FLASH_REGS_ADDR + 0x00)
|
||||
#define FLASH_KEYR (FLASH_REGS_ADDR + 0x04)
|
||||
#define FLASH_OPTKEYR (FLASH_REGS_ADDR + 0x08)
|
||||
#define FLASH_SR (FLASH_REGS_ADDR + 0x0c)
|
||||
#define FLASH_CR (FLASH_REGS_ADDR + 0x10)
|
||||
#define FLASH_AR (FLASH_REGS_ADDR + 0x14)
|
||||
#define FLASH_OBR (FLASH_REGS_ADDR + 0x1c)
|
||||
#define FLASH_WRPR (FLASH_REGS_ADDR + 0x20)
|
||||
|
||||
// STM32F10x_XL has two flash memory banks with separate registers to control
|
||||
// the second bank.
|
||||
#define FLASH_KEYR2 (FLASH_REGS_ADDR + 0x44)
|
||||
#define FLASH_SR2 (FLASH_REGS_ADDR + 0x4c)
|
||||
#define FLASH_CR2 (FLASH_REGS_ADDR + 0x50)
|
||||
#define FLASH_AR2 (FLASH_REGS_ADDR + 0x54)
|
||||
|
||||
// For STM32F05x, the RDPTR_KEY may be wrong, but as it is not used anywhere...
|
||||
#define FLASH_RDPTR_KEY 0x00a5
|
||||
#define FLASH_KEY1 0x45670123
|
||||
#define FLASH_KEY2 0xcdef89ab
|
||||
|
||||
#define FLASH_L0_PRGKEY1 0x8c9daebf
|
||||
#define FLASH_L0_PRGKEY2 0x13141516
|
||||
|
||||
#define FLASH_L0_PEKEY1 0x89abcdef
|
||||
#define FLASH_L0_PEKEY2 0x02030405
|
||||
|
||||
#define FLASH_OPTKEY1 0x08192A3B
|
||||
#define FLASH_OPTKEY2 0x4C5D6E7F
|
||||
|
||||
#define FLASH_F0_OPTKEY1 0x45670123
|
||||
#define FLASH_F0_OPTKEY2 0xCDEF89AB
|
||||
|
||||
#define FLASH_L0_OPTKEY1 0xFBEAD9C8
|
||||
#define FLASH_L0_OPTKEY2 0x24252627
|
||||
|
||||
#define FLASH_SR_BSY 0
|
||||
#define FLASH_SR_PG_ERR 2
|
||||
#define FLASH_SR_WRPRT_ERR 4
|
||||
#define FLASH_SR_EOP 5
|
||||
|
||||
#define FLASH_SR_ERROR_MASK ((1 << FLASH_SR_PG_ERR) | (1 << FLASH_SR_WRPRT_ERR))
|
||||
|
||||
#define FLASH_CR_PG 0
|
||||
#define FLASH_CR_PER 1
|
||||
#define FLASH_CR_MER 2
|
||||
#define FLASH_CR_OPTPG 4
|
||||
#define FLASH_CR_OPTER 5
|
||||
#define FLASH_CR_STRT 6
|
||||
#define FLASH_CR_LOCK 7
|
||||
#define FLASH_CR_OPTWRE 9
|
||||
#define FLASH_CR_OBL_LAUNCH 13
|
||||
|
||||
#define STM32L_FLASH_REGS_ADDR ((uint32_t)0x40023c00)
|
||||
#define STM32L_FLASH_ACR (STM32L_FLASH_REGS_ADDR + 0x00)
|
||||
#define STM32L_FLASH_PECR (STM32L_FLASH_REGS_ADDR + 0x04)
|
||||
#define STM32L_FLASH_PDKEYR (STM32L_FLASH_REGS_ADDR + 0x08)
|
||||
#define STM32L_FLASH_PEKEYR (STM32L_FLASH_REGS_ADDR + 0x0c)
|
||||
#define STM32L_FLASH_PRGKEYR (STM32L_FLASH_REGS_ADDR + 0x10)
|
||||
#define STM32L_FLASH_OPTKEYR (STM32L_FLASH_REGS_ADDR + 0x14)
|
||||
#define STM32L_FLASH_SR (STM32L_FLASH_REGS_ADDR + 0x18)
|
||||
#define STM32L_FLASH_OBR (STM32L_FLASH_REGS_ADDR + 0x1c)
|
||||
#define STM32L_FLASH_WRPR (STM32L_FLASH_REGS_ADDR + 0x20)
|
||||
#define FLASH_L1_FPRG 10
|
||||
#define FLASH_L1_PROG 3
|
||||
|
||||
// Flash registers common to STM32G0 and STM32G4 series.
|
||||
#define STM32Gx_FLASH_REGS_ADDR ((uint32_t)0x40022000)
|
||||
#define STM32Gx_FLASH_ACR (STM32Gx_FLASH_REGS_ADDR + 0x00)
|
||||
#define STM32Gx_FLASH_KEYR (STM32Gx_FLASH_REGS_ADDR + 0x08)
|
||||
#define STM32Gx_FLASH_OPTKEYR (STM32Gx_FLASH_REGS_ADDR + 0x0c)
|
||||
#define STM32Gx_FLASH_SR (STM32Gx_FLASH_REGS_ADDR + 0x10)
|
||||
#define STM32Gx_FLASH_CR (STM32Gx_FLASH_REGS_ADDR + 0x14)
|
||||
#define STM32Gx_FLASH_ECCR (STM32Gx_FLASH_REGS_ADDR + 0x18)
|
||||
#define STM32Gx_FLASH_OPTR (STM32Gx_FLASH_REGS_ADDR + 0x20)
|
||||
|
||||
// G0 (RM0444 Table 1, sec 3.7)
|
||||
// Mostly the same as G4 chips, but the notation
|
||||
// varies a bit after the 'OPTR' register.
|
||||
#define STM32G0_FLASH_REGS_ADDR (STM32Gx_FLASH_REGS_ADDR)
|
||||
#define STM32G0_FLASH_PCROP1ASR (STM32G0_FLASH_REGS_ADDR + 0x24)
|
||||
#define STM32G0_FLASH_PCROP1AER (STM32G0_FLASH_REGS_ADDR + 0x28)
|
||||
#define STM32G0_FLASH_WRP1AR (STM32G0_FLASH_REGS_ADDR + 0x2C)
|
||||
#define STM32G0_FLASH_WRP1BR (STM32G0_FLASH_REGS_ADDR + 0x30)
|
||||
#define STM32G0_FLASH_PCROP1BSR (STM32G0_FLASH_REGS_ADDR + 0x34)
|
||||
#define STM32G0_FLASH_PCROP1BER (STM32G0_FLASH_REGS_ADDR + 0x38)
|
||||
#define STM32G0_FLASH_SECR (STM32G0_FLASH_REGS_ADDR + 0x80)
|
||||
|
||||
// G4 (RM0440 Table 17, sec 3.7.19)
|
||||
// Mostly the same as STM32G0 chips, but there are a few extra
|
||||
// registers because 'cat 3' devices can have two Flash banks.
|
||||
#define STM32G4_FLASH_REGS_ADDR (STM32Gx_FLASH_REGS_ADDR)
|
||||
#define STM32G4_FLASH_PDKEYR (STM32G4_FLASH_REGS_ADDR + 0x04)
|
||||
#define STM32G4_FLASH_PCROP1SR (STM32G4_FLASH_REGS_ADDR + 0x24)
|
||||
#define STM32G4_FLASH_PCROP1ER (STM32G4_FLASH_REGS_ADDR + 0x28)
|
||||
#define STM32G4_FLASH_WRP1AR (STM32G4_FLASH_REGS_ADDR + 0x2C)
|
||||
#define STM32G4_FLASH_WRP1BR (STM32G4_FLASH_REGS_ADDR + 0x30)
|
||||
#define STM32G4_FLASH_PCROP2SR (STM32G4_FLASH_REGS_ADDR + 0x44)
|
||||
#define STM32G4_FLASH_PCROP2ER (STM32G4_FLASH_REGS_ADDR + 0x48)
|
||||
#define STM32G4_FLASH_WRP2AR (STM32G4_FLASH_REGS_ADDR + 0x4C)
|
||||
#define STM32G4_FLASH_WRP2BR (STM32G4_FLASH_REGS_ADDR + 0x50)
|
||||
#define STM32G4_FLASH_SEC1R (STM32G4_FLASH_REGS_ADDR + 0x70)
|
||||
#define STM32G4_FLASH_SEC2R (STM32G4_FLASH_REGS_ADDR + 0x74)
|
||||
|
||||
// G0/G4 FLASH control register
|
||||
#define STM32Gx_FLASH_CR_PG (0) /* Program */
|
||||
#define STM32Gx_FLASH_CR_PER (1) /* Page erase */
|
||||
#define STM32Gx_FLASH_CR_MER1 (2) /* Mass erase */
|
||||
#define STM32Gx_FLASH_CR_PNB (3) /* Page number */
|
||||
#define STM32G0_FLASH_CR_PNG_LEN (5) /* STM32G0: 5 page number bits */
|
||||
#define STM32G4_FLASH_CR_PNG_LEN (7) /* STM32G4: 7 page number bits */
|
||||
#define STM32Gx_FLASH_CR_MER2 (15) /* Mass erase (2nd bank)*/
|
||||
#define STM32Gx_FLASH_CR_STRT (16) /* Start */
|
||||
#define STM32Gx_FLASH_CR_OPTSTRT \
|
||||
(17) /* Start of modification of option bytes */
|
||||
#define STM32Gx_FLASH_CR_FSTPG (18) /* Fast programming */
|
||||
#define STM32Gx_FLASH_CR_EOPIE (24) /* End of operation interrupt enable */
|
||||
#define STM32Gx_FLASH_CR_ERRIE (25) /* Error interrupt enable */
|
||||
#define STM32Gx_FLASH_CR_OBL_LAUNCH (27) /* Forces the option byte loading */
|
||||
#define STM32Gx_FLASH_CR_OPTLOCK (30) /* Options Lock */
|
||||
#define STM32Gx_FLASH_CR_LOCK (31) /* FLASH_CR Lock */
|
||||
|
||||
// G0/G4 FLASH status register
|
||||
#define STM32Gx_FLASH_SR_ERROR_MASK (0x3fa)
|
||||
#define STM32Gx_FLASH_SR_PROGERR (3)
|
||||
#define STM32Gx_FLASH_SR_WRPERR (4)
|
||||
#define STM32Gx_FLASH_SR_PGAERR (5)
|
||||
#define STM32Gx_FLASH_SR_BSY (16) /* FLASH_SR Busy */
|
||||
#define STM32Gx_FLASH_SR_EOP (0) /* FLASH_EOP End of Operation */
|
||||
|
||||
// G4 FLASH option register
|
||||
#define STM32G4_FLASH_OPTR_DBANK (22) /* FLASH_OPTR Dual Bank Mode */
|
||||
|
||||
// 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) /* Start */
|
||||
#define STM32WB_FLASH_CR_OPTLOCK (30) /* Option Lock */
|
||||
#define STM32WB_FLASH_CR_LOCK (31) /* Lock */
|
||||
// WB Flash status register.
|
||||
#define STM32WB_FLASH_SR_ERROR_MASK (0x3f8) /* SR [9:3] */
|
||||
#define STM32WB_FLASH_SR_PROGERR (3) /* Programming alignment error */
|
||||
#define STM32WB_FLASH_SR_WRPERR (4) /* Write protection error */
|
||||
#define STM32WB_FLASH_SR_PGAERR (5) /* Programming error */
|
||||
#define STM32WB_FLASH_SR_BSY (16) /* Busy */
|
||||
|
||||
// 32L4 register base is at FLASH_REGS_ADDR (0x40022000)
|
||||
#define STM32L4_FLASH_KEYR (FLASH_REGS_ADDR + 0x08)
|
||||
#define STM32L4_FLASH_OPTKEYR (FLASH_REGS_ADDR + 0x0C)
|
||||
#define STM32L4_FLASH_SR (FLASH_REGS_ADDR + 0x10)
|
||||
#define STM32L4_FLASH_CR (FLASH_REGS_ADDR + 0x14)
|
||||
#define STM32L4_FLASH_OPTR (FLASH_REGS_ADDR + 0x20)
|
||||
|
||||
#define STM32L4_FLASH_SR_ERROR_MASK 0x3f8 /* SR [9:3] */
|
||||
#define STM32L4_FLASH_SR_PROGERR 3
|
||||
#define STM32L4_FLASH_SR_WRPERR 4
|
||||
#define STM32L4_FLASH_SR_PGAERR 5
|
||||
#define STM32L4_FLASH_SR_BSY 16
|
||||
|
||||
#define STM32L4_FLASH_CR_LOCK 31 /* Lock control register */
|
||||
#define STM32L4_FLASH_CR_OPTLOCK 30 /* Lock option bytes */
|
||||
#define STM32L4_FLASH_CR_PG 0 /* Program */
|
||||
#define STM32L4_FLASH_CR_PER 1 /* Page erase */
|
||||
#define STM32L4_FLASH_CR_MER1 2 /* Bank 1 erase */
|
||||
#define STM32L4_FLASH_CR_MER2 15 /* Bank 2 erase */
|
||||
#define STM32L4_FLASH_CR_STRT 16 /* Start command */
|
||||
#define STM32L4_FLASH_CR_OPTSTRT 17 /* Start writing option bytes */
|
||||
#define STM32L4_FLASH_CR_BKER 11 /* Bank select for page erase */
|
||||
#define STM32L4_FLASH_CR_PNB 3 /* Page number (8 bits) */
|
||||
#define STM32L4_FLASH_CR_OBL_LAUNCH 27 /* Option bytes reload */
|
||||
// Bits requesting flash operations (useful when we want to clear them)
|
||||
#define STM32L4_FLASH_CR_OPBITS \
|
||||
(uint32_t)((1lu << STM32L4_FLASH_CR_PG) | (1lu << STM32L4_FLASH_CR_PER) | \
|
||||
(1lu << STM32L4_FLASH_CR_MER1) | (1lu << STM32L4_FLASH_CR_MER1))
|
||||
// Page is fully specified by BKER and PNB
|
||||
#define STM32L4_FLASH_CR_PAGEMASK (uint32_t)(0x1fflu << STM32L4_FLASH_CR_PNB)
|
||||
|
||||
#define STM32L4_FLASH_OPTR_DUALBANK 21
|
||||
|
||||
// STM32L0x flash register base and offsets RM0090 - DM00031020.pdf
|
||||
#define STM32L0_FLASH_REGS_ADDR ((uint32_t)0x40022000)
|
||||
|
||||
#define STM32L0_FLASH_PELOCK (0)
|
||||
#define STM32L0_FLASH_OPTLOCK (2)
|
||||
#define STM32L0_FLASH_OBL_LAUNCH (18)
|
||||
|
||||
#define STM32L0_FLASH_SR_ERROR_MASK 0x00013F00
|
||||
#define STM32L0_FLASH_SR_WRPERR 8
|
||||
#define STM32L0_FLASH_SR_PGAERR 9
|
||||
#define STM32L0_FLASH_SR_NOTZEROERR 16
|
||||
|
||||
#define FLASH_ACR_OFF ((uint32_t)0x00)
|
||||
#define FLASH_PECR_OFF ((uint32_t)0x04)
|
||||
#define FLASH_PDKEYR_OFF ((uint32_t)0x08)
|
||||
#define FLASH_PEKEYR_OFF ((uint32_t)0x0c)
|
||||
#define FLASH_PRGKEYR_OFF ((uint32_t)0x10)
|
||||
#define FLASH_OPTKEYR_OFF ((uint32_t)0x14)
|
||||
#define FLASH_SR_OFF ((uint32_t)0x18)
|
||||
#define FLASH_OBR_OFF ((uint32_t)0x1c)
|
||||
#define FLASH_WRPR_OFF ((uint32_t)0x20)
|
||||
|
||||
// STM32F7
|
||||
#define FLASH_F7_REGS_ADDR ((uint32_t)0x40023c00)
|
||||
#define FLASH_F7_KEYR (FLASH_F7_REGS_ADDR + 0x04)
|
||||
#define FLASH_F7_OPT_KEYR (FLASH_F7_REGS_ADDR + 0x08)
|
||||
#define FLASH_F7_SR (FLASH_F7_REGS_ADDR + 0x0c)
|
||||
#define FLASH_F7_CR (FLASH_F7_REGS_ADDR + 0x10)
|
||||
#define FLASH_F7_OPTCR (FLASH_F7_REGS_ADDR + 0x14)
|
||||
#define FLASH_F7_OPTCR1 (FLASH_F7_REGS_ADDR + 0x18)
|
||||
#define FLASH_F7_OPTCR_LOCK 0
|
||||
#define FLASH_F7_OPTCR_START 1
|
||||
#define FLASH_F7_CR_STRT 16
|
||||
#define FLASH_F7_CR_LOCK 31
|
||||
#define FLASH_F7_CR_SER 1
|
||||
#define FLASH_F7_CR_SNB 3
|
||||
#define FLASH_F7_CR_SNB_MASK 0xf8
|
||||
#define FLASH_F7_SR_BSY 16
|
||||
#define FLASH_F7_SR_ERS_ERR 7 /* Erase Sequence Error */
|
||||
#define FLASH_F7_SR_PGP_ERR 6 /* Programming parallelism error */
|
||||
#define FLASH_F7_SR_PGA_ERR 5 /* Programming alignment error */
|
||||
#define FLASH_F7_SR_WRP_ERR 4 /* Write protection error */
|
||||
#define FLASH_F7_SR_OP_ERR 1 /* Operation error */
|
||||
#define FLASH_F7_SR_EOP 0 /* End of operation */
|
||||
#define FLASH_F7_OPTCR1_BOOT_ADD0 0
|
||||
#define FLASH_F7_OPTCR1_BOOT_ADD1 16
|
||||
|
||||
#define FLASH_F7_SR_ERROR_MASK \
|
||||
((1 << FLASH_F7_SR_ERS_ERR) | (1 << FLASH_F7_SR_PGP_ERR) | \
|
||||
(1 << FLASH_F7_SR_PGA_ERR) | (1 << FLASH_F7_SR_WRP_ERR) | \
|
||||
(1 << FLASH_F7_SR_OP_ERR))
|
||||
|
||||
// STM32F4
|
||||
#define FLASH_F4_REGS_ADDR ((uint32_t)0x40023c00)
|
||||
#define FLASH_F4_KEYR (FLASH_F4_REGS_ADDR + 0x04)
|
||||
#define FLASH_F4_OPT_KEYR (FLASH_F4_REGS_ADDR + 0x08)
|
||||
#define FLASH_F4_SR (FLASH_F4_REGS_ADDR + 0x0c)
|
||||
#define FLASH_F4_CR (FLASH_F4_REGS_ADDR + 0x10)
|
||||
#define FLASH_F4_OPTCR (FLASH_F4_REGS_ADDR + 0x14)
|
||||
#define FLASH_F4_OPTCR_LOCK 0
|
||||
#define FLASH_F4_OPTCR_START 1
|
||||
#define FLASH_F4_CR_STRT 16
|
||||
#define FLASH_F4_CR_LOCK 31
|
||||
#define FLASH_F4_CR_SER 1
|
||||
#define FLASH_F4_CR_SNB 3
|
||||
#define FLASH_F4_CR_SNB_MASK 0xf8
|
||||
#define FLASH_F4_SR_ERROR_MASK 0x000000F0
|
||||
#define FLASH_F4_SR_PGAERR 5
|
||||
#define FLASH_F4_SR_WRPERR 4
|
||||
#define FLASH_F4_SR_BSY 16
|
||||
|
||||
// STM32F2
|
||||
#define FLASH_F2_REGS_ADDR ((uint32_t)0x40023c00)
|
||||
#define FLASH_F2_KEYR (FLASH_F2_REGS_ADDR + 0x04)
|
||||
#define FLASH_F2_OPT_KEYR (FLASH_F2_REGS_ADDR + 0x08)
|
||||
#define FLASH_F2_SR (FLASH_F2_REGS_ADDR + 0x0c)
|
||||
#define FLASH_F2_CR (FLASH_F2_REGS_ADDR + 0x10)
|
||||
#define FLASH_F2_OPT_CR (FLASH_F2_REGS_ADDR + 0x14)
|
||||
#define FLASH_F2_OPT_LOCK_BIT (1u << 0)
|
||||
#define FLASH_F2_CR_STRT 16
|
||||
#define FLASH_F2_CR_LOCK 31
|
||||
|
||||
#define FLASH_F2_CR_SER 1
|
||||
#define FLASH_F2_CR_SNB 3
|
||||
#define FLASH_F2_CR_SNB_MASK 0x78
|
||||
#define FLASH_F2_SR_BSY 16
|
||||
|
||||
// STM32H7xx
|
||||
#define FLASH_H7_CR_LOCK 0
|
||||
#define FLASH_H7_CR_PG 1
|
||||
#define FLASH_H7_CR_SER 2
|
||||
#define FLASH_H7_CR_BER 3
|
||||
#define FLASH_H7_CR_PSIZE 4
|
||||
#define FLASH_H7_CR_START(chipid) (chipid == STM32_CHIPID_H7Ax ? 5 : 7)
|
||||
#define FLASH_H7_CR_SNB 8
|
||||
#define FLASH_H7_CR_SNB_MASK 0x700
|
||||
|
||||
#define FLASH_H7_SR_QW 2
|
||||
#define FLASH_H7_SR_WRPERR 17
|
||||
#define FLASH_H7_SR_PGSERR 18
|
||||
#define FLASH_H7_SR_STRBERR 19
|
||||
#define FLASH_H7_SR_ERROR_MASK \
|
||||
((1 << FLASH_H7_SR_PGSERR) | (1 << FLASH_H7_SR_STRBERR) | \
|
||||
(1 << FLASH_H7_SR_WRPERR))
|
||||
|
||||
#define FLASH_H7_OPTCR_OPTLOCK 0
|
||||
#define FLASH_H7_OPTCR_OPTSTART 1
|
||||
#define FLASH_H7_OPTCR_MER 4
|
||||
|
||||
#define FLASH_H7_OPTSR_OPT_BUSY 0
|
||||
#define FLASH_H7_OPTSR_OPTCHANGEERR 30
|
||||
|
||||
#define FLASH_H7_OPTCCR_CLR_OPTCHANGEERR 30
|
||||
|
||||
#define FLASH_H7_REGS_ADDR ((uint32_t)0x52002000)
|
||||
#define FLASH_H7_KEYR1 (FLASH_H7_REGS_ADDR + 0x04)
|
||||
#define FLASH_H7_KEYR2 (FLASH_H7_REGS_ADDR + 0x104)
|
||||
#define FLASH_H7_OPT_KEYR (FLASH_H7_REGS_ADDR + 0x08)
|
||||
#define FLASH_H7_OPT_KEYR2 (FLASH_H7_REGS_ADDR + 0x108)
|
||||
#define FLASH_H7_CR1 (FLASH_H7_REGS_ADDR + 0x0c)
|
||||
#define FLASH_H7_CR2 (FLASH_H7_REGS_ADDR + 0x10c)
|
||||
#define FLASH_H7_SR1 (FLASH_H7_REGS_ADDR + 0x10)
|
||||
#define FLASH_H7_SR2 (FLASH_H7_REGS_ADDR + 0x110)
|
||||
#define FLASH_H7_CCR1 (FLASH_H7_REGS_ADDR + 0x14)
|
||||
#define FLASH_H7_CCR2 (FLASH_H7_REGS_ADDR + 0x114)
|
||||
#define FLASH_H7_OPTCR (FLASH_H7_REGS_ADDR + 0x18)
|
||||
#define FLASH_H7_OPTCR2 (FLASH_H7_REGS_ADDR + 0x118)
|
||||
#define FLASH_H7_OPTSR_CUR (FLASH_H7_REGS_ADDR + 0x1c)
|
||||
#define FLASH_H7_OPTCCR (FLASH_H7_REGS_ADDR + 0x24)
|
||||
|
||||
#endif // STM32FLASH_H
|
|
@ -0,0 +1,74 @@
|
|||
#include <stlink.h>
|
||||
#include "calculate.h"
|
||||
#include "common_flash.h"
|
||||
|
||||
uint32_t calculate_F4_sectornum(uint32_t flashaddr) {
|
||||
uint32_t offset = 0;
|
||||
flashaddr &= ~STM32_FLASH_BASE; // page now holding the actual flash address
|
||||
|
||||
if (flashaddr >= 0x100000) {
|
||||
offset = 12;
|
||||
flashaddr -= 0x100000;
|
||||
}
|
||||
|
||||
if (flashaddr < 0x4000) {
|
||||
return (offset + 0);
|
||||
} else if (flashaddr < 0x8000) {
|
||||
return (offset + 1);
|
||||
} else if (flashaddr < 0xc000) {
|
||||
return (offset + 2);
|
||||
} else if (flashaddr < 0x10000) {
|
||||
return (offset + 3);
|
||||
} else if (flashaddr < 0x20000) {
|
||||
return (offset + 4);
|
||||
} else {
|
||||
return (offset + (flashaddr / 0x20000) + 4);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t calculate_F7_sectornum(uint32_t flashaddr) {
|
||||
flashaddr &= ~STM32_FLASH_BASE; // Page now holding the actual flash address
|
||||
|
||||
if (flashaddr < 0x20000) {
|
||||
return (flashaddr / 0x8000);
|
||||
} else if (flashaddr < 0x40000) {
|
||||
return (4);
|
||||
} else {
|
||||
return ((flashaddr / 0x40000) + 4);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t calculate_H7_sectornum(stlink_t *sl, uint32_t flashaddr,
|
||||
unsigned bank) {
|
||||
flashaddr &=
|
||||
~((bank == BANK_1)
|
||||
? STM32_FLASH_BASE
|
||||
: STM32_H7_FLASH_BANK2_BASE); // sector holding the flash address
|
||||
return (flashaddr / sl->flash_pgsz);
|
||||
}
|
||||
|
||||
// returns BKER:PNB for the given page address
|
||||
uint32_t calculate_L4_page(stlink_t *sl, uint32_t flashaddr) {
|
||||
uint32_t bker = 0;
|
||||
uint32_t flashopt;
|
||||
stlink_read_debug32(sl, STM32L4_FLASH_OPTR, &flashopt);
|
||||
flashaddr -= STM32_FLASH_BASE;
|
||||
|
||||
if (sl->chip_id == STM32_CHIPID_L4 ||
|
||||
sl->chip_id == STM32_CHIPID_L496x_L4A6x ||
|
||||
sl->chip_id == STM32_CHIPID_L4Rx) {
|
||||
// this chip use dual banked flash
|
||||
if (flashopt & (uint32_t)(1lu << STM32L4_FLASH_OPTR_DUALBANK)) {
|
||||
uint32_t banksize = (uint32_t)sl->flash_size / 2;
|
||||
|
||||
if (flashaddr >= banksize) {
|
||||
flashaddr -= banksize;
|
||||
bker = 0x100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For 1MB chips without the dual-bank option set, the page address will
|
||||
// overflow into the BKER bit, which gives us the correct bank:page value.
|
||||
return (bker | flashaddr / (uint32_t)sl->flash_pgsz);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* File: calculate.h
|
||||
*
|
||||
* Calculation of sector numbers and pages
|
||||
*/
|
||||
|
||||
#ifndef CALCULATE_H
|
||||
#define CALCULATE_H
|
||||
|
||||
uint32_t calculate_F4_sectornum(uint32_t);
|
||||
uint32_t calculate_F7_sectornum(uint32_t);
|
||||
uint32_t calculate_H7_sectornum(stlink_t *, uint32_t, unsigned);
|
||||
uint32_t calculate_L4_page(stlink_t *, uint32_t);
|
||||
|
||||
#endif // CALCULATE_H
|
4223
src/common.c
4223
src/common.c
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* File: common.h
|
||||
*
|
||||
* General helper functions
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
int check_file(stlink_t *, mapped_file_t *, stm32_addr_t);
|
||||
void md5_calculate(mapped_file_t *);
|
||||
void stlink_checksum(mapped_file_t *);
|
||||
void stlink_fwrite_finalize(stlink_t *, stm32_addr_t);
|
||||
|
||||
#endif // COMMON_H
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* File: common_flash.h
|
||||
*
|
||||
* Flash operations
|
||||
*/
|
||||
|
||||
#ifndef COMMON_FLASH_H
|
||||
#define COMMON_FLASH_H
|
||||
|
||||
void lock_flash(stlink_t *);
|
||||
void clear_flash_error(stlink_t *);
|
||||
void wait_flash_busy(stlink_t *);
|
||||
int check_flash_error(stlink_t *);
|
||||
int unlock_flash_if(stlink_t *);
|
||||
int lock_flash_option(stlink_t *);
|
||||
int unlock_flash_option_if(stlink_t *);
|
||||
void write_flash_cr_psiz(stlink_t *, uint32_t, unsigned);
|
||||
void clear_flash_cr_pg(stlink_t *, unsigned);
|
||||
|
||||
// TODO: move to private defines if possible
|
||||
|
||||
#define BANK_1 0
|
||||
#define BANK_2 1
|
||||
|
||||
uint32_t read_flash_cr(stlink_t *, unsigned);
|
||||
uint32_t get_stm32l0_flash_base(stlink_t *);
|
||||
#endif // STLINK_H
|
|
@ -0,0 +1,482 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stlink.h>
|
||||
#include "common_flash.h"
|
||||
|
||||
#define L1_WRITE_BLOCK_SIZE 0x80
|
||||
#define L0_WRITE_BLOCK_SIZE 0x40
|
||||
|
||||
int stm32l1_write_half_pages(stlink_t *sl, stm32_addr_t addr, uint8_t *base,
|
||||
uint32_t len, uint32_t pagesize) {
|
||||
unsigned int count, off;
|
||||
unsigned int num_half_pages = len / pagesize;
|
||||
uint32_t val;
|
||||
uint32_t flash_regs_base = get_stm32l0_flash_base(sl);
|
||||
flash_loader_t fl;
|
||||
bool use_loader = true;
|
||||
int ret = 0;
|
||||
|
||||
// enable half page write
|
||||
stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val);
|
||||
val |= (1 << FLASH_L1_FPRG);
|
||||
stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val);
|
||||
val |= (1 << FLASH_L1_PROG);
|
||||
stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val);
|
||||
|
||||
wait_flash_busy(sl);
|
||||
|
||||
for (count = 0; count < num_half_pages; count++) {
|
||||
if (use_loader) {
|
||||
ret = stlink_flash_loader_run(sl, &fl, addr + count * pagesize,
|
||||
base + count * pagesize, pagesize);
|
||||
if (ret && count == 0) {
|
||||
/* It seems that stm32lx devices have a problem when it is blank */
|
||||
WLOG("Failed to use flash loader, fallback to soft write\n");
|
||||
use_loader = false;
|
||||
}
|
||||
}
|
||||
if (!use_loader) {
|
||||
ret = 0;
|
||||
for (off = 0; off < pagesize && !ret; off += 64) {
|
||||
size_t chunk = (pagesize - off > 64) ? 64 : pagesize - off;
|
||||
memcpy(sl->q_buf, base + count * pagesize + off, chunk);
|
||||
ret = stlink_write_mem32(sl, addr + count * pagesize + off, (uint16_t)chunk);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
WLOG("l1_stlink_flash_loader_run(%#x) failed! == -1\n",
|
||||
addr + count * pagesize);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sl->verbose >= 1) {
|
||||
// show progress; writing procedure is slow and previous errors are
|
||||
// misleading
|
||||
fprintf(stdout, "\r%3u/%u halfpages written", count + 1, num_half_pages);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// wait for sr.busy to be cleared
|
||||
wait_flash_busy(sl);
|
||||
}
|
||||
|
||||
// disable half page write
|
||||
stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val);
|
||||
val &= ~((1 << FLASH_L1_FPRG) | (1 << FLASH_L1_PROG));
|
||||
stlink_write_debug32(sl, flash_regs_base + FLASH_PECR_OFF, val);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void set_flash_cr_pg(stlink_t *sl, unsigned bank) {
|
||||
uint32_t cr_reg, x;
|
||||
|
||||
x = read_flash_cr(sl, bank);
|
||||
|
||||
if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
|
||||
cr_reg = FLASH_F4_CR;
|
||||
x |= 1 << FLASH_CR_PG;
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_F7) {
|
||||
cr_reg = FLASH_F7_CR;
|
||||
x |= 1 << FLASH_CR_PG;
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_L4_L4P) {
|
||||
cr_reg = STM32L4_FLASH_CR;
|
||||
x &= ~STM32L4_FLASH_CR_OPBITS;
|
||||
x |= (1 << STM32L4_FLASH_CR_PG);
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
|
||||
sl->flash_type == STM32_FLASH_TYPE_G4) {
|
||||
cr_reg = STM32Gx_FLASH_CR;
|
||||
x |= (1 << FLASH_CR_PG);
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_WB_WL) {
|
||||
cr_reg = STM32WB_FLASH_CR;
|
||||
x |= (1 << FLASH_CR_PG);
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_H7) {
|
||||
cr_reg = (bank == BANK_1) ? FLASH_H7_CR1 : FLASH_H7_CR2;
|
||||
x |= (1 << FLASH_H7_CR_PG);
|
||||
} else {
|
||||
cr_reg = FLASH_CR;
|
||||
x = (1 << FLASH_CR_PG);
|
||||
}
|
||||
|
||||
stlink_write_debug32(sl, cr_reg, x);
|
||||
}
|
||||
|
||||
static void set_dma_state(stlink_t *sl, flash_loader_t *fl, int bckpRstr) {
|
||||
uint32_t rcc, rcc_dma_mask, value;
|
||||
|
||||
rcc = rcc_dma_mask = value = 0;
|
||||
|
||||
switch (sl->flash_type) {
|
||||
case STM32_FLASH_TYPE_F0_F1_F3:
|
||||
case STM32_FLASH_TYPE_F1_XL:
|
||||
rcc = STM32F1_RCC_AHBENR;
|
||||
rcc_dma_mask = STM32F1_RCC_DMAEN;
|
||||
break;
|
||||
case STM32_FLASH_TYPE_F2_F4:
|
||||
case STM32_FLASH_TYPE_F7:
|
||||
rcc = STM32F4_RCC_AHB1ENR;
|
||||
rcc_dma_mask = STM32F4_RCC_DMAEN;
|
||||
break;
|
||||
case STM32_FLASH_TYPE_G0:
|
||||
rcc = STM32G0_RCC_AHBENR;
|
||||
rcc_dma_mask = STM32G0_RCC_DMAEN;
|
||||
break;
|
||||
case STM32_FLASH_TYPE_G4:
|
||||
case STM32_FLASH_TYPE_L4_L4P:
|
||||
rcc = STM32G4_RCC_AHB1ENR;
|
||||
rcc_dma_mask = STM32G4_RCC_DMAEN;
|
||||
break;
|
||||
case STM32_FLASH_TYPE_L0_L1:
|
||||
rcc = STM32L0_RCC_AHBENR;
|
||||
rcc_dma_mask = STM32L0_RCC_DMAEN;
|
||||
break;
|
||||
case STM32_FLASH_TYPE_H7:
|
||||
rcc = STM32H7_RCC_AHB1ENR;
|
||||
rcc_dma_mask = STM32H7_RCC_DMAEN;
|
||||
break;
|
||||
case STM32_FLASH_TYPE_WB_WL:
|
||||
rcc = STM32WB_RCC_AHB1ENR;
|
||||
rcc_dma_mask = STM32WB_RCC_DMAEN;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stlink_read_debug32(sl, rcc, &value)) {
|
||||
if (bckpRstr) {
|
||||
value = (value & (~rcc_dma_mask)) | fl->rcc_dma_bkp;
|
||||
} else {
|
||||
fl->rcc_dma_bkp = value & rcc_dma_mask;
|
||||
value &= ~rcc_dma_mask;
|
||||
}
|
||||
stlink_write_debug32(sl, rcc, value);
|
||||
}
|
||||
}
|
||||
|
||||
int stlink_flashloader_start(stlink_t *sl, flash_loader_t *fl) {
|
||||
// disable DMA
|
||||
set_dma_state(sl, fl, 0);
|
||||
|
||||
// wait for ongoing op to finish
|
||||
wait_flash_busy(sl);
|
||||
// Clear errors
|
||||
clear_flash_error(sl);
|
||||
|
||||
if ((sl->flash_type == STM32_FLASH_TYPE_F2_F4) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_F7) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_L4_L4P)) {
|
||||
ILOG("Starting Flash write for F2/F4/F7/L4\n");
|
||||
|
||||
// Flash loader initialisation
|
||||
if (stlink_flash_loader_init(sl, fl) == -1) {
|
||||
ELOG("stlink_flash_loader_init() == -1\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
unlock_flash_if(sl); // first unlock the cr
|
||||
|
||||
int voltage;
|
||||
if (sl->version.stlink_v == 1) {
|
||||
WLOG("STLINK V1 cannot read voltage, use default voltage 3.2V\n");
|
||||
voltage = 3200;
|
||||
} else {
|
||||
voltage = stlink_target_voltage(sl);
|
||||
}
|
||||
|
||||
if (voltage == -1) {
|
||||
ELOG("Failed to read Target voltage\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (sl->flash_type == STM32_FLASH_TYPE_L4_L4P) {
|
||||
// L4 does not have a byte-write mode
|
||||
if (voltage < 1710) {
|
||||
ELOG("Target voltage (%d mV) too low for flash writes!\n", voltage);
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if (voltage > 2700) {
|
||||
ILOG("enabling 32-bit flash writes\n");
|
||||
write_flash_cr_psiz(sl, 2, BANK_1);
|
||||
} else {
|
||||
ILOG("Target voltage (%d mV) too low for 32-bit flash, "
|
||||
"using 8-bit flash writes\n",
|
||||
voltage);
|
||||
write_flash_cr_psiz(sl, 0, BANK_1);
|
||||
}
|
||||
}
|
||||
|
||||
// set programming mode
|
||||
set_flash_cr_pg(sl, BANK_1);
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_WB_WL ||
|
||||
sl->flash_type == STM32_FLASH_TYPE_G0 ||
|
||||
sl->flash_type == STM32_FLASH_TYPE_G4) {
|
||||
ILOG("Starting Flash write for WB/G0/G4\n");
|
||||
|
||||
unlock_flash_if(sl); // unlock flash if necessary
|
||||
set_flash_cr_pg(sl, BANK_1); // set PG 'allow programming' bit
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_L0_L1) {
|
||||
ILOG("Starting Flash write for L0\n");
|
||||
|
||||
uint32_t val;
|
||||
uint32_t flash_regs_base = get_stm32l0_flash_base(sl);
|
||||
|
||||
// disable pecr protection
|
||||
stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF,
|
||||
FLASH_L0_PEKEY1);
|
||||
stlink_write_debug32(sl, flash_regs_base + FLASH_PEKEYR_OFF,
|
||||
FLASH_L0_PEKEY2);
|
||||
|
||||
// check pecr.pelock is cleared
|
||||
stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val);
|
||||
if (val & (1 << 0)) {
|
||||
ELOG("pecr.pelock not clear\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// unlock program memory
|
||||
stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF,
|
||||
FLASH_L0_PRGKEY1);
|
||||
stlink_write_debug32(sl, flash_regs_base + FLASH_PRGKEYR_OFF,
|
||||
FLASH_L0_PRGKEY2);
|
||||
|
||||
// check pecr.prglock is cleared
|
||||
stlink_read_debug32(sl, flash_regs_base + FLASH_PECR_OFF, &val);
|
||||
if (val & (1 << 1)) {
|
||||
ELOG("pecr.prglock not clear\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Flash loader initialisation */
|
||||
if (stlink_flash_loader_init(sl, fl) == -1) {
|
||||
// L0/L1 have fallback to soft write
|
||||
WLOG("stlink_flash_loader_init() == -1\n");
|
||||
}
|
||||
} else if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
|
||||
ILOG("Starting Flash write for VL/F0/F3/F1_XL\n");
|
||||
|
||||
// flash loader initialisation
|
||||
if (stlink_flash_loader_init(sl, fl) == -1) {
|
||||
ELOG("stlink_flash_loader_init() == -1\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// unlock flash
|
||||
unlock_flash_if(sl);
|
||||
|
||||
// set programming mode
|
||||
set_flash_cr_pg(sl, BANK_1);
|
||||
if (sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
|
||||
set_flash_cr_pg(sl, BANK_2);
|
||||
}
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_H7) {
|
||||
ILOG("Starting Flash write for H7\n");
|
||||
|
||||
unlock_flash_if(sl); // unlock the cr
|
||||
set_flash_cr_pg(sl, BANK_1); // set programming mode
|
||||
if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) {
|
||||
set_flash_cr_pg(sl, BANK_2);
|
||||
}
|
||||
if (sl->chip_id != STM32_CHIPID_H7Ax) {
|
||||
// set parallelism
|
||||
write_flash_cr_psiz(sl, 3 /*64it*/, BANK_1);
|
||||
if (sl->chip_flags & CHIP_F_HAS_DUAL_BANK) {
|
||||
write_flash_cr_psiz(sl, 3 /*64bit*/, BANK_2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ELOG("unknown coreid, not sure how to write: %x\n", sl->core_id);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int stlink_flashloader_write(stlink_t *sl, flash_loader_t *fl,
|
||||
stm32_addr_t addr, uint8_t *base, uint32_t len) {
|
||||
size_t off;
|
||||
if ((sl->flash_type == STM32_FLASH_TYPE_F2_F4) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_F7) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_L4_L4P)) {
|
||||
size_t buf_size = (sl->sram_size > 0x8000) ? 0x8000 : 0x4000;
|
||||
for (off = 0; off < len;) {
|
||||
size_t size = len - off > buf_size ? buf_size : len - off;
|
||||
if (stlink_flash_loader_run(sl, fl, addr + (uint32_t)off, base + off,
|
||||
size) == -1) {
|
||||
ELOG("stlink_flash_loader_run(%#x) failed! == -1\n",
|
||||
(unsigned)(addr + off));
|
||||
check_flash_error(sl);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
off += size;
|
||||
}
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_WB_WL ||
|
||||
sl->flash_type == STM32_FLASH_TYPE_G0 ||
|
||||
sl->flash_type == STM32_FLASH_TYPE_G4) {
|
||||
DLOG("Starting %3u page write\r\n", (unsigned int)(len / sl->flash_pgsz));
|
||||
for (off = 0; off < len; off += sizeof(uint32_t)) {
|
||||
uint32_t data;
|
||||
|
||||
if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) {
|
||||
fprintf(stdout, "\r%3u/%3u pages written",
|
||||
(unsigned int)(off / sl->flash_pgsz),
|
||||
(unsigned int)(len / sl->flash_pgsz));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
write_uint32((unsigned char *)&data, *(uint32_t *)(base + off));
|
||||
stlink_write_debug32(sl, addr + (uint32_t)off, data);
|
||||
wait_flash_busy(sl); // wait for 'busy' bit in FLASH_SR to clear
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
// flash writes happen as 2 words at a time
|
||||
if ((off / sizeof(uint32_t)) % 2 != 0) {
|
||||
stlink_write_debug32(sl, addr + (uint32_t)off,
|
||||
0); // write a single word of zeros
|
||||
wait_flash_busy(sl); // wait for 'busy' bit in FLASH_SR to clear
|
||||
}
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_L0_L1) {
|
||||
uint32_t val;
|
||||
uint32_t flash_regs_base = get_stm32l0_flash_base(sl);
|
||||
uint32_t pagesize = (flash_regs_base==STM32L0_FLASH_REGS_ADDR)?
|
||||
L0_WRITE_BLOCK_SIZE:L1_WRITE_BLOCK_SIZE;
|
||||
|
||||
DLOG("Starting %3u page write\r\n", (unsigned int)(len / sl->flash_pgsz));
|
||||
|
||||
off = 0;
|
||||
|
||||
if (len > pagesize) {
|
||||
if (stm32l1_write_half_pages(sl, addr, base, len, pagesize)) {
|
||||
return (-1);
|
||||
} else {
|
||||
off = (size_t)(len / pagesize) * pagesize;
|
||||
}
|
||||
}
|
||||
|
||||
// write remaining word in program memory
|
||||
for (; off < len; off += sizeof(uint32_t)) {
|
||||
uint32_t data;
|
||||
|
||||
if ((off % sl->flash_pgsz) > (sl->flash_pgsz - 5)) {
|
||||
fprintf(stdout, "\r%3u/%3u pages written",
|
||||
(unsigned int)(off / sl->flash_pgsz),
|
||||
(unsigned int)(len / sl->flash_pgsz));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
write_uint32((unsigned char *)&data, *(uint32_t *)(base + off));
|
||||
stlink_write_debug32(sl, addr + (uint32_t)off, data);
|
||||
|
||||
// wait for sr.busy to be cleared
|
||||
do {
|
||||
stlink_read_debug32(sl, flash_regs_base + FLASH_SR_OFF, &val);
|
||||
} while ((val & (1 << 0)) != 0);
|
||||
|
||||
// TODO: check redo write operation
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
} else if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
|
||||
int write_block_count = 0;
|
||||
for (off = 0; off < len; off += sl->flash_pgsz) {
|
||||
// adjust last write size
|
||||
size_t size = len - off > sl->flash_pgsz ? sl->flash_pgsz : len - off;
|
||||
|
||||
// unlock and set programming mode
|
||||
unlock_flash_if(sl);
|
||||
|
||||
DLOG("Finished unlocking flash, running loader!\n");
|
||||
|
||||
if (stlink_flash_loader_run(sl, fl, addr + (uint32_t)off, base + off,
|
||||
size) == -1) {
|
||||
ELOG("stlink_flash_loader_run(%#x) failed! == -1\n",
|
||||
(unsigned)(addr + off));
|
||||
check_flash_error(sl);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
lock_flash(sl);
|
||||
|
||||
if (sl->verbose >= 1) {
|
||||
// show progress; writing procedure is slow and previous errors are
|
||||
// misleading
|
||||
fprintf(stdout, "\r%3u/%3u pages written", ++write_block_count,
|
||||
(unsigned int)((len + sl->flash_pgsz - 1) / sl->flash_pgsz));
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
if (sl->verbose >= 1) {
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_H7) {
|
||||
for (off = 0; off < len;) {
|
||||
// Program STM32H7x with 64-byte Flash words
|
||||
size_t chunk = (len - off > 64) ? 64 : len - off;
|
||||
memcpy(sl->q_buf, base + off, chunk);
|
||||
stlink_write_mem32(sl, addr + (uint32_t)off, 64);
|
||||
wait_flash_busy(sl);
|
||||
|
||||
off += chunk;
|
||||
|
||||
if (sl->verbose >= 1) {
|
||||
// show progress
|
||||
fprintf(stdout, "\r%u/%u bytes written", (unsigned int)off,
|
||||
(unsigned int)len);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
if (sl->verbose >= 1) {
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return check_flash_error(sl);
|
||||
}
|
||||
|
||||
int stlink_flashloader_stop(stlink_t *sl, flash_loader_t *fl) {
|
||||
uint32_t dhcsr;
|
||||
|
||||
if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_F2_F4) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_F7) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_L4_L4P) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_WB_WL) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_G0) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_G4) ||
|
||||
(sl->flash_type == STM32_FLASH_TYPE_H7)) {
|
||||
|
||||
clear_flash_cr_pg(sl, BANK_1);
|
||||
if ((sl->flash_type == STM32_FLASH_TYPE_H7 &&
|
||||
sl->chip_flags & CHIP_F_HAS_DUAL_BANK) ||
|
||||
sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
|
||||
clear_flash_cr_pg(sl, BANK_2);
|
||||
}
|
||||
lock_flash(sl);
|
||||
} else if (sl->flash_type == STM32_FLASH_TYPE_L0_L1) {
|
||||
uint32_t val;
|
||||
uint32_t flash_regs_base = get_stm32l0_flash_base(sl);
|
||||
|
||||
// reset lock bits
|
||||
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);
|
||||
}
|
||||
|
||||
// enable interrupt
|
||||
if (!stlink_read_debug32(sl, STLINK_REG_DHCSR, &dhcsr)) {
|
||||
stlink_write_debug32(sl, STLINK_REG_DHCSR,
|
||||
STLINK_REG_DHCSR_DBGKEY | STLINK_REG_DHCSR_C_DEBUGEN |
|
||||
(dhcsr & (~STLINK_REG_DHCSR_C_MASKINTS)));
|
||||
}
|
||||
|
||||
// restore DMA state
|
||||
set_dma_state(sl, fl, 1);
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <md5.h>
|
||||
#include <unistd.h> // for close
|
||||
#include <stlink.h>
|
||||
#include <logging.h>
|
||||
|
||||
|
||||
#include "map_file.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef MAX_FILE_SIZE
|
||||
#define MAX_FILE_SIZE (1<<20) // 1 GB max file size
|
||||
#endif
|
||||
|
||||
int map_file(mapped_file_t *mf, const char *path) {
|
||||
int error = -1;
|
||||
struct stat st;
|
||||
|
||||
const int fd = open(path, O_RDONLY | O_BINARY);
|
||||
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "open(%s) == -1\n", path);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) == -1) {
|
||||
fprintf(stderr, "fstat(%s) == -1\n", path);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if (sizeof(st.st_size) != sizeof(size_t)) {
|
||||
// on 32 bit systems, check if there is an overflow
|
||||
if (st.st_size > (off_t)MAX_FILE_SIZE /*1 GB*/ ) {
|
||||
// limit file size to 1 GB
|
||||
fprintf(stderr, "mmap() size_t overflow for file %s\n", path);
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
mf->base =
|
||||
(uint8_t *)mmap(NULL, (size_t)(st.st_size), PROT_READ, MAP_SHARED, fd, 0);
|
||||
|
||||
if (mf->base == MAP_FAILED) {
|
||||
fprintf(stderr, "mmap() == MAP_FAILED for file %s\n", path);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
mf->len = (size_t)st.st_size;
|
||||
error = 0; // success
|
||||
|
||||
on_error:
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
|
||||
void unmap_file(mapped_file_t *mf) {
|
||||
munmap((void *)mf->base, mf->len);
|
||||
mf->base = (unsigned char *)MAP_FAILED;
|
||||
mf->len = 0;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* File: map_file.h
|
||||
*
|
||||
* File mapping
|
||||
*/
|
||||
|
||||
#ifndef MAP_FILE_H
|
||||
#define MAP_FILE_H
|
||||
|
||||
#ifdef STLINK_HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#else
|
||||
#include <mmap.h>
|
||||
#endif
|
||||
|
||||
/* Memory mapped file */
|
||||
typedef struct mapped_file {
|
||||
uint8_t *base;
|
||||
size_t len;
|
||||
} mapped_file_t;
|
||||
|
||||
#define MAPPED_FILE_INITIALIZER \
|
||||
{ NULL, 0 }
|
||||
|
||||
int map_file(mapped_file_t *, const char *);
|
||||
void unmap_file(mapped_file_t *);
|
||||
|
||||
#endif // MAP_FILE_H
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,143 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stlink.h>
|
||||
|
||||
// Endianness
|
||||
// https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
|
||||
// These functions encode and decode little endian uint16 and uint32 values.
|
||||
|
||||
void write_uint32(unsigned char *buf, uint32_t ui) {
|
||||
buf[0] = ui;
|
||||
buf[1] = ui >> 8;
|
||||
buf[2] = ui >> 16;
|
||||
buf[3] = ui >> 24;
|
||||
}
|
||||
|
||||
void write_uint16(unsigned char *buf, uint16_t ui) {
|
||||
buf[0] = (uint8_t)ui;
|
||||
buf[1] = (uint8_t)(ui >> 8);
|
||||
}
|
||||
|
||||
uint32_t read_uint32(const unsigned char *c, const int pt) {
|
||||
return ((uint32_t)c[pt]) | ((uint32_t)c[pt + 1] << 8) |
|
||||
((uint32_t)c[pt + 2] << 16) | ((uint32_t)c[pt + 3] << 24);
|
||||
}
|
||||
|
||||
uint16_t read_uint16(const unsigned char *c, const int pt) {
|
||||
return ((uint16_t)c[pt]) | ((uint16_t)c[pt + 1] << 8);
|
||||
}
|
||||
|
||||
int stlink_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) {
|
||||
int ret;
|
||||
|
||||
ret = sl->backend->read_debug32(sl, addr, data);
|
||||
if (!ret)
|
||||
DLOG("*** stlink_read_debug32 %#010x at %#010x\n", *data, addr);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int stlink_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) {
|
||||
DLOG("*** stlink_write_debug32 %#010x to %#010x\n", data, addr);
|
||||
return sl->backend->write_debug32(sl, addr, data);
|
||||
}
|
||||
|
||||
int stlink_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
|
||||
DLOG("*** stlink_write_mem32 %u bytes to %#x\n", len, addr);
|
||||
|
||||
if (len % 4 != 0) {
|
||||
ELOG("Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (sl->backend->write_mem32(sl, addr, len));
|
||||
}
|
||||
|
||||
int stlink_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
|
||||
DLOG("*** stlink_read_mem32 ***\n");
|
||||
|
||||
if (len % 4 != 0) { // !!! never ever: fw gives just wrong values
|
||||
ELOG("Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (sl->backend->read_mem32(sl, addr, len));
|
||||
}
|
||||
|
||||
int stlink_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
|
||||
DLOG("*** stlink_write_mem8 ***\n");
|
||||
return (sl->backend->write_mem8(sl, addr, len));
|
||||
}
|
||||
|
||||
int stlink_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
|
||||
DLOG("*** stlink_read_all_regs ***\n");
|
||||
return (sl->backend->read_all_regs(sl, regp));
|
||||
}
|
||||
|
||||
int stlink_read_all_unsupported_regs(stlink_t *sl, struct stlink_reg *regp) {
|
||||
DLOG("*** stlink_read_all_unsupported_regs ***\n");
|
||||
return (sl->backend->read_all_unsupported_regs(sl, regp));
|
||||
}
|
||||
|
||||
int stlink_write_reg(stlink_t *sl, uint32_t reg, int idx) {
|
||||
DLOG("*** stlink_write_reg\n");
|
||||
return (sl->backend->write_reg(sl, reg, idx));
|
||||
}
|
||||
|
||||
int stlink_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) {
|
||||
DLOG("*** stlink_read_reg\n");
|
||||
DLOG(" (%d) ***\n", r_idx);
|
||||
|
||||
if (r_idx > 20 || r_idx < 0) {
|
||||
fprintf(stderr, "Error: register index must be in [0..20]\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (sl->backend->read_reg(sl, r_idx, regp));
|
||||
}
|
||||
|
||||
int stlink_read_unsupported_reg(stlink_t *sl, int r_idx,
|
||||
struct stlink_reg *regp) {
|
||||
int r_convert;
|
||||
|
||||
DLOG("*** stlink_read_unsupported_reg\n");
|
||||
DLOG(" (%d) ***\n", r_idx);
|
||||
|
||||
/* Convert to values used by STLINK_REG_DCRSR */
|
||||
if (r_idx >= 0x1C &&
|
||||
r_idx <= 0x1F) { // primask, basepri, faultmask, or control
|
||||
r_convert = 0x14;
|
||||
} else if (r_idx == 0x40) { // FPSCR
|
||||
r_convert = 0x21;
|
||||
} else if (r_idx >= 0x20 && r_idx < 0x40) {
|
||||
r_convert = 0x40 + (r_idx - 0x20);
|
||||
} else {
|
||||
fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (sl->backend->read_unsupported_reg(sl, r_convert, regp));
|
||||
}
|
||||
|
||||
int stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx,
|
||||
struct stlink_reg *regp) {
|
||||
int r_convert;
|
||||
|
||||
DLOG("*** stlink_write_unsupported_reg\n");
|
||||
DLOG(" (%d) ***\n", r_idx);
|
||||
|
||||
/* Convert to values used by STLINK_REG_DCRSR */
|
||||
if (r_idx >= 0x1C &&
|
||||
r_idx <= 0x1F) { /* primask, basepri, faultmask, or control */
|
||||
r_convert = r_idx; // the backend function handles this
|
||||
} else if (r_idx == 0x40) { // FPSCR
|
||||
r_convert = 0x21;
|
||||
} else if (r_idx >= 0x20 && r_idx < 0x40) {
|
||||
r_convert = 0x40 + (r_idx - 0x20);
|
||||
} else {
|
||||
fprintf(stderr, "Error: register address must be in [0x1C..0x40]\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (sl->backend->write_unsupported_reg(sl, val, r_convert, regp));
|
||||
}
|
Ładowanie…
Reference in New Issue