Skip to content

Commit

Permalink
Merge pull request #1354 from rcubee/c0
Browse files Browse the repository at this point in the history
Added support for STM32C0x1.
  • Loading branch information
Nightwalker-87 committed Nov 23, 2023
2 parents fb141d4 + cf840b5 commit e212349
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 43 deletions.
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 @@ -99,7 +99,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

0 comments on commit e212349

Please sign in to comment.