Low frequency and high frequency clocks had separate devices while they are actually handled by single peripheral with single interrupt. The split was done probably because opaque subsys argument in the API was used for other purposes and there was no way to pass the information which clock should be controlled. Implementation changes some time ago and subsys parameter was no longer used. It now can be used to indicate which clock should be controlled. Change become necessary when nrf5340 is taken into account where there are more clocks and current approach would lead to create multiple devices - mess. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
194 lines
4.5 KiB
C
194 lines
4.5 KiB
C
/*
|
|
* Copyright (c) 2016-2018 Nordic Semiconductor ASA
|
|
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/types.h>
|
|
#include <string.h>
|
|
|
|
#include <soc.h>
|
|
#include <device.h>
|
|
#include <drivers/clock_control.h>
|
|
#include <drivers/clock_control/nrf_clock_control.h>
|
|
#include <bluetooth/hci.h>
|
|
|
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
|
|
#define LOG_MODULE_NAME bt_ctlr_ll
|
|
#include "common/log.h"
|
|
|
|
#include "hal/cpu.h"
|
|
#include "hal/cntr.h"
|
|
#include "hal/ccm.h"
|
|
#include "hal/radio.h"
|
|
#include "hal/ticker.h"
|
|
#include "hal/debug.h"
|
|
|
|
#include "util/util.h"
|
|
#include "util/mem.h"
|
|
#include "util/memq.h"
|
|
#include "util/mayfly.h"
|
|
|
|
#include "ticker/ticker.h"
|
|
|
|
#include "pdu.h"
|
|
#include "lll.h"
|
|
#include "ctrl.h"
|
|
#include "ctrl_internal.h"
|
|
#include "ll.h"
|
|
#include "ll_feat.h"
|
|
#include "ll_filter.h"
|
|
|
|
/* Global singletons */
|
|
|
|
#if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC)
|
|
#define FLASH_TICKER_NODES 1 /* No. of tickers reserved for flashing */
|
|
#define FLASH_TICKER_USER_APP_OPS 1 /* No. of additional ticker operations */
|
|
#else
|
|
#define FLASH_TICKER_NODES 0
|
|
#define FLASH_TICKER_USER_APP_OPS 0
|
|
#endif
|
|
|
|
#define TICKER_NODES (RADIO_TICKER_NODES + FLASH_TICKER_NODES)
|
|
#define TICKER_USER_APP_OPS (RADIO_TICKER_USER_APP_OPS + \
|
|
FLASH_TICKER_USER_APP_OPS)
|
|
#define TICKER_USER_OPS (RADIO_TICKER_USER_OPS + \
|
|
FLASH_TICKER_USER_APP_OPS)
|
|
|
|
/* memory for ticker nodes/instances */
|
|
static u8_t MALIGN(4) _ticker_nodes[TICKER_NODES][TICKER_NODE_T_SIZE];
|
|
|
|
/* memory for users/contexts operating on ticker module */
|
|
static u8_t MALIGN(4) _ticker_users[MAYFLY_CALLER_COUNT][TICKER_USER_T_SIZE];
|
|
|
|
/* memory for user/context simultaneous API operations */
|
|
static u8_t MALIGN(4) _ticker_user_ops[TICKER_USER_OPS][TICKER_USER_OP_T_SIZE];
|
|
|
|
/* memory for Bluetooth Controller (buffers, queues etc.) */
|
|
static u8_t MALIGN(4) _radio[LL_MEM_TOTAL];
|
|
|
|
static struct k_sem *sem_recv;
|
|
|
|
void radio_active_callback(u8_t active)
|
|
{
|
|
}
|
|
|
|
void radio_event_callback(void)
|
|
{
|
|
k_sem_give(sem_recv);
|
|
}
|
|
|
|
ISR_DIRECT_DECLARE(radio_nrf5_isr)
|
|
{
|
|
DEBUG_RADIO_ISR(1);
|
|
|
|
isr_radio();
|
|
|
|
ISR_DIRECT_PM();
|
|
|
|
DEBUG_RADIO_ISR(0);
|
|
return 1;
|
|
}
|
|
|
|
static void rtc0_nrf5_isr(void *arg)
|
|
{
|
|
DEBUG_TICKER_ISR(1);
|
|
|
|
/* On compare0 run ticker worker instance0 */
|
|
if (NRF_RTC0->EVENTS_COMPARE[0]) {
|
|
NRF_RTC0->EVENTS_COMPARE[0] = 0;
|
|
|
|
ticker_trigger(0);
|
|
}
|
|
|
|
mayfly_run(MAYFLY_CALL_ID_0);
|
|
|
|
DEBUG_TICKER_ISR(0);
|
|
}
|
|
|
|
static void swi5_nrf5_isr(void *arg)
|
|
{
|
|
DEBUG_TICKER_JOB(1);
|
|
|
|
mayfly_run(MAYFLY_CALL_ID_1);
|
|
|
|
DEBUG_TICKER_JOB(0);
|
|
}
|
|
|
|
int ll_init(struct k_sem *sem_rx)
|
|
{
|
|
struct device *clk;
|
|
struct device *entropy;
|
|
u32_t err;
|
|
|
|
sem_recv = sem_rx;
|
|
|
|
clk = device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL);
|
|
if (!clk) {
|
|
return -ENODEV;
|
|
}
|
|
|
|
clock_control_on(clk, CLOCK_CONTROL_NRF_SUBSYS_LF);
|
|
|
|
entropy = device_get_binding(CONFIG_ENTROPY_NAME);
|
|
if (!entropy) {
|
|
return -ENODEV;
|
|
}
|
|
|
|
/* TODO: bind and use counter driver */
|
|
cntr_init();
|
|
|
|
mayfly_init();
|
|
|
|
_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] = TICKER_USER_APP_OPS;
|
|
|
|
err = ticker_init(RADIO_TICKER_INSTANCE_ID_RADIO,
|
|
TICKER_NODES, &_ticker_nodes[0],
|
|
MAYFLY_CALLER_COUNT, &_ticker_users[0],
|
|
TICKER_USER_OPS, &_ticker_user_ops[0],
|
|
hal_ticker_instance0_caller_id_get,
|
|
hal_ticker_instance0_sched,
|
|
hal_ticker_instance0_trigger_set);
|
|
LL_ASSERT(!err);
|
|
|
|
err = radio_init(clk, CLOCK_CONTROL_NRF_K32SRC_ACCURACY, entropy,
|
|
RADIO_CONNECTION_CONTEXT_MAX,
|
|
RADIO_PACKET_COUNT_RX_MAX,
|
|
RADIO_PACKET_COUNT_TX_MAX,
|
|
LL_LENGTH_OCTETS_RX_MAX,
|
|
RADIO_PACKET_TX_DATA_SIZE, &_radio[0], sizeof(_radio));
|
|
if (err) {
|
|
BT_ERR("Required RAM size: %d, supplied: %u.", err,
|
|
sizeof(_radio));
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* reset whitelist, resolving list and initialise RPA timeout*/
|
|
if (IS_ENABLED(CONFIG_BT_CTLR_FILTER)) {
|
|
ll_filter_reset(true);
|
|
}
|
|
|
|
IRQ_DIRECT_CONNECT(RADIO_IRQn, CONFIG_BT_CTLR_WORKER_PRIO,
|
|
radio_nrf5_isr, 0);
|
|
IRQ_CONNECT(RTC0_IRQn, CONFIG_BT_CTLR_WORKER_PRIO,
|
|
rtc0_nrf5_isr, NULL, 0);
|
|
IRQ_CONNECT(SWI5_IRQn, CONFIG_BT_CTLR_JOB_PRIO,
|
|
swi5_nrf5_isr, NULL, 0);
|
|
|
|
irq_enable(RADIO_IRQn);
|
|
irq_enable(RTC0_IRQn);
|
|
irq_enable(SWI5_IRQn);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ll_timeslice_ticker_id_get(u8_t * const instance_index, u8_t * const user_id)
|
|
{
|
|
*user_id = (TICKER_NODES - FLASH_TICKER_NODES); /* The last index in the total tickers */
|
|
*instance_index = RADIO_TICKER_INSTANCE_ID_RADIO;
|
|
}
|