-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cpu/stm32: unify support for flashpage/flashpage_raw with L0/L1/F0/F1 families #8768
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides the comments on this PR, the flashpage_write_raw
implementation is missing and I think it can bee added at the same time, since it's trivial and adds flexibility.
On the other hand, it looks a bit like a duplicate of #7712. I'd say we could merge both implementations to give a complete flashpage driver for the stm32l CPUs.
cpu/stm32_common/periph/flashpage.c
Outdated
#define CNTRL_REG (FLASH->CR) | ||
#define CNTRL_REG_LOCK (FLASH_CR_LOCK) | ||
#define KEY_REG (FLASH->KEYR) | ||
#define FLASHPAGE_LIMIT (FLASHPAGE_SIZE / 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This FLASHPAGE_LIMIT
define is not documented and thus I don't see what is really about.
cpu/stm32_common/periph/flashpage.c
Outdated
FLASH->KEYR = FLASH_KEY2; | ||
if (CNTRL_REG & CNTRL_REG_LOCK) { | ||
KEY_REG = FLASH_KEY1; | ||
KEY_REG = FLASH_KEY2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're redefining this values, but I don't see why you don't use them below, which makes me wonder what's the use of it after all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry @kYc0o, but I'd like that you read this PR carefully before commenting (and also the datasheet). They are not reused below because they are not the same (FLASH->PEKEYR != FLASH->PRGKEYR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know the datasheet and I know what is this about (my PR was there for about 6 months), I was referring to CTRL_REG
and actually since you're defining KEY_REG
you could also define KEY_PREG
to be reused in other parts of the code, especially if your intention is to add the EEPROM driver.
cpu/stm32_common/periph/flashpage.c
Outdated
#if defined(CPU_FAM_STM32L0) | ||
DEBUG("[flashpage] unlocking the flash program memory\n"); | ||
if (!(CNTRL_REG & CNTRL_REG_LOCK)) { | ||
if (FLASH->PECR & FLASH_PECR_PRGLOCK) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This nested if's seem a bit weird to me... especially because both CTRL_REG
and FLASH->PECR
are defining the same registers.
I'd tend to prefer this approach over #7712 but I also think |
I still think we can merge both approaches, no need to add more PRs or wait for them. As I said it's trivial and adds a lot of flexibility while writing into flash. What I propose is to add my changes to this PR, if @vincent-d likes it more. |
d5d3e07
to
0003aae
Compare
0003aae
to
df326ea
Compare
Indeed there are good ideas on both sides. I updated this PR to integrate them and also added the flashpage_raw feature to stm32f0 and stm32f1. Tested in nucleo-f030, nucleo-l152 and b-l072z-lrwan1 boards and works. I'm not sure of the values for alignment and block size, so it may be worth checking that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't test it but I have some comments. Looks already good in general.
cpu/stm32_common/periph/flashpage.c
Outdated
@@ -27,60 +30,150 @@ | |||
|
|||
#include "periph/flashpage.h" | |||
|
|||
#if defined(CPU_FAM_STM32L0) | defined(CPU_FAM_STM32L1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
||
cpu/stm32_common/periph/flashpage.c
Outdated
|
||
void flashpage_write_raw(void *target_addr, void *data, size_t len) | ||
{ | ||
/* The actual minimal block size for writing is 16B, thus we |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it really 16B ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During my tests, it was actually possible to write even 4B, but I left 16B as the smallest.
cpu/stm32_common/periph/flashpage.c
Outdated
uint16_t *page_addr = flashpage_addr(page); | ||
uint16_t *data_addr = (uint16_t *)data; | ||
#endif | ||
uint32_t hsi_state = (RCC->CR & RCC_CR_HSION); | ||
|
||
/* the internal RC oscillator (HSI) must be enabled */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't it needed in flashpage_write_raw
as well?
cpu/stm32_common/periph/flashpage.c
Outdated
uint16_t *page_addr = flashpage_addr(page); | ||
uint16_t *data_addr = (uint16_t *)data; | ||
#endif | ||
uint32_t hsi_state = (RCC->CR & RCC_CR_HSION); | ||
|
||
/* the internal RC oscillator (HSI) must be enabled */ | ||
RCC->CR |= (RCC_CR_HSION); | ||
while (!(RCC->CR & RCC_CR_HSIRDY)) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could use stmclk_enable_hsi
and stmclk_disable_hsi
below
cpu/stm32_common/periph/flashpage.c
Outdated
/* set PG bit and program page to flash */ | ||
CNTRL_REG |= FLASH_CR_PG; | ||
#endif | ||
for (size_t i = 0; i < (FLASHPAGE_SIZE / FLASHPAGE_DIV); i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
len / FLASHPAGE_DIV
?
cpu/stm32_common/periph/flashpage.c
Outdated
} | ||
|
||
/* finally, lock the flash module again */ | ||
DEBUG("flashpage] now locking the flash module again\n"); | ||
FLASH->CR |= FLASH_CR_LOCK; | ||
_lock(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if it wouldn't be cleaner to lock right after erasing, as unlocking/locking are done again in flashpage_write_raw
in case of writing
cpu/stm32_common/periph/flashpage.c
Outdated
uint32_t *data_addr = (uint32_t *)data; | ||
#else | ||
uint16_t *dst = target_addr; | ||
uint16_t *data_addr = (uint16_t *)data; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is something I'm not sure to understand here: this seems to allow half-word (i.e. 2 bytes) alignment, as FLASHPAGE_DIV
seems to suggest too. But FLASHPAGE_RAW_ALIGNMENT
and FLASHPAGE_RAW_BLOCKSIZE
are 4 and then it's not allowed to write only 2 bytes.
Am I missing something?
@vincent-d @kYc0o, I tested more in depth the flashpage_raw feature: I think it works (not really sure how the test application is supposed to be used) with L0 and L1 but it crashes with F0 (I have no F1, except iotlab-m3 but have problem flashing this one). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works on b-l072z-lrwan1 but crashes on nucleo-f091 if HSI is not enabled before writing
cpu/stm32_common/periph/flashpage.c
Outdated
uint16_t *dst = (uint16_t *)target_addr; | ||
uint16_t *data_addr = (uint16_t *)data; | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HSI needs to be enabled here and disabled after locking, otherwise it crashes on stm32f091
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HSI needs to be enabled here and disabled after locking
Thanks, I'll try that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot @vincent-d, that was it! I refactored a bit the code again and tested on nucleo-l073 and nucleo-f070, it works on both.
3dc2728
to
06392bb
Compare
@vincent-d @kYc0o, I think we are nearly good here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK
@kYc0o just missing your ACK, and we are good ! |
It looks ok. I'll test and give my ACK. |
Tested ACK. |
*/ | ||
#define FLASHPAGE_RAW_BLOCKSIZE (2U) | ||
/* Writing should be always 4 bytes aligned */ | ||
#define FLASHPAGE_RAW_ALIGNMENT (4U) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cladmi, It could be one of those 2 lines, can you test with a value of 2 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With ENABLE_DEBUG (1)
in stm32_common/periph/flashpage.c
it works so it must be something else.
Broken on
With
|
Contribution description
This PR adapts the STM32 flashpage feature to make it work with the STM32L0 family. It has been tested with success on nucleo-l0xx and b-l072z-lrwan1 boards.
Issues/PRs references
None