From 71535104e47f2a96ce6a87a6da0fc4519bc64d15 Mon Sep 17 00:00:00 2001 From: Andy Isaacson Date: Tue, 9 Jun 2015 11:15:28 -0700 Subject: [PATCH] STM32F4 8-bit support for 1.8v operation Per ST doc DM00035129.pdf "DocID022063 Rev 5", the STM32F415xx data sheet, table 40 on page 110 of the PDF, 32-bit program operation is only possible above 2.7 Volts. In order to support programming on devices running at lower voltages, this commit adds an 8-bit programming mode and the necessary tests to enable it when the reported voltage is below 2.7 Volts. --- flashloaders/stm32f4lv.s | 33 +++++++++++++++++++++++++++ src/stlink-common.c | 49 +++++++++++++++++++++++++++++++++++----- 2 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 flashloaders/stm32f4lv.s diff --git a/flashloaders/stm32f4lv.s b/flashloaders/stm32f4lv.s new file mode 100644 index 000000000..f60ee8797 --- /dev/null +++ b/flashloaders/stm32f4lv.s @@ -0,0 +1,33 @@ +.global start +.syntax unified + +@ r0 = source +@ r1 = target +@ r2 = wordcount +@ r3 = flash_base +@ r4 = temp + +start: + lsls r2, r2, #2 + ldr r3, flash_base +next: + cbz r2, done + ldrb r4, [r0] + strb r4, [r1] + +wait: + ldrh r4, [r3, #0x0e] + tst.w r4, #1 + bne wait + + add r0, #1 + add r1, #1 + sub r2, #1 + b next +done: + bkpt + +.align 2 + +flash_base: + .word 0x40023c00 diff --git a/src/stlink-common.c b/src/stlink-common.c index cbb2f255e..972c9f31c 100644 --- a/src/stlink-common.c +++ b/src/stlink-common.c @@ -65,6 +65,7 @@ //STM32L0x flash register base and offsets //same as 32L1 above +// RM0090 - DM00031020.pdf #define STM32L0_FLASH_REGS_ADDR ((uint32_t)0x40022000) #define FLASH_ACR_OFF ((uint32_t) 0x00) #define FLASH_PECR_OFF ((uint32_t) 0x04) @@ -1374,6 +1375,29 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) { 0x00, 0x3c, 0x02, 0x40, }; + static const uint8_t loader_code_stm32f4_lv[] = { + // flashloaders/stm32f4lv.s + 0x92, 0x00, + + 0x08, 0x4b, + 0x62, 0xb1, + 0x04, 0x78, + 0x0c, 0x70, + + 0xdc, 0x89, + 0x14, 0xf0, 0x01, 0x0f, + 0xfb, 0xd1, + 0x00, 0xf1, 0x01, 0x00, + 0x01, 0xf1, 0x01, 0x01, + 0xa2, 0xf1, 0x01, 0x02, + 0xf1, 0xe7, + + 0x00, 0xbe, + 0x00, 0xbf, + + 0x00, 0x3c, 0x02, 0x40, + }; + const uint8_t* loader_code; size_t loader_size; @@ -1391,15 +1415,21 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) { loader_size = sizeof(loader_code_stm32vl); } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4 || (sl->chip_id == STM32_CHIPID_F4_DE) || sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD || (sl->chip_id == STM32_CHIPID_F411RE)){ - loader_code = loader_code_stm32f4; - loader_size = sizeof(loader_code_stm32f4); + int voltage = stlink_target_voltage(sl); + if (voltage > 2700) { + loader_code = loader_code_stm32f4; + loader_size = sizeof(loader_code_stm32f4); + } else { + loader_code = loader_code_stm32f4_lv; + loader_size = sizeof(loader_code_stm32f4_lv); + } } else if (sl->chip_id == STM32_CHIPID_F0 || sl->chip_id == STM32_CHIPID_F04 || sl->chip_id == STM32_CHIPID_F0_CAN || sl->chip_id == STM32_CHIPID_F0_SMALL || sl->chip_id == STM32_CHIPID_F09X) { loader_code = loader_code_stm32f0; loader_size = sizeof(loader_code_stm32f0); } else if (sl->chip_id == STM32_CHIPID_L0) { - loader_code = loader_code_stm32l0; - loader_size = sizeof(loader_code_stm32l0); - } else { + loader_code = loader_code_stm32l0; + loader_size = sizeof(loader_code_stm32l0); + } else { ELOG("unknown coreid, not sure what flash loader to use, aborting!: %x\n", sl->core_id); return -1; } @@ -1588,7 +1618,14 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t /* TODO: Check that Voltage range is 2.7 - 3.6 V */ /* set parallelisim to 32 bit*/ - write_flash_cr_psiz(sl, 2); + int voltage = stlink_target_voltage(sl); + if (voltage > 2700) { + printf("enabling 32-bit flash writes\n"); + write_flash_cr_psiz(sl, 2); + } else { + printf("Target voltage (%d mV) too low for 32-bit flash, using 8-bit flash writes\n", voltage); + write_flash_cr_psiz(sl, 0); + } /* set programming mode */ set_flash_cr_pg(sl);