2016-08-15 13:21:26 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Nordic Semiconductor ASA
|
|
|
|
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2016-08-15 13:21:26 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stddef.h>
|
2016-09-14 20:30:50 +02:00
|
|
|
#include <string.h>
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-11-07 11:36:56 +01:00
|
|
|
#include <zephyr.h>
|
2016-09-14 20:30:50 +02:00
|
|
|
#include <soc.h>
|
2016-08-15 13:21:26 +02:00
|
|
|
#include <init.h>
|
2016-09-14 20:30:50 +02:00
|
|
|
#include <device.h>
|
|
|
|
#include <clock_control.h>
|
|
|
|
|
2016-08-15 13:21:26 +02:00
|
|
|
#include <misc/util.h>
|
2016-09-01 21:34:56 +02:00
|
|
|
#include <misc/stack.h>
|
2016-08-15 13:21:26 +02:00
|
|
|
#include <misc/byteorder.h>
|
|
|
|
|
2017-01-17 11:01:47 +02:00
|
|
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BLUETOOTH_DEBUG_HCI_DRIVER)
|
2016-08-15 13:21:26 +02:00
|
|
|
#include <bluetooth/log.h>
|
2017-01-17 11:01:47 +02:00
|
|
|
#include <bluetooth/bluetooth.h>
|
2016-08-15 13:21:26 +02:00
|
|
|
#include <bluetooth/hci.h>
|
2016-11-02 13:07:55 +02:00
|
|
|
#include <drivers/bluetooth/hci_driver.h>
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-11-05 05:13:51 +01:00
|
|
|
#ifdef CONFIG_CLOCK_CONTROL_NRF5
|
|
|
|
#include <drivers/clock_control/nrf5_clock_control.h>
|
|
|
|
#endif
|
|
|
|
|
2017-01-13 10:40:36 -06:00
|
|
|
#include <arch/arm/cortex_m/cmsis.h>
|
|
|
|
|
2016-12-21 06:21:13 +01:00
|
|
|
#include "util/config.h"
|
|
|
|
#include "util/mayfly.h"
|
|
|
|
#include "util/util.h"
|
|
|
|
#include "util/mem.h"
|
2016-08-15 13:21:26 +02:00
|
|
|
#include "hal/rand.h"
|
|
|
|
#include "hal/ccm.h"
|
|
|
|
#include "hal/radio.h"
|
2016-12-21 06:21:13 +01:00
|
|
|
#include "hal/cntr.h"
|
2016-11-16 16:24:27 +01:00
|
|
|
#include "hal/cpu.h"
|
2016-12-21 06:21:13 +01:00
|
|
|
#include "ticker/ticker.h"
|
2017-03-14 14:48:54 +01:00
|
|
|
#include "ll_sw/pdu.h"
|
|
|
|
#include "ll_sw/ctrl.h"
|
|
|
|
#include "ll_sw/ctrl_internal.h"
|
|
|
|
#include "ll.h"
|
2016-09-15 10:07:56 +02:00
|
|
|
#include "hci_internal.h"
|
2016-08-15 13:21:26 +02:00
|
|
|
|
|
|
|
#include "hal/debug.h"
|
|
|
|
|
2016-12-21 06:21:13 +01:00
|
|
|
static uint8_t MALIGN(4) _rand_context[3 + 4 + 1];
|
|
|
|
static uint8_t MALIGN(4) _ticker_nodes[RADIO_TICKER_NODES][TICKER_NODE_T_SIZE];
|
|
|
|
static uint8_t MALIGN(4) _ticker_users[MAYFLY_CALLER_COUNT]
|
|
|
|
[TICKER_USER_T_SIZE];
|
|
|
|
static uint8_t MALIGN(4) _ticker_user_ops[RADIO_TICKER_USER_OPS]
|
2016-08-25 10:30:54 +03:00
|
|
|
[TICKER_USER_OP_T_SIZE];
|
2016-12-21 06:21:13 +01:00
|
|
|
static uint8_t MALIGN(4) _radio[LL_MEM_TOTAL];
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2017-01-02 18:59:22 +01:00
|
|
|
static K_SEM_DEFINE(sem_prio_recv, 0, UINT_MAX);
|
|
|
|
static K_FIFO_DEFINE(recv_fifo);
|
|
|
|
|
|
|
|
static BT_STACK_NOINIT(prio_recv_thread_stack,
|
|
|
|
CONFIG_BLUETOOTH_CONTROLLER_RX_PRIO_STACK_SIZE);
|
|
|
|
static BT_STACK_NOINIT(recv_thread_stack, CONFIG_BLUETOOTH_RX_STACK_SIZE);
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-11-16 16:24:27 +01:00
|
|
|
K_MUTEX_DEFINE(mutex_rand);
|
|
|
|
|
2017-01-09 13:49:37 +02:00
|
|
|
int bt_rand(void *buf, size_t len)
|
2016-11-16 16:24:27 +01:00
|
|
|
{
|
|
|
|
while (len) {
|
|
|
|
k_mutex_lock(&mutex_rand, K_FOREVER);
|
|
|
|
len = rand_get(len, buf);
|
|
|
|
k_mutex_unlock(&mutex_rand);
|
|
|
|
if (len) {
|
|
|
|
cpu_sleep();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-04 04:58:22 +01:00
|
|
|
void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
|
2016-12-21 06:21:13 +01:00
|
|
|
{
|
|
|
|
(void)caller_id;
|
|
|
|
|
|
|
|
LL_ASSERT(callee_id == MAYFLY_CALL_ID_1);
|
|
|
|
|
|
|
|
if (enable) {
|
|
|
|
irq_enable(SWI4_IRQn);
|
|
|
|
} else {
|
|
|
|
irq_disable(SWI4_IRQn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id)
|
|
|
|
{
|
|
|
|
(void)caller_id;
|
|
|
|
|
|
|
|
if (callee_id == MAYFLY_CALL_ID_0) {
|
|
|
|
return irq_is_enabled(RTC0_IRQn);
|
|
|
|
} else if (callee_id == MAYFLY_CALL_ID_1) {
|
|
|
|
return irq_is_enabled(SWI4_IRQn);
|
|
|
|
}
|
|
|
|
|
|
|
|
LL_ASSERT(0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t mayfly_prio_is_equal(uint8_t caller_id, uint8_t callee_id)
|
|
|
|
{
|
|
|
|
return (caller_id == callee_id) ||
|
|
|
|
((caller_id == MAYFLY_CALL_ID_0) &&
|
|
|
|
(callee_id == MAYFLY_CALL_ID_1)) ||
|
|
|
|
((caller_id == MAYFLY_CALL_ID_1) &&
|
|
|
|
(callee_id == MAYFLY_CALL_ID_0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void mayfly_pend(uint8_t caller_id, uint8_t callee_id)
|
|
|
|
{
|
|
|
|
(void)caller_id;
|
|
|
|
|
|
|
|
switch (callee_id) {
|
|
|
|
case MAYFLY_CALL_ID_0:
|
2017-01-13 10:40:36 -06:00
|
|
|
NVIC_SetPendingIRQ(RTC0_IRQn);
|
2016-12-21 06:21:13 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MAYFLY_CALL_ID_1:
|
2017-01-13 10:40:36 -06:00
|
|
|
NVIC_SetPendingIRQ(SWI4_IRQn);
|
2016-12-21 06:21:13 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MAYFLY_CALL_ID_PROGRAM:
|
|
|
|
default:
|
|
|
|
LL_ASSERT(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-15 13:21:26 +02:00
|
|
|
void radio_active_callback(uint8_t active)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void radio_event_callback(void)
|
|
|
|
{
|
2017-01-02 18:59:22 +01:00
|
|
|
k_sem_give(&sem_prio_recv);
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2017-02-14 14:07:24 +01:00
|
|
|
ISR_DIRECT_DECLARE(radio_nrf5_isr)
|
2016-08-15 13:21:26 +02:00
|
|
|
{
|
2017-02-14 14:07:24 +01:00
|
|
|
isr_radio();
|
|
|
|
|
|
|
|
ISR_DIRECT_PM();
|
|
|
|
return 1;
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2017-02-21 05:07:29 +01:00
|
|
|
static void rtc0_nrf5_isr(void *arg)
|
2016-08-15 13:21:26 +02:00
|
|
|
{
|
|
|
|
uint32_t compare0, compare1;
|
|
|
|
|
|
|
|
/* store interested events */
|
|
|
|
compare0 = NRF_RTC0->EVENTS_COMPARE[0];
|
|
|
|
compare1 = NRF_RTC0->EVENTS_COMPARE[1];
|
|
|
|
|
|
|
|
/* On compare0 run ticker worker instance0 */
|
|
|
|
if (compare0) {
|
|
|
|
NRF_RTC0->EVENTS_COMPARE[0] = 0;
|
|
|
|
|
|
|
|
ticker_trigger(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* On compare1 run ticker worker instance1 */
|
|
|
|
if (compare1) {
|
|
|
|
NRF_RTC0->EVENTS_COMPARE[1] = 0;
|
|
|
|
|
|
|
|
ticker_trigger(1);
|
|
|
|
}
|
|
|
|
|
2016-12-21 06:21:13 +01:00
|
|
|
mayfly_run(MAYFLY_CALL_ID_0);
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void rng_nrf5_isr(void *arg)
|
|
|
|
{
|
2016-12-21 06:21:13 +01:00
|
|
|
isr_rand(arg);
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2017-02-21 05:07:29 +01:00
|
|
|
static void swi4_nrf5_isr(void *arg)
|
2016-08-15 13:21:26 +02:00
|
|
|
{
|
2016-12-21 06:21:13 +01:00
|
|
|
mayfly_run(MAYFLY_CALL_ID_1);
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2017-01-02 18:59:22 +01:00
|
|
|
static void prio_recv_thread(void *p1, void *p2, void *p3)
|
2016-08-15 13:21:26 +02:00
|
|
|
{
|
|
|
|
while (1) {
|
2016-09-22 16:46:21 +02:00
|
|
|
struct radio_pdu_node_rx *node_rx;
|
|
|
|
struct net_buf *buf;
|
2016-08-15 13:21:26 +02:00
|
|
|
uint8_t num_cmplt;
|
2016-09-22 16:46:21 +02:00
|
|
|
uint16_t handle;
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-09-22 16:46:21 +02:00
|
|
|
while ((num_cmplt = radio_rx_get(&node_rx, &handle))) {
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-12-26 17:22:48 +02:00
|
|
|
buf = bt_buf_get_rx(K_FOREVER);
|
|
|
|
bt_buf_set_type(buf, BT_BUF_EVT);
|
|
|
|
hci_num_cmplt_encode(buf, handle, num_cmplt);
|
|
|
|
BT_DBG("Num Complete: 0x%04x:%u", handle, num_cmplt);
|
2017-01-02 13:43:12 +02:00
|
|
|
bt_recv_prio(buf);
|
2016-08-28 17:53:51 +02:00
|
|
|
|
2016-11-10 21:53:12 +02:00
|
|
|
k_yield();
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2016-09-22 16:46:21 +02:00
|
|
|
if (node_rx) {
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2017-01-02 18:59:22 +01:00
|
|
|
radio_rx_dequeue();
|
|
|
|
|
|
|
|
BT_DBG("RX node enqueue");
|
|
|
|
k_fifo_put(&recv_fifo, node_rx);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
BT_DBG("sem take...");
|
|
|
|
k_sem_take(&sem_prio_recv, K_FOREVER);
|
|
|
|
BT_DBG("sem taken");
|
|
|
|
|
|
|
|
stack_analyze("prio recv thread stack", prio_recv_thread_stack,
|
|
|
|
sizeof(prio_recv_thread_stack));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void recv_thread(void *p1, void *p2, void *p3)
|
|
|
|
{
|
|
|
|
while (1) {
|
|
|
|
struct radio_pdu_node_rx *node_rx;
|
|
|
|
struct pdu_data *pdu_data;
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
BT_DBG("RX node get");
|
|
|
|
node_rx = k_fifo_get(&recv_fifo, K_FOREVER);
|
|
|
|
BT_DBG("RX node dequeued");
|
|
|
|
|
|
|
|
pdu_data = (void *)node_rx->pdu_data;
|
|
|
|
/* Check if we need to generate an HCI event or ACL
|
|
|
|
* data
|
|
|
|
*/
|
|
|
|
if (node_rx->hdr.type != NODE_RX_TYPE_DC_PDU ||
|
|
|
|
pdu_data->ll_id == PDU_DATA_LLID_CTRL) {
|
|
|
|
/* generate a (non-priority) HCI event */
|
|
|
|
if (hci_evt_is_discardable(node_rx)) {
|
|
|
|
buf = bt_buf_get_rx(K_NO_WAIT);
|
2016-09-22 16:46:21 +02:00
|
|
|
} else {
|
2016-12-26 17:22:48 +02:00
|
|
|
buf = bt_buf_get_rx(K_FOREVER);
|
2016-09-22 16:46:21 +02:00
|
|
|
}
|
|
|
|
|
2016-10-27 18:13:06 +02:00
|
|
|
if (buf) {
|
2017-01-02 18:59:22 +01:00
|
|
|
bt_buf_set_type(buf, BT_BUF_EVT);
|
|
|
|
hci_evt_encode(node_rx, buf);
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
2017-01-02 18:59:22 +01:00
|
|
|
} else {
|
|
|
|
/* generate ACL data */
|
|
|
|
buf = bt_buf_get_rx(K_FOREVER);
|
|
|
|
bt_buf_set_type(buf, BT_BUF_ACL_IN);
|
|
|
|
hci_acl_encode(node_rx, buf);
|
|
|
|
}
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2017-01-02 18:59:22 +01:00
|
|
|
radio_rx_fc_set(node_rx->hdr.handle, 0);
|
|
|
|
node_rx->hdr.onion.next = 0;
|
|
|
|
radio_rx_mem_release(&node_rx);
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2017-01-02 18:59:22 +01:00
|
|
|
if (buf) {
|
|
|
|
if (buf->len) {
|
|
|
|
BT_DBG("Packet in: type:%u len:%u",
|
|
|
|
bt_buf_get_type(buf), buf->len);
|
|
|
|
bt_recv(buf);
|
|
|
|
} else {
|
|
|
|
net_buf_unref(buf);
|
|
|
|
}
|
2016-08-28 17:53:51 +02:00
|
|
|
}
|
2016-09-01 21:34:56 +02:00
|
|
|
|
2017-01-02 18:59:22 +01:00
|
|
|
k_yield();
|
|
|
|
|
2016-11-11 10:02:49 +02:00
|
|
|
stack_analyze("recv thread stack", recv_thread_stack,
|
|
|
|
sizeof(recv_thread_stack));
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-21 18:09:16 +02:00
|
|
|
static int cmd_handle(struct net_buf *buf)
|
|
|
|
{
|
|
|
|
struct net_buf *evt;
|
|
|
|
|
2017-02-01 17:32:29 +02:00
|
|
|
evt = hci_cmd_handle(buf);
|
|
|
|
if (!evt) {
|
|
|
|
return -EINVAL;
|
2016-09-21 18:09:16 +02:00
|
|
|
}
|
|
|
|
|
2017-02-01 17:32:29 +02:00
|
|
|
BT_DBG("Replying with event of %u bytes", evt->len);
|
|
|
|
bt_recv_prio(evt);
|
|
|
|
|
|
|
|
return 0;
|
2016-09-21 18:09:16 +02:00
|
|
|
}
|
|
|
|
|
2016-09-16 16:16:23 +02:00
|
|
|
static int hci_driver_send(struct net_buf *buf)
|
2016-08-15 13:21:26 +02:00
|
|
|
{
|
2016-09-21 18:09:16 +02:00
|
|
|
uint8_t type;
|
2016-09-20 12:36:44 +02:00
|
|
|
int err;
|
2016-08-15 13:21:26 +02:00
|
|
|
|
|
|
|
BT_DBG("enter");
|
|
|
|
|
2016-09-21 18:09:16 +02:00
|
|
|
if (!buf->len) {
|
|
|
|
BT_ERR("Empty HCI packet");
|
|
|
|
return -EINVAL;
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2016-09-21 18:09:16 +02:00
|
|
|
type = bt_buf_get_type(buf);
|
|
|
|
switch (type) {
|
|
|
|
case BT_BUF_ACL_OUT:
|
|
|
|
err = hci_acl_handle(buf);
|
|
|
|
break;
|
|
|
|
case BT_BUF_CMD:
|
|
|
|
err = cmd_handle(buf);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BT_ERR("Unknown HCI type %u", type);
|
|
|
|
return -EINVAL;
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2016-09-21 18:09:16 +02:00
|
|
|
if (!err) {
|
|
|
|
net_buf_unref(buf);
|
|
|
|
}
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-09-21 18:09:16 +02:00
|
|
|
BT_DBG("exit: %d", err);
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-09-21 18:09:16 +02:00
|
|
|
return err;
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2016-09-16 16:16:23 +02:00
|
|
|
static int hci_driver_open(void)
|
2016-08-15 13:21:26 +02:00
|
|
|
{
|
2016-09-14 20:30:50 +02:00
|
|
|
struct device *clk_k32;
|
|
|
|
struct device *clk_m16;
|
2016-09-22 16:46:21 +02:00
|
|
|
uint32_t err;
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-09-09 18:16:26 +02:00
|
|
|
DEBUG_INIT();
|
|
|
|
|
2016-11-08 05:23:27 +01:00
|
|
|
/* TODO: bind and use RNG driver */
|
|
|
|
rand_init(_rand_context, sizeof(_rand_context));
|
|
|
|
|
2016-09-14 20:30:50 +02:00
|
|
|
clk_k32 = device_get_binding(CONFIG_CLOCK_CONTROL_NRF5_K32SRC_DRV_NAME);
|
|
|
|
if (!clk_k32) {
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2016-11-05 05:13:51 +01:00
|
|
|
clock_control_on(clk_k32, (void *)CLOCK_CONTROL_NRF5_K32SRC);
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-11-08 05:23:27 +01:00
|
|
|
/* TODO: bind and use counter driver */
|
2016-12-21 06:21:13 +01:00
|
|
|
cntr_init();
|
|
|
|
|
|
|
|
mayfly_init();
|
2016-11-08 05:23:27 +01:00
|
|
|
|
2016-12-21 06:21:13 +01:00
|
|
|
_ticker_users[MAYFLY_CALL_ID_0][0] = RADIO_TICKER_USER_WORKER_OPS;
|
|
|
|
_ticker_users[MAYFLY_CALL_ID_1][0] = RADIO_TICKER_USER_JOB_OPS;
|
|
|
|
_ticker_users[MAYFLY_CALL_ID_2][0] = 0;
|
|
|
|
_ticker_users[MAYFLY_CALL_ID_PROGRAM][0] = RADIO_TICKER_USER_APP_OPS;
|
2016-08-15 13:21:26 +02:00
|
|
|
|
|
|
|
ticker_init(RADIO_TICKER_INSTANCE_ID_RADIO, RADIO_TICKER_NODES,
|
2016-12-21 06:21:13 +01:00
|
|
|
&_ticker_nodes[0], MAYFLY_CALLER_COUNT, &_ticker_users[0],
|
|
|
|
RADIO_TICKER_USER_OPS, &_ticker_user_ops[0]);
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2016-09-14 20:30:50 +02:00
|
|
|
clk_m16 = device_get_binding(CONFIG_CLOCK_CONTROL_NRF5_M16SRC_DRV_NAME);
|
|
|
|
if (!clk_m16) {
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2016-12-30 06:24:42 +01:00
|
|
|
err = radio_init(clk_m16, CLOCK_CONTROL_NRF5_K32SRC_ACCURACY,
|
2016-09-22 16:46:21 +02:00
|
|
|
RADIO_CONNECTION_CONTEXT_MAX,
|
|
|
|
RADIO_PACKET_COUNT_RX_MAX,
|
|
|
|
RADIO_PACKET_COUNT_TX_MAX,
|
2016-12-30 06:24:42 +01:00
|
|
|
RADIO_LL_LENGTH_OCTETS_RX_MAX,
|
|
|
|
RADIO_PACKET_TX_DATA_SIZE, &_radio[0], sizeof(_radio));
|
2016-09-22 16:46:21 +02:00
|
|
|
if (err) {
|
|
|
|
BT_ERR("Required RAM size: %d, supplied: %u.", err,
|
2016-08-28 17:52:12 +02:00
|
|
|
sizeof(_radio));
|
|
|
|
return -ENOMEM;
|
2016-08-15 13:21:26 +02:00
|
|
|
}
|
|
|
|
|
2017-02-14 14:07:24 +01:00
|
|
|
IRQ_DIRECT_CONNECT(NRF5_IRQ_RADIO_IRQn, 0, radio_nrf5_isr, 0);
|
2017-02-21 05:07:29 +01:00
|
|
|
IRQ_CONNECT(NRF5_IRQ_RTC0_IRQn, 0, rtc0_nrf5_isr, 0, 0);
|
2016-10-05 18:09:51 -03:00
|
|
|
IRQ_CONNECT(NRF5_IRQ_RNG_IRQn, 1, rng_nrf5_isr, 0, 0);
|
2017-02-21 05:07:29 +01:00
|
|
|
IRQ_CONNECT(NRF5_IRQ_SWI4_IRQn, 0, swi4_nrf5_isr, 0, 0);
|
2016-10-05 18:09:51 -03:00
|
|
|
irq_enable(NRF5_IRQ_RADIO_IRQn);
|
|
|
|
irq_enable(NRF5_IRQ_RTC0_IRQn);
|
|
|
|
irq_enable(NRF5_IRQ_RNG_IRQn);
|
|
|
|
irq_enable(NRF5_IRQ_SWI4_IRQn);
|
2016-08-15 13:21:26 +02:00
|
|
|
|
2017-01-02 18:59:22 +01:00
|
|
|
k_thread_spawn(prio_recv_thread_stack, sizeof(prio_recv_thread_stack),
|
|
|
|
prio_recv_thread, NULL, NULL, NULL, K_PRIO_COOP(6), 0,
|
|
|
|
K_NO_WAIT);
|
|
|
|
|
2016-11-11 10:02:49 +02:00
|
|
|
k_thread_spawn(recv_thread_stack, sizeof(recv_thread_stack),
|
|
|
|
recv_thread, NULL, NULL, NULL, K_PRIO_COOP(7), 0,
|
|
|
|
K_NO_WAIT);
|
2016-08-15 13:21:26 +02:00
|
|
|
|
|
|
|
BT_DBG("Success.");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-14 15:00:15 +02:00
|
|
|
static const struct bt_hci_driver drv = {
|
2016-08-15 13:21:26 +02:00
|
|
|
.name = "Controller",
|
2016-10-27 16:55:01 +03:00
|
|
|
.bus = BT_HCI_DRIVER_BUS_VIRTUAL,
|
2016-09-16 16:16:23 +02:00
|
|
|
.open = hci_driver_open,
|
|
|
|
.send = hci_driver_send,
|
2016-08-15 13:21:26 +02:00
|
|
|
};
|
|
|
|
|
2016-09-16 16:16:23 +02:00
|
|
|
static int _hci_driver_init(struct device *unused)
|
2016-08-15 13:21:26 +02:00
|
|
|
{
|
|
|
|
ARG_UNUSED(unused);
|
|
|
|
|
2016-10-27 16:55:01 +03:00
|
|
|
bt_hci_driver_register(&drv);
|
2016-08-15 13:21:26 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-11 10:02:49 +02:00
|
|
|
SYS_INIT(_hci_driver_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|