mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-15 22:47:53 +00:00
[linux] Linux port using NPL (Nimble Platform Layer).
- Added linux implementations of npl abstractions: * callout, eventq, mutex, sem, time
This commit is contained in:
@@ -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 $@ $^
|
||||
|
||||
@@ -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) $@
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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, ¶m);
|
||||
if (err) return err;
|
||||
err = pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
||||
if (err) return err;
|
||||
param.sched_priority = prio;
|
||||
err = pthread_attr_setschedparam (&attr, ¶m);
|
||||
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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 $@
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
Reference in New Issue
Block a user