Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions config/chips/C011xx.chip
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Chip-ID file for STM32C011xx device
#
dev_type STM32C011xx
ref_manual_id 0490
chip_id 0x453 // STM32_CHIPID_C011xx
flash_type C0
flash_size_reg 0x1fff75a0
flash_pagesize 0x800 // 2 KB
sram_size 0x1800 // 6 KB
bootrom_base 0x1fff0000
bootrom_size 0x1800 // 6 KB
option_base 0x1fff7800 // STM32_C0_OPTION_BYTES_BASE
option_size 0x80 // 128 B
flags none
14 changes: 14 additions & 0 deletions config/chips/C031xx.chip
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Chip-ID file for STM32C031xx device
#
dev_type STM32C031xx
ref_manual_id 0490
chip_id 0x453 // STM32_CHIPID_C031xx
flash_type C0
flash_size_reg 0x1fff75a0
flash_pagesize 0x800 // 2 KB
sram_size 0x3000 // 12 KB
bootrom_base 0x1fff0000
bootrom_size 0x1800 // 6 KB
option_base 0x1fff7800 // STM32_C0_OPTION_BYTES_BASE
option_size 0x80 // 128 B
flags none
1 change: 1 addition & 0 deletions doc/supported_devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ More commonly these are:
| Product-Family | ARM Cortex Core | Product Line |
| -------------- | --------------- | ---------------------------------------------------------- |
| STM32F0 | M0 | |
| STM32C0 | M0+ | |
| STM32G0 | M0+ | |
| STM32L0 | M0+ | |
| STM32F10**0** | M3 | Value line |
Expand Down
30 changes: 19 additions & 11 deletions inc/stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,18 @@ enum stm32_core_id {
/* STM32 flash types */
enum stm32_flash_type {
STM32_FLASH_TYPE_UNKNOWN = 0,
STM32_FLASH_TYPE_F0_F1_F3 = 1,
STM32_FLASH_TYPE_F1_XL = 2,
STM32_FLASH_TYPE_F2_F4 = 3,
STM32_FLASH_TYPE_F7 = 4,
STM32_FLASH_TYPE_G0 = 5,
STM32_FLASH_TYPE_G4 = 6,
STM32_FLASH_TYPE_H7 = 7,
STM32_FLASH_TYPE_L0_L1 = 8,
STM32_FLASH_TYPE_L4 = 9,
STM32_FLASH_TYPE_L5_U5_H5 = 10,
STM32_FLASH_TYPE_WB_WL = 11,
STM32_FLASH_TYPE_C0 = 1,
STM32_FLASH_TYPE_F0_F1_F3 = 2,
STM32_FLASH_TYPE_F1_XL = 3,
STM32_FLASH_TYPE_F2_F4 = 4,
STM32_FLASH_TYPE_F7 = 5,
STM32_FLASH_TYPE_G0 = 6,
STM32_FLASH_TYPE_G4 = 7,
STM32_FLASH_TYPE_H7 = 8,
STM32_FLASH_TYPE_L0_L1 = 9,
STM32_FLASH_TYPE_L4 = 10,
STM32_FLASH_TYPE_L5_U5_H5 = 11,
STM32_FLASH_TYPE_WB_WL = 12,
};

/* STM32 chip-ids */
Expand Down Expand Up @@ -102,6 +103,7 @@ enum stm32_chipids {
STM32_CHIPID_F0 = 0x440,
STM32_CHIPID_F412 = 0x441,
STM32_CHIPID_F09x = 0x442,
STM32_CHIPID_C011xx = 0x443, /* RM0490 (revision 3), section 26.10.1 "DBG device ID code register (DBG_IDCODE)" */
STM32_CHIPID_F0xx_SMALL = 0x444,
STM32_CHIPID_F04 = 0x445,
STM32_CHIPID_F303_HD = 0x446, /* high density */
Expand All @@ -111,6 +113,7 @@ enum stm32_chipids {
STM32_CHIPID_H74xxx = 0x450, /* RM0433, p.3189 */
STM32_CHIPID_F76xxx = 0x451,
STM32_CHIPID_F72xxx = 0x452, /* Nucleo F722ZE board */
STM32_CHIPID_C031xx = 0x453, /* RM0490 (revision 3), section 26.10.1 "DBG device ID code register (DBG_IDCODE)" */
STM32_CHIPID_G0_CAT4 = 0x456, /* G051/G061 */
STM32_CHIPID_L0_CAT1 = 0x457,
STM32_CHIPID_F410 = 0x458,
Expand All @@ -136,6 +139,8 @@ enum stm32_chipids {
};

/* Constant STM32 option bytes base memory address */
#define STM32_C0_OPTION_BYTES_BASE ((uint32_t)0x1fff7800)

#define STM32_F4_OPTION_BYTES_BASE ((uint32_t)0x40023c14)

#define STM32_H7_OPTION_BYTES_BASE ((uint32_t)0x5200201c)
Expand Down Expand Up @@ -189,6 +194,9 @@ enum stm32_chipids {
#define STM32WB_DBGMCU_APB1FZR1_WWDG_STOP 11
#define STM32WB_DBGMCU_APB1FZR1_IWDG_STOP 12

#define STM32C0_RCC_AHBENR 0x40021038 // RM0490 (revision 3), section 5.4.25 "RCC register map"
#define STM32C0_RCC_DMAEN 0x00000001 // DMAEN // RM0490 (revision 3), section 5.4.25 "RCC register map"

#define STM32F1_RCC_AHBENR 0x40021014
#define STM32F1_RCC_DMAEN 0x00000003 // DMA2EN | DMA1EN

Expand Down
24 changes: 24 additions & 0 deletions inc/stm32flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,30 @@
#define FLASH_OBR_OFF ((uint32_t)0x1c)
#define FLASH_WRPR_OFF ((uint32_t)0x20)

// == STM32C0 == (RM0490)
// C0 Flash registers
#define FLASH_C0_REGS_ADDR ((uint32_t)0x40022000)
#define FLASH_C0_KEYR (FLASH_C0_REGS_ADDR + 0x08)
#define FLASH_C0_OPT_KEYR (FLASH_C0_REGS_ADDR + 0x0C)
#define FLASH_C0_SR (FLASH_C0_REGS_ADDR + 0x10)
#define FLASH_C0_CR (FLASH_C0_REGS_ADDR + 0x14)
#define FLASH_C0_OPTR (FLASH_C0_REGS_ADDR + 0x20)

// C0 Flash control register
#define FLASH_C0_CR_PNB 3
#define FLASH_C0_CR_STRT 16
#define FLASH_C0_CR_OPTSTRT 17
#define FLASH_C0_CR_OBL_LAUNCH 27
#define FLASH_C0_CR_OPTLOCK 30
#define FLASH_C0_CR_LOCK 31

// C0 Flash status register
#define FLASH_C0_SR_ERROR_MASK 0xC3F8 // [15:14], [9:3]
#define FLASH_C0_SR_PROGERR 3
#define FLASH_C0_SR_WRPERR 4
#define FLASH_C0_SR_PGAERR 5
#define FLASH_C0_SR_BSY 16

// == STM32F0 ==
#define FLASH_F0_OPTKEY1 0x45670123
#define FLASH_F0_OPTKEY2 0xcdef89ab
Expand Down
4 changes: 3 additions & 1 deletion src/stlink-lib/chipid.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ void process_chipfile(char *fname) {
buf[strlen(buf) - 1] = 0; // chomp newline
sscanf(buf, "%*s %n", &nc);
// Match human readable flash_type with enum stm32_flash_type { }.
if (strcmp(value, "F0_F1_F3") == 0) {
if(strcmp(value, "C0") == 0) {
ts->flash_type = STM32_FLASH_TYPE_C0;
} else if (strcmp(value, "F0_F1_F3") == 0) {
ts->flash_type = STM32_FLASH_TYPE_F0_F1_F3;
} else if (strcmp(value, "F1_XL") == 0) {
ts->flash_type = STM32_FLASH_TYPE_F1_XL;
Expand Down
98 changes: 78 additions & 20 deletions src/stlink-lib/common_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ uint32_t get_stm32l0_flash_base(stlink_t *sl) {
uint32_t read_flash_cr(stlink_t *sl, uint32_t bank) {
uint32_t reg, res;

if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
reg = FLASH_C0_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
reg = FLASH_F4_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F7) {
reg = FLASH_F7_CR;
Expand Down Expand Up @@ -77,7 +79,10 @@ void lock_flash(stlink_t *sl) {
uint32_t cr_lock_shift = 0, cr_reg = 0, n = 0, cr2_reg = 0;
uint32_t cr_mask = 0xffffffffu;

if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
cr_lock_shift = FLASH_C0_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) {
cr_reg = FLASH_CR;
cr_lock_shift = FLASH_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
Expand Down Expand Up @@ -132,8 +137,10 @@ void lock_flash(stlink_t *sl) {
static inline int32_t write_flash_sr(stlink_t *sl, uint32_t bank, uint32_t val) {
uint32_t sr_reg;

if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
sr_reg = FLASH_C0_SR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3 ||
sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
sr_reg = (bank == BANK_1) ? FLASH_SR : FLASH_SR2;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
sr_reg = FLASH_F4_SR;
Expand Down Expand Up @@ -162,6 +169,9 @@ static inline int32_t write_flash_sr(stlink_t *sl, uint32_t bank, uint32_t val)

void clear_flash_error(stlink_t *sl) {
switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
write_flash_sr(sl, BANK_1, FLASH_C0_SR_ERROR_MASK);
break;
case STM32_FLASH_TYPE_F0_F1_F3:
write_flash_sr(sl, BANK_1, FLASH_SR_ERROR_MASK);
break;
Expand Down Expand Up @@ -205,8 +215,10 @@ void clear_flash_error(stlink_t *sl) {
uint32_t read_flash_sr(stlink_t *sl, uint32_t bank) {
uint32_t res, sr_reg;

if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
sr_reg = FLASH_C0_SR;
} else if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
sr_reg = (bank == BANK_1) ? FLASH_SR : FLASH_SR2;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
sr_reg = FLASH_F4_SR;
Expand Down Expand Up @@ -238,9 +250,11 @@ uint32_t is_flash_busy(stlink_t *sl) {
uint32_t sr_busy_shift;
uint32_t res;

if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL) ||
(sl->flash_type == STM32_FLASH_TYPE_L0_L1)) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
sr_busy_shift = FLASH_C0_SR_BSY;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3 ||
sl->flash_type == STM32_FLASH_TYPE_F1_XL ||
sl->flash_type == STM32_FLASH_TYPE_L0_L1) {
sr_busy_shift = FLASH_SR_BSY;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
sr_busy_shift = FLASH_F4_SR_BSY;
Expand Down Expand Up @@ -286,6 +300,12 @@ int32_t check_flash_error(stlink_t *sl) {
WRPERR = PROGERR = PGAERR = 0;

switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
res = read_flash_sr(sl, BANK_1) & FLASH_C0_SR_ERROR_MASK;
WRPERR = (1 << FLASH_C0_SR_WRPERR);
PROGERR = (1 << FLASH_C0_SR_PROGERR);
PGAERR = (1 << FLASH_C0_SR_PGAERR);
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
res = read_flash_sr(sl, BANK_1) & FLASH_SR_ERROR_MASK;
Expand Down Expand Up @@ -382,8 +402,11 @@ static inline uint32_t is_flash_locked(stlink_t *sl) {
uint32_t cr_reg;
uint32_t n;

if ((sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) ||
(sl->flash_type == STM32_FLASH_TYPE_F1_XL)) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
cr_lock_shift = FLASH_C0_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3 ||
sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
cr_reg = FLASH_CR;
cr_lock_shift = FLASH_CR_LOCK;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
Expand Down Expand Up @@ -429,7 +452,9 @@ static void unlock_flash(stlink_t *sl) {
* definitive lock of the FPEC block until next reset.
*/

if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
key_reg = FLASH_C0_KEYR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F0_F1_F3) {
key_reg = FLASH_KEYR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F1_XL) {
key_reg = FLASH_KEYR;
Expand Down Expand Up @@ -497,6 +522,10 @@ int32_t lock_flash_option(stlink_t *sl) {
int32_t active_bit_level = 1;

switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
optcr_reg = FLASH_C0_CR;
optlock_shift = FLASH_C0_CR_OPTLOCK;
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
optcr_reg = FLASH_CR;
Expand Down Expand Up @@ -574,6 +603,10 @@ static bool is_flash_option_locked(stlink_t *sl) {
uint32_t n;

switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
optcr_reg = FLASH_C0_CR;
optlock_shift = FLASH_C0_CR_OPTLOCK;
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
optcr_reg = FLASH_CR;
Expand Down Expand Up @@ -633,6 +666,9 @@ static int32_t unlock_flash_option(stlink_t *sl) {
uint32_t optkey2 = FLASH_OPTKEY2;

switch (sl->flash_type) {
case STM32_FLASH_TYPE_C0:
optkey_reg = FLASH_C0_OPT_KEYR;
break;
case STM32_FLASH_TYPE_F0_F1_F3:
case STM32_FLASH_TYPE_F1_XL:
optkey_reg = FLASH_OPTKEYR;
Expand Down Expand Up @@ -726,7 +762,9 @@ void clear_flash_cr_pg(stlink_t *sl, uint32_t bank) {
uint32_t cr_reg, n;
uint32_t bit = FLASH_CR_PG;

if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
cr_reg = FLASH_F4_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_F7) {
cr_reg = FLASH_F7_CR;
Expand Down Expand Up @@ -802,8 +840,10 @@ static inline void write_flash_cr_snb(stlink_t *sl, uint32_t n, uint32_t bank) {
static void set_flash_cr_per(stlink_t *sl, uint32_t bank) {
uint32_t cr_reg, val;

if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4) {
cr_reg = FLASH_Gx_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5) {
cr_reg = FLASH_L5_NSCR;
Expand All @@ -821,8 +861,10 @@ static void set_flash_cr_per(stlink_t *sl, uint32_t bank) {
static void clear_flash_cr_per(stlink_t *sl, uint32_t bank) {
uint32_t cr_reg;

if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4) {
cr_reg = FLASH_Gx_CR;
} else if (sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5) {
cr_reg = FLASH_L5_NSCR;
Expand Down Expand Up @@ -855,7 +897,10 @@ static inline void write_flash_cr_bker_pnb(stlink_t *sl, uint32_t n) {
static void set_flash_cr_strt(stlink_t *sl, uint32_t bank) {
uint32_t val, cr_reg, cr_strt;

if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
cr_strt = 1 << FLASH_C0_CR_STRT;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
cr_reg = FLASH_F4_CR;
cr_strt = 1 << FLASH_F4_CR_STRT;
} else if (sl->flash_type == STM32_FLASH_TYPE_F7) {
Expand Down Expand Up @@ -890,7 +935,11 @@ static void set_flash_cr_strt(stlink_t *sl, uint32_t bank) {
static void set_flash_cr_mer(stlink_t *sl, bool v, uint32_t bank) {
uint32_t val, cr_reg, cr_mer, cr_pg;

if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
if (sl->flash_type == STM32_FLASH_TYPE_C0) {
cr_reg = FLASH_C0_CR;
cr_mer = 1 << FLASH_CR_MER;
cr_pg = 1 << FLASH_CR_PG;
} else if (sl->flash_type == STM32_FLASH_TYPE_F2_F4) {
cr_reg = FLASH_F4_CR;
cr_mer = 1 << FLASH_CR_MER;
cr_pg = 1 << FLASH_CR_PG;
Expand Down Expand Up @@ -1062,7 +1111,8 @@ int32_t stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) {
} else if (sl->flash_type == STM32_FLASH_TYPE_G0 ||
sl->flash_type == STM32_FLASH_TYPE_G4 ||
sl->flash_type == STM32_FLASH_TYPE_L5_U5_H5 ||
sl->flash_type == STM32_FLASH_TYPE_WB_WL) {
sl->flash_type == STM32_FLASH_TYPE_WB_WL ||
sl->flash_type == STM32_FLASH_TYPE_C0) {
uint32_t val;
unlock_flash_if(sl);
set_flash_cr_per(sl, BANK_1); // set the 'enable Flash erase' bit
Expand Down Expand Up @@ -1107,6 +1157,14 @@ int32_t stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr) {
val |= ((flash_page & 0xFF) << 3);

stlink_write_debug32(sl, FLASH_WB_CR, val);
} else if (sl->flash_type == STM32_FLASH_TYPE_C0) {
uint32_t flash_page = ((flashaddr - STM32_FLASH_BASE) / sl->flash_pgsz);
stlink_read_debug32(sl, FLASH_C0_CR, &val);

val &= ~(0xF << FLASH_C0_CR_PNB);
val |= ((flash_page & 0xF) << FLASH_C0_CR_PNB);

stlink_write_debug32(sl, FLASH_C0_CR, val);
}

set_flash_cr_strt(sl, BANK_1); // set the 'start operation' bit
Expand Down
Loading