diff options
author | bob <rea952@gmail.com> | 2018-11-24 00:40:39 +1100 |
---|---|---|
committer | Spencer Oliver <spen@spen-soft.co.uk> | 2018-12-11 13:27:49 +0000 |
commit | 077d45415796037838406f5c9293e1562413c17e (patch) | |
tree | 6bee3297fc761fbda407852ce57864a4f7f43606 /src | |
parent | cbe00ef68813f1dbc640a9acf376c81c0ea36116 (diff) | |
download | riscv-openocd-077d45415796037838406f5c9293e1562413c17e.zip riscv-openocd-077d45415796037838406f5c9293e1562413c17e.tar.gz riscv-openocd-077d45415796037838406f5c9293e1562413c17e.tar.bz2 |
flash/nor: Add support for sector erase in stm32l4x.c for L4+ family
Updates support for L4+ device id: 0x470 added by #4310
Extends #4641 to account for L4+ use of multiple DBANK option bits
Enables L4+ 1M and 2M devices to be programmed using sector erase
Change-Id: I42bb379d7d97986f4506423e3da503d07c787c6b
Signed-off-by: bob <rea952@gmail.com>
Reviewed-on: http://openocd.zylin.com/4777
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Diffstat (limited to 'src')
-rw-r--r-- | src/flash/nor/stm32l4x.c | 105 |
1 files changed, 78 insertions, 27 deletions
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index ae0ae26..7c5811e 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -33,6 +33,9 @@ * RM0394 (STM32L43x/44x/45x/46x) * http://www.st.com/resource/en/reference_manual/dm00151940.pdf * + * RM0432 (STM32L4R/4Sxx) + * http://www.st.com/resource/en/reference_manual/dm00310109.pdf + * * STM32L476RG Datasheet (for erase timing) * http://www.st.com/resource/en/datasheet/stm32l476rg.pdf * @@ -43,6 +46,14 @@ * * RM0394 devices have a single bank only. * + * RM0432 devices have single and dual bank operating modes. + * The FLASH size is 1Mbyte or 2Mbyte. + * Bank page (sector) size is 4Kbyte (dual mode) or 8Kbyte (single mode). + * + * Bank mode is controlled by two different bits in option bytes register. + * In 2M FLASH devices bit 22 (DBANK) controls Dual Bank mode. + * In 1M FLASH devices bit 21 (DB1M) controls Dual Bank mode. + * */ /* Erase time can be as high as 25ms, 10x this and assume it's toast... */ @@ -82,7 +93,7 @@ #define FLASH_BSY (1 << 16) /* Fast programming not used => related errors not used*/ #define FLASH_PGSERR (1 << 7) /* Programming sequence error */ -#define FLASH_SIZERR (1 << 6) /* Size error */ +#define FLASH_SIZERR (1 << 6) /* Size error */ #define FLASH_PGAERR (1 << 5) /* Programming alignment error */ #define FLASH_WRPERR (1 << 4) /* Write protection error */ #define FLASH_PROGERR (1 << 3) /* Programming error */ @@ -93,7 +104,8 @@ /* STM32_FLASH_OBR bit definitions (reading) */ -#define OPT_DUALBANK (1 << 21) /* dual flash bank only */ +#define OPT_DBANK_LE_1M (1 << 21) /* dual bank for devices up to 1M flash */ +#define OPT_DBANK_GE_2M (1 << 22) /* dual bank for devices with 2M flash */ /* register unlock keys */ @@ -325,7 +337,7 @@ static int stm32l4_protect_check(struct flash_bank *bank) bank->sectors[i].is_protected = 0; } else { uint8_t snb; - snb = i - stm32l4_info->bank2_start + 256; + snb = i - stm32l4_info->bank2_start; if (((snb >= wrp2a_start) && (snb <= wrp2a_end)) || ((snb >= wrp2b_start) && @@ -362,7 +374,7 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last) 1. Check that no Flash memory operation is ongoing by checking the BSY bit in the FLASH_SR register 2. Set the PER bit and select the page and bank - you wish to erase in the FLASH_CR register + you wish to erase in the FLASH_CR register 3. Set the STRT bit in the FLASH_CR register 4. Wait for the BSY bit to be cleared */ @@ -372,9 +384,9 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last) uint32_t erase_flags; erase_flags = FLASH_PER | FLASH_STRT; - if (i >= stm32l4_info->bank2_start) { + if (i >= stm32l4_info->bank2_start) { uint8_t snb; - snb = (i - stm32l4_info->bank2_start) + 256; + snb = i - stm32l4_info->bank2_start; erase_flags |= snb << FLASH_PAGE_SHIFT | FLASH_CR_BKER; } else erase_flags |= i << FLASH_PAGE_SHIFT; @@ -473,7 +485,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); - LOG_WARNING("no large enough working area available, can't do block memory writes"); + LOG_WARNING("large enough working area not available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } @@ -594,6 +606,9 @@ static int stm32l4_probe(struct flash_bank *bank) /* set max flash size depending on family */ switch (device_id & 0xfff) { + case 0x470: + max_flash_size_in_kb = 2048; + break; case 0x461: case 0x415: max_flash_size_in_kb = 1024; @@ -605,7 +620,7 @@ static int stm32l4_probe(struct flash_bank *bank) max_flash_size_in_kb = 256; break; default: - LOG_WARNING("Cannot identify target as a STM32L4 family."); + LOG_WARNING("Cannot identify target as an STM32L4 family device."); return ERROR_FAIL; } @@ -622,45 +637,77 @@ static int stm32l4_probe(struct flash_bank *bank) LOG_INFO("flash size = %dkbytes", flash_size_in_kb); - /* did we assign flash size? */ - assert(flash_size_in_kb != 0xffff); + /* did we assign a flash size? */ + assert((flash_size_in_kb != 0xffff) && flash_size_in_kb); - /* get options to for DUAL BANK. */ + /* get options for DUAL BANK. */ retval = target_read_u32(target, STM32_FLASH_OPTR, &options); if (retval != ERROR_OK) return retval; - /* did we assign flash size? */ - assert((flash_size_in_kb != 0xffff) && flash_size_in_kb); - - /* calculate numbers of pages */ - int num_pages = flash_size_in_kb / 2; - - /* check that calculation result makes sense */ - assert(num_pages > 0); + int num_pages = 0; + int page_size = 0; - /* only devices with < 1024 kiB may be set to single bank dual banks */ - if ((flash_size_in_kb == 1024) || !(options & OPT_DUALBANK)) - stm32l4_info->bank2_start = 256; - else - stm32l4_info->bank2_start = num_pages / 2; + switch (device_id & 0xfff) { + case 0x470: + /* L4R/S have 1M or 2M FLASH and dual/single bank mode. + * Page size is 4K or 8K.*/ + if (flash_size_in_kb == 2048) { + stm32l4_info->bank2_start = 256; + if (options & OPT_DBANK_GE_2M) { + page_size = 4096; + num_pages = 512; + } else { + page_size = 8192; + num_pages = 256; + } + break; + } + if (flash_size_in_kb == 1024) { + stm32l4_info->bank2_start = 128; + if (options & OPT_DBANK_LE_1M) { + page_size = 4096; + num_pages = 256; + } else { + page_size = 8192; + num_pages = 128; + } + break; + } + /* Invalid FLASH size for this device. */ + LOG_WARNING("Invalid flash size for STM32L4+ family device."); + return ERROR_FAIL; + default: + /* Other L4 family devices have 2K pages. */ + page_size = 2048; + num_pages = flash_size_in_kb / 2; + /* check that calculation result makes sense */ + assert(num_pages > 0); + if ((flash_size_in_kb == 1024) || !(options & OPT_DBANK_LE_1M)) + stm32l4_info->bank2_start = 256; + else + stm32l4_info->bank2_start = num_pages / 2; + break; + } + /* Release sector table if allocated. */ if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } + /* Set bank configuration and construct sector table. */ bank->base = base_address; - bank->size = num_pages * (1 << 11); + bank->size = num_pages * page_size; bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); if (!bank->sectors) return ERROR_FAIL; /* Checkme: What better error to use?*/ for (i = 0; i < num_pages; i++) { - bank->sectors[i].offset = i << 11; - bank->sectors[i].size = 1 << 11; + bank->sectors[i].offset = i * page_size; + bank->sectors[i].size = page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } @@ -703,6 +750,10 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) const char *device_str; switch (device_id) { + case 0x470: + device_str = "STM32L4R/4Sxx"; + break; + case 0x461: device_str = "STM32L496/4A6"; break; |