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.. 

  • 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.

Reply
  • 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.

Children
  • So for saving (ie) two words, i have to :

    0) look for the last code position

    1) erase the next whole page after that possition

    2) write a word in the first position of that page

    3) jump a whole page

    4) erase that page

    5) write a word in the first possition of that page.


    Right? 



    I DO THIS : 


    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-2; // 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);

    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-3; // Use last page in flash


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


    And the sistem still freezing even in the flash_page_erase or in the flash_word_write (if i comment the erase function)....

    Debugging the code, just besore to erase, this page (firs word) is: 0xffffffff (so i guess the is no code there... ) 

  • Hi,

    Nasib said:
    Right? 

    Yes.

    Nasib said:

    And the sistem still freezing even in the flash_page_erase or in the flash_word_write (if i comment the erase function)....

    Debugging the code, just besore to erase, this page (firs word) is: 0xffffffff (so i guess the is no code there... ) 

    Odd. Your code works for me (with some minor cleanup). You can verify by putting this main.c file in  <SDK 12.3>\examples\peripheral\blinky\:

    /**
     * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     *
     * @defgroup blinky_example_main main.c
     * @{
     * @ingroup blinky_example
     * @brief Blinky Example Application main file.
     *
     * This file contains the source code for a sample application to blink LEDs.
     *
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "nrf_delay.h"
    #include "boards.h"
    
    
    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.
        }
    }
    
    
    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.
        }
    }
    
    
    int main(void)
    {
        uint32_t pg_size = NRF_FICR->CODEPAGESIZE;
        uint32_t pg_num = NRF_FICR->CODESIZE-2; // Use last page in flash
    
    
        uint32_t * addr = (uint32_t *)(pg_size * pg_num);
        flash_page_erase(addr); 
        char patwr_32 = 'D';
        flash_word_write(addr, patwr_32); 
        nrf_delay_ms(10);
    
        pg_num = NRF_FICR->CODESIZE-3; // Use last page in flash
    
    
        addr = (uint32_t *)(pg_size * pg_num);
        flash_page_erase(addr); 
        patwr_32 = 'X';
        flash_word_write(addr, patwr_32);
        nrf_delay_ms(10);
    
        while (true)
        {
            // Do nothing
        }
    }
    

    Using a debugger (remember to turn off optimization) you can see that the code finishes all flash operations and runs to the main loop. Then I verified that the data had been written by dumping the flash (using "nrfjprog.exe --memrd 0 --n 0x40000 > flash_dump.txt"). As you can see in the attached file (flash_dump.txt), you have the expected data written to 0x0003F800 and 0x0003F400 (using a nRF51 device with 256 kB flash).

  • Ok i discovered what is happening.. but i dont know how to solve it. 

    It works for me also, but if before the memory writing and erasing i initialize the BLE, the GPIOTE, and the TIMERS, then is when the system stops... 

    Is there any shared resource or something ? 

  • Hi,

    Nasib said:
    It works for me also, but if before the memory writing and erasing i initialize the BLE, the GPIOTE, and the TIMERS, then is when the system stops... 

    That is expected. You are not allowed to write to flash directly when the SoftDevice is active. In that case, you need to use the SoftDevice API to write to flash, or alternatively fstorage, which does this for you.

  • Ok i did this after all the initializations: 

    pg_size = NRF_FICR->CODEPAGESIZE;
    pg_num = NRF_FICR->CODESIZE-1; // Use last page in flash
    //---------------------------------
    addr = (uint32_t *)(pg_size * pg_num);
    uint32_t buffer[3]={1,2,3};
    sd_flash_page_erase(pg_num);
    nrf_delay_ms(50);
    sd_flash_write(addr,(uint32_t*)buffer,3);


    erasing the mem works perfect, but writing on it doesn't make anything... just pass over it without write anything 

Related