2017-08-03 01:36 AM
I'm trying to reprogram the NVM (flash bank 2) while running code from flash bank 1 in STM32L071CB microcontroller.
As AN4808 and AN4767 stand, 'the memory interface is capable of reading both banks in parallel, or reading one bank while writing to the other...' but I'm experiencing some problems:
I know I'm missing something but I can't find out what it is. Maybe someone had similar problem? I'm starting to think that there's something is wrong with the uC (errata sheet points out some problems with dual-bank switching mechanism, but it shouldn't be a problem in my case, because I'm not switching banks right now).
My function works properly when executed from RAM memory, but I'd rather want it to run from flash bank 1.
(you can take a look at the code here:
) SYSCLK is 16 MHz, checked on MCO with oscilloscope. PWR is in range 1 (the highest applicable).Thanks for any help.
#flash-read-and-write #stm32l071 #dual-bank #firmware-update Note: this post was migrated and contained many threaded conversations, some content may be missing.Solved! Go to Solution.
2017-09-19 09:43 AM
Hi,
Reading-While-Write has some limitation in case of Multiple programming operation. See
§ 3.3.4 Writing/erasing the NVM - Program half-page in Flash program memory page 82:'When a half-page operation starts, the memory interface waits for 16 addresses/data,
aborting (with a hard fault) all read accesses that are not a fetch (refer to
Fetch andprefetch
). A fetch stops the half-page operation. The memory content remains
unchanged, the FWWERR error is set in the FLASH_SR register.'
This means that no fetch operation are allowed in the flash while feeding the memory interface with the 16 words (whatever the code is running in bank 1 and the half page programming is performed in bank 2) . Once the 16 words have been sent to the memory interface, you can resume execution from flash, i.e. during the physical writing of the data inside the flash bank (assuming your code is running in the other bank).
In a nutshell, you need to execute from SRAM the feeding of the memory interface with the 16 words and make sure the interrupts will not cause fetch in flash memory (either mask all interrupts or relocate interrupt handlers and interrupts vector in SRAM).
Note: there is no such limitation in case of Single programming operation.
Regards
Bruno
2017-08-03 05:06 AM
Make sure you know exactly what part you are working with, and what die is inside. ST has had a somewhat liberal policy to die/marking, so while I think the part should act like a 128KB one, it might not.
If the die has 192 KB of FLASH the second bank starts at 0x08018000 rather than 0x08010000
Try your test at 0x08018000
2017-08-03 07:09 AM
2017-08-03 08:00 AM
Thans for your reply.
I've got CPUID = 0x410CC601 and DEVID = 0x447. It stands for ARM rev0 / arch. ARMv6-M / Cortex M0+ core / STM32L0 family / patch 1 / Device cat. 5.Reading DBGMCU->IDCODE & 0xFFFF0000 (REV_ID) gives me 'rev. Z'. Unless rev. Z stands for STM32L071xZ, then I don't think that's my problem.Reading Flash size register (at 0x1FF8007C) gave me 128 KB.
I also tried writting half-page to the address of bank 2 from 192 KB flash devices (0x08018000), but I got the same result (FWWERR).
2017-08-03 08:33 AM
Is the system free standing, or attached to a debugger? FLASH issues are best debugged by outputting telemetry via a serial port rather than via a JTAG probe, you can't control what memory the debugger will touch or poke around with.
2017-08-04 03:11 AM
Well I'm really confused right now. Today I've started debugging the same code as yesterday and FWWERR disappeared. I've tried both versions - with debugger attached and standalone. I'm trying to recreate the situation that caused FWWERR error right now. I'll let you know when something changes. The flash is still empty.
Edit:
OK, I got this error once again. This is my test code:(with ST's example code from L0 snippets my uC behaves the same way)volatile uint8_t flag_from_isr = 0;
int main(void){
SystemCoreClockUpdate();
bl_SystemInit(); // initialize nvm, pwr, bootloader uart, ...
uint8_t test = 0xFF;
bl_uart_send(&test, 1);
// currently 0x08010000 (...) is empty so there's no need to erase
/* prepare some data */
uint32_t dummydata[32], i;
for(i=0; i<32; i++){
dummydata[i] = i;
}
test = 0x1;
bl_uart_send(&test, 1);
nvm_prog_write_halfpages((uint32_t *) 0x08010000, &dummydata[0], 2); // write 2 half-pages at the beginning of flash bank 2
test = 0x2;
bl_uart_send(&test, 1);
while(1){
/* check if FWWERR occured */
if(flag_from_isr == 1){
flag_from_isr = 0;
test = 0xea;
bl_uart_send(&test, 1);
}
}
}
------------ and in another file-----------
extern uint8_t flag_from_isr;
void FLASH_IRQHandler(void){
volatile uint32_t source = FLASH->SR;
if((source & (1 << 17)) == (1 << 17)){
flag_from_isr = 1;
}
FLASH->SR |= (source & 0xFFFFFFF2); // clear all flags
}
On the oscilloscope there's a following sequence:
0xFF, 0x01, (about 350 us of delay) 0x02, 0xEA
2017-08-04 09:26 AM
You should make sure the memory is clear, test first, don't assume.
Make sure you clear any pending status from the flash controller before starting your own interactions with it, the download process can leave it in an indeterminate state.
2017-09-19 09:43 AM
Hi,
Reading-While-Write has some limitation in case of Multiple programming operation. See
§ 3.3.4 Writing/erasing the NVM - Program half-page in Flash program memory page 82:'When a half-page operation starts, the memory interface waits for 16 addresses/data,
aborting (with a hard fault) all read accesses that are not a fetch (refer to
Fetch andprefetch
). A fetch stops the half-page operation. The memory content remains
unchanged, the FWWERR error is set in the FLASH_SR register.'
This means that no fetch operation are allowed in the flash while feeding the memory interface with the 16 words (whatever the code is running in bank 1 and the half page programming is performed in bank 2) . Once the 16 words have been sent to the memory interface, you can resume execution from flash, i.e. during the physical writing of the data inside the flash bank (assuming your code is running in the other bank).
In a nutshell, you need to execute from SRAM the feeding of the memory interface with the 16 words and make sure the interrupts will not cause fetch in flash memory (either mask all interrupts or relocate interrupt handlers and interrupts vector in SRAM).
Note: there is no such limitation in case of Single programming operation.
Regards
Bruno
2017-09-21 05:05 AM
Hi,
thank you for your answer. I had to suspend my project for a while due to some (not uC realated) reasons, but when the project resumes, I'll rewrite the code. I'll probably just stick to the single programming operation.
2017-10-15 10:53 PM
I'm trying to do the same thing with my STM32L082 microcontroller, so I have been trying to use the half-page program function from HAL (RAM function)
When I use it, I still get a run-time error in the flash program status register FLASH_SR saying that the programming was interrupted by a fetch (bit 17, FWWERR). When I step through the code with a debugger, I see that the program counter is 0x0800e190, which is in the middle of bank 1 of flash, which makes me think that the HAL '__RAM_FUNC HAL_FLASHEx_HalfPageProgram' isn't actually getting compiled into RAM. Is there something special I need to do to force the function into RAM? I'm using System Workbench for STM32.
I searched around a bit and found a post that recommended I change the option in the flash_ramfunc.c file to have 'position independent code'. I checked that box but I'm still getting the FWWERR, and when I step the program counters are still in the bank 1 flash range, but now I get about a dozen PC halted console messages for every debug step.
Has anyone gotten the HAL half-page program RAM function to work, or at least load into RAM?
Thanks.
-Adrian