move components to SDK dir

This commit is contained in:
Shuanglei Tao
2025-03-03 09:06:26 +08:00
parent 20d1297e57
commit f4f4c9e60d
1021 changed files with 58 additions and 35059 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,122 @@
/**
* Copyright (c) 2016 - 2017, 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 nrf_ble_dfu DFU BLE Service
* @{
* @ingroup sdk_nrf_bootloader
* @brief Device Firmware Update (DFU) transport layer for <em>Bluetooth</em> low energy.
*
* @details The Device Firmware Update (DFU) Service is a GATT-based service that can be used for
* performing firmware updates over BLE. Note that this implementation uses
* vendor-specific UUIDs for the service and characteristics and is intended to demonstrate
* firmware updates over BLE. See @ref lib_dfu_transport_ble "DFU Transport: BLE" for more information on the service and the profile.
*/
#ifndef NRF_BLE_DFU_H__
#define NRF_BLE_DFU_H__
#include <stdint.h>
#include "ble_gatts.h"
#include "ble.h"
#ifdef __cplusplus
extern "C" {
#endif
// This is a 16-bit UUID.
#define BLE_DFU_SERVICE_UUID 0xFE59 //!< The UUID of the DFU Service.
// These UUIDs are used with the Nordic base address to create a 128-bit UUID (0x8EC9XXXXF3154F609FB8838830DAEA50).
#define BLE_DFU_CTRL_PT_UUID 0x0001 //!< The UUID of the DFU Control Point.
#define BLE_DFU_PKT_CHAR_UUID 0x0002 //!< The UUID of the DFU Packet Characteristic.
/**@brief BLE DFU opcodes.
*
* @details These types of opcodes are used in control point access.
*/
typedef enum
{
BLE_DFU_OP_CODE_CREATE_OBJECT = 0x01, /**< Value of the opcode field for a 'Create object' request. */
BLE_DFU_OP_CODE_SET_RECEIPT_NOTIF = 0x02, /**< Value of the opcode field for a 'Set Packet Receipt Notification' request. */
BLE_DFU_OP_CODE_CALCULATE_CRC = 0x03, /**< Value of the opcode field for a 'Calculating checksum' request. */
BLE_DFU_OP_CODE_EXECUTE_OBJECT = 0x04, /**< Value of the opcode field for an 'Initialize DFU parameters' request. */
BLE_DFU_OP_CODE_SELECT_OBJECT = 0x06, /**< Value of the opcode field for a 'Select object' request. */
BLE_DFU_OP_CODE_RESPONSE = 0x60 /**< Value of the opcode field for a response.*/
} ble_dfu_op_code_t;
/**@brief DFU Service.
*
* @details This structure contains status information related to the service.
*/
typedef struct
{
uint16_t service_handle; /**< Handle of the DFU Service (as provided by the SoftDevice). */
uint8_t uuid_type; /**< UUID type assigned to the DFU Service by the SoftDevice. */
ble_gatts_char_handles_t dfu_pkt_handles; /**< Handles related to the DFU Packet Characteristic. */
ble_gatts_char_handles_t dfu_ctrl_pt_handles; /**< Handles related to the DFU Control Point Characteristic. */
} ble_dfu_t;
/**@brief Function for initializing the DFU Service.
*
* @retval NRF_SUCCESS If the DFU Service and its characteristics were successfully added to the
* SoftDevice. Otherwise, an error code is returned.
*/
uint32_t ble_dfu_transport_init(void);
/**@brief Function for closing down the DFU Service and disconnecting from the host.
*
* @retval NRF_SUCCESS If the DFU Service was correctly closed down.
*/
uint32_t ble_dfu_transport_close(void);
#ifdef __cplusplus
}
#endif
#endif // NRF_BLE_DFU_H__
/** @} */

View File

@@ -0,0 +1,177 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include "nrf_dfu.h"
#include "nrf_dfu_transport.h"
#include "nrf_dfu_utils.h"
#include "nrf_bootloader_app_start.h"
#include "nrf_dfu_settings.h"
#include "nrf_gpio.h"
#include "app_scheduler.h"
#include "app_timer_appsh.h"
#include "nrf_log.h"
#include "boards.h"
#include "nrf_bootloader_info.h"
#include "nrf_dfu_req_handler.h"
#define SCHED_MAX_EVENT_DATA_SIZE MAX(APP_TIMER_SCHED_EVT_SIZE, 0) /**< Maximum size of scheduler events. */
#define SCHED_QUEUE_SIZE 20 /**< Maximum number of events in the scheduler queue. */
#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
#define APP_TIMER_OP_QUEUE_SIZE 4 /**< Size of timer operation queues. */
// Weak function implementation
/** @brief Weak implemenation of nrf_dfu_check_enter.
*
* @note This function must be overridden to enable entering DFU mode at will.
* Default behaviour is to enter DFU when BOOTLOADER_BUTTON is pressed.
*/
__WEAK bool nrf_dfu_enter_check(void)
{
if (nrf_gpio_pin_read(BOOTLOADER_BUTTON) == 0)
{
return true;
}
if (s_dfu_settings.enter_buttonless_dfu == 1)
{
s_dfu_settings.enter_buttonless_dfu = 0;
APP_ERROR_CHECK(nrf_dfu_settings_write(NULL));
return true;
}
return false;
}
// Internal Functions
/**@brief Function for initializing the timer handler module (app_timer).
*/
static void timers_init(void)
{
// Initialize timer module, making it use the scheduler.
APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, true);
}
/** @brief Function for event scheduler initialization.
*/
static void scheduler_init(void)
{
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
}
static void wait_for_event()
{
// Transport is waiting for event?
while(true)
{
// Can't be emptied like this because of lack of static variables
app_sched_execute();
}
}
void nrf_dfu_wait()
{
app_sched_execute();
}
uint32_t nrf_dfu_init()
{
uint32_t ret_val = NRF_SUCCESS;
uint32_t enter_bootloader_mode = 0;
NRF_LOG_INFO("In real nrf_dfu_init\r\n");
nrf_dfu_settings_init();
// Continue ongoing DFU operations
// Note that this part does not rely on SoftDevice interaction
ret_val = nrf_dfu_continue(&enter_bootloader_mode);
if(ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("Could not continue DFU operation: 0x%08x\r\n");
enter_bootloader_mode = 1;
}
// Check if there is a reason to enter DFU mode
// besides the effect of the continuation
if (nrf_dfu_enter_check())
{
NRF_LOG_INFO("Application sent bootloader request\n");
enter_bootloader_mode = 1;
}
if(enter_bootloader_mode != 0 || !nrf_dfu_app_is_valid())
{
timers_init();
scheduler_init();
// Initializing transports
ret_val = nrf_dfu_transports_init();
if (ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("Could not initalize DFU transport: 0x%08x\r\n");
return ret_val;
}
(void)nrf_dfu_req_handler_init();
// This function will never return
NRF_LOG_INFO("Waiting for events\r\n");
wait_for_event();
NRF_LOG_INFO("After waiting for events\r\n");
}
if (nrf_dfu_app_is_valid())
{
NRF_LOG_INFO("Jumping to: 0x%08x\r\n", MAIN_APPLICATION_START_ADDR);
nrf_bootloader_app_start(MAIN_APPLICATION_START_ADDR);
}
// Should not be reached!
NRF_LOG_INFO("After real nrf_dfu_init\r\n");
return NRF_SUCCESS;
}

View File

@@ -0,0 +1,107 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_nrf_dfu DFU bootloader
* @{
* @ingroup sdk_nrf_bootloader
* @brief Bootloader with Device Firmware Update (DFU) functionality.
*
* The DFU bootloader module, in combination with the @ref sdk_bootloader module,
* can be used to implement a bootloader that supports Device Firmware Updates.
*/
#ifndef NRF_DFU_H__
#define NRF_DFU_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
#define BOOTLOADER_BUTTON (BSP_BUTTON_3) /**< Button for entering DFU mode. */
/** @brief Function for initializing a DFU operation.
*
* This function initializes a DFU operation and any transports that are registered
* in the system.
*
* @retval NRF_SUCCESS If the DFU operation was successfully initialized.
*/
uint32_t nrf_dfu_init(void);
/** @brief Function for checking if DFU mode should be entered.
*
* This function checks whether DFU mode is required.
*
* @retval true If DFU mode must be entered.
* @retval false If there is no need to enter DFU mode.
*/
bool nrf_dfu_enter_check(void);
/** @brief Function for checking if DFU should be reset (failsafe).
*
* This function will check if DFU should be reset (failsafe).
*
* If this returns true, DFU mode will be entered and DFU will be reset.
*
* @retval true If DFU must be reset (failsafe).
* @retval false If there is no need to reset DFU.
*/
bool nrf_dfu_check_failsafe_reset(void);
/** @brief Function for blocking until an event (i.e. incoming BLE packet) arrives.
*/
void nrf_dfu_wait(void);
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_H__
/** @} */

View File

@@ -0,0 +1,317 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include "nrf_dfu_flash.h"
#include "nrf_dfu_types.h"
#include "softdevice_handler.h"
#include "nrf_nvmc.h"
#include "nrf_log.h"
#ifdef SOFTDEVICE_PRESENT
// Only include fstorage if SD interaction is required
#include "fstorage.h"
#endif
#define FLASH_FLAG_NONE (0)
#define FLASH_FLAG_OPER (1<<0)
#define FLASH_FLAG_FAILURE_SINCE_LAST (1<<1)
#define FLASH_FLAG_SD_ENABLED (1<<2)
static uint32_t m_flags;
#ifdef BLE_STACK_SUPPORT_REQD
// Function prototypes
static void fs_evt_handler(fs_evt_t const * const evt, fs_ret_t result);
FS_REGISTER_CFG(fs_config_t fs_dfu_config) =
{
.callback = fs_evt_handler, // Function for event callbacks.
.p_start_addr = (uint32_t*)MBR_SIZE,
.p_end_addr = (uint32_t*)BOOTLOADER_SETTINGS_ADDRESS + CODE_PAGE_SIZE
};
static void fs_evt_handler(fs_evt_t const * const evt, fs_ret_t result)
{
// Clear the operation flag
m_flags &= ~FLASH_FLAG_OPER;
if (result == FS_SUCCESS)
{
// Clear flag for ongoing operation and failure since last
m_flags &= ~FLASH_FLAG_FAILURE_SINCE_LAST;
}
else
{
NRF_LOG_INFO("Generating failure\r\n");
m_flags |= FLASH_FLAG_FAILURE_SINCE_LAST;
}
if (evt->p_context)
{
//lint -e611
((dfu_flash_callback_t)evt->p_context)(evt, result);
}
}
#endif
uint32_t nrf_dfu_flash_init(bool sd_enabled)
{
uint32_t err_code = NRF_SUCCESS;
#ifdef BLE_STACK_SUPPORT_REQD
// Only run this initialization if SD is enabled
if(sd_enabled)
{
NRF_LOG_INFO("------- nrf_dfu_flash_init-------\r\n");
if (fs_fake_init() != FS_SUCCESS)
{
NRF_LOG_INFO("Not initializing the thing\r\n");
return NRF_ERROR_INVALID_STATE;
}
// Enable access to the whole range
err_code = softdevice_sys_evt_handler_set(fs_sys_event_handler);
if (err_code != NRF_SUCCESS)
{
NRF_LOG_INFO("Not initializing the thing 2\r\n");
return NRF_ERROR_INVALID_STATE;
}
// Setting flag to indicate that SD is enabled to ensure fstorage is use in calls
// to do flash operations.
m_flags = FLASH_FLAG_SD_ENABLED;
}
else
#endif
{
m_flags = FLASH_FLAG_NONE;
}
return err_code;
}
fs_ret_t nrf_dfu_flash_store(uint32_t const * p_dest, uint32_t const * const p_src, uint32_t len_words, dfu_flash_callback_t callback)
{
fs_ret_t ret_val = FS_SUCCESS;
#ifdef BLE_STACK_SUPPORT_REQD
if ((m_flags & FLASH_FLAG_SD_ENABLED) != 0)
{
// Check if there is a pending error
if ((m_flags & FLASH_FLAG_FAILURE_SINCE_LAST) != 0)
{
NRF_LOG_INFO("Flash: Failure since last\r\n");
return FS_ERR_FAILURE_SINCE_LAST;
}
// Set the flag to indicate ongoing operation
m_flags |= FLASH_FLAG_OPER;
//lint -e611
ret_val = fs_store(&fs_dfu_config, p_dest, p_src, len_words, (void*)callback);
if (ret_val != FS_SUCCESS)
{
NRF_LOG_INFO("Flash: failed %d\r\n", ret_val);
return ret_val;
}
// Set the flag to indicate ongoing operation
m_flags |= FLASH_FLAG_OPER;
}
else
#endif
{
#ifndef NRF51
if ((p_src == NULL) || (p_dest == NULL))
{
return FS_ERR_NULL_ARG;
}
// Check that both pointers are word aligned.
if (((uint32_t)p_src & 0x03) ||
((uint32_t)p_dest & 0x03))
{
return FS_ERR_UNALIGNED_ADDR;
}
if (len_words == 0)
{
NRF_LOG_INFO("Flash: Invallid length (NVMC)\r\n");
return FS_ERR_INVALID_ARG;
}
#endif
nrf_nvmc_write_words((uint32_t)p_dest, p_src, len_words);
#if (__LINT__ != 1)
if (callback)
{
fs_evt_t evt =
{
.id = FS_EVT_STORE,
.p_context = (void*)callback,
.store =
{
.length_words = len_words,
.p_data = p_dest
}
};
callback(&evt, FS_SUCCESS);
}
#endif
}
return ret_val;
}
/** @brief Internal function to initialize DFU BLE transport
*/
fs_ret_t nrf_dfu_flash_erase(uint32_t const * p_dest, uint32_t num_pages, dfu_flash_callback_t callback)
{
fs_ret_t ret_val = FS_SUCCESS;
NRF_LOG_INFO("Erasing: 0x%08x, num: %d\r\n", (uint32_t)p_dest, num_pages);
#ifdef BLE_STACK_SUPPORT_REQD
if ((m_flags & FLASH_FLAG_SD_ENABLED) != 0)
{
// Check if there is a pending error
if ((m_flags & FLASH_FLAG_FAILURE_SINCE_LAST) != 0)
{
NRF_LOG_INFO("Erase: Failure since last\r\n");
return FS_ERR_FAILURE_SINCE_LAST;
}
m_flags |= FLASH_FLAG_OPER;
ret_val = fs_erase(&fs_dfu_config, p_dest, num_pages, (void*)callback);
if (ret_val != FS_SUCCESS)
{
NRF_LOG_INFO("Erase failed: %d\r\n", ret_val);
m_flags &= ~FLASH_FLAG_OPER;
return ret_val;
}
// Set the flag to indicate ongoing operation
m_flags |= FLASH_FLAG_OPER;
}
else
#endif
{
#ifndef NRF51
// Softdevice is not present or activated. Run the NVMC instead
if (((uint32_t)p_dest & (CODE_PAGE_SIZE-1)) != 0)
{
NRF_LOG_INFO("Invalid address\r\n");
return FS_ERR_UNALIGNED_ADDR;
}
#endif
uint16_t first_page = ((uint32_t)p_dest / CODE_PAGE_SIZE);
do
{
nrf_nvmc_page_erase((uint32_t)p_dest);
p_dest += CODE_PAGE_SIZE/sizeof(uint32_t);
}
while(--num_pages > 0);
if (callback)
{
#if (__LINT__ != 1)
fs_evt_t evt =
{
.id = FS_EVT_ERASE,
.p_context = (void*)callback,
.erase =
{
.first_page = first_page,
.last_page = ((uint32_t)p_dest / CODE_PAGE_SIZE)
}
};
callback(&evt, FS_SUCCESS);
#else
(void)first_page;
#endif
}
}
return ret_val;
}
void nrf_dfu_flash_error_clear(void)
{
m_flags &= ~FLASH_FLAG_FAILURE_SINCE_LAST;
}
fs_ret_t nrf_dfu_flash_wait(void)
{
NRF_LOG_INFO("Waiting for finished...\r\n");
#ifdef BLE_STACK_SUPPORT_REQD
if ((m_flags & FLASH_FLAG_SD_ENABLED) != 0)
{
while ((m_flags & FLASH_FLAG_OPER) != 0)
{
(void)sd_app_evt_wait();
}
if ((m_flags & FLASH_FLAG_FAILURE_SINCE_LAST) != 0)
{
NRF_LOG_INFO("Failure since last\r\n");
return FS_ERR_FAILURE_SINCE_LAST;
}
}
#endif
NRF_LOG_INFO("After wait!\r\n");
return FS_SUCCESS;
}

View File

@@ -0,0 +1,157 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_nrf_dfu_flash Flash operations
* @{
* @ingroup sdk_nrf_dfu
*/
#ifndef NRF_DFU_FLASH_H__
#define NRF_DFU_FLASH_H__
#include <stdint.h>
#include <stdbool.h>
#include "fstorage.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief fstorage event handler function for DFU fstorage operations.
*
* This function is intended to be registered to the fstorage module as the event handler for all DFU flash operations.
* When each flash operation has completed or failed this function will be called.
*
* See ::fs_cb_t for implementation details.
*/
typedef fs_cb_t dfu_flash_callback_t;
/**@brief Function for initializing the flash module.
*
* You can use this module with or without a SoftDevice:
* - If the module is initialized with the SoftDevice enabled flag set, the @ref fstorage
* module is used as back end for all flash operations. Flash storage calls
* are asynchronous; the SoftDevice manages when the actual operation in
* flash is done.
* - If the module is initialized with the SoftDevice enabled flag not set,
* the non-volatile memory controller (NVMC) driver handles the flash operations
* by directly accessing flash. These operations are synchronous.
*
* @param[in] sd_enabled Set the flash handling to run with or without the SoftDevice enabled.
*
* @retval NRF_SUCCESS If the operation was successful.
* @retval NRF_ERROR_INVALID_STATE If the fstorage module could not be initiated or the SoftDevice could not set the event handler.
*/
uint32_t nrf_dfu_flash_init(bool sd_enabled);
/**@brief Function for storing data to flash (with or without the SoftDevice enabled).
*
* @warning The content to be stored must be kept at @p p_src until the operation is
* complete. Without SoftDevice, the operation is complete when the function
* returns. With SoftDevice, the operation is complete when the fstorage event is received.
*
* @param[in] p_dest Pointer to the address where the data should be stored.
* @param[in] p_src Pointer to the address where the data should be copied from.
* This address can be in flash or RAM.
* @param[in] len_words The number of words to be copied from @p p_src to @p p_dest.
* @param[in] callback Pointer to the callback function.
*
* @retval FS_SUCCESS If the operation was successful.
* @retval FS_ERR_FAILURE_SINCE_LAST If an error occurred in another transaction and fstorage cannot continue before
* the event has been dealt with.
* @retval FS_ERR_UNALIGNED_ADDR If @p p_src or @p p_dest is not word-aligned. Ensure that the address pointed to is divisible by four.
* @retval FS_ERR_INVALID_ARG If @p len_words is zero. It is not possible to write zero words.
* @retval FS_ERR_NULL_ARG If @p p_src or @p p_dest is NULL.
*
* @retval FS_ERR_NOT_INITIALIZED If the fstorage module is not initialized.
* @retval FS_ERR_INVALID_CFG If the initialization of the fstorage module is invalid.
* @retval FS_ERR_QUEUE_FULL If the internal operation queue of the fstorage module is full.
*/
fs_ret_t nrf_dfu_flash_store(uint32_t const * p_dest, uint32_t const * const p_src, uint32_t len_words, dfu_flash_callback_t callback);
/**@brief Function for erasing data from flash (with or without the SoftDevice enabled).
*
* @param[in] p_dest The address of the first byte to be deleted.
* @param[in] num_pages The number of flash pages to be deleted.
* @param[in] callback Pointer to the callback function.
*
* @retval FS_SUCCESS If the operation was successful.
* @retval FS_ERR_UNALIGNED_ADDR If @p p_dest is not aligned to a page boundary.
* @retval FS_ERR_INVALID_ADDR If @p p_dest does not point to the start of a flash page or the operation would
* go beyond the flash memory boundary.
* @retval FS_ERR_NOT_INITIALIZED If the fstorage module is not initialized.
* @retval FS_ERR_INVALID_CFG If the initialization of the fstorage module is invalid.
* @retval FS_ERR_NULL_ARG If @p p_dest is NULL.
* @retval FS_ERR_INVALID_ARG If @p num_pages is zero.
* @retval FS_ERR_QUEUE_FULL If the internal operation queue of the fstorage module is full.
*/
fs_ret_t nrf_dfu_flash_erase(uint32_t const * p_dest, uint32_t num_pages, dfu_flash_callback_t callback);
/**@brief Function for clearing an error that has occurred during fstorage operations.
*/
void nrf_dfu_flash_error_clear(void);
/**@brief Function for waiting for an event from fstorage.
*
* This function halts execution until an event is received from the SoftDevice.
* You can use this function to halt execution until a flash operation has completed, to prevent
* tampering with the source data until fstorage is done with it.
*
* @retval FS_SUCCESS If the operation was successful.
* @retval FS_ERR_FAILURE_SINCE_LAST If an error has occurred in another transaction and fstorage cannot continue before
* the event has been dealt with.
*/
fs_ret_t nrf_dfu_flash_wait(void);
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_FLASH_H__
/** @} */

View File

@@ -0,0 +1,135 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include "nrf_dfu_mbr.h"
#include "nrf_mbr.h"
#include "nrf_dfu_types.h"
#include "nrf_log.h"
uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len)
{
uint32_t ret_val;
uint32_t const len_words = len / sizeof(uint32_t);
sd_mbr_command_t command =
{
.command = SD_MBR_COMMAND_COPY_BL,
.params.copy_bl.bl_src = p_src,
.params.copy_bl.bl_len = len_words
};
ret_val = sd_mbr_command(&command);
return ret_val;
}
uint32_t nrf_dfu_mbr_copy_sd(uint32_t * p_dst, uint32_t * p_src, uint32_t len)
{
uint32_t ret_val;
uint32_t const len_words = len / sizeof(uint32_t);
if((len_words & (CODE_PAGE_SIZE / sizeof(uint32_t) - 1)) != 0)
return NRF_ERROR_INVALID_LENGTH;
sd_mbr_command_t command =
{
.command = SD_MBR_COMMAND_COPY_SD,
.params.copy_sd.src = p_src,
.params.copy_sd.dst = p_dst,
.params.copy_sd.len = len_words
};
ret_val = sd_mbr_command(&command);
return ret_val;
}
uint32_t nrf_dfu_mbr_init_sd(void)
{
uint32_t ret_val;
sd_mbr_command_t command =
{
.command = SD_MBR_COMMAND_INIT_SD
};
ret_val = sd_mbr_command(&command);
return ret_val;
}
uint32_t nrf_dfu_mbr_compare(uint32_t * p_ptr1, uint32_t * p_ptr2, uint32_t len)
{
uint32_t ret_val;
uint32_t const len_words = len / sizeof(uint32_t);
sd_mbr_command_t command =
{
.command = SD_MBR_COMMAND_COMPARE,
.params.compare.ptr1 = p_ptr1,
.params.compare.ptr2 = p_ptr2,
.params.compare.len = len_words
};
ret_val = sd_mbr_command(&command);
return ret_val;
}
uint32_t nrf_dfu_mbr_vector_table_set(uint32_t address)
{
uint32_t ret_val;
NRF_LOG_INFO("running vector table set\r\n");
sd_mbr_command_t command =
{
.command = SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET,
.params.base_set.address = address
};
ret_val = sd_mbr_command(&command);
NRF_LOG_INFO("After running vector table set\r\n");
return ret_val;
}

View File

@@ -0,0 +1,120 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_nrf_dfu_mbr MBR functions
* @{
* @ingroup sdk_nrf_dfu
*/
#ifndef NRF_DFU_MBR_H__
#define NRF_DFU_MBR_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Function for copying the bootloader using an MBR command.
*
* @param[in] p_src Source address of the bootloader data to copy.
* @param[in] len Length of the data to copy in bytes.
*
* @return This function will return only if the command request could not be run.
* See @ref sd_mbr_command_copy_bl_t for possible return values.
*/
uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len);
/** @brief Function for copying the SoftDevice using an MBR command.
*
* @param[in] p_dst Target of the SoftDevice copy.
* @param[in] p_src Source address of the SoftDevice image to copy.
* @param[in] len Length of the data to copy in bytes.
*
* @retval NRF_SUCCESS indicates that the contents of the memory blocks where copied correctly.
* @retval NRF_ERROR_INVALID_LENGTH Invalid len
* @retval NRF_ERROR_NO_MEM if UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF).
* @retval NRF_ERROR_INVALID_PARAM if an invalid command is given.
* @retval NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
*/
uint32_t nrf_dfu_mbr_copy_sd(uint32_t * p_dst, uint32_t * p_src, uint32_t len);
/** @brief Function for initializing the SoftDevice using an MBR command.
*
* @retval NRF_SUCCESS If the SoftDevice was copied successfully.
* Any other return value indicates that the SoftDevice
* could not be copied.
*/
uint32_t nrf_dfu_mbr_init_sd(void);
/** @brief Function for comparing source and target using an MBR command.
*
* @param[in] p_ptr1 First pointer to data to compare.
* @param[in] p_ptr2 Second pointer to data to compare.
* @param[in] len Length of the data to compare in bytes.
*
* @retval NRF_SUCCESS If the content of both memory blocks is equal.
* @retval NRF_ERROR_NULL If the content of the memory blocks differs.
*/
uint32_t nrf_dfu_mbr_compare(uint32_t * p_ptr1, uint32_t * p_ptr2, uint32_t len);
/** @brief Function for setting the address of the vector table using an MBR command.
*
* @param[in] address Address of the new vector table.
*
* @retval NRF_SUCCESS If the address of the new vector table was set. Any other
* return value indicates that the address could not be set.
*/
uint32_t nrf_dfu_mbr_vector_table_set(uint32_t address);
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_MBR_H__
/** @} */

View File

@@ -0,0 +1,204 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_nrf_dfu_req_handler Request handling
* @{
* @ingroup sdk_nrf_dfu
*/
#ifndef NRF_DFU_REQ_HANDLER_H__
#define NRF_DFU_REQ_HANDLER_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_dfu_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**@brief DFU object types.
*/
typedef enum
{
NRF_DFU_OBJ_TYPE_INVALID, /**< Invalid object type.*/
NRF_DFU_OBJ_TYPE_COMMAND, /**< Command object packet.*/
NRF_DFU_OBJ_TYPE_DATA, /**< Data object.*/
} nrf_dfu_obj_type_t;
/**@brief DFU request operation codes.
*
* @details The DFU transport layer creates request events of these types. The implementation of @ref nrf_dfu_req_handler_on_req handles requests of these types.
*/
typedef enum
{
NRF_DFU_OBJECT_OP_NONE = 0, /**< No operation set. */
NRF_DFU_OBJECT_OP_CREATE = 1, /**< Create operation. The length of the request indicates the required size. When called, the created object is selected. */
NRF_DFU_OBJECT_OP_WRITE = 2, /**< Write operation. When called, offset and CRC of the selected object are reported back. */
NRF_DFU_OBJECT_OP_EXECUTE = 3, /**< Execute operation. When called, the selected object is executed. */
NRF_DFU_OBJECT_OP_CRC = 4, /**< Calculate checksum operation. When called, offset and CRC of the selected object are reported back. */
NRF_DFU_OBJECT_OP_SELECT = 6, /**< Select operation. When called, the object of the given type is selected, and information about the object is reported back. */
NRF_DFU_OBJECT_OP_OTHER = 7, /**< A user-defined DFU request type. The application must define how to interpret the request. */
} nrf_dfu_req_op_t;
/**@brief DFU request result codes.
*
* @details The DFU transport layer creates request events of types @ref nrf_dfu_req_op_t,
* which are handled by @ref nrf_dfu_req_handler_on_req. That functions returns one of these result codes.
*/
typedef enum
{
NRF_DFU_RES_CODE_INVALID = 0x00, /**< Invalid opcode. */
NRF_DFU_RES_CODE_SUCCESS = 0x01, /**< Operation successful. */
NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED = 0x02, /**< Opcode not supported. */
NRF_DFU_RES_CODE_INVALID_PARAMETER = 0x03, /**< Missing or invalid parameter value. */
NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES = 0x04, /**< Not enough memory for the data object. */
NRF_DFU_RES_CODE_INVALID_OBJECT = 0x05, /**< Data object does not match the firmware and hardware requirements, the signature is missing, or parsing the command failed. */
NRF_DFU_RES_CODE_UNSUPPORTED_TYPE = 0x07, /**< Not a valid object type for a Create request. */
NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED = 0x08, /**< The state of the DFU process does not allow this operation. */
NRF_DFU_RES_CODE_OPERATION_FAILED = 0x0A, /**< Operation failed. */
NRF_DFU_RES_CODE_EXT_ERROR = 0x0B, /**< Extended error. */
} nrf_dfu_res_code_t;
#if defined(__CC_ARM)
#pragma push
#pragma anon_unions
#elif defined(__ICCARM__)
#pragma language=extended
#elif defined(__GNUC__)
// Anonymous unions are enabled by default.
#endif
/** @brief Definition of a DFU request sent from the transport layer.
*
* @details When the transport layer gets a DFU event, it calls the function @ref nrf_dfu_req_handler_on_req to handle the DFU request.
*/
typedef struct
{
nrf_dfu_req_op_t req_type; /**< Request operation type. */
union
{
struct
{
uint32_t obj_type; /**< Object type of the object to be created for a request of type @ref NRF_DFU_OBJECT_OP_CREATE. */
uint32_t object_size; /**< Size of the object to be created for a request of type @ref NRF_DFU_OBJECT_OP_CREATE. Note that the object size is not the same as the size of the firmware. */
};
struct
{
uint8_t * p_req; /**< Pointer to an array holding the serialized version of the request. */
uint32_t req_len; /**< Length of the request array. */
};
};
} nrf_dfu_req_t;
/** @brief Response used during DFU operations.
*/
typedef struct
{
union
{
struct
{
uint8_t * p_res; /**< Pointer to an array holding the serialized version of the response. */
uint32_t res_len; /**< Length of the response array. */
};
struct
{
uint32_t max_size; /**< Maximum size of the object of a given type. */
uint32_t offset; /**< Current offset. */
uint32_t crc; /**< Current CRC. */
};
};
} nrf_dfu_res_t;
#if defined(__CC_ARM)
#pragma pop
#elif defined(__ICCARM__)
// Leave anonymous unions enabled.
#elif defined(__GNUC__)
// Anonymous unions are enabled by default.
#endif
/** @brief Function for initializing the request handling module.
*
* @details This function initializes the flash with or without the SoftDevice, depending on the project configuration.
*
* @retval NRF_SUCCESS If the operation was successful.
* @retval NRF_ERROR_INVALID_STATE If the fstorage module could not be initiated or the SoftDevice could not set the event handler.
*/
uint32_t nrf_dfu_req_handler_init(void);
/** @brief Function type for handling a DFU request.
*
* @param[in,out] p_context Pointer to context-specific RAM required for
* running the command request.
* This value may be NULL if the command request
* does not require context-specific RAM.
* @param[in,out] p_req Pointer to the structure holding the DFU request.
* @param[in,out] p_res Pointer to the structure holding the DFU response.
*
* @retval NRF_DFU_RES_CODE_SUCCESS If the command request was executed successfully.
* Any other error code indicates that the request
* could not be handled.
*/
nrf_dfu_res_code_t nrf_dfu_req_handler_on_req(void * p_context, nrf_dfu_req_t * p_req, nrf_dfu_res_t * p_res);
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_REQ_HANDLER_H__
/** @} */

View File

@@ -0,0 +1,260 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include "nrf_dfu_settings.h"
#include "nrf_dfu_flash.h"
#include "nrf_log.h"
#include "crc32.h"
#include <string.h>
#include "app_scheduler.h"
#include "nrf_delay.h"
/** @brief This variable reserves a codepage for bootloader specific settings,
* to ensure the compiler doesn't locate any code or variables at his location.
*/
#if defined (__CC_ARM )
uint8_t m_dfu_settings_buffer[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_SETTINGS_ADDRESS)))
__attribute__((used));
#elif defined ( __GNUC__ )
uint8_t m_dfu_settings_buffer[CODE_PAGE_SIZE] __attribute__ ((section(".bootloaderSettings")))
__attribute__((used));
#elif defined ( __ICCARM__ )
__no_init __root uint8_t m_dfu_settings_buffer[CODE_PAGE_SIZE] @ BOOTLOADER_SETTINGS_ADDRESS;
#else
#error Not a valid compiler/linker for m_dfu_settings placement.
#endif
#if defined ( NRF52 )
/**@brief This variable reserves a codepage for mbr parameters, to ensure the compiler doesn't
* locate any code or variables at his location.
*/
#if defined ( __CC_ARM )
uint8_t m_mbr_params_page[CODE_PAGE_SIZE] __attribute__((at(NRF_MBR_PARAMS_PAGE_ADDRESS))) __attribute__((used));
#elif defined ( __GNUC__ )
uint8_t m_mbr_params_page[CODE_PAGE_SIZE] __attribute__ ((section(".mbrParamsPage")));
#elif defined ( __ICCARM__ )
__no_init uint8_t m_mbr_params_page[CODE_PAGE_SIZE] @ NRF_MBR_PARAMS_PAGE_ADDRESS;
#else
#error Not a valid compiler/linker for m_mbr_params_page placement.
#endif
/**@brief This variable makes the linker script write the mbr parameters page address to the
* UICR register. This value will be written in the HEX file and thus written to the
* UICR when the bootloader is flashed into the chip.
*/
#if defined ( __CC_ARM )
uint32_t m_uicr_mbr_params_page_address __attribute__((at(NRF_UICR_MBR_PARAMS_PAGE_ADDRESS)))
= NRF_MBR_PARAMS_PAGE_ADDRESS;
#elif defined ( __GNUC__ )
volatile uint32_t m_uicr_mbr_params_page_address __attribute__ ((section(".uicrMbrParamsPageAddress")))
= NRF_MBR_PARAMS_PAGE_ADDRESS;
#elif defined ( __ICCARM__ )
__root const uint32_t m_uicr_mbr_params_page_address @ NRF_UICR_MBR_PARAMS_PAGE_ADDRESS
= NRF_MBR_PARAMS_PAGE_ADDRESS;
#else
#error Not a valid compiler/linker for m_mbr_params_page placement.
#endif
#endif // defined ( NRF52 )
nrf_dfu_settings_t s_dfu_settings;
//lint -save -esym(551, flash_operation_pending)
static bool flash_operation_pending; // barrier for reading flash
//lint -restore
static dfu_flash_callback_t m_callback;
static void dfu_settings_write_callback(fs_evt_t const * const evt, fs_ret_t result)
{
if (result == FS_SUCCESS)
{
flash_operation_pending = false;
}
if (m_callback != NULL)
{
m_callback(evt, result);
}
}
static void delay_operation(void)
{
nrf_delay_ms(100);
app_sched_execute();
}
static void wait_for_pending(void)
{
while (flash_operation_pending == true)
{
NRF_LOG_INFO("Waiting for other flash operation to finish.\r\n");
delay_operation();
}
}
static void wait_for_queue(void)
{
while (fs_queue_is_full())
{
NRF_LOG_INFO("Waiting for available space on flash queue.\r\n");
delay_operation();
}
}
uint32_t nrf_dfu_settings_calculate_crc(void)
{
// the crc is calculated from the s_dfu_settings struct, except the crc itself and the init command
return crc32_compute((uint8_t*)&s_dfu_settings + 4, sizeof(nrf_dfu_settings_t) - 4 - sizeof(s_dfu_settings.init_command), NULL);
}
void nrf_dfu_settings_init(void)
{
NRF_LOG_INFO("running nrf_dfu_settings_init\r\n");
uint32_t crc;
flash_operation_pending = false;
// Copy the DFU settings out of flash and into a buffer in RAM.
memcpy((void*)&s_dfu_settings, &m_dfu_settings_buffer[0], sizeof(nrf_dfu_settings_t));
if(s_dfu_settings.crc != 0xFFFFFFFF)
{
// CRC is set. Content must be valid
crc = nrf_dfu_settings_calculate_crc();
if(crc == s_dfu_settings.crc)
{
return;
}
}
// Reached if nothing is configured or if CRC was wrong
NRF_LOG_INFO("!!!!!!!!!!!!!!! Resetting bootloader settings !!!!!!!!!!!\r\n");
memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t));
s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION;
APP_ERROR_CHECK(nrf_dfu_settings_write(NULL));
}
ret_code_t nrf_dfu_settings_write(dfu_flash_callback_t callback)
{
ret_code_t err_code = FS_SUCCESS;
NRF_LOG_INFO("Erasing old settings at: 0x%08x\r\n", (uint32_t)&m_dfu_settings_buffer[0]);
// Wait for any ongoing operation (because of multiple calls to nrf_dfu_settings_write)
wait_for_pending();
flash_operation_pending = true;
m_callback = callback;
do
{
wait_for_queue();
// Not setting the callback function because ERASE is required before STORE
// Only report completion on successful STORE.
err_code = nrf_dfu_flash_erase((uint32_t*)&m_dfu_settings_buffer[0], 1, NULL);
} while (err_code == FS_ERR_QUEUE_FULL);
if (err_code != FS_SUCCESS)
{
NRF_LOG_ERROR("Erasing from flash memory failed.\r\n");
flash_operation_pending = false;
return NRF_ERROR_INTERNAL;
}
s_dfu_settings.crc = nrf_dfu_settings_calculate_crc();
NRF_LOG_INFO("Writing 0x%08x words\r\n", sizeof(nrf_dfu_settings_t)/4);
static nrf_dfu_settings_t temp_dfu_settings;
memcpy(&temp_dfu_settings, &s_dfu_settings, sizeof(nrf_dfu_settings_t));
do
{
wait_for_queue();
err_code = nrf_dfu_flash_store((uint32_t*)&m_dfu_settings_buffer[0],
(uint32_t*)&temp_dfu_settings,
sizeof(nrf_dfu_settings_t)/4,
dfu_settings_write_callback);
} while (err_code == FS_ERR_QUEUE_FULL);
if (err_code != FS_SUCCESS)
{
NRF_LOG_ERROR("Storing to flash memory failed.\r\n");
flash_operation_pending = false;
return NRF_ERROR_INTERNAL;
}
NRF_LOG_INFO("Writing settings...\r\n");
return NRF_SUCCESS;
}

View File

@@ -0,0 +1,89 @@
/**
* Copyright (c) 2016 - 2017, 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 nrf_dfu_settings DFU settings
* @{
* @ingroup sdk_nrf_dfu
*/
#ifndef NRF_DFU_SETTINGS_H__
#define NRF_DFU_SETTINGS_H__
#include <stdint.h>
#include "app_util_platform.h"
#include "nrf_dfu_types.h"
#include "nrf_dfu_flash.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Global DFU settings.
*
* @note Using this variable is not thread-safe.
*
*/
extern nrf_dfu_settings_t s_dfu_settings;
/** @brief Function for writing DFU settings to flash.
*
* @param[in] callback Pointer to a function that is called after completing the write operation.
*
* @retval NRF_SUCCESS If the write process was successfully initiated.
* @retval NRF_ERROR_INTERNAL If a flash error occurred.
*/
ret_code_t nrf_dfu_settings_write(dfu_flash_callback_t callback);
/** @brief Function for initializing the DFU settings module.
*/
void nrf_dfu_settings_init(void);
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_SETTINGS_H__
/**@} */

View File

@@ -0,0 +1,99 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include "nrf_dfu_transport.h"
#include "nrf_log.h"
#define DFU_TRANS_SECTION_VARS_GET(i) NRF_SECTION_VARS_GET((i), nrf_dfu_transport_t, dfu_trans)
#define DFU_TRANS_SECTION_VARS_COUNT NRF_SECTION_VARS_COUNT(nrf_dfu_transport_t, dfu_trans)
//lint -save -e19 -e526
NRF_SECTION_VARS_CREATE_SECTION(dfu_trans, const nrf_dfu_transport_t);
//lint -restore
uint32_t nrf_dfu_transports_init(void)
{
uint32_t const num_transports = DFU_TRANS_SECTION_VARS_COUNT;
uint32_t ret_val = NRF_SUCCESS;
NRF_LOG_INFO("In nrf_dfu_transports_init\r\n");
NRF_LOG_INFO("num transports: %d\r\n", num_transports);
for (uint32_t i = 0; i < num_transports; i++)
{
nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_VARS_GET(i);
ret_val = trans->init_func();
if (ret_val != NRF_SUCCESS)
{
break;
}
}
NRF_LOG_INFO("After nrf_dfu_transports_init\r\n");
return ret_val;
}
uint32_t nrf_dfu_transports_close(void)
{
uint32_t const num_transports = DFU_TRANS_SECTION_VARS_COUNT;
uint32_t ret_val = NRF_SUCCESS;
NRF_LOG_INFO("In nrf_dfu_transports_close\r\n");
NRF_LOG_INFO("num transports: %d\r\n", num_transports);
for (uint32_t i = 0; i < num_transports; i++)
{
nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_VARS_GET(i);
ret_val = trans->close_func();
if (ret_val != NRF_SUCCESS)
{
break;
}
}
NRF_LOG_INFO("After nrf_dfu_transports_init\r\n");
return ret_val;
}

View File

@@ -0,0 +1,126 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_nrf_dfu_transport DFU transport
* @{
* @ingroup sdk_nrf_bootloader
* @brief Generic Device Firmware Update (DFU) transport interface.
*
* @details The DFU transport module defines a generic interface that must
* be implemented for each transport layer.
*/
#ifndef NRF_DFU_TRANSPORT_H__
#define NRF_DFU_TRANSPORT_H__
#include <stdint.h>
#include "section_vars.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Function type for initializing a DFU transport.
*
* @details This function initializes a DFU transport. The implementation
* of the function must initialize DFU mode and stay in service
* until either the device is reset or the DFU operation is finalized.
* When the DFU transport receives requests, it should call @ref nrf_dfu_req_handler_on_req for handling the requests.
*
* @retval NRF_SUCCESS If initialization was successful for the transport. Any other return code indicates that the DFU transport could not be initialized.
*/
typedef uint32_t (*nrf_dfu_init_fn_t)(void);
/** @brief Function type for closing down a DFU transport.
*
* @details This function closes down a DFU transport in a gentle way.
*
* @retval NRF_SUCCESS If closing was successful for the transport. Any other return code indicates that the DFU transport could not be closed closed down.
*/
typedef uint32_t (*nrf_dfu_disconnect_fn_t)(void);
/** @brief DFU transport registration.
*
* @details Every DFU transport must provide a registration of the initialization function.
*/
typedef struct
{
nrf_dfu_init_fn_t init_func; /**< Registration of the init function to run to initialize a DFU transport. */
nrf_dfu_disconnect_fn_t close_func; /**< Registration of the close function to close down a DFU transport. */
} nrf_dfu_transport_t;
/** @brief Function for initializing all the registered DFU transports.
*
* @retval NRF_SUCCESS If all DFU transport were initialized successfully.
* Any other error code indicates that at least one DFU
* transport could not be initialized.
*/
uint32_t nrf_dfu_transports_init(void);
/** @brief Function for closing down all the registered DFU transports.
*
* @retval NRF_SUCCESS If all DFU transport were closed down successfully.
* Any other error code indicates that at least one DFU
* transport could not be closed down.
*/
uint32_t nrf_dfu_transports_close(void);
/** @brief Macro for registering a DFU transport by using section variables.
*
* @details This macro places a variable in a section named "dfu_trans", which
* is initialized by @ref nrf_dfu_transports_init.
*/
#define DFU_TRANSPORT_REGISTER(trans_var) NRF_SECTION_VARS_REGISTER_VAR(dfu_trans, trans_var)
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_TRANSPORT_H__
/** @} */

View File

@@ -0,0 +1,237 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_nrf_dfu_types DFU types
* @{
* @ingroup sdk_nrf_dfu
*/
#ifndef NRF_DFU_TYPES_H__
#define NRF_DFU_TYPES_H__
#include <stdint.h>
#include <stddef.h>
#include "nrf_mbr.h"
#include "nrf_sdm.h"
#ifdef __cplusplus
extern "C" {
#endif
#define INIT_COMMAND_MAX_SIZE 256 /**< Maximum size of the init command stored in dfu_settings. */
/** @brief Size of a flash codepage. This value is used for calculating the size of the reserved
* flash space in the bootloader region. It is checked against NRF_UICR->CODEPAGESIZE
* at run time to ensure that the region is correct.
*/
#if defined(NRF51)
#define CODE_PAGE_SIZE (PAGE_SIZE_IN_WORDS*sizeof(uint32_t))
#elif defined(NRF52)
#define CODE_PAGE_SIZE (MBR_PAGE_SIZE_IN_WORDS*sizeof(uint32_t))
#else
#error "Architecture not set."
#endif
/** @brief Maximum size of a data object.*/
#ifdef NRF51
#define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE * 4)
#elif NRF52
#define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE)
#else
#error "Architecture not set."
#endif
/** @brief Page location of the bootloader settings address.
*/
#if defined (NRF51 )
#define BOOTLOADER_SETTINGS_ADDRESS (0x0003FC00UL)
#elif defined ( NRF52 )
#define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL)
#else
#error No valid target set for BOOTLOADER_SETTINGS_ADDRESS.
#endif
#if defined(NRF52)
/**
* @brief MBR parameters page in UICR.
*
* Register location in UICR where the page address of the MBR parameters page is stored (only used by the nRF52 MBR).
*
* @note If the value at the given location is 0xFFFFFFFF, no MBR parameters page is set.
*/
#define NRF_UICR_MBR_PARAMS_PAGE_ADDRESS (NRF_UICR_BASE + 0x18)
/** @brief Page location of the MBR parameters page address.
*
*/
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL)
#endif
/** @brief Size of the flash space reserved for application data.
*/
#ifndef DFU_APP_DATA_RESERVED
#define DFU_APP_DATA_RESERVED CODE_PAGE_SIZE * 3
#endif
/** @brief Total size of the region between the SoftDevice and the bootloader.
*/
#define DFU_REGION_TOTAL_SIZE ((* (uint32_t *)NRF_UICR_BOOTLOADER_START_ADDRESS) - CODE_REGION_1_START)
/** @brief Start address of the SoftDevice (excluding the area for the MBR).
*/
#define SOFTDEVICE_REGION_START MBR_SIZE
/** @brief Size of the Code Region 0, found in the UICR.CLEN0 register.
*
* @details This value is identical to the start of Code Region 1. This value is used for
* compilation safety, because the linker will fail if the application expands
* into the bootloader. At run time, the bootloader uses the value found in UICR.CLEN0.
*/
#ifndef CODE_REGION_1_START
#define CODE_REGION_1_START SD_SIZE_GET(MBR_SIZE)
#endif
#define NRF_DFU_CURRENT_BANK_0 0x00
#define NRF_DFU_CURRENT_BANK_1 0x01
#define NRF_DFU_BANK_LAYOUT_DUAL 0x00
#define NRF_DFU_BANK_LAYOUT_SINGLE 0x01
/** @brief DFU bank state codes.
*
* @details The DFU bank state indicates the content of a bank:
* A valid image of a certain type or an invalid image.
*/
#define NRF_DFU_BANK_INVALID 0x00 /**< Invalid image. */
#define NRF_DFU_BANK_VALID_APP 0x01 /**< Valid application. */
#define NRF_DFU_BANK_VALID_SD 0xA5 /**< Valid SoftDevice. */
#define NRF_DFU_BANK_VALID_BL 0xAA /**< Valid bootloader. */
#define NRF_DFU_BANK_VALID_SD_BL 0xAC /**< Valid SoftDevice and bootloader. */
/** @brief Description of a single bank. */
#pragma pack(4)
typedef struct
{
uint32_t image_size; /**< Size of the image in the bank. */
uint32_t image_crc; /**< CRC of the image. If set to 0, the CRC is ignored. */
uint32_t bank_code; /**< Identifier code for the bank. */
} nrf_dfu_bank_t;
/**@brief DFU progress.
*
* Be aware of the difference between objects and firmware images. A firmware image consists of multiple objects, each of a maximum size @ref DATA_OBJECT_MAX_SIZE.
*/
typedef struct
{
uint32_t command_size; /**< The size of the current init command stored in the DFU settings. */
uint32_t command_offset; /**< The offset of the currently received init command data. The offset will increase as the init command is received. */
uint32_t command_crc; /**< The calculated CRC of the init command (calculated after the transfer is completed). */
uint32_t data_object_size; /**< The size of the last object created. Note that this size is not the size of the whole firmware image.*/
uint32_t firmware_image_crc; /**< CRC value of the current firmware (continuously calculated as data is received). */
uint32_t firmware_image_crc_last; /**< The CRC of the last executed object. */
uint32_t firmware_image_offset; /**< The offset of the current firmware image being transferred. Note that this offset is the offset in the entire firmware image and not only the current object. */
uint32_t firmware_image_offset_last;/**< The offset of the last executed object from the start of the firmware image. */
} dfu_progress_t;
/**@brief DFU settings for application and bank data.
*/
typedef struct
{
uint32_t crc; /**< CRC for the stored DFU settings, not including the CRC itself. If 0xFFFFFFF, the CRC has never been calculated. */
uint32_t settings_version; /**< Version of the currect dfu settings struct layout.*/
uint32_t app_version; /**< Version of the last stored application. */
uint32_t bootloader_version; /**< Version of the last stored bootloader. */
uint32_t bank_layout; /**< Bank layout: single bank or dual bank. This value can change. */
uint32_t bank_current; /**< The bank that is currently used. */
nrf_dfu_bank_t bank_0; /**< Bank 0. */
nrf_dfu_bank_t bank_1; /**< Bank 1. */
uint32_t write_offset; /**< Write offset for the current operation. */
uint32_t sd_size; /**< SoftDevice size (if combined BL and SD). */
dfu_progress_t progress; /**< Current DFU progress. */
uint32_t enter_buttonless_dfu;
uint8_t init_command[INIT_COMMAND_MAX_SIZE]; /**< Buffer for storing the init command. */
} nrf_dfu_settings_t;
#pragma pack() // revert pack settings
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_TYPES_H__
/** @} */

View File

@@ -0,0 +1,574 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include "nrf_dfu_utils.h"
#include <string.h>
#include "nrf_dfu_settings.h"
#include "nrf_dfu_mbr.h"
#include "nrf_bootloader_app_start.h"
#include "nrf_bootloader_info.h"
#include "crc32.h"
#include "nrf_log.h"
static uint32_t align_to_page(uint32_t val, uint32_t page_size)
{
return ((val + page_size - 1 ) &~ (page_size - 1));
}
static void nrf_dfu_invalidate_bank(nrf_dfu_bank_t * p_bank)
{
// Set the bank-code to invalid, and reset size/CRC
memset(p_bank, 0, sizeof(nrf_dfu_bank_t));
// Reset write pointer after completed operation
s_dfu_settings.write_offset = 0;
// Reset SD size
s_dfu_settings.sd_size = 0;
// Promote dual bank layout
s_dfu_settings.bank_layout = NRF_DFU_BANK_LAYOUT_DUAL;
// Signify that bank 0 is empty
s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0;
}
/** @brief Function to continue App update
*
* @details This function will be called after reset if there is a valid application in Bank1
* required to be copied down to bank0.
*
* @param[in] src_addr Source address of the application to copy from Bank1 to Bank0.
*
* @retval NRF_SUCCESS Continuation was successful.
* @retval NRF_ERROR_NULL Invalid data during compare.
* @retval FS_ERR_UNALIGNED_ADDR A call to fstorage was not aligned to a page boundary or the address was not word aliged.
* @retval FS_ERR_INVALID_ADDR The destination of a call to fstorage does not point to
* the start of a flash page or the operation would
* go beyond the flash memory boundary.
* @retval FS_ERR_NOT_INITIALIZED The fstorage module is not initialized.
* @retval FS_ERR_INVALID_CFG The initialization of the fstorage module is invalid.
* @retval FS_ERR_NULL_ARG A call to fstorage had an invalid NULL argument.
* @retval FS_ERR_INVALID_ARG A call to fstorage had invalid arguments.
* @retval FS_ERR_QUEUE_FULL If the internal operation queue of the fstorage module is full.
* @retval FS_ERR_FAILURE_SINCE_LAST If an error occurred in another transaction and fstorage cannot continue before
* the event has been dealt with.
*/
static uint32_t nrf_dfu_app_continue(uint32_t src_addr)
{
// This function only in use when new app is present in bank 1
uint32_t const image_size = s_dfu_settings.bank_1.image_size;
uint32_t const split_size = CODE_PAGE_SIZE; // Arbitrary number that must be page aligned
uint32_t ret_val = NRF_SUCCESS;
uint32_t target_addr = MAIN_APPLICATION_START_ADDR + s_dfu_settings.write_offset;
uint32_t length_left = (image_size - s_dfu_settings.write_offset);
uint32_t cur_len;
uint32_t crc;
NRF_LOG_INFO("Enter nrf_dfu_app_continue\r\n");
// Copy the application down safely
do
{
cur_len = (length_left > split_size) ? split_size : length_left;
// Erase the target page
ret_val = nrf_dfu_flash_erase((uint32_t*) target_addr, split_size / CODE_PAGE_SIZE, NULL);
if (ret_val != NRF_SUCCESS)
{
return ret_val;
}
// Flash one page
ret_val = nrf_dfu_flash_store((uint32_t*)target_addr, (uint32_t*)src_addr, cur_len, NULL);
if (ret_val != NRF_SUCCESS)
{
return ret_val;
}
ret_val = nrf_dfu_mbr_compare((uint32_t*)target_addr, (uint32_t*)src_addr, cur_len);
if (ret_val != NRF_SUCCESS)
{
// We will not retry the copy
NRF_LOG_INFO("Invalid data during compare: target: 0x%08x, src: 0x%08x\r\n", target_addr, src_addr);
return ret_val;
}
// Erase the head (to handle growing bank 0)
ret_val = nrf_dfu_flash_erase((uint32_t*) src_addr, split_size / CODE_PAGE_SIZE, NULL);
if (ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("App update: Failure erasing page at addr: 0x%08x\r\n", src_addr);
return ret_val;
}
s_dfu_settings.write_offset += cur_len;
ret_val = nrf_dfu_settings_write(NULL);
target_addr += cur_len;
src_addr += cur_len;
length_left -= cur_len;
}
while(length_left > 0);
// Check the crc of the copied data. Enable if so.
crc = crc32_compute((uint8_t*)MAIN_APPLICATION_START_ADDR, image_size, NULL);
if (crc == s_dfu_settings.bank_1.image_crc)
{
NRF_LOG_INFO("Setting app as valid\r\n");
s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_VALID_APP;
s_dfu_settings.bank_0.image_crc = crc;
s_dfu_settings.bank_0.image_size = image_size;
}
else
{
NRF_LOG_INFO("CRC computation failed for copied app: src crc: 0x%08x, res crc: 0x08x\r\n", s_dfu_settings.bank_1.image_crc, crc);
}
nrf_dfu_invalidate_bank(&s_dfu_settings.bank_1);
ret_val = nrf_dfu_settings_write(NULL);
return ret_val;
}
/** @brief Function to execute the continuation of a SoftDevice update.
*
* @param[in] src_addr Source address of the SoftDevice to copy from.
* @param[in] p_bank Pointer to the bank where the SoftDevice resides.
*
* @retval NRF_SUCCESS Continuation was successful.
* @retval NRF_ERROR_INVALID_LENGTH Invalid len
* @retval NRF_ERROR_NO_MEM if UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF).
* @retval NRF_ERROR_INVALID_PARAM if an invalid command is given.
* @retval NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
* @retval NRF_ERROR_NULL If the content of the memory blocks differs after copying.
*/
static uint32_t nrf_dfu_sd_continue_impl(uint32_t src_addr,
nrf_dfu_bank_t * p_bank)
{
uint32_t ret_val = NRF_SUCCESS;
uint32_t target_addr = SOFTDEVICE_REGION_START + s_dfu_settings.write_offset;
uint32_t length_left = align_to_page(s_dfu_settings.sd_size - s_dfu_settings.write_offset, CODE_PAGE_SIZE);
uint32_t split_size = align_to_page(length_left / 4, CODE_PAGE_SIZE);
NRF_LOG_INFO("Enter nrf_bootloader_dfu_sd_continue\r\n");
// This can be a continuation due to a power failure
src_addr += s_dfu_settings.write_offset;
if (s_dfu_settings.sd_size != 0 && s_dfu_settings.write_offset == s_dfu_settings.sd_size)
{
NRF_LOG_INFO("SD already copied\r\n");
return NRF_SUCCESS;
}
NRF_LOG_INFO("Updating SD. Old SD ver: 0x%04x\r\n", SD_FWID_GET(MBR_SIZE));
do
{
NRF_LOG_INFO("Copying [0x%08x-0x%08x] to [0x%08x-0x%08x]: Len: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);
// Copy a chunk of the SD. Size in words
ret_val = nrf_dfu_mbr_copy_sd((uint32_t*)target_addr, (uint32_t*)src_addr, split_size);
if (ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("Failed to copy SD: target: 0x%08x, src: 0x%08x, len: 0x%08x\r\n", target_addr, src_addr, split_size);
return ret_val;
}
NRF_LOG_INFO("Finished copying [0x%08x-0x%08x] to [0x%08x-0x%08x]: Len: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);
// Validate copy. Size in words
ret_val = nrf_dfu_mbr_compare((uint32_t*)target_addr, (uint32_t*)src_addr, split_size);
if (ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("Failed to Compare SD: target: 0x%08x, src: 0x%08x, len: 0x%08x\r\n", target_addr, src_addr, split_size);
return ret_val;
}
NRF_LOG_INFO("Validated 0x%08x-0x%08x to 0x%08x-0x%08x: Size: 0x%08x\r\n", src_addr, src_addr + split_size, target_addr, target_addr + split_size, split_size);
target_addr += split_size;
src_addr += split_size;
if (split_size > length_left)
{
length_left = 0;
}
else
{
length_left -= split_size;
}
NRF_LOG_INFO("Finished with the SD update.\r\n");
// Save the updated point of writes in case of power loss
s_dfu_settings.write_offset = s_dfu_settings.sd_size - length_left;
ret_val = nrf_dfu_settings_write(NULL);
}
while (length_left > 0);
return ret_val;
}
/** @brief Function to continue SoftDevice update
*
* @details This function will be called after reset if there is a valid SoftDevice in Bank0 or Bank1
* required to be relocated and activated through MBR commands.
*
* @param[in] src_addr Source address of the SoftDevice to copy from.
* @param[in] p_bank Pointer to the bank where the SoftDevice resides.
*
* @retval NRF_SUCCESS Continuation was successful.
* @retval NRF_ERROR_INVALID_LENGTH Invalid len
* @retval NRF_ERROR_NO_MEM if UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF).
* @retval NRF_ERROR_INVALID_PARAM if an invalid command is given.
* @retval NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
* @retval NRF_ERROR_NULL If the content of the memory blocks differs after copying.
*/
static uint32_t nrf_dfu_sd_continue(uint32_t src_addr,
nrf_dfu_bank_t * p_bank)
{
uint32_t ret_val;
ret_val = nrf_dfu_sd_continue_impl(src_addr, p_bank);
if (ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("SD update continuation failed\r\n");
return ret_val;
}
nrf_dfu_invalidate_bank(p_bank);
ret_val = nrf_dfu_settings_write(NULL);
return ret_val;
}
/** @brief Function to continue Bootloader update
*
* @details This function will be called after reset if there is a valid Bootloader in Bank0 or Bank1
* required to be relocated and activated through MBR commands.
*
* @param[in] src_addr Source address of the BL to copy from.
* @param[in] p_bank Pointer to the bank where the SoftDevice resides.
*
* @return This fucntion will not return if the bootloader is copied succesfully.
* After the copy is verified the device will reset and start the new bootloader.
*
* @retval NRF_SUCCESS Continuation was successful.
* @retval NRF_ERROR_INVALID_LENGTH Invalid length of flash operation.
* @retval NRF_ERROR_NO_MEM if no parameter page is provided (see sds for more info).
* @retval NRF_ERROR_INVALID_PARAM if an invalid command is given.
* @retval NRF_ERROR_INTERNAL internal error that should not happen.
* @retval NRF_ERROR_FORBIDDEN if NRF_UICR->BOOTADDR is not set.
*/
static uint32_t nrf_dfu_bl_continue(uint32_t src_addr, nrf_dfu_bank_t * p_bank)
{
uint32_t ret_val = NRF_SUCCESS;
uint32_t const len = (p_bank->image_size - s_dfu_settings.sd_size);
// if the update is a combination of BL + SD, offset with SD size to get BL start address
src_addr += s_dfu_settings.sd_size;
NRF_LOG_INFO("Verifying BL: Addr: 0x%08x, Src: 0x%08x, Len: 0x%08x\r\n", MAIN_APPLICATION_START_ADDR, src_addr, len);
// If the bootloader is the same as the banked version, the copy is finished
ret_val = nrf_dfu_mbr_compare((uint32_t*)BOOTLOADER_START_ADDR, (uint32_t*)src_addr, len);
if (ret_val == NRF_SUCCESS)
{
NRF_LOG_INFO("Bootloader was verified\r\n");
// Invalidate bank, marking completion
nrf_dfu_invalidate_bank(p_bank);
ret_val = nrf_dfu_settings_write(NULL);
}
else
{
NRF_LOG_INFO("Bootloader not verified, copying: Src: 0x%08x, Len: 0x%08x\r\n", src_addr, len);
// Bootloader is different than the banked version. Continue copy
// Note that if the SD and BL was combined, then the split point between them is in s_dfu_settings.sd_size
ret_val = nrf_dfu_mbr_copy_bl((uint32_t*)src_addr, len);
if(ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("Request to copy BL failed\r\n");
}
}
return ret_val;
}
/** @brief Function to continue combined Bootloader and SoftDevice update
*
* @details This function will be called after reset if there is a valid Bootloader and SoftDevice in Bank0 or Bank1
* required to be relocated and activated through MBR commands.
*
* @param[in] src_addr Source address of the combined Bootloader and SoftDevice to copy from.
* @param[in] p_bank Pointer to the bank where the SoftDevice resides.
*
* @retval NRF_SUCCESS Continuation was successful.
* @retval NRF_ERROR_INVALID_LENGTH Invalid len
* @retval NRF_ERROR_NO_MEM if UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF).
* @retval NRF_ERROR_INVALID_PARAM if an invalid command is given.
* @retval NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
* @retval NRF_ERROR_NULL If the content of the memory blocks differs after copying.
* @retval NRF_ERROR_FORBIDDEN if NRF_UICR->BOOTADDR is not set.
*/
static uint32_t nrf_dfu_sd_bl_continue(uint32_t src_addr, nrf_dfu_bank_t * p_bank)
{
uint32_t ret_val = NRF_SUCCESS;
NRF_LOG_INFO("Enter nrf_dfu_sd_bl_continue\r\n");
ret_val = nrf_dfu_sd_continue_impl(src_addr, p_bank);
if (ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("SD+BL: SD copy failed\r\n");
return ret_val;
}
ret_val = nrf_dfu_bl_continue(src_addr, p_bank);
if (ret_val != NRF_SUCCESS)
{
NRF_LOG_INFO("SD+BL: BL copy failed\r\n");
return ret_val;
}
return ret_val;
}
static uint32_t nrf_dfu_continue_bank(nrf_dfu_bank_t * p_bank, uint32_t src_addr, uint32_t * p_enter_dfu_mode)
{
uint32_t ret_val = NRF_SUCCESS;
switch (p_bank->bank_code)
{
case NRF_DFU_BANK_VALID_APP:
NRF_LOG_INFO("Valid App\r\n");
if(s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1)
{
// Only continue copying if valid app in bank1
ret_val = nrf_dfu_app_continue(src_addr);
}
break;
case NRF_DFU_BANK_VALID_SD:
NRF_LOG_INFO("Valid SD\r\n");
// There is a valid SD that needs to be copied (or continued)
ret_val = nrf_dfu_sd_continue(src_addr, p_bank);
(*p_enter_dfu_mode) = 1;
break;
case NRF_DFU_BANK_VALID_BL:
NRF_LOG_INFO("Valid BL\r\n");
// There is a valid BL that must be copied (or continued)
ret_val = nrf_dfu_bl_continue(src_addr, p_bank);
break;
case NRF_DFU_BANK_VALID_SD_BL:
NRF_LOG_INFO("Single: Valid SD + BL\r\n");
// There is a valid SD + BL that must be copied (or continued)
ret_val = nrf_dfu_sd_bl_continue(src_addr, p_bank);
// Set the bank-code to invalid, and reset size/CRC
(*p_enter_dfu_mode) = 1;
break;
case NRF_DFU_BANK_INVALID:
default:
NRF_LOG_INFO("Single: Invalid bank\r\n");
break;
}
return ret_val;
}
uint32_t nrf_dfu_continue(uint32_t * p_enter_dfu_mode)
{
uint32_t ret_val;
nrf_dfu_bank_t * p_bank;
uint32_t src_addr = CODE_REGION_1_START;
NRF_LOG_INFO("Enter nrf_dfu_continue\r\n");
if (s_dfu_settings.bank_layout == NRF_DFU_BANK_LAYOUT_SINGLE )
{
p_bank = &s_dfu_settings.bank_0;
}
else if(s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_0)
{
p_bank = &s_dfu_settings.bank_0;
}
else
{
p_bank = &s_dfu_settings.bank_1;
src_addr += align_to_page(s_dfu_settings.bank_0.image_size, CODE_PAGE_SIZE);
}
ret_val = nrf_dfu_continue_bank(p_bank, src_addr, p_enter_dfu_mode);
return ret_val;
}
bool nrf_dfu_app_is_valid(void)
{
NRF_LOG_INFO("Enter nrf_dfu_app_is_valid\r\n");
if (s_dfu_settings.bank_0.bank_code != NRF_DFU_BANK_VALID_APP)
{
// Bank 0 has no valid app. Nothing to boot
NRF_LOG_INFO("Return false in valid app check\r\n");
return false;
}
// If CRC == 0, this means CRC check is skipped.
if (s_dfu_settings.bank_0.image_crc != 0)
{
uint32_t crc = crc32_compute((uint8_t*) CODE_REGION_1_START,
s_dfu_settings.bank_0.image_size,
NULL);
if (crc != s_dfu_settings.bank_0.image_crc)
{
// CRC does not match with what is stored.
NRF_LOG_INFO("Return false in CRC\r\n");
return false;
}
}
NRF_LOG_INFO("Return true. App was valid\r\n");
return true;
}
uint32_t nrf_dfu_find_cache(uint32_t size_req, bool dual_bank_only, uint32_t * p_address)
{
// TODO: Prevalidate p_address and p_bank
uint32_t free_size = DFU_REGION_TOTAL_SIZE - DFU_APP_DATA_RESERVED;
nrf_dfu_bank_t * p_bank;
NRF_LOG_INFO("Enter nrf_dfu_find_cache\r\n");
// Simple check if size requirement can me met
if(free_size < size_req)
{
NRF_LOG_INFO("No way to fit the new firmware on device\r\n");
return NRF_ERROR_NO_MEM;
}
NRF_LOG_INFO("Bank content\r\n");
NRF_LOG_INFO("Bank type: %d\r\n", s_dfu_settings.bank_layout);
NRF_LOG_INFO("Bank 0 code: 0x%02x: Size: %d\r\n", s_dfu_settings.bank_0.bank_code, s_dfu_settings.bank_0.image_size);
NRF_LOG_INFO("Bank 1 code: 0x%02x: Size: %d\r\n", s_dfu_settings.bank_1.bank_code, s_dfu_settings.bank_1.image_size);
// Setting bank_0 as candidate
p_bank = &s_dfu_settings.bank_0;
// Setting candidate address
(*p_address) = MAIN_APPLICATION_START_ADDR;
// Calculate free size
if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP)
{
// Valid app present.
NRF_LOG_INFO("free_size before bank select: %d\r\n", free_size);
free_size -= align_to_page(p_bank->image_size, CODE_PAGE_SIZE);
NRF_LOG_INFO("free_size: %d, size_req: %d\r\n", free_size, size_req);
// Check if we can fit the new in the free space or if removal of old app is required.
if(size_req > free_size)
{
// Not enough room in free space (bank_1)
if ((dual_bank_only))
{
NRF_LOG_INFO("Failure: dual bank restriction\r\n");
return NRF_ERROR_NO_MEM;
}
// Can only support single bank update, clearing old app.
s_dfu_settings.bank_layout = NRF_DFU_BANK_LAYOUT_SINGLE;
s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0;
p_bank = &s_dfu_settings.bank_0;
NRF_LOG_INFO("Enforcing single bank\r\n");
}
else
{
// Room in bank_1 for update
// Ensure we are using dual bank layout
s_dfu_settings.bank_layout = NRF_DFU_BANK_LAYOUT_DUAL;
s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_1;
p_bank = &s_dfu_settings.bank_1;
// Set to first free page boundry after previous app
(*p_address) += align_to_page(s_dfu_settings.bank_0.image_size, CODE_PAGE_SIZE);
NRF_LOG_INFO("Using second bank\r\n");
}
}
else
{
// No valid app present. Promoting dual bank.
s_dfu_settings.bank_layout = NRF_DFU_BANK_LAYOUT_DUAL;
s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0;
p_bank = &s_dfu_settings.bank_0;
NRF_LOG_INFO("No previous, using bank 0\r\n");
}
// Set the bank-code to invalid, and reset size/CRC
memset(p_bank, 0, sizeof(nrf_dfu_bank_t));
// Store the Firmware size in the bank for continuations
p_bank->image_size = size_req;
return NRF_SUCCESS;
}

View File

@@ -0,0 +1,120 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_nrf_dfu_utils DFU utilities
* @{
* @ingroup sdk_nrf_dfu
*/
#ifndef NRF_DFU_UTILS_H__
#define NRF_DFU_UTILS_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_dfu_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
/** @brief Function for continuing an ongoing DFU operation.
*
* @details This function initiates or continues the DFU copy-back
* routines. These routines are fail-safe operations to activate
* either a new SoftDevice, Bootloader, combination of SoftDevice and
* Bootloader, or a new application.
*
* @details This function relies on accessing MBR commands through supervisor calls.
* It does not rely on the SoftDevice for flash operations.
*
* @note When updating the bootloader or both bootloader and SoftDevice in combination,
* this function does not return, but rather initiate a reboot to activate
* the new bootloader.
*
* @param[in,out] p_enter_dfu_mode True if the continuation failed or the update requires DFU mode.
*
* @retval NRF_SUCCESS If the DFU operation was continued successfully.
* Any other error code indicates that the DFU operation could
* not be continued.
*/
uint32_t nrf_dfu_continue(uint32_t * p_enter_dfu_mode);
/** @brief Function for checking if the main application is valid.
*
* @details This function checks if there is a valid application
* located at Bank 0.
*
* @retval true If a valid application has been detected.
* @retval false If there is no valid application.
*/
bool nrf_dfu_app_is_valid(void);
/** @brief Function for finding a cache write location for the DFU process.
*
* @details This function checks the size requirements and selects a location for
* placing the cache of the DFU images.
* The function tries to find enough space in Bank 1. If there is not enough space,
* the present application is erased.
*
* @param[in] size_req Requirements for the size of the new image.
* @param[in] dual_bank_only True to enforce dual-bank updates. In this case, if there
* is not enough space for caching the DFU image, the existing
* application is retained and the function returns an error.
* @param[out] p_address Updated to the cache address if a cache location is found.
*
* @retval NRF_SUCCESS If a cache location was found for the DFU process.
* @retval NRF_ERROR_NO_MEM If there is no space available on the device to continue the DFU process.
*/
uint32_t nrf_dfu_find_cache(uint32_t size_req, bool dual_bank_only, uint32_t * p_address);
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_UTILS_H__
/** @} */

View File

@@ -0,0 +1,101 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include "nrf_bootloader.h"
#include "compiler_abstraction.h"
#include "nrf.h"
#include "nrf_bootloader_app_start.h"
#include "nrf_log.h"
#include "nrf_dfu.h"
#include "nrf_error.h"
/** @brief Weak implemenation of nrf_dfu_init
*
* @note This function will be overridden if nrf_dfu.c is
* compiled and linked with the project
*/
#if (__LINT__ != 1)
__WEAK uint32_t nrf_dfu_init(void)
{
NRF_LOG_INFO("in weak nrf_dfu_init\r\n");
return NRF_SUCCESS;
}
#endif
/** @brief Weak implementation of nrf_dfu_init
*
* @note This function must be overridden in application if
* user-specific initialization is needed.
*/
__WEAK uint32_t nrf_dfu_init_user(void)
{
NRF_LOG_INFO("in weak nrf_dfu_init_user\r\n");
return NRF_SUCCESS;
}
uint32_t nrf_bootloader_init(void)
{
NRF_LOG_INFO("In nrf_bootloader_init\r\n");
uint32_t ret_val = NRF_SUCCESS;
#if 0
// Call user-defined init function if implemented
ret_val = nrf_dfu_init_user();
if (ret_val != NRF_SUCCESS)
{
return ret_val;
}
#endif
// Call DFU init function if implemented
ret_val = nrf_dfu_init();
if (ret_val != NRF_SUCCESS)
{
return ret_val;
}
NRF_LOG_INFO("After nrf_bootloader_init\r\n");
return ret_val;
}

View File

@@ -0,0 +1,93 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_nrf_bootloader Bootloader modules
* @ingroup app_common
* @brief Modules for creating a bootloader.
*
* @defgroup sdk_bootloader Bootloader
* @{
* @ingroup sdk_nrf_bootloader
* @brief Basic bootloader.
*
* The bootloader module can be used to implement a basic bootloader that
* can be extended with, for example, Device Firmware Update (DFU) support
* or custom functionality.
*/
#ifndef NRF_BOOTLOADER_H__
#define NRF_BOOTLOADER_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Function for initializing the bootloader.
*
* @details This function is the entry point of all bootloader operations.
* If DFU functionality is compiled in, the DFU process is initialized
* when running this function.
*
* @retval NRF_SUCCESS If the bootloader was successfully initialized.
* Any other return code indicates that the operation failed.
*/
uint32_t nrf_bootloader_init(void);
/** @brief Function for customizing the bootloader initialization.
*
* @details This function is called during the initialization of the bootloader.
* It is implemented as weak function that can be overridden in the main file of the application.
*
* @retval NRF_SUCCESS If the user initialization was run successfully.
*/
uint32_t nrf_bootloader_user_init(void);
#ifdef __cplusplus
}
#endif
#endif // NRF_BOOTLOADER_H__
/** @} */

View File

@@ -0,0 +1,211 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include <stdint.h>
#include "nrf_bootloader_app_start.h"
#include "compiler_abstraction.h"
#include "nrf_log.h"
#include "nrf_dfu_mbr.h"
#include "nrf_sdm.h"
#if defined ( __CC_ARM )
__ASM static void nrf_bootloader_app_start_impl(uint32_t start_addr)
{
LDR R5, [R0] ; Get App initial MSP for bootloader.
MSR MSP, R5 ; Set the main stack pointer to the applications MSP.
LDR R0, [R0, #0x04] ; Load Reset handler into R0. This will be first argument to branch instruction (BX).
MOVS R4, #0xFF ; Load ones to R4.
SXTB R4, R4 ; Sign extend R4 to obtain 0xFFFFFFFF instead of 0xFF.
MRS R5, IPSR ; Load IPSR to R5 to check for handler or thread mode.
CMP R5, #0x00 ; Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader.
BNE isr_abort ; If not zero we need to exit current ISR and jump to reset handler of bootloader.
MOV LR, R4 ; Clear the link register and set to ones to ensure no return, R4 = 0xFFFFFFFF.
BX R0 ; Branch to reset handler of bootloader.
isr_abort
; R4 contains ones from line above. Will be popped as R12 when exiting ISR (Cleaning up the registers).
MOV R5, R4 ; Fill with ones before jumping to reset handling. We be popped as LR when exiting ISR. Ensures no return to application.
MOV R6, R0 ; Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR.
MOVS r7, #0x21 ; Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21.
REV r7, r7 ; Reverse byte order to put 0x21 as MSB.
PUSH {r4-r7} ; Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR.
MOVS R4, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers).
MOVS R5, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers).
MOVS R6, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers).
MOVS R7, #0x00 ; Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers).
PUSH {r4-r7} ; Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine.
MOVS R0, #0xF9 ; Move the execution return command into register, 0xFFFFFFF9.
SXTB R0, R0 ; Sign extend R0 to obtain 0xFFFFFFF9 instead of 0xF9.
BX R0 ; No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application.
ALIGN
}
#elif defined ( __GNUC__ )
static void __attribute__ ((noinline)) nrf_bootloader_app_start_impl(uint32_t start_addr)
{
__ASM volatile(
"ldr r0, [%0]\t\n" // Get App initial MSP for bootloader.
"msr msp, r0\t\n" // Set the main stack pointer to the applications MSP.
"ldr r0, [%0, #0x04]\t\n" // Load Reset handler into R0.
"movs r4, #0xFF\t\n" // Move ones to R4.
"sxtb r4, r4\t\n" // Sign extend R4 to obtain 0xFFFFFFFF instead of 0xFF.
"mrs r5, IPSR\t\n" // Load IPSR to R5 to check for handler or thread mode.
"cmp r5, #0x00\t\n" // Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader.
"bne isr_abort\t\n" // If not zero we need to exit current ISR and jump to reset handler of bootloader.
"mov lr, r4\t\n" // Clear the link register and set to ones to ensure no return.
"bx r0\t\n" // Branch to reset handler of bootloader.
"isr_abort: \t\n"
"mov r5, r4\t\n" // Fill with ones before jumping to reset handling. Will be popped as LR when exiting ISR. Ensures no return to application.
"mov r6, r0\t\n" // Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR.
"movs r7, #0x21\t\n" // Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21.
"rev r7, r7\t\n" // Reverse byte order to put 0x21 as MSB.
"push {r4-r7}\t\n" // Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR.
"movs r4, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers).
"movs r5, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers).
"movs r6, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers).
"movs r7, #0x00\t\n" // Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers).
"push {r4-r7}\t\n" // Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine.
"movs r0, #0xF9\t\n" // Move the execution return command into register, 0xFFFFFFF9.
"sxtb r0, r0\t\n" // Sign extend R0 to obtain 0xFFFFFFF9 instead of 0xF9.
"bx r0\t\n" // No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application.
".align\t\n"
:: "r" (start_addr) // Argument list for the gcc assembly. start_addr is %0.
: "r0", "r4", "r5", "r6", "r7" // List of register maintained manually.
);
}
#elif defined ( __ICCARM__ )
static inline void nrf_bootloader_app_start_impl(uint32_t start_addr)
{
__ASM("ldr r5, [%0]\n" // Get App initial MSP for bootloader.
"msr msp, r5\n" // Set the main stack pointer to the applications MSP.
"ldr r0, [%0, #0x04]\n" // Load Reset handler into R0.
"movs r4, #0x00\n" // Load zero into R4.
"mvns r4, r4\n" // Invert R4 to ensure it contain ones.
"mrs r5, IPSR\n" // Load IPSR to R5 to check for handler or thread mode
"cmp r5, #0x00\n" // Compare, if 0 then we are in thread mode and can continue to reset handler of bootloader.
"bne.n isr_abort\n" // If not zero we need to exit current ISR and jump to reset handler of bootloader.
"mov lr, r4\n" // Clear the link register and set to ones to ensure no return.
"bx r0\n" // Branch to reset handler of bootloader.
"isr_abort: \n"
// R4 contains ones from line above. We be popped as R12 when exiting ISR (Cleaning up the registers).
"mov r5, r4\n" // Fill with ones before jumping to reset handling. Will be popped as LR when exiting ISR. Ensures no return to application.
"mov r6, r0\n" // Move address of reset handler to R6. Will be popped as PC when exiting ISR. Ensures the reset handler will be executed when exist ISR.
"movs r7, #0x21\n" // Move MSB reset value of xPSR to R7. Will be popped as xPSR when exiting ISR. xPSR is 0x21000000 thus MSB is 0x21.
"rev r7, r7\n" // Reverse byte order to put 0x21 as MSB.
"push {r4-r7}\n" // Push everything to new stack to allow interrupt handler to fetch it on exiting the ISR.
"movs r4, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R0 when exiting ISR (Cleaning up of the registers).
"movs r5, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R1 when exiting ISR (Cleaning up of the registers).
"movs r6, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R2 when exiting ISR (Cleaning up of the registers).
"movs r7, #0x00\n" // Fill with zeros before jumping to reset handling. We be popped as R3 when exiting ISR (Cleaning up of the registers).
"push {r4-r7}\n" // Push zeros (R4-R7) to stack to prepare for exiting the interrupt routine.
"movs r0, #0x06\n" // Load 0x06 into R6 to prepare for exec return command.
"mvns r0, r0\n" // Invert 0x06 to obtain EXEC_RETURN, 0xFFFFFFF9.
"bx r0\n" // No return - Handler mode will be exited. Stack will be popped and execution will continue in reset handler initializing other application.
:: "r" (start_addr) // Argument list for the IAR assembly. start_addr is %0.
: "r0", "r4", "r5", "r6", "r7"); // List of register maintained manually.
}
#else
#error Compiler not supported.
#endif
void nrf_bootloader_app_start(uint32_t start_addr)
{
NRF_LOG_INFO("Running nrf_bootloader_app_start with address: 0x%08x\r\n", start_addr);
#ifdef BLE_STACK_SUPPORT_REQD
uint32_t err_code;
//NRF_LOG_INFO("Initializing SD in mbr\r\n");
err_code = nrf_dfu_mbr_init_sd();
if(err_code != NRF_SUCCESS)
{
NRF_LOG_INFO("Failed running nrf_dfu_mbr_init_sd\r\n");
return;
}
#endif
// Disable interrupts
NRF_LOG_INFO("Disabling interrupts\r\n");
NVIC->ICER[0]=0xFFFFFFFF;
#if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2
NVIC->ICER[1]=0xFFFFFFFF;
#endif
#ifdef BLE_STACK_SUPPORT_REQD
// Set the sd softdevice vector table base address
NRF_LOG_INFO("Setting SD vector table base: 0x%08x\r\n", start_addr);
err_code = sd_softdevice_vector_table_base_set(start_addr);
if(err_code != NRF_SUCCESS)
{
NRF_LOG_INFO("Failed running sd_softdevice_vector_table_base_set\r\n");
return;
}
#endif
// Run application
nrf_bootloader_app_start_impl(start_addr);
}

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_bootloader_app Application start
* @{
* @ingroup sdk_bootloader
*/
#ifndef NRF_BOOTLOADER_APP_START_H__
#define NRF_BOOTLOADER_APP_START_H__
#include <stdint.h>
/**@brief Function for starting another application (and aborting the current one).
*
* @details This function uses the provided address to swap the stack pointer and then load
* the address of the reset handler to be executed. It checks the current system mode
* (thread/handler). If in thread mode, it resets into the other application.
* If in handler mode, isr_abort is executed to ensure that handler mode is left correctly.
* It then jumps into the reset handler of the other application.
*
* @note This function will never return, but issues a reset into the provided application.
*
* @param[in] start_addr Start address of the other application. This address must point to the
initial stack pointer of the application.
*
*/
void nrf_bootloader_app_start(uint32_t start_addr);
#endif // NRF_BOOTLOADER_APP_START_H__
/** @} */

View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2016 - 2017, 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.
*
*/
#include "nrf_bootloader_info.h"
/** @brief This variable ensures that the linker script will write the bootloader start address
* to the UICR register. This value will be written in the HEX file and thus written to
* UICR when the bootloader is flashed into the chip.
*/
#if defined (__CC_ARM )
#pragma push
#pragma diag_suppress 1296
uint32_t m_uicr_bootloader_start_address __attribute__((at(NRF_UICR_BOOTLOADER_START_ADDRESS)))
= BOOTLOADER_START_ADDR;
#pragma pop
#elif defined ( __GNUC__ )
volatile uint32_t m_uicr_bootloader_start_address __attribute__ ((section(".uicrBootStartAddress")))
= BOOTLOADER_START_ADDR;
#elif defined ( __ICCARM__ )
__root const uint32_t m_uicr_bootloader_start_address @ NRF_UICR_BOOTLOADER_START_ADDRESS
= BOOTLOADER_START_ADDR;
#endif

View File

@@ -0,0 +1,137 @@
/**
* Copyright (c) 2016 - 2017, 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 sdk_bootloader_info Information
* @{
* @ingroup sdk_bootloader
*/
#ifndef NRF_BOOTLOADER_INFO_H__
#define NRF_BOOTLOADER_INFO_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "nrf.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_sdm.h"
#endif
/** @brief External definitions of symbols for the start of the application image.
*/
#if (__LINT__ == 1)
// No implementation
#elif defined ( __CC_ARM )
extern uint32_t* Image$$ER_IROM1$$Base __attribute__((used));
#elif defined ( __GNUC__ )
extern uint32_t * __isr_vector;
#elif defined ( __ICCARM__ )
extern void * __vector_table;
#else
#error Not a valid compiler/linker for application image symbols.
#endif
/** @brief Macro for getting the start address of the application image.
*
* This macro is valid only when absolute placement is used for the application
* image. The macro is not a compile time symbol. It cannot be used as a
* constant expression, for example, inside a static assert or linker script
* at-placement.
*/
#if (__LINT__ == 1)
#define BOOTLOADER_START_ADDR (0x3AC00)
#elif BOOTLOADER_START_ADDR
// Bootloader start address is defined at project level
#elif defined (__CC_ARM)
#define BOOTLOADER_START_ADDR (uint32_t)&Image$$ER_IROM1$$Base
#elif defined (__GNUC__)
#define BOOTLOADER_START_ADDR (uint32_t)&__isr_vector
#elif defined (__ICCARM__)
#define BOOTLOADER_START_ADDR (uint32_t)&__vector_table
#else
#error Not a valid compiler/linker for BOOTLOADER_START_ADDR.
#endif
/**
* @brief Bootloader start address in UICR.
*
* Register location in UICR where the bootloader start address is stored.
*
* @note If the value at the given location is 0xFFFFFFFF, the bootloader address is not set.
*/
#define NRF_UICR_BOOTLOADER_START_ADDRESS (NRF_UICR_BASE + 0x14)
#ifndef MAIN_APPLICATION_START_ADDR
#ifdef SOFTDEVICE_PRESENT
/** @brief Main application start address (if the project uses a SoftDevice).
*
* @note The start address is equal to the end address of the SoftDevice.
*/
#define MAIN_APPLICATION_START_ADDR (SD_SIZE_GET(MBR_SIZE))
#else
/** @brief Main application start address if the project does not use a SoftDevice.
*
* @note The MBR is required for the @ref sdk_bootloader to function.
*/
#define MAIN_APPLICATION_START_ADDR (MBR_SIZE)
#endif
#endif // #ifndef MAIN_APPLICATION_START_ADDR
#ifdef __cplusplus
}
#endif
#endif // #ifndef NRF_BOOTLOADER_INFO_H__
/** @} */