[linux] Linux port using NPL (Nimble Platform Layer).

- Added linux implementations of npl abstractions:
  * callout, eventq, mutex, sem, time
This commit is contained in:
Martin Turon
2018-05-25 20:14:51 -07:00
parent 3d4e20ca33
commit f07c96621d
24 changed files with 3079 additions and 2 deletions
+14 -2
View File
@@ -17,6 +17,18 @@
# under the License.
#
# Toolchain commands
CROSS_COMPILE ?=
CC := ccache $(CROSS_COMPLIE)gcc
CXX := ccache $(CROSS_COMPILE)g++
LD := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
AS := $(CROSS_COMPILE)as
NM := $(CROSS_COMPILE)nm
OBJDUMP := $(CROSS_COMPILE)objdump
OBJCOPY := $(CROSS_COMPILE)objcopy
SIZE := $(CROSS_COMPILE)size
# Configure NimBLE variables
NIMBLE_ROOT := ../../..
NIMBLE_CFG_TINYCRYPT := 1
@@ -48,7 +60,7 @@ clean:
rm dummy -f
%.o: %.c
$(CC) -m32 -c $(addprefix -I, $(INC)) $(CFLAGS) -o $@ $<
$(CC) -c $(addprefix -I, $(INC)) $(CFLAGS) -o $@ $<
dummy: $(OBJ)
$(CC) -m32 -o $@ $^
$(CC) -o $@ $^
+81
View File
@@ -0,0 +1,81 @@
# Toolchain commands
CROSS_COMPILE ?=
CC := ccache $(CROSS_COMPLIE)gcc
CXX := ccache $(CROSS_COMPILE)g++
LD := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
AS := $(CROSS_COMPILE)as
NM := $(CROSS_COMPILE)nm
OBJDUMP := $(CROSS_COMPILE)objdump
OBJCOPY := $(CROSS_COMPILE)objcopy
SIZE := $(CROSS_COMPILE)size
# Configure NimBLE variables
NIMBLE_ROOT := ../../..
NIMBLE_CFG_TINYCRYPT := 1
include $(NIMBLE_ROOT)/porting/nimble/Makefile.defs
SRC := $(NIMBLE_SRC)
# Source files for NPL OSAL
SRC += \
$(NIMBLE_ROOT)/porting/npl/linux/src/os_atomic.c \
$(NIMBLE_ROOT)/porting/npl/linux/src/os_callout.c \
$(NIMBLE_ROOT)/porting/npl/linux/src/os_eventq.cc \
$(NIMBLE_ROOT)/porting/npl/linux/src/os_mutex.c \
$(NIMBLE_ROOT)/porting/npl/linux/src/os_sem.c \
$(NIMBLE_ROOT)/porting/npl/linux/src/os_task.c \
$(NIMBLE_ROOT)/porting/npl/linux/src/os_time.c \
$(NIMBLE_ROOT)/nimble/transport/socket/src/ble_hci_socket.c \
$(NULL)
# Source files for demo app
SRC += \
./ble.c \
./main.c \
$(NULL)
# Add NPL and all NimBLE directories to include paths
INC = \
./include \
$(NIMBLE_ROOT)/porting/npl/linux/include \
$(NIMBLE_ROOT)/porting/npl/linux/src \
$(NIMBLE_ROOT)/nimble/transport/socket/include \
$(NIMBLE_INCLUDE) \
$(NULL)
INCLUDES := $(addprefix -I, $(INC))
SRC_C = $(filter %.c, $(SRC))
SRC_CC = $(filter %.cc, $(SRC))
OBJ := $(SRC_C:.c=.o)
OBJ += $(SRC_CC:.cc=.o)
CFLAGS = \
$(NIMBLE_CFLAGS) \
$(INCLUDES) \
-g \
-D_GNU_SOURCE \
$(NULL)
LIBS := -lrt -lpthread -lstdc++
.PHONY: all clean
.DEFAULT: all
all: nimble-linux
clean:
rm $(OBJ) -f
rm dummy -f
%.o: %.c
$(CC) -c $(INCLUDES) $(CFLAGS) -o $@ $<
%.o: %.cc
$(CXX) -c $(INCLUDES) $(CFLAGS) -o $@ $<
nimble-linux: $(OBJ)
$(LD) -o $@ $^ $(LIBS)
$(SIZE) $@
+73
View File
@@ -0,0 +1,73 @@
<!--
#
# 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.
#
-->
# Apache Mynewt NimBLE
## Overview
See (https://mynewt.apache.org/network/ble/ble_intro/).
## Building
NimBLE is usually built as a part of Apache Mynewt OS, but ports for
other RTOS-es are also available.
### Linux
1. Build the sample application
```no-highlight
cd porting/examples/linux
make
```
2. Run the sample application
First insert a USB Bluetooth dongle. These are typically BLE 4.0 capable.
Verify the dongle is connected with hciconfig:
```no-highlight
$ hciconfig
hci0: Type: BR/EDR Bus: USB
BD Address: 00:1B:DC:06:62:5E ACL MTU: 310:10 SCO MTU: 64:8
DOWN
RX bytes:5470 acl:0 sco:0 events:40 errors:0
TX bytes:5537 acl:176 sco:0 commands:139 errors:1
```
Then run the application built in step one. The application is configured
in sysconfig.h to use hci0.
```no-highlight
cd porting/examples/linux
sudo ./_build/nimble_linux.out
```
3. Build and run the unit tests
The Operating System Abstraction Layer (OSAL) used to port Nimble to Linux
has a suite of unit tests.
```no-highlight
cd tests/unit/porting/npl
make test
```
+116
View File
@@ -0,0 +1,116 @@
/*
* 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 <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "nimble/nimble_port.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "services/gap/ble_svc_gap.h"
static const char gap_name[] = "nimble";
static uint8_t own_addr_type;
static void start_advertise(void);
static void
put_ad(uint8_t ad_type, uint8_t ad_len, const void *ad, uint8_t *buf,
uint8_t *len)
{
buf[(*len)++] = ad_len + 1;
buf[(*len)++] = ad_type;
memcpy(&buf[*len], ad, ad_len);
*len += ad_len;
}
static void
update_ad(void)
{
uint8_t ad[BLE_HS_ADV_MAX_SZ];
uint8_t ad_len = 0;
uint8_t ad_flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
put_ad(BLE_HS_ADV_TYPE_FLAGS, 1, &ad_flags, ad, &ad_len);
put_ad(BLE_HS_ADV_TYPE_COMP_NAME, sizeof(gap_name), gap_name, ad, &ad_len);
ble_gap_adv_set_data(ad, ad_len);
}
static int
gap_event_cb(struct ble_gap_event *event, void *arg)
{
switch (event->type) {
case BLE_GAP_EVENT_CONNECT:
if (event->connect.status) {
start_advertise();
}
break;
case BLE_GAP_EVENT_DISCONNECT:
start_advertise();
break;
}
return 0;
}
static void
start_advertise(void)
{
struct ble_gap_adv_params advp;
int rc;
update_ad();
memset(&advp, 0, sizeof advp);
advp.conn_mode = BLE_GAP_CONN_MODE_UND;
advp.disc_mode = BLE_GAP_DISC_MODE_GEN;
rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
&advp, gap_event_cb, NULL);
assert(rc == 0);
}
static void
app_ble_sync_cb(void)
{
int rc;
rc = ble_hs_util_ensure_addr(0);
assert(rc == 0);
rc = ble_hs_id_infer_auto(0, &own_addr_type);
assert(rc == 0);
start_advertise();
}
void
nimble_host_task(void *param)
{
ble_hs_cfg.sync_cb = app_ble_sync_cb;
ble_svc_gap_device_name_set(gap_name);
nimble_port_run();
}
File diff suppressed because it is too large Load Diff
+89
View File
@@ -0,0 +1,89 @@
/*
* 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 <stdbool.h>
#include <stdint.h>
#include <pthread.h>
#include "nimble/nimble_npl.h"
#include "nimble/nimble_port.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "services/ans/ble_svc_ans.h"
#include "services/ias/ble_svc_ias.h"
#include "services/lls/ble_svc_lls.h"
#include "services/tps/ble_svc_tps.h"
static struct ble_npl_task s_task_host;
static struct ble_npl_task s_task_hci;
void nimble_host_task(void *param);
void ble_hci_sock_ack_handler(void *param);
void ble_hci_sock_init(void);
#define TASK_DEFAULT_PRIORITY 1
#define TASK_DEFAULT_STACK NULL
#define TASK_DEFAULT_STACK_SIZE 400
void *ble_hci_sock_task(void *param)
{
ble_hci_sock_ack_handler(param);
return NULL;
}
void *ble_host_task(void *param)
{
nimble_host_task(param);
return NULL;
}
int main(void)
{
ble_hci_sock_init();
nimble_port_init();
/* This example provides GATT Alert service */
ble_svc_gap_init();
ble_svc_gatt_init();
ble_svc_ans_init();
ble_svc_ias_init();
ble_svc_lls_init();
ble_svc_tps_init();
/* XXX Need to have template for store */
ble_store_ram_init();
ble_npl_task_init(&s_task_hci, "hci_sock", ble_hci_sock_task,
NULL, TASK_DEFAULT_PRIORITY, BLE_NPL_WAIT_FOREVER,
TASK_DEFAULT_STACK, TASK_DEFAULT_STACK_SIZE);
/* Create task which handles default event queue for host stack. */
ble_npl_task_init(&s_task_host, "ble_host", ble_host_task,
NULL, TASK_DEFAULT_PRIORITY, BLE_NPL_WAIT_FOREVER,
TASK_DEFAULT_STACK, TASK_DEFAULT_STACK_SIZE);
int ret = 0;
pthread_exit(&ret);
while (true)
{
pthread_yield();
}
}
@@ -0,0 +1,54 @@
/*
* 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 <assert.h>
#include <stdint.h>
#include <string.h>
#include "npl_osal.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BLE_NPL_OS_ALIGNMENT 4
#define BLE_NPL_TIME_FOREVER INT32_MAX
/* This should be compatible with TickType_t */
typedef uint32_t ble_npl_time_t;
typedef int32_t ble_npl_stime_t;
#define SYSINIT_PANIC_MSG(msg) __assert_fail(msg, __FILE__, __LINE__, __func__)
#define SYSINIT_PANIC_ASSERT_MSG(rc, msg) do \
{ \
if (!(rc)) { \
SYSINIT_PANIC_MSG(msg); \
} \
} while (0)
#ifdef __cplusplus
}
#endif
#endif /* _NPL_H_ */
+29
View File
@@ -0,0 +1,29 @@
/*
* 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 _NPL_OSAL_H
#define _NPL_OSAL_H
#include "os_types.h"
#include "nimble/nimble_npl.h"
#include "os/os.h"
#endif // _NPL_OSAL_H
+36
View File
@@ -0,0 +1,36 @@
/*
* 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 <stdint.h>
#include <pthread.h>
#include "npl_osal.h"
static pthread_mutex_t s_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
uint32_t ble_npl_hw_enter_critical(void)
{
pthread_mutex_lock(&s_mutex);
return 0;
}
void ble_npl_hw_exit_critical(uint32_t ctx)
{
pthread_mutex_unlock(&s_mutex);
}
+132
View File
@@ -0,0 +1,132 @@
/*
* 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 <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include "npl_osal.h"
static void
ble_npl_callout_timer_cb(union sigval sv)
{
struct ble_npl_callout *c = (struct ble_npl_callout *)sv.sival_ptr;
assert(c);
if (c->c_evq) {
ble_npl_eventq_put(c->c_evq, &c->c_ev);
} else {
c->c_ev.ev_cb(&c->c_ev);
}
}
void ble_npl_callout_init(struct ble_npl_callout *c,
struct ble_npl_eventq *evq,
ble_npl_event_fn *ev_cb,
void *ev_arg)
{
struct sigevent event;
/* Initialize the callout. */
memset(c, 0, sizeof(*c));
c->c_ev.ev_cb = ev_cb;
c->c_ev.ev_arg = ev_arg;
c->c_evq = evq;
c->c_active = false;
event.sigev_notify = SIGEV_THREAD;
event.sigev_value.sival_ptr = c; // put callout obj in signal args
event.sigev_notify_function = ble_npl_callout_timer_cb;
event.sigev_notify_attributes = NULL;
timer_create(CLOCK_REALTIME, &event, &c->c_timer);
}
bool ble_npl_callout_is_active(struct ble_npl_callout *c)
{
// TODO: seek native posix method to determine whether timer_t is active.
// TODO: fix bug where one-shot timer is still active after fired.
return c->c_active;
}
int ble_npl_callout_inited(struct ble_npl_callout *c)
{
return (c->c_timer != NULL);
}
ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *c,
ble_npl_time_t ticks)
{
struct itimerspec its;
if (ticks < 0) {
return BLE_NPL_EINVAL;
}
if (ticks == 0) {
ticks = 1;
}
c->c_ticks = ble_npl_time_get() + ticks;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0; // one shot
its.it_value.tv_sec = (ticks / 1000);
its.it_value.tv_nsec = (ticks % 1000) * 1000000; // expiration
its.it_value.tv_nsec %= 1000000000;
c->c_active = true;
timer_settime(c->c_timer, 0, &its, NULL);
return BLE_NPL_OK;
}
int ble_npl_callout_queued(struct ble_npl_callout *c)
{
struct itimerspec its;
timer_gettime(c->c_timer, &its);
return ((its.it_value.tv_sec > 0) ||
(its.it_value.tv_nsec > 0));
}
void ble_npl_callout_stop(struct ble_npl_callout *c)
{
if (!ble_npl_callout_inited(c)) {
return;
}
struct itimerspec its;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 0;
timer_settime(c->c_timer, 0, &its, NULL);
c->c_active = false;
}
ble_npl_time_t
ble_npl_callout_get_ticks(struct ble_npl_callout *co)
{
return co->c_ticks;
}
+129
View File
@@ -0,0 +1,129 @@
/*
* 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 <assert.h>
#include <stdint.h>
#include <string.h>
#include "npl_osal.h"
#include "wqueue.h"
extern "C" {
typedef wqueue<ble_npl_event *> wqueue_t;
static struct ble_npl_eventq dflt_evq;
struct ble_npl_eventq *
ble_npl_eventq_dflt_get(void)
{
if (!dflt_evq.q) {
dflt_evq.q = new wqueue_t();
}
return &dflt_evq;
}
void
ble_npl_eventq_init(struct ble_npl_eventq *evq)
{
evq->q = new wqueue_t();
}
int
ble_npl_eventq_inited(const struct ble_npl_eventq *evq)
{
return (evq->q != NULL);
}
void
ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
{
wqueue_t *q = static_cast<wqueue_t *>(evq->q);
if (ev->ev_queued) {
return;
}
ev->ev_queued = 1;
q->put(ev);
}
struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *evq,
ble_npl_time_t tmo)
{
struct ble_npl_event *ev;
wqueue_t *q = static_cast<wqueue_t *>(evq->q);
ev = q->get();
ev->ev_queued = 0;
return ev;
}
void
ble_npl_eventq_run(struct ble_npl_eventq *evq)
{
struct ble_npl_event *ev;
ev = ble_npl_eventq_get(evq, BLE_NPL_TIME_FOREVER);
ble_npl_event_run(ev);
}
// ========================================================================
// Event Implementation
// ========================================================================
void
ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
void *arg)
{
memset(ev, 0, sizeof(*ev));
ev->ev_cb = fn;
ev->ev_arg = arg;
}
bool
ble_npl_event_is_queued(struct ble_npl_event *ev)
{
return ev->ev_queued;
}
void *
ble_npl_event_get_arg(struct ble_npl_event *ev)
{
return ev->ev_arg;
}
void
ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg)
{
ev->ev_arg = arg;
}
void
ble_npl_event_run(struct ble_npl_event *ev)
{
assert(ev->ev_cb != NULL);
ev->ev_cb(ev);
}
}
+76
View File
@@ -0,0 +1,76 @@
/*
* 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 <assert.h>
#include <stdint.h>
#include <string.h>
#include "os/os.h"
#include <pthread.h>
ble_npl_error_t
ble_npl_mutex_init(struct ble_npl_mutex *mu)
{
pthread_mutexattr_t mu_attr;
if (!mu) {
return BLE_NPL_INVALID_PARAM;
}
pthread_mutexattr_settype(&mu_attr, PTHREAD_MUTEX_RECURSIVE_NP);
pthread_mutex_init(&mu->lock, &mu_attr);
return BLE_NPL_OK;
}
ble_npl_error_t
ble_npl_mutex_release(struct ble_npl_mutex *mu)
{
if (!mu) {
return BLE_NPL_INVALID_PARAM;
}
if (pthread_mutex_unlock(&mu->lock)) {
return BLE_NPL_BAD_MUTEX;
}
return BLE_NPL_OK;
}
ble_npl_error_t
ble_npl_mutex_pend(struct ble_npl_mutex *mu, uint32_t timeout)
{
struct timespec wait;
if (!mu) {
return BLE_NPL_INVALID_PARAM;
}
assert(&mu->lock);
wait.tv_sec = timeout / 1000;
wait.tv_nsec = (timeout % 1000) * 1000000;
wait.tv_nsec %= 1000000000;
if (pthread_mutex_timedlock(&mu->lock, &wait)) {
return BLE_NPL_TIMEOUT;
}
return BLE_NPL_OK;
}
+99
View File
@@ -0,0 +1,99 @@
/*
* 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 <assert.h>
#include <stdint.h>
#include <string.h>
#include "os/os.h"
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
ble_npl_error_t
ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
{
if (!sem) {
return BLE_NPL_INVALID_PARAM;
}
sem_init(&sem->lock, 0, tokens);
return BLE_NPL_OK;
}
ble_npl_error_t
ble_npl_sem_release(struct ble_npl_sem *sem)
{
int err;
if (!sem) {
return BLE_NPL_INVALID_PARAM;
}
err = sem_post(&sem->lock);
return (err) ? BLE_NPL_ERROR : BLE_NPL_OK;
}
ble_npl_error_t
ble_npl_sem_pend(struct ble_npl_sem *sem, uint32_t timeout)
{
int err = 0;
struct timespec wait;
if (!sem) {
return BLE_NPL_INVALID_PARAM;
}
err = clock_gettime(CLOCK_REALTIME, &wait);
if (err) {
return BLE_NPL_ERROR;
}
wait.tv_sec += timeout / 1000;
wait.tv_nsec += (timeout % 1000) * 1000000;
wait.tv_nsec %= 1000000000;
if (timeout == BLE_NPL_WAIT_FOREVER) {
err = sem_wait(&sem->lock);
}
else
{
if (sem_timedwait(&sem->lock, &wait)) {
assert(errno == ETIMEDOUT);
return BLE_NPL_TIMEOUT;
}
}
return (err) ? BLE_NPL_ERROR : BLE_NPL_OK;
}
uint16_t
ble_npl_sem_get_count(struct ble_npl_sem *sem)
{
int count;
assert(sem);
assert(&sem->lock);
sem_getvalue(&sem->lock, &count);
return count;
}
+110
View File
@@ -0,0 +1,110 @@
/*
* 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 "os/os.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Initialize a task.
*
* This function initializes the task structure pointed to by t,
* clearing and setting it's stack pointer, provides sane defaults
* and sets the task as ready to run, and inserts it into the operating
* system scheduler.
*
* @param t The task to initialize
* @param name The name of the task to initialize
* @param func The task function to call
* @param arg The argument to pass to this task function
* @param prio The priority at which to run this task
* @param sanity_itvl The time at which this task should check in with the
* sanity task. OS_WAIT_FOREVER means never check in
* here.
* @param stack_bottom A pointer to the bottom of a task's stack
* @param stack_size The overall size of the task's stack.
*
* @return 0 on success, non-zero on failure.
*/
int
ble_npl_task_init(struct ble_npl_task *t, const char *name, ble_npl_task_func_t func,
void *arg, uint8_t prio, ble_npl_time_t sanity_itvl,
ble_npl_stack_t *stack_bottom, uint16_t stack_size)
{
int err;
if ((t == NULL) || (func == NULL)) {
return OS_INVALID_PARM;
}
pthread_attr_t attr;
struct sched_param param;
err = pthread_attr_init(&attr);
if (err) return err;
err = pthread_attr_getschedparam (&attr, &param);
if (err) return err;
err = pthread_attr_setschedpolicy(&attr, SCHED_RR);
if (err) return err;
param.sched_priority = prio;
err = pthread_attr_setschedparam (&attr, &param);
if (err) return err;
t->name = name;
err = pthread_create(&t->handle, &attr, func, arg);
return err;
}
/*
* Removes specified task
* XXX
* NOTE: This interface is currently experimental and not ready for common use
*/
int
ble_npl_task_remove(struct ble_npl_task *t)
{
return pthread_cancel(t->handle);
}
/**
* Return the number of tasks initialized.
*
* @return number of tasks initialized
*/
uint8_t
ble_npl_task_count(void)
{
return 0;
}
void *
ble_npl_get_current_task_id(void)
{
return (void *)pthread_self();
}
bool ble_npl_os_started(void)
{
return true;
}
#ifdef __cplusplus
}
#endif
+64
View File
@@ -0,0 +1,64 @@
/*
* 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 <assert.h>
#include <stdint.h>
#include <string.h>
#include "os/os.h"
#include <time.h>
/**
* Return ticks [ms] since system start as uint32_t.
*/
ble_npl_time_t
ble_npl_time_get(void)
{
struct timespec now;
if (clock_gettime(CLOCK_MONOTONIC, &now)) {
return 0;
}
return now.tv_sec * 1000.0 + now.tv_nsec / 1000000.0;
}
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;
}
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;
}
ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms)
{
return ms;
}
uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks)
{
return ticks;
}
+85
View File
@@ -0,0 +1,85 @@
/*
* 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 _NPL_OS_TYPES_H
#define _NPL_OS_TYPES_H
#include <time.h>
#include <signal.h>
#include <stdbool.h>
#include <pthread.h>
#include <semaphore.h>
#define BLE_NPL_WAIT_FOREVER (-1)
/* The highest and lowest task priorities */
#define OS_TASK_PRI_HIGHEST (sched_get_priority_max(SCHED_RR))
#define OS_TASK_PRI_LOWEST (sched_get_priority_min(SCHED_RR))
typedef uint32_t ble_npl_time_t;
typedef int32_t ble_npl_stime_t;
//typedef int os_sr_t;
typedef int ble_npl_stack_t;
struct ble_npl_event;
typedef void ble_npl_event_fn(struct ble_npl_event *ev);
struct ble_npl_event {
uint8_t ev_queued;
ble_npl_event_fn *ev_cb;
void *ev_arg;
};
struct ble_npl_eventq {
void *q;
};
struct ble_npl_callout {
struct ble_npl_event c_ev;
struct ble_npl_eventq *c_evq;
uint32_t c_ticks;
timer_t c_timer;
bool c_active;
};
struct ble_npl_mutex {
pthread_mutex_t lock;
};
struct ble_npl_sem {
sem_t lock;
};
struct ble_npl_task {
pthread_t handle;
const char* name;
};
typedef void *(*ble_npl_task_func_t)(void *);
int ble_npl_task_init(struct ble_npl_task *t, const char *name, ble_npl_task_func_t func,
void *arg, uint8_t prio, ble_npl_time_t sanity_itvl,
ble_npl_stack_t *stack_bottom, uint16_t stack_size);
int ble_npl_task_remove(struct ble_npl_task *t);
uint8_t ble_npl_task_count(void);
#endif // _NPL_OS_TYPES_H
+76
View File
@@ -0,0 +1,76 @@
/*
wqueue.h
Worker thread queue based on the Standard C++ library list
template class.
------------------------------------------
Copyright (c) 2013 Vic Hargrave
Licensed 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.
*/
// https://vichargrave.github.io/articles/2013-01/multithreaded-work-queue-in-cpp
// https://github.com/vichargrave/wqueue/blob/master/wqueue.h
#ifndef __wqueue_h__
#define __wqueue_h__
#include <pthread.h>
#include <list>
using namespace std;
template <typename T> class wqueue
{
list<T> m_queue;
pthread_mutex_t m_mutex;
pthread_cond_t m_condv;
public:
wqueue()
{
pthread_mutexattr_t attr;
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attr);
pthread_cond_init(&m_condv, NULL);
}
~wqueue() {
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_condv);
}
void put(T item) {
pthread_mutex_lock(&m_mutex);
m_queue.push_back(item);
pthread_cond_signal(&m_condv);
pthread_mutex_unlock(&m_mutex);
}
T get() {
pthread_mutex_lock(&m_mutex);
while (m_queue.size() == 0) {
pthread_cond_wait(&m_condv, &m_mutex);
}
T item = m_queue.front();
m_queue.pop_front();
pthread_mutex_unlock(&m_mutex);
return item;
}
int size() {
pthread_mutex_lock(&m_mutex);
int size = m_queue.size();
pthread_mutex_unlock(&m_mutex);
return size;
}
};
#endif
+103
View File
@@ -0,0 +1,103 @@
# Makefile
PROJ_ROOT = ../../../..
### ===== Toolchain =====
CROSS_COMPILE ?=
CC = ccache $(CROSS_COMPILE)gcc
CPP = ccache $(CROSS_COMPILE)g++
LD = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar
### ===== Compiler Flags =====
INCLUDES = \
-I. \
-I$(PROJ_ROOT)/nimble/include \
-I$(PROJ_ROOT)/porting/npl/linux/include \
-I$(PROJ_ROOT)/porting/npl/linux/src \
-I$(PROJ_ROOT)/porting/nimble/include \
$(NULL)
DEFINES =
CFLAGS = \
$(INCLUDES) $(DEFINES) \
-g \
-D_GNU_SOURCE \
$(NULL)
LIBS = -lrt -lpthread -lstdc++
LDFLAGS =
### ===== Sources =====
OSAL_PATH = $(PROJ_ROOT)/porting/npl/linux/src
SRCS = $(shell find $(OSAL_PATH) -maxdepth 1 -name '*.c')
SRCS += $(shell find $(OSAL_PATH) -maxdepth 1 -name '*.cc')
SRCS += $(PROJ_ROOT)/porting/nimble/src/os_mempool.c
OBJS = $(patsubst %.c, %.o,$(filter %.c, $(SRCS)))
OBJS += $(patsubst %.cc,%.o,$(filter %.cc, $(SRCS)))
TEST_SRCS = $(shell find . -maxdepth 1 -name '*.c')
TEST_SRCS += $(shell find . -maxdepth 1 -name '*.cc')
TEST_OBJS = $(patsubst %.c, %.o,$(filter %.c, $(SRCS)))
TEST_OBJS += $(patsubst %.cc,%.o,$(filter %.cc, $(SRCS)))
### ===== Rules =====
all: depend \
test_npl_task.exe \
test_npl_callout.exe \
test_npl_eventq.exe \
test_npl_sem.exe \
$(NULL)
test_npl_task.exe: test_npl_task.o $(OBJS)
$(LD) -o $@ $^ $(LDFLAGS) $(LIBS)
test_npl_eventq.exe: test_npl_eventq.o $(OBJS)
$(LD) -o $@ $^ $(LDFLAGS) $(LIBS)
test_npl_callout.exe: test_npl_callout.o $(OBJS)
$(LD) -o $@ $^ $(LDFLAGS) $(LIBS)
test_npl_sem.exe: test_npl_sem.o $(OBJS)
$(LD) -o $@ $^ $(LDFLAGS) $(LIBS)
test: all
./test_npl_task.exe
./test_npl_callout.exe
./test_npl_eventq.exe
./test_npl_sem.exe
show_objs:
@echo $(OBJS)
### ===== Clean =====
clean:
@echo "Cleaning artifacts."
rm *~ .depend $(OBJS) *.o *.exe
### ===== Dependencies =====
### Rebuild if headers change
depend: .depend
.depend: $(SRCS) $(TEST_SRCS)
@echo "Building dependencies."
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ > ./.depend;
include .depend
### Generic rules based on extension
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
%.o: %.cc
$(CPP) -c $(CFLAGS) $< -o $@
+116
View File
@@ -0,0 +1,116 @@
/*
* 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.
*/
/**
Unit tests for the ble_npl_callout api:
void ble_npl_callout_init(struct ble_npl_callout *cf, struct ble_npl_eventq *evq,
ble_npl_event_fn *ev_cb, void *ev_arg);
int ble_npl_callout_reset(struct ble_npl_callout *, int32_t);
int ble_npl_callout_queued(struct ble_npl_callout *c);
void ble_npl_callout_stop(struct ble_npl_callout *c);
*/
#include "test_util.h"
#include "nimble/nimble_npl.h"
#define TEST_ARGS_VALUE (55)
#define TEST_INTERVAL (100)
static bool s_tests_running = true;
static struct ble_npl_task s_task;
static struct ble_npl_callout s_callout;
static int s_callout_args = TEST_ARGS_VALUE;
static struct ble_npl_eventq s_eventq;
void on_callout(struct ble_npl_event *ev)
{
VerifyOrQuit(ev->ev_arg == &s_callout_args,
"callout: wrong args passed");
VerifyOrQuit(*(int*)ev->ev_arg == TEST_ARGS_VALUE,
"callout: args corrupted");
s_tests_running = false;
}
/**
* ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq,
* ble_npl_event_fn *ev_cb, void *ev_arg)
*/
int test_init()
{
ble_npl_callout_init(&s_callout,
&s_eventq,
on_callout,
&s_callout_args);
return PASS;
}
int test_queued()
{
//VerifyOrQuit(ble_npl_callout_queued(&s_callout),
// "callout: not queued when expected");
return PASS;
}
int test_reset()
{
return ble_npl_callout_reset(&s_callout, TEST_INTERVAL);
}
int test_stop()
{
return PASS;
}
/**
* ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq,
* ble_npl_event_fn *ev_cb, void *ev_arg)
*/
void *test_task_run(void *args)
{
SuccessOrQuit(test_init(), "callout_init failed");
SuccessOrQuit(test_queued(), "callout_queued failed");
SuccessOrQuit(test_reset(), "callout_reset failed");
while (s_tests_running)
{
ble_npl_eventq_run(&s_eventq);
}
printf("All tests passed\n");
exit(PASS);
return NULL;
}
int main(void)
{
ble_npl_eventq_init(&s_eventq);
SuccessOrQuit(ble_npl_task_init(&s_task, "s_task", test_task_run,
NULL, 1, 0, NULL, 0),
"task: error initializing");
while (1) {}
}
+130
View File
@@ -0,0 +1,130 @@
/*
* 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.
*/
/**
Unit tests for the ble_npl_eventq api:
void ble_npl_eventq_init(struct ble_npl_eventq *);
void ble_npl_eventq_put(struct ble_npl_eventq *, struct ble_npl_event *);
struct ble_npl_event *ble_npl_eventq_get_no_wait(struct ble_npl_eventq *evq);
struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *);
void ble_npl_eventq_run(struct ble_npl_eventq *evq);
struct ble_npl_event *ble_npl_eventq_poll(struct ble_npl_eventq **, int, ble_npl_time_t);
void ble_npl_eventq_remove(struct ble_npl_eventq *, struct ble_npl_event *);
struct ble_npl_eventq *ble_npl_eventq_dflt_get(void);
*/
#include <assert.h>
#include <pthread.h>
#include "test_util.h"
#include "nimble/nimble_npl.h"
#define TEST_ARGS_VALUE (55)
#define TEST_STACK_SIZE (1024)
static bool s_tests_running = true;
static struct ble_npl_task s_task_runner;
static struct ble_npl_task s_task_dispatcher;
static struct ble_npl_eventq s_eventq;
static struct ble_npl_event s_event;
static int s_event_args = TEST_ARGS_VALUE;
void on_event(struct ble_npl_event *ev)
{
VerifyOrQuit(ev->ev_arg == &s_event_args,
"callout: wrong args passed");
VerifyOrQuit(*(int*)ev->ev_arg == TEST_ARGS_VALUE,
"callout: args corrupted");
s_tests_running = false;
}
int test_init()
{
//VerifyOrQuit(!ble_npl_eventq_inited(&s_eventq), "eventq: empty q initialized");
ble_npl_eventq_init(&s_eventq);
//VerifyOrQuit(ble_npl_eventq_inited(&s_eventq), "eventq: not initialized");
return PASS;
}
int test_run()
{
while (s_tests_running)
{
ble_npl_eventq_run(&s_eventq);
}
return PASS;
}
int test_put()
{
s_event.ev_cb = on_event;
s_event.ev_arg = &s_event_args;
ble_npl_eventq_put(&s_eventq, &s_event);
return PASS;
}
int test_get_no_wait()
{
//struct ble_npl_event *ev = ble_npl_eventq_get_no_wait(&s_eventq);
return FAIL;
}
int test_get()
{
struct ble_npl_event *ev = ble_npl_eventq_get(&s_eventq);
VerifyOrQuit(ev == &s_event,
"callout: wrong event passed");
return PASS;
}
void *task_test_runner(void *args)
{
int count = 1000000000;
SuccessOrQuit(test_init(), "eventq_init failed");
SuccessOrQuit(test_put(), "eventq_put failed");
SuccessOrQuit(test_get(), "eventq_get failed");
SuccessOrQuit(test_put(), "eventq_put failed");
SuccessOrQuit(test_run(), "eventq_run failed");
printf("All tests passed\n");
exit(PASS);
return NULL;
}
int main(void)
{
SuccessOrQuit(ble_npl_task_init(&s_task_runner,
"task_test_runner",
task_test_runner,
NULL, 1, 0, NULL, 0),
"task: error initializing");
while (1) {}
}
+111
View File
@@ -0,0 +1,111 @@
/*
* 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 "test_util.h"
#include "nimble/nimble_npl.h"
#define TEST_MEMPOOL_BLOCKS 4
#define TEST_MEMPOOL_BLOCK_SIZE 128
static struct ble_npl_mempool s_mempool;
static os_membuf_t s_mempool_mem[OS_MEMPOOL_SIZE(TEST_MEMPOOL_BLOCKS,
TEST_MEMPOOL_BLOCK_SIZE)];
static void *s_memblock[TEST_MEMPOOL_BLOCKS];
/**
* Unit test for initializing a mempool.
*
* ble_npl_error_t ble_npl_mempool_init(struct ble_npl_mempool *mp, int blocks,
* int block_size, void *membuf, char *name);
*
*/
int test_init()
{
int err;
err = ble_npl_mempool_init(NULL,
TEST_MEMPOOL_BLOCKS,
TEST_MEMPOOL_BLOCK_SIZE,
NULL,
"Null mempool");
VerifyOrQuit(err, "ble_npl_mempool_init accepted NULL parameters.");
err = ble_npl_mempool_init(&s_mempool,
TEST_MEMPOOL_BLOCKS,
TEST_MEMPOOL_BLOCK_SIZE,
s_mempool_mem,
"s_mempool");
return err;
}
/**
* Test integrity check of a mempool.
*
* bool ble_npl_mempool_is_sane(const struct ble_npl_mempool *mp);
*/
int test_is_sane()
{
return (ble_npl_mempool_is_sane(&s_mempool)) ? PASS : FAIL;
}
/**
* Test getting a memory block from the pool, putting it back,
* and checking if it is still valid.
*
* void *ble_npl_memblock_get(struct ble_npl_mempool *mp);
*
* ble_npl_error_t ble_npl_memblock_put(struct ble_npl_mempool *mp, void *block_addr);
*
* int ble_npl_memblock_from(const struct ble_npl_mempool *mp, const void *block_addr);
*/
int test_stress()
{
int loops = 3;
while(loops--)
{
for (int i = 0; i < 4; i++)
{
s_memblock[i] = ble_npl_memblock_get(&s_mempool);
VerifyOrQuit(ble_npl_memblock_from(&s_mempool, s_memblock[i]),
"ble_npl_memblock_get return invalid block.");
}
for (int i = 0; i < 4; i++)
{
SuccessOrQuit(ble_npl_memblock_put(&s_mempool, s_memblock[i]),
"ble_npl_memblock_put refused to take valid block.");
//VerifyOrQuit(!ble_npl_memblock_from(&s_mempool, s_memblock[i]),
// "Block still valid after ble_npl_memblock_put.");
}
}
return PASS;
}
int main(void)
{
SuccessOrQuit(test_init(), "Failed: ble_npl_mempool_init");
SuccessOrQuit(test_is_sane(), "Failed: ble_npl_mempool_is_sane");
SuccessOrQuit(test_stress(), "Failed: ble_npl_mempool stree test");
SuccessOrQuit(test_is_sane(), "Failed: ble_npl_mempool_is_sane");
printf("All tests passed\n");
return PASS;
}
+155
View File
@@ -0,0 +1,155 @@
/*
* 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.
*/
/**
Unit tests for the Semaphore api (ble_npl_sem):
ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens);
ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem);
ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, uint32_t timeout);
uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem);
*/
#include "test_util.h"
#include "nimble/nimble_npl.h"
//#include "os/os.h"
#define TEST_ITERATIONS 10
#define TASK1_PRIO 1
#define TASK2_PRIO 1
#define TASK1_STACK_SIZE 1028
#define TASK2_STACK_SIZE 1028
static struct ble_npl_task task1;
static struct ble_npl_task task2;
static ble_npl_stack_t task1_stack[TASK1_STACK_SIZE];
static ble_npl_stack_t task2_stack[TASK2_STACK_SIZE];
struct ble_npl_sem task1_sem;
struct ble_npl_sem task2_sem;
/* Task 1 handler function */
void *
task1_handler(void *arg)
{
for (int i = 0; i < TEST_ITERATIONS; i++)
{
/* Release semaphore to task 2 */
SuccessOrQuit(ble_npl_sem_release(&task1_sem),
"ble_npl_sem_release: error releasing task2_sem.");
/* Wait for semaphore from task 2 */
SuccessOrQuit(ble_npl_sem_pend(&task2_sem, BLE_NPL_TIME_FOREVER),
"ble_npl_sem_pend: error waiting for task2_sem.");
}
printf("All tests passed\n");
exit(PASS);
return NULL;
}
/* Task 2 handler function */
void *
task2_handler(void *arg)
{
while(1)
{
/* Wait for semaphore from task1 */
SuccessOrQuit(ble_npl_sem_pend(&task1_sem, BLE_NPL_TIME_FOREVER),
"ble_npl_sem_pend: error waiting for task1_sem.");
/* Release task2 semaphore */
SuccessOrQuit(ble_npl_sem_release(&task2_sem),
"ble_npl_sem_release: error releasing task1_sem.");
}
return NULL;
}
/* Initialize task 1 exposed data objects */
void
task1_init(void)
{
/* Initialize task1 semaphore */
SuccessOrQuit(ble_npl_sem_init(&task1_sem, 0),
"ble_npl_sem_init: task1 returned error.");
}
/* Initialize task 2 exposed data objects */
void
task2_init(void)
{
/* Initialize task1 semaphore */
SuccessOrQuit(ble_npl_sem_init(&task2_sem, 0),
"ble_npl_sem_init: task2 returned error.");
}
/**
* init_app_tasks
*
* This function performs initializations that are required before tasks run.
*
* @return int 0 success; error otherwise.
*/
static int
init_app_tasks(void)
{
/*
* Call task specific initialization functions to initialize any shared objects
* before initializing the tasks with the OS.
*/
task1_init();
task2_init();
/*
* Initialize tasks 1 and 2 with the OS.
*/
ble_npl_task_init(&task1, "task1", task1_handler, NULL, TASK1_PRIO,
BLE_NPL_WAIT_FOREVER, task1_stack, TASK1_STACK_SIZE);
ble_npl_task_init(&task2, "task2", task2_handler, NULL, TASK2_PRIO,
BLE_NPL_WAIT_FOREVER, task2_stack, TASK2_STACK_SIZE);
return 0;
}
/**
* main
*
* The main function for the application. This function initializes the system and packages,
* calls the application specific task initialization function, then waits and dispatches
* events from the OS default event queue in an infinite loop.
*/
int
main(int argc, char **arg)
{
/* Initialize application specific tasks */
init_app_tasks();
while (1)
{
ble_npl_eventq_run(ble_npl_eventq_dflt_get());
}
/* main never returns */
}
+98
View File
@@ -0,0 +1,98 @@
/*
* 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 "test_util.h"
#include "nimble/nimble_npl.h"
#include <pthread.h>
#define TASK0_ARG 55
#define TASK1_ARG 66
static struct ble_npl_task s_task[2];
static int s_task_arg[2] =
{
TASK0_ARG, TASK1_ARG
};
void *task0_run(void *args)
{
int i = 10000;
VerifyOrQuit(args == &s_task_arg[0], "Wrong args passed to task0");
while (i--)
{
}
return NULL;
}
void *task1_run(void *args)
{
int i = 10000;
VerifyOrQuit(args == &s_task_arg[1], "Wrong args passed to task0");
while (i--)
{
}
printf("All tests passed\n");
exit(PASS);
return NULL;
}
/**
* Unit test for initializing a task.
*
* int ble_npl_task_init(struct ble_npl_task *t, const char *name, ble_npl_task_func_t func,
* void *arg, uint8_t prio, ble_npl_time_t sanity_itvl,
* ble_npl_stack_t *stack_bottom, uint16_t stack_size)
*
*/
int test_init()
{
int err;
err = ble_npl_task_init(NULL,
"Null task",
NULL, NULL, 1, 0, NULL, 0);
VerifyOrQuit(err, "ble_npl_task_init accepted NULL parameters.");
err = ble_npl_task_init(&s_task[0],
"s_task[0]",
task0_run, &s_task_arg[0], 1, 0, NULL, 0);
SuccessOrQuit(err, "ble_npl_task_init failed.");
err = ble_npl_task_init(&s_task[1],
"s_task[1]",
task1_run, &s_task_arg[1], 1, 0, NULL, 0);
return err;
}
int main(void)
{
int ret = PASS;
SuccessOrQuit(test_init(), "Failed: ble_npl_task_init");
pthread_exit(&ret);
return ret;
}
+56
View File
@@ -0,0 +1,56 @@
/*
* 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 _TEST_UTIL_H_
#define _TEST_UTIL_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#define PASS (0)
#define FAIL (-1)
#define SuccessOrQuit(ERR, MSG) \
do { \
if ((ERR)) \
{ \
fprintf(stderr, "\nFAILED %s:%d - %s\n", __FUNCTION__, __LINE__, MSG); \
exit(-1); \
} \
} while (false)
#define VerifyOrQuit(TST, MSG) \
do { \
if (!(TST)) \
{ \
fprintf(stderr, "\nFAILED %s:%d - %s\n", __FUNCTION__, __LINE__, MSG); \
exit(-1); \
} \
} while (false)
#ifdef __cplusplus
}
#endif
#endif /* _TEST_UTIL_H_ */