From 23d834ee035587fbe3be834d5b12325a6f549a0e Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 24 May 2018 12:00:23 +0200 Subject: [PATCH 1/7] porting: Add missing API to dummy NPL --- porting/npl/dummy/src/npl_os_dummy.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/porting/npl/dummy/src/npl_os_dummy.c b/porting/npl/dummy/src/npl_os_dummy.c index 855d9710a..48a28741c 100644 --- a/porting/npl/dummy/src/npl_os_dummy.c +++ b/porting/npl/dummy/src/npl_os_dummy.c @@ -44,6 +44,11 @@ ble_npl_eventq_init(struct ble_npl_eventq *evq) } +struct ble_npl_event * +ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) +{ +} + void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) { From 7501d3816cbdc700bc4ebaeee29127b52318a333 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 24 May 2018 10:58:52 +0200 Subject: [PATCH 2/7] porting: Add API to run an event instead of running an eventq This makes more sense since now we have API which can just fire callback associated with event. Running eventq is just getting an event from queue and then running it. --- nimble/controller/src/ble_ll.c | 6 +++++- nimble/include/nimble/nimble_npl.h | 4 ++-- porting/npl/dummy/src/npl_os_dummy.c | 2 +- porting/npl/freertos/include/nimble/nimble_npl_os.h | 7 +------ porting/npl/mynewt/include/nimble/nimble_npl_os.h | 4 ++-- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 87317eccd..d1d2a2c7d 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -1088,6 +1088,8 @@ ble_ll_event_comp_pkts(struct ble_npl_event *ev) void ble_ll_task(void *arg) { + struct ble_npl_event *ev; + /* Init ble phy */ ble_phy_init(); @@ -1100,7 +1102,9 @@ ble_ll_task(void *arg) ble_ll_rand_start(); while (1) { - ble_npl_eventq_run(&g_ble_ll_data.ll_evq); + ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER); + assert(ev); + ble_npl_event_run(ev); } } diff --git a/nimble/include/nimble/nimble_npl.h b/nimble/include/nimble/nimble_npl.h index fd1867ac0..9757e1b69 100644 --- a/nimble/include/nimble/nimble_npl.h +++ b/nimble/include/nimble/nimble_npl.h @@ -76,8 +76,6 @@ void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev); void ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev); -void ble_npl_eventq_run(struct ble_npl_eventq *evq); - void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void *arg); @@ -89,6 +87,8 @@ void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg); bool ble_npl_eventq_is_empty(struct ble_npl_eventq *evq); +void ble_npl_event_run(struct ble_npl_event *ev); + /* * Mutexes */ diff --git a/porting/npl/dummy/src/npl_os_dummy.c b/porting/npl/dummy/src/npl_os_dummy.c index 48a28741c..90d37da5b 100644 --- a/porting/npl/dummy/src/npl_os_dummy.c +++ b/porting/npl/dummy/src/npl_os_dummy.c @@ -62,7 +62,7 @@ ble_npl_eventq_remove(struct ble_npl_eventq *evq, } void -ble_npl_eventq_run(struct ble_npl_eventq *evq) +ble_npl_event_run(struct ble_npl_event *ev) { } diff --git a/porting/npl/freertos/include/nimble/nimble_npl_os.h b/porting/npl/freertos/include/nimble/nimble_npl_os.h index 9c0b5849b..ca1c2e5cb 100644 --- a/porting/npl/freertos/include/nimble/nimble_npl_os.h +++ b/porting/npl/freertos/include/nimble/nimble_npl_os.h @@ -118,13 +118,8 @@ ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev) } static inline void -ble_npl_eventq_run(struct ble_npl_eventq *evq) +ble_npl_event_run(struct ble_npl_event *ev) { - struct ble_npl_event *ev; - - ev = ble_npl_eventq_get(evq, BLE_NPL_TIME_FOREVER); - assert(ev->fn != NULL); - ev->fn(ev); } diff --git a/porting/npl/mynewt/include/nimble/nimble_npl_os.h b/porting/npl/mynewt/include/nimble/nimble_npl_os.h index de7df5cd4..e1c670010 100644 --- a/porting/npl/mynewt/include/nimble/nimble_npl_os.h +++ b/porting/npl/mynewt/include/nimble/nimble_npl_os.h @@ -110,9 +110,9 @@ ble_npl_eventq_remove(struct ble_npl_eventq *evq, } static inline void -ble_npl_eventq_run(struct ble_npl_eventq *evq) +ble_npl_event_run(struct ble_npl_event *ev) { - os_eventq_run(&evq->evq); + ev->ev.ev_cb(&ev->ev); } static inline bool From 095288a5497829f22857e12e3442378419d153a2 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 24 May 2018 11:02:23 +0200 Subject: [PATCH 3/7] porting: Move default event queue management to common porting code OS specific code should not care about default event queue thus it will be created by nimble_port_init() function internally. We'll just add simple getter in case someone wants to use it. --- nimble/host/src/ble_hs.c | 16 +++++++++++++--- nimble/include/nimble/nimble_npl.h | 2 -- porting/nimble/include/nimble/nimble_port.h | 4 ++++ porting/nimble/src/nimble_port.c | 11 +++++++++++ porting/npl/dummy/src/npl_os_dummy.c | 6 ------ .../npl/freertos/include/nimble/nimble_npl_os.h | 8 -------- porting/npl/freertos/src/npl_os_freertos.c | 12 ------------ 7 files changed, 28 insertions(+), 31 deletions(-) diff --git a/nimble/host/src/ble_hs.c b/nimble/host/src/ble_hs.c index 05975d5f0..62b7e4855 100644 --- a/nimble/host/src/ble_hs.c +++ b/nimble/host/src/ble_hs.c @@ -27,6 +27,9 @@ #include "ble_hs_priv.h" #include "ble_monitor_priv.h" #include "nimble/nimble_npl.h" +#ifndef MYNEWT +#include "nimble/nimble_port.h" +#endif #define BLE_HS_HCI_EVT_COUNT \ (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + \ @@ -674,13 +677,20 @@ ble_hs_init(void) /* Configure the HCI transport to communicate with a host. */ ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); - ble_hs_evq_set(ble_npl_eventq_dflt_get()); - +#ifdef MYNEWT + ble_hs_evq_set((struct ble_npl_eventq *)os_eventq_dflt_get()); +#else + ble_hs_evq_set(nimble_port_get_dflt_eventq()); +#endif /* Enqueue the start event to the default event queue. Using the default * queue ensures the event won't run until the end of main(). This allows * the application to configure this package in the meantime. */ - ble_npl_eventq_put(ble_npl_eventq_dflt_get(), &ble_hs_ev_start); +#ifdef MYNEWT + ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(), &ble_hs_ev_start); +#else + ble_npl_eventq_put(nimble_port_get_dflt_eventq(), &ble_hs_ev_start); +#endif #if BLE_MONITOR ble_monitor_new_index(0, (uint8_t[6]){ }, "nimble0"); diff --git a/nimble/include/nimble/nimble_npl.h b/nimble/include/nimble/nimble_npl.h index 9757e1b69..d7a4faed9 100644 --- a/nimble/include/nimble/nimble_npl.h +++ b/nimble/include/nimble/nimble_npl.h @@ -64,8 +64,6 @@ void *ble_npl_get_current_task_id(void); * Event queue */ -struct ble_npl_eventq *ble_npl_eventq_dflt_get(void); - void ble_npl_eventq_init(struct ble_npl_eventq *evq); struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *evq, diff --git a/porting/nimble/include/nimble/nimble_port.h b/porting/nimble/include/nimble/nimble_port.h index 8a3b60438..496acbbb1 100644 --- a/porting/nimble/include/nimble/nimble_port.h +++ b/porting/nimble/include/nimble/nimble_port.h @@ -20,12 +20,16 @@ #ifndef _NIMBLE_PORT_H #define _NIMBLE_PORT_H +#include "nimble/nimble_npl.h" + #ifdef __cplusplus extern "C" { #endif void nimble_port_init(void); +struct ble_npl_eventq *nimble_port_get_dflt_eventq(void); + #if NIMBLE_CFG_CONTROLLER void nimble_port_ll_task_func(void *arg); #endif diff --git a/porting/nimble/src/nimble_port.c b/porting/nimble/src/nimble_port.c index 8c2ac0164..606429fe0 100644 --- a/porting/nimble/src/nimble_port.c +++ b/porting/nimble/src/nimble_port.c @@ -25,6 +25,8 @@ #include "controller/ble_ll.h" #endif +static struct ble_npl_eventq g_eventq_dflt; + void nimble_port_init(void) { @@ -34,6 +36,9 @@ nimble_port_init(void) void ble_hci_ram_init(void); #endif + /* Initialize default event queue */ + ble_npl_eventq_init(&g_eventq_dflt); + os_msys_init(); ble_hs_init(); @@ -49,6 +54,12 @@ nimble_port_init(void) #endif } +struct ble_npl_eventq * +nimble_port_get_dflt_eventq(void) +{ + return &g_eventq_dflt; +} + #if NIMBLE_CFG_CONTROLLER void nimble_port_ll_task_func(void *arg) diff --git a/porting/npl/dummy/src/npl_os_dummy.c b/porting/npl/dummy/src/npl_os_dummy.c index 90d37da5b..a522531fa 100644 --- a/porting/npl/dummy/src/npl_os_dummy.c +++ b/porting/npl/dummy/src/npl_os_dummy.c @@ -32,12 +32,6 @@ ble_npl_get_current_task_id(void) return NULL; } -struct ble_npl_eventq * -ble_npl_eventq_dflt_get(void) -{ - return NULL; -} - void ble_npl_eventq_init(struct ble_npl_eventq *evq) { diff --git a/porting/npl/freertos/include/nimble/nimble_npl_os.h b/porting/npl/freertos/include/nimble/nimble_npl_os.h index ca1c2e5cb..d5b18d299 100644 --- a/porting/npl/freertos/include/nimble/nimble_npl_os.h +++ b/porting/npl/freertos/include/nimble/nimble_npl_os.h @@ -85,14 +85,6 @@ ble_npl_get_current_task_id(void) return xTaskGetCurrentTaskHandle(); } -struct ble_npl_eventq *npl_freertos_eventq_dflt_get(void); - -static inline struct ble_npl_eventq * -ble_npl_eventq_dflt_get(void) -{ - return npl_freertos_eventq_dflt_get(); -} - static inline void ble_npl_eventq_init(struct ble_npl_eventq *evq) { diff --git a/porting/npl/freertos/src/npl_os_freertos.c b/porting/npl/freertos/src/npl_os_freertos.c index 248baf864..d99116966 100644 --- a/porting/npl/freertos/src/npl_os_freertos.c +++ b/porting/npl/freertos/src/npl_os_freertos.c @@ -29,18 +29,6 @@ in_isr(void) return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0; } -static struct ble_npl_eventq dflt_evq; - -struct ble_npl_eventq * -npl_freertos_eventq_dflt_get(void) -{ - if (!dflt_evq.q) { - dflt_evq.q = xQueueCreate(32, sizeof(struct ble_npl_eventq *)); - } - - return &dflt_evq; -} - struct ble_npl_event * npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) { From 4c70f15a7489df665ef9da5af8bad673b778d214 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 24 May 2018 11:04:09 +0200 Subject: [PATCH 4/7] porting: Add common function to run default event queue Now application can just call single function which will run default event queue instead of creating "standard" loop. Also on some OS it may be just possible to call some OS-specific API instead, so it's up to app what to do - this is just a convenience function. --- porting/nimble/include/nimble/nimble_port.h | 2 ++ porting/nimble/src/nimble_port.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/porting/nimble/include/nimble/nimble_port.h b/porting/nimble/include/nimble/nimble_port.h index 496acbbb1..28065cf8e 100644 --- a/porting/nimble/include/nimble/nimble_port.h +++ b/porting/nimble/include/nimble/nimble_port.h @@ -28,6 +28,8 @@ extern "C" { void nimble_port_init(void); +void nimble_port_run(void); + struct ble_npl_eventq *nimble_port_get_dflt_eventq(void); #if NIMBLE_CFG_CONTROLLER diff --git a/porting/nimble/src/nimble_port.c b/porting/nimble/src/nimble_port.c index 606429fe0..bf1803cb5 100644 --- a/porting/nimble/src/nimble_port.c +++ b/porting/nimble/src/nimble_port.c @@ -54,6 +54,17 @@ nimble_port_init(void) #endif } +void +nimble_port_run(void) +{ + struct ble_npl_event *ev; + + while (1) { + ev = ble_npl_eventq_get(&g_eventq_dflt, BLE_NPL_TIME_FOREVER); + ble_npl_event_run(ev); + } +} + struct ble_npl_eventq * nimble_port_get_dflt_eventq(void) { From 86d4b254bebd04e1330b2e5fdc9e99f8e864017a Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 24 May 2018 11:06:31 +0200 Subject: [PATCH 5/7] porting: Use common FreeRTOS macros for entering/exiting critical sect --- porting/npl/freertos/include/nimble/nimble_npl_os.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/porting/npl/freertos/include/nimble/nimble_npl_os.h b/porting/npl/freertos/include/nimble/nimble_npl_os.h index d5b18d299..c2f8361a2 100644 --- a/porting/npl/freertos/include/nimble/nimble_npl_os.h +++ b/porting/npl/freertos/include/nimble/nimble_npl_os.h @@ -281,13 +281,15 @@ ble_npl_hw_set_isr(int irqn, uint32_t addr) static inline uint32_t ble_npl_hw_enter_critical(void) { - return npl_freertos_hw_enter_critical(); + vPortEnterCritical(); + return 0; } static inline void ble_npl_hw_exit_critical(uint32_t ctx) { - npl_freertos_hw_exit_critical(ctx); + vPortExitCritical(); + } #ifdef __cplusplus From 3c07cb1898fe6038ae76ea54c8c714a3f670ffc8 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 24 May 2018 11:07:28 +0200 Subject: [PATCH 6/7] porting: Add convenience init function in FreeRTOS NPL This adds convenience function for FreeRTOS NPL which initializes OS-specific things. Currently it creates tasks necessary to run ported NimBLE. --- .../include/nimble/nimble_port_freertos.h | 35 +++++++++++++ .../npl/freertos/src/nimble_port_freertos.c | 51 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 porting/npl/freertos/include/nimble/nimble_port_freertos.h create mode 100644 porting/npl/freertos/src/nimble_port_freertos.c diff --git a/porting/npl/freertos/include/nimble/nimble_port_freertos.h b/porting/npl/freertos/include/nimble/nimble_port_freertos.h new file mode 100644 index 000000000..43cbf2915 --- /dev/null +++ b/porting/npl/freertos/include/nimble/nimble_port_freertos.h @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _NIMBLE_PORT_FREERTOS_H +#define _NIMBLE_PORT_FREERTOS_H + +#include "nimble/nimble_npl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void nimble_port_freertos_init(TaskFunction_t host_task_fn); + +#ifdef __cplusplus +} +#endif + +#endif /* _NIMBLE_PORT_FREERTOS_H */ diff --git a/porting/npl/freertos/src/nimble_port_freertos.c b/porting/npl/freertos/src/nimble_port_freertos.c new file mode 100644 index 000000000..8ee3475ad --- /dev/null +++ b/porting/npl/freertos/src/nimble_port_freertos.c @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "FreeRTOS.h" +#include "task.h" +#include "nimble/nimble_port.h" + +#if NIMBLE_CFG_CONTROLLER +static TaskHandle_t ll_task_h; +#endif +static TaskHandle_t host_task_h; + +void +nimble_port_freertos_init(TaskFunction_t host_task_fn) +{ +#if NIMBLE_CFG_CONTROLLER + /* + * Create task where NimBLE LL will run. This one is required as LL has its + * own event queue and should have highest priority. The task function is + * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped + * since it has compatible prototype. + */ + xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 400, + NULL, configMAX_PRIORITIES - 1, &ll_task_h); +#endif + + /* + * Create task where NimBLE host will run. It is not strictly necessary to + * have separate task for NimBLE host, but since something needs to handle + * default queue it is just easier to make separate task which does this. + */ + xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 400, + NULL, tskIDLE_PRIORITY + 1, &host_task_h); +} From daed64e78655c1c3d597bc1a2a9fa2d418ac775f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 24 May 2018 12:00:53 +0200 Subject: [PATCH 7/7] porting: Fix FreeRTOS NPL Make ble_npl_eventq_remove properly handle calling from ISR. --- porting/npl/freertos/src/npl_os_freertos.c | 44 ++++++++++++++++------ 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/porting/npl/freertos/src/npl_os_freertos.c b/porting/npl/freertos/src/npl_os_freertos.c index d99116966..87936bd8d 100644 --- a/porting/npl/freertos/src/npl_os_freertos.c +++ b/porting/npl/freertos/src/npl_os_freertos.c @@ -82,6 +82,7 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, BaseType_t ret; int i; int count; + BaseType_t woken, woken2; if (!ev->queued) { return; @@ -94,22 +95,43 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, * better use counting semaphore with os_queue to handle this in future. */ - vPortEnterCritical(); + if (in_isr()) { + woken = pdFALSE; - count = uxQueueMessagesWaiting(evq->q); - for (i = 0; i < count; i++) { - ret = xQueueReceive(evq->q, &tmp_ev, 0); - assert(ret == pdPASS); + count = uxQueueMessagesWaitingFromISR(evq->q); + for (i = 0; i < count; i++) { + ret = xQueueReceiveFromISR(evq->q, &tmp_ev, &woken2); + assert(ret == pdPASS); + woken |= woken2; - if (tmp_ev == ev) { - continue; + if (tmp_ev == ev) { + continue; + } + + ret = xQueueSendToBackFromISR(evq->q, &tmp_ev, &woken2); + assert(ret == pdPASS); + woken |= woken2; } - ret = xQueueSendToBack(evq->q, &tmp_ev, 0); - assert(ret == pdPASS); - } + portYIELD_FROM_ISR(woken); + } else { + vPortEnterCritical(); - vPortExitCritical(); + count = uxQueueMessagesWaiting(evq->q); + for (i = 0; i < count; i++) { + ret = xQueueReceive(evq->q, &tmp_ev, 0); + assert(ret == pdPASS); + + if (tmp_ev == ev) { + continue; + } + + ret = xQueueSendToBack(evq->q, &tmp_ev, 0); + assert(ret == pdPASS); + } + + vPortExitCritical(); + } ev->queued = 0; }