This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Hardfault

Hi. 

I just put this on my main code: 



uint32_t pg_size,* addr,pg_num,numero_guardado_memoria=0;

pg_size = NRF_FICR->CODEPAGESIZE;
pg_num = NRF_FICR->CODESIZE - 1;

addr= (uint32_t *)(pg_size * (pg_num+1));
if((uint32_t)*(addr)=='D'){
     addr=(uint32_t *)(pg_size * (pg_num + 2));
     numero_guardado_memoria=(uint32_t)*(addr);
}

to simply read what is stored in a memory position ... and ones i debug the program, just after the if.. it lauch me a hardfault...

i can't understand. 

please i need your help. 

Parents
  • Hi, 

    pg_size * (pg_num+1)  will point to a non-existing byte right after your flash memory, it's no wonder that you're catching a hardfault..

  • How can i acces to the first 32bits word after de code ? and the second one.. and so on ? 
     
    I need to storage and read info from sensors to de flash.. 

    Thanks a lot.. 

  • Could you explain me a little bit what is a page and how big in it is ? 

    Thanks a lot Dmitry (really)

  • You can read documentation about how flash memory works.

    Flash page size depends on chip: nrf51 - 1024 bytes, nrf52 - 4096 bytes.

  • Hi Dmitry, i try this: 

    IROM1: 0x1B000 to 0x3F800 (2048 less than normally) 

    And in the code: 

    doing this, writing and reading is ok 

    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-1; // Use last page in flash
    //--------------------------------- 
    addr = (uint32_t *)(pg_size * pg_num); 
    flash_page_erase(addr); 
    patwr_32 = 'D'; 
    flash_word_write(addr, patwr_32); 
    nrf_delay_ms(10);


    doing this reading is ok: 

    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-1; // Use last page in flash
    //---------------------------------
    addr = (uint32_t *)(pg_size * pg_num)+1;

    if((uint32_t)*(addr)=='D'){ //renombro
    numero_guardado_memoria=(uint32_t)*(addr);
    }

    Doing this it crashes in flash_page_erase: 

    addr = (uint32_t *)(pg_size * pg_num)+1 ;
    flash_page_erase(addr); 
    patwr_32 = 'D';
    flash_word_write(addr, patwr_32); 
    nrf_delay_ms(10);

    And with this in word_write: 

    addr = (uint32_t *)(pg_size * (pg_num+1)) ;
    flash_page_erase(addr); 
    patwr_32 = 'D';
    flash_word_write(addr, patwr_32);
    nrf_delay_ms(10);





    And finally i do this manually: 

     addr=(uint32_t *)0x5A801;

    That is 0x1B000 + 0x3F800 +1

    ( I guess it is the next position in memory that the one dedicated for code ) 

    and ALSO it gives me a hardfault

  • Hi,

    Nasib said:

    And finally i do this manually: 

     addr=(uint32_t *)0x5A801;

    That is 0x1B000 + 0x3F800 +1

    ( I guess it is the next position in memory that the one dedicated for code ) 

    and ALSO it gives me a hardfault

    This is clearly an invalid address (since it is higher than 256*1024=0x4000, so the hardfault is expected. You cannot use memory that does not exist.

  • Hi..

    The Rom1 conf (in keil) was: from 0x1b000 to 0x40000

    So i guess that memory was just for code. so i reduce it in keil conf to: 01b000 to 0x3f800

    Then i expected that those 2048 bytes were free to be used for other purposes... 

    As i understood from your reply, what i configure in keil is going to be the total amount of memory i can use in my device ?? (code + other purposes) 


    What about the other problems? 

    I think the question is easy.. but i dont know how to solve it: 

    With this everything is ok : 

    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-1; // Use last page in flash
    //--------------------------------- 
    addr = (uint32_t *)(pg_size * pg_num); 
    flash_page_erase(addr); 
    patwr_32 = 'D'; 
    flash_word_write(addr, patwr_32); 
    nrf_delay_ms(10);

    But i dont know how to store other 32bit words without having hardfaults... 




Reply
  • Hi..

    The Rom1 conf (in keil) was: from 0x1b000 to 0x40000

    So i guess that memory was just for code. so i reduce it in keil conf to: 01b000 to 0x3f800

    Then i expected that those 2048 bytes were free to be used for other purposes... 

    As i understood from your reply, what i configure in keil is going to be the total amount of memory i can use in my device ?? (code + other purposes) 


    What about the other problems? 

    I think the question is easy.. but i dont know how to solve it: 

    With this everything is ok : 

    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-1; // Use last page in flash
    //--------------------------------- 
    addr = (uint32_t *)(pg_size * pg_num); 
    flash_page_erase(addr); 
    patwr_32 = 'D'; 
    flash_word_write(addr, patwr_32); 
    nrf_delay_ms(10);

    But i dont know how to store other 32bit words without having hardfaults... 




Children
  • Hi,

    Remembering this:

    pg_size = NRF_FICR->CODEPAGESIZE; // 1024
    pg_num = NRF_FICR->CODESIZE-1; // 256-1=255 (assuming you don't have a device with small flash

    Let's look at your other code snippet (which you write fails):

    addr = (uint32_t *)(pg_size * pg_num)+1 ;
    flash_page_erase(addr); 
    patwr_32 = 'D';
    flash_word_write(addr, patwr_32); 
    nrf_delay_ms(10);

    Here you provide an address that is not the beginning of the flash page to flash_page_erase(). How does it handle that? How is flash_page_erase() implemented? Most likely you must provide the address to the first byte of the flash page. If so, you should remove the "+1" when calculating addr.

  • Hi Einar!

    These are the functions: 


    static void flash_page_erase(uint32_t * page_address){
    // Turn on flash erase enable and wait until the NVMC is ready:
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);

    while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
    {
    // Do nothing.
    }

    // Erase page:
    NRF_NVMC->ERASEPAGE = (uint32_t)page_address;

    while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
    {
    // Do nothing.
    }

    // Turn off flash erase enable and wait until the NVMC is ready:
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);

    while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
    {
    // Do nothing.
    }
    }






    and








    static void flash_word_write(uint32_t * address, uint32_t value){
    // Turn on flash write enable and wait until the NVMC is ready:
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);

    while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
    {
    // Do nothing.
    }

    *address = value;

    while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
    {
    // Do nothing.
    }

    // Turn off flash write enable and wait until the NVMC is ready:
    NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);

    while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
    {
    // Do nothing.
    }
    }








    how would you write just 4 words (32bits) in memory ?? 

    I just need to do this. 

    Which are the steps? 

    Thanks




    __________________________________________________________

    Another aproach::



    i do this in the main fuinction AND EVERYTHING WORKS OK: 

    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-1; // Use last page in flash
    //---------------------------------
    addr = (uint32_t *)(pg_size * pg_num);
    //addr=(uint32_t *)0x5A801;

    if((uint32_t)*(addr)=='D'){ //renombro
    numero_guardado_memoria=(uint32_t)*(addr);
    }
    //----------------------------------------------
    //------GUARDO D-------------------
    addr = (uint32_t *)(pg_size * pg_num)+1;
    flash_page_erase(addr); //borramos memoria
    patwr_32 = 'D';
    flash_word_write(addr, patwr_32); //guardamos D en la primera posición después de la D
    nrf_delay_ms(10);

    addr = (uint32_t *)(pg_size * pg_num)+1;
    flash_page_erase(addr); //borramos memoria
    patwr_32 = 'D';
    flash_word_write(addr, patwr_32); //guardamos D en la primera posición después de la D
    nrf_delay_ms(10);






    BUT when i try to repeat this paragraph in another function , it crashes in erasing the memory



    addr = (uint32_t *)(pg_size * pg_num)+1;
    flash_page_erase(addr); //borramos memoria
    patwr_32 = 'D'; 
    flash_word_write(addr, patwr_32); //guardamos D en la primera posición después de la D
    nrf_delay_ms(10); 

  • Hi,

    The flash_page_erase() you have implemented does not support non-page aligned addresses, which is what you provide as mentioned before. See register documentation for ERASEPAGE:

    Register for starting erase of a page in code area.

    The value is the address to the page to be erased (addresses of first word in page). Note that the erase must be enabled using CONFIG.WEN before the page can be erased. Attempts to erase pages that are outside the code area may result in undesirable behavior, e.g. the wrong page may be erased.

    You need to have control over your addresses. I suggest you consider using fstorage instead, as that will handle the low-level complexities for you. Moreover, if you make mistakes like passing invalid addresses, you will get a sensible error code returned. In this case, you would have gotten a NRF_ERROR_INVALID_ADDR returned from nrf_fstorage_erase().

  • Ok , i am going to implement the code with fstorage. But before to start i need to solve 2 concepts: 

    1) should i erase the existing word before to write a new one? 
    2) if the code ends in the X position , where can i storage data ? should i configure the keil to end short the code memory reservation? 

  • Hi,

    Nasib said:
    1) should i erase the existing word before to write a new one? 

    Yes and no. Due to the nature of flash, writing can only change '1' to '0'. So you cannot overwrite existing data unless that is already erased, or just just want to turn more bits from '1' to zero. Also due to the nature of flash, you cannot erase single words, but only full pages. Erasing a flash page means making all words in that flash page all '1's (0xFFFFFFFF).

    Nasib said:
    2) if the code ends in the X position , where can i storage data ? should i configure the keil to end short the code memory reservation?

    You can store application data in any available flash that is not occupied by the application. If you do not have a bootloader and do not use FDS or similar (used by the peer manager if you use BLE bonding), then any space above the application end address is available. But make sure to stare with a page offset, so that you are able to erase it without erasing parts of the application.

Related