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

Setting up a variable at a fixed location

Hi,

I want to reserve a space of two bytes in flash so I can change those externally. I want to read same memory location from the code.

How do I do it? 

How to read a variable from a specific memory address and how to change linker or any other file to write a specific value to that address.

Parents
  • Hi Daniel

    Please check out this main.c file, which is from an example project doing the following

    • Press button 1 to erase flash page
    • Once a flash page is erased a word is written to flash.
    • Once the word is written, it's read back and verified.

    As the example demonstrates, you will need to take care of the following when creating such an application:

    • Flash write and erase operations are asynchronous. Therefore, you should always wait for it to complete before assuming anything about the state of the Flash.
    • Flash write operations assume that the input data is in static memory, so you have to make sure that the data is valid at least until you get the event indicating that it has been written.

    /**
     * Copyright (c) 2015 - 2018, 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.
     *
     */
    /**
     * @brief Blinky Sample Application main file.
     *
     * This file contains the source code for a sample server application using the LED Button service.
     */
    
    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_err.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advdata.h"
    #include "ble_conn_params.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_sdh_soc.h"
    #include "boards.h"
    #include "app_timer.h"
    #include "app_button.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define APP_BLE_CONN_CFG_TAG        1                                   /**< Tag that identifies the BLE configuration of the SoftDevice. */
    #define APP_BLE_OBSERVER_PRIO       3                                   /**< BLE observer priority of the application. There is no need to modify this value. */
    #define APP_SOC_OBSERVER_PRIO       1                                   /**< SoC observer priority of the application. There is no need to modify this value. */
    
    #define BUTTON_DETECTION_DELAY              APP_TIMER_TICKS(50)
    
    #define DEAD_BEEF                       0xDEADBEEF                              /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    static uint32_t * const ADDRESS_ADR = (uint32_t *)0x0007ff00;  
    static const uint32_t   FLASH_PAGE  = 127; 
    
    /**@brief Test state. */
    typedef enum
    {
        TEST_STATE_ERASING,
        TEST_STATE_WRITING,
        TEST_STATE_IDLE
    } test_state_t;
    
    
    static const uint32_t m_test_words[2]       = {0x12340000, 0x0000ABCD};
    static test_state_t m_current_test_state    = TEST_STATE_IDLE;
    static uint32_t m_test_num                  = 0;
    
    
    static void flash_erase(uint32_t page_number)
    {
        uint32_t err_code;
    
        err_code = sd_flash_page_erase(page_number);
        APP_ERROR_CHECK(err_code);        
    }
    
    
    static void flash_write(uint32_t * addr, uint32_t const * word)
    {
        uint32_t err_code;
    
        err_code = sd_flash_write(addr, word, 1);
        APP_ERROR_CHECK(err_code);
    }
    
    
    // First stage of the test where flash is erased.
    static void test_erase()
    {
        NRF_LOG_INFO("Start test %u.", ++m_test_num);
        NRF_LOG_INFO("Erase flash page.");
        m_current_test_state = TEST_STATE_ERASING;
    
        flash_erase(FLASH_PAGE);
    }
    
    
    // Second stage of the test where test word is written.
    static void test_write()
    {
        NRF_LOG_INFO("Write to flash.");
        m_current_test_state = TEST_STATE_WRITING;
    
        flash_write(ADDRESS_ADR, &m_test_words[m_test_num % 2]);
    }
    
    
    // Third and last stage where the test word is read back and verified.
    static void test_verify()
    {
        NRF_LOG_INFO("Read from flash and verify.");
    
        if (*ADDRESS_ADR == m_test_words[m_test_num % 2])
        {
            NRF_LOG_INFO("Test successfull (%08x == %08x).", *ADDRESS_ADR, m_test_words[m_test_num % 2]);
        }
        else
        {
            NRF_LOG_ERROR("Test FAILED (%08x != %08x).", *ADDRESS_ADR, m_test_words[m_test_num % 2]);
        }
        
    
        m_current_test_state = TEST_STATE_IDLE;
    }
    
    
    /**@brief Function for assert macro callback.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in] line_num    Line number of the failing ASSERT call.
     * @param[in] p_file_name File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    
    /**@brief Function for the Timer initialization.
     *
     * @details Initializes the timer module.
     */
    static void timers_init(void)
    {
        // Initialize timer module, making it use the scheduler
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief SoftDevice SoC event handler.
     *
     * @param[in] evt_id    SoC event.
     * @param[in] p_context Context.
     */
    static void soc_evt_handler(uint32_t evt_id, void * p_context)
    {
        switch (evt_id)
        {
            case NRF_EVT_FLASH_OPERATION_SUCCESS:
            {
                switch (m_current_test_state)
                {
                    case TEST_STATE_ERASING:
                        NRF_LOG_INFO("Flash erase commpleated successfully.");
                        test_write();
                        break;
    
                    case TEST_STATE_WRITING:
                         NRF_LOG_INFO("Flash write commpleated successfully.");
                         test_verify();
                         break;
    
                    default:
                        NRF_LOG_ERROR("Invalid state.");
                        break;
                }
            } break;
    
            case NRF_EVT_FLASH_OPERATION_ERROR:
                NRF_LOG_INFO("Flash operations failed.");
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_SOC_OBSERVER(m_soc_observer, APP_SOC_OBSERVER_PRIO, soc_evt_handler, NULL);
    }
    
    
    /**@brief Function for handling events from the button handler module.
     *
     * @param[in] pin_no        The pin that the event applies to.
     * @param[in] button_action The button action (press/release).
     */
    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    
        switch (pin_no)
        {
            case BSP_BUTTON_0:
                if (button_action == APP_BUTTON_PUSH)
                {
                    NRF_LOG_INFO("Button pushed.");
                    test_erase();
                }
                break;
    
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }
    
    
    /**@brief Function for initializing the button handler module.
     */
    static void buttons_init(void)
    {
        ret_code_t err_code;
    
        //The array must be static because a pointer to it will be saved in the button handler module.
        static app_button_cfg_t buttons[] =
        {
            {BSP_BUTTON_0, false, BUTTON_PULL, button_event_handler}
        };
    
        err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                                   BUTTON_DETECTION_DELAY);
        APP_ERROR_CHECK(err_code);
    
        err_code = app_button_enable();
        APP_ERROR_CHECK(err_code);
    }
    
    
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
        log_init();
        timers_init();
        buttons_init();
        ble_stack_init();
    
        // Start execution.
        NRF_LOG_INFO("Flash write via SD API example started.");
        NRF_LOG_INFO("Press button 1 to write and read back random word.");
    
        // Enter main loop.
        for (;;)
        {
            sd_app_evt_wait();
        }
    }
    
    
    /**
     * @}
     */
    

    I have also attached the example project below, but keep in mind that it is for the nRF52832 DK, and some adjustments, see this Infocenter page, will likely be necessary for it to work on an nRF52810. (This example drops into SDK 15.2, so I recommend using that SDK to test this example).

    simple_flash_write_examle_with_sd.zip

    Best regards,

    Simon

  • Thanks, Simonr.

    I want to use the linker to change the content of the flash in the post-build action. 

    Is there any way to do so? 

Reply Children
No Data
Related