Skip to main content
Angelo1
Associate III
April 2, 2014
Question

stm32f4xx FLASH_ProgramWord error, FLASH_ERROR_PROGRAM

  • April 2, 2014
  • 7 replies
  • 1653 views
Posted on April 02, 2014 at 16:13

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.
    This topic has been closed for replies.

    7 replies

    Tesla DeLorean
    Guru
    April 2, 2014
    Posted on April 02, 2014 at 16:21

    flash_location_sect3 is what?

    You'd really help yourself if you provide complete/concise examples.
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Angelo1
    Angelo1Author
    Associate III
    April 2, 2014
    Posted on April 02, 2014 at 17:16

    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.

    Tesla DeLorean
    Guru
    April 2, 2014
    Posted on April 02, 2014 at 17:53

    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.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Angelo1
    Angelo1Author
    Associate III
    April 2, 2014
    Posted on April 02, 2014 at 19:03

    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 !

    Angelo1
    Angelo1Author
    Associate III
    April 2, 2014
    Posted on April 02, 2014 at 22:57

    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 :)
    Tesla DeLorean
    Guru
    April 2, 2014
    Posted on April 02, 2014 at 23:05

    Watch for *(.bss) and *(.bss*) also, with things not being zero

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    April 2, 2014
    Posted on April 03, 2014 at 00:43

    Linker script example

    https://drive.google.com/file/d/0B7OY5pub_GfIY01DaHY4OVp4NUk/edit?usp=sharing

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..