2022-04-26 02:39 AM
Hello guys,
I am working with a STM32L071CB MCU.
Currently I am trying to backup GPS data to internal memory flash when there is not LTE connection to send later when the LTE service is restored.
Writing data to memory has been done right. I am having problem with reading back the data.
First I am using bank1(start addr 0x08000000) to store the program code and the bank 2 (start addr 0x08010000) to backup data.
The problems I am having are as follow:
If I don't unlock the memory for writing, when I try to read starting the first address of bank2 (page 512), it reads starting the first address of bank 1 (page0).
Now when unlocking the flash, I can read some data right, however some values are still read from page0 and not from page 512 as its supposed to be. Its driving me crazy.
I am attaching the relevant information:
Here is the function to read the flash:
void flashRead (uint32_t readAddr, uint32_t *readBuf, uint16_t wordCnt){
flashUnlock();
while (wordCnt--){
*readBuf = *(__IO uint32_t *)(readAddr);
readAddr += 4;
readBuf++;
}
flashLock();
}
Unlock function taken from RM:
void flashUnlock(void){
/****UNLOCK PELOCK****/
/* (1) Wait till no operation is on going */
/* (2) Check if the PELOCK is unlocked */
/* (3) Perform unlock sequence */
while ((FLASH->SR & FLASH_SR_BSY) != 0){ /* (1) */
/* For robust implementation, add here time-out management */
}
if ((FLASH->PECR & FLASH_PECR_PELOCK) != 0){ /* (2) */
FLASH->PEKEYR = FLASH_PEKEY1; /* (3) */
FLASH->PEKEYR = FLASH_PEKEY2;
}
/****UNLOCK PRGLOCK****/
/* (1) Wait till no operation is on going */
/* (2) Check that the PELOCK is unlocked */
/* (3) Check if the PRGLOCK is unlocked */
/* (4) Perform unlock sequence */
while ((FLASH->SR & FLASH_SR_BSY) != 0){ /* (1) */
/* For robust implementation, add here time-out management */
}
if ((FLASH->PECR & FLASH_PECR_PELOCK) == 0){ /* (2) */
if ((FLASH->PECR & FLASH_PECR_PRGLOCK) != 0){ /* (3) */
FLASH->PRGKEYR = FLASH_PRGKEY1; /* (4) */
FLASH->PRGKEYR = FLASH_PRGKEY2;
}
}
}
Lock function taken from RM:
void flashLock(void){
/* (1) Wait till no operation is on going */
/* (2) Locks the NVM by setting PELOCK in PECR */
while ((FLASH->SR & FLASH_SR_BSY) != 0){ /* (1) */
/* For robust implementation, add here time-out management */
}
FLASH->PECR |= FLASH_PECR_PELOCK; /* (2) */
}
Here is the data I saved in bank2 page512:
Here is the data stored in flash bank1 page0:
This is the data I am reading:
Read Buffer:
20000FC0 080000D9 0800119D 08000695
210C000B 792C3010 182CC326 FFFF2501
011B0000 00000000 001B0700 08001273
FFFFFFFF FFFFFFFF 0800119F 08001275
As you can see, underlined values not are only wrong but they belong to data in the page0 and I don't have any idea how the iteration can fetch these values out of the range of the address.
If this help, I am using multiple interrupts in my program..
Please any help would be greatly appreciated.
Solved! Go to Solution.
2022-04-26 03:35 AM
Hope it helps.
2022-04-26 03:35 AM
Hope it helps.
2022-04-26 05:52 AM
Hello thank you.
The point 1, yes I have considered it. I don't have options here: RTC registers are not enough, external memory is not available. However this device is kind of use once and and throw it away, so there is not chance of running out of write cycles.
I will try points 2 and 3. Yes, my understanding is that there is no need to unlock flash just for reading.
I just realized the point 5. Have to check it. Weird because if program code is modified the app will colapse
The address I'm passing to the function:
#define PREV_GPS_ADDR 0x08010000
uint32_t* RB;
flashRead ((uint32_t)PREV_GPS_ADDR, RB, 16);
Thanks again
2022-04-26 06:17 AM
From your screenshot, ALL of the values match up with values in 1, not just some. Some of them happen to be the same in both banks.
> If I don't unlock the memory for writing, when I try to read starting the first address of bank2 (page 512), it reads starting the first address of bank 1 (page0).
MCUs aren't prone to erratic behavior. Gotta be something in your program logic that is awry. No need to unlock the flash to read it.
2022-04-26 06:26 AM
Right, that's a fact. I just cannot figure out what I'm doing wrong
2022-04-26 08:12 PM
What I have discover is I have all the time been reading starting from 0x08000000. It does not matter which address I use or the method, the program always go to read from page0. The locking/unlocking flash was just a bad judgement, the result is always the same.
As you suggested I used memcpy as below:
void flashRead (const uint32_t *readAddr, uint32_t *readBuf, uint16_t wordCnt){
memcpy(readBuf, readAddr , wordCnt);
}
The result is the same. There is no way the program read from the address I want it to do...
The writing is fine, just write the data where I want to
Any ide what might be the problem ?
2022-04-26 10:33 PM
Well, I have found the solution. I just used a simple function that returns one address position at a time. Iterate this function thru the range of addresses I want to read (page512).
I will leave it here in case some newbie like me find the same problem:
uint32_t flashRead(uint32_t startAddr){
return *(__IO uint32_t*)startAddr;
}
uint32_t data[16];
uint32_t dataAddr = 0x08010000;
for( int i = 0; i < 16; i++){
data[i] = flashRead(dataAddr);
addr+=4;
}
Thank you all you guys for the help
2022-04-26 10:53 PM
2022-04-27 06:37 AM
Point 5 happened because I was trying different addresses. Now I've got the solution
Just to verify I will give it a try to point 3
Thank you for your help.