初始版本
This commit is contained in:
772
components/libraries/bootloader/ant_dfu/nrf_dfu_ant.c
Normal file
772
components/libraries/bootloader/ant_dfu/nrf_dfu_ant.c
Normal file
@@ -0,0 +1,772 @@
|
||||
/**
|
||||
* This software is subject to the ANT+ Shared Source License
|
||||
* www.thisisant.com/swlicenses
|
||||
* Copyright (c) Garmin Canada Inc. 2018
|
||||
* 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 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 Garmin nor the names of its
|
||||
* contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* The following actions are prohibited:
|
||||
*
|
||||
* 1) Redistribution of source code containing the ANT+ Network
|
||||
* Key. The ANT+ Network Key is available to ANT+ Adopters.
|
||||
* Please refer to http://thisisant.com to become an ANT+
|
||||
* Adopter and access the key.
|
||||
*
|
||||
* 2) Reverse engineering, decompilation, and/or disassembly of
|
||||
* software provided in binary form under this license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE HEREBY
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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; DAMAGE TO ANY DEVICE, 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. SOME STATES DO NOT ALLOW
|
||||
* THE EXCLUSION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE
|
||||
* ABOVE LIMITATIONS MAY NOT APPLY TO YOU.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "sdk_common.h"
|
||||
|
||||
#include "ant_channel_config.h"
|
||||
#include "ant_interface.h"
|
||||
#include "ant_parameters.h"
|
||||
#include "nrf_assert.h"
|
||||
#include "nrf_balloc.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "nrf_dfu_handling_error.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
#include "nrf_dfu_transport.h"
|
||||
#include "nrf_dfu_mbr.h"
|
||||
#include "nrf_sdh.h"
|
||||
#include "nrf_sdh_ant.h"
|
||||
#include "nrf_soc.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_ant
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_dfu_ant ANT transport for reference DFU.
|
||||
* @ingroup nrf_dfu
|
||||
* @brief Device Firmware Update (DFU) transport layer using ANT.
|
||||
*
|
||||
* Transport documentation:
|
||||
*
|
||||
* The ANT transport uses all of the same opcodes and payload formats as the
|
||||
* UART serial transport. The only differences are the packet header format and
|
||||
* some extra details to deal with retransmissions.
|
||||
*
|
||||
* The device receiving the update is the ANT master. The format of the
|
||||
* broadcast buffer is as follows;
|
||||
* Byte 0: Current Slave -> Master sequence number.
|
||||
* Byte 1: Current Master -> Slave sequence number.
|
||||
* Bytes 2-7: Reserved, set to 0.
|
||||
*
|
||||
* The sequence numbers are used to detect retransmissions, any messages sent
|
||||
* with a sequence number equivalent to the current sequence will be ignored.
|
||||
*
|
||||
* When the slave first connects to the master it should inspect the broadcast
|
||||
* data in order to synchronize its sequence counters.
|
||||
*
|
||||
* All commands/responses are padded out to the nearest 8-byte boundary after
|
||||
* framing, and then sent using either a burst or acknowledged data depending on
|
||||
* length (ack data is used for 8-byte messages). The message transmission is
|
||||
* retried until an EVENT_TRANSFER_TX_COMPLETE event is received.
|
||||
* All messages are framed using the following format:
|
||||
* Bytes 0-1: Message length before padding, little endian, includes header.
|
||||
* Byte 2: Sequence number. Increment for every new message.
|
||||
* Byte 3: Op code. Always 0x60 for responses.
|
||||
* Bytes 4-N: Command/Response payload. This follows the same format as the
|
||||
* UART serial transport, without any SLIP encoding.
|
||||
*
|
||||
* As a final note, the MTU for this protocol is the maximum size of a burst
|
||||
* that can be received.
|
||||
*/
|
||||
|
||||
/** Packet header is always 2 byte length + seq num + op code */
|
||||
#define PKT_HEADER_SIZE 4
|
||||
|
||||
/** Maximum size of the payload in a write command. */
|
||||
#define MAX_WRITE_PAYLOAD (NRF_DFU_ANT_MTU - PKT_HEADER_SIZE)
|
||||
|
||||
/** Bursts are always a multiple of the standard data size. */
|
||||
STATIC_ASSERT_MSG(
|
||||
ALIGN_NUM(ANT_STANDARD_DATA_PAYLOAD_SIZE, NRF_DFU_ANT_MTU) == NRF_DFU_ANT_MTU,
|
||||
"ANT MTU must be a multiple of " STRINGIFY(ANT_STANDARD_DATA_PAYLOAD_SIZE));
|
||||
|
||||
/** Number of buffers to reserve space for with balloc. */
|
||||
#if (NRF_DFU_ANT_BUFFERS_OVERRIDE)
|
||||
#define NUM_BUFFERS NRF_DFU_ANT_BUFFERS
|
||||
#else
|
||||
#define NUM_BUFFERS CEIL_DIV(CODE_PAGE_SIZE, MAX_WRITE_PAYLOAD)
|
||||
#endif
|
||||
|
||||
static uint32_t ant_dfu_init(nrf_dfu_observer_t observer);
|
||||
static uint32_t ant_dfu_close(nrf_dfu_transport_t const * p_exception);
|
||||
|
||||
static ant_channel_config_t m_channel_config = {
|
||||
.channel_number = 0,
|
||||
.channel_type = CHANNEL_TYPE_MASTER,
|
||||
.rf_freq = NRF_DFU_ANT_RF_FREQ,
|
||||
.transmission_type = 1, // Non-shared, no global pages.
|
||||
.device_type = NRF_DFU_ANT_DEV_TYPE,
|
||||
.channel_period = NRF_DFU_ANT_CHANNEL_PERIOD,
|
||||
};
|
||||
|
||||
static nrf_dfu_observer_t m_observer;
|
||||
/** Has transport been initialized by DFU core */
|
||||
static bool m_initialized = false;
|
||||
/** Has the channel started broadcasting */
|
||||
static bool m_started = false;
|
||||
/** Has some data been received on the transport. */
|
||||
static bool m_active = false;
|
||||
|
||||
/** State tracking for rx transfers. */
|
||||
static struct
|
||||
{
|
||||
/** Buffer for holding the command. */
|
||||
uint8_t * buff;
|
||||
/** Amount of data written */
|
||||
size_t offset;
|
||||
/** Sequence of last processed command. */
|
||||
uint8_t seq;
|
||||
} m_rx;
|
||||
|
||||
/** State tracking for tx transfers. */
|
||||
static struct
|
||||
{
|
||||
/** Raw data to send. */
|
||||
uint8_t resp[ALIGN_NUM(ANT_STANDARD_DATA_PAYLOAD_SIZE,
|
||||
PKT_HEADER_SIZE + sizeof(nrf_dfu_response_t))];
|
||||
/** Length of data to send. 0 Indicates no response queued. */
|
||||
size_t len;
|
||||
/** Sequence number of last queued response. */
|
||||
uint8_t seq;
|
||||
/**
|
||||
* Used as burst flag for softdevice, allows to busy loop until all data is
|
||||
* accepted by softdevice.
|
||||
*/
|
||||
volatile bool buffering;
|
||||
/**
|
||||
* Indicate that a new response was generated before the last one was
|
||||
* confirmed.
|
||||
*/
|
||||
bool response_overwritten;
|
||||
/** Data buffer used for broadcast messages. */
|
||||
uint8_t bcast_data[ANT_STANDARD_DATA_PAYLOAD_SIZE];
|
||||
} m_tx;
|
||||
|
||||
/** State tracking for progress notifications. */
|
||||
static struct
|
||||
{
|
||||
/** Requested PRN */
|
||||
uint16_t limit;
|
||||
/** How many more write commands until a CRC should be sent back. */
|
||||
uint16_t remaining;
|
||||
} m_pkt_notify;
|
||||
|
||||
DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const ant_dfu_transport) = {
|
||||
.init_func = ant_dfu_init,
|
||||
.close_func = ant_dfu_close,
|
||||
};
|
||||
|
||||
NRF_BALLOC_DEF(m_buffer_pool, NRF_DFU_ANT_MTU, NUM_BUFFERS);
|
||||
|
||||
static void release_rx_buff(void)
|
||||
{
|
||||
if (m_rx.buff != NULL)
|
||||
{
|
||||
nrf_balloc_free(&m_buffer_pool, m_rx.buff);
|
||||
m_rx.buff = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void transmit_response(void)
|
||||
{
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
|
||||
size_t full_len = ALIGN_NUM(ANT_STANDARD_DATA_PAYLOAD_SIZE, m_tx.len);
|
||||
|
||||
// Pad out with 0's.
|
||||
memset(&m_tx.resp[m_tx.len], 0, full_len - m_tx.len);
|
||||
|
||||
if (full_len > ANT_STANDARD_DATA_PAYLOAD_SIZE)
|
||||
{
|
||||
err_code = sd_ant_burst_handler_request(
|
||||
m_channel_config.channel_number,
|
||||
full_len, m_tx.resp,
|
||||
BURST_SEGMENT_START | BURST_SEGMENT_END);
|
||||
} else
|
||||
{
|
||||
err_code = sd_ant_acknowledge_message_tx(
|
||||
m_channel_config.channel_number,
|
||||
full_len, m_tx.resp);
|
||||
}
|
||||
|
||||
// Wait for buffer to be consumed.
|
||||
// TODO: wait flag management needs to be improved if this will coexist with
|
||||
// other channels.
|
||||
while (err_code == NRF_SUCCESS && m_tx.buffering)
|
||||
{
|
||||
err_code = sd_app_evt_wait();
|
||||
}
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Sending response failed with error %d", err_code);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_bcast_data(void)
|
||||
{
|
||||
memset(m_tx.bcast_data, 0, sizeof(m_tx.bcast_data));
|
||||
m_tx.bcast_data[0] = m_rx.seq;
|
||||
m_tx.bcast_data[1] = m_tx.seq;
|
||||
|
||||
if (NRF_SUCCESS != sd_ant_broadcast_message_tx(
|
||||
m_channel_config.channel_number,
|
||||
sizeof(m_tx.bcast_data), m_tx.bcast_data))
|
||||
{
|
||||
NRF_LOG_WARNING("Unable to update broadcast data.");
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_write_complete(void * p_buf)
|
||||
{
|
||||
nrf_balloc_free(&m_buffer_pool, p_buf);
|
||||
}
|
||||
|
||||
static void prepare_response(nrf_dfu_response_t * p_res)
|
||||
{
|
||||
if (m_tx.len)
|
||||
{
|
||||
NRF_LOG_WARNING("Overwriting previous response.");
|
||||
m_tx.response_overwritten = true;
|
||||
}
|
||||
|
||||
// reserve first 2 bytes for length.
|
||||
m_tx.len = 2;
|
||||
|
||||
m_tx.resp[m_tx.len++] = ++(m_tx.seq);
|
||||
m_tx.resp[m_tx.len++] = NRF_DFU_OP_RESPONSE;
|
||||
m_tx.resp[m_tx.len++] = p_res->request;
|
||||
m_tx.resp[m_tx.len++] = p_res->result;
|
||||
|
||||
if (p_res->result == NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
switch(p_res->request)
|
||||
{
|
||||
case NRF_DFU_OP_PROTOCOL_VERSION:
|
||||
{
|
||||
m_tx.resp[m_tx.len++] = p_res->protocol.version;
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_CRC_GET:
|
||||
{
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->crc.offset, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->crc.crc, &m_tx.resp[m_tx.len]);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_SELECT:
|
||||
{
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->select.max_size, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->select.offset, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->select.crc, &m_tx.resp[m_tx.len]);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_MTU_GET:
|
||||
{
|
||||
m_tx.len += uint16_encode(
|
||||
p_res->mtu.size, &m_tx.resp[m_tx.len]);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_PING:
|
||||
{
|
||||
m_tx.resp[m_tx.len++] = p_res->ping.id;
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_HARDWARE_VERSION:
|
||||
{
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->hardware.part, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->hardware.variant, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->hardware.memory.rom_size, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->hardware.memory.rom_page_size, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->hardware.memory.ram_size, &m_tx.resp[m_tx.len]);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_FIRMWARE_VERSION:
|
||||
{
|
||||
m_tx.resp[m_tx.len++] = p_res->firmware.type;
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->firmware.version, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->firmware.addr, &m_tx.resp[m_tx.len]);
|
||||
m_tx.len += uint32_encode(
|
||||
p_res->firmware.len, &m_tx.resp[m_tx.len]);
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (p_res->result == NRF_DFU_RES_CODE_EXT_ERROR)
|
||||
{
|
||||
m_tx.resp[m_tx.len++] = ext_error_get();
|
||||
UNUSED_RETURN_VALUE(ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR));
|
||||
}
|
||||
|
||||
// Finally fill in the length.
|
||||
UNUSED_RETURN_VALUE(uint16_encode(m_tx.len, m_tx.resp));
|
||||
|
||||
// Safety check buffer overflow.
|
||||
ASSERT(m_tx.len <= sizeof(m_tx.resp));
|
||||
|
||||
if (!m_tx.response_overwritten)
|
||||
{
|
||||
// Can send out the response immediately if there wasn't a previous one
|
||||
// queued.
|
||||
transmit_response();
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_response(nrf_dfu_response_t * p_res, void * p_context)
|
||||
{
|
||||
UNUSED_PARAMETER(p_context);
|
||||
|
||||
if (p_res->result != NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
NRF_LOG_WARNING("Operation %d had result %d",
|
||||
p_res->request, p_res->result);
|
||||
}
|
||||
|
||||
if (p_res->request == NRF_DFU_OP_OBJECT_WRITE)
|
||||
{
|
||||
if (m_pkt_notify.limit == 0 ||
|
||||
--m_pkt_notify.remaining != 0)
|
||||
{
|
||||
// No packet notification needed, filter out response.
|
||||
return;
|
||||
}
|
||||
|
||||
// Packet Notification time, send a CRC response.
|
||||
m_pkt_notify.remaining = m_pkt_notify.limit;
|
||||
p_res->request = NRF_DFU_OP_CRC_GET;
|
||||
uint32_t offset = p_res->write.offset;
|
||||
uint32_t crc = p_res->write.crc;
|
||||
p_res->crc.offset = offset;
|
||||
p_res->crc.crc = crc;
|
||||
}
|
||||
|
||||
prepare_response(p_res);
|
||||
}
|
||||
|
||||
static uint32_t handle_request(void)
|
||||
{
|
||||
uint16_t len = uint16_decode(m_rx.buff);
|
||||
uint16_t offset = sizeof(uint16_t);
|
||||
|
||||
if (len < PKT_HEADER_SIZE || len > m_rx.offset)
|
||||
{
|
||||
NRF_LOG_WARNING("Ignoring command with invalid length.");
|
||||
return NRF_ERROR_DATA_SIZE;
|
||||
}
|
||||
|
||||
uint8_t seq = m_rx.buff[offset++];
|
||||
if (!m_active)
|
||||
{
|
||||
m_active = true;
|
||||
// Close all other transports.
|
||||
UNUSED_RETURN_VALUE(nrf_dfu_transports_close(&ant_dfu_transport));
|
||||
}
|
||||
else if (seq == m_rx.seq)
|
||||
{
|
||||
NRF_LOG_DEBUG("Ignoring repeated command");
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
m_rx.seq = seq;
|
||||
|
||||
nrf_dfu_request_t request = {
|
||||
.request = (nrf_dfu_op_t)m_rx.buff[offset++],
|
||||
.callback.response = handle_response,
|
||||
};
|
||||
|
||||
switch(request.request)
|
||||
{
|
||||
case NRF_DFU_OP_OBJECT_CREATE:
|
||||
{
|
||||
request.create.object_type = m_rx.buff[offset++];
|
||||
request.create.object_size = uint32_decode(&m_rx.buff[offset]);
|
||||
offset += sizeof(uint32_t);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_RECEIPT_NOTIF_SET:
|
||||
{
|
||||
request.prn.target = uint16_decode(&m_rx.buff[offset]);
|
||||
offset += sizeof(uint16_t);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_SELECT:
|
||||
{
|
||||
request.select.object_type = m_rx.buff[offset++];
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_WRITE:
|
||||
{
|
||||
request.write.p_data = &m_rx.buff[offset];
|
||||
request.write.len = len - offset;
|
||||
offset = len;
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_PING:
|
||||
{
|
||||
request.ping.id = m_rx.buff[offset++];
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_FIRMWARE_VERSION:
|
||||
{
|
||||
request.firmware.image_number = m_rx.buff[offset++];
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_MTU_GET:
|
||||
{
|
||||
NRF_LOG_DEBUG("ANT DFU: Responding to MTU request with %d",
|
||||
NRF_DFU_ANT_MTU);
|
||||
request.mtu.size = NRF_DFU_ANT_MTU;
|
||||
} break;
|
||||
|
||||
default:
|
||||
// Do nothing.
|
||||
break;
|
||||
}
|
||||
|
||||
if (offset > len)
|
||||
{
|
||||
NRF_LOG_WARNING("Ignoring command with invalid length");
|
||||
return NRF_ERROR_DATA_SIZE;
|
||||
}
|
||||
|
||||
// Some processing that is only safe to do if accepting the command.
|
||||
|
||||
switch (request.request)
|
||||
{
|
||||
case NRF_DFU_OP_RECEIPT_NOTIF_SET:
|
||||
{
|
||||
m_pkt_notify.limit = request.prn.target;
|
||||
m_pkt_notify.remaining = m_pkt_notify.limit;
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_CREATE:
|
||||
case NRF_DFU_OP_OBJECT_SELECT:
|
||||
{
|
||||
m_pkt_notify.remaining = m_pkt_notify.limit;
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_WRITE:
|
||||
{
|
||||
// Ownership of buffer is transferred to the write command.
|
||||
request.callback.write = handle_write_complete;
|
||||
m_rx.buff = NULL;
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return nrf_dfu_req_handler_on_req(&request);
|
||||
}
|
||||
|
||||
static void handle_tx_transfer_complete(bool success)
|
||||
{
|
||||
if (m_tx.response_overwritten)
|
||||
{
|
||||
// By treating the result as a failure the retransmission will send out
|
||||
// the new response.
|
||||
success = false;
|
||||
m_tx.response_overwritten = false;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
m_tx.len = 0;
|
||||
update_bcast_data();
|
||||
}
|
||||
else
|
||||
{
|
||||
transmit_response();
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_rx_transfer_start()
|
||||
{
|
||||
if (m_rx.buff == NULL)
|
||||
{
|
||||
m_rx.buff = nrf_balloc_alloc(&m_buffer_pool);
|
||||
if (m_rx.buff != NULL)
|
||||
{
|
||||
NRF_LOG_INFO("Allocated buffer %x", m_rx.buff);
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_ERROR("Unable to allocate buffer for incoming packet.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Resetting rx pointer.");
|
||||
m_rx.offset = 0;
|
||||
}
|
||||
|
||||
static void handle_rx_transfer_complete(bool success)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
uint32_t err_code = handle_request();
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Error %d handling request.", err_code);
|
||||
}
|
||||
}
|
||||
|
||||
release_rx_buff();
|
||||
}
|
||||
|
||||
static void handle_rx_transfer_data(uint8_t * data, size_t len)
|
||||
{
|
||||
if (m_rx.buff == NULL)
|
||||
{
|
||||
NRF_LOG_DEBUG("Ignoring transfer data.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_rx.offset + len > NRF_DFU_ANT_MTU)
|
||||
{
|
||||
NRF_LOG_ERROR("Received packet overflows MTU.");
|
||||
handle_rx_transfer_complete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&m_rx.buff[m_rx.offset], data, len);
|
||||
m_rx.offset += len;
|
||||
}
|
||||
|
||||
static void handle_data_mesg(ANT_MESSAGE * p_msg)
|
||||
{
|
||||
bool is_first = false;
|
||||
bool is_last = false;
|
||||
uint8_t len = ANT_STANDARD_DATA_PAYLOAD_SIZE;
|
||||
|
||||
switch(p_msg->ANT_MESSAGE_ucMesgID)
|
||||
{
|
||||
case MESG_BROADCAST_DATA_ID:
|
||||
{
|
||||
// Broadcast data is ignored.
|
||||
len = 0;
|
||||
} break;
|
||||
|
||||
case MESG_ACKNOWLEDGED_DATA_ID:
|
||||
{
|
||||
is_first = true;
|
||||
is_last = true;
|
||||
} break;
|
||||
|
||||
case MESG_ADV_BURST_DATA_ID:
|
||||
{
|
||||
len = p_msg->ANT_MESSAGE_ucSize - MESG_CHANNEL_NUM_SIZE;
|
||||
} // FALL-THROUGH : both burst types act the same other than len.
|
||||
case MESG_BURST_DATA_ID:
|
||||
{
|
||||
uint8_t seq = p_msg->ANT_MESSAGE_ucChannel & SEQUENCE_NUMBER_MASK;
|
||||
is_first = seq == SEQUENCE_FIRST_MESSAGE;
|
||||
is_last = !!(seq & SEQUENCE_LAST_MESSAGE);
|
||||
} break;
|
||||
}
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
if (is_first)
|
||||
{
|
||||
handle_rx_transfer_start();
|
||||
}
|
||||
|
||||
handle_rx_transfer_data(p_msg->ANT_MESSAGE_aucPayload, len);
|
||||
|
||||
if (is_last)
|
||||
{
|
||||
handle_rx_transfer_complete(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ant_dfu_evt_handler(ant_evt_t * p_ant_evt, void * p_context)
|
||||
{
|
||||
// Ignore messages meant for other channels.
|
||||
if (p_ant_evt->channel != m_channel_config.channel_number)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch(p_ant_evt->event)
|
||||
{
|
||||
case EVENT_TX:
|
||||
{
|
||||
if (!m_started)
|
||||
{
|
||||
m_started = true;
|
||||
m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED);
|
||||
}
|
||||
} break;
|
||||
|
||||
case EVENT_TRANSFER_TX_COMPLETED:
|
||||
handle_tx_transfer_complete(true);
|
||||
break;
|
||||
case EVENT_TRANSFER_TX_FAILED:
|
||||
handle_tx_transfer_complete(false);
|
||||
break;
|
||||
|
||||
case EVENT_RX:
|
||||
handle_data_mesg(&p_ant_evt->message);
|
||||
break;
|
||||
|
||||
case EVENT_TRANSFER_RX_FAILED:
|
||||
handle_rx_transfer_complete(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t ant_dfu_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
if (m_initialized)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
NRF_SDH_ANT_OBSERVER(ant_dfu_observer, NRF_DFU_ANT_EVT_HANDLER_PRIO,
|
||||
ant_dfu_evt_handler, NULL);
|
||||
|
||||
m_observer = observer;
|
||||
m_tx.seq = m_rx.seq = 0;
|
||||
m_active = false;
|
||||
m_started = false;
|
||||
|
||||
NRF_LOG_DEBUG("Initializing ANT DFU transport");
|
||||
|
||||
err_code = nrf_balloc_init(&m_buffer_pool);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
err_code = nrf_dfu_mbr_init_sd();
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
NRF_LOG_DEBUG("Setting up vector table: 0x%08x", BOOTLOADER_START_ADDR);
|
||||
err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_START_ADDR);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
NRF_LOG_DEBUG("Enabling softdevice");
|
||||
err_code = nrf_sdh_enable_request();
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
err_code = nrf_sdh_ant_enable();
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
static uint8_t adv_burst_conf[] = {
|
||||
ADV_BURST_MODE_ENABLE,
|
||||
ADV_BURST_MODES_SIZE_24_BYTES,
|
||||
0, // No required modes.
|
||||
0, 0, // Reserved
|
||||
ADV_BURST_MODES_FREQ_HOP, // Optional Modes
|
||||
0, 0, // Reserved
|
||||
// No optional configs.
|
||||
};
|
||||
err_code = sd_ant_adv_burst_config_set(adv_burst_conf, sizeof(adv_burst_conf));
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
m_channel_config.device_number = NRF_FICR->DEVICEID[0];
|
||||
m_channel_config.transmission_type |= (NRF_FICR->DEVICEID[1] & 0xF) << 4;
|
||||
|
||||
err_code = ant_channel_init(&m_channel_config);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
update_bcast_data();
|
||||
|
||||
err_code = sd_ant_channel_open(m_channel_config.channel_number);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
NRF_LOG_DEBUG("ANT transport intialized");
|
||||
|
||||
m_initialized = true;
|
||||
return err_code;
|
||||
}
|
||||
|
||||
static uint32_t ant_dfu_close(nrf_dfu_transport_t const * p_exception)
|
||||
{
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
|
||||
if (p_exception != &ant_dfu_transport && m_initialized)
|
||||
{
|
||||
NRF_LOG_DEBUG("Shutting down ANT DFU transport");
|
||||
|
||||
m_initialized = false;
|
||||
|
||||
err_code = sd_ant_channel_close(m_channel_config.channel_number);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
uint8_t status;
|
||||
do
|
||||
{
|
||||
// The initial wait is safe because the close command above would
|
||||
// have generated at least 1 app event.
|
||||
err_code = sd_app_evt_wait();
|
||||
VERIFY_SUCCESS(err_code);
|
||||
err_code = sd_ant_channel_status_get(
|
||||
m_channel_config.channel_number, &status);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
} while ((status & STATUS_CHANNEL_STATE_MASK) != STATUS_ASSIGNED_CHANNEL);
|
||||
|
||||
err_code = nrf_sdh_disable_request();
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
NRF_LOG_DEBUG("ANT transport disabled.");
|
||||
}
|
||||
|
||||
return err_code;
|
||||
}
|
||||
1261
components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c
Normal file
1261
components/libraries/bootloader/ble_dfu/nrf_dfu_ble.c
Normal file
File diff suppressed because it is too large
Load Diff
121
components/libraries/bootloader/ble_dfu/nrf_dfu_ble.h
Normal file
121
components/libraries/bootloader/ble_dfu/nrf_dfu_ble.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_ble DFU BLE Service
|
||||
* @{
|
||||
* @ingroup nrf_dfu
|
||||
* @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_DFU_BLE_H__
|
||||
#define NRF_DFU_BLE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ble_gatts.h"
|
||||
#include "ble.h"
|
||||
#include "nrf_dfu_transport.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// This is a 16-bit UUID.
|
||||
#define BLE_DFU_SERVICE_UUID 0xFE59 //!< 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 //!< UUID of the DFU Control Point.
|
||||
#define BLE_DFU_PKT_CHAR_UUID 0x0002 //!< UUID of the DFU Packet Characteristic.
|
||||
|
||||
|
||||
/**@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 BLE transport.
|
||||
*
|
||||
* @param[in] observer Callback function for receiving notifications from the BLE transport.
|
||||
*
|
||||
* @retval NRF_SUCCESS If successful.
|
||||
* @return Error code from sub-call on error.
|
||||
*/
|
||||
uint32_t ble_dfu_transport_init(nrf_dfu_observer_t observer);
|
||||
|
||||
/**@brief Function for closing the BLE transport.
|
||||
*
|
||||
* This function disconnects and disables the SoftDevice.
|
||||
*
|
||||
* @param[in] p_exception Optional exception. If the exception refers to this transport,
|
||||
* this function will do nothing. Can be NULL to signify no exception.
|
||||
*
|
||||
* @retval NRF_SUCCESS If successful.
|
||||
* @return Error code from sub-call on error.
|
||||
*/
|
||||
uint32_t ble_dfu_transport_close(nrf_dfu_transport_t const * p_exception);
|
||||
|
||||
/**@brief Function for disconnecting from the BLE peer and starting advertising.
|
||||
*
|
||||
* @retval NRF_SUCCESS If successful.
|
||||
* @return Error code from sub-call on error.
|
||||
*/
|
||||
uint32_t ble_dfu_transport_disconnect(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_BLE_H__
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_svci_bond_sharing Supervisor call interface for bond sharing
|
||||
* @{
|
||||
* @ingroup nrf_dfu
|
||||
* @brief The Supervisor call interface is a thread-safe method to call into the current application or into an external application using a Supervisor instruction.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef NRF_DFU_BLE_SVCI_BOND_SHARING_H__
|
||||
#define NRF_DFU_BLE_SVCI_BOND_SHARING_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "nrf_svci.h"
|
||||
#include "nrf_svci_async_function.h"
|
||||
#include "sdk_config.h"
|
||||
#include "nrf_dfu_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define NRF_DFU_SVCI_SET_PEER_DATA 2
|
||||
#define NRF_DFU_SVCI_SET_ADV_NAME 3
|
||||
|
||||
#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE
|
||||
|
||||
/**@brief Sets up the async SVCI interface for exchanging peer data like bonding and the system attribute table.
|
||||
*
|
||||
* @details The peer data will be stored in flash by the bootloader. This requires memory management and
|
||||
* handling forwarding of system events and state from the main application to the bootloader.
|
||||
*
|
||||
* @note This is only available in the buttonless DFU that supports bond sharing.
|
||||
*/
|
||||
NRF_SVCI_ASYNC_FUNC_DECLARE(NRF_DFU_SVCI_SET_PEER_DATA, nrf_dfu_set_peer_data, nrf_dfu_peer_data_t, nrf_dfu_peer_data_state_t);
|
||||
|
||||
/**@brief Sets up the async SVCI interface for exchanging advertisement name to use when entering DFU mode.
|
||||
*
|
||||
* @details The advertisement name will be stored in flash by the bootloader. This requires memory management
|
||||
* and handling forwarding of system events and state from the main application to the bootloader.
|
||||
*
|
||||
* @note This is only available in the buttonless DFU that does not support bond sharing.
|
||||
*/
|
||||
NRF_SVCI_ASYNC_FUNC_DECLARE(NRF_DFU_SVCI_SET_ADV_NAME, nrf_dfu_set_adv_name, nrf_dfu_adv_name_t, nrf_dfu_set_adv_name_state_t);
|
||||
|
||||
#endif // NRF_DFU_TRANSPORT_BLE
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_BLE_SVCI_BOND_SHARING_H__
|
||||
|
||||
/** @} */
|
||||
5
components/libraries/bootloader/dfu/dfu-cc.options
Normal file
5
components/libraries/bootloader/dfu/dfu-cc.options
Normal file
@@ -0,0 +1,5 @@
|
||||
dfu.Hash.hash max_size:32
|
||||
dfu.SignedCommand.signature max_size:64
|
||||
dfu.InitCommand.sd_req max_count:16
|
||||
dfu.InitCommand.boot_validation max_count:3
|
||||
dfu.BootValidation.bytes max_size:64
|
||||
123
components/libraries/bootloader/dfu/dfu-cc.pb.c
Normal file
123
components/libraries/bootloader/dfu/dfu-cc.pb.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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.
|
||||
*
|
||||
*/
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.3.6-dev at Tue Sep 11 14:37:18 2018. */
|
||||
|
||||
#include "dfu-cc.pb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
const bool dfu_init_command_is_debug_default = false;
|
||||
|
||||
|
||||
const pb_field_t dfu_hash_fields[3] = {
|
||||
PB_FIELD( 1, UENUM , REQUIRED, STATIC , FIRST, dfu_hash_t, hash_type, hash_type, 0),
|
||||
PB_FIELD( 2, BYTES , REQUIRED, STATIC , OTHER, dfu_hash_t, hash, hash_type, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t dfu_boot_validation_fields[3] = {
|
||||
PB_FIELD( 1, UENUM , REQUIRED, STATIC , FIRST, dfu_boot_validation_t, type, type, 0),
|
||||
PB_FIELD( 2, BYTES , REQUIRED, STATIC , OTHER, dfu_boot_validation_t, bytes, type, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t dfu_init_command_fields[11] = {
|
||||
PB_FIELD( 1, UINT32 , OPTIONAL, STATIC , FIRST, dfu_init_command_t, fw_version, fw_version, 0),
|
||||
PB_FIELD( 2, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, hw_version, fw_version, 0),
|
||||
PB_FIELD( 3, UINT32 , REPEATED, STATIC , OTHER, dfu_init_command_t, sd_req, hw_version, 0),
|
||||
PB_FIELD( 4, UENUM , OPTIONAL, STATIC , OTHER, dfu_init_command_t, type, sd_req, 0),
|
||||
PB_FIELD( 5, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, sd_size, type, 0),
|
||||
PB_FIELD( 6, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, bl_size, sd_size, 0),
|
||||
PB_FIELD( 7, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, app_size, bl_size, 0),
|
||||
PB_FIELD( 8, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_init_command_t, hash, app_size, &dfu_hash_fields),
|
||||
PB_FIELD( 9, BOOL , OPTIONAL, STATIC , OTHER, dfu_init_command_t, is_debug, hash, &dfu_init_command_is_debug_default),
|
||||
PB_FIELD( 10, MESSAGE , REPEATED, STATIC , OTHER, dfu_init_command_t, boot_validation, is_debug, &dfu_boot_validation_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t dfu_command_fields[3] = {
|
||||
PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, dfu_command_t, op_code, op_code, 0),
|
||||
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_command_t, init, op_code, &dfu_init_command_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t dfu_signed_command_fields[4] = {
|
||||
PB_FIELD( 1, MESSAGE , REQUIRED, STATIC , FIRST, dfu_signed_command_t, command, command, &dfu_command_fields),
|
||||
PB_FIELD( 2, UENUM , REQUIRED, STATIC , OTHER, dfu_signed_command_t, signature_type, command, 0),
|
||||
PB_FIELD( 3, BYTES , REQUIRED, STATIC , OTHER, dfu_signed_command_t, signature, signature_type, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t dfu_packet_fields[3] = {
|
||||
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, dfu_packet_t, command, command, &dfu_command_fields),
|
||||
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_packet_t, signed_command, command, &dfu_signed_command_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
|
||||
/* Check that field information fits in pb_field_t */
|
||||
#if !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
|
||||
* field descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(dfu_init_command_t, hash) < 65536 && pb_membersize(dfu_init_command_t, boot_validation[0]) < 65536 && pb_membersize(dfu_command_t, init) < 65536 && pb_membersize(dfu_signed_command_t, command) < 65536 && pb_membersize(dfu_packet_t, command) < 65536 && pb_membersize(dfu_packet_t, signed_command) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_dfu_hash_dfu_boot_validation_dfu_init_command_dfu_command_dfu_signed_command_dfu_packet)
|
||||
#endif
|
||||
|
||||
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in the default
|
||||
* 8 bit descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(dfu_init_command_t, hash) < 256 && pb_membersize(dfu_init_command_t, boot_validation[0]) < 256 && pb_membersize(dfu_command_t, init) < 256 && pb_membersize(dfu_signed_command_t, command) < 256 && pb_membersize(dfu_packet_t, command) < 256 && pb_membersize(dfu_packet_t, signed_command) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_dfu_hash_dfu_boot_validation_dfu_init_command_dfu_command_dfu_signed_command_dfu_packet)
|
||||
#endif
|
||||
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
241
components/libraries/bootloader/dfu/dfu-cc.pb.h
Normal file
241
components/libraries/bootloader/dfu/dfu-cc.pb.h
Normal file
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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.
|
||||
*
|
||||
*/
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.6-dev at Tue Sep 11 14:37:18 2018. */
|
||||
|
||||
#ifndef PB_DFU_CC_PB_H_INCLUDED
|
||||
#define PB_DFU_CC_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum
|
||||
{
|
||||
DFU_FW_TYPE_APPLICATION = 0,
|
||||
DFU_FW_TYPE_SOFTDEVICE = 1,
|
||||
DFU_FW_TYPE_BOOTLOADER = 2,
|
||||
DFU_FW_TYPE_SOFTDEVICE_BOOTLOADER = 3,
|
||||
DFU_FW_TYPE_EXTERNAL_APPLICATION = 4
|
||||
} dfu_fw_type_t;
|
||||
#define DFU_FW_TYPE_MIN DFU_FW_TYPE_APPLICATION
|
||||
#define DFU_FW_TYPE_MAX DFU_FW_TYPE_EXTERNAL_APPLICATION
|
||||
#define DFU_FW_TYPE_ARRAYSIZE ((dfu_fw_type_t)(DFU_FW_TYPE_EXTERNAL_APPLICATION+1))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DFU_HASH_TYPE_NO_HASH = 0,
|
||||
DFU_HASH_TYPE_CRC = 1,
|
||||
DFU_HASH_TYPE_SHA128 = 2,
|
||||
DFU_HASH_TYPE_SHA256 = 3,
|
||||
DFU_HASH_TYPE_SHA512 = 4
|
||||
} dfu_hash_type_t;
|
||||
#define DFU_HASH_TYPE_MIN DFU_HASH_TYPE_NO_HASH
|
||||
#define DFU_HASH_TYPE_MAX DFU_HASH_TYPE_SHA512
|
||||
#define DFU_HASH_TYPE_ARRAYSIZE ((dfu_hash_type_t)(DFU_HASH_TYPE_SHA512+1))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DFU_OP_CODE_INIT = 1
|
||||
} dfu_op_code_t;
|
||||
#define DFU_OP_CODE_MIN DFU_OP_CODE_INIT
|
||||
#define DFU_OP_CODE_MAX DFU_OP_CODE_INIT
|
||||
#define DFU_OP_CODE_ARRAYSIZE ((dfu_op_code_t)(DFU_OP_CODE_INIT+1))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DFU_VALIDATION_TYPE_NO_VALIDATION = 0,
|
||||
DFU_VALIDATION_TYPE_VALIDATE_GENERATED_CRC = 1,
|
||||
DFU_VALIDATION_TYPE_VALIDATE_SHA256 = 2,
|
||||
DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256 = 3
|
||||
} dfu_validation_type_t;
|
||||
#define DFU_VALIDATION_TYPE_MIN DFU_VALIDATION_TYPE_NO_VALIDATION
|
||||
#define DFU_VALIDATION_TYPE_MAX DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256
|
||||
#define DFU_VALIDATION_TYPE_ARRAYSIZE ((dfu_validation_type_t)(DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256+1))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256 = 0,
|
||||
DFU_SIGNATURE_TYPE_ED25519 = 1
|
||||
} dfu_signature_type_t;
|
||||
#define DFU_SIGNATURE_TYPE_MIN DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256
|
||||
#define DFU_SIGNATURE_TYPE_MAX DFU_SIGNATURE_TYPE_ED25519
|
||||
#define DFU_SIGNATURE_TYPE_ARRAYSIZE ((dfu_signature_type_t)(DFU_SIGNATURE_TYPE_ED25519+1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef PB_BYTES_ARRAY_T(64) dfu_boot_validation_bytes_t;
|
||||
typedef struct {
|
||||
dfu_validation_type_t type;
|
||||
dfu_boot_validation_bytes_t bytes;
|
||||
/* @@protoc_insertion_point(struct:dfu_boot_validation_t) */
|
||||
} dfu_boot_validation_t;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(32) dfu_hash_hash_t;
|
||||
typedef struct {
|
||||
dfu_hash_type_t hash_type;
|
||||
dfu_hash_hash_t hash;
|
||||
/* @@protoc_insertion_point(struct:dfu_hash_t) */
|
||||
} dfu_hash_t;
|
||||
|
||||
typedef struct {
|
||||
bool has_fw_version;
|
||||
uint32_t fw_version;
|
||||
bool has_hw_version;
|
||||
uint32_t hw_version;
|
||||
pb_size_t sd_req_count;
|
||||
uint32_t sd_req[16];
|
||||
bool has_type;
|
||||
dfu_fw_type_t type;
|
||||
bool has_sd_size;
|
||||
uint32_t sd_size;
|
||||
bool has_bl_size;
|
||||
uint32_t bl_size;
|
||||
bool has_app_size;
|
||||
uint32_t app_size;
|
||||
bool has_hash;
|
||||
dfu_hash_t hash;
|
||||
bool has_is_debug;
|
||||
bool is_debug;
|
||||
pb_size_t boot_validation_count;
|
||||
dfu_boot_validation_t boot_validation[3];
|
||||
/* @@protoc_insertion_point(struct:dfu_init_command_t) */
|
||||
} dfu_init_command_t;
|
||||
|
||||
typedef struct {
|
||||
bool has_op_code;
|
||||
dfu_op_code_t op_code;
|
||||
bool has_init;
|
||||
dfu_init_command_t init;
|
||||
/* @@protoc_insertion_point(struct:dfu_command_t) */
|
||||
} dfu_command_t;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(64) dfu_signed_command_signature_t;
|
||||
typedef struct {
|
||||
dfu_command_t command;
|
||||
dfu_signature_type_t signature_type;
|
||||
dfu_signed_command_signature_t signature;
|
||||
/* @@protoc_insertion_point(struct:dfu_signed_command_t) */
|
||||
} dfu_signed_command_t;
|
||||
|
||||
typedef struct {
|
||||
bool has_command;
|
||||
dfu_command_t command;
|
||||
bool has_signed_command;
|
||||
dfu_signed_command_t signed_command;
|
||||
/* @@protoc_insertion_point(struct:dfu_packet_t) */
|
||||
} dfu_packet_t;
|
||||
|
||||
/* Default values for struct fields */
|
||||
extern const bool dfu_init_command_is_debug_default;
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define DFU_HASH_INIT_DEFAULT {(dfu_hash_type_t)0, {0, {0}}}
|
||||
#define DFU_BOOT_VALIDATION_INIT_DEFAULT {(dfu_validation_type_t)0, {0, {0}}}
|
||||
#define DFU_INIT_COMMAND_INIT_DEFAULT {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, (dfu_fw_type_t)0, false, 0, false, 0, false, 0, false, DFU_HASH_INIT_DEFAULT, false, false, 0, {DFU_BOOT_VALIDATION_INIT_DEFAULT, DFU_BOOT_VALIDATION_INIT_DEFAULT, DFU_BOOT_VALIDATION_INIT_DEFAULT}}
|
||||
#define DFU_COMMAND_INIT_DEFAULT {false, (dfu_op_code_t)0, false, DFU_INIT_COMMAND_INIT_DEFAULT}
|
||||
#define DFU_SIGNED_COMMAND_INIT_DEFAULT {DFU_COMMAND_INIT_DEFAULT, (dfu_signature_type_t)0, {0, {0}}}
|
||||
#define DFU_PACKET_INIT_DEFAULT {false, DFU_COMMAND_INIT_DEFAULT, false, DFU_SIGNED_COMMAND_INIT_DEFAULT}
|
||||
#define DFU_HASH_INIT_ZERO {(dfu_hash_type_t)0, {0, {0}}}
|
||||
#define DFU_BOOT_VALIDATION_INIT_ZERO {(dfu_validation_type_t)0, {0, {0}}}
|
||||
#define DFU_INIT_COMMAND_INIT_ZERO {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, (dfu_fw_type_t)0, false, 0, false, 0, false, 0, false, DFU_HASH_INIT_ZERO, false, 0, 0, {DFU_BOOT_VALIDATION_INIT_ZERO, DFU_BOOT_VALIDATION_INIT_ZERO, DFU_BOOT_VALIDATION_INIT_ZERO}}
|
||||
#define DFU_COMMAND_INIT_ZERO {false, (dfu_op_code_t)0, false, DFU_INIT_COMMAND_INIT_ZERO}
|
||||
#define DFU_SIGNED_COMMAND_INIT_ZERO {DFU_COMMAND_INIT_ZERO, (dfu_signature_type_t)0, {0, {0}}}
|
||||
#define DFU_PACKET_INIT_ZERO {false, DFU_COMMAND_INIT_ZERO, false, DFU_SIGNED_COMMAND_INIT_ZERO}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define DFU_BOOT_VALIDATION_TYPE_TAG 1
|
||||
#define DFU_BOOT_VALIDATION_BYTES_TAG 2
|
||||
#define DFU_HASH_HASH_TYPE_TAG 1
|
||||
#define DFU_HASH_HASH_TAG 2
|
||||
#define DFU_INIT_COMMAND_FW_VERSION_TAG 1
|
||||
#define DFU_INIT_COMMAND_HW_VERSION_TAG 2
|
||||
#define DFU_INIT_COMMAND_SD_REQ_TAG 3
|
||||
#define DFU_INIT_COMMAND_TYPE_TAG 4
|
||||
#define DFU_INIT_COMMAND_SD_SIZE_TAG 5
|
||||
#define DFU_INIT_COMMAND_BL_SIZE_TAG 6
|
||||
#define DFU_INIT_COMMAND_APP_SIZE_TAG 7
|
||||
#define DFU_INIT_COMMAND_HASH_TAG 8
|
||||
#define DFU_INIT_COMMAND_IS_DEBUG_TAG 9
|
||||
#define DFU_INIT_COMMAND_BOOT_VALIDATION_TAG 10
|
||||
#define DFU_COMMAND_OP_CODE_TAG 1
|
||||
#define DFU_COMMAND_INIT_TAG 2
|
||||
#define DFU_SIGNED_COMMAND_COMMAND_TAG 1
|
||||
#define DFU_SIGNED_COMMAND_SIGNATURE_TYPE_TAG 2
|
||||
#define DFU_SIGNED_COMMAND_SIGNATURE_TAG 3
|
||||
#define DFU_PACKET_COMMAND_TAG 1
|
||||
#define DFU_PACKET_SIGNED_COMMAND_TAG 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t dfu_hash_fields[3];
|
||||
extern const pb_field_t dfu_boot_validation_fields[3];
|
||||
extern const pb_field_t dfu_init_command_fields[11];
|
||||
extern const pb_field_t dfu_command_fields[3];
|
||||
extern const pb_field_t dfu_signed_command_fields[4];
|
||||
extern const pb_field_t dfu_packet_fields[3];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define DFU_HASH_SIZE 36
|
||||
#define DFU_BOOT_VALIDATION_SIZE 68
|
||||
#define DFU_INIT_COMMAND_SIZE 378
|
||||
#define DFU_COMMAND_SIZE 383
|
||||
#define DFU_SIGNED_COMMAND_SIZE 454
|
||||
#define DFU_PACKET_SIZE 843
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define DFU_CC_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
82
components/libraries/bootloader/dfu/dfu-cc.proto
Normal file
82
components/libraries/bootloader/dfu/dfu-cc.proto
Normal file
@@ -0,0 +1,82 @@
|
||||
package dfu;
|
||||
|
||||
// Version 0.1
|
||||
|
||||
enum FwType {
|
||||
APPLICATION = 0;
|
||||
SOFTDEVICE = 1;
|
||||
BOOTLOADER = 2;
|
||||
SOFTDEVICE_BOOTLOADER = 3;
|
||||
EXTERNAL_APPLICATION = 4;
|
||||
}
|
||||
|
||||
enum HashType {
|
||||
NO_HASH = 0;
|
||||
CRC = 1;
|
||||
SHA128 = 2;
|
||||
SHA256 = 3;
|
||||
SHA512 = 4;
|
||||
}
|
||||
|
||||
enum OpCode {
|
||||
INIT = 1;
|
||||
}
|
||||
|
||||
enum ValidationType {
|
||||
NO_VALIDATION = 0;
|
||||
VALIDATE_GENERATED_CRC = 1;
|
||||
VALIDATE_SHA256 = 2;
|
||||
VALIDATE_ECDSA_P256_SHA256 = 3;
|
||||
}
|
||||
|
||||
message Hash {
|
||||
required HashType hash_type = 1;
|
||||
required bytes hash = 2;
|
||||
}
|
||||
|
||||
message BootValidation {
|
||||
|
||||
required ValidationType type = 1;
|
||||
required bytes bytes = 2;
|
||||
}
|
||||
|
||||
// Commands data
|
||||
message InitCommand {
|
||||
optional uint32 fw_version = 1;
|
||||
optional uint32 hw_version = 2;
|
||||
repeated uint32 sd_req = 3 [packed = true];
|
||||
optional FwType type = 4;
|
||||
|
||||
optional uint32 sd_size = 5;
|
||||
optional uint32 bl_size = 6;
|
||||
optional uint32 app_size = 7;
|
||||
|
||||
optional Hash hash = 8;
|
||||
|
||||
optional bool is_debug = 9 [default = false];
|
||||
repeated BootValidation boot_validation = 10;
|
||||
}
|
||||
|
||||
// Command type
|
||||
message Command {
|
||||
optional OpCode op_code = 1;
|
||||
optional InitCommand init = 2;
|
||||
}
|
||||
|
||||
// Signed command types
|
||||
enum SignatureType {
|
||||
ECDSA_P256_SHA256 = 0;
|
||||
ED25519 = 1;
|
||||
}
|
||||
|
||||
message SignedCommand {
|
||||
required Command command = 1;
|
||||
required SignatureType signature_type = 2;
|
||||
required bytes signature = 3;
|
||||
}
|
||||
|
||||
// Parent packet type
|
||||
message Packet {
|
||||
optional Command command = 1;
|
||||
optional SignedCommand signed_command = 2;
|
||||
}
|
||||
98
components/libraries/bootloader/dfu/nrf_dfu.c
Normal file
98
components/libraries/bootloader/dfu/nrf_dfu.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_utils.h"
|
||||
#include "nrf_dfu_transport.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
#include "nrf_log.h"
|
||||
|
||||
static nrf_dfu_observer_t m_user_observer; //<! Observer callback set by the user.
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function calls the user's observer (@ref m_observer) after it is done handling the event.
|
||||
*/
|
||||
static void dfu_observer(nrf_dfu_evt_type_t event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case NRF_DFU_EVT_DFU_COMPLETED:
|
||||
case NRF_DFU_EVT_DFU_ABORTED:
|
||||
#ifndef NRF_DFU_NO_TRANSPORT
|
||||
UNUSED_RETURN_VALUE(nrf_dfu_transports_close(NULL));
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call user's observer if present. */
|
||||
if (m_user_observer)
|
||||
{
|
||||
m_user_observer(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t nrf_dfu_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
uint32_t ret_val;
|
||||
|
||||
m_user_observer = observer;
|
||||
|
||||
NRF_LOG_INFO("Entering DFU mode.");
|
||||
|
||||
dfu_observer(NRF_DFU_EVT_DFU_INITIALIZED);
|
||||
|
||||
// Initializing transports
|
||||
ret_val = nrf_dfu_transports_init(dfu_observer);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not initalize DFU transport: 0x%08x", ret_val);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
ret_val = nrf_dfu_req_handler_init(dfu_observer);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
85
components/libraries/bootloader/dfu/nrf_dfu.h
Normal file
85
components/libraries/bootloader/dfu/nrf_dfu.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 DFU modules
|
||||
* @{
|
||||
* @ingroup nrf_bootloader
|
||||
* @brief Modules providing Device Firmware Update (DFU) functionality.
|
||||
*
|
||||
* The DFU module, in combination with the @ref nrf_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>
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define NRF_DFU_SCHED_EVENT_DATA_SIZE (sizeof(nrf_dfu_request_t))
|
||||
|
||||
|
||||
/** @brief Function for initializing a DFU operation.
|
||||
*
|
||||
* This function initializes a DFU operation and any transports that are registered
|
||||
* in the system.
|
||||
*
|
||||
* @param[in] observer Callback function for receiving DFU notifications.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the DFU operation was successfully initialized.
|
||||
*/
|
||||
uint32_t nrf_dfu_init(nrf_dfu_observer_t observer);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_H__
|
||||
|
||||
/** @} */
|
||||
167
components/libraries/bootloader/dfu/nrf_dfu_flash.c
Normal file
167
components/libraries/bootloader/dfu/nrf_dfu_flash.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 "nrf_fstorage.h"
|
||||
#include "nrf_fstorage_sd.h"
|
||||
#include "nrf_fstorage_nvmc.h"
|
||||
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_flash
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
void dfu_fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
|
||||
|
||||
|
||||
NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) =
|
||||
{
|
||||
.evt_handler = dfu_fstorage_evt_handler,
|
||||
.start_addr = MBR_SIZE,
|
||||
.end_addr = BOOTLOADER_SETTINGS_ADDRESS + BOOTLOADER_SETTINGS_PAGE_SIZE
|
||||
};
|
||||
|
||||
static uint32_t m_flash_operations_pending;
|
||||
|
||||
void dfu_fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
|
||||
{
|
||||
if (NRF_LOG_ENABLED && (m_flash_operations_pending > 0))
|
||||
{
|
||||
m_flash_operations_pending--;
|
||||
}
|
||||
|
||||
if (p_evt->result == NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_DEBUG("Flash %s success: addr=%p, pending %d",
|
||||
(p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) ? "write" : "erase",
|
||||
p_evt->addr, m_flash_operations_pending);
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_DEBUG("Flash %s failed (0x%x): addr=%p, len=0x%x bytes, pending %d",
|
||||
(p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) ? "write" : "erase",
|
||||
p_evt->result, p_evt->addr, p_evt->len, m_flash_operations_pending);
|
||||
}
|
||||
|
||||
if (p_evt->p_param)
|
||||
{
|
||||
//lint -save -e611 (Suspicious cast)
|
||||
((nrf_dfu_flash_callback_t)(p_evt->p_param))((void*)p_evt->p_src);
|
||||
//lint -restore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_flash_init(bool sd_irq_initialized)
|
||||
{
|
||||
nrf_fstorage_api_t * p_api_impl;
|
||||
|
||||
/* Setup the desired API implementation. */
|
||||
#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
|
||||
if (sd_irq_initialized)
|
||||
{
|
||||
NRF_LOG_DEBUG("Initializing nrf_fstorage_sd backend.");
|
||||
p_api_impl = &nrf_fstorage_sd;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
NRF_LOG_DEBUG("Initializing nrf_fstorage_nvmc backend.");
|
||||
p_api_impl = &nrf_fstorage_nvmc;
|
||||
}
|
||||
|
||||
return nrf_fstorage_init(&m_fs, p_api_impl, NULL);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_flash_store(uint32_t dest,
|
||||
void const * p_src,
|
||||
uint32_t len,
|
||||
nrf_dfu_flash_callback_t callback)
|
||||
{
|
||||
ret_code_t rc;
|
||||
|
||||
NRF_LOG_DEBUG("nrf_fstorage_write(addr=%p, src=%p, len=%d bytes), queue usage: %d",
|
||||
dest, p_src, len, m_flash_operations_pending);
|
||||
|
||||
//lint -save -e611 (Suspicious cast)
|
||||
rc = nrf_fstorage_write(&m_fs, dest, p_src, len, (void *)callback);
|
||||
//lint -restore
|
||||
|
||||
if ((NRF_LOG_ENABLED) && (rc == NRF_SUCCESS))
|
||||
{
|
||||
m_flash_operations_pending++;
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_WARNING("nrf_fstorage_write() failed with error 0x%x.", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_flash_erase(uint32_t page_addr,
|
||||
uint32_t num_pages,
|
||||
nrf_dfu_flash_callback_t callback)
|
||||
{
|
||||
ret_code_t rc;
|
||||
|
||||
NRF_LOG_DEBUG("nrf_fstorage_erase(addr=0x%p, len=%d pages), queue usage: %d",
|
||||
page_addr, num_pages, m_flash_operations_pending);
|
||||
|
||||
//lint -save -e611 (Suspicious cast)
|
||||
rc = nrf_fstorage_erase(&m_fs, page_addr, num_pages, (void *)callback);
|
||||
//lint -restore
|
||||
|
||||
if ((NRF_LOG_ENABLED) && (rc == NRF_SUCCESS))
|
||||
{
|
||||
m_flash_operations_pending++;
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_WARNING("nrf_fstorage_erase() failed with error 0x%x.", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
132
components/libraries/bootloader/dfu/nrf_dfu_flash.h
Normal file
132
components/libraries/bootloader/dfu/nrf_dfu_flash.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 nrf_dfu
|
||||
*/
|
||||
|
||||
#ifndef NRF_DFU_FLASH_H__
|
||||
#define NRF_DFU_FLASH_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "sdk_errors.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**@brief nrf_fstorage event handler function for DFU fstorage operations.
|
||||
*
|
||||
* This function will be called after a flash operation has completed.
|
||||
*/
|
||||
typedef void (*nrf_dfu_flash_callback_t)(void * p_buf);
|
||||
|
||||
|
||||
/**@brief Function for initializing the flash module.
|
||||
*
|
||||
* Depending on whether or not the SoftDevice is present and its IRQ have been initialized,
|
||||
* this function initializes the correct @ref nrf_fstorage backend.
|
||||
*
|
||||
* @param[in] sd_irq_initialized Whether or not the SoftDevice IRQ have been initialized.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the operation was successful.
|
||||
*/
|
||||
ret_code_t nrf_dfu_flash_init(bool sd_irq_initialized);
|
||||
|
||||
|
||||
/**@brief Function for storing data to flash.
|
||||
*
|
||||
* This functions is asynchronous when the SoftDevice is enabled and synchronous when
|
||||
* the SoftDevice is not present or disabled. In both cases, if a callback function is provided,
|
||||
* it will be called when the operation has completed.
|
||||
*
|
||||
* @note The content of @p p_src should be kept in memory until the operation has completed.
|
||||
*
|
||||
* @param[in] dest 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 The number of bytes to be copied from @p p_src to @p dest.
|
||||
* @param[in] callback Callback function.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the operation was successful.
|
||||
* @retval NRF_ERROR_INVALID_STATE If nrf_dfu_flash is not initialized.
|
||||
* @retval NRF_ERROR_INVALID_ADDR If @p p_src or @p dest is not word-aligned.
|
||||
* @retval NRF_ERROR_INVALID_LENGTH If @p len is zero.
|
||||
* @retval NRF_ERROR_NULL If @p p_src is NULL.
|
||||
* @retval NRF_ERROR_NO_MEM If nrf_fstorage is out of memory.
|
||||
*/
|
||||
ret_code_t nrf_dfu_flash_store(uint32_t dest,
|
||||
void const * p_src,
|
||||
uint32_t len,
|
||||
nrf_dfu_flash_callback_t callback);
|
||||
|
||||
|
||||
/**@brief Function for erasing data from flash.
|
||||
*
|
||||
* This functions is asynchronous when the SoftDevice is enabled and synchronous when
|
||||
* the SoftDevice is not present or disabled. In both cases, if a callback function is provided,
|
||||
* it will be called when the operation has completed.
|
||||
*
|
||||
* @param[in] page_addr The address of the first flash page to be deleted.
|
||||
* @param[in] num_pages The number of flash pages to be deleted.
|
||||
* @param[in] callback Callback function.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the operation was successful.
|
||||
* @retval NRF_ERROR_INVALID_STATE If nrf_dfu_flash is not initialized.
|
||||
* @retval NRF_ERROR_INVALID_ADDR If @p page_addr is not aligned to a page boundary or the
|
||||
* operation would go beyond the flash memory boundaries.
|
||||
* @retval NRF_ERROR_INVALID_LENGTH If @p num_pages is zero.
|
||||
* @retval NRF_ERROR_NULL If @p page_addr is NULL.
|
||||
* @retval NRF_ERROR_NO_MEM If the queue of nrf_fstorage is full.
|
||||
*/
|
||||
ret_code_t nrf_dfu_flash_erase(uint32_t page_addr, uint32_t num_pages, nrf_dfu_flash_callback_t callback);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // NRF_DFU_FLASH_H__
|
||||
/** @} */
|
||||
61
components/libraries/bootloader/dfu/nrf_dfu_handling_error.c
Normal file
61
components/libraries/bootloader/dfu/nrf_dfu_handling_error.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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_handling_error.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
|
||||
static nrf_dfu_ext_error_code_t m_last_error = NRF_DFU_EXT_ERROR_NO_ERROR;
|
||||
|
||||
nrf_dfu_result_t ext_error_set(nrf_dfu_ext_error_code_t error_code)
|
||||
{
|
||||
m_last_error = error_code;
|
||||
|
||||
return NRF_DFU_RES_CODE_EXT_ERROR;
|
||||
}
|
||||
|
||||
nrf_dfu_ext_error_code_t ext_error_get()
|
||||
{
|
||||
nrf_dfu_ext_error_code_t last_error = m_last_error;
|
||||
m_last_error = NRF_DFU_EXT_ERROR_NO_ERROR;
|
||||
|
||||
return last_error;
|
||||
}
|
||||
125
components/libraries/bootloader/dfu/nrf_dfu_handling_error.h
Normal file
125
components/libraries/bootloader/dfu/nrf_dfu_handling_error.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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_rescodes DFU result codes
|
||||
* @{
|
||||
* @ingroup sdk_nrf_dfu_transport
|
||||
* @brief When the DFU controller sends requests to the DFU bootloader on
|
||||
* the DFU target, the DFU bootloader answers with any of these result codes.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DFU_HANDLING_ERROR_H__
|
||||
#define DFU_HANDLING_ERROR_H__
|
||||
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**@brief DFU request extended result codes.
|
||||
*
|
||||
* @details When an event returns @ref NRF_DFU_RES_CODE_EXT_ERROR, it also stores an extended error code.
|
||||
* The transport layer can then send the extended error code together with the error code to give
|
||||
* the controller additional information about the cause of the error.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRF_DFU_EXT_ERROR_NO_ERROR = 0x00, /**< No extended error code has been set. This error indicates an implementation problem. */
|
||||
NRF_DFU_EXT_ERROR_INVALID_ERROR_CODE = 0x01, /**< Invalid error code. This error code should never be used outside of development. */
|
||||
NRF_DFU_EXT_ERROR_WRONG_COMMAND_FORMAT = 0x02, /**< The format of the command was incorrect. This error code is not used in the
|
||||
current implementation, because @ref NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED
|
||||
and @ref NRF_DFU_RES_CODE_INVALID_PARAMETER cover all
|
||||
possible format errors. */
|
||||
NRF_DFU_EXT_ERROR_UNKNOWN_COMMAND = 0x03, /**< The command was successfully parsed, but it is not supported or unknown. */
|
||||
NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID = 0x04, /**< The init command is invalid. The init packet either has
|
||||
an invalid update type or it is missing required fields for the update type
|
||||
(for example, the init packet for a SoftDevice update is missing the SoftDevice size field). */
|
||||
NRF_DFU_EXT_ERROR_FW_VERSION_FAILURE = 0x05, /**< The firmware version is too low. For an application or SoftDevice, the version must be greater than
|
||||
or equal to the current version. For a bootloader, it must be greater than the current version.
|
||||
to the current version. This requirement prevents downgrade attacks.*/
|
||||
NRF_DFU_EXT_ERROR_HW_VERSION_FAILURE = 0x06, /**< The hardware version of the device does not match the required
|
||||
hardware version for the update. */
|
||||
NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE = 0x07, /**< The array of supported SoftDevices for the update does not contain
|
||||
the FWID of the current SoftDevice or the first FWID is '0' on a
|
||||
bootloader which requires the SoftDevice to be present. */
|
||||
NRF_DFU_EXT_ERROR_SIGNATURE_MISSING = 0x08, /**< The init packet does not contain a signature. This error code is not used in the
|
||||
current implementation, because init packets without a signature
|
||||
are regarded as invalid. */
|
||||
NRF_DFU_EXT_ERROR_WRONG_HASH_TYPE = 0x09, /**< The hash type that is specified by the init packet is not supported by the DFU bootloader. */
|
||||
NRF_DFU_EXT_ERROR_HASH_FAILED = 0x0A, /**< The hash of the firmware image cannot be calculated. */
|
||||
NRF_DFU_EXT_ERROR_WRONG_SIGNATURE_TYPE = 0x0B, /**< The type of the signature is unknown or not supported by the DFU bootloader. */
|
||||
NRF_DFU_EXT_ERROR_VERIFICATION_FAILED = 0x0C, /**< The hash of the received firmware image does not match the hash in the init packet. */
|
||||
NRF_DFU_EXT_ERROR_INSUFFICIENT_SPACE = 0x0D, /**< The available space on the device is insufficient to hold the firmware. */
|
||||
} nrf_dfu_ext_error_code_t;
|
||||
|
||||
|
||||
/**@brief Function for setting an extended error code that can be retrieved later.
|
||||
*
|
||||
* @details When an extended error occurs in the DFU process, this function can be used to store the error.
|
||||
*
|
||||
* @param error_code The error code to store.
|
||||
*
|
||||
* @retval NRF_DFU_RES_CODE_EXT_ERROR
|
||||
*/
|
||||
nrf_dfu_result_t ext_error_set(nrf_dfu_ext_error_code_t error_code);
|
||||
|
||||
/**@brief Function for getting the most recent extended error code.
|
||||
*
|
||||
* @details This function is used by the transport layer to fetch the most recent extended error code.
|
||||
*
|
||||
* @return The most recent error code. If the function is called again before a new error occurs, @ref NRF_DFU_EXT_ERROR_NO_ERROR is returned.
|
||||
*/
|
||||
nrf_dfu_ext_error_code_t ext_error_get( void );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // DFU_HANDLING_ERROR_H__
|
||||
|
||||
/** @} */
|
||||
105
components/libraries/bootloader/dfu/nrf_dfu_mbr.c
Normal file
105
components/libraries/bootloader/dfu/nrf_dfu_mbr.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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"
|
||||
#include "nrf_bootloader_info.h"
|
||||
|
||||
#define MBR_IRQ_FORWARD_ADDRESS_ADDRESS (0x20000000) //!< The address of the variable that decides where the MBR forwards interrupts
|
||||
|
||||
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_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_irq_forward_address_set(void)
|
||||
{
|
||||
uint32_t ret_val = NRF_ERROR_INVALID_PARAM;
|
||||
uint32_t address = MBR_SIZE;
|
||||
|
||||
#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD)
|
||||
sd_mbr_command_t command =
|
||||
{
|
||||
.command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET,
|
||||
.params.irq_forward_address_set.address = address,
|
||||
};
|
||||
|
||||
ret_val = sd_mbr_command(&command);
|
||||
#endif
|
||||
|
||||
if (ret_val == NRF_ERROR_INVALID_PARAM)
|
||||
{
|
||||
// Manually set the forward address if this MBR doesn't have the command.
|
||||
*(uint32_t *)(MBR_IRQ_FORWARD_ADDRESS_ADDRESS) = address;
|
||||
|
||||
ret_val = NRF_SUCCESS;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
90
components/libraries/bootloader/dfu/nrf_dfu_mbr.h
Normal file
90
components/libraries/bootloader/dfu/nrf_dfu_mbr.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 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 initializing the SoftDevice using an MBR command.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the SoftDevice was initialized successfully.
|
||||
* Any other return value indicates that the SoftDevice
|
||||
* could not be initialized.
|
||||
*/
|
||||
uint32_t nrf_dfu_mbr_init_sd(void);
|
||||
|
||||
|
||||
/** @brief Function for setting the address of the IRQ table to the app's using an MBR command.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the address of the new irq table was set. Any other
|
||||
* return value indicates that the address could not be set.
|
||||
*/
|
||||
uint32_t nrf_dfu_mbr_irq_forward_address_set(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_MBR_H__
|
||||
|
||||
/** @} */
|
||||
865
components/libraries/bootloader/dfu/nrf_dfu_req_handler.c
Normal file
865
components/libraries/bootloader/dfu/nrf_dfu_req_handler.c
Normal file
@@ -0,0 +1,865 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 <stdbool.h>
|
||||
#include "sdk_config.h"
|
||||
#include "nrf_dfu.h"
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
#include "nrf_dfu_handling_error.h"
|
||||
#include "nrf_dfu_settings.h"
|
||||
#include "nrf_dfu_utils.h"
|
||||
#include "nrf_dfu_flash.h"
|
||||
#include "nrf_fstorage.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "app_util.h"
|
||||
#include "pb.h"
|
||||
#include "pb_common.h"
|
||||
#include "pb_decode.h"
|
||||
#include "dfu-cc.pb.h"
|
||||
#include "crc32.h"
|
||||
#include "app_scheduler.h"
|
||||
#include "sdk_macros.h"
|
||||
#include "nrf_crypto.h"
|
||||
#include "nrf_assert.h"
|
||||
#include "nrf_dfu_validation.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_req_handler
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
#define NRF_DFU_PROTOCOL_VERSION (0x01)
|
||||
|
||||
#ifndef NRF_DFU_PROTOCOL_REDUCED
|
||||
#define NRF_DFU_PROTOCOL_REDUCED 0
|
||||
#endif
|
||||
|
||||
STATIC_ASSERT(DFU_SIGNED_COMMAND_SIZE <= INIT_COMMAND_MAX_SIZE);
|
||||
|
||||
static uint32_t m_firmware_start_addr; /**< Start address of the current firmware image. */
|
||||
static uint32_t m_firmware_size_req; /**< The size of the entire firmware image. Defined by the init command. */
|
||||
|
||||
static nrf_dfu_observer_t m_observer;
|
||||
|
||||
|
||||
static void on_dfu_complete(nrf_fstorage_evt_t * p_evt)
|
||||
{
|
||||
UNUSED_PARAMETER(p_evt);
|
||||
|
||||
NRF_LOG_DEBUG("All flash operations have completed. DFU completed.");
|
||||
|
||||
m_observer(NRF_DFU_EVT_DFU_COMPLETED);
|
||||
}
|
||||
|
||||
|
||||
static nrf_dfu_result_t ext_err_code_handle(nrf_dfu_result_t ret_val)
|
||||
{
|
||||
if (ret_val < NRF_DFU_RES_CODE_EXT_ERROR)
|
||||
{
|
||||
return ret_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_dfu_ext_error_code_t ext_err =
|
||||
(nrf_dfu_ext_error_code_t)((uint8_t)ret_val - (uint8_t)NRF_DFU_RES_CODE_EXT_ERROR);
|
||||
return ext_error_set(ext_err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !NRF_DFU_PROTOCOL_REDUCED
|
||||
static void on_protocol_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
UNUSED_PARAMETER(p_req);
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_PROTOCOL_VERSION");
|
||||
|
||||
if (NRF_DFU_PROTOCOL_VERSION_MSG)
|
||||
{
|
||||
p_res->protocol.version = NRF_DFU_PROTOCOL_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_DEBUG("NRF_DFU_OP_PROTOCOL_VERSION disabled.");
|
||||
p_res->result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_hw_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_HARDWARE_VERSION");
|
||||
|
||||
p_res->hardware.part = NRF_FICR->INFO.PART;
|
||||
p_res->hardware.variant = NRF_FICR->INFO.VARIANT;
|
||||
|
||||
/* FICR values are in Kilobytes, we report them in bytes. */
|
||||
p_res->hardware.memory.ram_size = NRF_FICR->INFO.RAM * 1024;
|
||||
p_res->hardware.memory.rom_size = NRF_FICR->INFO.FLASH * 1024;
|
||||
p_res->hardware.memory.rom_page_size = NRF_FICR->CODEPAGESIZE;
|
||||
}
|
||||
|
||||
|
||||
static void on_fw_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_FIRMWARE_VERSION");
|
||||
NRF_LOG_DEBUG("Firmware image requested: %d", p_req->firmware.image_number);
|
||||
|
||||
if (NRF_DFU_PROTOCOL_FW_VERSION_MSG)
|
||||
{
|
||||
uint8_t fw_count = 1;
|
||||
|
||||
if (SD_PRESENT)
|
||||
{
|
||||
fw_count++;
|
||||
}
|
||||
|
||||
if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP)
|
||||
{
|
||||
fw_count++;
|
||||
}
|
||||
|
||||
p_res->result = NRF_DFU_RES_CODE_SUCCESS;
|
||||
|
||||
if (p_req->firmware.image_number == 0)
|
||||
{
|
||||
/* Bootloader is always present and it is always image zero. */
|
||||
p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_BOOTLOADER;
|
||||
p_res->firmware.version = s_dfu_settings.bootloader_version;
|
||||
p_res->firmware.addr = BOOTLOADER_START_ADDR;
|
||||
p_res->firmware.len = BOOTLOADER_SIZE;
|
||||
}
|
||||
else if ((p_req->firmware.image_number == 1) && SD_PRESENT)
|
||||
{
|
||||
/* If a SoftDevice is present, it will be firmware image one. */
|
||||
p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_SOFTDEVICE;
|
||||
p_res->firmware.version = SD_VERSION_GET(MBR_SIZE);
|
||||
p_res->firmware.addr = MBR_SIZE;
|
||||
p_res->firmware.len = SD_SIZE_GET(MBR_SIZE);
|
||||
}
|
||||
else if ((p_req->firmware.image_number < fw_count))
|
||||
{
|
||||
/* Either there is no SoftDevice and the firmware image requested is one,
|
||||
* or there is a SoftDevice and the firmware image requested is two.
|
||||
*/
|
||||
p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_APPLICATION;
|
||||
p_res->firmware.version = s_dfu_settings.app_version;
|
||||
p_res->firmware.addr = nrf_dfu_app_start_address();
|
||||
p_res->firmware.len = s_dfu_settings.bank_0.image_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_DEBUG("No such firmware image");
|
||||
p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_UNKNOWN;
|
||||
p_res->firmware.version = 0x00;
|
||||
p_res->firmware.addr = 0x00;
|
||||
p_res->firmware.len = 0x00;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_DEBUG("NRF_DFU_OP_FIRMWARE_VERSION disabled.");
|
||||
p_res->result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED;
|
||||
p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_ping_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_PING");
|
||||
p_res->ping.id = p_req->ping.id;
|
||||
}
|
||||
|
||||
|
||||
static void on_mtu_get_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_MTU_GET");
|
||||
p_res->mtu.size = p_req->mtu.size;
|
||||
}
|
||||
#endif // !NRF_DFU_PROTOCOL_REDUCED
|
||||
|
||||
|
||||
static void on_prn_set_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
UNUSED_PARAMETER(p_req);
|
||||
UNUSED_PARAMETER(p_res);
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_RECEIPT_NOTIF_SET");
|
||||
}
|
||||
|
||||
|
||||
static void on_abort_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
UNUSED_PARAMETER(p_req);
|
||||
UNUSED_PARAMETER(p_res);
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_ABORT");
|
||||
|
||||
m_observer(NRF_DFU_EVT_DFU_ABORTED);
|
||||
}
|
||||
|
||||
|
||||
/* Set offset and CRC fields in the response for a 'command' message. */
|
||||
static void cmd_response_offset_and_crc_set(nrf_dfu_response_t * const p_res)
|
||||
{
|
||||
ASSERT(p_res);
|
||||
|
||||
/* Copy the CRC and offset of the init packet. */
|
||||
p_res->crc.offset = s_dfu_settings.progress.command_offset;
|
||||
p_res->crc.crc = s_dfu_settings.progress.command_crc;
|
||||
}
|
||||
|
||||
|
||||
static void on_cmd_obj_select_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
UNUSED_PARAMETER(p_req);
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_SELECT (command)");
|
||||
|
||||
p_res->select.max_size = INIT_COMMAND_MAX_SIZE;
|
||||
cmd_response_offset_and_crc_set(p_res);
|
||||
}
|
||||
|
||||
|
||||
static void on_cmd_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
ASSERT(p_req);
|
||||
ASSERT(p_res);
|
||||
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (command)");
|
||||
|
||||
m_observer(NRF_DFU_EVT_DFU_STARTED);
|
||||
|
||||
nrf_dfu_result_t ret_val = nrf_dfu_validation_init_cmd_create(p_req->create.object_size);
|
||||
p_res->result = ext_err_code_handle(ret_val);
|
||||
}
|
||||
|
||||
|
||||
static void on_cmd_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
ASSERT(p_req);
|
||||
ASSERT(p_req->write.p_data);
|
||||
ASSERT(p_req->write.len);
|
||||
ASSERT(p_res);
|
||||
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (command)");
|
||||
|
||||
nrf_dfu_result_t ret_val;
|
||||
|
||||
ret_val = nrf_dfu_validation_init_cmd_append(p_req->write.p_data, p_req->write.len);
|
||||
p_res->result = ext_err_code_handle(ret_val);
|
||||
|
||||
/* Update response. This is only used when the PRN is triggered and the 'write' message
|
||||
* is answered with a CRC message and these field are copied into the response. */
|
||||
cmd_response_offset_and_crc_set(p_res);
|
||||
|
||||
/* If a callback to free the request payload buffer was provided, invoke it now. */
|
||||
if (p_req->callback.write)
|
||||
{
|
||||
p_req->callback.write((void*)p_req->write.p_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_cmd_obj_execute_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
ASSERT(p_req);
|
||||
ASSERT(p_res);
|
||||
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_EXECUTE (command)");
|
||||
|
||||
nrf_dfu_result_t ret_val;
|
||||
ret_val = nrf_dfu_validation_init_cmd_execute(&m_firmware_start_addr, &m_firmware_size_req);
|
||||
p_res->result = ext_err_code_handle(ret_val);
|
||||
|
||||
if (p_res->result == NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
if (nrf_dfu_settings_write_and_backup(NULL) == NRF_SUCCESS)
|
||||
{
|
||||
/* Setting DFU to initialized */
|
||||
NRF_LOG_DEBUG("Writing valid init command to flash.");
|
||||
}
|
||||
else
|
||||
{
|
||||
p_res->result = NRF_DFU_RES_CODE_OPERATION_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_cmd_obj_crc_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
UNUSED_PARAMETER(p_req);
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_CRC_GET (command)");
|
||||
|
||||
cmd_response_offset_and_crc_set(p_res);
|
||||
}
|
||||
|
||||
|
||||
/** @brief Function handling command requests from the transport layer.
|
||||
*
|
||||
* @param p_req[in] Pointer to the structure holding the DFU request.
|
||||
* @param p_res[out] Pointer to the structure holding the DFU response.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the command request was executed successfully.
|
||||
* Any other error code indicates that the data request
|
||||
* could not be handled.
|
||||
*/
|
||||
static void nrf_dfu_command_req(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
ASSERT(p_req);
|
||||
ASSERT(p_res);
|
||||
|
||||
switch (p_req->request)
|
||||
{
|
||||
case NRF_DFU_OP_OBJECT_CREATE:
|
||||
{
|
||||
on_cmd_obj_create_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_CRC_GET:
|
||||
{
|
||||
on_cmd_obj_crc_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_WRITE:
|
||||
{
|
||||
on_cmd_obj_write_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_EXECUTE:
|
||||
{
|
||||
on_cmd_obj_execute_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_SELECT:
|
||||
{
|
||||
on_cmd_obj_select_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
ASSERT(false);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_data_obj_select_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_SELECT (data)");
|
||||
|
||||
p_res->select.crc = s_dfu_settings.progress.firmware_image_crc;
|
||||
p_res->select.offset = s_dfu_settings.progress.firmware_image_offset;
|
||||
|
||||
p_res->select.max_size = DATA_OBJECT_MAX_SIZE;
|
||||
|
||||
NRF_LOG_DEBUG("crc = 0x%x, offset = 0x%x, max_size = 0x%x",
|
||||
p_res->select.crc,
|
||||
p_res->select.offset,
|
||||
p_res->select.max_size);
|
||||
}
|
||||
|
||||
|
||||
static void on_data_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (data)");
|
||||
|
||||
if (!nrf_dfu_validation_init_cmd_present())
|
||||
{
|
||||
/* Can't accept data because DFU isn't initialized by init command. */
|
||||
NRF_LOG_ERROR("Cannot create data object without valid init command");
|
||||
p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_req->create.object_size == 0)
|
||||
{
|
||||
NRF_LOG_ERROR("Object size cannot be 0.")
|
||||
p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ((p_req->create.object_size & (CODE_PAGE_SIZE - 1)) != 0)
|
||||
&& (s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size != m_firmware_size_req))
|
||||
{
|
||||
NRF_LOG_ERROR("Object size must be page aligned");
|
||||
p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_req->create.object_size > DATA_OBJECT_MAX_SIZE)
|
||||
{
|
||||
/* It is impossible to handle the command because the size is too large */
|
||||
NRF_LOG_ERROR("Invalid size for object (too large)");
|
||||
p_res->result = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size) >
|
||||
m_firmware_size_req)
|
||||
{
|
||||
NRF_LOG_ERROR("Creating the object with size 0x%08x would overflow firmware size. "
|
||||
"Offset is 0x%08x and firmware size is 0x%08x.",
|
||||
p_req->create.object_size,
|
||||
s_dfu_settings.progress.firmware_image_offset_last,
|
||||
m_firmware_size_req);
|
||||
|
||||
p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED;
|
||||
return;
|
||||
}
|
||||
|
||||
s_dfu_settings.progress.data_object_size = p_req->create.object_size;
|
||||
s_dfu_settings.progress.firmware_image_crc = s_dfu_settings.progress.firmware_image_crc_last;
|
||||
s_dfu_settings.progress.firmware_image_offset = s_dfu_settings.progress.firmware_image_offset_last;
|
||||
s_dfu_settings.write_offset = s_dfu_settings.progress.firmware_image_offset_last;
|
||||
|
||||
/* Erase the page we're at. */
|
||||
if (nrf_dfu_flash_erase((m_firmware_start_addr + s_dfu_settings.progress.firmware_image_offset),
|
||||
CEIL_DIV(p_req->create.object_size, CODE_PAGE_SIZE), NULL) != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Erase operation failed");
|
||||
p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT;
|
||||
return;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Creating object with size: %d. Offset: 0x%08x, CRC: 0x%08x",
|
||||
s_dfu_settings.progress.data_object_size,
|
||||
s_dfu_settings.progress.firmware_image_offset,
|
||||
s_dfu_settings.progress.firmware_image_crc);
|
||||
}
|
||||
|
||||
|
||||
static void on_data_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (data)");
|
||||
|
||||
if (!nrf_dfu_validation_init_cmd_present())
|
||||
{
|
||||
/* Can't accept data because DFU isn't initialized by init command. */
|
||||
p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t const data_object_offset = s_dfu_settings.progress.firmware_image_offset -
|
||||
s_dfu_settings.progress.firmware_image_offset_last;
|
||||
|
||||
if ((p_req->write.len + data_object_offset) > s_dfu_settings.progress.data_object_size)
|
||||
{
|
||||
/* Can't accept data because too much data has been received. */
|
||||
NRF_LOG_ERROR("Write request too long");
|
||||
p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t const write_addr = m_firmware_start_addr + s_dfu_settings.write_offset;
|
||||
/* CRC must be calculated before handing off the data to fstorage because the data is
|
||||
* freed on write completion.
|
||||
*/
|
||||
uint32_t const next_crc =
|
||||
crc32_compute(p_req->write.p_data, p_req->write.len, &s_dfu_settings.progress.firmware_image_crc);
|
||||
|
||||
ASSERT(p_req->callback.write);
|
||||
|
||||
ret_code_t ret =
|
||||
nrf_dfu_flash_store(write_addr, p_req->write.p_data, p_req->write.len, p_req->callback.write);
|
||||
|
||||
if (ret != NRF_SUCCESS)
|
||||
{
|
||||
/* When nrf_dfu_flash_store() fails because there is no space in the queue,
|
||||
* stop processing the request so that the peer can detect a CRC error
|
||||
* and retransmit this object. Remember to manually free the buffer !
|
||||
*/
|
||||
p_req->callback.write((void*)p_req->write.p_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update the CRC of the firmware image. */
|
||||
s_dfu_settings.write_offset += p_req->write.len;
|
||||
s_dfu_settings.progress.firmware_image_offset += p_req->write.len;
|
||||
s_dfu_settings.progress.firmware_image_crc = next_crc;
|
||||
|
||||
/* This is only used when the PRN is triggered and the 'write' message
|
||||
* is answered with a CRC message and these field are copied into the response.
|
||||
*/
|
||||
p_res->write.crc = s_dfu_settings.progress.firmware_image_crc;
|
||||
p_res->write.offset = s_dfu_settings.progress.firmware_image_offset;
|
||||
}
|
||||
|
||||
|
||||
static void on_data_obj_crc_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_CRC_GET (data)");
|
||||
NRF_LOG_DEBUG("Offset:%d, CRC:0x%08x",
|
||||
s_dfu_settings.progress.firmware_image_offset,
|
||||
s_dfu_settings.progress.firmware_image_crc);
|
||||
|
||||
p_res->crc.crc = s_dfu_settings.progress.firmware_image_crc;
|
||||
p_res->crc.offset = s_dfu_settings.progress.firmware_image_offset;
|
||||
}
|
||||
|
||||
|
||||
static void on_data_obj_execute_request_sched(void * p_evt, uint16_t event_length)
|
||||
{
|
||||
UNUSED_PARAMETER(event_length);
|
||||
|
||||
ret_code_t ret;
|
||||
nrf_dfu_request_t * p_req = (nrf_dfu_request_t *)(p_evt);
|
||||
|
||||
/* Wait for all buffers to be written in flash. */
|
||||
if (nrf_fstorage_is_busy(NULL))
|
||||
{
|
||||
ret = app_sched_event_put(p_req, sizeof(nrf_dfu_request_t), on_data_obj_execute_request_sched);
|
||||
if (ret != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed to schedule object execute: 0x%x.", ret);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nrf_dfu_response_t res =
|
||||
{
|
||||
.request = NRF_DFU_OP_OBJECT_EXECUTE,
|
||||
};
|
||||
|
||||
if (s_dfu_settings.progress.firmware_image_offset == m_firmware_size_req)
|
||||
{
|
||||
NRF_LOG_DEBUG("Whole firmware image received. Postvalidating.");
|
||||
|
||||
#if NRF_DFU_IN_APP
|
||||
res.result = nrf_dfu_validation_post_data_execute(m_firmware_start_addr, m_firmware_size_req);
|
||||
#else
|
||||
res.result = nrf_dfu_validation_activation_prepare(m_firmware_start_addr, m_firmware_size_req);
|
||||
#endif
|
||||
|
||||
res.result = ext_err_code_handle(res.result);
|
||||
|
||||
/* Provide response to transport */
|
||||
p_req->callback.response(&res, p_req->p_context);
|
||||
|
||||
ret = nrf_dfu_settings_write_and_backup((nrf_dfu_flash_callback_t)on_dfu_complete);
|
||||
UNUSED_RETURN_VALUE(ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.result = NRF_DFU_RES_CODE_SUCCESS;
|
||||
|
||||
/* Provide response to transport */
|
||||
p_req->callback.response(&res, p_req->p_context);
|
||||
|
||||
if (NRF_DFU_SAVE_PROGRESS_IN_FLASH)
|
||||
{
|
||||
/* Allowing skipping settings backup to save time and flash wear. */
|
||||
ret = nrf_dfu_settings_write_and_backup(NULL);
|
||||
UNUSED_RETURN_VALUE(ret);
|
||||
}
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Request handling complete. Result: 0x%x", res.result);
|
||||
}
|
||||
|
||||
|
||||
static bool on_data_obj_execute_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_EXECUTE (data)");
|
||||
|
||||
uint32_t const data_object_size = s_dfu_settings.progress.firmware_image_offset -
|
||||
s_dfu_settings.progress.firmware_image_offset_last;
|
||||
|
||||
if (s_dfu_settings.progress.data_object_size != data_object_size)
|
||||
{
|
||||
/* The size of the written object was not as expected. */
|
||||
NRF_LOG_ERROR("Invalid data. expected: %d, got: %d",
|
||||
s_dfu_settings.progress.data_object_size,
|
||||
data_object_size);
|
||||
|
||||
p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Update the offset and crc values for the last object written. */
|
||||
s_dfu_settings.progress.data_object_size = 0;
|
||||
s_dfu_settings.progress.firmware_image_crc_last = s_dfu_settings.progress.firmware_image_crc;
|
||||
s_dfu_settings.progress.firmware_image_offset_last = s_dfu_settings.progress.firmware_image_offset;
|
||||
|
||||
on_data_obj_execute_request_sched(p_req, 0);
|
||||
|
||||
m_observer(NRF_DFU_EVT_OBJECT_RECEIVED);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool nrf_dfu_data_req(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
ASSERT(p_req);
|
||||
ASSERT(p_res);
|
||||
|
||||
bool response_ready = true;
|
||||
|
||||
switch (p_req->request)
|
||||
{
|
||||
case NRF_DFU_OP_OBJECT_CREATE:
|
||||
{
|
||||
on_data_obj_create_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_WRITE:
|
||||
{
|
||||
on_data_obj_write_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_CRC_GET:
|
||||
{
|
||||
on_data_obj_crc_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_EXECUTE:
|
||||
{
|
||||
response_ready = on_data_obj_execute_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_SELECT:
|
||||
{
|
||||
on_data_obj_select_request(p_req, p_res);
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
ASSERT(false);
|
||||
} break;
|
||||
}
|
||||
|
||||
return response_ready;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling requests to manipulate data or command objects.
|
||||
*
|
||||
* @param[in] p_req Request.
|
||||
* @param[out] p_res Response.
|
||||
*
|
||||
* @return Whether response is ready to be sent.
|
||||
*/
|
||||
static bool nrf_dfu_obj_op(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res)
|
||||
{
|
||||
/* Keep track of the current object type since write and execute requests don't contain it. */
|
||||
static nrf_dfu_obj_type_t current_object = NRF_DFU_OBJ_TYPE_COMMAND;
|
||||
|
||||
if ( (p_req->request == NRF_DFU_OP_OBJECT_SELECT)
|
||||
|| (p_req->request == NRF_DFU_OP_OBJECT_CREATE))
|
||||
{
|
||||
STATIC_ASSERT(offsetof(nrf_dfu_request_select_t, object_type) ==
|
||||
offsetof(nrf_dfu_request_create_t, object_type),
|
||||
"Wrong object_type offset!");
|
||||
|
||||
current_object = (nrf_dfu_obj_type_t)(p_req->select.object_type);
|
||||
}
|
||||
|
||||
bool response_ready = true;
|
||||
|
||||
switch (current_object)
|
||||
{
|
||||
case NRF_DFU_OBJ_TYPE_COMMAND:
|
||||
nrf_dfu_command_req(p_req, p_res);
|
||||
break;
|
||||
|
||||
case NRF_DFU_OBJ_TYPE_DATA:
|
||||
response_ready = nrf_dfu_data_req(p_req, p_res);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* The select request had an invalid object type. */
|
||||
NRF_LOG_ERROR("Invalid object type in request.");
|
||||
current_object = NRF_DFU_OBJ_TYPE_INVALID;
|
||||
p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT;
|
||||
break;
|
||||
}
|
||||
|
||||
return response_ready;
|
||||
}
|
||||
|
||||
|
||||
static void nrf_dfu_req_handler_req_process(nrf_dfu_request_t * p_req)
|
||||
{
|
||||
ASSERT(p_req->callback.response);
|
||||
|
||||
bool response_ready = true;
|
||||
|
||||
/* The request handlers assume these values to be set. */
|
||||
nrf_dfu_response_t response =
|
||||
{
|
||||
.request = p_req->request,
|
||||
.result = NRF_DFU_RES_CODE_SUCCESS,
|
||||
};
|
||||
|
||||
|
||||
switch (p_req->request)
|
||||
{
|
||||
#if !NRF_DFU_PROTOCOL_REDUCED
|
||||
case NRF_DFU_OP_PROTOCOL_VERSION:
|
||||
{
|
||||
on_protocol_version_request(p_req, &response);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_HARDWARE_VERSION:
|
||||
{
|
||||
on_hw_version_request(p_req, &response);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_FIRMWARE_VERSION:
|
||||
{
|
||||
on_fw_version_request(p_req, &response);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_PING:
|
||||
{
|
||||
on_ping_request(p_req, &response);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_MTU_GET:
|
||||
{
|
||||
on_mtu_get_request(p_req, &response);
|
||||
} break;
|
||||
#endif
|
||||
case NRF_DFU_OP_RECEIPT_NOTIF_SET:
|
||||
{
|
||||
on_prn_set_request(p_req, &response);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_ABORT:
|
||||
{
|
||||
on_abort_request(p_req, &response);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_CREATE:
|
||||
/* Restart the inactivity timer on CREATE messages. */
|
||||
/* Fallthrough. */
|
||||
case NRF_DFU_OP_OBJECT_SELECT:
|
||||
case NRF_DFU_OP_OBJECT_WRITE:
|
||||
case NRF_DFU_OP_OBJECT_EXECUTE:
|
||||
case NRF_DFU_OP_CRC_GET:
|
||||
{
|
||||
response_ready = nrf_dfu_obj_op(p_req, &response);
|
||||
} break;
|
||||
|
||||
default:
|
||||
NRF_LOG_INFO("Invalid opcode received: 0x%x.", p_req->request);
|
||||
response.result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (response_ready)
|
||||
{
|
||||
NRF_LOG_DEBUG("Request handling complete. Result: 0x%x", response.result);
|
||||
|
||||
p_req->callback.response(&response, p_req->p_context);
|
||||
|
||||
if (response.result != NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
m_observer(NRF_DFU_EVT_DFU_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void nrf_dfu_req_handler_req(void * p_evt, uint16_t event_length)
|
||||
{
|
||||
nrf_dfu_request_t * p_req = (nrf_dfu_request_t *)(p_evt);
|
||||
nrf_dfu_req_handler_req_process(p_req);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_req_handler_on_req(nrf_dfu_request_t * p_req)
|
||||
{
|
||||
ret_code_t ret;
|
||||
|
||||
if (p_req->callback.response == NULL)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ret = app_sched_event_put(p_req, sizeof(nrf_dfu_request_t), nrf_dfu_req_handler_req);
|
||||
if (ret != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_WARNING("Scheduler ran out of space!");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_req_handler_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
ret_code_t ret_val;
|
||||
nrf_dfu_result_t result;
|
||||
|
||||
if (observer == NULL)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
|
||||
ret_val = nrf_dfu_flash_init(true);
|
||||
#else
|
||||
ret_val = nrf_dfu_flash_init(false);
|
||||
#endif
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
nrf_dfu_validation_init();
|
||||
if (nrf_dfu_validation_init_cmd_present())
|
||||
{
|
||||
/* Execute a previously received init packed. Subsequent executes will have no effect. */
|
||||
result = nrf_dfu_validation_init_cmd_execute(&m_firmware_start_addr, &m_firmware_size_req);
|
||||
if (result != NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
/* Init packet in flash is not valid! */
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
m_observer = observer;
|
||||
|
||||
/* Initialize extended error handling with "No error" as the most recent error. */
|
||||
result = ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR);
|
||||
UNUSED_RETURN_VALUE(result);
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
345
components/libraries/bootloader/dfu/nrf_dfu_req_handler.h
Normal file
345
components/libraries/bootloader/dfu/nrf_dfu_req_handler.h
Normal file
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 nrf_dfu
|
||||
*/
|
||||
|
||||
#ifndef NRF_DFU_REQ_HANDLER_H__
|
||||
#define NRF_DFU_REQ_HANDLER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "app_util_platform.h"
|
||||
#include "nrf_dfu_flash.h"
|
||||
#include "nrf_dfu_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
ANON_UNIONS_ENABLE;
|
||||
|
||||
/**
|
||||
* @brief DFU object types.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRF_DFU_OBJ_TYPE_INVALID, //!< Invalid object type.
|
||||
NRF_DFU_OBJ_TYPE_COMMAND, //!< Command object.
|
||||
NRF_DFU_OBJ_TYPE_DATA, //!< Data object.
|
||||
} nrf_dfu_obj_type_t;
|
||||
|
||||
/**
|
||||
* @brief DFU protocol operation.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRF_DFU_OP_PROTOCOL_VERSION = 0x00, //!< Retrieve protocol version.
|
||||
NRF_DFU_OP_OBJECT_CREATE = 0x01, //!< Create selected object.
|
||||
NRF_DFU_OP_RECEIPT_NOTIF_SET = 0x02, //!< Set receipt notification.
|
||||
NRF_DFU_OP_CRC_GET = 0x03, //!< Request CRC of selected object.
|
||||
NRF_DFU_OP_OBJECT_EXECUTE = 0x04, //!< Execute selected object.
|
||||
NRF_DFU_OP_OBJECT_SELECT = 0x06, //!< Select object.
|
||||
NRF_DFU_OP_MTU_GET = 0x07, //!< Retrieve MTU size.
|
||||
NRF_DFU_OP_OBJECT_WRITE = 0x08, //!< Write selected object.
|
||||
NRF_DFU_OP_PING = 0x09, //!< Ping.
|
||||
NRF_DFU_OP_HARDWARE_VERSION = 0x0A, //!< Retrieve hardware version.
|
||||
NRF_DFU_OP_FIRMWARE_VERSION = 0x0B, //!< Retrieve firmware version.
|
||||
NRF_DFU_OP_ABORT = 0x0C, //!< Abort the DFU procedure.
|
||||
NRF_DFU_OP_RESPONSE = 0x60, //!< Response.
|
||||
NRF_DFU_OP_INVALID = 0xFF,
|
||||
} nrf_dfu_op_t;
|
||||
|
||||
/**
|
||||
* @brief DFU operation result code.
|
||||
*/
|
||||
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 wrong, 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. The next byte of the response contains the error code of the extended error (see @ref nrf_dfu_ext_error_code_t.
|
||||
} nrf_dfu_result_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NRF_DFU_FIRMWARE_TYPE_SOFTDEVICE = 0x00,
|
||||
NRF_DFU_FIRMWARE_TYPE_APPLICATION = 0x01,
|
||||
NRF_DFU_FIRMWARE_TYPE_BOOTLOADER = 0x02,
|
||||
NRF_DFU_FIRMWARE_TYPE_UNKNOWN = 0xFF,
|
||||
} nrf_dfu_firmware_type_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_PROTOCOL_VERSION response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t version; //!< Protocol version.
|
||||
} nrf_dfu_response_protocol_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_HARDWARE_VERSION response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t part; //!< Hardware part, from FICR register.
|
||||
uint32_t variant; //!< Hardware variant, from FICR register.
|
||||
struct
|
||||
{
|
||||
uint32_t rom_size; //!< ROM size, in bytes.
|
||||
uint32_t ram_size; //!< RAM size, in bytes.
|
||||
uint32_t rom_page_size; //!< ROM flash page size, in bytes.
|
||||
} memory;
|
||||
} nrf_dfu_response_hardware_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_FIRMWARE_VERSION response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrf_dfu_firmware_type_t type; //!< Firmware type.
|
||||
uint32_t version; //!< Firmware version.
|
||||
uint32_t addr; //!< Firmware address in flash.
|
||||
uint32_t len; //!< Firmware length in bytes.
|
||||
} nrf_dfu_response_firmware_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_OBJECT_SELECT response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t offset; //!< Current offset.
|
||||
uint32_t crc; //!< Current CRC.
|
||||
uint32_t max_size; //!< Maximum size of selected object.
|
||||
} nrf_dfu_response_select_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_OBJECT_CREATE response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t offset; //!< Current offset
|
||||
uint32_t crc; //!< Current CRC.
|
||||
} nrf_dfu_response_create_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_OBJECT_WRITE response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t offset; //!< Used only when packet receipt notification is used.
|
||||
uint32_t crc; //!< Used only when packet receipt notification is used.
|
||||
} nrf_dfu_response_write_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_CRC_GET response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t offset; //!< Current offset.
|
||||
uint32_t crc; //!< Current CRC.
|
||||
} nrf_dfu_response_crc_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_PING response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t id; //!< The received ID which is echoed back.
|
||||
} nrf_dfu_response_ping_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_MTU_GET response details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t size; //!< The MTU size as specified by the local transport.
|
||||
} nrf_dfu_response_mtu_t;
|
||||
|
||||
/**
|
||||
* @brief DFU response message.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrf_dfu_op_t request; //!< Requested operation.
|
||||
nrf_dfu_result_t result; //!< Result of the operation.
|
||||
union
|
||||
{
|
||||
nrf_dfu_response_protocol_t protocol; //!< Protocol version response.
|
||||
nrf_dfu_response_hardware_t hardware; //!< Hardware version response.
|
||||
nrf_dfu_response_firmware_t firmware; //!< Firmware version response.
|
||||
nrf_dfu_response_select_t select; //!< Select object response..
|
||||
nrf_dfu_response_create_t create; //!< Create object response..
|
||||
nrf_dfu_response_write_t write; //!< Write object response.
|
||||
nrf_dfu_response_crc_t crc; //!< CRC response.
|
||||
nrf_dfu_response_ping_t ping; //!< Ping response.
|
||||
nrf_dfu_response_mtu_t mtu; //!< MTU response.
|
||||
};
|
||||
} nrf_dfu_response_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_FIRMWARE_VERSION request details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t image_number; //!< Index of the firmware.
|
||||
} nrf_dfu_request_firmware_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_OBJECT_SELECT request details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t object_type; //!< Object type. See @ref nrf_dfu_obj_type_t.
|
||||
} nrf_dfu_request_select_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_OBJECT_CREATE request details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t object_type; //!< Object type. See @ref nrf_dfu_obj_type_t.
|
||||
uint32_t object_size; //!< Object size in bytes.
|
||||
} nrf_dfu_request_create_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_OBJECT_WRITE request details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t const * p_data; //!< Data.
|
||||
uint16_t len; //!< Length of data in @ref nrf_dfu_request_write_t::p_data.
|
||||
} nrf_dfu_request_write_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_PING request details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t id; //!< Ping ID that will be returned in response.
|
||||
} nrf_dfu_request_ping_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_MTU_GET request details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t size; //!< Transport MTU size in bytes.
|
||||
} nrf_dfu_request_mtu_t;
|
||||
|
||||
/**
|
||||
* @brief @ref NRF_DFU_OP_RECEIPT_NOTIF_SET request details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t target; //!< Target PRN.
|
||||
} nrf_dfu_request_prn_t;
|
||||
|
||||
|
||||
typedef void (*nrf_dfu_response_callback_t)(nrf_dfu_response_t * p_res, void * p_context);
|
||||
|
||||
/**
|
||||
*@brief DFU request.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
nrf_dfu_op_t request; //!< Requested operation.
|
||||
void * p_context;
|
||||
struct
|
||||
{
|
||||
nrf_dfu_response_callback_t response; //!< Callback to call to send the response.
|
||||
nrf_dfu_flash_callback_t write;
|
||||
} callback;
|
||||
union
|
||||
{
|
||||
nrf_dfu_request_firmware_t firmware; //!< Firmware version request.
|
||||
nrf_dfu_request_select_t select; //!< Select object request.
|
||||
nrf_dfu_request_create_t create; //!< Create object request.
|
||||
nrf_dfu_request_write_t write; //!< Write object request.
|
||||
nrf_dfu_request_ping_t ping; //!< Ping.
|
||||
nrf_dfu_request_mtu_t mtu; //!< MTU size request.
|
||||
nrf_dfu_request_prn_t prn; //!< Set receipt notification request.
|
||||
};
|
||||
} nrf_dfu_request_t;
|
||||
|
||||
|
||||
/**@brief Function for initializing the request handling module.
|
||||
*
|
||||
* @param observer Callback function for receiving notifications.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the operation was successful.
|
||||
* @retval NRF_ERROR_INTERNAL If the init packet in flash is not valid.
|
||||
* @retval NRF_ERROR_INVALID_PARAM If observer is not provided.
|
||||
*/
|
||||
ret_code_t nrf_dfu_req_handler_init(nrf_dfu_observer_t observer);
|
||||
|
||||
|
||||
/**@brief Function for scheduling processing of a DFU request.
|
||||
*
|
||||
* Requests are processed asynchronously by the scheduler.
|
||||
*
|
||||
* @param[in] p_req Request to be handled. The response callback must be non-null.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the command request was executed successfully.
|
||||
* @retval NRF_ERROR_NO_MEM If the scheduler ran out of memory.
|
||||
* @retval NRF_ERROR_INVALID_PARAM If the response callback is NULL.
|
||||
*/
|
||||
ret_code_t nrf_dfu_req_handler_on_req(nrf_dfu_request_t * p_req);
|
||||
|
||||
|
||||
ANON_UNIONS_DISABLE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_REQ_HANDLER_H__
|
||||
|
||||
/** @} */
|
||||
433
components/libraries/bootloader/dfu/nrf_dfu_settings.c
Normal file
433
components/libraries/bootloader/dfu/nrf_dfu_settings.c
Normal file
@@ -0,0 +1,433 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 <stddef.h>
|
||||
#include <string.h>
|
||||
#include "nrf_dfu_flash.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "crc32.h"
|
||||
#include "nrf_nvmc.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
|
||||
#define DFU_SETTINGS_VERSION_OFFSET (offsetof(nrf_dfu_settings_t, settings_version)) //<! Offset in the settings struct where the settings version is located.
|
||||
#define DFU_SETTINGS_INIT_COMMAND_OFFSET (offsetof(nrf_dfu_settings_t, init_command)) //<! Offset in the settings struct where the InitCommand is located.
|
||||
#define DFU_SETTINGS_BOOT_VALIDATION_OFFSET (offsetof(nrf_dfu_settings_t, boot_validation_crc)) //<! Offset in the settings struct where the boot validation info is located.
|
||||
#define DFU_SETTINGS_BOOT_VALIDATION_SIZE ((3 * sizeof(boot_validation_t)) + 4)
|
||||
#define DFU_SETTINGS_BOND_DATA_OFFSET_V1 (offsetof(nrf_dfu_settings_t, init_command) + INIT_COMMAND_MAX_SIZE_v1) //<! Offset in the settings struct where the bond data was located in settings version 1.
|
||||
#define DFU_SETTINGS_ADV_NAME_OFFSET_V1 (offsetof(nrf_dfu_settings_t, init_command) + INIT_COMMAND_MAX_SIZE_v1 + NRF_DFU_PEER_DATA_LEN) //<! Offset in the settings struct where the bond data was located in settings version 1.
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_settings
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
/**@brief This variable reserves a page in flash for bootloader settings
|
||||
* to ensure the linker doesn't place any code or variables at this location.
|
||||
*/
|
||||
#if defined (__CC_ARM )
|
||||
|
||||
uint8_t m_dfu_settings_buffer[BOOTLOADER_SETTINGS_PAGE_SIZE]
|
||||
__attribute__((at(BOOTLOADER_SETTINGS_ADDRESS)))
|
||||
__attribute__((used));
|
||||
|
||||
#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
|
||||
|
||||
uint8_t m_dfu_settings_buffer[BOOTLOADER_SETTINGS_PAGE_SIZE]
|
||||
__attribute__((section(".bootloader_settings_page")))
|
||||
__attribute__((used));
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
|
||||
__no_init __root uint8_t m_dfu_settings_buffer[BOOTLOADER_SETTINGS_PAGE_SIZE]
|
||||
@ BOOTLOADER_SETTINGS_ADDRESS;
|
||||
|
||||
#else
|
||||
|
||||
#error Not a valid compiler/linker for m_dfu_settings placement.
|
||||
|
||||
#endif // Compiler specific
|
||||
|
||||
#if defined(NRF52_SERIES)
|
||||
|
||||
/**@brief This variable reserves a page in flash for MBR parameters
|
||||
* to ensure the linker doesn't place any code or variables at this location.
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
|
||||
uint8_t m_mbr_params_page[NRF_MBR_PARAMS_PAGE_SIZE]
|
||||
__attribute__((at(NRF_MBR_PARAMS_PAGE_ADDRESS)))
|
||||
__attribute__((used));
|
||||
|
||||
#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
|
||||
|
||||
uint8_t m_mbr_params_page[NRF_MBR_PARAMS_PAGE_SIZE]
|
||||
__attribute__((section(".mbr_params_page")))
|
||||
__attribute__((used));
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
|
||||
__no_init uint8_t m_mbr_params_page[NRF_MBR_PARAMS_PAGE_SIZE]
|
||||
@ NRF_MBR_PARAMS_PAGE_ADDRESS;
|
||||
|
||||
#else
|
||||
|
||||
#error Not a valid compiler/linker for m_mbr_params_page placement.
|
||||
|
||||
#endif // Compiler specific
|
||||
|
||||
uint8_t * mp_dfu_settings_backup_buffer = &m_mbr_params_page[0];
|
||||
|
||||
|
||||
#ifndef NRF_DFU_IN_APP
|
||||
#define NRF_DFU_IN_APP 0
|
||||
#endif
|
||||
|
||||
|
||||
#define UICR_PARAM_PAGE_ADDR 0x10001018
|
||||
|
||||
#if !defined(BL_SETTINGS_ACCESS_ONLY) && !NRF_DFU_IN_APP
|
||||
/**@brief This variable has the linker write the MBR parameters page address to the
|
||||
* UICR register. This value will be written in the HEX file and thus to the
|
||||
* UICR when the bootloader is flashed into the chip.
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
|
||||
uint32_t const m_uicr_mbr_params_page_address
|
||||
__attribute__((at(UICR_PARAM_PAGE_ADDR))) = NRF_MBR_PARAMS_PAGE_ADDRESS;
|
||||
|
||||
#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
|
||||
|
||||
uint32_t const m_uicr_mbr_params_page_address
|
||||
__attribute__ ((section(".uicr_mbr_params_page")))
|
||||
__attribute__ ((used)) = NRF_MBR_PARAMS_PAGE_ADDRESS;
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
|
||||
__root uint32_t const m_uicr_mbr_params_page_address
|
||||
@ UICR_PARAM_PAGE_ADDR = NRF_MBR_PARAMS_PAGE_ADDRESS;
|
||||
|
||||
#else
|
||||
|
||||
#error Not a valid compiler/linker for m_mbr_params_page placement.
|
||||
|
||||
#endif // Compiler specific
|
||||
#endif // #ifndef BL_SETTINGS_ACCESS_ONLY
|
||||
#endif // #if defined( NRF52_SERIES )
|
||||
|
||||
nrf_dfu_settings_t s_dfu_settings;
|
||||
|
||||
static uint32_t settings_crc_get(nrf_dfu_settings_t const * p_settings)
|
||||
{
|
||||
ASSERT(offsetof(nrf_dfu_settings_t, crc) == 0);
|
||||
|
||||
// The crc is calculated from the s_dfu_settings struct, except the crc itself, the init command, bond data, and boot validation.
|
||||
return crc32_compute((uint8_t*)(p_settings) + 4, DFU_SETTINGS_INIT_COMMAND_OFFSET - 4, NULL);
|
||||
}
|
||||
|
||||
|
||||
static bool crc_ok(nrf_dfu_settings_t const * p_settings)
|
||||
{
|
||||
if (p_settings->crc != 0xFFFFFFFF)
|
||||
{
|
||||
// CRC is set. Content must be valid
|
||||
uint32_t crc = settings_crc_get(p_settings);
|
||||
if (crc == p_settings->crc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t boot_validation_crc(nrf_dfu_settings_t const * p_settings)
|
||||
{
|
||||
return crc32_compute((const uint8_t *)&p_settings->boot_validation_softdevice,
|
||||
DFU_SETTINGS_BOOT_VALIDATION_SIZE - 4,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static bool boot_validation_crc_ok(nrf_dfu_settings_t const * p_settings)
|
||||
{
|
||||
return (boot_validation_crc(p_settings) == p_settings->boot_validation_crc);
|
||||
}
|
||||
|
||||
|
||||
static bool settings_crc_ok(void)
|
||||
{
|
||||
nrf_dfu_settings_t const * p_settings = (nrf_dfu_settings_t const *)m_dfu_settings_buffer;
|
||||
return crc_ok(p_settings);
|
||||
}
|
||||
|
||||
|
||||
static bool settings_backup_crc_ok(void)
|
||||
{
|
||||
nrf_dfu_settings_t const * p_settings = (nrf_dfu_settings_t const *)mp_dfu_settings_backup_buffer;
|
||||
return crc_ok(p_settings) && ((p_settings->settings_version == 1) || boot_validation_crc_ok(p_settings));
|
||||
}
|
||||
|
||||
#define REGION_COPY_BY_MEMBER(start_member, end_member, p_dst_addr) \
|
||||
memcpy(p_dst_addr + offsetof(nrf_dfu_settings_t, start_member), \
|
||||
mp_dfu_settings_backup_buffer + offsetof(nrf_dfu_settings_t, start_member), \
|
||||
offsetof(nrf_dfu_settings_t, end_member) - offsetof(nrf_dfu_settings_t, start_member))
|
||||
|
||||
|
||||
static void settings_forbidden_parts_copy_from_backup(uint8_t * p_dst_addr)
|
||||
{
|
||||
#if NRF_DFU_IN_APP || NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
|
||||
REGION_COPY_BY_MEMBER(settings_version, bank_current, p_dst_addr);
|
||||
REGION_COPY_BY_MEMBER(bank_0, write_offset, p_dst_addr);
|
||||
REGION_COPY_BY_MEMBER(sd_size, progress, p_dst_addr);
|
||||
REGION_COPY_BY_MEMBER(boot_validation_crc, peer_data, p_dst_addr);
|
||||
#else
|
||||
REGION_COPY_BY_MEMBER(settings_version, enter_buttonless_dfu, p_dst_addr);
|
||||
REGION_COPY_BY_MEMBER(init_command, peer_data, p_dst_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void nrf_dfu_settings_reinit(void)
|
||||
{
|
||||
bool settings_valid = settings_crc_ok();
|
||||
bool settings_backup_valid = settings_backup_crc_ok();
|
||||
|
||||
if (settings_valid)
|
||||
{
|
||||
NRF_LOG_DEBUG("Using settings page.");
|
||||
memcpy(&s_dfu_settings, m_dfu_settings_buffer, sizeof(nrf_dfu_settings_t));
|
||||
if (settings_backup_valid)
|
||||
{
|
||||
NRF_LOG_DEBUG("Copying forbidden parts from backup page.");
|
||||
settings_forbidden_parts_copy_from_backup((uint8_t *)&s_dfu_settings);
|
||||
}
|
||||
}
|
||||
else if (settings_backup_valid)
|
||||
{
|
||||
NRF_LOG_INFO("Restoring settings from backup since the settings page contents are "
|
||||
"invalid (CRC error).");
|
||||
memcpy(&s_dfu_settings,
|
||||
mp_dfu_settings_backup_buffer,
|
||||
sizeof(nrf_dfu_settings_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_WARNING("Resetting bootloader settings since neither the settings page nor the "
|
||||
"backup are valid (CRC error).");
|
||||
memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t));
|
||||
s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION;
|
||||
}
|
||||
|
||||
if (NRF_DFU_SETTINGS_COMPATIBILITY_MODE && !NRF_DFU_IN_APP && (s_dfu_settings.settings_version == 1))
|
||||
{
|
||||
NRF_LOG_INFO("Old settings page detected. Upgrading info.");
|
||||
|
||||
// Old version. Translate.
|
||||
memcpy(&s_dfu_settings.peer_data, (uint8_t *)&s_dfu_settings + DFU_SETTINGS_BOND_DATA_OFFSET_V1, NRF_DFU_PEER_DATA_LEN);
|
||||
memcpy(&s_dfu_settings.adv_name, (uint8_t *)&s_dfu_settings + DFU_SETTINGS_ADV_NAME_OFFSET_V1, NRF_DFU_ADV_NAME_LEN);
|
||||
|
||||
// Initialize with defaults.
|
||||
s_dfu_settings.boot_validation_softdevice.type = NO_VALIDATION;
|
||||
s_dfu_settings.boot_validation_app.type = VALIDATE_CRC;
|
||||
s_dfu_settings.boot_validation_bootloader.type = NO_VALIDATION;
|
||||
memcpy(s_dfu_settings.boot_validation_app.bytes, &s_dfu_settings.bank_0.image_crc, sizeof(uint32_t));
|
||||
|
||||
s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized)
|
||||
{
|
||||
NRF_LOG_DEBUG("Calling nrf_dfu_settings_init()...");
|
||||
|
||||
ret_code_t err_code = nrf_dfu_flash_init(sd_irq_initialized);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("nrf_dfu_flash_init() failed with error: %x", err_code);
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
nrf_dfu_settings_reinit();
|
||||
|
||||
err_code = nrf_dfu_settings_write_and_backup(NULL);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("nrf_dfu_settings_write_and_backup() failed with error: %x", err_code);
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static bool settings_forbidden_parts_equal_to_backup(uint8_t * p_compare_addr)
|
||||
{
|
||||
nrf_dfu_settings_t temp_settings;
|
||||
memcpy(&temp_settings, p_compare_addr, sizeof(nrf_dfu_settings_t));
|
||||
settings_forbidden_parts_copy_from_backup((uint8_t *)&temp_settings);
|
||||
return memcmp(&temp_settings, p_compare_addr, sizeof(nrf_dfu_settings_t)) == 0;
|
||||
}
|
||||
|
||||
|
||||
static ret_code_t settings_write(void * p_dst,
|
||||
void const * p_src,
|
||||
nrf_dfu_flash_callback_t callback,
|
||||
nrf_dfu_settings_t * p_dfu_settings_buffer)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
|
||||
if (memcmp(p_dst, p_src, sizeof(nrf_dfu_settings_t)) == 0)
|
||||
{
|
||||
NRF_LOG_DEBUG("Destination settings are identical to source, write not needed. Skipping.");
|
||||
if (callback != NULL)
|
||||
{
|
||||
callback(NULL);
|
||||
}
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
if (NRF_DFU_IN_APP && !settings_forbidden_parts_equal_to_backup((uint8_t *)&s_dfu_settings))
|
||||
{
|
||||
NRF_LOG_WARNING("Settings write aborted since it tries writing to forbidden settings.");
|
||||
return NRF_ERROR_FORBIDDEN;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Writing settings...");
|
||||
NRF_LOG_DEBUG("Erasing old settings at: 0x%08x", p_dst);
|
||||
|
||||
// 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)p_dst, 1, NULL);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not erase the settings page!");
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
ASSERT(p_dfu_settings_buffer != NULL);
|
||||
memcpy(p_dfu_settings_buffer, p_src, sizeof(nrf_dfu_settings_t));
|
||||
|
||||
err_code = nrf_dfu_flash_store((uint32_t)p_dst,
|
||||
p_dfu_settings_buffer,
|
||||
sizeof(nrf_dfu_settings_t),
|
||||
callback);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not write the DFU settings page!");
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_settings_write(nrf_dfu_flash_callback_t callback)
|
||||
{
|
||||
static nrf_dfu_settings_t dfu_settings_buffer;
|
||||
s_dfu_settings.crc = settings_crc_get(&s_dfu_settings);
|
||||
s_dfu_settings.boot_validation_crc = boot_validation_crc(&s_dfu_settings);
|
||||
return settings_write(m_dfu_settings_buffer,
|
||||
&s_dfu_settings,
|
||||
callback,
|
||||
&dfu_settings_buffer);
|
||||
}
|
||||
|
||||
|
||||
void settings_backup(nrf_dfu_flash_callback_t callback, void * p_src)
|
||||
{
|
||||
#if NRF_DFU_IN_APP
|
||||
NRF_LOG_INFO("Settings backup not available from app.");
|
||||
#else
|
||||
static nrf_dfu_settings_t dfu_settings_buffer;
|
||||
NRF_LOG_INFO("Backing up settings page to address 0x%x.", mp_dfu_settings_backup_buffer);
|
||||
ASSERT(crc_ok(p_src));
|
||||
ret_code_t err_code = settings_write(mp_dfu_settings_backup_buffer,
|
||||
p_src,
|
||||
callback,
|
||||
&dfu_settings_buffer);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not perform backup of bootloader settings! Error: 0x%x", err_code);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void nrf_dfu_settings_backup(nrf_dfu_flash_callback_t callback)
|
||||
{
|
||||
settings_backup(callback, m_dfu_settings_buffer);
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_settings_write_and_backup(nrf_dfu_flash_callback_t callback)
|
||||
{
|
||||
#if NRF_DFU_IN_APP
|
||||
ret_code_t err_code = nrf_dfu_settings_write(callback);
|
||||
#else
|
||||
ret_code_t err_code = nrf_dfu_settings_write(NULL);
|
||||
if (err_code == NRF_SUCCESS)
|
||||
{
|
||||
settings_backup(callback, &s_dfu_settings);
|
||||
}
|
||||
#endif
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
__WEAK ret_code_t nrf_dfu_settings_additional_erase(void)
|
||||
{
|
||||
NRF_LOG_WARNING("No additional data erased");
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void nrf_dfu_settings_progress_reset(void)
|
||||
{
|
||||
memset(s_dfu_settings.init_command, 0xFF, INIT_COMMAND_MAX_SIZE); // Remove the last init command
|
||||
memset(&s_dfu_settings.progress, 0, sizeof(dfu_progress_t));
|
||||
s_dfu_settings.write_offset = 0;
|
||||
}
|
||||
212
components/libraries/bootloader/dfu/nrf_dfu_settings.h
Normal file
212
components/libraries/bootloader/dfu/nrf_dfu_settings.h
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 nrf_dfu
|
||||
*/
|
||||
|
||||
#ifndef NRF_DFU_SETTINGS_H__
|
||||
#define NRF_DFU_SETTINGS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "nrf_dfu_flash.h"
|
||||
#include "sdk_config.h"
|
||||
#include "sdk_errors.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**@brief Global 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(nrf_dfu_flash_callback_t callback);
|
||||
|
||||
|
||||
/**@brief Function for backing up the settings.
|
||||
*
|
||||
* This function copies the contents of the settings page (in flash) to a separate page (in flash).
|
||||
* During @ref nrf_dfu_settings_init, the backup is restored if the original is invalid.
|
||||
*
|
||||
* @param[in] callback Pointer to a function that is called after completing the write operation.
|
||||
*/
|
||||
void nrf_dfu_settings_backup(nrf_dfu_flash_callback_t callback);
|
||||
|
||||
|
||||
/**@brief Function for writing DFU settings to flash and to backup.
|
||||
*
|
||||
* This function first calls @ref nrf_dfu_settings_write and then @ref nrf_dfu_settings_backup.
|
||||
*
|
||||
* @param[in] callback Pointer to a function that is called after completing the write and backup operation.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the write process was successfully initiated.
|
||||
* @retval NRF_ERROR_INTERNAL If a flash error occurred during the first write.
|
||||
*/
|
||||
ret_code_t nrf_dfu_settings_write_and_backup(nrf_dfu_flash_callback_t callback);
|
||||
|
||||
|
||||
/**@brief Function for initializing the DFU settings structure.
|
||||
*
|
||||
* Initializes the RAM structure from the flash contents.
|
||||
* This function is called as part of @ref nrf_dfu_settings_init.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the initialization was successful.
|
||||
* @retval NRF_ERROR_INTERNAL If a flash error occurred.
|
||||
*/
|
||||
void nrf_dfu_settings_reinit(void);
|
||||
|
||||
|
||||
/**@brief Function for initializing the DFU settings module.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the initialization was successful.
|
||||
* @retval NRF_ERROR_INTERNAL If a flash error occurred.
|
||||
*/
|
||||
ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized);
|
||||
|
||||
|
||||
#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE
|
||||
/** @brief Function for storing peer data received through an SVCI call in DFU settings.
|
||||
*
|
||||
* @note The content of the type can be verified by a CRC value stored inside the struct
|
||||
* If the CRC value is 0xFFFFFFFF, it means that no data is set.
|
||||
*
|
||||
* @note The storage operation is an asynchronous progress. Success will be notified
|
||||
* through system events raised by the SoftDevice.
|
||||
*
|
||||
* @param[in] p_data Peer data to be stored in flash.
|
||||
*
|
||||
* @retval NRF_SUCCESS Asynchronous operation was successfully started.
|
||||
* @retval NRF_ERROR_NULL p_data was NULL.
|
||||
* @retval Any other error code reported by SoftDevice API calls.
|
||||
*/
|
||||
ret_code_t nrf_dfu_settings_peer_data_write(nrf_dfu_peer_data_t * p_data);
|
||||
|
||||
|
||||
/** @brief Function for copying peer data from DFU settings to RAM.
|
||||
*
|
||||
* @param[in,out] p_data Structure to copy peer data to.
|
||||
*
|
||||
* @retval NRF_SUCCESS Peer data was successfully copied.
|
||||
* @retval NRF_ERROR_NULL p_data was NULL.
|
||||
*/
|
||||
ret_code_t nrf_dfu_settings_peer_data_copy(nrf_dfu_peer_data_t * p_data);
|
||||
|
||||
|
||||
/** @brief Function for validating peer data in DFU settings.
|
||||
*
|
||||
* @retval True if peer data is validated by CRC, false if not.
|
||||
*/
|
||||
bool nrf_dfu_settings_peer_data_is_valid(void);
|
||||
|
||||
|
||||
/** @brief Function for storing an advertisement name received through an SVCI call in DFU settings.
|
||||
*
|
||||
* @note The content of the type is verifyable by a CRC-value stored inside the struct.
|
||||
*
|
||||
* @note The storage operation is an asynchronous progress. Success will be notified
|
||||
* through system events raised by the SoftDevice.
|
||||
*
|
||||
* @param[in] p_adv_name Structure holding information about the new advertisement name.
|
||||
*
|
||||
* @retval NRF_SUCCESS Asynchronous operation was successfully started.
|
||||
* @retval NRF_ERROR_NULL p_adv_name was NULL.
|
||||
* @retval Any other error code reported by SoftDevice API calls.
|
||||
*/
|
||||
ret_code_t nrf_dfu_settings_adv_name_write(nrf_dfu_adv_name_t * p_adv_name);
|
||||
|
||||
|
||||
/** @brief Function for copying the advertisement name from DFU settings to RAM.
|
||||
*
|
||||
* @param[in,out] p_adv_name Structure to copy the new advertisement name to.
|
||||
*
|
||||
* @retval NRF_SUCCESS Advertisement name was successfully copied.
|
||||
* @retval NRF_ERROR_NULL p_adv_name was NULL.
|
||||
*/
|
||||
ret_code_t nrf_dfu_settings_adv_name_copy(nrf_dfu_adv_name_t * p_adv_name);
|
||||
|
||||
|
||||
/** @brief Function for validating advertisement data in DFU settings.
|
||||
*
|
||||
* @retval True if advertisement name is validated by CRC, false if not.
|
||||
*/
|
||||
bool nrf_dfu_settings_adv_name_is_valid(void);
|
||||
|
||||
#endif // NRF_DFU_TRANSPORT_BLE
|
||||
|
||||
/** @brief Function for erasing additional data in DFU settings.
|
||||
*
|
||||
* @note Erasing additional data in DFU settings is only possible
|
||||
* if nrf_dfu_flash is initialized to not use SoftDevice calls.
|
||||
*
|
||||
* @retval NRF_SUCCESS Additional data was successfully erased.
|
||||
* @retval Any other error code reported by nrf_dfu_flash
|
||||
*/
|
||||
ret_code_t nrf_dfu_settings_additional_erase(void);
|
||||
|
||||
/** @brief Function for resetting both init command and DFU transfer progress inside settings structure.
|
||||
*
|
||||
* @note This function does not perform flash operation.
|
||||
* In order to save the reset state, please use @ref nrf_dfu_settings_write function.
|
||||
*/
|
||||
void nrf_dfu_settings_progress_reset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_SETTINGS_H__
|
||||
|
||||
/**@} */
|
||||
185
components/libraries/bootloader/dfu/nrf_dfu_settings_svci.c
Normal file
185
components/libraries/bootloader/dfu/nrf_dfu_settings_svci.c
Normal file
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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 <stddef.h>
|
||||
#include <string.h>
|
||||
#include "app_error.h"
|
||||
#include "sdk_macros.h"
|
||||
#include "nrf_dfu_settings.h"
|
||||
#include "nrf_nvmc.h"
|
||||
#include "crc32.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_settings_svci
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
#define DFU_SETTINGS_PEER_DATA_OFFSET offsetof(nrf_dfu_settings_t, peer_data) //<! Offset in the settings struct where the additional peer data is located.
|
||||
#define DFU_SETTINGS_ADV_NAME_OFFSET offsetof(nrf_dfu_settings_t, adv_name) //<! Offset in the settings struct where the additional advertisement name is located.
|
||||
|
||||
extern nrf_dfu_settings_t s_dfu_settings;
|
||||
extern uint8_t m_dfu_settings_buffer[CODE_PAGE_SIZE];
|
||||
|
||||
#if defined(NRF_DFU_BLE_REQUIRES_BONDS) && (NRF_DFU_BLE_REQUIRES_BONDS == 1)
|
||||
|
||||
ret_code_t nrf_dfu_settings_peer_data_write(nrf_dfu_peer_data_t * p_data)
|
||||
{
|
||||
uint32_t ret_val;
|
||||
|
||||
uint32_t * p_peer_data_settings =
|
||||
(uint32_t*) &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET];
|
||||
|
||||
uint32_t crc = (uint32_t)*p_peer_data_settings;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_data);
|
||||
|
||||
if (crc != 0xFFFFFFFF)
|
||||
{
|
||||
// Already written to, must be cleared out
|
||||
// Reset required.
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
// Calculate the CRC for the structure excluding the CRC value itself.
|
||||
p_data->crc = crc32_compute((uint8_t*)p_data + 4, sizeof(nrf_dfu_peer_data_t) - 4, NULL);
|
||||
|
||||
// Using SoftDevice call since this function cannot use static memory.
|
||||
ret_val = sd_flash_write(p_peer_data_settings,
|
||||
(uint32_t*)p_data,
|
||||
sizeof(nrf_dfu_peer_data_t)/4);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_settings_peer_data_copy(nrf_dfu_peer_data_t * p_data)
|
||||
{
|
||||
VERIFY_PARAM_NOT_NULL(p_data);
|
||||
|
||||
memcpy(p_data, &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET], sizeof(nrf_dfu_peer_data_t));
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
bool nrf_dfu_settings_peer_data_is_valid(void)
|
||||
{
|
||||
nrf_dfu_peer_data_t * p_peer_data =
|
||||
(nrf_dfu_peer_data_t*) &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET];
|
||||
|
||||
// Calculate the CRC for the structure excluding the CRC value itself.
|
||||
uint32_t crc = crc32_compute((uint8_t*)p_peer_data + 4, sizeof(nrf_dfu_peer_data_t) - 4, NULL);
|
||||
|
||||
return (p_peer_data->crc == crc);
|
||||
}
|
||||
|
||||
#else // not NRF_DFU_BLE_REQUIRES_BONDS
|
||||
|
||||
ret_code_t nrf_dfu_settings_adv_name_write(nrf_dfu_adv_name_t * p_adv_name)
|
||||
{
|
||||
uint32_t ret_val;
|
||||
|
||||
uint32_t * p_adv_name_settings =
|
||||
(uint32_t*) &m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET];
|
||||
|
||||
uint32_t crc = (uint32_t)*p_adv_name_settings;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_adv_name);
|
||||
|
||||
if (crc != 0xFFFFFFFF)
|
||||
{
|
||||
// Already written to, must be cleared out.
|
||||
// Reset required
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
// Calculate the CRC for the structure excluding the CRC value itself.
|
||||
p_adv_name->crc = crc32_compute((uint8_t *)p_adv_name + 4, sizeof(nrf_dfu_adv_name_t) - 4, NULL);
|
||||
|
||||
// Using SoftDevice call since this function cannot use static memory.
|
||||
ret_val = sd_flash_write(p_adv_name_settings,
|
||||
(uint32_t*) p_adv_name,
|
||||
sizeof(nrf_dfu_adv_name_t)/4);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_dfu_settings_adv_name_copy(nrf_dfu_adv_name_t * p_adv_name)
|
||||
{
|
||||
VERIFY_PARAM_NOT_NULL(p_adv_name);
|
||||
memcpy(p_adv_name, &m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET], sizeof(nrf_dfu_adv_name_t));
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
bool nrf_dfu_settings_adv_name_is_valid(void)
|
||||
{
|
||||
nrf_dfu_adv_name_t * p_adv_name =
|
||||
(nrf_dfu_adv_name_t*)&m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET];
|
||||
|
||||
// Calculate the CRC for the structure excluding the CRC value itself.
|
||||
uint32_t crc = crc32_compute((uint8_t*)p_adv_name + 4, sizeof(nrf_dfu_adv_name_t) - 4, NULL);
|
||||
|
||||
return (p_adv_name->crc == crc);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//lint -save -e(14)
|
||||
ret_code_t nrf_dfu_settings_additional_erase(void)
|
||||
{
|
||||
ret_code_t ret_code = NRF_SUCCESS;
|
||||
|
||||
// Check CRC for both types.
|
||||
if ( (s_dfu_settings.peer_data.crc != 0xFFFFFFFF)
|
||||
|| (s_dfu_settings.adv_name.crc != 0xFFFFFFFF))
|
||||
{
|
||||
NRF_LOG_DEBUG("Erasing settings page additional data.");
|
||||
|
||||
// Erasing and resetting the settings page without the peer data/adv data
|
||||
nrf_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS);
|
||||
nrf_nvmc_write_words(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t const *)&s_dfu_settings, DFU_SETTINGS_PEER_DATA_OFFSET / 4);
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
//lint -restore
|
||||
|
||||
87
components/libraries/bootloader/dfu/nrf_dfu_svci.c
Normal file
87
components/libraries/bootloader/dfu/nrf_dfu_svci.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 <stdbool.h>
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_sdm.h"
|
||||
#include "app_util.h"
|
||||
|
||||
#define APP_START_ADDR CODE_START
|
||||
|
||||
|
||||
uint32_t nrf_dfu_svci_vector_table_set(void)
|
||||
{
|
||||
uint32_t err_code;
|
||||
uint32_t bootloader_addr = BOOTLOADER_ADDRESS;
|
||||
|
||||
if (bootloader_addr != 0xFFFFFFFF)
|
||||
{
|
||||
NRF_LOG_INFO("Setting vector table to bootloader: 0x%08x", bootloader_addr);
|
||||
err_code = sd_softdevice_vector_table_base_set(bootloader_addr);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed running sd_softdevice_vector_table_base_set");
|
||||
return err_code;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
NRF_LOG_ERROR("No bootloader was found");
|
||||
return NRF_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrf_dfu_svci_vector_table_unset(void)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
NRF_LOG_INFO("Setting vector table to main app: 0x%08x", APP_START_ADDR);
|
||||
err_code = sd_softdevice_vector_table_base_set(APP_START_ADDR);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed running sd_softdevice_vector_table_base_set");
|
||||
return err_code;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
212
components/libraries/bootloader/dfu/nrf_dfu_svci_handler.c
Normal file
212
components/libraries/bootloader/dfu/nrf_dfu_svci_handler.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 <string.h>
|
||||
#include "nrf_svci_async_handler.h"
|
||||
#include "app_error.h"
|
||||
#include "nrf_nvmc.h"
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "nrf_dfu_ble_svci_bond_sharing.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_dfu_settings.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
|
||||
#if (NRF_DFU_TRANSPORT_BLE && NRF_DFU_BLE_REQUIRES_BONDS)
|
||||
|
||||
|
||||
NRF_SVCI_ASYNC_HANDLER_CREATE(NRF_DFU_SVCI_SET_PEER_DATA,
|
||||
nrf_dfu_set_peer_data, nrf_dfu_peer_data_t, nrf_dfu_peer_data_state_t);
|
||||
|
||||
|
||||
static uint32_t nrf_dfu_set_peer_data_handler(nrf_dfu_set_peer_data_svci_async_t * p_async)
|
||||
{
|
||||
VERIFY_PARAM_NOT_NULL(p_async);
|
||||
|
||||
p_async->async_func = nrf_dfu_set_peer_data_on_call;
|
||||
p_async->sys_evt_handler = nrf_dfu_set_peer_data_on_sys_evt;
|
||||
p_async->state = DFU_PEER_DATA_STATE_INITIALIZED;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t nrf_dfu_set_peer_data_on_call(nrf_dfu_peer_data_t * p_data,
|
||||
nrf_dfu_peer_data_state_t * p_state)
|
||||
{
|
||||
uint32_t ret_val = NRF_ERROR_BUSY;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_state);
|
||||
|
||||
switch (*p_state)
|
||||
{
|
||||
case DFU_PEER_DATA_STATE_INVALID:
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
|
||||
case DFU_PEER_DATA_STATE_INITIALIZED:
|
||||
ret_val = nrf_dfu_settings_peer_data_write(p_data);
|
||||
if (ret_val == NRF_SUCCESS)
|
||||
{
|
||||
*p_state = DFU_PEER_DATA_STATE_WRITE_REQUESTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case DFU_PEER_DATA_STATE_WRITE_REQUESTED:
|
||||
return NRF_ERROR_BUSY;
|
||||
|
||||
case DFU_PEER_DATA_STATE_WRITE_FINISHED:
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
|
||||
case DFU_PEER_DATA_STATE_WRITE_FAILED:
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t nrf_dfu_set_peer_data_on_sys_evt(uint32_t sys_event, nrf_dfu_peer_data_state_t * p_state)
|
||||
{
|
||||
uint32_t ret_val = NRF_ERROR_INVALID_STATE;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_state);
|
||||
|
||||
if (*p_state == DFU_PEER_DATA_STATE_WRITE_REQUESTED)
|
||||
{
|
||||
switch (sys_event)
|
||||
{
|
||||
case NRF_EVT_FLASH_OPERATION_ERROR:
|
||||
return NRF_ERROR_BUSY;
|
||||
|
||||
case NRF_EVT_FLASH_OPERATION_SUCCESS:
|
||||
ret_val = NRF_SUCCESS;
|
||||
(*p_state) = DFU_PEER_DATA_STATE_WRITE_FINISHED;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Event not intended for us
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
#elif (NRF_DFU_TRANSPORT_BLE && !NRF_DFU_BLE_REQUIRES_BONDS)
|
||||
|
||||
|
||||
NRF_SVCI_ASYNC_HANDLER_CREATE(NRF_DFU_SVCI_SET_ADV_NAME,
|
||||
nrf_dfu_set_adv_name, nrf_dfu_adv_name_t, nrf_dfu_set_adv_name_state_t);
|
||||
|
||||
|
||||
static uint32_t nrf_dfu_set_adv_name_handler(nrf_dfu_set_adv_name_svci_async_t * p_async)
|
||||
{
|
||||
VERIFY_PARAM_NOT_NULL(p_async);
|
||||
|
||||
p_async->async_func = nrf_dfu_set_adv_name_on_call;
|
||||
p_async->sys_evt_handler = nrf_dfu_set_adv_name_on_sys_evt;
|
||||
p_async->state = DFU_ADV_NAME_STATE_INITIALIZED;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t nrf_dfu_set_adv_name_on_call(nrf_dfu_adv_name_t * p_adv_name,
|
||||
nrf_dfu_set_adv_name_state_t * p_state)
|
||||
{
|
||||
uint32_t ret_val = NRF_ERROR_BUSY;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_state);
|
||||
|
||||
switch (*p_state)
|
||||
{
|
||||
case DFU_ADV_NAME_STATE_INVALID:
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
|
||||
case DFU_ADV_NAME_STATE_INITIALIZED:
|
||||
ret_val = nrf_dfu_settings_adv_name_write(p_adv_name);
|
||||
if (ret_val == NRF_SUCCESS)
|
||||
{
|
||||
*p_state = DFU_ADV_NAME_STATE_WRITE_REQUESTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case DFU_ADV_NAME_STATE_WRITE_REQUESTED:
|
||||
return NRF_ERROR_BUSY;
|
||||
|
||||
case DFU_ADV_NAME_STATE_WRITE_FINISHED:
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
|
||||
case DFU_ADV_NAME_STATE_WRITE_FAILED:
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t nrf_dfu_set_adv_name_on_sys_evt(uint32_t sys_event, nrf_dfu_set_adv_name_state_t * p_state)
|
||||
{
|
||||
uint32_t ret_val = NRF_ERROR_INVALID_STATE;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_state);
|
||||
|
||||
if (*p_state == DFU_ADV_NAME_STATE_WRITE_REQUESTED)
|
||||
{
|
||||
switch (sys_event)
|
||||
{
|
||||
case NRF_EVT_FLASH_OPERATION_ERROR:
|
||||
return NRF_ERROR_BUSY;
|
||||
|
||||
case NRF_EVT_FLASH_OPERATION_SUCCESS:
|
||||
ret_val = NRF_SUCCESS;
|
||||
(*p_state) = DFU_ADV_NAME_STATE_WRITE_FINISHED;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Event not intended for us
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
#endif // NRF_DFU_TRANSPORT_BLE && !NRF_DFU_BLE_REQUIRES_BONDS
|
||||
91
components/libraries/bootloader/dfu/nrf_dfu_transport.c
Normal file
91
components/libraries/bootloader/dfu/nrf_dfu_transport.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_ITEM_GET(i) NRF_SECTION_ITEM_GET(dfu_trans, nrf_dfu_transport_t, (i))
|
||||
#define DFU_TRANS_SECTION_ITEM_COUNT NRF_SECTION_ITEM_COUNT(dfu_trans, nrf_dfu_transport_t)
|
||||
|
||||
NRF_SECTION_DEF(dfu_trans, const nrf_dfu_transport_t);
|
||||
|
||||
|
||||
uint32_t nrf_dfu_transports_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
uint32_t const num_transports = DFU_TRANS_SECTION_ITEM_COUNT;
|
||||
uint32_t ret_val = NRF_SUCCESS;
|
||||
|
||||
NRF_LOG_DEBUG("Initializing transports (found: %d)", num_transports);
|
||||
|
||||
for (uint32_t i = 0; i < num_transports; i++)
|
||||
{
|
||||
nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_ITEM_GET(i);
|
||||
ret_val = trans->init_func(observer);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_DEBUG("Failed to initialize transport %d, error %d", i, ret_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrf_dfu_transports_close(nrf_dfu_transport_t const * p_exception)
|
||||
{
|
||||
uint32_t const num_transports = DFU_TRANS_SECTION_ITEM_COUNT;
|
||||
uint32_t ret_val = NRF_SUCCESS;
|
||||
|
||||
NRF_LOG_DEBUG("Shutting down transports (found: %d)", num_transports);
|
||||
|
||||
for (uint32_t i = 0; i < num_transports; i++)
|
||||
{
|
||||
nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_ITEM_GET(i);
|
||||
ret_val = trans->close_func(p_exception);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_DEBUG("Failed to shutdown transport %d, error %d", i, ret_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
134
components/libraries/bootloader/dfu/nrf_dfu_transport.h
Normal file
134
components/libraries/bootloader/dfu/nrf_dfu_transport.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 nrf_dfu
|
||||
* @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 "nrf_section.h"
|
||||
#include "nrf_dfu_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Forward declaration of nrf_dfu_transport_t */
|
||||
typedef struct nrf_dfu_transport_s nrf_dfu_transport_t;
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @param observer Callback function for receiving DFU transport notifications.
|
||||
*
|
||||
* @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)(nrf_dfu_observer_t observer);
|
||||
|
||||
|
||||
/** @brief Function type for closing down a DFU transport.
|
||||
*
|
||||
* @details This function closes down a DFU transport in a gentle way.
|
||||
*
|
||||
* @param[in] p_exception If exception matches current transport closing should be omitted.
|
||||
*
|
||||
* @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_close_fn_t)(nrf_dfu_transport_t const * p_exception);
|
||||
|
||||
|
||||
|
||||
/** @brief DFU transport registration.
|
||||
*
|
||||
* @details Every DFU transport must provide a registration of the initialization function.
|
||||
*/
|
||||
struct nrf_dfu_transport_s
|
||||
{
|
||||
nrf_dfu_init_fn_t init_func; /**< Registration of the init function to run to initialize a DFU transport. */
|
||||
nrf_dfu_close_fn_t close_func; /**< Registration of the close function to close down a DFU transport. */
|
||||
};
|
||||
|
||||
|
||||
/** @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(nrf_dfu_observer_t observer);
|
||||
|
||||
/** @brief Function for closing down all (with optional exception) the registered DFU transports.
|
||||
*
|
||||
* @param[in] p_exception Transport which should not be closed. NULL if all transports should be closed.
|
||||
* @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(nrf_dfu_transport_t const * p_exception);
|
||||
|
||||
|
||||
/** @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_ITEM_REGISTER(dfu_trans, trans_var)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_TRANSPORT_H__
|
||||
|
||||
/** @} */
|
||||
244
components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.c
Normal file
244
components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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_trigger_usb.h"
|
||||
#include "app_usbd.h"
|
||||
#include "app_usbd_nrf_dfu_trigger.h"
|
||||
#include "nrf_drv_clock.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "boards.h"
|
||||
#include "app_util.h"
|
||||
#include "app_usbd_serial_num.h"
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_trigger_usb
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
#ifndef BSP_SELF_PINRESET_PIN
|
||||
#error "This module is intended to be used with boards that have the GP pin shortened with the RESET pin."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable power USB detection.
|
||||
*
|
||||
* Configure if the example supports USB port connection.
|
||||
*/
|
||||
#ifndef USBD_POWER_DETECTION
|
||||
#define USBD_POWER_DETECTION true
|
||||
#endif
|
||||
|
||||
#define DFU_FLASH_PAGE_SIZE (NRF_FICR->CODEPAGESIZE)
|
||||
#define DFU_FLASH_PAGE_COUNT (NRF_FICR->CODESIZE)
|
||||
|
||||
// Semantic versioning string.
|
||||
#define VERSION_STRING STRINGIFY(APP_VERSION_MAJOR) "." STRINGIFY(APP_VERSION_MINOR) "." STRINGIFY(APP_VERSION_PATCH) APP_VERSION_PRERELEASE APP_VERSION_METADATA
|
||||
|
||||
static uint8_t m_version_string[] = APP_NAME " " VERSION_STRING; ///< Human-readable version string.
|
||||
static app_usbd_nrf_dfu_trigger_nordic_info_t m_dfu_info; ///< Struct with various information about the current firmware.
|
||||
|
||||
static void dfu_trigger_evt_handler(app_usbd_class_inst_t const * p_inst,
|
||||
app_usbd_nrf_dfu_trigger_user_event_t event)
|
||||
{
|
||||
UNUSED_PARAMETER(p_inst);
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case APP_USBD_NRF_DFU_TRIGGER_USER_EVT_DETACH:
|
||||
NRF_LOG_INFO("DFU Detach request received. Triggering a pin reset.");
|
||||
NRF_LOG_FINAL_FLUSH();
|
||||
nrf_gpio_cfg_output(BSP_SELF_PINRESET_PIN);
|
||||
nrf_gpio_pin_clear(BSP_SELF_PINRESET_PIN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
APP_USBD_NRF_DFU_TRIGGER_GLOBAL_DEF(m_app_dfu,
|
||||
NRF_DFU_TRIGGER_USB_INTERFACE_NUM,
|
||||
&m_dfu_info,
|
||||
m_version_string,
|
||||
dfu_trigger_evt_handler);
|
||||
|
||||
|
||||
static void usbd_user_evt_handler(app_usbd_event_type_t event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case APP_USBD_EVT_DRV_SUSPEND:
|
||||
break;
|
||||
case APP_USBD_EVT_DRV_RESUME:
|
||||
break;
|
||||
case APP_USBD_EVT_STARTED:
|
||||
break;
|
||||
case APP_USBD_EVT_STOPPED:
|
||||
app_usbd_disable();
|
||||
break;
|
||||
case APP_USBD_EVT_POWER_DETECTED:
|
||||
NRF_LOG_INFO("USB power detected");
|
||||
|
||||
if (!nrf_drv_usbd_is_enabled())
|
||||
{
|
||||
app_usbd_enable();
|
||||
}
|
||||
break;
|
||||
case APP_USBD_EVT_POWER_REMOVED:
|
||||
NRF_LOG_INFO("USB power removed");
|
||||
app_usbd_stop();
|
||||
break;
|
||||
case APP_USBD_EVT_POWER_READY:
|
||||
NRF_LOG_INFO("USB ready");
|
||||
app_usbd_start();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void strings_create(void)
|
||||
{
|
||||
uint8_t prev_char = 'a'; // Arbitrary valid char, not '-'.
|
||||
|
||||
// Remove characters that are not supported in semantic version strings.
|
||||
for (size_t i = strlen(APP_NAME) + 1; i < strlen((char*)m_version_string); i++)
|
||||
{
|
||||
if (((m_version_string[i] >= 'a') && (m_version_string[i] <= 'z'))
|
||||
|| ((m_version_string[i] >= 'A') && (m_version_string[i] <= 'Z'))
|
||||
|| ((m_version_string[i] >= '0') && (m_version_string[i] <= '9'))
|
||||
|| (m_version_string[i] == '+')
|
||||
|| (m_version_string[i] == '.')
|
||||
|| (m_version_string[i] == '-'))
|
||||
{
|
||||
// Valid semantic version character.
|
||||
}
|
||||
else if (prev_char == '-')
|
||||
{
|
||||
m_version_string[i] = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
m_version_string[i] = '-';
|
||||
}
|
||||
|
||||
prev_char = m_version_string[i];
|
||||
}
|
||||
|
||||
#if !NRF_DFU_TRIGGER_USB_USB_SHARED
|
||||
app_usbd_serial_num_generate();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)
|
||||
static void usbd_evt_handler(app_usbd_internal_evt_t const * const p_event)
|
||||
{
|
||||
app_usbd_event_execute(p_event);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret_code_t nrf_dfu_trigger_usb_init(void)
|
||||
{
|
||||
ret_code_t ret;
|
||||
static bool initialized = false;
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
m_dfu_info.wAddress = CODE_START;
|
||||
m_dfu_info.wFirmwareSize = CODE_SIZE;
|
||||
m_dfu_info.wVersionMajor = APP_VERSION_MAJOR;
|
||||
m_dfu_info.wVersionMinor = APP_VERSION_MINOR;
|
||||
m_dfu_info.wFirmwareID = APP_ID;
|
||||
m_dfu_info.wFlashPageSize = DFU_FLASH_PAGE_SIZE;
|
||||
m_dfu_info.wFlashSize = m_dfu_info.wFlashPageSize * DFU_FLASH_PAGE_COUNT;
|
||||
|
||||
strings_create();
|
||||
|
||||
if (!NRF_DFU_TRIGGER_USB_USB_SHARED)
|
||||
{
|
||||
static const app_usbd_config_t usbd_config = {
|
||||
|
||||
#if !(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)
|
||||
.ev_handler = usbd_evt_handler,
|
||||
#endif
|
||||
.ev_state_proc = usbd_user_evt_handler
|
||||
};
|
||||
|
||||
ret = nrf_drv_clock_init();
|
||||
if ((ret != NRF_SUCCESS) && (ret != NRF_ERROR_MODULE_ALREADY_INITIALIZED))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = app_usbd_init(&usbd_config);
|
||||
if (ret != NRF_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
app_usbd_class_inst_t const * class_dfu = app_usbd_nrf_dfu_trigger_class_inst_get(&m_app_dfu);
|
||||
ret = app_usbd_class_append(class_dfu);
|
||||
|
||||
if (!NRF_DFU_TRIGGER_USB_USB_SHARED)
|
||||
{
|
||||
if (USBD_POWER_DETECTION)
|
||||
{
|
||||
ret = app_usbd_power_events_enable();
|
||||
APP_ERROR_CHECK(ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now");
|
||||
|
||||
app_usbd_enable();
|
||||
app_usbd_start();
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == NRF_SUCCESS)
|
||||
{
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
74
components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.h
Normal file
74
components/libraries/bootloader/dfu/nrf_dfu_trigger_usb.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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.
|
||||
*
|
||||
*/
|
||||
#ifndef NRF_DFU_TRIGGER_USB_H
|
||||
#define NRF_DFU_TRIGGER_USB_H
|
||||
|
||||
#include "sdk_errors.h"
|
||||
|
||||
/**
|
||||
* @defgroup nrf_dfu_trigger_usb USB DFU trigger library
|
||||
* @ingroup app_common
|
||||
*
|
||||
* @brief @tagAPI52840 USB DFU trigger library is used to enter the bootloader and read the firmware version.
|
||||
*
|
||||
* @details See @ref lib_dfu_trigger_usb for additional documentation.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the USB DFU trigger library.
|
||||
*
|
||||
* @note If the USB is also used for other purposes, then this function must be called after USB is
|
||||
* initialized but before it is enabled. In this case, the configuration flag @ref
|
||||
* NRF_DFU_TRIGGER_USB_USB_SHARED must be set to 1.
|
||||
*
|
||||
* @note Calling this again after the first success has no effect and returns @ref NRF_SUCCESS.
|
||||
*
|
||||
* @note If @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE is on (1), USB events must be handled manually.
|
||||
* See @ref app_usbd_event_queue_process.
|
||||
*
|
||||
* @retval NRF_SUCCESS On successful initialization.
|
||||
* @return An error code on failure, for example if called at a wrong time.
|
||||
*/
|
||||
ret_code_t nrf_dfu_trigger_usb_init(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif //NRF_DFU_TRIGGER_USB_H
|
||||
342
components/libraries/bootloader/dfu/nrf_dfu_types.h
Normal file
342
components/libraries/bootloader/dfu/nrf_dfu_types.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 nrf_dfu
|
||||
*/
|
||||
|
||||
#ifndef NRF_DFU_TYPES_H__
|
||||
#define NRF_DFU_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "sdk_common.h"
|
||||
#include "nrf.h"
|
||||
#include "nrf_mbr.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE
|
||||
#include "ble_gap.h"
|
||||
#define SYSTEM_SERVICE_ATT_SIZE 8 /**< Size of the system service attribute length including CRC-16 at the end. */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define INIT_COMMAND_MAX_SIZE 512 /**< Maximum size of the init command stored in dfu_settings. */
|
||||
#define INIT_COMMAND_MAX_SIZE_v1 256 /**< Maximum size of the init command in settings version 1. */
|
||||
|
||||
/** @brief Size of a flash page. This value is used for calculating the size of the reserved
|
||||
* flash space in the bootloader region.
|
||||
*/
|
||||
#if defined(NRF51)
|
||||
#define CODE_PAGE_SIZE (PAGE_SIZE_IN_WORDS * sizeof(uint32_t))
|
||||
#elif defined(NRF52_SERIES)
|
||||
#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.*/
|
||||
#if defined(NRF51)
|
||||
#define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE * 4)
|
||||
#elif defined(NRF52_SERIES) || defined (__SDK_DOXYGEN__)
|
||||
#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( NRF52810_XXAA )
|
||||
#define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL)
|
||||
#elif defined( NRF52811_XXAA )
|
||||
#define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL)
|
||||
#elif defined( NRF52820_XXAA )
|
||||
#define BOOTLOADER_SETTINGS_ADDRESS (0x0003F000UL)
|
||||
#elif defined( NRF52832_XXAA )
|
||||
#define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL)
|
||||
#elif defined( NRF52833_XXAA )
|
||||
#define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL)
|
||||
#elif defined(NRF52840_XXAA)
|
||||
#define BOOTLOADER_SETTINGS_ADDRESS (0x000FF000UL)
|
||||
#else
|
||||
#error No valid target set for BOOTLOADER_SETTINGS_ADDRESS.
|
||||
#endif
|
||||
|
||||
#define BOOTLOADER_SETTINGS_PAGE_SIZE (CODE_PAGE_SIZE)
|
||||
#define NRF_MBR_PARAMS_PAGE_SIZE (CODE_PAGE_SIZE)
|
||||
|
||||
/** @brief Page location of the MBR parameters page address.
|
||||
*/
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52840_XXAA_ENGA)
|
||||
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x000FE000UL)
|
||||
#elif defined(NRF52832_XXAA)
|
||||
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL)
|
||||
#elif defined(NRF52833_XXAA)
|
||||
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL)
|
||||
#elif defined(NRF52810_XXAA)
|
||||
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL)
|
||||
#elif defined(NRF52811_XXAA)
|
||||
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL)
|
||||
#elif defined(NRF52820_XXAA)
|
||||
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0003E000UL)
|
||||
#endif
|
||||
|
||||
#define BOOTLOADER_SETTINGS_BACKUP_ADDRESS NRF_MBR_PARAMS_PAGE_ADDRESS
|
||||
|
||||
|
||||
#ifndef NRF_DFU_APP_DATA_AREA_SIZE
|
||||
#define NRF_DFU_APP_DATA_AREA_SIZE (CODE_PAGE_SIZE * 3)
|
||||
#endif
|
||||
|
||||
STATIC_ASSERT((NRF_DFU_APP_DATA_AREA_SIZE % CODE_PAGE_SIZE) == 0, "NRF_DFU_APP_DATA_AREA_SIZE must be a multiple of the flash page size.");
|
||||
|
||||
#define DFU_APP_DATA_RESERVED NRF_DFU_APP_DATA_AREA_SIZE // For backward compatibility with 15.0.0.
|
||||
|
||||
/** @brief Total size of the region between the SoftDevice and the bootloader.
|
||||
*/
|
||||
#define DFU_REGION_END(bootloader_start_addr) ((bootloader_start_addr) - (NRF_DFU_APP_DATA_AREA_SIZE))
|
||||
|
||||
#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
|
||||
#define DFU_REGION_START (nrf_dfu_bank0_start_addr())
|
||||
#else
|
||||
#define DFU_REGION_START (MBR_SIZE)
|
||||
#endif
|
||||
|
||||
#define DFU_REGION_TOTAL_SIZE ((DFU_REGION_END) - (DFU_REGION_START))
|
||||
|
||||
#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. */
|
||||
#define NRF_DFU_BANK_VALID_EXT_APP 0xB1 /**< Valid application designated for a remote node. */
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @note The union inside this struct is cleared when CREATE_OBJECT of command type is executed, and when there is a valid post-validation.
|
||||
* In DFU activation (after reset) the @ref dfu_progress_t::update_start_address will be used in case of a SD/SD+BL update.
|
||||
*/
|
||||
ANON_UNIONS_ENABLE;
|
||||
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.*/
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
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. */
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint32_t update_start_address; /**< Value indicating the start address of the new firmware (before copy). It's always used, but it's most important for an SD/SD+BL update where the SD changes size or if the DFU process had a power loss when updating a SD with changed size. */
|
||||
};
|
||||
};
|
||||
} dfu_progress_t;
|
||||
ANON_UNIONS_DISABLE;
|
||||
|
||||
/** @brief Event types in the bootloader and DFU process. */
|
||||
typedef enum
|
||||
{
|
||||
NRF_DFU_EVT_DFU_INITIALIZED, /**< Starting DFU. */
|
||||
NRF_DFU_EVT_TRANSPORT_ACTIVATED, /**< Transport activated (e.g. BLE connected, USB plugged in). */
|
||||
NRF_DFU_EVT_TRANSPORT_DEACTIVATED, /**< Transport deactivated (e.g. BLE disconnected, USB plugged out). */
|
||||
NRF_DFU_EVT_DFU_STARTED, /**< DFU process started. */
|
||||
NRF_DFU_EVT_OBJECT_RECEIVED, /**< A DFU data object has been received. */
|
||||
NRF_DFU_EVT_DFU_FAILED, /**< DFU process has failed, been interrupted, or hung. */
|
||||
NRF_DFU_EVT_DFU_COMPLETED, /**< DFU process completed. */
|
||||
NRF_DFU_EVT_DFU_ABORTED, /**< DFU process aborted. */
|
||||
} nrf_dfu_evt_type_t;
|
||||
|
||||
/**
|
||||
* @brief Function for notifying DFU state.
|
||||
*/
|
||||
typedef void (*nrf_dfu_observer_t)(nrf_dfu_evt_type_t notification);
|
||||
|
||||
#define NRF_DFU_PEER_DATA_LEN 64 /**< The length in bytes of nrf_dfu_peer_data_t expected by tools manipulating the settings page. Do not change without changing the settings page version. */
|
||||
#define NRF_DFU_ADV_NAME_LEN 28 /**< The length in bytes of nrf_dfu_adv_name_t expected by tools manipulating the settings page. Do not change without changing the settings page version. */
|
||||
|
||||
#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t crc; /**< CRC of the rest of the parameters in this struct. */
|
||||
ble_gap_id_key_t ble_id; /**< BLE GAP identity key of the device that initiated the DFU process. */
|
||||
ble_gap_enc_key_t enc_key; /**< Encryption key structure containing encrypted diversifier and LTK for reestablishing the bond. */
|
||||
uint8_t sys_serv_attr[SYSTEM_SERVICE_ATT_SIZE]; /**< System service attributes for restoring of Service Changed Indication setting in DFU mode. */
|
||||
} nrf_dfu_peer_data_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DFU_PEER_DATA_STATE_INVALID = 0,
|
||||
DFU_PEER_DATA_STATE_INITIALIZED = 1,
|
||||
DFU_PEER_DATA_STATE_WRITE_REQUESTED = 2,
|
||||
DFU_PEER_DATA_STATE_WRITE_FINISHED = 3,
|
||||
DFU_PEER_DATA_STATE_WRITE_FAILED = 4,
|
||||
} nrf_dfu_peer_data_state_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t crc; /**< CRC of the rest of the parameters in this struct. Calculated by the bootloader. */
|
||||
uint8_t name[20]; /**< New advertisement name to set. */
|
||||
uint32_t len; /**< Length of the advertisement name. */
|
||||
} nrf_dfu_adv_name_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DFU_ADV_NAME_STATE_INVALID = 0,
|
||||
DFU_ADV_NAME_STATE_INITIALIZED = 1,
|
||||
DFU_ADV_NAME_STATE_WRITE_REQUESTED = 2,
|
||||
DFU_ADV_NAME_STATE_WRITE_FINISHED = 3,
|
||||
DFU_ADV_NAME_STATE_WRITE_FAILED = 4,
|
||||
} nrf_dfu_set_adv_name_state_t;
|
||||
|
||||
#else
|
||||
typedef struct
|
||||
{
|
||||
uint8_t dummy_data[NRF_DFU_PEER_DATA_LEN];
|
||||
} nrf_dfu_peer_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t dummy_data[NRF_DFU_ADV_NAME_LEN];
|
||||
} nrf_dfu_adv_name_t;
|
||||
#endif // NRF_DFU_TRANSPORT_BLE
|
||||
|
||||
STATIC_ASSERT(sizeof(nrf_dfu_peer_data_t) == NRF_DFU_PEER_DATA_LEN, "nrf_dfu_peer_data_t has unexpected length. This can cause incompatibility with tools.");
|
||||
STATIC_ASSERT(sizeof(nrf_dfu_adv_name_t) == NRF_DFU_ADV_NAME_LEN, "nrf_dfu_adv_name_t has unexpected length. This can cause incompatibility with tools.");
|
||||
|
||||
#define SETTINGS_RESERVED_AREA_SIZE 16 /**< The number of words in the reserved area of the DFU settings. */
|
||||
#define SETTINGS_BOOT_VALIDATION_SIZE 64 /**< The number of bytes reserved for boot_validation value. */
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NO_VALIDATION,
|
||||
VALIDATE_CRC,
|
||||
VALIDATE_SHA256,
|
||||
VALIDATE_ECDSA_P256_SHA256,
|
||||
} boot_validation_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
boot_validation_type_t type;
|
||||
uint8_t bytes[SETTINGS_BOOT_VALIDATION_SIZE];
|
||||
} boot_validation_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 current 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; /**< Size of the SoftDevice. */
|
||||
|
||||
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. */
|
||||
|
||||
uint32_t boot_validation_crc;
|
||||
boot_validation_t boot_validation_softdevice;
|
||||
boot_validation_t boot_validation_app;
|
||||
boot_validation_t boot_validation_bootloader;
|
||||
|
||||
nrf_dfu_peer_data_t peer_data; /**< Not included in calculated CRC. */
|
||||
nrf_dfu_adv_name_t adv_name; /**< Not included in calculated CRC. */
|
||||
} nrf_dfu_settings_t;
|
||||
|
||||
#pragma pack() // revert pack settings
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_TYPES_H__
|
||||
|
||||
/** @} */
|
||||
220
components/libraries/bootloader/dfu/nrf_dfu_utils.c
Normal file
220
components/libraries/bootloader/dfu/nrf_dfu_utils.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 "nrf_dfu_settings.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "crc32.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_dfu_validation.h"
|
||||
|
||||
void nrf_dfu_bank_invalidate(nrf_dfu_bank_t * const 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;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD)
|
||||
void nrf_dfu_softdevice_invalidate(void)
|
||||
{
|
||||
static const uint32_t all_zero = 0UL;
|
||||
|
||||
if (SD_PRESENT && !NRF_DFU_IN_APP)
|
||||
{
|
||||
ret_code_t err_code = nrf_dfu_flash_store(SD_MAGIC_NUMBER_ABS_OFFSET_GET(MBR_SIZE), &all_zero, 4, NULL);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not invalidate SoftDevice.")
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is an app it must be invalidated since its start address can no longer be resolved.
|
||||
if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP)
|
||||
{
|
||||
s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_INVALID;
|
||||
}
|
||||
// Since the start of bank 0 has now implicitly been moved to the start
|
||||
// of the invalidated SoftDevice, its image size must be increased by the
|
||||
// same amount so the start of bank 1 will be correctly calculated.
|
||||
s_dfu_settings.bank_0.image_size += SD_SIZE_GET(MBR_SIZE) - MBR_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t nrf_dfu_bank0_start_addr(void)
|
||||
{
|
||||
if (SD_PRESENT)
|
||||
{
|
||||
return ALIGN_TO_PAGE(SD_SIZE_GET(MBR_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
return MBR_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrf_dfu_bank1_start_addr(void)
|
||||
{
|
||||
uint32_t bank0_addr = nrf_dfu_bank0_start_addr();
|
||||
return ALIGN_TO_PAGE(bank0_addr + s_dfu_settings.bank_0.image_size);
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrf_dfu_app_start_address(void)
|
||||
{
|
||||
return nrf_dfu_bank0_start_addr();
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrf_dfu_softdevice_start_address(void)
|
||||
{
|
||||
return MBR_SIZE;
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrf_dfu_cache_prepare(const uint32_t required_size, bool single_bank, bool keep_app, bool keep_softdevice)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
bool cache_too_small;
|
||||
enum
|
||||
{
|
||||
INITIAL_DELETE_APP = 0,
|
||||
APP_DELETED_DELETE_SOFTDEVICE = 1,
|
||||
SOFTDEVICE_DELETED = 2
|
||||
} pass;
|
||||
|
||||
NRF_LOG_DEBUG("Enter nrf_dfu_cache_prepare()");
|
||||
NRF_LOG_DEBUG("required_size: 0x%x.", required_size);
|
||||
NRF_LOG_DEBUG("single_bank: %s.", single_bank ? "true" : "false");
|
||||
NRF_LOG_DEBUG("keep_app: %s.", keep_app ? "true" : "false");
|
||||
NRF_LOG_DEBUG("keep_softdevice: %s.", keep_softdevice ? "true" : "false");
|
||||
NRF_LOG_DEBUG("SD_PRESENT: %s.", SD_PRESENT ? "true" : "false");
|
||||
NRF_LOG_DEBUG("Bank contents:");
|
||||
NRF_LOG_DEBUG("Bank 0 code: 0x%02x: Size: 0x%x", s_dfu_settings.bank_0.bank_code, s_dfu_settings.bank_0.image_size);
|
||||
NRF_LOG_DEBUG("Bank 1 code: 0x%02x: Size: 0x%x", s_dfu_settings.bank_1.bank_code, s_dfu_settings.bank_1.image_size);
|
||||
|
||||
// Pass 0 deletes the app if necessary or requested, and if so, proceeds to pass 1.
|
||||
// Pass 1 deletes the SoftDevice if necessary or requested, and if so, proceeds to pass 2.
|
||||
// Pass 2 does a last size check.
|
||||
for (pass = INITIAL_DELETE_APP; pass <= SOFTDEVICE_DELETED; pass++)
|
||||
{
|
||||
uint32_t cache_address;
|
||||
const uint32_t bootloader_start_addr = BOOTLOADER_START_ADDR; // Assign to a variable to prevent warning in Keil 4.
|
||||
bool keep_firmware = true;
|
||||
bool delete_more;
|
||||
|
||||
switch (pass)
|
||||
{
|
||||
case INITIAL_DELETE_APP:
|
||||
cache_address = nrf_dfu_bank1_start_addr();
|
||||
|
||||
// If there is no app, keep_app should be assumed false, so we can free up more space.
|
||||
keep_firmware = keep_app && (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP);
|
||||
break;
|
||||
|
||||
case APP_DELETED_DELETE_SOFTDEVICE:
|
||||
cache_address = nrf_dfu_bank0_start_addr();
|
||||
|
||||
// If there is no SoftDevice, keep_SoftDevice should be assumed true, because there is
|
||||
// no point to continuing since the SoftDevice is the last firmware that can be deleted.
|
||||
keep_firmware = keep_softdevice || !SD_PRESENT;
|
||||
break;
|
||||
|
||||
case SOFTDEVICE_DELETED:
|
||||
cache_address = nrf_dfu_softdevice_start_address();
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(false);
|
||||
cache_address = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(cache_address <= DFU_REGION_END(bootloader_start_addr));
|
||||
cache_too_small = required_size > (DFU_REGION_END(bootloader_start_addr) - cache_address);
|
||||
delete_more = cache_too_small || single_bank; // Delete app or SoftDevice only if we need more room, or if single bank is requested.
|
||||
|
||||
NRF_LOG_DEBUG("pass: %d.", pass);
|
||||
NRF_LOG_DEBUG("cache_address: 0x%x.", cache_address);
|
||||
NRF_LOG_DEBUG("cache_too_small: %s.", cache_too_small ? "true" : "false");
|
||||
NRF_LOG_DEBUG("keep_firmware: %s.", keep_firmware ? "true" : "false");
|
||||
NRF_LOG_DEBUG("delete_more: %s.", delete_more ? "true" : "false");
|
||||
|
||||
if (!delete_more || keep_firmware || (pass >= SOFTDEVICE_DELETED))
|
||||
{
|
||||
// Stop, done.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cache_too_small)
|
||||
{
|
||||
NRF_LOG_WARNING("Aborting. Cannot fit new firmware on device");
|
||||
err_code = NRF_ERROR_NO_MEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Room was found. Make the necessary preparations for receiving update.
|
||||
|
||||
#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD)
|
||||
if (pass >= SOFTDEVICE_DELETED)
|
||||
{
|
||||
NRF_LOG_DEBUG("Invalidating SoftDevice.");
|
||||
nrf_dfu_softdevice_invalidate();
|
||||
}
|
||||
#endif
|
||||
if (pass >= APP_DELETED_DELETE_SOFTDEVICE)
|
||||
{
|
||||
NRF_LOG_DEBUG("Invalidating app.");
|
||||
nrf_dfu_bank_invalidate(&s_dfu_settings.bank_0);
|
||||
}
|
||||
|
||||
err_code = NRF_SUCCESS;
|
||||
}
|
||||
|
||||
return err_code;
|
||||
}
|
||||
154
components/libraries/bootloader/dfu/nrf_dfu_utils.h
Normal file
154
components/libraries/bootloader/dfu/nrf_dfu_utils.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 nrf_dfu
|
||||
*/
|
||||
|
||||
#ifndef NRF_DFU_UTILS_H__
|
||||
#define NRF_DFU_UTILS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "app_util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Round up val to the next page boundary
|
||||
*/
|
||||
#define ALIGN_TO_PAGE(val) ALIGN_NUM((CODE_PAGE_SIZE), (val))
|
||||
|
||||
|
||||
/** @brief Function for getting the start address of bank 0.
|
||||
*
|
||||
* @note Bank 0 starts after the SoftDevice if a SoftDevice is present.
|
||||
*
|
||||
* @return The start address of bank 0.
|
||||
*/
|
||||
uint32_t nrf_dfu_bank0_start_addr(void);
|
||||
|
||||
|
||||
/** @brief Function for getting the start address of bank 1.
|
||||
*
|
||||
* @return The start address of bank 1.
|
||||
*/
|
||||
uint32_t nrf_dfu_bank1_start_addr(void);
|
||||
|
||||
|
||||
/** @brief Function for getting the start address of the app.
|
||||
*
|
||||
* @return The start address of the bootable app.
|
||||
*/
|
||||
uint32_t nrf_dfu_app_start_address(void);
|
||||
|
||||
|
||||
/** @brief Function for getting the start address of the SoftDevice.
|
||||
*
|
||||
* @return The start address of the SoftDevivce.
|
||||
*/
|
||||
uint32_t nrf_dfu_softdevice_start_address(void);
|
||||
|
||||
|
||||
/** @brief Function for finding and preparing a place in flash in which to store a DFU update.
|
||||
*
|
||||
* @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 after the existing firmwares. If there is not
|
||||
* enough space, the present application is deleted. If there is still not enough space,
|
||||
* the SoftDevice is deleted.
|
||||
* If @p single_bank is true, the default behavior is to immediately delete the app and
|
||||
* SoftDevice as necessary to place the new firmware at its intended location. If the
|
||||
* intended location cannot be made available, or if the update is a bootloader update,
|
||||
* the update will be a dual bank update, and nothing will be deleted by this function
|
||||
* except when needed for size.
|
||||
* If @p keep_app is true, the app is never deleted by this function. Likewise if @p
|
||||
* keep_softdevice is true, the SoftDevice is never deleted by this function.
|
||||
* If the new firmware cannot fit within the constraints, nothing is deleted and the
|
||||
* function fails.
|
||||
*
|
||||
* @param[in] required_size Requirements for the size of the new image.
|
||||
* @param[in] single_bank Whether to put the firmware directly where it's meant to go.
|
||||
* @p keep_app and @p keep_softdevice take precedence over this.
|
||||
* @param[in] keep_app True to ensure the app is not deleted by this function. This
|
||||
* effectively enforces dual bank update.
|
||||
* @param[out] keep_softdevice True to ensure the SoftDevice is not deleted by this function.
|
||||
*
|
||||
* @retval NRF_SUCCESS If a cache location was found for the DFU process.
|
||||
* @retval NRF_ERROR_NO_MEM If there is not enough space available to receive the update.
|
||||
* Nothing has been deleted.
|
||||
*/
|
||||
uint32_t nrf_dfu_cache_prepare(uint32_t required_size, bool single_bank, bool keep_app, bool keep_softdevice);
|
||||
|
||||
|
||||
/**@brief Function for making sure a SoftDevice is not recognized as such anymore.
|
||||
*
|
||||
* @details It works by overwriting the magic number of the SoftDevice with 0s. The
|
||||
* magic number is used throughout the bootloader to detect whether a SoftDevice
|
||||
* is present.
|
||||
*
|
||||
* @warning This function should only be called when both banks are already invalid.
|
||||
* because the (implicit) position of the banks will shift when the SoftDevice
|
||||
* is invalidated.
|
||||
*/
|
||||
void nrf_dfu_softdevice_invalidate(void);
|
||||
|
||||
|
||||
/**@brief Function for making sure a bank is not copied or booted.
|
||||
*
|
||||
* @details This also sets the size of the bank to 0.
|
||||
*
|
||||
* @param[in] p_bank Pointer to the bank to be invalidated.
|
||||
*/
|
||||
void nrf_dfu_bank_invalidate(nrf_dfu_bank_t * const p_bank);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_UTILS_H__
|
||||
|
||||
/** @} */
|
||||
1087
components/libraries/bootloader/dfu/nrf_dfu_validation.c
Normal file
1087
components/libraries/bootloader/dfu/nrf_dfu_validation.c
Normal file
File diff suppressed because it is too large
Load Diff
199
components/libraries/bootloader/dfu/nrf_dfu_validation.h
Normal file
199
components/libraries/bootloader/dfu/nrf_dfu_validation.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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_validation Validation
|
||||
* @{
|
||||
* @ingroup nrf_dfu
|
||||
*/
|
||||
|
||||
#ifndef __NRF_DFU_VALIDATION_H
|
||||
#define __NRF_DFU_VALIDATION_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "sdk_errors.h"
|
||||
#include "dfu-cc.pb.h"
|
||||
#include "nrf_dfu_handling_error.h"
|
||||
|
||||
/**
|
||||
* @brief Function for module initialization.
|
||||
*
|
||||
* Function checks if there is a valid init packet in DFU settings written in flash.
|
||||
*/
|
||||
void nrf_dfu_validation_init(void);
|
||||
|
||||
/**
|
||||
* @brief Function called on reception of init command creation request.
|
||||
*
|
||||
* @param[in] size Size of incoming init packet.
|
||||
*
|
||||
* @return Operation result. See @ref nrf_dfu_result_t
|
||||
*/
|
||||
nrf_dfu_result_t nrf_dfu_validation_init_cmd_create(uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Function called on reception of fragment of init command.
|
||||
*
|
||||
* @param[in] p_data Init command fragment.
|
||||
* @param[in] length Init command fragment size.
|
||||
*
|
||||
* @return Operation result. See @ref nrf_dfu_result_t
|
||||
*/
|
||||
nrf_dfu_result_t nrf_dfu_validation_init_cmd_append(uint8_t const * p_data, uint32_t length);
|
||||
|
||||
/**
|
||||
* @brief Function for getting init command status.
|
||||
*
|
||||
* @param[out] p_offset Current offset.
|
||||
* @param[out] p_crc Current CRC.
|
||||
* @param[out] p_max_size Maximum size of init command.
|
||||
*/
|
||||
void nrf_dfu_validation_init_cmd_status_get(uint32_t * p_offset,
|
||||
uint32_t * p_crc,
|
||||
uint32_t * p_max_size);
|
||||
|
||||
/**
|
||||
* @brief Function for inquiring whether a valid init command has been received.
|
||||
*
|
||||
* @return true if there is a valid init command. This can be true at boot time
|
||||
* if the device was reset during a DFU operation.
|
||||
*/
|
||||
bool nrf_dfu_validation_init_cmd_present(void);
|
||||
|
||||
/**
|
||||
* @brief Function for validating init command and retrieving the address and length of the firmware.
|
||||
*
|
||||
* If init command is successfully validated Bank 1 details are written to out parameters.
|
||||
*
|
||||
* Until @ref nrf_dfu_validation_init_cmd_create is called, this function can be called
|
||||
* again after the first time without side effects to retrieve address and length.
|
||||
*
|
||||
* @param[out] p_dst_data_addr Start address of received data, if validation is successful.
|
||||
* @param[out] p_data_len Expected length of received data, if validation is successful.
|
||||
*
|
||||
* @return Operation result. See @ref nrf_dfu_result_t
|
||||
*/
|
||||
nrf_dfu_result_t nrf_dfu_validation_init_cmd_execute(uint32_t * p_dst_data_addr,
|
||||
uint32_t * p_data_len);
|
||||
|
||||
/**
|
||||
* @brief Function for validating the init command.
|
||||
*
|
||||
* @return Operation result. See @ref nrf_dfu_result_t.
|
||||
*/
|
||||
nrf_dfu_result_t nrf_dfu_validation_prevalidate(void);
|
||||
|
||||
/**
|
||||
* @brief Function for validating the firmware for booting.
|
||||
*
|
||||
* @param[in] p_validation Validation parameters.
|
||||
* @param[in] data_addr Start address of the firmware.
|
||||
* @param[in] data_len Length of the firmware.
|
||||
*
|
||||
* @return Whether the firmware is valid for booting.
|
||||
*/
|
||||
bool nrf_dfu_validation_boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len);
|
||||
|
||||
/**
|
||||
* @brief Function for postvalidating the update after all data is received.
|
||||
*
|
||||
* @param[in] data_addr Start address of the received data.
|
||||
* @param[in] data_len Length of the received data.
|
||||
*
|
||||
* @return Operation result. See @ref nrf_dfu_result_t.
|
||||
*/
|
||||
nrf_dfu_result_t nrf_dfu_validation_post_data_execute(uint32_t data_addr, uint32_t data_len);
|
||||
|
||||
/**
|
||||
* @brief Function for preparing the update for activation.
|
||||
*
|
||||
* This function is called after a reset, after all data is received. This function also runs
|
||||
* @ref nrf_dfu_validation_post_data_execute internally. If this succeeds, the update is
|
||||
* activated by the activation machinery in the bootloader the next time it runs.
|
||||
*
|
||||
* @note The caller must have permissions to edit the relevant entries in the settings.
|
||||
*
|
||||
* @param[in] data_addr Start address of the received data.
|
||||
* @param[in] data_len Length of the received data.
|
||||
*
|
||||
* @return Operation result. See @ref nrf_dfu_result_t
|
||||
*/
|
||||
nrf_dfu_result_t nrf_dfu_validation_activation_prepare(uint32_t data_addr, uint32_t data_len);
|
||||
|
||||
/**
|
||||
* @brief Function to execute on a validated external app.
|
||||
*
|
||||
* @details This function is called once all data is received with the parameter
|
||||
* @p is_boot set to false. The function is called during bootup with the parameter
|
||||
* set to true.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @note This function requires that @ref NRF_DFU_SUPPORTS_EXTERNAL_APP is set to 1.
|
||||
* It is up to the user to implement this function.
|
||||
*
|
||||
* @warning Parameter @p is_trusted must be used to ensure that no loss of security of process can happen.
|
||||
* This parameter should only be set if the function is called after a root-of-trust
|
||||
* reset on the device.
|
||||
*
|
||||
* Parameter @p is_trusted can be used for the following:
|
||||
* - Ensuring that an external application is run only once (after root-of-trust).
|
||||
* - Ensuring that a bank flag or any other flash access can only happen after root-of-trust.
|
||||
* - Ensuring that the device reaches the correct state after a power failure on the device.
|
||||
*
|
||||
* @param[in] p_init Init command for the firmware upgrade.
|
||||
* @param[in] is_trusted Must be set to true if this is called after root-of-trust boot.
|
||||
* Must be set to false if this is called from DFU mode or background
|
||||
* DFU operation.
|
||||
*
|
||||
* @return Operation result. see @ref nrf_dfu_result_t.
|
||||
*/
|
||||
nrf_dfu_result_t nrf_dfu_validation_post_external_app_execute(dfu_init_command_t const * p_init, bool is_trusted);
|
||||
|
||||
/**
|
||||
* @brief Function to check if there is a valid external app in Bank 1.
|
||||
*
|
||||
* @returns True if valid external app, otherwise false.
|
||||
*/
|
||||
bool nrf_dfu_validation_valid_external_app(void);
|
||||
|
||||
#endif //__NRF_DFU_VALIDATION_H
|
||||
|
||||
/** @} */
|
||||
312
components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c
Normal file
312
components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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 <stdbool.h>
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "nrf_dfu_settings.h"
|
||||
#include "nrf_dfu_utils.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "nrf_crypto.h"
|
||||
#include "nrf_assert.h"
|
||||
#include "dfu-cc.pb.h"
|
||||
#include "nrf_dfu_ver_validation.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_ver_validation
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
/** @brief Macro for reading the Firmware ID of a SoftDevice at a given base address.
|
||||
*/
|
||||
#ifndef _SD_FWID_GET
|
||||
#define _SD_FWID_GET(baseaddr) SD_OFFSET_GET_UINT16(baseaddr, 0x0C)
|
||||
#endif
|
||||
|
||||
#define EXT_ERR(err) (nrf_dfu_result_t)((uint32_t)NRF_DFU_RES_CODE_EXT_ERROR + (uint32_t)err)
|
||||
|
||||
static bool sd_req_check(uint32_t const * p_sd_req, uint8_t sd_req_cnt, bool accept_any)
|
||||
{
|
||||
bool result = false;
|
||||
for (uint8_t i = 0; i < sd_req_cnt; i++)
|
||||
{
|
||||
if ((SD_PRESENT && (p_sd_req[i] == _SD_FWID_GET(MBR_SIZE))) ||
|
||||
(accept_any && (p_sd_req[i] == SD_REQ_ANY_VERSION))
|
||||
)
|
||||
{
|
||||
// Found a matching sd_req field. sd_req is ok.
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static bool sd_req_ok(dfu_init_command_t const * p_init)
|
||||
{
|
||||
ASSERT(p_init != NULL);
|
||||
bool result;
|
||||
#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
|
||||
// The bootloader needs the SoftDevice, so disabling NRF_DFU_APP_DOWNGRADE_PREVENTION
|
||||
// should not be applied to SoftDevice updates.
|
||||
const bool prevent_downgrade = NRF_DFU_APP_DOWNGRADE_PREVENTION || (p_init->type == DFU_FW_TYPE_SOFTDEVICE);
|
||||
#else
|
||||
const bool prevent_downgrade = NRF_DFU_APP_DOWNGRADE_PREVENTION;
|
||||
#endif
|
||||
|
||||
if (SD_PRESENT)
|
||||
{
|
||||
if (p_init->sd_req_count == 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else if (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD)
|
||||
{
|
||||
result = sd_req_check(p_init->sd_req,
|
||||
p_init->sd_req_count,
|
||||
(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION));
|
||||
}
|
||||
else if (p_init->type == DFU_FW_TYPE_APPLICATION)
|
||||
{
|
||||
// The application wants to overwrite the SoftDevice.
|
||||
if (prevent_downgrade && (p_init->sd_req_count > 1) && (p_init->sd_req[0] == SD_REQ_APP_OVERWRITES_SD))
|
||||
{
|
||||
// The application can overwrite the SD if sd_req[0] == 0 and table has the FWID of the current SD.
|
||||
result = sd_req_check(p_init->sd_req, p_init->sd_req_count, false);
|
||||
|
||||
// Prevent BLE/ANT bootloaders from allowing applications overwriting the SoftDevice.
|
||||
#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
|
||||
result = false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
#if NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
else if(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)
|
||||
{
|
||||
// Won't accept FW upgrade using external application to
|
||||
// enforce replacing SoftDevice (SD_REQ_APP_OVERWRITES_SD)
|
||||
result = false;
|
||||
}
|
||||
#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
else
|
||||
{
|
||||
// Don't allow SoftDevice updates which assume no SD is present already.
|
||||
result = !prevent_downgrade || (p_init->type != DFU_FW_TYPE_SOFTDEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (p_init->sd_req_count && (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD))
|
||||
{
|
||||
// Fail if there is no SD and the update requires SD. The special "any" FWID is valid
|
||||
// for external apps only.
|
||||
result = false;
|
||||
#if NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
result = sd_req_check(p_init->sd_req,
|
||||
p_init->sd_req_count,
|
||||
(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION));
|
||||
#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is no SD and update has SD it is accepted only if it has a fw_version.
|
||||
result = !prevent_downgrade || p_init->has_fw_version;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static bool fw_hash_type_ok(dfu_init_command_t const * p_init)
|
||||
{
|
||||
ASSERT(p_init != NULL);
|
||||
|
||||
return (p_init->hash.hash_type == DFU_HASH_TYPE_SHA256);
|
||||
}
|
||||
|
||||
|
||||
static bool fw_version_required(dfu_fw_type_t new_fw_type)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (new_fw_type == DFU_FW_TYPE_SOFTDEVICE)
|
||||
{
|
||||
result = false; // fw_version is optional in SoftDevice updates. If present, it will be checked against the app version.
|
||||
}
|
||||
else if (new_fw_type == DFU_FW_TYPE_APPLICATION)
|
||||
{
|
||||
result = NRF_DFU_APP_DOWNGRADE_PREVENTION; // fw_version is configurable in app updates.
|
||||
}
|
||||
#if NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
#if !NRF_DFU_EXTERNAL_APP_VERSIONING
|
||||
else if (new_fw_type == DFU_FW_TYPE_EXTERNAL_APPLICATION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif //!NRF_DFU_EXTERNAL_APP_VERSIONING
|
||||
#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static bool fw_type_ok(dfu_init_command_t const * p_init)
|
||||
{
|
||||
ASSERT(p_init != NULL);
|
||||
|
||||
return ((p_init->has_type)
|
||||
&& ( (p_init->type == DFU_FW_TYPE_APPLICATION)
|
||||
|| (p_init->type == DFU_FW_TYPE_SOFTDEVICE)
|
||||
|| (p_init->type == DFU_FW_TYPE_BOOTLOADER)
|
||||
|| (p_init->type == DFU_FW_TYPE_SOFTDEVICE_BOOTLOADER)
|
||||
#if NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
|| (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)
|
||||
#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifndef NRF_DFU_APP_ACCEPT_SAME_VERSION
|
||||
#define NRF_DFU_APP_ACCEPT_SAME_VERSION 1
|
||||
#endif
|
||||
|
||||
|
||||
// This function assumes p_init->has_fw_version.
|
||||
static bool fw_version_ok(dfu_init_command_t const * p_init)
|
||||
{
|
||||
ASSERT(p_init != NULL);
|
||||
ASSERT(p_init->has_fw_version);
|
||||
|
||||
if ((p_init->type == DFU_FW_TYPE_APPLICATION) ||
|
||||
(p_init->type == DFU_FW_TYPE_SOFTDEVICE))
|
||||
{
|
||||
if (!NRF_DFU_APP_DOWNGRADE_PREVENTION)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if ((p_init->fw_version > s_dfu_settings.app_version))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if ((p_init->fw_version == s_dfu_settings.app_version))
|
||||
{
|
||||
return NRF_DFU_APP_ACCEPT_SAME_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#if NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
#if NRF_DFU_EXTERNAL_APP_VERSIONING
|
||||
else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)
|
||||
{
|
||||
return (p_init->fw_version >= s_dfu_settings.app_version);
|
||||
}
|
||||
#else
|
||||
else if(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif // NRF_DFU_EXTERNAL_APP_VERSIONING
|
||||
#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP
|
||||
else
|
||||
{
|
||||
return (p_init->fw_version > s_dfu_settings.bootloader_version);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_init_command_t const * p_init)
|
||||
{
|
||||
nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS;
|
||||
if (!fw_type_ok(p_init))
|
||||
{
|
||||
NRF_LOG_ERROR("Invalid firmware type.");
|
||||
ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID);
|
||||
}
|
||||
else if (!fw_hash_type_ok(p_init))
|
||||
{
|
||||
NRF_LOG_ERROR("Invalid hash type.");
|
||||
ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_WRONG_HASH_TYPE);
|
||||
}
|
||||
else if (!NRF_DFU_DEBUG ||
|
||||
(NRF_DFU_DEBUG && ((p_init->has_is_debug == false) || (p_init->is_debug == false))))
|
||||
{
|
||||
if (p_init->has_hw_version == false)
|
||||
{
|
||||
NRF_LOG_ERROR("No HW version.");
|
||||
ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID);
|
||||
}
|
||||
else if (p_init->hw_version != NRF_DFU_HW_VERSION)
|
||||
{
|
||||
NRF_LOG_WARNING("Faulty HW version.");
|
||||
ret_val = EXT_ERR( NRF_DFU_EXT_ERROR_HW_VERSION_FAILURE);
|
||||
}
|
||||
|
||||
else if (!sd_req_ok(p_init))
|
||||
{
|
||||
NRF_LOG_WARNING("SD req not met.");
|
||||
ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE);
|
||||
}
|
||||
else if (p_init->has_fw_version)
|
||||
{
|
||||
if (!fw_version_ok(p_init))
|
||||
{
|
||||
NRF_LOG_WARNING("FW version too low.");
|
||||
ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_FW_VERSION_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fw_version_required(p_init->type))
|
||||
{
|
||||
NRF_LOG_ERROR("FW version missing.");
|
||||
ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
64
components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h
Normal file
64
components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __NRF_DFU_VER_VALIDATION_H
|
||||
#define __NRF_DFU_VER_VALIDATION_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "sdk_errors.h"
|
||||
#include "nrf_dfu_handling_error.h"
|
||||
#include "dfu-cc.pb.h"
|
||||
|
||||
/** @brief SD_REQ field value which indicates that Softdevice can be overwritten by the application. */
|
||||
#define SD_REQ_APP_OVERWRITES_SD 0
|
||||
|
||||
/** @brief SD_REQ_ANY_VERSION field value which indicates that any SoftDevice version is valid.
|
||||
*
|
||||
* @note This is used by external application in case SoftDevice version compatibility isn't needed.
|
||||
*/
|
||||
#define SD_REQ_ANY_VERSION (0xFFFE)
|
||||
|
||||
/**
|
||||
* @brief Function for validating version of new firmware.
|
||||
*
|
||||
* @return NRF_DFU_RES_CODE_SUCCESS if successful or error code otherwise
|
||||
*/
|
||||
nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_init_command_t const * p_init);
|
||||
|
||||
#endif //__NRF_DFU_VER_VALIDATION_H
|
||||
528
components/libraries/bootloader/nrf_bootloader.c
Normal file
528
components/libraries/bootloader/nrf_bootloader.c
Normal file
@@ -0,0 +1,528 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 "boards.h"
|
||||
#include "sdk_config.h"
|
||||
#include "nrf_power.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_dfu.h"
|
||||
#include "nrf_error.h"
|
||||
#include "nrf_dfu_settings.h"
|
||||
#include "nrf_dfu_utils.h"
|
||||
#include "nrf_bootloader_wdt.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "nrf_bootloader_app_start.h"
|
||||
#include "nrf_bootloader_fw_activation.h"
|
||||
#include "nrf_bootloader_dfu_timers.h"
|
||||
#include "app_scheduler.h"
|
||||
#include "nrf_dfu_validation.h"
|
||||
|
||||
static nrf_dfu_observer_t m_user_observer; //<! Observer callback set by the user.
|
||||
static volatile bool m_flash_write_done;
|
||||
|
||||
#define SCHED_QUEUE_SIZE 32 /**< Maximum number of events in the scheduler queue. */
|
||||
#define SCHED_EVENT_DATA_SIZE NRF_DFU_SCHED_EVENT_DATA_SIZE /**< Maximum app_scheduler event size. */
|
||||
|
||||
#if !(defined(NRF_BL_DFU_ENTER_METHOD_BUTTON) && \
|
||||
defined(NRF_BL_DFU_ENTER_METHOD_PINRESET) && \
|
||||
defined(NRF_BL_DFU_ENTER_METHOD_GPREGRET) && \
|
||||
defined(NRF_BL_DFU_ENTER_METHOD_BUTTONLESS)&& \
|
||||
defined(NRF_BL_RESET_DELAY_MS) && \
|
||||
defined(NRF_BL_DEBUG_PORT_DISABLE))
|
||||
#error Configuration file is missing flags. Update sdk_config.h.
|
||||
#endif
|
||||
|
||||
STATIC_ASSERT((NRF_BL_DFU_INACTIVITY_TIMEOUT_MS >= 100) || (NRF_BL_DFU_INACTIVITY_TIMEOUT_MS == 0),
|
||||
"NRF_BL_DFU_INACTIVITY_TIMEOUT_MS must be 100 ms or more, or 0 to indicate that it is disabled.");
|
||||
|
||||
#if defined(NRF_LOG_BACKEND_FLASH_START_PAGE)
|
||||
STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_START_PAGE != 0,
|
||||
"If nrf_log flash backend is used it cannot use space after code because it would collide with settings page.");
|
||||
#endif
|
||||
|
||||
/**@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(nrf_dfu_observer_t observer)
|
||||
{
|
||||
NRF_LOG_DEBUG("in weak nrf_dfu_init");
|
||||
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_DEBUG("in weak nrf_dfu_init_user");
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void flash_write_callback(void * p_context)
|
||||
{
|
||||
UNUSED_PARAMETER(p_context);
|
||||
m_flash_write_done = true;
|
||||
}
|
||||
|
||||
|
||||
static void do_reset(void * p_context)
|
||||
{
|
||||
UNUSED_PARAMETER(p_context);
|
||||
|
||||
NRF_LOG_FINAL_FLUSH();
|
||||
|
||||
nrf_delay_ms(NRF_BL_RESET_DELAY_MS);
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
|
||||
static void bootloader_reset(bool do_backup)
|
||||
{
|
||||
NRF_LOG_DEBUG("Resetting bootloader.");
|
||||
|
||||
if (do_backup)
|
||||
{
|
||||
m_flash_write_done = false;
|
||||
nrf_dfu_settings_backup(do_reset);
|
||||
}
|
||||
else
|
||||
{
|
||||
do_reset(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void inactivity_timeout(void)
|
||||
{
|
||||
NRF_LOG_INFO("Inactivity timeout.");
|
||||
bootloader_reset(true);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling DFU events.
|
||||
*/
|
||||
static void dfu_observer(nrf_dfu_evt_type_t evt_type)
|
||||
{
|
||||
switch (evt_type)
|
||||
{
|
||||
case NRF_DFU_EVT_DFU_STARTED:
|
||||
case NRF_DFU_EVT_OBJECT_RECEIVED:
|
||||
nrf_bootloader_dfu_inactivity_timer_restart(
|
||||
NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS),
|
||||
inactivity_timeout);
|
||||
break;
|
||||
case NRF_DFU_EVT_DFU_COMPLETED:
|
||||
case NRF_DFU_EVT_DFU_ABORTED:
|
||||
bootloader_reset(true);
|
||||
break;
|
||||
case NRF_DFU_EVT_TRANSPORT_DEACTIVATED:
|
||||
// Reset the internal state of the DFU settings to the last stored state.
|
||||
nrf_dfu_settings_reinit();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_user_observer)
|
||||
{
|
||||
m_user_observer(evt_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for initializing the event scheduler.
|
||||
*/
|
||||
static void scheduler_init(void)
|
||||
{
|
||||
APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Suspend the CPU until an interrupt occurs.
|
||||
*/
|
||||
static void wait_for_event(void)
|
||||
{
|
||||
#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
|
||||
(void)sd_app_evt_wait();
|
||||
#else
|
||||
// Wait for an event.
|
||||
__WFE();
|
||||
// Clear the internal event register.
|
||||
__SEV();
|
||||
__WFE();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**@brief Continually sleep and process tasks whenever woken.
|
||||
*/
|
||||
static void loop_forever(void)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
//feed the watchdog if enabled.
|
||||
nrf_bootloader_wdt_feed();
|
||||
|
||||
app_sched_execute();
|
||||
|
||||
if (!NRF_LOG_PROCESS())
|
||||
{
|
||||
wait_for_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NRF_BL_DFU_ENTER_METHOD_BUTTON
|
||||
#ifndef BUTTON_PULL
|
||||
#error NRF_BL_DFU_ENTER_METHOD_BUTTON is enabled but not buttons seem to be available on the board.
|
||||
#endif
|
||||
/**@brief Function for initializing button used to enter DFU mode.
|
||||
*/
|
||||
static void dfu_enter_button_init(void)
|
||||
{
|
||||
nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN,
|
||||
BUTTON_PULL,
|
||||
NRF_GPIO_PIN_SENSE_LOW);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static bool crc_on_valid_app_required(void)
|
||||
{
|
||||
bool ret = true;
|
||||
if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET &&
|
||||
(nrf_power_resetreas_get() & NRF_POWER_RESETREAS_OFF_MASK))
|
||||
{
|
||||
nrf_power_resetreas_clear(NRF_POWER_RESETREAS_OFF_MASK);
|
||||
ret = false;
|
||||
}
|
||||
else if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 &&
|
||||
((nrf_power_gpregret2_get() & BOOTLOADER_DFU_GPREGRET2_MASK) == BOOTLOADER_DFU_GPREGRET2)
|
||||
&& (nrf_power_gpregret2_get() & BOOTLOADER_DFU_SKIP_CRC_BIT_MASK))
|
||||
{
|
||||
nrf_power_gpregret2_set(nrf_power_gpregret2_get() & ~BOOTLOADER_DFU_SKIP_CRC);
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len, bool do_crc)
|
||||
{
|
||||
if (!do_crc && (p_validation->type == VALIDATE_CRC))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return nrf_dfu_validation_boot_validate(p_validation, data_addr, data_len);
|
||||
}
|
||||
|
||||
|
||||
/** @brief Function for checking if the main application is valid.
|
||||
*
|
||||
* @details This function checks if there is a valid application
|
||||
* located at Bank 0.
|
||||
*
|
||||
* @param[in] do_crc Perform CRC check on application. Only CRC checks
|
||||
can be skipped. For other boot validation types,
|
||||
this parameter is ignored.
|
||||
*
|
||||
* @retval true If a valid application has been detected.
|
||||
* @retval false If there is no valid application.
|
||||
*/
|
||||
static bool app_is_valid(bool do_crc)
|
||||
{
|
||||
if (s_dfu_settings.bank_0.bank_code != NRF_DFU_BANK_VALID_APP)
|
||||
{
|
||||
NRF_LOG_INFO("Boot validation failed. No valid app to boot.");
|
||||
return false;
|
||||
}
|
||||
else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED &&
|
||||
(s_dfu_settings.boot_validation_app.type != VALIDATE_ECDSA_P256_SHA256))
|
||||
{
|
||||
NRF_LOG_WARNING("Boot validation failed. The boot validation of the app must be a signature check.");
|
||||
return false;
|
||||
}
|
||||
else if (SD_PRESENT && !boot_validate(&s_dfu_settings.boot_validation_softdevice, MBR_SIZE, s_dfu_settings.sd_size, do_crc))
|
||||
{
|
||||
NRF_LOG_WARNING("Boot validation failed. SoftDevice is present but invalid.");
|
||||
return false;
|
||||
}
|
||||
else if (!boot_validate(&s_dfu_settings.boot_validation_app, nrf_dfu_bank0_start_addr(), s_dfu_settings.bank_0.image_size, do_crc))
|
||||
{
|
||||
NRF_LOG_WARNING("Boot validation failed. App is invalid.");
|
||||
return false;
|
||||
}
|
||||
// The bootloader itself is not checked, since a self-check of this kind gives little to no benefit
|
||||
// compared to the cost incurred on each bootup.
|
||||
|
||||
NRF_LOG_DEBUG("App is valid");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**@brief Function for clearing all DFU enter flags that
|
||||
* preserve state during reset.
|
||||
*
|
||||
* @details This is used to make sure that each of these flags
|
||||
* is checked only once after reset.
|
||||
*/
|
||||
static void dfu_enter_flags_clear(void)
|
||||
{
|
||||
if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
|
||||
(NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk))
|
||||
{
|
||||
// Clear RESETPIN flag.
|
||||
NRF_POWER->RESETREAS |= POWER_RESETREAS_RESETPIN_Msk;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
|
||||
((nrf_power_gpregret_get() & BOOTLOADER_DFU_GPREGRET_MASK) == BOOTLOADER_DFU_GPREGRET)
|
||||
&& (nrf_power_gpregret_get() & BOOTLOADER_DFU_START_BIT_MASK))
|
||||
{
|
||||
// Clear DFU mark in GPREGRET register.
|
||||
nrf_power_gpregret_set(nrf_power_gpregret_get() & ~BOOTLOADER_DFU_START);
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
|
||||
(s_dfu_settings.enter_buttonless_dfu == 1))
|
||||
{
|
||||
// Clear DFU flag in flash settings.
|
||||
s_dfu_settings.enter_buttonless_dfu = 0;
|
||||
APP_ERROR_CHECK(nrf_dfu_settings_write(NULL));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for checking whether to enter DFU mode or not.
|
||||
*/
|
||||
static bool dfu_enter_check(void)
|
||||
{
|
||||
if (!app_is_valid(crc_on_valid_app_required()))
|
||||
{
|
||||
NRF_LOG_DEBUG("DFU mode because app is not valid.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_BUTTON &&
|
||||
(nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0))
|
||||
{
|
||||
NRF_LOG_DEBUG("DFU mode requested via button.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
|
||||
(NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk))
|
||||
{
|
||||
NRF_LOG_DEBUG("DFU mode requested via pin-reset.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
|
||||
(nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
|
||||
{
|
||||
NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
|
||||
(s_dfu_settings.enter_buttonless_dfu == 1))
|
||||
{
|
||||
NRF_LOG_DEBUG("DFU mode requested via bootloader settings.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
|
||||
static void postvalidate(void)
|
||||
{
|
||||
NRF_LOG_INFO("Postvalidating update after reset.");
|
||||
nrf_dfu_validation_init();
|
||||
|
||||
if (nrf_dfu_validation_init_cmd_present())
|
||||
{
|
||||
uint32_t firmware_start_addr;
|
||||
uint32_t firmware_size;
|
||||
|
||||
// Execute a previously received init packed. Subsequent executes will have no effect.
|
||||
if (nrf_dfu_validation_init_cmd_execute(&firmware_start_addr, &firmware_size) == NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
if (nrf_dfu_validation_prevalidate() == NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
if (nrf_dfu_validation_activation_prepare(firmware_start_addr, firmware_size) == NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
NRF_LOG_INFO("Postvalidation successful.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0;
|
||||
UNUSED_RETURN_VALUE(nrf_dfu_settings_write_and_backup(flash_write_callback));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
NRF_LOG_DEBUG("In nrf_bootloader_init");
|
||||
|
||||
ret_code_t ret_val;
|
||||
nrf_bootloader_fw_activation_result_t activation_result;
|
||||
uint32_t initial_timeout;
|
||||
bool dfu_enter = false;
|
||||
|
||||
m_user_observer = observer;
|
||||
|
||||
if (NRF_BL_DEBUG_PORT_DISABLE)
|
||||
{
|
||||
nrf_bootloader_debug_port_disable();
|
||||
}
|
||||
|
||||
#if NRF_BL_DFU_ENTER_METHOD_BUTTON
|
||||
dfu_enter_button_init();
|
||||
#endif
|
||||
|
||||
ret_val = nrf_dfu_settings_init(false);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
|
||||
// Postvalidate if DFU has signaled that update is ready.
|
||||
if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1)
|
||||
{
|
||||
postvalidate();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check if an update needs to be activated and activate it.
|
||||
activation_result = nrf_bootloader_fw_activate();
|
||||
|
||||
switch (activation_result)
|
||||
{
|
||||
case ACTIVATION_NONE:
|
||||
initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS);
|
||||
dfu_enter = dfu_enter_check();
|
||||
break;
|
||||
|
||||
case ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE:
|
||||
initial_timeout = NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_CONTINUATION_TIMEOUT_MS);
|
||||
dfu_enter = true;
|
||||
break;
|
||||
|
||||
case ACTIVATION_SUCCESS:
|
||||
bootloader_reset(true);
|
||||
NRF_LOG_ERROR("Unreachable");
|
||||
return NRF_ERROR_INTERNAL; // Should not reach this.
|
||||
|
||||
case ACTIVATION_ERROR:
|
||||
default:
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
if (dfu_enter)
|
||||
{
|
||||
nrf_bootloader_wdt_init();
|
||||
scheduler_init();
|
||||
dfu_enter_flags_clear();
|
||||
|
||||
// Call user-defined init function if implemented
|
||||
ret_val = nrf_dfu_init_user();
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout, inactivity_timeout);
|
||||
|
||||
ret_val = nrf_dfu_init(dfu_observer);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Enter main loop");
|
||||
loop_forever(); // This function will never return.
|
||||
NRF_LOG_ERROR("Unreachable");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Erase additional data like peer data or advertisement name
|
||||
ret_val = nrf_dfu_settings_additional_erase();
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
m_flash_write_done = false;
|
||||
nrf_dfu_settings_backup(flash_write_callback);
|
||||
ASSERT(m_flash_write_done);
|
||||
|
||||
nrf_bootloader_app_start();
|
||||
NRF_LOG_ERROR("Unreachable");
|
||||
}
|
||||
|
||||
// Should not be reached.
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
79
components/libraries/bootloader/nrf_bootloader.h
Normal file
79
components/libraries/bootloader/nrf_bootloader.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_bootloader Bootloader modules
|
||||
* @{
|
||||
* @ingroup app_common
|
||||
* @brief Bootloader and DFU modules
|
||||
*
|
||||
* 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>
|
||||
#include "nrf_dfu.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.
|
||||
*
|
||||
* @note This function does not return unless an error occurred.
|
||||
*
|
||||
* @retval NRF_ERROR_INTERNAL Something went wrong.
|
||||
*/
|
||||
ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_BOOTLOADER_H__
|
||||
/** @} */
|
||||
77
components/libraries/bootloader/nrf_bootloader_app_start.c
Normal file
77
components/libraries/bootloader/nrf_bootloader_app_start.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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.h"
|
||||
#include "nrf_bootloader_app_start.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_dfu_mbr.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
|
||||
// Do the final stages of app_start. Protect flash and run app. See nrf_bootloader_app_start_final.c
|
||||
void nrf_bootloader_app_start_final(uint32_t start_addr);
|
||||
|
||||
void nrf_bootloader_app_start(void)
|
||||
{
|
||||
uint32_t start_addr = MBR_SIZE; // Always boot from end of MBR. If a SoftDevice is present, it will boot the app.
|
||||
NRF_LOG_DEBUG("Running nrf_bootloader_app_start with address: 0x%08x", start_addr);
|
||||
uint32_t err_code;
|
||||
|
||||
// Disable and clear interrupts
|
||||
// Notice that this disables only 'external' interrupts (positive IRQn).
|
||||
NRF_LOG_DEBUG("Disabling interrupts. NVIC->ICER[0]: 0x%x", NVIC->ICER[0]);
|
||||
|
||||
NVIC->ICER[0]=0xFFFFFFFF;
|
||||
NVIC->ICPR[0]=0xFFFFFFFF;
|
||||
#if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2
|
||||
NVIC->ICER[1]=0xFFFFFFFF;
|
||||
NVIC->ICPR[1]=0xFFFFFFFF;
|
||||
#endif
|
||||
|
||||
err_code = nrf_dfu_mbr_irq_forward_address_set();
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed running nrf_dfu_mbr_irq_forward_address_set()");
|
||||
}
|
||||
|
||||
NRF_LOG_FLUSH();
|
||||
nrf_bootloader_app_start_final(start_addr);
|
||||
}
|
||||
88
components/libraries/bootloader/nrf_bootloader_app_start.h
Normal file
88
components/libraries/bootloader/nrf_bootloader_app_start.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_bootloader_app Application start
|
||||
* @{
|
||||
* @ingroup nrf_bootloader
|
||||
*/
|
||||
|
||||
#ifndef NRF_BOOTLOADER_APP_START_H__
|
||||
#define NRF_BOOTLOADER_APP_START_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "sdk_errors.h"
|
||||
|
||||
|
||||
/**@brief Function for using hardware to protect flash from writing and reading.
|
||||
*
|
||||
* @details This function applies write/erase protection to a specific area, using the BPROT or ACL
|
||||
* peripheral, depending on which is available.
|
||||
*
|
||||
* @param[in] address The start address of the area to protect. Must be a flash page
|
||||
* boundary.
|
||||
* @param[in] size The size of the area to protect, in bytes. Must be a multiple
|
||||
* of flash page size.
|
||||
*
|
||||
* @retval NRF_SUCCESS Flash protection applied successfully.
|
||||
* @retval NRF_ERROR_NO_MEM No more ACL instances to use for flash protection.
|
||||
* @retval NRF_ERROR_INVALID_PARAM Address was out of range or size was not a multiple
|
||||
* of flash page size.
|
||||
*/
|
||||
ret_code_t nrf_bootloader_flash_protect(uint32_t address, uint32_t size);
|
||||
|
||||
/**@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 assumes the SoftDevice has not previously been initialized.
|
||||
*
|
||||
* @note This function will never return, but issues a reset into the provided application.
|
||||
*/
|
||||
void nrf_bootloader_app_start(void);
|
||||
|
||||
#endif // NRF_BOOTLOADER_APP_START_H__
|
||||
|
||||
/** @} */
|
||||
188
components/libraries/bootloader/nrf_bootloader_app_start_final.c
Normal file
188
components/libraries/bootloader/nrf_bootloader_app_start_final.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 "sdk_config.h"
|
||||
#include "nrf_bootloader_app_start.h"
|
||||
#include <stdint.h>
|
||||
#include "nrf.h"
|
||||
#include "nrf_peripherals.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "nrf_dfu_utils.h"
|
||||
#include "nrf_dfu_settings.h"
|
||||
#include "nrf_assert.h"
|
||||
#include "nrf_log.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
|
||||
#define HANDLER_MODE_EXIT 0xFFFFFFF9 // When this is jumped to, the CPU will exit interrupt context
|
||||
// (handler mode), and pop values from the stack into registers.
|
||||
// See ARM's documentation for "Exception entry and return".
|
||||
#define EXCEPTION_STACK_WORD_COUNT 8 // The number of words popped from the stack when
|
||||
// HANDLER_MODE_EXIT is branched to.
|
||||
|
||||
|
||||
/**@brief Function that sets the stack pointer and starts executing a particular address.
|
||||
*
|
||||
* @param[in] new_msp The new value to set in the main stack pointer.
|
||||
* @param[in] addr The address to execute.
|
||||
*/
|
||||
void jump_to_addr(uint32_t new_msp, uint32_t addr)
|
||||
{
|
||||
__set_MSP(new_msp);
|
||||
((void (*)(void))addr)();
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for booting an app as if the chip was reset.
|
||||
*
|
||||
* @param[in] vector_table_addr The address of the app's vector table.
|
||||
*/
|
||||
__STATIC_INLINE void app_start(uint32_t vector_table_addr)
|
||||
{
|
||||
const uint32_t current_isr_num = (__get_IPSR() & IPSR_ISR_Msk);
|
||||
const uint32_t new_msp = *((uint32_t *)(vector_table_addr)); // The app's Stack Pointer is found as the first word of the vector table.
|
||||
const uint32_t reset_handler = *((uint32_t *)(vector_table_addr + sizeof(uint32_t))); // The app's Reset Handler is found as the second word of the vector table.
|
||||
|
||||
__set_CONTROL(0x00000000); // Set CONTROL to its reset value 0.
|
||||
__set_PRIMASK(0x00000000); // Set PRIMASK to its reset value 0.
|
||||
__set_BASEPRI(0x00000000); // Set BASEPRI to its reset value 0.
|
||||
__set_FAULTMASK(0x00000000); // Set FAULTMASK to its reset value 0.
|
||||
|
||||
ASSERT(current_isr_num == 0); // If this is triggered, the CPU is currently in an interrupt.
|
||||
|
||||
// The CPU is in Thread mode (main context).
|
||||
jump_to_addr(new_msp, reset_handler); // Jump directly to the App's Reset Handler.
|
||||
}
|
||||
|
||||
|
||||
ret_code_t nrf_bootloader_flash_protect(uint32_t address, uint32_t size)
|
||||
{
|
||||
if ((size & (CODE_PAGE_SIZE - 1)) || (address > BOOTLOADER_SETTINGS_ADDRESS))
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
#if defined(ACL_PRESENT)
|
||||
|
||||
// Protect using ACL.
|
||||
static uint32_t acl_instance = 0;
|
||||
|
||||
uint32_t const mask = (ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos);
|
||||
|
||||
if (acl_instance >= ACL_REGIONS_COUNT)
|
||||
{
|
||||
return NRF_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
NRF_ACL->ACL[acl_instance].ADDR = address;
|
||||
NRF_ACL->ACL[acl_instance].SIZE = size;
|
||||
NRF_ACL->ACL[acl_instance].PERM = mask;
|
||||
|
||||
acl_instance++;
|
||||
|
||||
#elif defined (BPROT_PRESENT)
|
||||
|
||||
// Protect using BPROT. BPROT does not support read protection.
|
||||
uint32_t pagenum_start = address / CODE_PAGE_SIZE;
|
||||
uint32_t pagenum_end = pagenum_start + ((size - 1) / CODE_PAGE_SIZE);
|
||||
|
||||
for (uint32_t i = pagenum_start; i <= pagenum_end; i++)
|
||||
{
|
||||
uint32_t config_index = i / 32;
|
||||
uint32_t mask = (1 << (i - config_index * 32));
|
||||
|
||||
switch (config_index)
|
||||
{
|
||||
case 0:
|
||||
NRF_BPROT->CONFIG0 = mask;
|
||||
break;
|
||||
case 1:
|
||||
NRF_BPROT->CONFIG1 = mask;
|
||||
break;
|
||||
#if BPROT_REGIONS_NUM > 64
|
||||
case 2:
|
||||
NRF_BPROT->CONFIG2 = mask;
|
||||
break;
|
||||
case 3:
|
||||
NRF_BPROT->CONFIG3 = mask;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void nrf_bootloader_app_start_final(uint32_t vector_table_addr)
|
||||
{
|
||||
ret_code_t ret_val;
|
||||
|
||||
// Size of the flash area to protect.
|
||||
uint32_t area_size;
|
||||
|
||||
area_size = BOOTLOADER_SIZE + NRF_MBR_PARAMS_PAGE_SIZE;
|
||||
if (!NRF_BL_DFU_ALLOW_UPDATE_FROM_APP && !NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && !NRF_DFU_TRANSPORT_BLE)
|
||||
{
|
||||
area_size += BOOTLOADER_SETTINGS_PAGE_SIZE;
|
||||
}
|
||||
|
||||
ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, area_size);
|
||||
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not protect bootloader and settings pages, 0x%x.", ret_val);
|
||||
}
|
||||
APP_ERROR_CHECK(ret_val);
|
||||
|
||||
ret_val = nrf_bootloader_flash_protect(0,
|
||||
nrf_dfu_bank0_start_addr() + ALIGN_TO_PAGE(s_dfu_settings.bank_0.image_size));
|
||||
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not protect SoftDevice and application, 0x%x.", ret_val);
|
||||
}
|
||||
APP_ERROR_CHECK(ret_val);
|
||||
|
||||
// Run application
|
||||
app_start(vector_table_addr);
|
||||
}
|
||||
268
components/libraries/bootloader/nrf_bootloader_dfu_timers.c
Normal file
268
components/libraries/bootloader/nrf_bootloader_dfu_timers.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* Copyright (c) 2018 - 2020, 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_dfu_timers.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <nrfx.h>
|
||||
#include "nrf_clock.h"
|
||||
#include "nrf_rtc.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_log.h"
|
||||
|
||||
|
||||
#define RTC_PRESCALER (0) //!< The value provided to the RTC as the prescaler. 0 corresponds to one tick per clock cycle of the LFCLK (32768 ticks/s).
|
||||
#define RTC_WRAP_TICKS ((1 << 24) - 1) //!< The largest possible value in the RTC counter register.
|
||||
#define MAX_TIMEOUT_TICKS (RTC_WRAP_TICKS) //!< The longest fire timeout allowed. Longer timeouts are handled by multiple firings.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
nrf_bootloader_dfu_timeout_callback_t callback; //!< Callback that is called when this timer times out.
|
||||
uint32_t timeout; //!< The number of ticks from the next firing until the actual timeout. This value will be different from 0 if the original timeout was longer than MAX_TIMEOUT_TICKS, so multiple firings were needed.
|
||||
uint32_t repeated_timeout; //!< If different from 0, this timer will be reactivated with this value after timing out.
|
||||
uint8_t cc_channel; //!< Which CC register this timer uses.
|
||||
} dfu_timer_t;
|
||||
|
||||
|
||||
dfu_timer_t m_timers[2] = {{.cc_channel = 0}, {.cc_channel = 1}}; //!< The timers used by this module.
|
||||
dfu_timer_t * mp_inactivity = &m_timers[0]; //!< Direct pointer to the inactivity timer, for convenience and readability.
|
||||
dfu_timer_t * mp_wdt_feed = &m_timers[1]; //!< Direct pointer to the wdt feed timer, for convenience and readability.
|
||||
uint32_t m_counter_loops = 0; //!< The number of times the RTC counter register has overflowed (wrapped around) since the RTC was started.
|
||||
|
||||
#if RTC_COUNT > 2
|
||||
#define RTC_INSTANCE 2
|
||||
#define RTC_STRUCT NRF_RTC2
|
||||
#define RTC_IRQHandler RTC2_IRQHandler
|
||||
#define RTC_IRQn RTC2_IRQn
|
||||
#define RTC_CC_COUNT NRF_RTC_CC_CHANNEL_COUNT(2))
|
||||
#elif RTC_COUNT > 1
|
||||
#define RTC_INSTANCE 1
|
||||
#define RTC_STRUCT NRF_RTC1
|
||||
#define RTC_IRQHandler RTC1_IRQHandler
|
||||
#define RTC_IRQn RTC1_IRQn
|
||||
#define RTC_CC_COUNT NRF_RTC_CC_CHANNEL_COUNT(1))
|
||||
#else
|
||||
#error Not enough RTC instances.
|
||||
#endif
|
||||
|
||||
/**@brief Function for initializing the timer if it is not already initialized.
|
||||
*/
|
||||
static void timer_init(void)
|
||||
{
|
||||
static bool m_timer_initialized;
|
||||
|
||||
if (!m_timer_initialized)
|
||||
{
|
||||
if (!nrf_clock_lf_is_running())
|
||||
{
|
||||
nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
|
||||
}
|
||||
|
||||
nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_TICK);
|
||||
nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_COMPARE_0);
|
||||
nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_COMPARE_1);
|
||||
NRFX_IRQ_PRIORITY_SET(RTC_IRQn, 5);
|
||||
NRFX_IRQ_ENABLE(RTC_IRQn);
|
||||
nrf_rtc_prescaler_set(RTC_STRUCT, RTC_PRESCALER);
|
||||
nrf_rtc_task_trigger(RTC_STRUCT, NRF_RTC_TASK_CLEAR);
|
||||
nrf_rtc_task_trigger(RTC_STRUCT, NRF_RTC_TASK_START);
|
||||
nrf_rtc_int_enable(RTC_STRUCT, RTC_INTENSET_OVRFLW_Msk);
|
||||
|
||||
m_timer_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for scheduling an RTC compare event.
|
||||
*
|
||||
* @param[in] cc_channel Which of the RTC compare registers to use.
|
||||
* @param[in] cc_value The ticks value at which to receive the event.
|
||||
*/
|
||||
static void rtc_update(uint32_t cc_channel, uint32_t cc_value)
|
||||
{
|
||||
ASSERT(cc_channel < NRF_RTC_CC_CHANNEL_COUNT(RTC_INSTANCE));
|
||||
|
||||
nrf_rtc_cc_set(RTC_STRUCT, cc_channel, cc_value);
|
||||
nrf_delay_us(31);
|
||||
nrf_rtc_event_clear(RTC_STRUCT, RTC_CHANNEL_EVENT_ADDR(cc_channel));
|
||||
nrf_rtc_int_enable(RTC_STRUCT, RTC_CHANNEL_INT_MASK(cc_channel));
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for activating a timer, so that it will be fired.
|
||||
*
|
||||
* This can happen multiple times before the actual timeout happens if the timeout is longer than
|
||||
* @ref MAX_TIMEOUT_TICKS.
|
||||
*
|
||||
* @param[in] p_timer The timer to activate.
|
||||
* @param[in] timeout_ticks The number of ticks until the timeout.
|
||||
*
|
||||
* @retval true If the timer was activated.
|
||||
* @retval false If the timer is already active.
|
||||
*/
|
||||
static void timer_activate(dfu_timer_t * p_timer, uint32_t timeout_ticks)
|
||||
{
|
||||
NRF_LOG_DEBUG("timer_activate (0x%x)", p_timer);
|
||||
|
||||
ASSERT(timeout_ticks <= MAX_TIMEOUT_TICKS);
|
||||
ASSERT(timeout_ticks >= NRF_BOOTLOADER_MIN_TIMEOUT_TICKS);
|
||||
uint32_t next_timeout_ticks = MIN(timeout_ticks, MAX_TIMEOUT_TICKS);
|
||||
uint32_t cc_value = RTC_WRAP(next_timeout_ticks + nrf_rtc_counter_get(RTC_STRUCT));
|
||||
p_timer->timeout = timeout_ticks - next_timeout_ticks;
|
||||
|
||||
if ((p_timer->timeout > 0) && (p_timer->timeout < NRF_BOOTLOADER_MIN_TIMEOUT_TICKS))
|
||||
{
|
||||
p_timer->timeout += NRF_BOOTLOADER_MIN_TIMEOUT_TICKS;
|
||||
cc_value -= NRF_BOOTLOADER_MIN_TIMEOUT_TICKS;
|
||||
}
|
||||
|
||||
rtc_update(p_timer->cc_channel, cc_value);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for deactivating a timer, so that it will not fire.
|
||||
*
|
||||
* @param[in] p_timer The timer to deactivate.
|
||||
*
|
||||
* @retval true If the timer was deactivated.
|
||||
* @retval false If the timer is already inactive.
|
||||
*/
|
||||
static void timer_stop(dfu_timer_t * p_timer)
|
||||
{
|
||||
NRF_LOG_DEBUG("timer_stop (0x%x)", p_timer);
|
||||
nrf_rtc_int_disable(RTC_STRUCT, RTC_CHANNEL_INT_MASK(p_timer->cc_channel));
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for firing a timer.
|
||||
*
|
||||
* This can happen multiple times before the actual timeout happens if the timeout is longer than
|
||||
* @ref MAX_TIMEOUT_TICKS.
|
||||
* This function reactivates the timer if the timer is repeating, or if the timer has not yet
|
||||
* timed out. It then calls the callback if the timer (repeating or not) has timed out.
|
||||
*
|
||||
* @param[in] p_timer The timer to fire.
|
||||
*/
|
||||
static void timer_fire(dfu_timer_t * p_timer)
|
||||
{
|
||||
NRF_LOG_DEBUG("timer_fire (0x%x)", p_timer);
|
||||
|
||||
if (p_timer->timeout != 0)
|
||||
{
|
||||
// The timer has not yet timed out.
|
||||
timer_activate(p_timer, p_timer->timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_timer->repeated_timeout != 0)
|
||||
{
|
||||
timer_activate(p_timer, p_timer->repeated_timeout);
|
||||
}
|
||||
|
||||
if (p_timer->callback != NULL)
|
||||
{
|
||||
p_timer->callback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for requesting a timeout.
|
||||
*
|
||||
* The timer will time out @p timeout_ticks ticks from now. When it times out, @p callback
|
||||
* will be called, and if @p p_timer->repeated_timeout is not 0, a new timeout will be scheduled.
|
||||
*
|
||||
* @param[in] p_timer The timer to start.
|
||||
* @param[in] timeout_ticks The number of ticks until the timeout.
|
||||
* @param[in] callback The callback to call when the timer times out.
|
||||
*/
|
||||
static void timer_start(dfu_timer_t * p_timer,
|
||||
uint32_t timeout_ticks,
|
||||
nrf_bootloader_dfu_timeout_callback_t callback)
|
||||
{
|
||||
timer_init(); // Initialize if needed.
|
||||
p_timer->callback = callback;
|
||||
timer_activate(p_timer, timeout_ticks);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Interrupt handler for the RTC (Real Time Clock) used for the DFU timers.
|
||||
*/
|
||||
void RTC_IRQHandler(void)
|
||||
{
|
||||
if (nrf_rtc_event_pending(RTC_STRUCT, NRF_RTC_EVENT_OVERFLOW))
|
||||
{
|
||||
m_counter_loops++;
|
||||
nrf_rtc_event_clear(RTC_STRUCT, NRF_RTC_EVENT_OVERFLOW);
|
||||
}
|
||||
|
||||
for (uint32_t channel = 0; channel < 2; channel++)
|
||||
{
|
||||
if (nrf_rtc_event_pending(RTC_STRUCT, RTC_CHANNEL_EVENT_ADDR(channel)))
|
||||
{
|
||||
nrf_rtc_event_clear(RTC_STRUCT, RTC_CHANNEL_EVENT_ADDR(channel));
|
||||
timer_stop(&m_timers[channel]);
|
||||
timer_fire(&m_timers[channel]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nrf_bootloader_dfu_inactivity_timer_restart(uint32_t timeout_ticks,
|
||||
nrf_bootloader_dfu_timeout_callback_t callback)
|
||||
{
|
||||
timer_stop(mp_inactivity);
|
||||
if (timeout_ticks != 0)
|
||||
{
|
||||
timer_start(mp_inactivity, timeout_ticks, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nrf_bootloader_wdt_feed_timer_start(uint32_t timeout_ticks,
|
||||
nrf_bootloader_dfu_timeout_callback_t callback)
|
||||
{
|
||||
mp_wdt_feed->repeated_timeout = timeout_ticks;
|
||||
timer_start(mp_wdt_feed, timeout_ticks, callback);
|
||||
}
|
||||
|
||||
|
||||
uint32_t nrf_bootloader_dfu_timer_counter_get(void)
|
||||
{
|
||||
return nrf_rtc_counter_get(RTC_STRUCT) + (m_counter_loops << 24);
|
||||
}
|
||||
111
components/libraries/bootloader/nrf_bootloader_dfu_timers.h
Normal file
111
components/libraries/bootloader/nrf_bootloader_dfu_timers.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (c) 2018 - 2020, 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_bootloader_dfu_timers Timers for DFU in the bootloader
|
||||
* @{
|
||||
* @ingroup nrf_bootloader
|
||||
*/
|
||||
|
||||
#ifndef NRF_BOOTLOADER_DFU_TIMERS_H__
|
||||
#define NRF_BOOTLOADER_DFU_TIMERS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define NRF_BOOTLOADER_MIN_TIMEOUT_TICKS (150) //!< The shortest timeout allowed. To avoid the timeout not being activated before the time has passed.
|
||||
|
||||
/**@brief Macro for converting milliseconds to timer ticks.
|
||||
*
|
||||
* @param[in] ms The milliseconds to convert.
|
||||
*
|
||||
* @return @p ms converted to ticks.
|
||||
*/
|
||||
#define NRF_BOOTLOADER_MS_TO_TICKS(ms) ((((uint64_t)(ms) * 32768)) / 1000)
|
||||
|
||||
/**@brief Handler called on timeout of a timer requested by the watchdog.
|
||||
*/
|
||||
typedef void (*nrf_bootloader_dfu_timeout_callback_t)(void);
|
||||
|
||||
|
||||
/**@brief Function for restarting the inactivity timer.
|
||||
*
|
||||
* @note Calling this function cancels any previous calls to this function.
|
||||
*
|
||||
* @param[in] timeout_ticks The number of ticks until reset. There are 32768 ticks per second.
|
||||
* If 0 is passed, the timer will be stopped and not restarted.
|
||||
* @param[in] callback Function to be called on timeout.
|
||||
*/
|
||||
void nrf_bootloader_dfu_inactivity_timer_restart(uint32_t timeout_ticks,
|
||||
nrf_bootloader_dfu_timeout_callback_t callback);
|
||||
|
||||
|
||||
/**@brief Function for initializing and starting a repeated timer for feeding the watchdog.
|
||||
*
|
||||
* @param[in] timeout_ticks The number of ticks between each feeding of the watchdog. There are
|
||||
* 32768 ticks per second.
|
||||
* @param[in] callback Function called on every timeout.
|
||||
*/
|
||||
void nrf_bootloader_wdt_feed_timer_start(uint32_t timeout_ticks,
|
||||
nrf_bootloader_dfu_timeout_callback_t callback);
|
||||
|
||||
|
||||
/**@brief Function for retrieving the number of ticks since the RTC was started.
|
||||
*
|
||||
* There are 32768 ticks per second. This value does not wrap, even when the RTC counter wraps.
|
||||
*
|
||||
* @note The value can be 2^24 ticks too small if sampled immediately after the RTC counter wraps,
|
||||
* but before the internal loop counter has been incremented.
|
||||
*
|
||||
* @return The number of ticks since the RTC was started.
|
||||
*/
|
||||
uint32_t nrf_bootloader_dfu_timer_counter_get(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_BOOTLOADER_DFU_TIMERS_H__
|
||||
|
||||
/** @} */
|
||||
441
components/libraries/bootloader/nrf_bootloader_fw_activation.c
Normal file
441
components/libraries/bootloader/nrf_bootloader_fw_activation.c
Normal file
@@ -0,0 +1,441 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_fw_activation.h"
|
||||
#include "nrf_dfu_settings.h"
|
||||
#include "nrf_dfu_mbr.h"
|
||||
#include "nrf_bootloader_info.h"
|
||||
#include "crc32.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_dfu_utils.h"
|
||||
#include "nrf_bootloader_wdt.h"
|
||||
|
||||
|
||||
static volatile bool m_flash_write_done;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for copying image. Image is copied in chunks. Frequency of storing progress
|
||||
* in flash is configured by input parameter.
|
||||
*
|
||||
* @param[in] dst_addr Destination address. Must be page aligned.
|
||||
* @param[in] src_addr Source address. Must be higher value than dst_addr.
|
||||
* @param[in] size Image size.
|
||||
* @param[in] progress_update_step Number of copied pages that triggers saving progress to non-volatile memory.
|
||||
* Note that step can be decreased if there is a risk of corruption caused by source
|
||||
* and destination overlapping.
|
||||
*
|
||||
* @return NRF_SUCCESS or error code in case of failure.
|
||||
*/
|
||||
static uint32_t image_copy(uint32_t dst_addr,
|
||||
uint32_t src_addr,
|
||||
uint32_t size,
|
||||
uint32_t progress_update_step)
|
||||
{
|
||||
if (src_addr == dst_addr)
|
||||
{
|
||||
NRF_LOG_DEBUG("No copy needed");
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
ASSERT(src_addr >= dst_addr);
|
||||
ASSERT(progress_update_step > 0);
|
||||
if (size != 0)
|
||||
{
|
||||
ASSERT((dst_addr % CODE_PAGE_SIZE) == 0);
|
||||
}
|
||||
|
||||
uint32_t max_safe_progress_upd_step = (src_addr - dst_addr)/CODE_PAGE_SIZE;
|
||||
ASSERT(max_safe_progress_upd_step > 0);
|
||||
|
||||
uint32_t ret_val = NRF_SUCCESS;
|
||||
uint32_t pages_left = CEIL_DIV(size, CODE_PAGE_SIZE);
|
||||
|
||||
//Firmware copying is time consuming operation thus watchdog handling is started
|
||||
nrf_bootloader_wdt_init();
|
||||
|
||||
progress_update_step = MIN(progress_update_step, max_safe_progress_upd_step);
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
uint32_t pages;
|
||||
uint32_t bytes;
|
||||
if (pages_left <= progress_update_step)
|
||||
{
|
||||
pages = pages_left;
|
||||
bytes = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
pages = progress_update_step;
|
||||
bytes = progress_update_step * CODE_PAGE_SIZE;
|
||||
}
|
||||
// Erase the target pages
|
||||
ret_val = nrf_dfu_flash_erase(dst_addr, pages, NULL);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
// Flash one page
|
||||
NRF_LOG_DEBUG("Copying 0x%x to 0x%x, size: 0x%x", src_addr, dst_addr, bytes);
|
||||
ret_val = nrf_dfu_flash_store(dst_addr,
|
||||
(uint32_t *)src_addr,
|
||||
ALIGN_NUM(sizeof(uint32_t), bytes),
|
||||
NULL);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
pages_left -= pages;
|
||||
size -= bytes;
|
||||
dst_addr += bytes;
|
||||
src_addr += bytes;
|
||||
s_dfu_settings.write_offset += bytes;
|
||||
|
||||
//store progress in flash on every successful chunk write
|
||||
ret_val = nrf_dfu_settings_write_and_backup(NULL);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed to write image copying progress to settings page.");
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/** @brief Function to continue application update.
|
||||
*
|
||||
* @details This function will be called after reset if there is a valid application in Bank1
|
||||
* required to be copied down to Bank 0.
|
||||
*
|
||||
* @return NRF_SUCCESS if continuation was successful, NRF_ERROR_INTERNAL if new firmware does not
|
||||
* contain softdevice or other error coming from modules used by this function.
|
||||
*/
|
||||
static uint32_t app_activate(void)
|
||||
{
|
||||
// This function is 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 src_addr = s_dfu_settings.progress.update_start_address;
|
||||
uint32_t ret_val = NRF_SUCCESS;
|
||||
uint32_t target_addr = nrf_dfu_bank0_start_addr() + s_dfu_settings.write_offset;
|
||||
uint32_t length_left = (image_size - s_dfu_settings.write_offset);
|
||||
uint32_t crc;
|
||||
|
||||
NRF_LOG_DEBUG("Enter nrf_dfu_app_continue");
|
||||
|
||||
src_addr += s_dfu_settings.write_offset;
|
||||
|
||||
if (src_addr == target_addr)
|
||||
{
|
||||
length_left = 0;
|
||||
}
|
||||
|
||||
ret_val = image_copy(target_addr, src_addr, length_left, NRF_BL_FW_COPY_PROGRESS_STORE_STEP);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed to copy firmware.");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
// Check the CRC of the copied data. Enable if so.
|
||||
crc = crc32_compute((uint8_t*)nrf_dfu_bank0_start_addr(), image_size, NULL);
|
||||
|
||||
if (crc == s_dfu_settings.bank_1.image_crc)
|
||||
{
|
||||
NRF_LOG_DEBUG("Setting app as valid");
|
||||
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_ERROR("CRC computation failed for copied app: "
|
||||
"src crc: 0x%08x, res crc: 0x%08x",
|
||||
s_dfu_settings.bank_1.image_crc,
|
||||
crc);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Function to execute the continuation of a SoftDevice update.
|
||||
*
|
||||
* @return NRF_SUCCESS if continuation was successful, NRF_ERROR_INTERNAL if new firmware does not
|
||||
* contain softdevice or other error coming from modules used by this function.
|
||||
*/
|
||||
static uint32_t sd_activate(void)
|
||||
{
|
||||
uint32_t ret_val = NRF_SUCCESS;
|
||||
uint32_t target_addr = nrf_dfu_softdevice_start_address() + s_dfu_settings.write_offset;
|
||||
uint32_t src_addr = s_dfu_settings.progress.update_start_address;
|
||||
uint32_t sd_size = s_dfu_settings.sd_size;
|
||||
uint32_t length_left = ALIGN_TO_PAGE(sd_size - s_dfu_settings.write_offset);
|
||||
|
||||
NRF_LOG_DEBUG("Enter nrf_bootloader_dfu_sd_continue");
|
||||
|
||||
if (SD_MAGIC_NUMBER_GET(src_addr) != SD_MAGIC_NUMBER)
|
||||
{
|
||||
NRF_LOG_ERROR("Source address does not contain a valid SoftDevice.")
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
// This can be a continuation due to a power failure
|
||||
src_addr += s_dfu_settings.write_offset;
|
||||
|
||||
if (s_dfu_settings.write_offset == sd_size)
|
||||
{
|
||||
NRF_LOG_DEBUG("SD already copied");
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
if (s_dfu_settings.write_offset == 0)
|
||||
{
|
||||
NRF_LOG_DEBUG("Updating SD. Old SD ver: %d, New ver: %d",
|
||||
SD_VERSION_GET(MBR_SIZE) / 1000000, SD_VERSION_GET(src_addr) / 1000000);
|
||||
}
|
||||
|
||||
ret_val = image_copy(target_addr, src_addr, length_left, NRF_BL_FW_COPY_PROGRESS_STORE_STEP);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed to copy firmware.");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
ret_val = nrf_dfu_settings_write_and_backup(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 Bank 0 or Bank 1
|
||||
* required to be relocated and activated through MBR commands.
|
||||
*
|
||||
* @return This function will not return if the bootloader is copied successfully.
|
||||
* 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 bl_activate(void)
|
||||
{
|
||||
uint32_t ret_val = NRF_ERROR_INVALID_DATA;
|
||||
nrf_dfu_bank_t * p_bank = &s_dfu_settings.bank_1;
|
||||
uint32_t len = p_bank->image_size;
|
||||
uint32_t src_addr = s_dfu_settings.progress.update_start_address;
|
||||
|
||||
if (p_bank->bank_code == NRF_DFU_BANK_VALID_SD_BL)
|
||||
{
|
||||
src_addr += s_dfu_settings.sd_size;
|
||||
len -= s_dfu_settings.sd_size;
|
||||
}
|
||||
else if (src_addr == 0)
|
||||
{
|
||||
src_addr = nrf_dfu_bank1_start_addr();
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Verifying BL: Addr: 0x%08x, Src: 0x%08x, Len: 0x%08x", BOOTLOADER_START_ADDR, src_addr, len);
|
||||
|
||||
// This code is a configurable workaround for updating SD+BL from SDK 12.x.y - 14.1.0
|
||||
// SoftDevice size increase would lead to unaligned source address when comparing new BL in SD+BL updates.
|
||||
// This workaround is not required once BL is successfully installed with a version that is compiled SDK 14.1.0
|
||||
#if defined(NRF52832_XXAA) && defined(BLE_STACK_SUPPORT_REQD)
|
||||
if ((p_bank->bank_code == NRF_DFU_BANK_VALID_SD_BL) &&
|
||||
(memcmp((void *)BOOTLOADER_START_ADDR, (void *)(src_addr - 0x4000), len) == 0))
|
||||
{
|
||||
ret_val = NRF_SUCCESS;
|
||||
}
|
||||
#endif // defined(NRF52832_XXAA)
|
||||
|
||||
// Check if the BL has already been copied.
|
||||
if ((ret_val != NRF_SUCCESS) &&
|
||||
(memcmp((void *)BOOTLOADER_START_ADDR, (void *)src_addr, len) == 0))
|
||||
{
|
||||
ret_val = NRF_SUCCESS;
|
||||
}
|
||||
|
||||
// If the bootloader is the same as the banked version, the copy is finished
|
||||
if (ret_val == NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_DEBUG("No bootloader copy needed, bootloader update complete.");
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_DEBUG("Copying bootloader: Src: 0x%08x, Len: 0x%08x", src_addr, len);
|
||||
NRF_LOG_FLUSH();
|
||||
|
||||
nrf_bootloader_wdt_feed();
|
||||
|
||||
// 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
|
||||
// On success this function won't return.
|
||||
ret_val = nrf_dfu_mbr_copy_bl((uint32_t*)src_addr, len);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Request to copy BL failed");
|
||||
}
|
||||
}
|
||||
|
||||
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 Bank 0 or Bank 1
|
||||
* required to be relocated and activated through MBR commands.
|
||||
*
|
||||
* @retval NRF_SUCCESS Continuation was successful.
|
||||
* @retval NRF_ERROR_INVALID_LENGTH Invalid length.
|
||||
* @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 sd_bl_activate()
|
||||
{
|
||||
uint32_t ret_val = NRF_SUCCESS;
|
||||
|
||||
NRF_LOG_DEBUG("Enter nrf_dfu_sd_bl_continue");
|
||||
|
||||
ret_val = sd_activate();
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("SD+BL: SD copy failed");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
ret_val = bl_activate();
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("SD+BL: BL copy failed");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
static void flash_write_callback(void * p_context)
|
||||
{
|
||||
UNUSED_PARAMETER(p_context);
|
||||
m_flash_write_done = true;
|
||||
}
|
||||
|
||||
|
||||
nrf_bootloader_fw_activation_result_t nrf_bootloader_fw_activate(void)
|
||||
{
|
||||
nrf_bootloader_fw_activation_result_t result;
|
||||
uint32_t ret_val = NRF_SUCCESS;
|
||||
nrf_dfu_bank_t * p_bank = &s_dfu_settings.bank_1;
|
||||
bool sd_update = false;
|
||||
|
||||
NRF_LOG_DEBUG("Enter nrf_bootloader_fw_activate");
|
||||
|
||||
switch (p_bank->bank_code)
|
||||
{
|
||||
case NRF_DFU_BANK_VALID_APP:
|
||||
NRF_LOG_DEBUG("Valid App");
|
||||
ret_val = app_activate();
|
||||
break;
|
||||
case NRF_DFU_BANK_VALID_SD:
|
||||
NRF_LOG_DEBUG("Valid SD");
|
||||
ret_val = sd_activate();
|
||||
sd_update = true;
|
||||
break;
|
||||
case NRF_DFU_BANK_VALID_BL:
|
||||
NRF_LOG_DEBUG("Valid BL");
|
||||
ret_val = bl_activate();
|
||||
break;
|
||||
case NRF_DFU_BANK_VALID_SD_BL:
|
||||
NRF_LOG_DEBUG("Valid SD + BL");
|
||||
ret_val = sd_bl_activate();
|
||||
sd_update = true;
|
||||
break;
|
||||
case NRF_DFU_BANK_INVALID:
|
||||
default:
|
||||
NRF_LOG_INFO("No firmware to activate.");
|
||||
return ACTIVATION_NONE;
|
||||
}
|
||||
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Activation failed with error %d (bank code: 0x%x)", ret_val, p_bank->bank_code);
|
||||
result = ACTIVATION_ERROR;
|
||||
}
|
||||
|
||||
// Invalidate bank, marking completion.
|
||||
nrf_dfu_bank_invalidate(p_bank);
|
||||
|
||||
m_flash_write_done = false;
|
||||
ret_val = nrf_dfu_settings_write_and_backup(flash_write_callback);
|
||||
ASSERT(m_flash_write_done); /* At this point flash module is performing blocking operation. It is expected that operation is already performed. */
|
||||
|
||||
if (ret_val == NRF_SUCCESS)
|
||||
{
|
||||
result = ACTIVATION_SUCCESS;
|
||||
if (sd_update && (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP))
|
||||
{
|
||||
//If SD was updated and application is valid we want to stay in DFU to receive application.
|
||||
NRF_LOG_DEBUG("A SoftDevice has just been activated. It's likely that an application will come immediately");
|
||||
result = ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_ERROR("Could not write settings.");
|
||||
result = ACTIVATION_ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (c) 2018 - 2020, 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_bootloader_fw_activation Firmware activation
|
||||
* @{
|
||||
* @ingroup nrf_bootloader
|
||||
*/
|
||||
|
||||
#ifndef NRF_BOOTLOADER_FW_ACTIVATION_H__
|
||||
#define NRF_BOOTLOADER_FW_ACTIVATION_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ACTIVATION_NONE, //!< No new update was found.
|
||||
ACTIVATION_SUCCESS, //!< Update was successfully activated.
|
||||
ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE, //!< Update was successfully activated, but there might be additional update(s) to be transferred.
|
||||
ACTIVATION_ERROR, //!< Activation of an update failed.
|
||||
} nrf_bootloader_fw_activation_result_t;
|
||||
|
||||
/** @brief Function for activating a firmware received during DFU.
|
||||
*
|
||||
* @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 initiates a reboot to activate
|
||||
* the new bootloader.
|
||||
*
|
||||
* @retval ACTIVATION_NONE If no update was found.
|
||||
* @retval ACTIVATION_SUCCESS If the firmware update was successfully activated.
|
||||
* @retval ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE If the firmware update was successfully activated,
|
||||
* but there are likely more updates to be transferred.
|
||||
* @retval ACTIVATION_ERROR If the firmware update could not be activated.
|
||||
*/
|
||||
nrf_bootloader_fw_activation_result_t nrf_bootloader_fw_activate(void);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_BOOTLOADER_FW_ACTIVATION_H__
|
||||
|
||||
/** @} */
|
||||
91
components/libraries/bootloader/nrf_bootloader_info.c
Normal file
91
components/libraries/bootloader/nrf_bootloader_info.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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"
|
||||
#include "nrf_dfu_types.h"
|
||||
#include "nrf_nvmc.h"
|
||||
|
||||
#define UICR_BOOTLOADER_ADDR 0x10001014
|
||||
|
||||
/** @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(UICR_BOOTLOADER_ADDR)))
|
||||
= BOOTLOADER_START_ADDR;
|
||||
#pragma pop
|
||||
#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
|
||||
volatile uint32_t m_uicr_bootloader_start_address __attribute__ ((section(".uicr_bootloader_start_address")))
|
||||
= BOOTLOADER_START_ADDR;
|
||||
#elif defined ( __ICCARM__ )
|
||||
__root const uint32_t m_uicr_bootloader_start_address @ UICR_BOOTLOADER_ADDR
|
||||
= BOOTLOADER_START_ADDR;
|
||||
#endif
|
||||
|
||||
void nrf_bootloader_mbr_addrs_populate(void)
|
||||
{
|
||||
if (*(const uint32_t *)MBR_BOOTLOADER_ADDR == 0xFFFFFFFF)
|
||||
{
|
||||
nrf_nvmc_write_word(MBR_BOOTLOADER_ADDR, BOOTLOADER_START_ADDR);
|
||||
}
|
||||
if (*(const uint32_t *)MBR_PARAM_PAGE_ADDR == 0xFFFFFFFF)
|
||||
{
|
||||
nrf_nvmc_write_word(MBR_PARAM_PAGE_ADDR, NRF_MBR_PARAMS_PAGE_ADDRESS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nrf_bootloader_debug_port_disable(void)
|
||||
{
|
||||
if (NRF_UICR->APPROTECT != 0x0)
|
||||
{
|
||||
nrf_nvmc_write_word((uint32_t)&NRF_UICR->APPROTECT, 0x0);
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
#if (!defined (NRF52810_XXAA) && !defined (NRF52811_XXAA) && !defined (NRF52832_XXAA) && !defined (NRF52832_XXAB))
|
||||
if (NRF_UICR->DEBUGCTRL != 0x0)
|
||||
{
|
||||
nrf_nvmc_write_word((uint32_t)&NRF_UICR->DEBUGCTRL, 0x0);
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
210
components/libraries/bootloader/nrf_bootloader_info.h
Normal file
210
components/libraries/bootloader/nrf_bootloader_info.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_bootloader_info Bootloader Information
|
||||
* @{
|
||||
* @ingroup nrf_bootloader
|
||||
*/
|
||||
|
||||
#ifndef NRF_BOOTLOADER_INFO_H__
|
||||
#define NRF_BOOTLOADER_INFO_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "app_util.h"
|
||||
#include "nrf.h"
|
||||
#include "nrf_mbr.h"
|
||||
|
||||
/** @brief Macro for getting the start address of the bootloader 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.
|
||||
*/
|
||||
#ifndef BOOTLOADER_START_ADDR
|
||||
#if (__LINT__ == 1)
|
||||
#define BOOTLOADER_START_ADDR (0x3AC00)
|
||||
#elif defined(CODE_START)
|
||||
#define BOOTLOADER_START_ADDR (CODE_START)
|
||||
#else
|
||||
#error Not a valid compiler/linker for BOOTLOADER_START_ADDR.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Macro for getting the size of the bootloader image.
|
||||
*/
|
||||
#ifndef BOOTLOADER_SIZE
|
||||
#if (__LINT__ == 1)
|
||||
#define BOOTLOADER_SIZE (0x6000)
|
||||
#elif defined ( NRF51 )
|
||||
#define BOOTLOADER_SIZE (BOOTLOADER_SETTINGS_ADDRESS - BOOTLOADER_START_ADDR)
|
||||
#elif defined( NRF52_SERIES )
|
||||
#define BOOTLOADER_SIZE (NRF_MBR_PARAMS_PAGE_ADDRESS - BOOTLOADER_START_ADDR)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The following macros are for accessing the SoftDevice information structure,
|
||||
// which is found inside the SoftDevice binary.
|
||||
|
||||
/** @brief Macro for converting an offset inside the SoftDevice information struct to an absolute address.
|
||||
*/
|
||||
#define SD_INFO_ABS_OFFSET_GET(baseaddr, offset) ((baseaddr) + (SOFTDEVICE_INFO_STRUCT_OFFSET) + (offset))
|
||||
|
||||
/** @brief Macros for reading a byte or a word at a particular offset inside a SoftDevice information struct.
|
||||
* Use MBR_SIZE as baseaddr when the SoftDevice is installed just above the MBR (the usual case).
|
||||
*/
|
||||
#define SD_OFFSET_GET_UINT32(baseaddr, offset) (*((uint32_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset)))
|
||||
#define SD_OFFSET_GET_UINT16(baseaddr, offset) (*((uint16_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset)))
|
||||
#define SD_OFFSET_GET_UINT8(baseaddr, offset) (*((uint8_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset)))
|
||||
|
||||
|
||||
#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD)
|
||||
#include "nrf_sdm.h"
|
||||
#else
|
||||
/** @brief The offset inside the SoftDevice at which the information struct is placed.
|
||||
* To see the layout of the information struct, see the SoftDevice specification.
|
||||
*/
|
||||
#define SOFTDEVICE_INFO_STRUCT_OFFSET (0x2000)
|
||||
|
||||
#define SD_INFO_STRUCT_SIZE(baseaddr) SD_OFFSET_GET_UINT8(baseaddr, 0x00)
|
||||
|
||||
/** @brief Macro for reading the size of a SoftDevice at a given base address.
|
||||
*/
|
||||
#ifndef SD_SIZE_GET
|
||||
#define SD_SIZE_GET(baseaddr) SD_OFFSET_GET_UINT32(baseaddr, 0x08)
|
||||
#endif
|
||||
|
||||
/** @brief Macro for reading the version of a SoftDevice at a given base address.
|
||||
* This expression checks the length of the information struct to see if the version is present.
|
||||
* The version number is constructed like this:
|
||||
* major_version * 1000000 + minor_version * 1000 + bugfix_version
|
||||
*/
|
||||
#ifndef SD_VERSION_GET
|
||||
#define SD_VERSION_GET(baseaddr) ((SD_INFO_STRUCT_SIZE(baseaddr) > (0x14)) \
|
||||
? SD_OFFSET_GET_UINT32(baseaddr, 0x14) \
|
||||
: 0)
|
||||
#endif
|
||||
|
||||
/** @brief Defines a macro for retrieving the actual SoftDevice ID from a given base address. Use
|
||||
* @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the
|
||||
* usual case). */
|
||||
#ifndef SD_ID_GET
|
||||
#define SD_ID_GET(baseaddr) ((SD_INFO_STRUCT_SIZE(baseaddr) > 0x10) \
|
||||
? SD_OFFSET_GET_UINT32(baseaddr, 0x10) : 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Macro for reading the magic number of a SoftDevice at a given base address.
|
||||
*/
|
||||
#ifndef SD_MAGIC_NUMBER_GET
|
||||
#define SD_MAGIC_NUMBER_GET(baseaddr) SD_OFFSET_GET_UINT32(baseaddr, 0x04)
|
||||
#endif
|
||||
|
||||
/** @brief Macro for getting the absolute address of the magic number.
|
||||
*/
|
||||
#define SD_MAGIC_NUMBER_ABS_OFFSET_GET(baseaddr) SD_INFO_ABS_OFFSET_GET(baseaddr, 0x04)
|
||||
|
||||
/** @brief The number present at a specific location in all SoftDevices.
|
||||
*/
|
||||
#define SD_MAGIC_NUMBER ((uint32_t)0x51B1E5DB)
|
||||
|
||||
/** @brief Whether a SoftDevice is at its regular location.
|
||||
*/
|
||||
#ifndef SD_PRESENT
|
||||
#define SD_PRESENT ((SD_MAGIC_NUMBER_GET(MBR_SIZE)) == (SD_MAGIC_NUMBER))
|
||||
#endif
|
||||
|
||||
/** @brief The multiplier for the major version of the SoftDevice. See \ref SD_VERSION_GET
|
||||
*/
|
||||
#define SD_MAJOR_VERSION_MULTIPLIER (1000000)
|
||||
|
||||
/** @brief Read the major version of the SoftDevice from the raw version number. See \ref SD_VERSION_GET.
|
||||
*/
|
||||
#define SD_MAJOR_VERSION_EXTRACT(raw_version) ((raw_version)/SD_MAJOR_VERSION_MULTIPLIER)
|
||||
|
||||
|
||||
#define BOOTLOADER_DFU_GPREGRET_MASK (0xF8) /**< Mask for GPGPREGRET bits used for the magic pattern written to GPREGRET register to signal between main app and DFU. */
|
||||
#define BOOTLOADER_DFU_GPREGRET (0xB0) /**< Magic pattern written to GPREGRET register to signal between main app and DFU. The 3 lower bits are assumed to be used for signalling purposes.*/
|
||||
#define BOOTLOADER_DFU_START_BIT_MASK (0x01) /**< Bit mask to signal from main application to enter DFU mode using a buttonless service. */
|
||||
|
||||
#define BOOTLOADER_DFU_GPREGRET2_MASK (0xF8) /**< Mask for GPGPREGRET2 bits used for the magic pattern written to GPREGRET2 register to signal between main app and DFU. */
|
||||
#define BOOTLOADER_DFU_GPREGRET2 (0xA8) /**< Magic pattern written to GPREGRET2 register to signal between main app and DFU. The 3 lower bits are assumed to be used for signalling purposes.*/
|
||||
#define BOOTLOADER_DFU_SKIP_CRC_BIT_MASK (0x01) /**< Bit mask to signal from main application that CRC-check is not needed for image verification. */
|
||||
|
||||
|
||||
#define BOOTLOADER_DFU_START (BOOTLOADER_DFU_GPREGRET | BOOTLOADER_DFU_START_BIT_MASK) /**< Magic number to signal that bootloader should enter DFU mode because of signal from Buttonless DFU in main app.*/
|
||||
#define BOOTLOADER_DFU_SKIP_CRC (BOOTLOADER_DFU_GPREGRET2 | BOOTLOADER_DFU_SKIP_CRC_BIT_MASK) /**< Magic number to signal that CRC can be skipped due to low power modes.*/
|
||||
|
||||
|
||||
/** @brief Macro based on @c NRF_DFU_DEBUG_VERSION that can be checked for true/false instead of defined/not defined.
|
||||
*/
|
||||
#ifndef NRF_DFU_DEBUG
|
||||
#ifdef NRF_DFU_DEBUG_VERSION
|
||||
#define NRF_DFU_DEBUG 1
|
||||
#else
|
||||
#define NRF_DFU_DEBUG 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** @brief Function for populating addresses in the MBR code page.
|
||||
*
|
||||
* This function writes two words to flash if the flash is 0xFFFFFFFF. This is done in code because
|
||||
* doing this through the hex file interferes with flashing algorithms. See nrf_mbr.h.
|
||||
*/
|
||||
void nrf_bootloader_mbr_addrs_populate(void);
|
||||
|
||||
/** @brief Function for checking if the debug port access is disabled.
|
||||
*
|
||||
* If the debug port access is enabled, disable it. This function checks and writes to the UICR
|
||||
* registers APPROTECT and DEBUGCTRL.
|
||||
*/
|
||||
void nrf_bootloader_debug_port_disable(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #ifndef NRF_BOOTLOADER_INFO_H__
|
||||
/** @} */
|
||||
121
components/libraries/bootloader/nrf_bootloader_wdt.c
Normal file
121
components/libraries/bootloader/nrf_bootloader_wdt.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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_wdt.h"
|
||||
#include "nrf_wdt.h"
|
||||
#include "nrf_bootloader_dfu_timers.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_bootloader_wdt
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
static void wdt_feed(void)
|
||||
{
|
||||
if (nrf_wdt_started())
|
||||
{
|
||||
for (nrf_wdt_rr_register_t i = NRF_WDT_RR0; i < NRF_WDT_RR7; i++)
|
||||
{
|
||||
if (nrf_wdt_reload_request_is_enabled(i))
|
||||
{
|
||||
nrf_wdt_reload_request_set(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void wdt_feed_timer_handler(void)
|
||||
{
|
||||
NRF_LOG_INFO("Internal feed");
|
||||
wdt_feed();
|
||||
}
|
||||
|
||||
|
||||
void WDT_IRQHandler(void)
|
||||
{
|
||||
nrf_wdt_event_clear(NRF_WDT_EVENT_TIMEOUT);
|
||||
NRF_LOG_FINAL_FLUSH();
|
||||
}
|
||||
|
||||
#define MAX_FLASH_OP_TIME_TICKS 3200 // ~100 ms
|
||||
|
||||
void nrf_bootloader_wdt_init(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (nrf_wdt_started())
|
||||
{
|
||||
uint32_t wdt_ticks = nrf_wdt_reload_value_get();
|
||||
|
||||
NRF_LOG_INFO("WDT enabled CRV:%d ticks", wdt_ticks);
|
||||
|
||||
//wdt_ticks must be reduced to feed the watchdog before the timeout.
|
||||
uint32_t reduced_timeout_ticks = MAX((int32_t)wdt_ticks - MAX_FLASH_OP_TIME_TICKS,
|
||||
NRF_BOOTLOADER_MIN_TIMEOUT_TICKS);
|
||||
|
||||
/* initial watchdog feed */
|
||||
wdt_feed();
|
||||
|
||||
NRF_LOG_INFO("Starting a timer (%d ticks) for feeding watchdog.", reduced_timeout_ticks);
|
||||
nrf_bootloader_wdt_feed_timer_start(reduced_timeout_ticks, wdt_feed_timer_handler);
|
||||
|
||||
NVIC_EnableIRQ(WDT_IRQn);
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_INFO("WDT is not enabled");
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void nrf_bootloader_wdt_feed(void)
|
||||
{
|
||||
if (nrf_wdt_started())
|
||||
{
|
||||
wdt_feed();
|
||||
}
|
||||
}
|
||||
79
components/libraries/bootloader/nrf_bootloader_wdt.h
Normal file
79
components/libraries/bootloader/nrf_bootloader_wdt.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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.
|
||||
*
|
||||
*/
|
||||
#ifndef NRF_BOOTLOADER_WDT_H
|
||||
#define NRF_BOOTLOADER_WDT_H
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_bootloader_wdt Automated feeding of the watchdog
|
||||
* @{
|
||||
* @ingroup nrf_bootloader
|
||||
* @brief Module that keeps the WDT from timing out if the WDT has been started in the application.
|
||||
*/
|
||||
|
||||
#include "sdk_errors.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**
|
||||
* @brief Function for checking whether the WDT peripheral is started and for getting its configuration.
|
||||
*
|
||||
* The module uses a timer to start regular feeding of the watchdog. Timer interval
|
||||
* is chosen based on watchdog settings. When @ref nrf_bootloader_wdt_feed is called, internal
|
||||
* feeding is stopped assuming that the application takes responsibity of watchdog feeding.
|
||||
* However, if @ref NRF_BL_WDT_MAX_SCHEDULER_LATENCY_MS or the watchdog is configured to
|
||||
* run during sleep, then internal feeding (from timeout handler context) is kept active.
|
||||
*/
|
||||
void nrf_bootloader_wdt_init(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for feeding the watchdog (if active).
|
||||
*/
|
||||
void nrf_bootloader_wdt_feed(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif //NRF_BOOTLOADER_WDT_H
|
||||
273
components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c
Normal file
273
components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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_serial.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
#include "nrf_dfu_handling_error.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_serial
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
#define NRF_SERIAL_OPCODE_SIZE (sizeof(uint8_t))
|
||||
|
||||
#if defined(NRF_DFU_PROTOCOL_REDUCED) && NRF_DFU_PROTOCOL_REDUCED
|
||||
#error Serial DFU (UART and USB) cannot function with the reduced protocol set.
|
||||
#endif
|
||||
|
||||
static uint32_t response_ext_err_payload_add(uint8_t * p_buffer, uint32_t buf_offset)
|
||||
{
|
||||
p_buffer[buf_offset] = ext_error_get();
|
||||
(void) ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void response_send(nrf_dfu_serial_t * p_transport,
|
||||
nrf_dfu_response_t const * p_response)
|
||||
{
|
||||
uint8_t index = 0;
|
||||
uint8_t * p_serialized_rsp = p_transport->p_rsp_buf;
|
||||
|
||||
NRF_LOG_DEBUG("Sending Response: [0x%01x, 0x%01x]", p_response->request, p_response->result);
|
||||
|
||||
p_serialized_rsp[index++] = NRF_DFU_OP_RESPONSE;
|
||||
p_serialized_rsp[index++] = p_response->request;
|
||||
p_serialized_rsp[index++] = (uint8_t)(p_response->result);
|
||||
|
||||
if (p_response->result == NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
switch (p_response->request)
|
||||
{
|
||||
case NRF_DFU_OP_PROTOCOL_VERSION:
|
||||
{
|
||||
p_serialized_rsp[index] = p_response->protocol.version;
|
||||
index += sizeof(uint8_t);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_HARDWARE_VERSION:
|
||||
{
|
||||
index += uint32_encode(p_response->hardware.part, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->hardware.variant, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->hardware.memory.rom_size, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->hardware.memory.ram_size, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->hardware.memory.rom_page_size, &p_serialized_rsp[index]);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_FIRMWARE_VERSION:
|
||||
{
|
||||
p_serialized_rsp[index++] = p_response->firmware.type;
|
||||
index += uint32_encode(p_response->firmware.version, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->firmware.addr, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->firmware.len, &p_serialized_rsp[index]);
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_CRC_GET:
|
||||
index += uint32_encode(p_response->crc.offset, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->crc.crc, &p_serialized_rsp[index]);
|
||||
break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_SELECT:
|
||||
index += uint32_encode(p_response->select.max_size, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->select.offset, &p_serialized_rsp[index]);
|
||||
index += uint32_encode(p_response->select.crc, &p_serialized_rsp[index]);
|
||||
break;
|
||||
|
||||
case NRF_DFU_OP_MTU_GET:
|
||||
index += uint16_encode(p_response->mtu.size, &p_serialized_rsp[index]);
|
||||
break;
|
||||
|
||||
case NRF_DFU_OP_PING:
|
||||
p_serialized_rsp[index] = p_response->ping.id;
|
||||
index += sizeof(uint8_t);
|
||||
break;
|
||||
|
||||
default:
|
||||
// no implementation
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (p_response->result == NRF_DFU_RES_CODE_EXT_ERROR)
|
||||
{
|
||||
index += response_ext_err_payload_add(p_serialized_rsp, index);
|
||||
}
|
||||
|
||||
if (index > NRF_SERIAL_MAX_RESPONSE_SIZE)
|
||||
{
|
||||
NRF_LOG_ERROR("Message is larger than expected.");
|
||||
}
|
||||
|
||||
// Send response.
|
||||
if (p_transport->rsp_func((uint8_t const *)(p_serialized_rsp), index) != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed to send data over serial interface!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dfu_req_handler_rsp_clbk(nrf_dfu_response_t * p_res, void * p_context)
|
||||
{
|
||||
nrf_dfu_serial_t * p_transport = (nrf_dfu_serial_t *)(p_context);
|
||||
|
||||
if (p_res->result != NRF_DFU_RES_CODE_SUCCESS)
|
||||
{
|
||||
NRF_LOG_WARNING("DFU request completed with result: 0x%x", p_res->result);
|
||||
}
|
||||
|
||||
switch (p_res->request)
|
||||
{
|
||||
default:
|
||||
/* Reply normally.
|
||||
* Make sure to reply to NRF_DFU_OP_OBJECT_CREATE when running DFU over serial,
|
||||
* otherwise the transfer might run very slow, without an apparent reason.
|
||||
*/
|
||||
break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_WRITE:
|
||||
{
|
||||
p_transport->pkt_notif_target_count--;
|
||||
|
||||
if ( (p_transport->pkt_notif_target == 0)
|
||||
|| (p_transport->pkt_notif_target_count != 0))
|
||||
{
|
||||
/* Do not reply to _OBJECT_WRITE messages. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reply with a CRC message and reset the packet counter. */
|
||||
p_transport->pkt_notif_target_count = p_transport->pkt_notif_target;
|
||||
|
||||
p_res->request = NRF_DFU_OP_CRC_GET;
|
||||
p_res->crc.offset = p_res->write.offset;
|
||||
p_res->crc.crc = p_res->write.crc;
|
||||
} break;
|
||||
}
|
||||
|
||||
response_send(p_transport, p_res);
|
||||
}
|
||||
|
||||
|
||||
void nrf_dfu_serial_on_packet_received(nrf_dfu_serial_t * p_transport,
|
||||
uint8_t const * p_data,
|
||||
uint32_t length)
|
||||
{
|
||||
uint8_t const * p_payload = &p_data[NRF_SERIAL_OPCODE_SIZE];
|
||||
uint16_t const payload_len = (length - NRF_SERIAL_OPCODE_SIZE);
|
||||
|
||||
nrf_dfu_request_t request =
|
||||
{
|
||||
.request = (nrf_dfu_op_t)(p_data[0]),
|
||||
.callback.response = dfu_req_handler_rsp_clbk,
|
||||
.p_context = p_transport
|
||||
};
|
||||
|
||||
bool buf_free = true;
|
||||
|
||||
switch (request.request)
|
||||
{
|
||||
case NRF_DFU_OP_FIRMWARE_VERSION:
|
||||
{
|
||||
request.firmware.image_number = p_payload[0];
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_RECEIPT_NOTIF_SET:
|
||||
{
|
||||
NRF_LOG_DEBUG("Set receipt notif target: %d", p_transport->pkt_notif_target);
|
||||
|
||||
p_transport->pkt_notif_target = uint16_decode(&p_payload[0]);
|
||||
p_transport->pkt_notif_target_count = p_transport->pkt_notif_target;
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_SELECT:
|
||||
{
|
||||
request.select.object_type = p_payload[0];
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_CREATE:
|
||||
{
|
||||
// Reset the packet receipt notification on create object
|
||||
p_transport->pkt_notif_target_count = p_transport->pkt_notif_target;
|
||||
|
||||
request.create.object_type = p_payload[0];
|
||||
request.create.object_size = uint32_decode(&p_payload[1]);
|
||||
|
||||
if (request.create.object_type == NRF_DFU_OBJ_TYPE_COMMAND)
|
||||
{
|
||||
/* Activity on the current transport. Close all except the current one. */
|
||||
(void) nrf_dfu_transports_close(p_transport->p_low_level_transport);
|
||||
}
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_OBJECT_WRITE:
|
||||
{
|
||||
// Buffer will be freed asynchronously
|
||||
buf_free = false;
|
||||
|
||||
request.write.p_data = p_payload;
|
||||
request.write.len = payload_len;
|
||||
request.callback.write = p_transport->payload_free_func;
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_MTU_GET:
|
||||
{
|
||||
NRF_LOG_DEBUG("Received serial mtu");
|
||||
request.mtu.size = p_transport->mtu;
|
||||
} break;
|
||||
|
||||
case NRF_DFU_OP_PING:
|
||||
{
|
||||
NRF_LOG_DEBUG("Received ping %d", p_payload[0]);
|
||||
request.ping.id = p_payload[0];
|
||||
} break;
|
||||
|
||||
default:
|
||||
/* Do nothing. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf_free)
|
||||
{
|
||||
p_transport->payload_free_func((void *)(p_payload));
|
||||
}
|
||||
|
||||
ret_code_t ret_code = nrf_dfu_req_handler_on_req(&request);
|
||||
ASSERT(ret_code == NRF_SUCCESS);
|
||||
}
|
||||
111
components/libraries/bootloader/serial_dfu/nrf_dfu_serial.h
Normal file
111
components/libraries/bootloader/serial_dfu/nrf_dfu_serial.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (c) 2017 - 2020, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NRF_DFU_SERIAL_H__
|
||||
#define NRF_DFU_SERIAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdk_errors.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
#include "nrf_dfu_transport.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_dfu_serial DFU Serial transports shared part
|
||||
* @{
|
||||
* @ingroup nrf_dfu
|
||||
* @brief Shared part of Device Firmware Update (DFU) transport layers using serial interface (UART, USB CDC ACM).
|
||||
*
|
||||
* @defgroup nrf_dfu_serial_uart DFU Serial UART transport
|
||||
* @ingroup nrf_dfu_serial
|
||||
* @brief Configuration for Device Firmware Update (DFU) transport layer using UART.
|
||||
*
|
||||
* @defgroup nrf_dfu_serial_usb DFU Serial USB CDC ACM transport
|
||||
* @ingroup nrf_dfu_serial
|
||||
* @brief Configuration for Device Firmware Update (DFU) transport layer using USB CDC ACM.
|
||||
*
|
||||
*/
|
||||
|
||||
#define NRF_SERIAL_MAX_RESPONSE_SIZE (sizeof(nrf_dfu_response_t))
|
||||
|
||||
/**
|
||||
* Prototype for function for sending response over serial DFU transport.
|
||||
*/
|
||||
typedef ret_code_t (*nrf_serial_rsp_func_t)(uint8_t const * p_data, uint32_t length);
|
||||
|
||||
/**
|
||||
* Prototype for function for freeing RX buffer.
|
||||
*
|
||||
* Function is called when input data is processed.
|
||||
*/
|
||||
typedef void (*nrf_serial_rx_buf_free_func_t)(void * p_buf);
|
||||
|
||||
|
||||
/**@brief DFU serial transport layer state.
|
||||
*
|
||||
* @details This structure contains status information related to the serial transport layer type.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t pkt_notif_target;
|
||||
uint16_t pkt_notif_target_count;
|
||||
nrf_serial_rsp_func_t rsp_func;
|
||||
nrf_serial_rx_buf_free_func_t payload_free_func;
|
||||
uint32_t mtu;
|
||||
uint8_t * p_rsp_buf;
|
||||
nrf_dfu_transport_t const * p_low_level_transport;
|
||||
} nrf_dfu_serial_t;
|
||||
|
||||
void nrf_dfu_serial_on_packet_received(nrf_dfu_serial_t * p_transport,
|
||||
uint8_t const * p_data,
|
||||
uint32_t length);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_DFU_SERIAL_H__
|
||||
238
components/libraries/bootloader/serial_dfu/nrf_dfu_serial_uart.c
Normal file
238
components/libraries/bootloader/serial_dfu/nrf_dfu_serial_uart.c
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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_serial.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "boards.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "nrf_dfu_transport.h"
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
#include "slip.h"
|
||||
#include "nrf_balloc.h"
|
||||
#include "nrf_drv_uart.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_serial_uart
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_dfu_serial_uart DFU Serial UART transport
|
||||
* @ingroup nrf_dfu
|
||||
* @brief Device Firmware Update (DFU) transport layer using UART.
|
||||
*/
|
||||
|
||||
#define NRF_SERIAL_OPCODE_SIZE (sizeof(uint8_t))
|
||||
#define NRF_UART_MAX_RESPONSE_SIZE_SLIP (2 * NRF_SERIAL_MAX_RESPONSE_SIZE + 1)
|
||||
#define RX_BUF_SIZE (64) //to get 64bytes payload
|
||||
#define OPCODE_OFFSET (sizeof(uint32_t) - NRF_SERIAL_OPCODE_SIZE)
|
||||
#define DATA_OFFSET (OPCODE_OFFSET + NRF_SERIAL_OPCODE_SIZE)
|
||||
#define UART_SLIP_MTU (2 * (RX_BUF_SIZE + 1) + 1)
|
||||
#define BALLOC_BUF_SIZE ((CEIL_DIV((RX_BUF_SIZE+OPCODE_SIZE),sizeof(uint32_t))*sizeof(uint32_t)))
|
||||
|
||||
NRF_BALLOC_DEF(m_payload_pool, (UART_SLIP_MTU + 1), NRF_DFU_SERIAL_UART_RX_BUFFERS);
|
||||
|
||||
static nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0);
|
||||
static uint8_t m_rx_byte;
|
||||
|
||||
static nrf_dfu_serial_t m_serial;
|
||||
static slip_t m_slip;
|
||||
static uint8_t m_rsp_buf[NRF_UART_MAX_RESPONSE_SIZE_SLIP];
|
||||
static bool m_active;
|
||||
|
||||
static nrf_dfu_observer_t m_observer;
|
||||
|
||||
static uint32_t uart_dfu_transport_init(nrf_dfu_observer_t observer);
|
||||
static uint32_t uart_dfu_transport_close(nrf_dfu_transport_t const * p_exception);
|
||||
|
||||
DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const uart_dfu_transport) =
|
||||
{
|
||||
.init_func = uart_dfu_transport_init,
|
||||
.close_func = uart_dfu_transport_close,
|
||||
};
|
||||
|
||||
static void payload_free(void * p_buf)
|
||||
{
|
||||
uint8_t * p_buf_root = (uint8_t *)p_buf - DATA_OFFSET; //pointer is shifted to point to data
|
||||
nrf_balloc_free(&m_payload_pool, p_buf_root);
|
||||
}
|
||||
|
||||
static ret_code_t rsp_send(uint8_t const * p_data, uint32_t length)
|
||||
{
|
||||
uint32_t slip_len;
|
||||
(void) slip_encode(m_rsp_buf, (uint8_t *)p_data, length, &slip_len);
|
||||
|
||||
return nrf_drv_uart_tx(&m_uart, m_rsp_buf, slip_len);
|
||||
}
|
||||
|
||||
static __INLINE void on_rx_complete(nrf_dfu_serial_t * p_transport, uint8_t * p_data, uint8_t len)
|
||||
{
|
||||
ret_code_t ret_code = NRF_ERROR_TIMEOUT;
|
||||
|
||||
// Check if there is byte to process. Zero length transfer means that RXTO occured.
|
||||
if (len)
|
||||
{
|
||||
ret_code = slip_decode_add_byte(&m_slip, p_data[0]);
|
||||
}
|
||||
|
||||
(void) nrf_drv_uart_rx(&m_uart, &m_rx_byte, 1);
|
||||
|
||||
if (ret_code == NRF_SUCCESS)
|
||||
{
|
||||
nrf_dfu_serial_on_packet_received(p_transport,
|
||||
(uint8_t const *)m_slip.p_buffer,
|
||||
m_slip.current_index);
|
||||
|
||||
uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool);
|
||||
if (p_rx_buf == NULL)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed to allocate buffer");
|
||||
return;
|
||||
}
|
||||
NRF_LOG_INFO("Allocated buffer %x", p_rx_buf);
|
||||
// reset the slip decoding
|
||||
m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET];
|
||||
m_slip.current_index = 0;
|
||||
m_slip.state = SLIP_STATE_DECODING;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context)
|
||||
{
|
||||
switch (p_event->type)
|
||||
{
|
||||
case NRF_DRV_UART_EVT_RX_DONE:
|
||||
on_rx_complete((nrf_dfu_serial_t*)p_context,
|
||||
p_event->data.rxtx.p_data,
|
||||
p_event->data.rxtx.bytes);
|
||||
break;
|
||||
|
||||
case NRF_DRV_UART_EVT_ERROR:
|
||||
APP_ERROR_HANDLER(p_event->data.error.error_mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No action.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t uart_dfu_transport_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
|
||||
if (m_active)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("serial_dfu_transport_init()");
|
||||
|
||||
m_observer = observer;
|
||||
|
||||
err_code = nrf_balloc_init(&m_payload_pool);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool);
|
||||
|
||||
m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET];
|
||||
m_slip.current_index = 0;
|
||||
m_slip.buffer_len = UART_SLIP_MTU;
|
||||
m_slip.state = SLIP_STATE_DECODING;
|
||||
|
||||
m_serial.rsp_func = rsp_send;
|
||||
m_serial.payload_free_func = payload_free;
|
||||
m_serial.mtu = UART_SLIP_MTU;
|
||||
m_serial.p_rsp_buf = &m_rsp_buf[NRF_UART_MAX_RESPONSE_SIZE_SLIP -
|
||||
NRF_SERIAL_MAX_RESPONSE_SIZE];
|
||||
m_serial.p_low_level_transport = &uart_dfu_transport;
|
||||
|
||||
nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
|
||||
|
||||
uart_config.pseltxd = TX_PIN_NUMBER;
|
||||
uart_config.pselrxd = RX_PIN_NUMBER;
|
||||
uart_config.pselcts = CTS_PIN_NUMBER;
|
||||
uart_config.pselrts = RTS_PIN_NUMBER;
|
||||
uart_config.hwfc = NRF_DFU_SERIAL_UART_USES_HWFC ?
|
||||
NRF_UART_HWFC_ENABLED : NRF_UART_HWFC_DISABLED;
|
||||
uart_config.p_context = &m_serial;
|
||||
|
||||
err_code = nrf_drv_uart_init(&m_uart, &uart_config, uart_event_handler);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed initializing uart");
|
||||
return err_code;
|
||||
}
|
||||
|
||||
err_code = nrf_drv_uart_rx(&m_uart, &m_rx_byte, 1);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed initializing rx");
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("serial_dfu_transport_init() completed");
|
||||
|
||||
m_active = true;
|
||||
|
||||
if (m_observer)
|
||||
{
|
||||
m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED);
|
||||
}
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t uart_dfu_transport_close(nrf_dfu_transport_t const * p_exception)
|
||||
{
|
||||
if ((m_active == true) && (p_exception != &uart_dfu_transport))
|
||||
{
|
||||
nrf_drv_uart_uninit(&m_uart);
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
368
components/libraries/bootloader/serial_dfu/nrf_dfu_serial_usb.c
Normal file
368
components/libraries/bootloader/serial_dfu/nrf_dfu_serial_usb.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/**
|
||||
* Copyright (c) 2016 - 2020, 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 <string.h>
|
||||
#include "nrf_dfu_req_handler.h"
|
||||
#include "nrf_dfu_transport.h"
|
||||
#include "slip.h"
|
||||
#include "nrf_balloc.h"
|
||||
#include "nrf_drv_power.h"
|
||||
#include "nrf_drv_clock.h"
|
||||
#include "nrf_drv_usbd.h"
|
||||
#include "nrf_dfu_serial.h"
|
||||
#include "app_scheduler.h"
|
||||
#include "app_usbd.h"
|
||||
#include "app_usbd_cdc_acm.h"
|
||||
#include "app_usbd_core.h"
|
||||
#include "app_usbd_string_desc.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "app_usbd_serial_num.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_serial_usb
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup nrf_dfu_serial_usb DFU Serial USB CDC ACM transport
|
||||
* @ingroup nrf_dfu
|
||||
* @brief Device Firmware Update (DFU) transport layer using USB CDC ACM.
|
||||
*/
|
||||
|
||||
#define NRF_SERIAL_OPCODE_SIZE (sizeof(uint8_t))
|
||||
|
||||
#define NRF_USB_MAX_RESPONSE_SIZE_SLIP (2 * NRF_SERIAL_MAX_RESPONSE_SIZE + 1)
|
||||
|
||||
#define RX_BUF_SIZE (1024)
|
||||
#define SLIP_MTU (2 * (RX_BUF_SIZE + 1) + 1)
|
||||
#define OPCODE_OFFSET (sizeof(uint32_t) - NRF_SERIAL_OPCODE_SIZE)
|
||||
#define DATA_OFFSET (OPCODE_OFFSET + NRF_SERIAL_OPCODE_SIZE)
|
||||
|
||||
#define CDC_ACM_COMM_INTERFACE 0
|
||||
#define CDC_ACM_COMM_EPIN NRF_DRV_USBD_EPIN2
|
||||
#define CDC_ACM_DATA_INTERFACE 1
|
||||
#define CDC_ACM_DATA_EPIN NRF_DRV_USBD_EPIN1
|
||||
#define CDC_ACM_DATA_EPOUT NRF_DRV_USBD_EPOUT1
|
||||
|
||||
/**
|
||||
* @brief Enable power USB detection
|
||||
*
|
||||
* Configure if example supports USB port connection
|
||||
*/
|
||||
#ifndef USBD_POWER_DETECTION
|
||||
#define USBD_POWER_DETECTION true
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Interfaces list passed to @ref APP_USBD_CDC_ACM_GLOBAL_DEF
|
||||
* */
|
||||
#define CDC_ACM_INTERFACES_CONFIG() \
|
||||
APP_USBD_CDC_ACM_CONFIG(CDC_ACM_COMM_INTERFACE, \
|
||||
CDC_ACM_COMM_EPIN, \
|
||||
CDC_ACM_DATA_INTERFACE, \
|
||||
CDC_ACM_DATA_EPIN, \
|
||||
CDC_ACM_DATA_EPOUT)
|
||||
|
||||
/*lint -save -e26 -e64 -e505 -e651 */
|
||||
static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
|
||||
app_usbd_cdc_acm_user_event_t event);
|
||||
|
||||
/**@brief CDC_ACM class instance. */
|
||||
APP_USBD_CDC_ACM_GLOBAL_DEF(m_app_cdc_acm,
|
||||
cdc_acm_user_ev_handler,
|
||||
CDC_ACM_COMM_INTERFACE,
|
||||
CDC_ACM_DATA_INTERFACE,
|
||||
CDC_ACM_COMM_EPIN,
|
||||
CDC_ACM_DATA_EPIN,
|
||||
CDC_ACM_DATA_EPOUT,
|
||||
APP_USBD_CDC_COMM_PROTOCOL_NONE);
|
||||
/*lint -restore */
|
||||
|
||||
NRF_BALLOC_DEF(m_payload_pool, (SLIP_MTU+1), NRF_DFU_SERIAL_USB_RX_BUFFERS);
|
||||
|
||||
static nrf_dfu_serial_t m_serial;
|
||||
static slip_t m_slip;
|
||||
static uint8_t m_rsp_buf[NRF_USB_MAX_RESPONSE_SIZE_SLIP];
|
||||
static uint8_t m_rx_buf[NRF_DRV_USBD_EPSIZE];
|
||||
|
||||
static nrf_dfu_observer_t m_observer;
|
||||
|
||||
static uint32_t usb_dfu_transport_init(nrf_dfu_observer_t observer);
|
||||
static uint32_t usb_dfu_transport_close(nrf_dfu_transport_t const * p_exception);
|
||||
|
||||
|
||||
DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const usb_dfu_transport) =
|
||||
{
|
||||
.init_func = usb_dfu_transport_init,
|
||||
.close_func = usb_dfu_transport_close,
|
||||
};
|
||||
|
||||
|
||||
static void payload_free(void * p_buf)
|
||||
{
|
||||
uint8_t * p_buf_root = ((uint8_t *)(p_buf)) - DATA_OFFSET; //pointer is shifted to point to data
|
||||
nrf_balloc_free(&m_payload_pool, p_buf_root);
|
||||
}
|
||||
|
||||
|
||||
static ret_code_t rsp_send(uint8_t const * p_data, uint32_t length)
|
||||
{
|
||||
ASSERT(p_data);
|
||||
ASSERT(length != 0);
|
||||
|
||||
uint32_t slip_len;
|
||||
|
||||
// Cannot fail if inputs are non-NULL.
|
||||
(void) slip_encode(m_rsp_buf, (uint8_t *)(p_data), length, &slip_len);
|
||||
|
||||
return app_usbd_cdc_acm_write(&m_app_cdc_acm, m_rsp_buf, slip_len);
|
||||
}
|
||||
|
||||
|
||||
static void on_rx_complete(nrf_dfu_serial_t * p_transport, uint8_t * p_data, uint8_t len)
|
||||
{
|
||||
ret_code_t ret_code;
|
||||
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
{
|
||||
ret_code = slip_decode_add_byte(&m_slip, p_data[i]);
|
||||
if (ret_code != NRF_SUCCESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
nrf_dfu_serial_on_packet_received(p_transport,
|
||||
(uint8_t const *)(m_slip.p_buffer),
|
||||
m_slip.current_index);
|
||||
|
||||
uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool);
|
||||
if (p_rx_buf == NULL)
|
||||
{
|
||||
NRF_LOG_ERROR("Failed to allocate buffer!");
|
||||
return;
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("Allocated buffer %x", p_rx_buf);
|
||||
// reset the slip decoding
|
||||
m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET];
|
||||
m_slip.current_index = 0;
|
||||
m_slip.state = SLIP_STATE_DECODING;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief User event handler @ref app_usbd_cdc_acm_user_ev_handler_t (headphones)
|
||||
* */
|
||||
static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
|
||||
app_usbd_cdc_acm_user_event_t event)
|
||||
{
|
||||
ret_code_t ret_code;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
|
||||
{
|
||||
ret_code = app_usbd_cdc_acm_read(&m_app_cdc_acm, m_rx_buf, 1);
|
||||
NRF_LOG_WARNING("Could not read from CDC. Error: 0x%x.", ret_code);
|
||||
} break;
|
||||
|
||||
case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
|
||||
{
|
||||
do
|
||||
{
|
||||
on_rx_complete(&m_serial, m_rx_buf, 1);
|
||||
ret_code = app_usbd_cdc_acm_read(&m_app_cdc_acm, m_rx_buf, 1);
|
||||
} while (ret_code == NRF_SUCCESS);
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void usbd_dfu_transport_ev_handler(app_usbd_event_type_t event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case APP_USBD_EVT_STOPPED:
|
||||
app_usbd_disable();
|
||||
break;
|
||||
|
||||
case APP_USBD_EVT_POWER_DETECTED:
|
||||
NRF_LOG_INFO("USB power detected");
|
||||
if (!nrf_drv_usbd_is_enabled())
|
||||
{
|
||||
app_usbd_enable();
|
||||
}
|
||||
|
||||
if (m_observer)
|
||||
{
|
||||
m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED);
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_USBD_EVT_POWER_REMOVED:
|
||||
NRF_LOG_INFO("USB power removed");
|
||||
app_usbd_stop();
|
||||
if (m_observer)
|
||||
{
|
||||
m_observer(NRF_DFU_EVT_TRANSPORT_DEACTIVATED);
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_USBD_EVT_POWER_READY:
|
||||
NRF_LOG_INFO("USB ready");
|
||||
app_usbd_start();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void usbd_sched_event_handler(void * p_event_data, uint16_t event_size)
|
||||
{
|
||||
app_usbd_event_execute(p_event_data);
|
||||
}
|
||||
|
||||
|
||||
static void usbd_event_handler(app_usbd_internal_evt_t const * const p_event)
|
||||
{
|
||||
ret_code_t ret_code;
|
||||
if (p_event->type == APP_USBD_EVT_DRV_SOF)
|
||||
{
|
||||
app_usbd_event_execute(p_event);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_code = app_sched_event_put(p_event,
|
||||
sizeof(app_usbd_internal_evt_t),
|
||||
usbd_sched_event_handler);
|
||||
|
||||
if (ret_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not schedule USB event!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint32_t usb_dfu_transport_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
/* Execute event directly in interrupt handler */
|
||||
static const app_usbd_config_t usbd_config =
|
||||
{
|
||||
.ev_handler = usbd_event_handler,
|
||||
.ev_state_proc = usbd_dfu_transport_ev_handler
|
||||
};
|
||||
|
||||
(void) nrf_balloc_init(&m_payload_pool); //Result is checked by checking result of _alloc().
|
||||
|
||||
m_observer = observer;
|
||||
|
||||
uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool);
|
||||
if (p_rx_buf == NULL)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not allocate payload pool.");
|
||||
return NRF_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET];
|
||||
m_slip.current_index = 0;
|
||||
m_slip.buffer_len = SLIP_MTU;
|
||||
m_slip.state = SLIP_STATE_DECODING;
|
||||
|
||||
m_serial.rsp_func = rsp_send;
|
||||
m_serial.payload_free_func = payload_free;
|
||||
m_serial.mtu = SLIP_MTU;
|
||||
m_serial.p_rsp_buf = &m_rsp_buf[NRF_USB_MAX_RESPONSE_SIZE_SLIP -
|
||||
NRF_SERIAL_MAX_RESPONSE_SIZE];
|
||||
m_serial.p_low_level_transport = &usb_dfu_transport;
|
||||
|
||||
|
||||
NRF_LOG_DEBUG("Initializing drivers.");
|
||||
|
||||
err_code = nrf_drv_clock_init();
|
||||
if (err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED)
|
||||
{
|
||||
VERIFY_SUCCESS(err_code);
|
||||
}
|
||||
|
||||
err_code = nrf_drv_power_init(NULL);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
app_usbd_serial_num_generate();
|
||||
|
||||
err_code = app_usbd_init(&usbd_config);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
app_usbd_class_inst_t const * class_cdc_acm = app_usbd_cdc_acm_class_inst_get(&m_app_cdc_acm);
|
||||
err_code = app_usbd_class_append(class_cdc_acm);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
NRF_LOG_DEBUG("Starting USB");
|
||||
|
||||
if (USBD_POWER_DETECTION)
|
||||
{
|
||||
err_code = app_usbd_power_events_enable();
|
||||
VERIFY_SUCCESS(err_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_DEBUG("No USB power detection enabled, starting USB now");
|
||||
|
||||
app_usbd_enable();
|
||||
app_usbd_start();
|
||||
}
|
||||
|
||||
NRF_LOG_DEBUG("USB Transport initialized");
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t usb_dfu_transport_close(nrf_dfu_transport_t const * p_exception)
|
||||
{
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user