From 39c32e6be13bd981e9371640e9ce6a4d0ef5d608 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Tue, 15 May 2018 12:56:50 +0200 Subject: [PATCH] porting: Add NPL for RIOT This patch adds NPL for RIOT, see https://www.riot-os.org/. Example applications are included in RIOT sources and should be build from there. RIOT build system will automatically fetch NimBLE sources as a package. --- .../npl/riot/include/nimble/nimble_npl_os.h | 261 ++++++++++++++++++ porting/npl/riot/src/npl_os_riot.c | 66 +++++ porting/npl/riot/src/nrf5x_isr.c | 58 ++++ 3 files changed, 385 insertions(+) create mode 100644 porting/npl/riot/include/nimble/nimble_npl_os.h create mode 100644 porting/npl/riot/src/npl_os_riot.c create mode 100644 porting/npl/riot/src/nrf5x_isr.c diff --git a/porting/npl/riot/include/nimble/nimble_npl_os.h b/porting/npl/riot/include/nimble/nimble_npl_os.h new file mode 100644 index 000000000..79c58c8b3 --- /dev/null +++ b/porting/npl/riot/include/nimble/nimble_npl_os.h @@ -0,0 +1,261 @@ +/* + * 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_NPL_OS_H_ +#define _NIMBLE_NPL_OS_H_ + +#include +#include +#include "event/callback.h" +#include "mutex.h" +#include "semaphore.h" +#include "xtimer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_NPL_OS_ALIGNMENT 4 + +#define BLE_NPL_TIME_FOREVER UINT32_MAX + +typedef uint32_t ble_npl_time_t; +typedef int32_t ble_npl_stime_t; + +struct ble_npl_event { + event_callback_t e; + void *arg; +}; + +struct ble_npl_eventq { + event_queue_t q; +}; + +struct ble_npl_callout { + xtimer_t timer; + ble_npl_time_t target_ticks; + struct ble_npl_event e; + event_queue_t *q; +}; + +struct ble_npl_mutex { + mutex_t mu; +}; + +struct ble_npl_sem { + sem_t sem; +}; + +static inline bool +ble_npl_os_started(void) +{ + return true; +} + +static inline void * +ble_npl_get_current_task_id(void) +{ + return (void *)(uint32_t)thread_getpid(); +} + +static inline void +ble_npl_eventq_init(struct ble_npl_eventq *evq) +{ + event_queue_init(&evq->q); +} + +static inline void +ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) +{ + event_post(&evq->q, &ev->e.super); +} + +static inline struct ble_npl_event * +ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) +{ + if (tmo == 0) { + return (struct ble_npl_event *)event_get(&evq->q); + } else if (tmo == BLE_NPL_TIME_FOREVER) { + return (struct ble_npl_event *)event_wait(&evq->q); + } else { + assert(0); + } +} + +static inline void +ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev) +{ + event_cancel(&evq->q, &ev->e.super); +} + +static inline void +ble_npl_event_run(struct ble_npl_event *ev) +{ + ev->e.super.handler(&ev->e.super); +} + +static inline void +ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void *arg) +{ + /* + * Need to clear list_node manually since init function below does not do + * this. + */ + ev->e.super.list_node.next = NULL; + event_callback_init(&ev->e, (void(*)(void *))fn, ev); + ev->arg = arg; +} + +static inline bool +ble_npl_event_is_queued(struct ble_npl_event *ev) +{ + return (ev->e.super.list_node.next != NULL); +} + +static inline void * +ble_npl_event_get_arg(struct ble_npl_event *ev) +{ + return ev->arg; +} + +static inline void +ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg) +{ + ev->arg = arg; +} + +static inline ble_npl_error_t +ble_npl_mutex_init(struct ble_npl_mutex *mu) +{ + mutex_init(&mu->mu); + return BLE_NPL_OK; +} + +static inline ble_npl_error_t +ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) +{ + assert(timeout == BLE_NPL_TIME_FOREVER); + mutex_lock(&mu->mu); + return BLE_NPL_OK; +} + +static inline ble_npl_error_t +ble_npl_mutex_release(struct ble_npl_mutex *mu) +{ + mutex_unlock(&mu->mu); + return BLE_NPL_OK; +} + +static inline ble_npl_error_t +ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) +{ + int rc; + + rc = sem_init(&sem->sem, 0, tokens); + + return rc == 0 ? BLE_NPL_OK : BLE_NPL_ERROR; +} + +static inline ble_npl_error_t +ble_npl_sem_release(struct ble_npl_sem *sem) +{ + int rc; + + rc = sem_post(&sem->sem); + + return rc == 0 ? BLE_NPL_OK : BLE_NPL_ERROR; +} + +static inline uint16_t +ble_npl_sem_get_count(struct ble_npl_sem *sem) +{ + int val = 0; + + sem_getvalue(&sem->sem, &val); + + return (uint16_t)val; +} + +static inline void +ble_npl_callout_stop(struct ble_npl_callout *co) +{ + xtimer_remove(&co->timer); +} + +static inline bool +ble_npl_callout_is_active(struct ble_npl_callout *c) +{ + return (c->timer.target || c->timer.long_target); +} + +static inline ble_npl_time_t +ble_npl_callout_get_ticks(struct ble_npl_callout *co) +{ + return co->target_ticks; +} + +static inline uint32_t +ble_npl_time_get(void) +{ + return xtimer_now_usec() / 1000; +} + +static inline ble_npl_error_t +ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) +{ + *out_ticks = ms; + return BLE_NPL_OK; +} + +static inline ble_npl_error_t +ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms) +{ + *out_ms = ticks; + return BLE_NPL_OK; +} + +static inline ble_npl_time_t +ble_npl_time_ms_to_ticks32(uint32_t ms) +{ + return ms; +} + +static inline uint32_t +ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) +{ + return ticks; +} + +static inline uint32_t +ble_npl_hw_enter_critical(void) +{ + return (uint32_t)irq_disable(); +} + +static inline void +ble_npl_hw_exit_critical(uint32_t ctx) +{ + irq_restore((unsigned)ctx); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _NPL_H_ */ diff --git a/porting/npl/riot/src/npl_os_riot.c b/porting/npl/riot/src/npl_os_riot.c new file mode 100644 index 000000000..fd3db6501 --- /dev/null +++ b/porting/npl/riot/src/npl_os_riot.c @@ -0,0 +1,66 @@ +/* + * 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 "nimble/nimble_npl.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static void +_callout_fire(void *arg) +{ + struct ble_npl_callout *co = (struct ble_npl_callout *)arg; + event_post(co->q, &co->e.e.super); +} + +ble_npl_error_t +ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) +{ + int rc; + struct timespec abs; + uint64_t time; + + time = xtimer_now_usec64() + ble_npl_time_ticks_to_ms32(timeout) * 1000; + abs.tv_sec = (time_t)(time / 1000000); + abs.tv_nsec = (long)((time % 1000000) * 1000); + + rc = sem_timedwait(&sem->sem, &abs); + + return rc == 0 ? BLE_NPL_OK : BLE_NPL_ENOENT; +} + +void +ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq, + ble_npl_event_fn *ev_cb, void *ev_arg) +{ + c->timer.arg = (void *)c; + c->timer.callback = _callout_fire; + c->q = &evq->q; + ble_npl_event_init(&c->e, ev_cb, ev_arg); +} + +ble_npl_error_t +ble_npl_callout_reset(struct ble_npl_callout *c, ble_npl_time_t ticks) +{ + uint32_t now = xtimer_now_usec(); + c->target_ticks = (ble_npl_time_t)((now / 1000) + ticks); + xtimer_set(&c->timer, ((ticks * 1000) - ((xtimer_now_usec() - now) / 1000))); + return BLE_NPL_OK; +} diff --git a/porting/npl/riot/src/nrf5x_isr.c b/porting/npl/riot/src/nrf5x_isr.c new file mode 100644 index 000000000..bf325ecb3 --- /dev/null +++ b/porting/npl/riot/src/nrf5x_isr.c @@ -0,0 +1,58 @@ +/* + * 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 "cpu.h" + +static uint32_t radio_isr_addr; +static uint32_t rng_isr_addr; +static uint32_t rtc0_isr_addr; + +void +isr_radio(void) +{ + ((void (*)(void))radio_isr_addr)(); +} + +void +isr_rng(void) +{ + ((void (*)(void))rng_isr_addr)(); +} + +void +isr_rtc0(void) +{ + ((void (*)(void))rtc0_isr_addr)(); +} + +void +ble_npl_hw_set_isr(int irqn, uint32_t addr) +{ + switch (irqn) { + case RADIO_IRQn: + radio_isr_addr = addr; + break; + case RNG_IRQn: + rng_isr_addr = addr; + break; + case RTC0_IRQn: + rtc0_isr_addr = addr; + break; + } +}