123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772 |
- /**
- * 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;
- }
|