summaryrefslogtreecommitdiffstats
path: root/bootloader/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootloader/main.c')
-rw-r--r--bootloader/main.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/bootloader/main.c b/bootloader/main.c
new file mode 100644
index 0000000..e5c8fb0
--- /dev/null
+++ b/bootloader/main.c
@@ -0,0 +1,259 @@
+/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
+ *
+ * The information contained herein is property of Nordic Semiconductor ASA.
+ * Terms and conditions of usage are described in detail in NORDIC
+ * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
+ *
+ * Licensees are granted free, non-transferable use of the information. NO
+ * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
+ * the file.
+ *
+ */
+
+/**@file
+ *
+ * @defgroup ble_sdk_app_bootloader_main main.c
+ * @{
+ * @ingroup dfu_bootloader_api
+ * @brief Bootloader project main file.
+ *
+ * -# Receive start data packet.
+ * -# Based on start packet, prepare NVM area to store received data.
+ * -# Receive data packet.
+ * -# Validate data packet.
+ * -# Write Data packet to NVM.
+ * -# If not finished - Wait for next packet.
+ * -# Receive stop data packet.
+ * -# Activate Image, boot application.
+ *
+ */
+#include <sdk/libraries/bootloader_dfu/dfu_transport.h>
+#include <sdk/libraries/bootloader_dfu/bootloader.h>
+#include <sdk/libraries/bootloader_dfu/bootloader_util.h>
+#include <stdint.h>
+#include <string.h>
+#include <stddef.h>
+#include <sdk/libraries/util/nordic_common.h>
+#include <sdk/device/nrf.h>
+#include <sdk/softdevice/s130/headers/nrf_soc.h>
+#include <sdk/libraries/util/app_error.h>
+#include <sdk/drivers_nrf/hal/nrf_gpio.h>
+#include <sdk/device/nrf51_bitfields.h>
+#include <sdk/softdevice/s130/headers/ble.h>
+#include <sdk/device/nrf51.h>
+#include <sdk/softdevice/s130/headers/ble_hci.h>
+#include <sdk/libraries/scheduler/app_scheduler.h>
+#include <sdk/libraries/timer/app_timer_appsh.h>
+#include <sdk/softdevice/s130/headers/nrf_error.h>
+#include "bsp/bsp.h"
+#include <sdk/softdevice/common/softdevice_handler/softdevice_handler_appsh.h>
+#include <sdk/drivers_nrf/pstorage/config/pstorage_platform.h>
+#include <sdk/softdevice/s130/headers/nrf_mbr.h>
+
+//#if BUTTONS_NUMBER < 1
+//#error "Not enough buttons on board"
+//#endif
+
+#if LEDS_NUMBER < 1
+#error "Not enough LEDs on board"
+#endif
+
+#define IS_SRVC_CHANGED_CHARACT_PRESENT 1 /**< Include the service_changed characteristic. For DFU this should normally be the case. */
+
+//#define BOOTLOADER_BUTTON BSP_BUTTON_1 /**< Button used to enter SW update mode. */
+#define UPDATE_IN_PROGRESS_LED BSP_LED_0 /**< Led used to indicate that DFU is active. */
+
+#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
+#define APP_TIMER_MAX_TIMERS 3 /**< Maximum number of simultaneously created timers. */
+#define APP_TIMER_OP_QUEUE_SIZE 4 /**< Size of timer operation queues. */
+
+#define SCHED_MAX_EVENT_DATA_SIZE MAX(APP_TIMER_SCHED_EVT_SIZE, 0) /**< Maximum size of scheduler events. */
+
+#define SCHED_QUEUE_SIZE 20 /**< Maximum number of events in the scheduler queue. */
+
+
+/**@brief Callback function for asserts in the SoftDevice.
+ *
+ * @details This function will be called in case of an assert in the SoftDevice.
+ *
+ * @warning This handler is an example only and does not fit a final product. You need to analyze
+ * how your product is supposed to react in case of Assert.
+ * @warning On assert from the SoftDevice, the system can only recover on reset.
+ *
+ * @param[in] line_num Line number of the failing ASSERT call.
+ * @param[in] file_name File name of the failing ASSERT call.
+ */
+void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
+{
+ app_error_handler(0xDEADBEEF, line_num, p_file_name);
+}
+
+
+/**@brief Function for initialization of LEDs.
+ */
+static void leds_init(void)
+{
+ nrf_gpio_cfg_output(UPDATE_IN_PROGRESS_LED);
+ nrf_gpio_pin_set(UPDATE_IN_PROGRESS_LED);
+}
+
+
+/**@brief Function for initializing the timer handler module (app_timer).
+ */
+static void timers_init(void)
+{
+ // Initialize timer module, making it use the scheduler.
+ APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, true);
+}
+
+
+/**@brief Function for initializing the button module.
+ */
+static void buttons_init(void)
+{
+#if defined(BOOTLOADER_BUTTON)
+ nrf_gpio_cfg_sense_input(BOOTLOADER_BUTTON,
+ BUTTON_PULL,
+ NRF_GPIO_PIN_SENSE_LOW);
+#endif
+}
+
+
+/**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler.
+ *
+ * @details This function is called from the scheduler in the main loop after a BLE stack
+ * event has been received.
+ *
+ * @param[in] p_ble_evt Bluetooth stack event.
+ */
+static void sys_evt_dispatch(uint32_t event)
+{
+ pstorage_sys_event_handler(event);
+}
+
+
+/**@brief Function for initializing the BLE stack.
+ *
+ * @details Initializes the SoftDevice and the BLE event interrupt.
+ *
+ * @param[in] init_softdevice true if SoftDevice should be initialized. The SoftDevice must only
+ * be initialized if a chip reset has occured. Soft reset from
+ * application must not reinitialize the SoftDevice.
+ */
+static void ble_stack_init(bool init_softdevice)
+{
+ uint32_t err_code;
+ sd_mbr_command_t com = {SD_MBR_COMMAND_INIT_SD, };
+
+ if (init_softdevice)
+ {
+ err_code = sd_mbr_command(&com);
+ APP_ERROR_CHECK(err_code);
+ }
+
+ err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_REGION_START);
+ APP_ERROR_CHECK(err_code);
+
+ SOFTDEVICE_HANDLER_APPSH_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, true);
+
+ // Enable BLE stack
+ ble_enable_params_t ble_enable_params;
+ memset(&ble_enable_params, 0, sizeof(ble_enable_params));
+
+ // Below code line is needed for s130. For s110 is inrrelevant - but executable
+ // can run with both s130 and s110.
+ ble_enable_params.gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT;
+
+ ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
+ err_code = sd_ble_enable(&ble_enable_params);
+ APP_ERROR_CHECK(err_code);
+
+ err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
+ APP_ERROR_CHECK(err_code);
+}
+
+
+/**@brief Function for event scheduler initialization.
+ */
+static void scheduler_init(void)
+{
+ APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
+}
+
+
+/**@brief Function for bootloader main entry.
+ */
+int main(void)
+{
+ uint32_t err_code;
+ bool dfu_start = false;
+ bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START);
+
+ if (app_reset)
+ {
+ NRF_POWER->GPREGRET = 0;
+ }
+
+ leds_init();
+
+ // This check ensures that the defined fields in the bootloader corresponds with actual
+ // setting in the nRF51 chip.
+ APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
+ APP_ERROR_CHECK_BOOL(NRF_FICR->CODEPAGESIZE == CODE_PAGE_SIZE);
+
+ // Initialize.
+ timers_init();
+ buttons_init();
+
+ (void)bootloader_init();
+
+ if (bootloader_dfu_sd_in_progress())
+ {
+ nrf_gpio_pin_clear(UPDATE_IN_PROGRESS_LED);
+
+ err_code = bootloader_dfu_sd_update_continue();
+ APP_ERROR_CHECK(err_code);
+
+ ble_stack_init(!app_reset);
+ scheduler_init();
+
+ err_code = bootloader_dfu_sd_update_finalize();
+ APP_ERROR_CHECK(err_code);
+
+ nrf_gpio_pin_set(UPDATE_IN_PROGRESS_LED);
+ }
+ else
+ {
+ // If stack is present then continue initialization of bootloader.
+ ble_stack_init(!app_reset);
+ scheduler_init();
+ }
+
+ dfu_start = app_reset;
+
+#if defined(BOOTLOADER_BUTTON)
+ dfu_start |= ((nrf_gpio_pin_read(BOOTLOADER_BUTTON) == 0) ? true: false);
+#else
+ dfu_start |= true;
+#endif
+
+ if (dfu_start || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START)))
+ {
+ nrf_gpio_pin_clear(UPDATE_IN_PROGRESS_LED);
+
+ // Initiate an update of the firmware.
+ err_code = bootloader_dfu_start();
+ APP_ERROR_CHECK(err_code);
+
+ nrf_gpio_pin_set(UPDATE_IN_PROGRESS_LED);
+ }
+
+ if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress())
+ {
+ // Select a bank region to use as application region.
+ // @note: Only applications running from DFU_BANK_0_REGION_START is supported.
+ bootloader_app_start(DFU_BANK_0_REGION_START);
+ }
+
+ NVIC_SystemReset();
+}