2014-04-02 07:13 AM
Dear,
i am getting this error, this is my flash write routine:
#include <stm32f4xx_flash.h>
#include ''flash.h''
uint8_t flash_status;
volatile uint32_t* flash_location_sect3 = (volatile uint32_t*)0x800C000;
#define FLASH_CFG_ULONGS 512
int save_data_to_flash(unsigned long *data)
{
int x;
flash_status = FLASH_COMPLETE;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR |FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
/* Get the number of the start and end sectors */
//sector_start = GetSector(FLASH_USER_START_ADDR);
//secto_end = GetSector(FLASH_USER_END_ADDR);
flash_status = FLASH_EraseSector(FLASH_Sector_3, VoltageRange_3);
if (flash_status != FLASH_COMPLETE) {
FLASH_Lock();
return ERR_BAD_ERASE;
}
for (x = 0; x < FLASH_CFG_ULONGS; ++x) {
if (*flash_location_sect3 != 0xffffffff)
return 254;
//program first run status bit
flash_status =
FLASH_ProgramWord((uint32_t)flash_location_sect3, *data);
flash_location_sect3++;
data++;
if (flash_status != FLASH_COMPLETE) {
FLASH_Lock();
return flash_status;
}
}
return -1;
}
I already checked that:
- erase works properly
- write fail probably at second FLASH_ProgramWord() (since i see the first value written correctly)
The error i am getting is FLASH_ERROR_PROGRAM (7)
Every help is welcome.
2014-04-02 07:21 AM
flash_location_sect3 is what?
You'd really help yourself if you provide complete/concise examples.2014-04-02 08:16 AM
Sry,
i updated the above code. I have seen some thread over the forum, also from you, about flash programming, and i don't see anything wrong/different in my code.2014-04-02 08:53 AM
This worked for me, in Keil on an STM32F4-DISCO
// STM32F4 FLASH - sourcer32@gmail.com
#include < stdio.h > #include ''stm32f4xx.h'' /**************************************************************************************/ #define FLASH_CFG_ULONGS 512 int save_data_to_flash(unsigned long *data) { FLASH_Status flash_status; volatile uint32_t *addr = (volatile uint32_t *)0x0800C000; // Sector 3 0x0800C000 .. 0x0800FFFF int x; flash_status = FLASH_COMPLETE; FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR |FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); flash_status = FLASH_EraseSector(FLASH_Sector_3, VoltageRange_3); if (flash_status != FLASH_COMPLETE) { FLASH_Lock(); return(66); // ERR_BAD_ERASE } for(x=0; x< FLASH_CFG_ULONGS ; x++) { if (*addr != 0xFFFFFFFF) // Not blank return(99); //program first run status bit flash_status = FLASH_ProgramWord ((uint32_t)addr, *data); if (flash_status != FLASH_COMPLETE) { printf(''ProgramWord fails @ %08X, status:%d\n'', (uint32_t)addr, flash_status); FLASH_Lock(); return((int)flash_status); } addr++; data++;}
return(-1); } /**************************************************************************************/ int main(void) { int i; puts(''FLASH Test''); for( i = 0 ; i<3; i++) printf(''#%d - save_data_to_flash status:%d\n'', i, save_data_to_flash((void *)(0x1FFF0000 + (FLASH_CFG_ULONGS * sizeof(unsigned long) * i))) ); while(1); // Don't want to exit } //****************************************************************************** // Hosting of stdio functionality through SWV - Serial Wire Viewer //****************************************************************************** #include <rt_misc.h> #pragma import(__use_no_semihosting_swi) struct __FILE { int handle; /* Add whatever you need here */ }; FILE __stdout; FILE __stdin; int fputc(int ch, FILE *f) { ITM_SendChar(ch); return(ch); } int fgetc(FILE *f) { char ch; ch = '?'; return((int)ch); } int ferror(FILE *f) { /* Your implementation of ferror */ return EOF; } void _ttywrch(int ch) { ITM_SendChar(ch); } void _sys_exit(int return_code) { label: goto label; /* endless loop */ } //****************************************************************************** #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */ /* Infinite loop */ while (1) { } } #endif //****************************************************************************** I don't understand the merits of having the address variable being global, sets you up for failure on multiple calls.2014-04-02 10:03 AM
Hi Clive,
many thanks, incredible, the fact you pointed out to avoid the address declaration as a global solved my issue: once moved the same declaration inside the function scope solved the issue and i could write correctly all the 512 32bit words block. Now i need to understand why. I mean, for a single call of the function, there shouldn't be any difference between using global or local stack address. Since the first FLASH_ProgramWord write was successful but not the second one, seems like the address get wrong at the second call. Thanks for now !2014-04-02 01:57 PM
Since i don't believe in ghosts, i went deeper in the global pointer failure.
I found an error in the linker script :i was using
.data : ALIGN(16) {
_data_beg = .;
_data_start = .;
*(.data)
*(.data*)
_data_end = .;
} >flash
instead of
.data : ALIGN(16) {
_data_beg = .;
_data_start = .;
*(.data)
*(.data*)
_data_end = .;
} >ram AT > flash
So still tanks, 2 problems solved in one thread :) now i have also globals working as expected :)
2014-04-02 02:05 PM
Watch for *(.bss) and *(.bss*) also, with things not being zero
2014-04-02 03:43 PM
Linker script example
https://drive.google.com/file/d/0B7OY5pub_GfIY01DaHY4OVp4NUk/edit?usp=sharing