From 33aff185cf40af4de3d96646e75054ea4b185599 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Wed, 11 Jul 2018 16:25:43 +0300 Subject: [PATCH 1/7] Add note about SES to readme --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 95c70b3e..e493587c 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ For more details, please see [licenses.md](). ## Developing Ruuvi Firmware Instructions below are tested using OS X and Ubuntu, but basically any Unix distribution (or even Windows) should be fine. Compilation works also using the *Bash on Ubuntu on Windows* -feature added in the July 2016 update of Windows 10 if you follow the Ubuntu directions. If you've compiled and flashed successfully (or unsuccessfully), please identify yourself on our Slack :) -### Prerequisites (to compile): +### Prerequisites (to compile with ARMGCC): The project currently uses the Nordic nRF52 SDK version 12.3.0 (downloaded in the `make` process) and thus requires the GNU ARM Embedded Toolchain version 4.9 Q3 2015 (aka 4.9.3) for compiling: @@ -157,6 +157,12 @@ Note that the nRF52 SDK will be downloaded in `make`, so only after this will the `$SDK/components/toolchain/gcc/` folder exist in the project (typically as the `nRF5_SDK_12.3.0_d7731ad/components/toolchain/gcc/` folder). +### Prerequisites (to compile with Segger Embedded Studio): +Since Q4 of 2017 Segger Embedded Studio has been free (as in beer) to use with Nordic Semiconductor products +such as nRF52. You can download latest version (>3.40) from Segger website. + +You'll need to download and unzip the Nordic SDK 12.3 as above. Only Ruuvi Firmware is currently supported with SES, open folder `ruuvi_examples/ruuvi_firmware/ruuvitag_b/ses`To find the project file. + ### Prerequisites (to create DFU distribution .zip packages) Instructions how to install (on OS X, Ubuntu): From 6ff10273c5c1bdb9ce06e875c913de01ecd352f0 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Wed, 18 Jul 2018 16:24:53 +0300 Subject: [PATCH 2/7] Remove dead code --- drivers/init/init.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/init/init.c b/drivers/init/init.c index 68d6f985..5beaadcb 100644 --- a/drivers/init/init.c +++ b/drivers/init/init.c @@ -235,9 +235,6 @@ init_err_code_t init_sensors(void) err_code |= init_lis2dh12(); //init environmental sensor bme280 err_code |= init_bme280(); - //init chain channels - chain_handler_init(); - set_chain_handler(chain_handler); return err_code; } @@ -264,7 +261,6 @@ init_err_code_t init_watchdog(watchdog_event_handler_t handler) err_code |= watchdog_init(handler); watchdog_enable(); return err_code; - } /** From c9a1dce2bd506ad0d5d24145f42d46d53c2978d8 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Wed, 18 Jul 2018 16:25:36 +0300 Subject: [PATCH 3/7] Fix indentation --- .../nrf_nordic_pininterrupt/pin_interrupt.c | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/nrf_nordic_pininterrupt/pin_interrupt.c b/drivers/nrf_nordic_pininterrupt/pin_interrupt.c index 4d6c4f19..3189162e 100644 --- a/drivers/nrf_nordic_pininterrupt/pin_interrupt.c +++ b/drivers/nrf_nordic_pininterrupt/pin_interrupt.c @@ -17,19 +17,19 @@ */ ret_code_t pin_interrupt_init() { - ret_code_t err_code = NRF_SUCCESS; - err_code |= nrf_drv_gpiote_init(); - return err_code; + ret_code_t err_code = NRF_SUCCESS; + err_code |= nrf_drv_gpiote_init(); + return err_code; } //Look-up table for event handlers static message_handler pin_event_handlers[32] = {0}; static void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { - //Call event handler with empty message TODO: invalid message add context? - NRF_LOG_DEBUG("Handling pin event\r\n"); - ruuvi_standard_message_t message; - if(NULL != pin_event_handlers[pin]){ (pin_event_handlers[pin])(message);} + //Call event handler with empty message TODO: invalid message add context? + NRF_LOG_DEBUG("Handling pin event\r\n"); + ruuvi_standard_message_t message; + if (NULL != pin_event_handlers[pin]) { (pin_event_handlers[pin])(message);} } /** * Enable interrput on pin. Pull-up is enabled on HITOLOW, pull-down is enabled on LOWTIHI @@ -38,37 +38,37 @@ static void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t actio * NRF_GPIOTE_POLARITY_HITOLO * NRF_GPIOTE_POLARITY_TOGGLE * - * Message handler is called with an empty message on event. + * Message handler is called with an empty message on event. */ ret_code_t pin_interrupt_enable(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t polarity, message_handler handler) { - NRF_LOG_INFO("Enabling\r\n"); - ret_code_t err_code = NRF_SUCCESS; - nrf_drv_gpiote_in_config_t in_config = { \ - .is_watcher = false, \ - .hi_accuracy = false, \ - .pull = NRF_GPIO_PIN_NOPULL, \ - .sense = polarity \ - }; - switch(polarity) - { - case NRF_GPIOTE_POLARITY_TOGGLE: - in_config.pull = NRF_GPIO_PIN_NOPULL; - break; - case NRF_GPIOTE_POLARITY_HITOLO: - NRF_LOG_INFO("Pull-up\r\n"); - in_config.pull = NRF_GPIO_PIN_PULLUP; - break; - case NRF_GPIOTE_POLARITY_LOTOHI: - in_config.pull = NRF_GPIO_PIN_PULLDOWN; - break; - default: - return 1; //TODO proper error code - } - pin_event_handlers[pin] = handler; - err_code |= nrf_drv_gpiote_in_init(pin, &in_config, in_pin_handler); + NRF_LOG_INFO("Enabling\r\n"); + ret_code_t err_code = NRF_SUCCESS; + nrf_drv_gpiote_in_config_t in_config = { + .is_watcher = false, \ + .hi_accuracy = false, \ + .pull = NRF_GPIO_PIN_NOPULL, \ + .sense = polarity \ + }; + switch (polarity) + { + case NRF_GPIOTE_POLARITY_TOGGLE: + in_config.pull = NRF_GPIO_PIN_NOPULL; + break; + case NRF_GPIOTE_POLARITY_HITOLO: + NRF_LOG_INFO("Pull-up\r\n"); + in_config.pull = NRF_GPIO_PIN_PULLUP; + break; + case NRF_GPIOTE_POLARITY_LOTOHI: + in_config.pull = NRF_GPIO_PIN_PULLDOWN; + break; + default: + return 1; //TODO proper error code + } + pin_event_handlers[pin] = handler; + err_code |= nrf_drv_gpiote_in_init(pin, &in_config, in_pin_handler); - nrf_drv_gpiote_in_event_enable(pin, true); + nrf_drv_gpiote_in_event_enable(pin, true); - return err_code; + return err_code; } From 42fa76eb058355eec242c2ec9e13ea5a114c87e8 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Wed, 18 Jul 2018 16:27:15 +0300 Subject: [PATCH 4/7] Use Nordic BLE code --- ruuvi_examples/eddystone/main.c | 299 +++++++++++++++++++++++++------- 1 file changed, 240 insertions(+), 59 deletions(-) diff --git a/ruuvi_examples/eddystone/main.c b/ruuvi_examples/eddystone/main.c index c2de28e7..b9689842 100644 --- a/ruuvi_examples/eddystone/main.c +++ b/ruuvi_examples/eddystone/main.c @@ -25,26 +25,21 @@ #include "ble_conn_params.h" #include "ble_advertising.h" #include "softdevice_handler.h" -#include "app_uart.h" #include "app_timer_appsh.h" #include "es_app_config.h" #include "app_scheduler.h" -#include "nrf_ble_escs.h" -#include "nrf_ble_es.h" #include "fstorage.h" #include "nrf_delay.h" #include "nrf_ble_es.h" +#include "init.h" +#include "pin_interrupt.h" +#include "nrf_nfc_handler.h" #define NRF_LOG_MODULE_NAME "MAIN" #include "nrf_log.h" #include "nrf_log_ctrl.h" -#include "init.h" -#include "bluetooth_core.h" -#include "pin_interrupt.h" -#include "nrf_nfc_handler.h" -#include "ruuvi_endpoints.h" #define DEAD_BEEF 0xDEADBEEF //!< Value used as error code on stack dump, can be used to identify stack location on stack unwind. @@ -61,38 +56,230 @@ */ void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) { - app_error_handler(DEAD_BEEF, line_num, p_file_name); + app_error_handler(DEAD_BEEF, line_num, p_file_name); +} + +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t a_info) +{ + error_info_t* info = (error_info_t*)a_info; + NRF_LOG_ERROR("File: %s Line: %d", (uint32_t)info->p_file_name, info->line_num); + NVIC_SystemReset(); +} + +/**@brief Function for the application's SoftDevice event handler. + * + * @param[in] p_ble_evt SoftDevice event. + */ +static void on_ble_evt(ble_evt_t * p_ble_evt) +{ + ret_code_t err_code; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + // Pairing not supported + err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.common_evt.conn_handle, + BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, + NULL, + NULL); + APP_ERROR_CHECK(err_code); + break; + + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + // No system attributes have been stored. + err_code = sd_ble_gatts_sys_attr_set(p_ble_evt->evt.common_evt.conn_handle, NULL, 0, 0); + APP_ERROR_CHECK(err_code); + break; + + case BLE_GAP_EVT_CONNECTED: + bsp_board_led_on(CONNECTED_LED_PIN); + bsp_board_led_off(CONNECTABLE_ADV_LED_PIN); + break; + + case BLE_GAP_EVT_DISCONNECTED: + bsp_board_led_off(CONNECTED_LED_PIN); + break; + +#if (NRF_SD_BLE_API_VERSION == 3) + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, + GATT_MTU_SIZE_DEFAULT); + APP_ERROR_CHECK(err_code); + break; +#endif + + default: + // No implementation needed. + break; + } +} + + +/**@brief Function for dispatching a SoftDevice event to all modules with a SoftDevice + * event handler. + * + * @details This function is called from the SoftDevice event interrupt handler after a + * SoftDevice event has been received. + * + * @param[in] p_ble_evt SoftDevice event. + */ +static void ble_evt_dispatch(ble_evt_t * p_ble_evt) +{ + ble_conn_params_on_ble_evt(p_ble_evt); + on_ble_evt(p_ble_evt); + nrf_ble_es_on_ble_evt(p_ble_evt); + ble_advertising_on_ble_evt(p_ble_evt); +} + + +/**@brief Function for handling system events from the SoftDevice. + * + * @param[in] evt SoftDevice system event. + */ +static void sys_evt_dispatch(uint32_t evt) +{ + fs_sys_event_handler(evt); +} + + +/**@brief Function for the GAP initialization. +* +* @details This function will set up all the necessary GAP (Generic Access Profile) parameters of +* the device. It also sets the permissions and appearance. +*/ +static void gap_params_init(void) +{ + ret_code_t err_code; + ble_gap_conn_params_t gap_conn_params; + ble_gap_conn_sec_mode_t sec_mode; + uint8_t device_name_base[] = APP_DEVICE_NAME; + uint32_t mac0 = NRF_FICR->DEVICEADDR[0] & 0xFFFF; + uint8_t postfix[5] = { 0 }; + uint8_t device_name[20] = { 0 }; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + snprintf((char*)postfix, 5, "%04x", (unsigned int)(mac0)); + + // ok to write trailing null, altough unnecessary if the base pointer includes it already + memcpy(device_name, device_name_base, strlen((const char *)device_name_base)); + memcpy(device_name + strlen((const char *)device_name_base), postfix, sizeof(postfix)); + + err_code = sd_ble_gap_device_name_set(&sec_mode, + device_name, + strlen((const char *)device_name)); + APP_ERROR_CHECK(err_code); + + memset(&gap_conn_params, 0, sizeof(gap_conn_params)); + + gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; + gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; + gap_conn_params.slave_latency = SLAVE_LATENCY; + gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; + + err_code = sd_ble_gap_ppcp_set(&gap_conn_params); + + APP_ERROR_CHECK(err_code); +} + + +/**@brief Function for initializing the BLE stack. + * + * @details Initializes the SoftDevice and the BLE event interrupt. + */ +static void ble_stack_init(void) +{ + ret_code_t err_code; + nrf_clock_lf_cfg_t lf_clock_config; + + lf_clock_config.source = NRF_CLOCK_LF_SRC_XTAL; + lf_clock_config.rc_ctiv = 0; + lf_clock_config.rc_temp_ctiv = 0; + lf_clock_config.xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM; + + // Initialize the SoftDevice handler module. + SOFTDEVICE_HANDLER_INIT(&lf_clock_config, NULL); + + ble_enable_params_t ble_enable_params; + err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT, + PERIPHERAL_LINK_COUNT, + &ble_enable_params); + APP_ERROR_CHECK(err_code); + + // Enable BLE stack. + err_code = softdevice_enable(&ble_enable_params); + APP_ERROR_CHECK(err_code); + + // Subscribe for BLE events. + err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); + APP_ERROR_CHECK(err_code); + + // Subscribe for system events. + err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch); + APP_ERROR_CHECK(err_code); } +/**@brief Function for initializing the Connection Parameters module. + */ +static void conn_params_init(void) +{ + ret_code_t err_code; + ble_conn_params_init_t cp_init; + + memset(&cp_init, 0, sizeof(cp_init)); + + cp_init.p_conn_params = NULL; + cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; + cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; + cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; + cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; + cp_init.disconnect_on_fail = false; + + err_code = ble_conn_params_init(&cp_init); + APP_ERROR_CHECK(err_code); + +} + static bool connectable = false; +bool isConnectable(void) +{ + return connectable; +} + /**@brief Function for handling Eddystone events. * * @param[in] evt Eddystone event to handle. */ static void on_es_evt(nrf_ble_es_evt_t evt) { - switch(evt) - { - case NRF_BLE_ES_EVT_ADVERTISEMENT_SENT: - // non-connectable advertisement - connectable = false; - break; - - case NRF_BLE_ES_EVT_CONNECTABLE_ADV_STARTED: - // connectable advertisement - connectable = true; - break; - - default: - break; - } + switch (evt) + { + case NRF_BLE_ES_EVT_ADVERTISEMENT_SENT: + // non-connectable advertisement + connectable = false; + break; + + case NRF_BLE_ES_EVT_CONNECTABLE_ADV_STARTED: + // connectable advertisement + connectable = true; + break; + + default: + break; + } } -bool isConnectable(void) + +static void timers_init(void) +{ + APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, true); +} + +static void scheduler_init(void) { - return connectable; + APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); } /**@brief Function for doing power management. @@ -101,24 +288,20 @@ bool isConnectable(void) */ static void power_manage(void) { - if(!isConnectable()) { nrf_gpio_pin_set(LED_GREEN); } + if (!isConnectable()) { nrf_gpio_pin_set(LED_GREEN); } nrf_gpio_pin_set(LED_RED); uint32_t err_code = sd_app_evt_wait(); APP_ERROR_CHECK(err_code); watchdog_feed(); nrf_gpio_pin_clear(LED_RED); - if(isConnectable()) nrf_gpio_pin_clear(LED_GREEN); + if (isConnectable()) nrf_gpio_pin_clear(LED_GREEN); } - - - - /**@brief Function for handling button events from app_button IRQ * */ ret_code_t button_press_handler(const ruuvi_standard_message_t message) -{ +{ nrf_ble_es_on_start_connectable_advertising(); return NRF_SUCCESS; } @@ -141,43 +324,41 @@ int main(void) uint32_t err_code = NRF_SUCCESS; // Initialize. - err_code |= init_log(); - - err_code |= init_ble(); - err_code |= bluetooth_configure_advertisement_type(BLE_GAP_ADV_TYPE_ADV_NONCONN_IND); + err_code |= init_log(); + err_code |= init_watchdog(NULL); + err_code |= init_leds(); + + // Enable DC/DC + NRF_POWER->DCDCEN = 1; + + timers_init(); + scheduler_init(); + ble_stack_init(); + gap_params_init(); + conn_params_init(); + nrf_ble_es_init(on_es_evt); err_code |= init_sensors(); - NRF_LOG_DEBUG("BLE init status: %d\r\n", err_code); - //init_handler must be called before init_nfc, as init_nfc passes function pointer set by init_handler to NFC stack nfc_init_handler(); nfc_connected_handler_set(nfc_detected_handler); err_code |= init_nfc(); + // Start interrupts. + err_code |= pin_interrupt_init(); - // Start interrupts. - err_code |= pin_interrupt_init(); - - // Initialize button. - err_code |= pin_interrupt_enable(BSP_BUTTON_0, NRF_GPIOTE_POLARITY_HITOLO, button_press_handler); - - APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); - APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, true); - APP_ERROR_CHECK(err_code); - - nrf_ble_es_init(on_es_evt); - - + // Initialize button. + err_code |= pin_interrupt_enable(BSP_BUTTON_0, NRF_GPIOTE_POLARITY_HITOLO, button_press_handler); NRF_LOG_INFO("Start!\r\n"); - // Enter main loop. - for (;; ) + // Enter main loop. + for (;; ) + { + if (NRF_LOG_PROCESS() == false) { - app_sched_execute(); - if (NRF_LOG_PROCESS() == false) - { - power_manage(); - } + app_sched_execute(); + power_manage(); } + } } From a5fab9f62e915d3719f6e3f5bb2623004a9aa534 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Wed, 18 Jul 2018 16:27:33 +0300 Subject: [PATCH 5/7] Include BLE app config --- drivers/bluetooth/bluetooth_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/bluetooth_core.c b/drivers/bluetooth/bluetooth_core.c index 5aaaa644..c43edc7c 100644 --- a/drivers/bluetooth/bluetooth_core.c +++ b/drivers/bluetooth/bluetooth_core.c @@ -27,6 +27,7 @@ #include "nrf_delay.h" #include "bluetooth_config.h" +#include "bluetooth_application_config.h" #include "ble_bulk_transfer.h" #include "eddystone.h" #include "ruuvi_endpoints.h" From 4de3920665f3e370bf0fa335be7e0043462dd0dc Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Wed, 18 Jul 2018 16:28:41 +0300 Subject: [PATCH 6/7] Update version number, fix macro --- ruuvi_examples/eddystone/bluetooth_application_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruuvi_examples/eddystone/bluetooth_application_config.h b/ruuvi_examples/eddystone/bluetooth_application_config.h index e1676ab3..c63c3359 100644 --- a/ruuvi_examples/eddystone/bluetooth_application_config.h +++ b/ruuvi_examples/eddystone/bluetooth_application_config.h @@ -8,9 +8,9 @@ #define APPLICATION_ADV_INTERVAL 500 /**< ms **/ #define APP_TX_POWER 4 /**< dBm **/ -#define INIT_FWREV "Eddystone_2.2.1" /**< Github tag **/ +#define INIT_FWREV "Eddystone_2.3.0" /**< Github tag **/ #define INIT_SWREV INIT_FWREV /**< Practicially same thing, as there is no separate SW **/ -#define APPLICATION_GATT 1 +#define APP_GATT_PROFILE_ENABLED 1 #endif \ No newline at end of file From 7662722d697a4133b43ff20fc3b08cef46d5702f Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Wed, 18 Jul 2018 16:29:14 +0300 Subject: [PATCH 7/7] Add readme to Eddystone --- ruuvi_examples/eddystone/readme.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 ruuvi_examples/eddystone/readme.md diff --git a/ruuvi_examples/eddystone/readme.md b/ruuvi_examples/eddystone/readme.md new file mode 100644 index 00000000..9b30de01 --- /dev/null +++ b/ruuvi_examples/eddystone/readme.md @@ -0,0 +1,16 @@ +# Eddystone firmware + + * Uses Nordic's Eddystone implementation to provide Eddystone beacon capablities. + * Enter configuration mode by doing NFC scan or pressing button "B" + * Default password is (0x)00112233445566778899AABBCCDDEEFF + * If you change your password, be sure to remember it. You'll need a wired connection to RuuviTag to reset forgotten password. + * Advertises "https://ruuvi.com" at 2 Hz, +0 dBm at boot. + * TLM frames use nRF52 as temperature sensor, regardless of if BME280 is present. + + # Changelog + ## 2.3.0 + * Removes Ruuvi BLE code, uses fully Nordic code instead + * Fixes issue with Eddystone EID ECDH ky exchange + * Removes DFU and DIS services from the GATT profile + +