Skip to content
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

Merged
merged 5 commits into from
Mar 13, 2018

Conversation

aabadie
Copy link
Contributor

@aabadie aabadie commented Mar 12, 2018

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

@aabadie aabadie added Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: new feature The issue requests / The PR implemements a new feature for RIOT CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Mar 12, 2018
@aabadie aabadie requested a review from kYc0o March 12, 2018 07:57
Copy link
Contributor

@kYc0o kYc0o left a 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.

#define CNTRL_REG (FLASH->CR)
#define CNTRL_REG_LOCK (FLASH_CR_LOCK)
#define KEY_REG (FLASH->KEYR)
#define FLASHPAGE_LIMIT (FLASHPAGE_SIZE / 2)
Copy link
Contributor

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.

FLASH->KEYR = FLASH_KEY2;
if (CNTRL_REG & CNTRL_REG_LOCK) {
KEY_REG = FLASH_KEY1;
KEY_REG = FLASH_KEY2;
Copy link
Contributor

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.

Copy link
Contributor Author

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).

Copy link
Contributor

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.

#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) {
Copy link
Contributor

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.

@vincent-d
Copy link
Member

I'd tend to prefer this approach over #7712 but I also think flashpage_write_raw could be added easily, but it could also come in a follow up as it could be implemented for every supported stm32 cpu.

@kYc0o
Copy link
Contributor

kYc0o commented Mar 12, 2018

I'd tend to prefer this approach over #7712 but I also think flashpage_write_raw could be added easily, but it could also come in a follow up as it could be implemented for every supported stm32 cpu.

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.

@aabadie aabadie force-pushed the pr/cpu/flashpage branch 3 times, most recently from d5d3e07 to 0003aae Compare March 13, 2018 10:14
@aabadie aabadie changed the title cpu/stm32l0: add support for flashpage feature cpu/stm32: unify support for flashpage/flashpage_raw with L0/L1/F0/F1 families Mar 13, 2018
@aabadie
Copy link
Contributor Author

aabadie commented Mar 13, 2018

What I propose is to add my changes to this PR

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.

Copy link
Member

@vincent-d vincent-d left a 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.

@@ -27,60 +30,150 @@

#include "periph/flashpage.h"

#if defined(CPU_FAM_STM32L0) | defined(CPU_FAM_STM32L1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

||


void flashpage_write_raw(void *target_addr, void *data, size_t len)
{
/* The actual minimal block size for writing is 16B, thus we
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it really 16B ?

Copy link
Contributor

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.

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 */
Copy link
Member

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?

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)) {}
Copy link
Member

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

/* 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++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

len / FLASHPAGE_DIV ?

}

/* finally, lock the flash module again */
DEBUG("flashpage] now locking the flash module again\n");
FLASH->CR |= FLASH_CR_LOCK;
_lock();
Copy link
Member

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

uint32_t *data_addr = (uint32_t *)data;
#else
uint16_t *dst = target_addr;
uint16_t *data_addr = (uint16_t *)data;
Copy link
Member

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?

@aabadie
Copy link
Contributor Author

aabadie commented Mar 13, 2018

@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).
Do you have an idea what could be problem ? I seems to be an alignment issue but I don't understand why.

Copy link
Member

@vincent-d vincent-d left a 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

uint16_t *dst = (uint16_t *)target_addr;
uint16_t *data_addr = (uint16_t *)data;
#endif

Copy link
Member

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

Copy link
Contributor Author

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

Copy link
Contributor Author

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.

@aabadie
Copy link
Contributor Author

aabadie commented Mar 13, 2018

@vincent-d @kYc0o, I think we are nearly good here.

Copy link
Member

@vincent-d vincent-d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK

@aabadie
Copy link
Contributor Author

aabadie commented Mar 13, 2018

@kYc0o just missing your ACK, and we are good !

@kYc0o
Copy link
Contributor

kYc0o commented Mar 13, 2018

It looks ok. I'll test and give my ACK.

@kYc0o
Copy link
Contributor

kYc0o commented Mar 13, 2018

Tested ACK.

@kYc0o kYc0o merged commit 5a05f1b into RIOT-OS:master Mar 13, 2018
*/
#define FLASHPAGE_RAW_BLOCKSIZE (2U)
/* Writing should be always 4 bytes aligned */
#define FLASHPAGE_RAW_ALIGNMENT (4U)
Copy link
Contributor Author

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 ?

Copy link
Contributor

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.

@cladmi
Copy link
Contributor

cladmi commented Mar 14, 2018

Broken on iotlab-m3. Test procedure on IoT-LAB.

dump 255
1521050271.397776;m3-380;> dump 255
# 0xff everywhere
test 255
1521050275.361341;m3-380;> test 255
     # need to type enter to see the error
1521050278.902577;m3-380;error verifying the content of page 255: >  
dump 255
1521050290.161453;m3-380;> dump 255
# 0xff everywhere

With ENABLE_DEBUG (1) its working properly

test 255
...
1521049756.371371;m3-380;[flashpage_raw] writing s to 0x807fffe
1521049756.372367;m3-380;[flashpage] write: done writing data
1521049756.373414;m3-380;flashpage_raw] now locking the flash module again
1521049756.373651;m3-380;[flashpage] locking the flash module
1521049756.375369;m3-380;wrote local page to flash page 255 at addr 0x807f800
dump 255
1521050605.346219;m3-380;> dump 255
# a b c d... as expected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants