From 51411ff85d661caa8f1036110c19c97461e8b651 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 2 Oct 2018 16:55:55 +0700 Subject: [PATCH] finally fix #31 using erasing in advance and skip erase on the fly for nrf52832. Note A small amount of delay (10 ms) is also added by adafruit-nrfutil after each 4KB to be safe. --- Makefile | 1 + lib/sdk/components/libraries/fifo/app_fifo.c | 214 ------------------ lib/sdk/components/libraries/fifo/app_fifo.h | 181 --------------- .../libraries/bootloader_dfu/bootloader.c | 14 +- .../bootloader_dfu/dfu_single_bank.c | 8 +- src/flash_nrf5x.c | 10 +- 6 files changed, 20 insertions(+), 408 deletions(-) delete mode 100644 lib/sdk/components/libraries/fifo/app_fifo.c delete mode 100644 lib/sdk/components/libraries/fifo/app_fifo.h diff --git a/Makefile b/Makefile index 8397856..ac2f055 100644 --- a/Makefile +++ b/Makefile @@ -275,6 +275,7 @@ CFLAGS += -DS140 else CFLAGS += -DNRF52 +CFLAGS += -DNRF52832_XXAA CFLAGS += -DS132 endif diff --git a/lib/sdk/components/libraries/fifo/app_fifo.c b/lib/sdk/components/libraries/fifo/app_fifo.c deleted file mode 100644 index 32e6e53..0000000 --- a/lib/sdk/components/libraries/fifo/app_fifo.c +++ /dev/null @@ -1,214 +0,0 @@ -/** - * Copyright (c) 2013 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(APP_FIFO) -#include "app_fifo.h" - -static __INLINE uint32_t fifo_length(app_fifo_t * p_fifo) -{ - uint32_t tmp = p_fifo->read_pos; - return p_fifo->write_pos - tmp; -} - - -#define FIFO_LENGTH() fifo_length(p_fifo) /**< Macro for calculating the FIFO length. */ - - -/**@brief Put one byte to the FIFO. */ -static __INLINE void fifo_put(app_fifo_t * p_fifo, uint8_t byte) -{ - p_fifo->p_buf[p_fifo->write_pos & p_fifo->buf_size_mask] = byte; - p_fifo->write_pos++; -} - - -/**@brief Look at one byte in the FIFO. */ -static __INLINE void fifo_peek(app_fifo_t * p_fifo, uint16_t index, uint8_t * p_byte) -{ - *p_byte = p_fifo->p_buf[(p_fifo->read_pos + index) & p_fifo->buf_size_mask]; -} - - -/**@brief Get one byte from the FIFO. */ -static __INLINE void fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte) -{ - fifo_peek(p_fifo, 0, p_byte); - p_fifo->read_pos++; -} - - -uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size) -{ - // Check buffer for null pointer. - if (p_buf == NULL) - { - return NRF_ERROR_NULL; - } - - // Check that the buffer size is a power of two. - if (!IS_POWER_OF_TWO(buf_size)) - { - return NRF_ERROR_INVALID_LENGTH; - } - - p_fifo->p_buf = p_buf; - p_fifo->buf_size_mask = buf_size - 1; - p_fifo->read_pos = 0; - p_fifo->write_pos = 0; - - return NRF_SUCCESS; -} - - -uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte) -{ - if (FIFO_LENGTH() <= p_fifo->buf_size_mask) - { - fifo_put(p_fifo, byte); - return NRF_SUCCESS; - } - - return NRF_ERROR_NO_MEM; -} - - -uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte) -{ - if (FIFO_LENGTH() != 0) - { - fifo_get(p_fifo, p_byte); - return NRF_SUCCESS; - } - - return NRF_ERROR_NOT_FOUND; - -} - - -uint32_t app_fifo_peek(app_fifo_t * p_fifo, uint16_t index, uint8_t * p_byte) -{ - if (FIFO_LENGTH() > index) - { - fifo_peek(p_fifo, index, p_byte); - return NRF_SUCCESS; - } - - return NRF_ERROR_NOT_FOUND; -} - - -uint32_t app_fifo_flush(app_fifo_t * p_fifo) -{ - p_fifo->read_pos = p_fifo->write_pos; - return NRF_SUCCESS; -} - - -uint32_t app_fifo_read(app_fifo_t * p_fifo, uint8_t * p_byte_array, uint32_t * p_size) -{ - VERIFY_PARAM_NOT_NULL(p_fifo); - VERIFY_PARAM_NOT_NULL(p_size); - - const uint32_t byte_count = fifo_length(p_fifo); - const uint32_t requested_len = (*p_size); - uint32_t index = 0; - uint32_t read_size = MIN(requested_len, byte_count); - - (*p_size) = byte_count; - - // Check if the FIFO is empty. - if (byte_count == 0) - { - return NRF_ERROR_NOT_FOUND; - } - - // Check if application has requested only the size. - if (p_byte_array == NULL) - { - return NRF_SUCCESS; - } - - // Fetch bytes from the FIFO. - while (index < read_size) - { - fifo_get(p_fifo, &p_byte_array[index++]); - } - - (*p_size) = read_size; - - return NRF_SUCCESS; -} - - -uint32_t app_fifo_write(app_fifo_t * p_fifo, uint8_t const * p_byte_array, uint32_t * p_size) -{ - VERIFY_PARAM_NOT_NULL(p_fifo); - VERIFY_PARAM_NOT_NULL(p_size); - - const uint32_t available_count = p_fifo->buf_size_mask - fifo_length(p_fifo) + 1; - const uint32_t requested_len = (*p_size); - uint32_t index = 0; - uint32_t write_size = MIN(requested_len, available_count); - - (*p_size) = available_count; - - // Check if the FIFO is FULL. - if (available_count == 0) - { - return NRF_ERROR_NO_MEM; - } - - // Check if application has requested only the size. - if (p_byte_array == NULL) - { - return NRF_SUCCESS; - } - - //Fetch bytes from the FIFO. - while (index < write_size) - { - fifo_put(p_fifo, p_byte_array[index++]); - } - - (*p_size) = write_size; - - return NRF_SUCCESS; -} -#endif //NRF_MODULE_ENABLED(APP_FIFO) diff --git a/lib/sdk/components/libraries/fifo/app_fifo.h b/lib/sdk/components/libraries/fifo/app_fifo.h deleted file mode 100644 index 75f2a7c..0000000 --- a/lib/sdk/components/libraries/fifo/app_fifo.h +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Copyright (c) 2013 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup app_fifo FIFO implementation - * @{ - * @ingroup app_common - * - * @brief FIFO implementation. - */ - -#ifndef APP_FIFO_H__ -#define APP_FIFO_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief A FIFO instance structure. - * @details Keeps track of which bytes to read and write next. - * Also, it keeps the information about which memory is allocated for the buffer - * and its size. This structure must be initialized by app_fifo_init() before use. - */ -typedef struct -{ - uint8_t * p_buf; /**< Pointer to FIFO buffer memory. */ - uint16_t buf_size_mask; /**< Read/write index mask. Also used for size checking. */ - volatile uint32_t read_pos; /**< Next read position in the FIFO buffer. */ - volatile uint32_t write_pos; /**< Next write position in the FIFO buffer. */ -} app_fifo_t; - -/**@brief Function for initializing the FIFO. - * - * @param[out] p_fifo FIFO object. - * @param[in] p_buf FIFO buffer for storing data. The buffer size must be a power of two. - * @param[in] buf_size Size of the FIFO buffer provided. This size must be a power of two. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_NULL If a NULL pointer is provided as buffer. - * @retval NRF_ERROR_INVALID_LENGTH If size of buffer provided is not a power of two. - */ -uint32_t app_fifo_init(app_fifo_t * p_fifo, uint8_t * p_buf, uint16_t buf_size); - -/**@brief Function for adding an element to the FIFO. - * - * @param[in] p_fifo Pointer to the FIFO. - * @param[in] byte Data byte to add to the FIFO. - * - * @retval NRF_SUCCESS If an element has been successfully added to the FIFO. - * @retval NRF_ERROR_NO_MEM If the FIFO is full. - */ -uint32_t app_fifo_put(app_fifo_t * p_fifo, uint8_t byte); - -/**@brief Function for getting the next element from the FIFO. - * - * @param[in] p_fifo Pointer to the FIFO. - * @param[out] p_byte Byte fetched from the FIFO. - * - * @retval NRF_SUCCESS If an element was returned. - * @retval NRF_ERROR_NOT_FOUND If there are no more elements in the queue. - */ -uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte); - -/**@brief Function for looking at an element in the FIFO, without consuming it. - * - * @param[in] p_fifo Pointer to the FIFO. - * @param[in] index Which element to look at. The lower the index, the earlier it was put. - * @param[out] p_byte Byte fetched from the FIFO. - * - * @retval NRF_SUCCESS If an element was returned. - * @retval NRF_ERROR_NOT_FOUND If there are no more elements in the queue, or the index was - * too large. - */ -uint32_t app_fifo_peek(app_fifo_t * p_fifo, uint16_t index, uint8_t * p_byte); - -/**@brief Function for flushing the FIFO. - * - * @param[in] p_fifo Pointer to the FIFO. - * - * @retval NRF_SUCCESS If the FIFO was flushed successfully. - */ -uint32_t app_fifo_flush(app_fifo_t * p_fifo); - -/**@brief Function for reading bytes from the FIFO. - * - * This function can also be used to get the number of bytes in the FIFO. - * - * @param[in] p_fifo Pointer to the FIFO. Must not be NULL. - * @param[out] p_byte_array Memory pointer where the read bytes are fetched from the FIFO. - * Can be NULL. If NULL, the number of bytes that can be read in the FIFO - * are returned in the p_size parameter. - * @param[inout] p_size Address to memory indicating the maximum number of bytes to be read. - * The provided memory is overwritten with the actual number of bytes - * read if the procedure was successful. This field must not be NULL. - * If p_byte_array is set to NULL by the application, this parameter - * returns the number of bytes in the FIFO. - * - * @retval NRF_SUCCESS If the procedure is successful. The actual number of bytes read might - * be less than the requested maximum, depending on how many elements exist - * in the FIFO. Even if less bytes are returned, the procedure is considered - * successful. - * @retval NRF_ERROR_NULL If a NULL parameter was passed for a parameter that must not - * be NULL. - * @retval NRF_ERROR_NOT_FOUND If the FIFO is empty. - */ -uint32_t app_fifo_read(app_fifo_t * p_fifo, uint8_t * p_byte_array, uint32_t * p_size); - -/**@brief Function for writing bytes to the FIFO. - * - * This function can also be used to get the available size on the FIFO. - * - * @param[in] p_fifo Pointer to the FIFO. Must not be NULL. - * @param[in] p_byte_array Memory pointer containing the bytes to be written to the FIFO. - * Can be NULL. If NULL, this function returns the number of bytes - * that can be written to the FIFO. - * @param[inout] p_size Address to memory indicating the maximum number of bytes to be written. - * The provided memory is overwritten with the number of bytes that were actually - * written if the procedure is successful. This field must not be NULL. - * If p_byte_array is set to NULL by the application, this parameter - * returns the number of bytes available in the FIFO. - * - * @retval NRF_SUCCESS If the procedure is successful. The actual number of bytes written might - * be less than the requested maximum, depending on how much room there is in - * the FIFO. Even if less bytes are written, the procedure is considered - * successful. If the write was partial, the application should use - * subsequent calls to attempt writing the data again. - * @retval NRF_ERROR_NULL If a NULL parameter was passed for a parameter that must not - * be NULL. - * @retval NRF_ERROR_NO_MEM If the FIFO is full. - * - */ -uint32_t app_fifo_write(app_fifo_t * p_fifo, uint8_t const * p_byte_array, uint32_t * p_size); - - -#ifdef __cplusplus -} -#endif - -#endif // APP_FIFO_H__ - -/** @} */ diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index 265e55b..de1e36b 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -141,7 +141,7 @@ static void wait_for_events(void) bool bootloader_app_is_valid(uint32_t app_addr) { - const bootloader_settings_t * p_bootloader_settings; + bootloader_settings_t const * p_bootloader_settings; // There exists an application in CODE region 1. if (*((uint32_t *)app_addr) == EMPTY_FLASH_MASK) @@ -185,8 +185,8 @@ static void bootloader_settings_save(bootloader_settings_t * p_settings) } else { - flash_nrf5x_write(BOOTLOADER_SETTINGS_ADDRESS, p_settings, sizeof(bootloader_settings_t)); - flash_nrf5x_flush(); + nrf_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS); + nrf_nvmc_write_words(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4); pstorage_callback_handler(&m_bootsettings_handle, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_settings, sizeof(bootloader_settings_t)); } @@ -195,8 +195,8 @@ static void bootloader_settings_save(bootloader_settings_t * p_settings) void bootloader_dfu_update_process(dfu_update_status_t update_status) { - static bootloader_settings_t settings; - const bootloader_settings_t * p_bootloader_settings; + __attribute__((aligned(4))) static bootloader_settings_t settings; + bootloader_settings_t const * p_bootloader_settings; bootloader_util_settings_get(&p_bootloader_settings); @@ -391,7 +391,7 @@ void bootloader_app_start(uint32_t app_addr) bool bootloader_dfu_sd_in_progress(void) { - const bootloader_settings_t * p_bootloader_settings; + bootloader_settings_t const * p_bootloader_settings; bootloader_util_settings_get(&p_bootloader_settings); @@ -446,7 +446,7 @@ uint32_t bootloader_dfu_sd_update_finalize(void) void bootloader_settings_get(bootloader_settings_t * const p_settings) { - const bootloader_settings_t * p_bootloader_settings; + bootloader_settings_t const * p_bootloader_settings; bootloader_util_settings_get(&p_bootloader_settings); diff --git a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c index d37cf45..96f5fef 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/dfu_single_bank.c @@ -146,12 +146,12 @@ static void dfu_prepare_func_app_erase(uint32_t image_size) } else { - uint32_t page_count = m_image_size/CODE_PAGE_SIZE; - if ( m_image_size%CODE_PAGE_SIZE ) page_count++; + uint32_t page_count = m_image_size / CODE_PAGE_SIZE; + if ( m_image_size % CODE_PAGE_SIZE ) page_count++; - for(uint32_t i=0; i +#include "nrf_sdm.h" #include "flash_nrf5x.h" #include "boards.h" -#include "nrf_sdm.h" - #define FLASH_PAGE_SIZE 4096 #define FLASH_CACHE_INVALID_ADDR 0xffffffff @@ -52,7 +51,14 @@ void flash_nrf5x_flush(void) if ( memcmp(_fl_buf, (void *) _fl_addr, FLASH_PAGE_SIZE) != 0 ) { +#ifdef NRF52840_XXAA + // - nRF52832 dfu via uart can miss incoming byte when erasing because cpu is blocked for > 2ms. + // Since dfu_prepare_func_app_erase() already erase the page for us, we can skip it here. + // + // - nRF52840 dfu serial/uf2 are USB-based which are DMA and should have no problems. Note MSC uf2 + // does not erase page in advance like dfu serial nrf_nvmc_page_erase(_fl_addr); +#endif nrf_nvmc_write_words(_fl_addr, (uint32_t *) _fl_buf, FLASH_PAGE_SIZE / 4); }