Bluetooth: Controller: replace work with mayfly
This commit introduces a very light-weight and lock-less scheduling of the Controller's deferred function calls called the Mayfly. Earlier work implementation used in the Controller had an O(n) to schedule a function in a linked list that used IRQ lock during modification of the linked list in the Controller's ISR executions. Mayfly is a compile time configurable matrix of queues where an execution context-safe queue exists between two execution context, one being the caller and the second being the callee. Callee(s) are run in a software interrupt but can also be run in an OS thread. There are minor clean ups too in this commit related to folder structure. Change-id: I5ff44dcee6679d2f5ce9e8437d98d6c868782f3d Signed-off-by: Vinayak Chettimada <vinayak.kariappa.chettimada@nordicsemi.no>
This commit is contained in:
parent
8bd73aeba7
commit
d5d473b0f8
30 changed files with 1046 additions and 667 deletions
|
@ -1,15 +1,16 @@
|
|||
ccflags-$(CONFIG_BLUETOOTH_CONTROLLER) += -I$(srctree)/subsys/bluetooth/controller/util
|
||||
ccflags-$(CONFIG_BLUETOOTH_CONTROLLER) += -I$(srctree)/subsys/bluetooth/controller/hal
|
||||
ccflags-$(CONFIG_BLUETOOTH_CONTROLLER) += -I$(srctree)/subsys/bluetooth/controller/ticker
|
||||
ccflags-$(CONFIG_BLUETOOTH_CONTROLLER) += -I$(srctree)/subsys/bluetooth/controller/ll
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += util/mem.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += util/memq.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += util/work.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += util/mayfly.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += util/util.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hal/rtc.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hal/rand.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hal/ecb.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hal/radio.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += ll/ticker.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hal/nrf5/cntr.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hal/nrf5/rand.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hal/nrf5/ecb.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hal/nrf5/radio.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += ticker/ticker.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += ll/ctrl.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += ll/ll.o
|
||||
obj-$(CONFIG_BLUETOOTH_CONTROLLER) += hci/hci_driver.o
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#ifndef _CCM_H_
|
||||
#define _CCM_H_
|
||||
|
||||
#include <toolchain.h>
|
||||
|
||||
struct ccm {
|
||||
uint8_t key[16];
|
||||
uint64_t counter;
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _RTC_H_
|
||||
#define _RTC_H_
|
||||
#ifndef _CNTR_H_
|
||||
#define _CNTR_H_
|
||||
|
||||
void rtc_init(void);
|
||||
uint32_t rtc_start(void);
|
||||
uint32_t rtc_stop(void);
|
||||
uint32_t rtc_tick_get(void);
|
||||
uint32_t rtc_compare_set(uint8_t instance, uint32_t value);
|
||||
void cntr_init(void);
|
||||
uint32_t cntr_start(void);
|
||||
uint32_t cntr_stop(void);
|
||||
uint32_t cntr_cnt_get(void);
|
||||
void cntr_cmp_set(uint8_t cmp, uint32_t value);
|
||||
|
||||
#endif /* _RTC_H_ */
|
||||
#endif /* _CNTR_H_ */
|
|
@ -18,8 +18,6 @@
|
|||
#ifndef _CPU_H_
|
||||
#define _CPU_H_
|
||||
|
||||
#include "nrf.h"
|
||||
|
||||
static inline void cpu_sleep(void)
|
||||
{
|
||||
__WFE();
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
#include <bluetooth/log.h>
|
||||
|
||||
#ifdef CONFIG_BLUETOOTH_CONTROLLER_ASSERT_HANDLER
|
||||
void bt_controller_assert_handle(char *file, uint32_t line);
|
||||
#define LL_ASSERT(cond) if (!(cond)) { \
|
||||
|
|
|
@ -38,7 +38,7 @@ void ecb_encrypt(uint8_t const *const key_le,
|
|||
uint8_t * const cipher_text_le,
|
||||
uint8_t * const cipher_text_be);
|
||||
uint32_t ecb_encrypt_nonblocking(struct ecb *ecb);
|
||||
void ecb_isr(void);
|
||||
void isr_ecb(void *param);
|
||||
|
||||
uint32_t ecb_ut(void);
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _HAL_WORK_H_
|
||||
#define _HAL_WORK_H_
|
||||
|
||||
#include "nrf.h"
|
||||
|
||||
#define WORK_TICKER_WORKER0_IRQ RTC0_IRQn
|
||||
#define WORK_TICKER_JOB0_IRQ SWI4_IRQn
|
||||
#define WORK_TICKER_WORKER1_IRQ SWI5_IRQn
|
||||
#define WORK_TICKER_JOB1_IRQ SWI5_IRQn
|
||||
|
||||
#define WORK_TICKER_WORKER0_IRQ_PRIORITY 0
|
||||
#define WORK_TICKER_JOB0_IRQ_PRIORITY 0
|
||||
#define WORK_TICKER_WORKER1_IRQ_PRIORITY 2
|
||||
#define WORK_TICKER_JOB1_IRQ_PRIORITY 2
|
||||
|
||||
#endif /* _HAL_WORK_H_ */
|
|
@ -15,27 +15,30 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nrf.h"
|
||||
#include <soc.h>
|
||||
#include "cntr.h"
|
||||
|
||||
#include <bluetooth/log.h>
|
||||
#include "debug.h"
|
||||
|
||||
/* RTC instance to use */
|
||||
#ifndef NRF_RTC
|
||||
#define NRF_RTC NRF_RTC0
|
||||
#endif
|
||||
|
||||
static uint8_t _rtc_refcount;
|
||||
static uint8_t _refcount;
|
||||
|
||||
void rtc_init(void)
|
||||
void cntr_init(void)
|
||||
{
|
||||
NRF_RTC->PRESCALER = 0;
|
||||
NRF_RTC->EVTENSET =
|
||||
(RTC_EVTENSET_COMPARE0_Msk | RTC_EVTENSET_COMPARE1_Msk);
|
||||
NRF_RTC->INTENSET =
|
||||
(RTC_INTENSET_COMPARE0_Msk | RTC_INTENSET_COMPARE1_Msk);
|
||||
NRF_RTC->EVTENSET = (RTC_EVTENSET_COMPARE0_Msk |
|
||||
RTC_EVTENSET_COMPARE1_Msk);
|
||||
NRF_RTC->INTENSET = (RTC_INTENSET_COMPARE0_Msk |
|
||||
RTC_INTENSET_COMPARE1_Msk);
|
||||
}
|
||||
|
||||
uint32_t rtc_start(void)
|
||||
uint32_t cntr_start(void)
|
||||
{
|
||||
if (_rtc_refcount++) {
|
||||
if (_refcount++) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -44,11 +47,11 @@ uint32_t rtc_start(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t rtc_stop(void)
|
||||
uint32_t cntr_stop(void)
|
||||
{
|
||||
LL_ASSERT(_rtc_refcount);
|
||||
LL_ASSERT(_refcount);
|
||||
|
||||
if (--_rtc_refcount) {
|
||||
if (--_refcount) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -57,12 +60,12 @@ uint32_t rtc_stop(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t rtc_tick_get(void)
|
||||
uint32_t cntr_cnt_get(void)
|
||||
{
|
||||
return NRF_RTC->COUNTER;
|
||||
}
|
||||
|
||||
void rtc_compare_set(uint8_t instance, uint32_t value)
|
||||
void cntr_cmp_set(uint8_t cmp, uint32_t value)
|
||||
{
|
||||
NRF_RTC->CC[instance] = value;
|
||||
NRF_RTC->CC[cmp] = value;
|
||||
}
|
|
@ -19,8 +19,10 @@
|
|||
#include <soc.h>
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
#include "ecb.h"
|
||||
|
||||
#include <bluetooth/log.h>
|
||||
#include "debug.h"
|
||||
|
||||
void ecb_encrypt(uint8_t const *const key_le,
|
||||
|
@ -102,8 +104,10 @@ static void ecb_cleanup(void)
|
|||
irq_disable(ECB_IRQn);
|
||||
}
|
||||
|
||||
void ecb_isr(void)
|
||||
void isr_ecb(void *param)
|
||||
{
|
||||
ARG_UNUSED(param);
|
||||
|
||||
if (NRF_ECB->EVENTS_ERRORECB) {
|
||||
struct ecb *ecb = (struct ecb *)NRF_ECB->ECBDATAPTR;
|
||||
|
|
@ -15,11 +15,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#include <soc.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#include "hal_work.h"
|
||||
|
||||
#include "defines.h"
|
||||
#include "util.h"
|
||||
#include "mem.h"
|
||||
#include "pdu.h"
|
||||
#include "ccm.h"
|
||||
#include "radio.h"
|
||||
|
||||
|
@ -33,8 +32,10 @@
|
|||
|
||||
static radio_isr_fp sfp_radio_isr;
|
||||
|
||||
void radio_isr(void)
|
||||
void isr_radio(void *param)
|
||||
{
|
||||
ARG_UNUSED(param);
|
||||
|
||||
if (sfp_radio_isr) {
|
||||
sfp_radio_isr();
|
||||
}
|
||||
|
@ -215,8 +216,8 @@ uint32_t radio_crc_is_valid(void)
|
|||
return NRF_RADIO->CRCSTATUS;
|
||||
}
|
||||
|
||||
static uint8_t ALIGNED(4) _pkt_empty[RADIO_EMPDU_SIZE_MAX];
|
||||
static uint8_t ALIGNED(4) _pkt_scratch[
|
||||
static uint8_t MALIGN(4) _pkt_empty[RADIO_EMPDU_SIZE_MAX];
|
||||
static uint8_t MALIGN(4) _pkt_scratch[
|
||||
((RADIO_PDU_LEN_MAX + 3) > RADIO_ACPDU_SIZE_MAX) ?
|
||||
(RADIO_PDU_LEN_MAX + 3) : RADIO_ACPDU_SIZE_MAX];
|
||||
|
||||
|
@ -431,7 +432,7 @@ uint32_t radio_tmr_sample_get(void)
|
|||
return NRF_TIMER0->CC[3];
|
||||
}
|
||||
|
||||
static uint8_t ALIGNED(4) _ccm_scratch[(RADIO_PDU_LEN_MAX - 4) + 16];
|
||||
static uint8_t MALIGN(4) _ccm_scratch[(RADIO_PDU_LEN_MAX - 4) + 16];
|
||||
|
||||
void *radio_ccm_rx_pkt_set(struct ccm *ccm, void *pkt)
|
||||
{
|
||||
|
@ -527,7 +528,7 @@ uint32_t radio_ccm_mic_is_valid(void)
|
|||
return NRF_CCM->MICSTATUS;
|
||||
}
|
||||
|
||||
static uint8_t ALIGNED(4) _aar_scratch[3];
|
||||
static uint8_t MALIGN(4) _aar_scratch[3];
|
||||
|
||||
void radio_ar_configure(uint32_t nirk, void *irk)
|
||||
{
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "rand.h"
|
||||
|
||||
#include <bluetooth/log.h>
|
||||
#include "debug.h"
|
||||
|
||||
#define RAND_RESERVED (4)
|
||||
|
@ -30,19 +31,20 @@ struct rand {
|
|||
uint8_t rand[1];
|
||||
};
|
||||
|
||||
static struct rand *_rand;
|
||||
static struct rand *rng;
|
||||
|
||||
void rand_init(uint8_t *context, uint8_t context_len)
|
||||
{
|
||||
LL_ASSERT(context_len > sizeof(struct rand));
|
||||
|
||||
_rand = (struct rand *)context;
|
||||
_rand->count = context_len - sizeof(struct rand) + 1;
|
||||
_rand->first = _rand->last = 0;
|
||||
rng = (struct rand *)context;
|
||||
rng->count = context_len - sizeof(struct rand) + 1;
|
||||
rng->first = rng->last = 0;
|
||||
|
||||
NRF_RNG->CONFIG = RNG_CONFIG_DERCEN_Msk;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
NRF_RNG->INTENSET = RNG_INTENSET_VALRDY_Msk;
|
||||
|
||||
NRF_RNG->TASKS_START = 1;
|
||||
}
|
||||
|
||||
|
@ -52,30 +54,30 @@ uint32_t rand_get(uint8_t octets, uint8_t *rand)
|
|||
uint8_t first;
|
||||
|
||||
while (octets) {
|
||||
if (_rand->first == _rand->last) {
|
||||
if (rng->first == rng->last) {
|
||||
break;
|
||||
}
|
||||
|
||||
rand[--octets] = _rand->rand[_rand->first];
|
||||
rand[--octets] = rng->rand[rng->first];
|
||||
|
||||
first = _rand->first + 1;
|
||||
if (first == _rand->count) {
|
||||
first = rng->first + 1;
|
||||
if (first == rng->count) {
|
||||
first = 0;
|
||||
}
|
||||
_rand->first = first;
|
||||
rng->first = first;
|
||||
}
|
||||
|
||||
reserved = RAND_RESERVED;
|
||||
first = _rand->first;
|
||||
first = rng->first;
|
||||
while (reserved--) {
|
||||
if (first == _rand->last) {
|
||||
if (first == rng->last) {
|
||||
NRF_RNG->TASKS_START = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
first++;
|
||||
if (first == _rand->count) {
|
||||
if (first == rng->count) {
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
|
@ -83,17 +85,19 @@ uint32_t rand_get(uint8_t octets, uint8_t *rand)
|
|||
return octets;
|
||||
}
|
||||
|
||||
void rng_isr(void)
|
||||
void isr_rand(void *param)
|
||||
{
|
||||
ARG_UNUSED(param);
|
||||
|
||||
if (NRF_RNG->EVENTS_VALRDY) {
|
||||
uint8_t last;
|
||||
|
||||
last = _rand->last + 1;
|
||||
if (last == _rand->count) {
|
||||
last = rng->last + 1;
|
||||
if (last == rng->count) {
|
||||
last = 0;
|
||||
}
|
||||
|
||||
if (last == _rand->first) {
|
||||
if (last == rng->first) {
|
||||
/* this condition should not happen
|
||||
* , but due to probable bug in HW
|
||||
* , new value could be generated
|
||||
|
@ -105,17 +109,17 @@ void rng_isr(void)
|
|||
return;
|
||||
}
|
||||
|
||||
_rand->rand[_rand->last] = NRF_RNG->VALUE;
|
||||
_rand->last = last;
|
||||
rng->rand[rng->last] = NRF_RNG->VALUE;
|
||||
rng->last = last;
|
||||
|
||||
last = _rand->last + 1;
|
||||
if (last == _rand->count) {
|
||||
last = rng->last + 1;
|
||||
if (last == rng->count) {
|
||||
last = 0;
|
||||
}
|
||||
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
|
||||
if (last == _rand->first) {
|
||||
if (last == rng->first) {
|
||||
NRF_RNG->TASKS_STOP = 1;
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
typedef void (*radio_isr_fp) (void);
|
||||
|
||||
void radio_isr(void);
|
||||
void isr_radio(void *param);
|
||||
void radio_isr_set(radio_isr_fp fp_radio_isr);
|
||||
|
||||
void radio_reset(void);
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
|
||||
void rand_init(uint8_t *context, uint8_t context_len);
|
||||
uint32_t rand_get(uint8_t octets, uint8_t *rand);
|
||||
void rng_isr(void);
|
||||
void isr_rand(void *param);
|
||||
|
||||
#endif /* _RAND_H_ */
|
||||
|
|
|
@ -18,18 +18,20 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <soc.h>
|
||||
#include <toolchain.h>
|
||||
#include <errno.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/buf.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <misc/byteorder.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "ticker.h"
|
||||
#include "util.h"
|
||||
#include "mem.h"
|
||||
#include "rand.h"
|
||||
#include "ticker.h"
|
||||
#include "cpu.h"
|
||||
#include "rand.h"
|
||||
#include "ecb.h"
|
||||
#include "ccm.h"
|
||||
#include "radio.h"
|
||||
|
@ -38,6 +40,7 @@
|
|||
#include "ll.h"
|
||||
#include "hci_internal.h"
|
||||
|
||||
#include <bluetooth/log.h>
|
||||
#include "debug.h"
|
||||
|
||||
/* opcode of the HCI command currently being processed. The opcode is stored
|
||||
|
|
|
@ -38,14 +38,18 @@
|
|||
#include <drivers/clock_control/nrf5_clock_control.h>
|
||||
#endif
|
||||
|
||||
#include "util/defines.h"
|
||||
#include "util/work.h"
|
||||
#include "util/config.h"
|
||||
#include "util/mayfly.h"
|
||||
#include "util/util.h"
|
||||
#include "util/mem.h"
|
||||
#include "hal/rand.h"
|
||||
#include "hal/ccm.h"
|
||||
#include "hal/radio.h"
|
||||
#include "hal/hal_rtc.h"
|
||||
#include "hal/cntr.h"
|
||||
#include "hal/cpu.h"
|
||||
#include "ll/ticker.h"
|
||||
#include "ticker/ticker.h"
|
||||
#include "ll/pdu.h"
|
||||
#include "ll/ctrl.h"
|
||||
#include "ll/ctrl_internal.h"
|
||||
#include "hci_internal.h"
|
||||
|
||||
|
@ -61,12 +65,13 @@
|
|||
#define HCI_SCO 0x03
|
||||
#define HCI_EVT 0x04
|
||||
|
||||
static uint8_t ALIGNED(4) _rand_context[3 + 4 + 1];
|
||||
static uint8_t ALIGNED(4) _ticker_nodes[RADIO_TICKER_NODES][TICKER_NODE_T_SIZE];
|
||||
static uint8_t ALIGNED(4) _ticker_users[RADIO_TICKER_USERS][TICKER_USER_T_SIZE];
|
||||
static uint8_t ALIGNED(4) _ticker_user_ops[RADIO_TICKER_USER_OPS]
|
||||
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]
|
||||
[TICKER_USER_OP_T_SIZE];
|
||||
static uint8_t ALIGNED(4) _radio[LL_MEM_TOTAL];
|
||||
static uint8_t MALIGN(4) _radio[LL_MEM_TOTAL];
|
||||
|
||||
static K_SEM_DEFINE(sem_recv, 0, UINT_MAX);
|
||||
static BT_STACK_NOINIT(recv_thread_stack,
|
||||
|
@ -96,6 +101,63 @@ int bt_rand(void *buf, size_t len)
|
|||
}
|
||||
#endif
|
||||
|
||||
void mayfly_enable(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
|
||||
{
|
||||
(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:
|
||||
_NvicIrqPend(RTC0_IRQn);
|
||||
break;
|
||||
|
||||
case MAYFLY_CALL_ID_1:
|
||||
_NvicIrqPend(SWI4_IRQn);
|
||||
break;
|
||||
|
||||
case MAYFLY_CALL_ID_PROGRAM:
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void radio_active_callback(uint8_t active)
|
||||
{
|
||||
}
|
||||
|
@ -107,7 +169,7 @@ void radio_event_callback(void)
|
|||
|
||||
static void radio_nrf5_isr(void *arg)
|
||||
{
|
||||
radio_isr();
|
||||
isr_radio(arg);
|
||||
}
|
||||
|
||||
static void rtc0_nrf5_isr(void *arg)
|
||||
|
@ -132,22 +194,17 @@ static void rtc0_nrf5_isr(void *arg)
|
|||
ticker_trigger(1);
|
||||
}
|
||||
|
||||
work_run(RTC0_IRQn);
|
||||
mayfly_run(MAYFLY_CALL_ID_0);
|
||||
}
|
||||
|
||||
static void rng_nrf5_isr(void *arg)
|
||||
{
|
||||
rng_isr();
|
||||
isr_rand(arg);
|
||||
}
|
||||
|
||||
static void swi4_nrf5_isr(void *arg)
|
||||
{
|
||||
work_run(NRF5_IRQ_SWI4_IRQn);
|
||||
}
|
||||
|
||||
static void swi5_nrf5_isr(void *arg)
|
||||
{
|
||||
work_run(NRF5_IRQ_SWI5_IRQn);
|
||||
mayfly_run(MAYFLY_CALL_ID_1);
|
||||
}
|
||||
|
||||
static void recv_thread(void *p1, void *p2, void *p3)
|
||||
|
@ -305,20 +362,18 @@ static int hci_driver_open(void)
|
|||
clock_control_on(clk_k32, (void *)CLOCK_CONTROL_NRF5_K32SRC);
|
||||
|
||||
/* TODO: bind and use counter driver */
|
||||
rtc_init();
|
||||
cntr_init();
|
||||
|
||||
_ticker_users[RADIO_TICKER_USER_ID_WORKER][0] =
|
||||
RADIO_TICKER_USER_WORKER_OPS;
|
||||
_ticker_users[RADIO_TICKER_USER_ID_JOB][0] =
|
||||
RADIO_TICKER_USER_JOB_OPS;
|
||||
_ticker_users[RADIO_TICKER_USER_ID_APP][0] =
|
||||
RADIO_TICKER_USER_APP_OPS;
|
||||
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] = RADIO_TICKER_USER_APP_OPS;
|
||||
|
||||
ticker_init(RADIO_TICKER_INSTANCE_ID_RADIO, RADIO_TICKER_NODES,
|
||||
&_ticker_nodes[0]
|
||||
, RADIO_TICKER_USERS, &_ticker_users[0]
|
||||
, RADIO_TICKER_USER_OPS, &_ticker_user_ops[0]
|
||||
);
|
||||
&_ticker_nodes[0], MAYFLY_CALLER_COUNT, &_ticker_users[0],
|
||||
RADIO_TICKER_USER_OPS, &_ticker_user_ops[0]);
|
||||
|
||||
clk_m16 = device_get_binding(CONFIG_CLOCK_CONTROL_NRF5_M16SRC_DRV_NAME);
|
||||
if (!clk_m16) {
|
||||
|
@ -341,12 +396,10 @@ static int hci_driver_open(void)
|
|||
IRQ_CONNECT(NRF5_IRQ_RTC0_IRQn, 0, rtc0_nrf5_isr, 0, 0);
|
||||
IRQ_CONNECT(NRF5_IRQ_RNG_IRQn, 1, rng_nrf5_isr, 0, 0);
|
||||
IRQ_CONNECT(NRF5_IRQ_SWI4_IRQn, 0, swi4_nrf5_isr, 0, 0);
|
||||
IRQ_CONNECT(NRF5_IRQ_SWI5_IRQn, 1, swi5_nrf5_isr, 0, 0);
|
||||
irq_enable(NRF5_IRQ_RADIO_IRQn);
|
||||
irq_enable(NRF5_IRQ_RTC0_IRQn);
|
||||
irq_enable(NRF5_IRQ_RNG_IRQn);
|
||||
irq_enable(NRF5_IRQ_SWI4_IRQn);
|
||||
irq_enable(NRF5_IRQ_SWI5_IRQn);
|
||||
|
||||
k_thread_spawn(recv_thread_stack, sizeof(recv_thread_stack),
|
||||
recv_thread, NULL, NULL, NULL, K_PRIO_COOP(7), 0,
|
||||
|
|
|
@ -15,30 +15,35 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <misc/util.h>
|
||||
#include <soc.h>
|
||||
#include <device.h>
|
||||
#include <clock_control.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
#include "hal_work.h"
|
||||
|
||||
#include "defines.h"
|
||||
#include "cpu.h"
|
||||
#include "work.h"
|
||||
#include "rand.h"
|
||||
#include "ticker.h"
|
||||
#include "mem.h"
|
||||
#include "memq.h"
|
||||
#include "util.h"
|
||||
#include "ecb.h"
|
||||
#include "ccm.h"
|
||||
#include "radio.h"
|
||||
|
||||
#include "mem.h"
|
||||
#include "memq.h"
|
||||
#include "mayfly.h"
|
||||
#include "util.h"
|
||||
#include "ticker.h"
|
||||
|
||||
#include "pdu.h"
|
||||
#include "ctrl.h"
|
||||
#include "ctrl_internal.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <bluetooth/log.h>
|
||||
#include "debug.h"
|
||||
|
||||
#define RADIO_PREAMBLE_TO_ADDRESS_US 40
|
||||
|
@ -331,16 +336,16 @@ uint32_t radio_init(void *hf_clock, uint8_t sca, uint8_t connection_count_max,
|
|||
_radio.link_rx_data_quota = rx_count_max;
|
||||
|
||||
/* initialise rx queue memory */
|
||||
_radio.packet_rx = (struct radio_pdu_node_rx **)mem_radio;
|
||||
_radio.packet_rx = (void *)mem_radio;
|
||||
mem_radio +=
|
||||
(sizeof(struct radio_pdu_node_rx *)*_radio.packet_rx_count);
|
||||
|
||||
/* initialise tx queue memory */
|
||||
_radio.pkt_tx = (struct pdu_data_q_tx *)mem_radio;
|
||||
_radio.pkt_tx = (void *)mem_radio;
|
||||
mem_radio += (sizeof(struct pdu_data_q_tx) * _radio.packet_tx_count);
|
||||
|
||||
/* initialise tx release queue memory */
|
||||
_radio.pkt_release = (struct pdu_data_q_tx *)mem_radio;
|
||||
_radio.pkt_release = (void *)mem_radio;
|
||||
mem_radio += (sizeof(struct pdu_data_q_tx) * _radio.packet_tx_count);
|
||||
|
||||
/* initialise rx memory size and count */
|
||||
|
@ -349,12 +354,12 @@ uint32_t radio_init(void *hf_clock, uint8_t sca, uint8_t connection_count_max,
|
|||
(offsetof(struct pdu_data, payload) +
|
||||
_radio.packet_data_octets_max)) {
|
||||
_radio.packet_rx_data_pool_size =
|
||||
(ALIGN4(offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
(MROUND(offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
offsetof(struct pdu_data, payload) +
|
||||
_radio.packet_data_octets_max) * rx_count_max);
|
||||
} else {
|
||||
_radio.packet_rx_data_pool_size =
|
||||
(ALIGN4(offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
(MROUND(offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
(RADIO_ACPDU_SIZE_MAX + 1)) * rx_count_max);
|
||||
}
|
||||
_radio.packet_rx_data_size = PACKET_RX_DATA_SIZE_MIN;
|
||||
|
@ -376,7 +381,7 @@ uint32_t radio_init(void *hf_clock, uint8_t sca, uint8_t connection_count_max,
|
|||
|
||||
/* initialise tx data memory size and count */
|
||||
_radio.packet_tx_data_size =
|
||||
ALIGN4(offsetof(struct radio_pdu_node_tx, pdu_data) +
|
||||
MROUND(offsetof(struct radio_pdu_node_tx, pdu_data) +
|
||||
offsetof(struct pdu_data, payload) +
|
||||
packet_tx_data_size);
|
||||
|
||||
|
@ -2682,7 +2687,7 @@ static inline void isr_radio_state_close(void)
|
|||
|
||||
clock_control_off(_radio.hf_clock, NULL);
|
||||
|
||||
work_enable(WORK_TICKER_JOB0_IRQ);
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_WORKER, RADIO_TICKER_USER_ID_JOB, 1);
|
||||
|
||||
DEBUG_RADIO_CLOSE(0);
|
||||
}
|
||||
|
@ -2756,14 +2761,15 @@ static void isr(void)
|
|||
DEBUG_RADIO_ISR(0);
|
||||
}
|
||||
|
||||
#if (WORK_TICKER_WORKER0_IRQ_PRIORITY == WORK_TICKER_JOB0_IRQ_PRIORITY)
|
||||
#if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO)
|
||||
static void ticker_job_disable(uint32_t status, void *op_context)
|
||||
{
|
||||
ARG_UNUSED(status);
|
||||
ARG_UNUSED(op_context);
|
||||
|
||||
if (_radio.state != STATE_NONE) {
|
||||
work_disable(WORK_TICKER_JOB0_IRQ);
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_JOB, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -2780,7 +2786,7 @@ static void ticker_success_assert(uint32_t status, void *params)
|
|||
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
static void work_radio_active(void *params)
|
||||
static void mayfly_radio_active(void *params)
|
||||
{
|
||||
static uint8_t s_active;
|
||||
|
||||
|
@ -2808,9 +2814,9 @@ static void work_radio_active(void *params)
|
|||
static void event_active(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *context)
|
||||
{
|
||||
static struct work s_work_radio_active = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ, (work_fp) work_radio_active,
|
||||
(void *)1};
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_radio_active = {0, 0, s_link, (void *)1,
|
||||
mayfly_radio_active};
|
||||
uint32_t retval;
|
||||
|
||||
ARG_UNUSED(ticks_at_expire);
|
||||
|
@ -2818,15 +2824,17 @@ static void event_active(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
ARG_UNUSED(lazy);
|
||||
ARG_UNUSED(context);
|
||||
|
||||
retval = work_schedule(&s_work_radio_active, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_radio_active);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
|
||||
static void work_radio_inactive(void *params)
|
||||
static void mayfly_radio_inactive(void *params)
|
||||
{
|
||||
ARG_UNUSED(params);
|
||||
|
||||
work_radio_active(0);
|
||||
mayfly_radio_active(0);
|
||||
|
||||
DEBUG_RADIO_CLOSE(0);
|
||||
}
|
||||
|
@ -2834,8 +2842,9 @@ static void work_radio_inactive(void *params)
|
|||
static void event_inactive(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *context)
|
||||
{
|
||||
static struct work s_work_radio_inactive = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ, (work_fp) work_radio_inactive, 0};
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_radio_inactive = {0, 0, s_link, 0,
|
||||
mayfly_radio_inactive};
|
||||
uint32_t retval;
|
||||
|
||||
ARG_UNUSED(ticks_at_expire);
|
||||
|
@ -2843,11 +2852,13 @@ static void event_inactive(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
ARG_UNUSED(lazy);
|
||||
ARG_UNUSED(context);
|
||||
|
||||
retval = work_schedule(&s_work_radio_inactive, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_radio_inactive);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
|
||||
static void work_xtal_start(void *params)
|
||||
static void mayfly_xtal_start(void *params)
|
||||
{
|
||||
ARG_UNUSED(params);
|
||||
|
||||
|
@ -2858,8 +2869,9 @@ static void work_xtal_start(void *params)
|
|||
static void event_xtal(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *context)
|
||||
{
|
||||
static struct work s_work_xtal_start = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ, (work_fp) work_xtal_start, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_xtal_start = {0, 0, s_link, 0,
|
||||
mayfly_xtal_start};
|
||||
uint32_t retval;
|
||||
|
||||
ARG_UNUSED(ticks_at_expire);
|
||||
|
@ -2867,11 +2879,13 @@ static void event_xtal(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
ARG_UNUSED(lazy);
|
||||
ARG_UNUSED(context);
|
||||
|
||||
retval = work_schedule(&s_work_xtal_start, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_xtal_start);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
|
||||
static void work_xtal_stop(void *params)
|
||||
static void mayfly_xtal_stop(void *params)
|
||||
{
|
||||
ARG_UNUSED(params);
|
||||
|
||||
|
@ -2881,32 +2895,36 @@ static void work_xtal_stop(void *params)
|
|||
}
|
||||
|
||||
#if XTAL_ADVANCED
|
||||
static void work_xtal_retain(uint8_t retain)
|
||||
static void mayfly_xtal_retain(uint8_t retain)
|
||||
{
|
||||
static uint8_t s_xtal_retained;
|
||||
|
||||
if (retain) {
|
||||
if (!s_xtal_retained) {
|
||||
static struct work s_work_xtal_start = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ,
|
||||
(work_fp) work_xtal_start, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_xtal_start = {0, 0, s_link,
|
||||
0, mayfly_xtal_start};
|
||||
uint32_t retval;
|
||||
|
||||
s_xtal_retained = 1;
|
||||
|
||||
retval = work_schedule(&s_work_xtal_start, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_xtal_start);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
} else {
|
||||
if (s_xtal_retained) {
|
||||
static struct work s_work_xtal_stop = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ,
|
||||
(work_fp) work_xtal_stop, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_xtal_stop = {0, 0, s_link,
|
||||
0, mayfly_xtal_stop};
|
||||
uint32_t retval;
|
||||
|
||||
s_xtal_retained = 0;
|
||||
|
||||
retval = work_schedule(&s_work_xtal_stop, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_xtal_stop);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
}
|
||||
|
@ -2972,7 +2990,7 @@ static uint32_t preempt_calc(struct shdr *hdr, uint8_t ticker_id,
|
|||
|
||||
diff += 3;
|
||||
if (diff > TICKER_US_TO_TICKS(RADIO_TICKER_START_PART_US)) {
|
||||
work_xtal_retain(0);
|
||||
mayfly_xtal_retain(0);
|
||||
|
||||
prepare_normal_set(hdr, RADIO_TICKER_USER_ID_WORKER, ticker_id);
|
||||
|
||||
|
@ -2997,7 +3015,7 @@ static uint32_t preempt_calc(struct shdr *hdr, uint8_t ticker_id,
|
|||
*
|
||||
* @todo Detect drift for overlapping tickers.
|
||||
*/
|
||||
static void work_xtal_stop_calc(void *params)
|
||||
static void mayfly_xtal_stop_calc(void *params)
|
||||
{
|
||||
uint32_t volatile ticker_status;
|
||||
uint8_t ticker_id;
|
||||
|
@ -3013,14 +3031,15 @@ static void work_xtal_stop_calc(void *params)
|
|||
ticker_if_done, (void *)&ticker_status);
|
||||
|
||||
while (ticker_status == TICKER_STATUS_BUSY) {
|
||||
ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO);
|
||||
ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO,
|
||||
RADIO_TICKER_USER_ID_JOB);
|
||||
}
|
||||
|
||||
LL_ASSERT(ticker_status == TICKER_STATUS_SUCCESS);
|
||||
|
||||
if ((ticker_id != 0xff) &&
|
||||
(ticks_to_expire < TICKER_US_TO_TICKS(10000))) {
|
||||
work_xtal_retain(1);
|
||||
mayfly_xtal_retain(1);
|
||||
|
||||
if (ticker_id >= RADIO_TICKER_ID_ADV) {
|
||||
#if SCHED_ADVANCED
|
||||
|
@ -3158,7 +3177,7 @@ static void work_xtal_stop_calc(void *params)
|
|||
#endif /* SCHED_ADVANCED */
|
||||
}
|
||||
} else {
|
||||
work_xtal_retain(0);
|
||||
mayfly_xtal_retain(0);
|
||||
|
||||
if ((ticker_id != 0xff) && (ticker_id >= RADIO_TICKER_ID_ADV)) {
|
||||
struct shdr *hdr = NULL;
|
||||
|
@ -3189,10 +3208,10 @@ static void work_xtal_stop_calc(void *params)
|
|||
#endif /* XTAL_ADVANCED */
|
||||
|
||||
#if SCHED_ADVANCED
|
||||
static void sched_after_master_free_slot_get(uint8_t user_id,
|
||||
uint32_t ticks_slot_abs,
|
||||
uint32_t *ticks_anchor,
|
||||
uint32_t *us_offset)
|
||||
static void sched_after_mstr_free_slot_get(uint8_t user_id,
|
||||
uint32_t ticks_slot_abs,
|
||||
uint32_t *ticks_anchor,
|
||||
uint32_t *us_offset)
|
||||
{
|
||||
uint8_t ticker_id;
|
||||
uint8_t ticker_id_prev;
|
||||
|
@ -3214,7 +3233,8 @@ static void sched_after_master_free_slot_get(uint8_t user_id,
|
|||
(void *)&ticker_status);
|
||||
|
||||
while (ticker_status == TICKER_STATUS_BUSY) {
|
||||
ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO);
|
||||
ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO,
|
||||
user_id);
|
||||
}
|
||||
|
||||
LL_ASSERT(ticker_status == TICKER_STATUS_SUCCESS);
|
||||
|
@ -3268,17 +3288,18 @@ static void sched_after_master_free_slot_get(uint8_t user_id,
|
|||
}
|
||||
}
|
||||
|
||||
static void sched_after_master_free_offset_get(uint16_t conn_interval,
|
||||
uint32_t ticks_slot,
|
||||
uint32_t ticks_anchor,
|
||||
uint32_t *win_offset_us)
|
||||
static void sched_after_mstr_free_offset_get(uint16_t conn_interval,
|
||||
uint32_t ticks_slot,
|
||||
uint32_t ticks_anchor,
|
||||
uint32_t *win_offset_us)
|
||||
{
|
||||
uint32_t ticks_anchor_offset = ticks_anchor;
|
||||
|
||||
sched_after_master_free_slot_get(RADIO_TICKER_USER_ID_JOB,
|
||||
(TICKER_US_TO_TICKS(RADIO_TICKER_XTAL_OFFSET_US) +
|
||||
ticks_slot), &ticks_anchor_offset,
|
||||
win_offset_us);
|
||||
sched_after_mstr_free_slot_get(RADIO_TICKER_USER_ID_JOB,
|
||||
(TICKER_US_TO_TICKS(
|
||||
RADIO_TICKER_XTAL_OFFSET_US) +
|
||||
ticks_slot), &ticks_anchor_offset,
|
||||
win_offset_us);
|
||||
|
||||
if (ticks_anchor_offset != ticks_anchor) {
|
||||
*win_offset_us +=
|
||||
|
@ -3295,23 +3316,23 @@ static void sched_after_master_free_offset_get(uint16_t conn_interval,
|
|||
}
|
||||
}
|
||||
|
||||
static void work_sched_after_master_free_offset_get(void *params)
|
||||
static void mayfly_sched_after_mstr_free_offset_get(void *params)
|
||||
{
|
||||
sched_after_master_free_offset_get(_radio.observer.conn_interval,
|
||||
_radio.observer.ticks_conn_slot,
|
||||
(uint32_t)params,
|
||||
&_radio.observer.win_offset_us);
|
||||
sched_after_mstr_free_offset_get(_radio.observer.conn_interval,
|
||||
_radio.observer.ticks_conn_slot,
|
||||
(uint32_t)params,
|
||||
&_radio.observer.win_offset_us);
|
||||
}
|
||||
|
||||
static void work_sched_win_offset_use(void *params)
|
||||
static void mayfly_sched_win_offset_use(void *params)
|
||||
{
|
||||
struct connection *conn = (struct connection *)params;
|
||||
uint16_t win_offset;
|
||||
|
||||
sched_after_master_free_offset_get(conn->conn_interval,
|
||||
conn->hdr.ticks_slot,
|
||||
conn->llcp.connection_update.ticks_ref,
|
||||
&conn->llcp.connection_update.win_offset_us);
|
||||
sched_after_mstr_free_offset_get(conn->conn_interval,
|
||||
conn->hdr.ticks_slot,
|
||||
conn->llcp.connection_update.ticks_ref,
|
||||
&conn->llcp.connection_update.win_offset_us);
|
||||
|
||||
win_offset = conn->llcp.connection_update.win_offset_us / 1250;
|
||||
memcpy(conn->llcp.connection_update.pdu_win_offset, &win_offset,
|
||||
|
@ -3366,7 +3387,8 @@ static void sched_free_win_offset_calc(struct connection *conn_curr,
|
|||
(void *)&ticker_status);
|
||||
|
||||
while (ticker_status == TICKER_STATUS_BUSY) {
|
||||
ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO);
|
||||
ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO,
|
||||
RADIO_TICKER_USER_ID_JOB);
|
||||
}
|
||||
|
||||
LL_ASSERT(ticker_status == TICKER_STATUS_SUCCESS);
|
||||
|
@ -3495,7 +3517,7 @@ static void sched_free_win_offset_calc(struct connection *conn_curr,
|
|||
*offset_max = offset_index;
|
||||
}
|
||||
|
||||
static void work_sched_free_win_offset_calc(void *params)
|
||||
static void mayfly_sched_free_win_offset_calc(void *params)
|
||||
{
|
||||
struct connection *conn = (struct connection *)params;
|
||||
uint32_t ticks_to_offset_default = 0;
|
||||
|
@ -3518,7 +3540,7 @@ static void work_sched_free_win_offset_calc(void *params)
|
|||
(uint8_t *)conn->llcp.connection_update.pdu_win_offset);
|
||||
}
|
||||
|
||||
static void work_sched_win_offset_select(void *params)
|
||||
static void mayfly_sched_win_offset_select(void *params)
|
||||
{
|
||||
#define OFFSET_S_MAX 6
|
||||
#define OFFSET_M_MAX 6
|
||||
|
@ -3592,7 +3614,7 @@ static void work_sched_win_offset_select(void *params)
|
|||
}
|
||||
#endif /* SCHED_ADVANCED */
|
||||
|
||||
static void work_radio_stop(void *params)
|
||||
static void mayfly_radio_stop(void *params)
|
||||
{
|
||||
enum state state = (enum state)((uint32_t)params & 0xff);
|
||||
uint32_t radio_used;
|
||||
|
@ -3615,8 +3637,9 @@ static void work_radio_stop(void *params)
|
|||
static void event_stop(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *context)
|
||||
{
|
||||
static struct work s_work_radio_stop = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ, (work_fp) work_radio_stop, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_radio_stop = {0, 0, s_link, 0,
|
||||
mayfly_radio_stop};
|
||||
uint32_t retval;
|
||||
|
||||
ARG_UNUSED(ticks_at_expire);
|
||||
|
@ -3626,10 +3649,12 @@ static void event_stop(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
/* Radio state requested (stop or abort) stored in context is supplied
|
||||
* in params.
|
||||
*/
|
||||
s_work_radio_stop.params = context;
|
||||
s_mfy_radio_stop.param = context;
|
||||
|
||||
/* Stop Radio Tx/Rx */
|
||||
retval = work_schedule(&s_work_radio_stop, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_radio_stop);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
|
||||
|
@ -3776,14 +3801,16 @@ static void event_common_prepare(uint32_t ticks_at_expire,
|
|||
/* calc whether xtal needs to be retained after this event */
|
||||
#if XTAL_ADVANCED
|
||||
{
|
||||
static struct work s_work_xtal_stop_calc = {
|
||||
0, 0, 0, WORK_TICKER_JOB0_IRQ,
|
||||
(work_fp) work_xtal_stop_calc, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_xtal_stop_calc = {0, 0, s_link, 0,
|
||||
mayfly_xtal_stop_calc};
|
||||
uint32_t retval;
|
||||
|
||||
s_work_xtal_stop_calc.params = (void *)(uint32_t)ticker_id;
|
||||
s_mfy_xtal_stop_calc.param = (void *)(uint32_t)ticker_id;
|
||||
|
||||
retval = work_schedule(&s_work_xtal_stop_calc, 1);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_JOB, 1,
|
||||
&s_mfy_xtal_stop_calc);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
#endif
|
||||
|
@ -4064,8 +4091,9 @@ static void event_adv(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
radio_disable();
|
||||
} else
|
||||
#endif
|
||||
/* Ticker Job Silence */
|
||||
#if (WORK_TICKER_WORKER0_IRQ_PRIORITY == WORK_TICKER_JOB0_IRQ_PRIORITY)
|
||||
|
||||
/* Ticker Job Silence */
|
||||
#if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO)
|
||||
{
|
||||
uint32_t ticker_status;
|
||||
|
||||
|
@ -4158,9 +4186,10 @@ static void event_obs_prepare(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
* to be placed
|
||||
*/
|
||||
if (_radio.observer.conn) {
|
||||
static struct work _work_sched_after_master_free_offset_get = {
|
||||
0, 0, 0, WORK_TICKER_JOB0_IRQ,
|
||||
(work_fp) work_sched_after_master_free_offset_get, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_sched_after_mstr_free_offset_get = {
|
||||
0, 0, s_link, 0,
|
||||
mayfly_sched_after_mstr_free_offset_get};
|
||||
uint32_t ticks_at_expire_normal = ticks_at_expire;
|
||||
uint32_t retval;
|
||||
|
||||
|
@ -4177,11 +4206,12 @@ static void event_obs_prepare(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
ticks_prepare_to_start);
|
||||
}
|
||||
|
||||
_work_sched_after_master_free_offset_get.params =
|
||||
s_mfy_sched_after_mstr_free_offset_get.param =
|
||||
(void *)ticks_at_expire_normal;
|
||||
|
||||
retval = work_schedule(&_work_sched_after_master_free_offset_get,
|
||||
1);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_JOB, 1,
|
||||
&s_mfy_sched_after_mstr_free_offset_get);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
#endif
|
||||
|
@ -4267,7 +4297,7 @@ static void event_obs(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
(ticker_status == TICKER_STATUS_BUSY));
|
||||
|
||||
/* Ticker Job Silence */
|
||||
#if (WORK_TICKER_WORKER0_IRQ_PRIORITY == WORK_TICKER_JOB0_IRQ_PRIORITY)
|
||||
#if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO)
|
||||
{
|
||||
uint32_t ticker_status;
|
||||
|
||||
|
@ -4285,12 +4315,13 @@ static void event_obs(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
DEBUG_RADIO_START_O(0);
|
||||
}
|
||||
|
||||
static inline void event_conn_update_st_init(struct connection *conn,
|
||||
uint16_t event_counter,
|
||||
struct pdu_data *pdu_ctrl_tx,
|
||||
uint32_t ticks_at_expire,
|
||||
struct work *work_sched_offset,
|
||||
work_fp fp_work_select_or_use)
|
||||
static inline void
|
||||
event_conn_update_st_init(struct connection *conn,
|
||||
uint16_t event_counter,
|
||||
struct pdu_data *pdu_ctrl_tx,
|
||||
uint32_t ticks_at_expire,
|
||||
struct mayfly *mayfly_sched_offset,
|
||||
void (*fp_mayfly_select_or_use)(void *))
|
||||
{
|
||||
/* move to in progress */
|
||||
conn->llcp.connection_update.state = LLCP_CONN_STATE_INPROG;
|
||||
|
@ -4342,16 +4373,18 @@ static inline void event_conn_update_st_init(struct connection *conn,
|
|||
conn->llcp.connection_update.pdu_win_offset = (uint16_t *)
|
||||
&pdu_ctrl_tx->payload.llctrl.ctrldata.conn_update_req.win_offset;
|
||||
|
||||
work_sched_offset->fp = fp_work_select_or_use;
|
||||
work_sched_offset->params = (void *)conn;
|
||||
mayfly_sched_offset->fp = fp_mayfly_select_or_use;
|
||||
mayfly_sched_offset->param = (void *)conn;
|
||||
|
||||
retval = work_schedule(work_sched_offset, 1);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_JOB, 1,
|
||||
mayfly_sched_offset);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
#else
|
||||
ARG_UNUSED(ticks_at_expire);
|
||||
ARG_UNUSED(work_sched_offset);
|
||||
ARG_UNUSED(fp_work_select_or_use);
|
||||
ARG_UNUSED(mayfly_sched_offset);
|
||||
ARG_UNUSED(fp_mayfly_select_or_use);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -4359,7 +4392,7 @@ static inline void event_conn_update_st_req(struct connection *conn,
|
|||
uint16_t event_counter,
|
||||
struct pdu_data *pdu_ctrl_tx,
|
||||
uint32_t ticks_at_expire,
|
||||
struct work *work_sched_offset)
|
||||
struct mayfly *mayfly_sched_offset)
|
||||
{
|
||||
/* move to wait for conn_update/rsp/rej */
|
||||
conn->llcp.connection_update.state = LLCP_CONN_STATE_RSP_WAIT;
|
||||
|
@ -4411,15 +4444,17 @@ static inline void event_conn_update_st_req(struct connection *conn,
|
|||
conn->llcp.connection_update.pdu_win_offset = (uint16_t *)
|
||||
&pdu_ctrl_tx->payload.llctrl.ctrldata.conn_param_req.offset0;
|
||||
|
||||
work_sched_offset->fp = work_sched_free_win_offset_calc;
|
||||
work_sched_offset->params = (void *)conn;
|
||||
mayfly_sched_offset->fp = mayfly_sched_free_win_offset_calc;
|
||||
mayfly_sched_offset->param = (void *)conn;
|
||||
|
||||
retval = work_schedule(work_sched_offset, 1);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_JOB, 1,
|
||||
mayfly_sched_offset);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
#else
|
||||
ARG_UNUSED(ticks_at_expire);
|
||||
ARG_UNUSED(work_sched_offset);
|
||||
ARG_UNUSED(mayfly_sched_offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -4490,9 +4525,10 @@ static inline uint32_t event_conn_update_prep(struct connection *conn,
|
|||
(conn->llcp.connection_update.state !=
|
||||
LLCP_CONN_STATE_RSP_WAIT)) {
|
||||
#if SCHED_ADVANCED
|
||||
static struct work gs_work_sched_offset = {
|
||||
0, 0, 0, WORK_TICKER_JOB0_IRQ, 0, 0 };
|
||||
work_fp fp_work_select_or_use;
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_sched_offset = {0, 0,
|
||||
s_link, 0, 0 };
|
||||
void (*fp_mayfly_select_or_use)(void *);
|
||||
#endif
|
||||
struct radio_pdu_node_tx *node_tx;
|
||||
struct pdu_data *pdu_ctrl_tx;
|
||||
|
@ -4506,15 +4542,15 @@ static inline uint32_t event_conn_update_prep(struct connection *conn,
|
|||
pdu_ctrl_tx = (struct pdu_data *)node_tx->pdu_data;
|
||||
|
||||
#if SCHED_ADVANCED
|
||||
fp_work_select_or_use = work_sched_win_offset_use;
|
||||
fp_mayfly_select_or_use = mayfly_sched_win_offset_use;
|
||||
#endif
|
||||
state = conn->llcp.connection_update.state;
|
||||
if ((state == LLCP_CONN_STATE_RSP) &&
|
||||
(conn->role.master.role == 0)) {
|
||||
state = LLCP_CONN_STATE_INITIATE;
|
||||
#if SCHED_ADVANCED
|
||||
fp_work_select_or_use =
|
||||
work_sched_win_offset_select;
|
||||
fp_mayfly_select_or_use =
|
||||
mayfly_sched_win_offset_select;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -4523,18 +4559,18 @@ static inline uint32_t event_conn_update_prep(struct connection *conn,
|
|||
if (conn->role.master.role == 0) {
|
||||
#if SCHED_ADVANCED
|
||||
event_conn_update_st_init(conn,
|
||||
event_counter,
|
||||
pdu_ctrl_tx,
|
||||
ticks_at_expire,
|
||||
&gs_work_sched_offset,
|
||||
fp_work_select_or_use);
|
||||
event_counter,
|
||||
pdu_ctrl_tx,
|
||||
ticks_at_expire,
|
||||
&s_mfy_sched_offset,
|
||||
fp_mayfly_select_or_use);
|
||||
#else
|
||||
event_conn_update_st_init(conn,
|
||||
event_counter,
|
||||
pdu_ctrl_tx,
|
||||
ticks_at_expire,
|
||||
NULL,
|
||||
NULL);
|
||||
event_counter,
|
||||
pdu_ctrl_tx,
|
||||
ticks_at_expire,
|
||||
NULL,
|
||||
NULL);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -4546,7 +4582,7 @@ static inline uint32_t event_conn_update_prep(struct connection *conn,
|
|||
event_counter,
|
||||
pdu_ctrl_tx,
|
||||
ticks_at_expire,
|
||||
&gs_work_sched_offset);
|
||||
&s_mfy_sched_offset);
|
||||
#else
|
||||
event_conn_update_st_req(conn,
|
||||
event_counter,
|
||||
|
@ -4579,7 +4615,7 @@ static inline uint32_t event_conn_update_prep(struct connection *conn,
|
|||
uint16_t conn_interval_old;
|
||||
uint16_t conn_interval_new;
|
||||
uint16_t latency;
|
||||
uint32_t work_was_enabled;
|
||||
uint32_t mayfly_was_enabled;
|
||||
|
||||
/* procedure request acked */
|
||||
conn->llcp_ack = conn->llcp_req;
|
||||
|
@ -4728,8 +4764,11 @@ static inline uint32_t event_conn_update_prep(struct connection *conn,
|
|||
/* disable ticker job, in order to chain stop and start
|
||||
* to avoid RTC being stopped if no tickers active.
|
||||
*/
|
||||
work_was_enabled = work_is_enabled(WORK_TICKER_JOB0_IRQ);
|
||||
work_disable(WORK_TICKER_JOB0_IRQ);
|
||||
mayfly_was_enabled =
|
||||
mayfly_is_enabled(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_JOB);
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_JOB, 0);
|
||||
|
||||
/* start slave/master with new timings */
|
||||
ticker_status =
|
||||
|
@ -4758,8 +4797,9 @@ static inline uint32_t event_conn_update_prep(struct connection *conn,
|
|||
(ticker_status == TICKER_STATUS_BUSY));
|
||||
|
||||
/* enable ticker job, if disabled in this function */
|
||||
if (work_was_enabled) {
|
||||
work_enable(WORK_TICKER_JOB0_IRQ);
|
||||
if (mayfly_was_enabled) {
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_WORKER,
|
||||
RADIO_TICKER_USER_ID_JOB, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -5204,7 +5244,7 @@ static inline void event_len_prep(struct connection *conn)
|
|||
if (_radio.observer.conn) {
|
||||
free_count_conn++;
|
||||
}
|
||||
packet_rx_data_size = ALIGN4(offsetof(struct radio_pdu_node_rx,
|
||||
packet_rx_data_size = MROUND(offsetof(struct radio_pdu_node_rx,
|
||||
pdu_data) +
|
||||
offsetof(struct pdu_data,
|
||||
payload) +
|
||||
|
@ -5247,9 +5287,9 @@ static inline void event_len_prep(struct connection *conn)
|
|||
/* calculate the new rx node size and new count */
|
||||
if (conn->max_rx_octets < (RADIO_ACPDU_SIZE_MAX + 1)) {
|
||||
_radio.packet_rx_data_size =
|
||||
ALIGN4(offsetof(struct radio_pdu_node_rx,
|
||||
pdu_data) +
|
||||
(RADIO_ACPDU_SIZE_MAX + 1));
|
||||
MROUND(offsetof(struct radio_pdu_node_rx,
|
||||
pdu_data) +
|
||||
(RADIO_ACPDU_SIZE_MAX + 1));
|
||||
} else {
|
||||
_radio.packet_rx_data_size =
|
||||
packet_rx_data_size;
|
||||
|
@ -5552,8 +5592,8 @@ static void event_slave(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
} else
|
||||
#endif
|
||||
|
||||
/* Ticker Job Silence */
|
||||
#if (WORK_TICKER_WORKER0_IRQ_PRIORITY == WORK_TICKER_JOB0_IRQ_PRIORITY)
|
||||
/* Ticker Job Silence */
|
||||
#if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO)
|
||||
{
|
||||
uint32_t ticker_status;
|
||||
|
||||
|
@ -5690,7 +5730,7 @@ static void event_master(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
#endif
|
||||
|
||||
/* Ticker Job Silence */
|
||||
#if (WORK_TICKER_WORKER0_IRQ_PRIORITY == WORK_TICKER_JOB0_IRQ_PRIORITY)
|
||||
#if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO)
|
||||
{
|
||||
uint32_t ticker_status;
|
||||
|
||||
|
@ -5920,12 +5960,14 @@ static struct radio_pdu_node_rx *packet_rx_reserve_get(uint8_t count)
|
|||
return radio_pdu_node_rx;
|
||||
}
|
||||
|
||||
static void event_callback(void)
|
||||
static void packet_rx_callback(void)
|
||||
{
|
||||
static struct work work_event_callback = { 0, 0, 0,
|
||||
WORK_TICKER_JOB0_IRQ, (work_fp) radio_event_callback, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_callback = {0, 0, s_link, 0,
|
||||
(void *)radio_event_callback};
|
||||
|
||||
work_schedule(&work_event_callback, 1);
|
||||
mayfly_enqueue(RADIO_TICKER_USER_ID_WORKER, RADIO_TICKER_USER_ID_JOB, 1,
|
||||
&s_mfy_callback);
|
||||
}
|
||||
|
||||
static void packet_rx_enqueue(void)
|
||||
|
@ -5959,7 +6001,7 @@ static void packet_rx_enqueue(void)
|
|||
LL_ASSERT(link);
|
||||
|
||||
/* callback to trigger application action */
|
||||
event_callback();
|
||||
packet_rx_callback();
|
||||
}
|
||||
|
||||
static void packet_tx_enqueue(uint8_t max)
|
||||
|
@ -6112,7 +6154,7 @@ static void pdu_node_tx_release(uint16_t handle,
|
|||
_radio.packet_release_last = last;
|
||||
|
||||
/* callback to trigger application action */
|
||||
event_callback();
|
||||
packet_rx_callback();
|
||||
}
|
||||
|
||||
static void connection_release(struct connection *conn)
|
||||
|
@ -6122,7 +6164,7 @@ static void connection_release(struct connection *conn)
|
|||
/* Enable Ticker Job, we are in a radio event which disabled it if
|
||||
* worker0 and job0 priority where same.
|
||||
*/
|
||||
work_enable(WORK_TICKER_JOB0_IRQ);
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_WORKER, RADIO_TICKER_USER_ID_JOB, 1);
|
||||
|
||||
/** @todo correctly stop tickers ensuring crystal and radio active are
|
||||
* placed in right states
|
||||
|
@ -6243,7 +6285,7 @@ static void terminate_ind_rx_enqueue(struct connection *conn, uint8_t reason)
|
|||
LL_ASSERT(link);
|
||||
|
||||
/* callback to trigger application action */
|
||||
event_callback();
|
||||
packet_rx_callback();
|
||||
}
|
||||
|
||||
static uint32_t conn_update(struct connection *conn,
|
||||
|
@ -6687,8 +6729,9 @@ static inline void role_active_disable(uint8_t ticker_id_stop,
|
|||
uint32_t ticks_xtal_to_start,
|
||||
uint32_t ticks_active_to_start)
|
||||
{
|
||||
static struct work s_work_radio_inactive = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ, (work_fp) work_radio_inactive, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_radio_inactive = {0, 0, s_link, 0,
|
||||
mayfly_radio_inactive};
|
||||
uint32_t volatile ticker_status_event;
|
||||
|
||||
/* Step 2: Is caller before Event? Stop Event */
|
||||
|
@ -6698,14 +6741,16 @@ static inline void role_active_disable(uint8_t ticker_id_stop,
|
|||
ticker_if_done, (void *)&ticker_status_event);
|
||||
|
||||
if (ticker_status_event == TICKER_STATUS_BUSY) {
|
||||
work_enable(WORK_TICKER_JOB0_IRQ);
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_JOB, 1);
|
||||
|
||||
LL_ASSERT(ticker_status_event != TICKER_STATUS_BUSY);
|
||||
}
|
||||
|
||||
if (ticker_status_event == TICKER_STATUS_SUCCESS) {
|
||||
static struct work s_work_xtal_stop = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ, (work_fp) work_xtal_stop, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_xtal_stop = {0, 0, s_link, 0,
|
||||
mayfly_xtal_stop};
|
||||
uint32_t volatile ticker_status_pre_event;
|
||||
|
||||
/* Step 2.1: Is caller between Primary and Marker0?
|
||||
|
@ -6719,7 +6764,8 @@ static inline void role_active_disable(uint8_t ticker_id_stop,
|
|||
(void *)&ticker_status_pre_event);
|
||||
|
||||
if (ticker_status_pre_event == TICKER_STATUS_BUSY) {
|
||||
work_enable(WORK_TICKER_JOB0_IRQ);
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_JOB, 1);
|
||||
|
||||
LL_ASSERT(ticker_status_event != TICKER_STATUS_BUSY);
|
||||
}
|
||||
|
@ -6734,14 +6780,19 @@ static inline void role_active_disable(uint8_t ticker_id_stop,
|
|||
/* radio active asserted, handle deasserting
|
||||
* here
|
||||
*/
|
||||
retval = work_schedule(&s_work_radio_inactive,
|
||||
0);
|
||||
retval = mayfly_enqueue(
|
||||
RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_radio_inactive);
|
||||
LL_ASSERT(!retval);
|
||||
} else {
|
||||
uint32_t retval;
|
||||
|
||||
/* XTAL started, handle XTAL stop here */
|
||||
retval = work_schedule(&s_work_xtal_stop, 0);
|
||||
retval = mayfly_enqueue(
|
||||
RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_xtal_stop);
|
||||
LL_ASSERT(!retval);
|
||||
}
|
||||
} else if (ticker_status_pre_event == TICKER_STATUS_FAILURE) {
|
||||
|
@ -6750,11 +6801,15 @@ static inline void role_active_disable(uint8_t ticker_id_stop,
|
|||
/* Step 2.1.2: Deassert Radio Active and XTAL start */
|
||||
|
||||
/* radio active asserted, handle deasserting here */
|
||||
retval = work_schedule(&s_work_radio_inactive, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_radio_inactive);
|
||||
LL_ASSERT(!retval);
|
||||
|
||||
/* XTAL started, handle XTAL stop here */
|
||||
retval = work_schedule(&s_work_xtal_stop, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_xtal_stop);
|
||||
LL_ASSERT(!retval);
|
||||
} else {
|
||||
LL_ASSERT(0);
|
||||
|
@ -6775,7 +6830,8 @@ static inline void role_active_disable(uint8_t ticker_id_stop,
|
|||
(void *)&ticker_status_stop);
|
||||
|
||||
if (ticker_status_stop == TICKER_STATUS_BUSY) {
|
||||
work_enable(WORK_TICKER_JOB0_IRQ);
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_JOB, 1);
|
||||
|
||||
LL_ASSERT(ticker_status_event != TICKER_STATUS_BUSY);
|
||||
}
|
||||
|
@ -6784,16 +6840,18 @@ static inline void role_active_disable(uint8_t ticker_id_stop,
|
|||
(ticker_status_stop == TICKER_STATUS_FAILURE));
|
||||
|
||||
if (_radio.role != ROLE_NONE) {
|
||||
static struct work s_work_radio_stop = { 0, 0, 0,
|
||||
WORK_TICKER_WORKER0_IRQ,
|
||||
(work_fp) work_radio_stop, 0 };
|
||||
static void *s_link[2];
|
||||
static struct mayfly s_mfy_radio_stop = {0, 0, s_link,
|
||||
0, mayfly_radio_stop};
|
||||
uint32_t retval;
|
||||
|
||||
/* Radio state STOP is supplied in params */
|
||||
s_work_radio_stop.params = (void *)STATE_STOP;
|
||||
s_mfy_radio_stop.param = (void *)STATE_STOP;
|
||||
|
||||
/* Stop Radio Tx/Rx */
|
||||
retval = work_schedule(&s_work_radio_stop, 0);
|
||||
retval = mayfly_enqueue(RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_WORKER, 0,
|
||||
&s_mfy_radio_stop);
|
||||
LL_ASSERT(!retval);
|
||||
|
||||
/* wait for radio ISR to exit */
|
||||
|
@ -6860,7 +6918,8 @@ static uint32_t role_disable(uint8_t ticker_id_primary,
|
|||
if (ticker_status == TICKER_STATUS_BUSY) {
|
||||
/* if inside our event, enable Job. */
|
||||
if (_radio.ticker_id_event == ticker_id_primary) {
|
||||
work_enable(WORK_TICKER_JOB0_IRQ);
|
||||
mayfly_enable(RADIO_TICKER_USER_ID_JOB,
|
||||
RADIO_TICKER_USER_ID_JOB, 1);
|
||||
}
|
||||
|
||||
/** @todo design to avoid this wait */
|
||||
|
@ -7156,10 +7215,10 @@ uint32_t radio_scan_enable(uint8_t scan_type, uint8_t init_addr_type,
|
|||
}
|
||||
#if SCHED_ADVANCED
|
||||
else {
|
||||
sched_after_master_free_slot_get(RADIO_TICKER_USER_ID_APP,
|
||||
(ticks_slot_offset +
|
||||
_radio.observer.hdr.ticks_slot),
|
||||
&ticks_anchor, &us_offset);
|
||||
sched_after_mstr_free_slot_get(RADIO_TICKER_USER_ID_APP,
|
||||
(ticks_slot_offset +
|
||||
_radio.observer.hdr.ticks_slot),
|
||||
&ticks_anchor, &us_offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#ifndef _CTRL_H_
|
||||
#define _CTRL_H_
|
||||
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Zephyr Kconfig defined
|
||||
****************************************************************************/
|
||||
|
@ -76,9 +74,12 @@
|
|||
|
||||
#define RADIO_TICKER_USERS 3
|
||||
|
||||
#define RADIO_TICKER_USER_ID_WORKER 0
|
||||
#define RADIO_TICKER_USER_ID_JOB 1
|
||||
#define RADIO_TICKER_USER_ID_APP 2
|
||||
#define RADIO_TICKER_USER_ID_WORKER TICKER_MAYFLY_CALL_ID_WORKER0
|
||||
#define RADIO_TICKER_USER_ID_JOB TICKER_MAYFLY_CALL_ID_JOB0
|
||||
#define RADIO_TICKER_USER_ID_APP TICKER_MAYFLY_CALL_ID_PROGRAM
|
||||
|
||||
#define RADIO_TICKER_USER_ID_WORKER_PRIO TICKER_MAYFLY_CALL_ID_WORKER0_PRIO
|
||||
#define RADIO_TICKER_USER_ID_JOB_PRIO TICKER_MAYFLY_CALL_ID_JOB0_PRIO
|
||||
|
||||
#define RADIO_TICKER_USER_WORKER_OPS (7 + 1)
|
||||
#define RADIO_TICKER_USER_JOB_OPS (2 + 1)
|
||||
|
@ -289,6 +290,7 @@ uint8_t radio_rx_get(struct radio_pdu_node_rx **radio_pdu_node_rx,
|
|||
void radio_rx_dequeue(void);
|
||||
void radio_rx_mem_release(struct radio_pdu_node_rx **radio_pdu_node_rx);
|
||||
uint8_t radio_rx_fc_set(uint16_t handle, uint8_t fc);
|
||||
uint8_t radio_rx_fc_get(uint16_t *handle);
|
||||
struct radio_pdu_node_tx *radio_tx_mem_acquire(void);
|
||||
void radio_tx_mem_release(struct radio_pdu_node_tx *pdu_data_node_tx);
|
||||
uint32_t radio_tx_mem_enqueue(uint16_t handle,
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "util/defines.h"
|
||||
#include "pdu.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
enum llcp {
|
||||
LLCP_NONE,
|
||||
LLCP_CONNECTION_UPDATE,
|
||||
|
@ -204,7 +199,7 @@ struct connection {
|
|||
uint8_t rssi_sample_count;
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI */
|
||||
};
|
||||
#define CONNECTION_T_SIZE ALIGN4(sizeof(struct connection))
|
||||
#define CONNECTION_T_SIZE MROUND(sizeof(struct connection))
|
||||
|
||||
struct pdu_data_q_tx {
|
||||
uint16_t handle;
|
||||
|
@ -213,12 +208,12 @@ struct pdu_data_q_tx {
|
|||
|
||||
/* Minimum Rx Data allocation size */
|
||||
#define PACKET_RX_DATA_SIZE_MIN \
|
||||
ALIGN4(offsetof(struct radio_pdu_node_rx, pdu_data) + \
|
||||
MROUND(offsetof(struct radio_pdu_node_rx, pdu_data) + \
|
||||
(RADIO_ACPDU_SIZE_MAX + 1))
|
||||
|
||||
/* Minimum Tx Ctrl allocation size */
|
||||
#define PACKET_TX_CTRL_SIZE_MIN \
|
||||
ALIGN4(offsetof(struct radio_pdu_node_tx, pdu_data) + \
|
||||
MROUND(offsetof(struct radio_pdu_node_tx, pdu_data) + \
|
||||
offsetof(struct pdu_data, payload) + 27)
|
||||
|
||||
/** @todo fix starvation when ctrl rx in radio ISR
|
||||
|
@ -232,7 +227,7 @@ struct pdu_data_q_tx {
|
|||
#define LL_MEM_TXQ (sizeof(struct pdu_data_q_tx) * \
|
||||
(RADIO_PACKET_COUNT_TX_MAX + 2))
|
||||
|
||||
#define LL_MEM_RX_POOL_SZ (ALIGN4(offsetof(struct radio_pdu_node_rx,\
|
||||
#define LL_MEM_RX_POOL_SZ (MROUND(offsetof(struct radio_pdu_node_rx,\
|
||||
pdu_data) + ((\
|
||||
(RADIO_ACPDU_SIZE_MAX + 1) < \
|
||||
(offsetof(struct pdu_data, payload) + \
|
||||
|
@ -247,7 +242,7 @@ struct pdu_data_q_tx {
|
|||
4) + RADIO_CONNECTION_CONTEXT_MAX))
|
||||
|
||||
#define LL_MEM_TX_CTRL_POOL (PACKET_TX_CTRL_SIZE_MIN * PACKET_MEM_COUNT_TX_CTRL)
|
||||
#define LL_MEM_TX_DATA_POOL ((ALIGN4(offsetof( \
|
||||
#define LL_MEM_TX_DATA_POOL ((MROUND(offsetof( \
|
||||
struct radio_pdu_node_tx, pdu_data) + \
|
||||
offsetof(struct pdu_data, payload) + \
|
||||
RADIO_PACKET_TX_DATA_SIZE)) \
|
||||
|
|
|
@ -17,14 +17,18 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "defines.h"
|
||||
#include "mem.h"
|
||||
#include "ticker.h"
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
#include "ccm.h"
|
||||
#include "radio.h"
|
||||
|
||||
#include "mem.h"
|
||||
#include "util.h"
|
||||
#include "ticker.h"
|
||||
|
||||
#include "pdu.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
#include "ll.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef _PDU_H_
|
||||
#define _PDU_H_
|
||||
|
||||
#include <toolchain.h>
|
||||
#define BDADDR_SIZE 6
|
||||
|
||||
struct pdu_adv_payload_adv_ind {
|
||||
uint8_t addr[BDADDR_SIZE];
|
||||
|
|
|
@ -17,26 +17,29 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hal_rtc.h"
|
||||
#include "hal_work.h"
|
||||
#include "work.h"
|
||||
|
||||
#include "cntr.h"
|
||||
#include "ticker.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <soc.h>
|
||||
#include <bluetooth/log.h>
|
||||
#include "debug.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Defines
|
||||
****************************************************************************/
|
||||
#define TICKER_DOUBLE_BUFFER_SIZE 2
|
||||
#define TICKER_RTC_CC_OFFSET_MIN 3
|
||||
#define DOUBLE_BUFFER_SIZE 2
|
||||
#define COUNTER_CMP_OFFSET_MIN 3
|
||||
|
||||
#define CALL_ID_TRIGGER 0
|
||||
#define CALL_ID_WORKER 1
|
||||
#define CALL_ID_JOB 2
|
||||
#define CALL_ID_USER 3
|
||||
|
||||
/*****************************************************************************
|
||||
* Types
|
||||
****************************************************************************/
|
||||
typedef void (*ticker_fp_sched) (uint8_t chain);
|
||||
typedef void (*ticker_fp_compare_set) (uint32_t cc);
|
||||
|
||||
struct ticker_node {
|
||||
uint8_t next;
|
||||
|
||||
|
@ -119,16 +122,16 @@ struct ticker_instance {
|
|||
uint8_t count_user;
|
||||
uint8_t ticks_elapsed_first;
|
||||
uint8_t ticks_elapsed_last;
|
||||
uint32_t ticks_elapsed[TICKER_DOUBLE_BUFFER_SIZE];
|
||||
uint32_t ticks_elapsed[DOUBLE_BUFFER_SIZE];
|
||||
uint32_t ticks_current;
|
||||
uint8_t ticker_id_head;
|
||||
uint8_t ticker_id_slot_previous;
|
||||
uint16_t ticks_slot_previous;
|
||||
uint8_t job_guard;
|
||||
uint8_t worker_trigger;
|
||||
ticker_fp_sched fp_worker_sched;
|
||||
ticker_fp_sched fp_job_sched;
|
||||
ticker_fp_compare_set fp_compare_set;
|
||||
uint8_t (*fp_caller_id_get)(uint8_t user_id);
|
||||
void (*fp_sched)(uint8_t caller_id, uint8_t callee_id, uint8_t chain);
|
||||
void (*fp_cmp_set)(uint32_t value);
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -356,8 +359,8 @@ static inline void ticker_worker(struct ticker_instance *instance)
|
|||
}
|
||||
|
||||
/* ticks_elapsed is collected here, job will use it */
|
||||
ticks_elapsed =
|
||||
ticker_ticks_diff_get(rtc_tick_get(), instance->ticks_current);
|
||||
ticks_elapsed = ticker_ticks_diff_get(cntr_cnt_get(),
|
||||
instance->ticks_current);
|
||||
|
||||
/* initialise actual elapsed ticks being consumed */
|
||||
ticks_expired = 0;
|
||||
|
@ -413,7 +416,7 @@ static inline void ticker_worker(struct ticker_instance *instance)
|
|||
uint8_t last;
|
||||
|
||||
last = instance->ticks_elapsed_last + 1;
|
||||
if (last == TICKER_DOUBLE_BUFFER_SIZE) {
|
||||
if (last == DOUBLE_BUFFER_SIZE) {
|
||||
last = 0;
|
||||
}
|
||||
instance->ticks_elapsed_last = last;
|
||||
|
@ -423,7 +426,7 @@ static inline void ticker_worker(struct ticker_instance *instance)
|
|||
|
||||
instance->worker_trigger = 0;
|
||||
|
||||
instance->fp_job_sched(1);
|
||||
instance->fp_sched(CALL_ID_WORKER, CALL_ID_JOB, 1);
|
||||
}
|
||||
|
||||
static void prepare_ticks_to_expire(struct ticker_node *ticker,
|
||||
|
@ -498,7 +501,7 @@ static inline void ticker_job_node_update(struct ticker_node *ticker,
|
|||
uint32_t ticks_now;
|
||||
uint32_t ticks_to_expire = ticker->ticks_to_expire;
|
||||
|
||||
ticks_now = rtc_tick_get();
|
||||
ticks_now = cntr_cnt_get();
|
||||
ticks_elapsed += ticker_ticks_diff_get(ticks_now, ticks_current);
|
||||
if (ticks_to_expire > ticks_elapsed) {
|
||||
ticks_to_expire -= ticks_elapsed;
|
||||
|
@ -685,7 +688,8 @@ static inline uint8_t ticker_job_list_manage(
|
|||
*/
|
||||
/* sched job to run after worker bottom half.
|
||||
*/
|
||||
instance->fp_job_sched(1);
|
||||
instance->fp_sched(CALL_ID_JOB,
|
||||
CALL_ID_JOB, 1);
|
||||
|
||||
/* Update the index upto which management is
|
||||
* complete.
|
||||
|
@ -1023,7 +1027,7 @@ static inline void ticker_job_compare_update(
|
|||
uint32_t i;
|
||||
|
||||
if (instance->ticker_id_head == TICKER_NULL) {
|
||||
if (rtc_stop() == 0) {
|
||||
if (cntr_stop() == 0) {
|
||||
instance->ticks_slot_previous = 0;
|
||||
}
|
||||
|
||||
|
@ -1033,9 +1037,9 @@ static inline void ticker_job_compare_update(
|
|||
if (ticker_id_old_head == TICKER_NULL) {
|
||||
uint32_t ticks_current;
|
||||
|
||||
ticks_current = rtc_tick_get();
|
||||
ticks_current = cntr_cnt_get();
|
||||
|
||||
if (rtc_start() == 0) {
|
||||
if (cntr_start() == 0) {
|
||||
instance->ticks_current = ticks_current;
|
||||
}
|
||||
}
|
||||
|
@ -1056,19 +1060,19 @@ static inline void ticker_job_compare_update(
|
|||
LL_ASSERT(i);
|
||||
i--;
|
||||
|
||||
ctr = rtc_tick_get();
|
||||
ctr = cntr_cnt_get();
|
||||
cc = instance->ticks_current;
|
||||
ticks_elapsed = ticker_ticks_diff_get(ctr, cc) +
|
||||
TICKER_RTC_CC_OFFSET_MIN;
|
||||
COUNTER_CMP_OFFSET_MIN;
|
||||
cc += ((ticks_elapsed < ticks_to_expire) ?
|
||||
ticks_to_expire : ticks_elapsed);
|
||||
cc &= 0x00FFFFFF;
|
||||
|
||||
instance->fp_compare_set(cc);
|
||||
instance->fp_cmp_set(cc);
|
||||
|
||||
ctr_post = rtc_tick_get();
|
||||
ctr_post = cntr_cnt_get();
|
||||
} while ((ticker_ticks_diff_get(ctr_post, ctr) +
|
||||
TICKER_RTC_CC_OFFSET_MIN) > ticker_ticks_diff_get(cc, ctr));
|
||||
COUNTER_CMP_OFFSET_MIN) > ticker_ticks_diff_get(cc, ctr));
|
||||
}
|
||||
|
||||
static inline void ticker_job(struct ticker_instance *instance)
|
||||
|
@ -1099,7 +1103,7 @@ static inline void ticker_job(struct ticker_instance *instance)
|
|||
uint8_t first;
|
||||
|
||||
first = instance->ticks_elapsed_first + 1;
|
||||
if (first == TICKER_DOUBLE_BUFFER_SIZE) {
|
||||
if (first == DOUBLE_BUFFER_SIZE) {
|
||||
first = 0;
|
||||
}
|
||||
instance->ticks_elapsed_first = first;
|
||||
|
@ -1172,79 +1176,341 @@ static inline void ticker_job(struct ticker_instance *instance)
|
|||
|
||||
/* trigger worker if deferred */
|
||||
if (instance->worker_trigger) {
|
||||
instance->fp_worker_sched(1);
|
||||
instance->fp_sched(CALL_ID_JOB, CALL_ID_WORKER, 1);
|
||||
}
|
||||
|
||||
DEBUG_TICKER_JOB(0);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Instances Work Helpers
|
||||
* Instances Helpers
|
||||
*
|
||||
* TODO: decouple it from using work/mayfly in this file and dynamically
|
||||
* import it.
|
||||
****************************************************************************/
|
||||
static void ticker_instance0_worker_sched(uint8_t chain)
|
||||
{
|
||||
static struct work instance0_worker_irq = {
|
||||
0, 0, 0, WORK_TICKER_WORKER0_IRQ, (work_fp) ticker_worker,
|
||||
&_instance[0]
|
||||
};
|
||||
#include "mayfly.h"
|
||||
#include "config.h"
|
||||
|
||||
static uint8_t ticker_instance0_caller_id_get(uint8_t user_id)
|
||||
{
|
||||
if (user_id == TICKER_MAYFLY_CALL_ID_PROGRAM) {
|
||||
return CALL_ID_USER;
|
||||
} else if (user_id == TICKER_MAYFLY_CALL_ID_JOB0) {
|
||||
return CALL_ID_JOB;
|
||||
} else if (user_id == TICKER_MAYFLY_CALL_ID_WORKER0) {
|
||||
return CALL_ID_WORKER;
|
||||
} else if (user_id == TICKER_MAYFLY_CALL_ID_TRIGGER) {
|
||||
return CALL_ID_TRIGGER;
|
||||
}
|
||||
|
||||
LL_ASSERT(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t ticker_instance1_caller_id_get(uint8_t user_id)
|
||||
{
|
||||
if (user_id == TICKER_MAYFLY_CALL_ID_PROGRAM) {
|
||||
return CALL_ID_USER;
|
||||
} else if (user_id == TICKER_MAYFLY_CALL_ID_JOB1) {
|
||||
return CALL_ID_JOB;
|
||||
} else if (user_id == TICKER_MAYFLY_CALL_ID_WORKER1) {
|
||||
return CALL_ID_WORKER;
|
||||
} else if (user_id == TICKER_MAYFLY_CALL_ID_TRIGGER) {
|
||||
return CALL_ID_TRIGGER;
|
||||
}
|
||||
|
||||
LL_ASSERT(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id,
|
||||
uint8_t chain)
|
||||
{
|
||||
/* return value not checked as we allow multiple calls to schedule
|
||||
* before being actually needing the work to complete before new
|
||||
* schedule.
|
||||
*/
|
||||
work_schedule(&instance0_worker_irq, chain);
|
||||
switch (caller_id) {
|
||||
case CALL_ID_TRIGGER:
|
||||
switch (callee_id) {
|
||||
case CALL_ID_WORKER:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
&_instance[0],
|
||||
(void *)ticker_worker
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER,
|
||||
TICKER_MAYFLY_CALL_ID_WORKER0,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL_ID_JOB:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[0],
|
||||
(void *)ticker_job
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER,
|
||||
TICKER_MAYFLY_CALL_ID_JOB0,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL_ID_WORKER:
|
||||
switch (callee_id) {
|
||||
case CALL_ID_JOB:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[0],
|
||||
(void *)ticker_job
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_WORKER0,
|
||||
TICKER_MAYFLY_CALL_ID_JOB0,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL_ID_JOB:
|
||||
switch (callee_id) {
|
||||
case CALL_ID_WORKER:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[0],
|
||||
(void *)ticker_worker
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB0,
|
||||
TICKER_MAYFLY_CALL_ID_WORKER0,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL_ID_JOB:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[0],
|
||||
(void *)ticker_job
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB0,
|
||||
TICKER_MAYFLY_CALL_ID_JOB0,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (callee_id) {
|
||||
case CALL_ID_JOB:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[0],
|
||||
(void *)ticker_job
|
||||
};
|
||||
|
||||
/* TODO: scheduler lock, if OS used */
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_PROGRAM,
|
||||
TICKER_MAYFLY_CALL_ID_JOB0,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ticker_instance0_job_sched(uint8_t chain)
|
||||
static void ticker_instance1_sched(uint8_t caller_id, uint8_t callee_id,
|
||||
uint8_t chain)
|
||||
{
|
||||
static struct work instance0_job_irq = {
|
||||
0, 0, 0, WORK_TICKER_JOB0_IRQ, (work_fp) ticker_job,
|
||||
&_instance[0]
|
||||
};
|
||||
|
||||
/* return value not checked as we allow multiple calls to schedule
|
||||
* before being actually needing the work to complete before new
|
||||
* schedule.
|
||||
*/
|
||||
work_schedule(&instance0_job_irq, chain);
|
||||
switch (caller_id) {
|
||||
case CALL_ID_TRIGGER:
|
||||
switch (callee_id) {
|
||||
case CALL_ID_WORKER:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
&_instance[1],
|
||||
(void *)ticker_worker
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER,
|
||||
TICKER_MAYFLY_CALL_ID_WORKER1,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL_ID_JOB:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[1],
|
||||
(void *)ticker_job
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER,
|
||||
TICKER_MAYFLY_CALL_ID_JOB1,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL_ID_WORKER:
|
||||
switch (callee_id) {
|
||||
case CALL_ID_JOB:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[1],
|
||||
(void *)ticker_job
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_WORKER1,
|
||||
TICKER_MAYFLY_CALL_ID_JOB1,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL_ID_JOB:
|
||||
switch (callee_id) {
|
||||
case CALL_ID_WORKER:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[1],
|
||||
(void *)ticker_worker
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB1,
|
||||
TICKER_MAYFLY_CALL_ID_WORKER1,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL_ID_JOB:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[1],
|
||||
(void *)ticker_job
|
||||
};
|
||||
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB1,
|
||||
TICKER_MAYFLY_CALL_ID_JOB1,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (callee_id) {
|
||||
case CALL_ID_JOB:
|
||||
{
|
||||
static void *link[2];
|
||||
static struct mayfly m = {
|
||||
0, 0, link,
|
||||
(void *)&_instance[1],
|
||||
(void *)ticker_job
|
||||
};
|
||||
|
||||
/* TODO: scheduler lock, if OS used */
|
||||
mayfly_enqueue(TICKER_MAYFLY_CALL_ID_PROGRAM,
|
||||
TICKER_MAYFLY_CALL_ID_JOB1,
|
||||
chain,
|
||||
&m);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ticker_instance0_rtc_compare_set(uint32_t value)
|
||||
static void ticker_instance0_cmp_set(uint32_t value)
|
||||
{
|
||||
rtc_compare_set(0, value);
|
||||
cntr_cmp_set(0, value);
|
||||
}
|
||||
|
||||
static void ticker_instance1_worker_sched(uint8_t chain)
|
||||
static void ticker_instance1_cmp_set(uint32_t value)
|
||||
{
|
||||
static struct work instance1_worker_irq = {
|
||||
0, 0, 0, WORK_TICKER_WORKER1_IRQ, (work_fp) ticker_worker,
|
||||
&_instance[1]
|
||||
};
|
||||
|
||||
/* return value not checked as we allow multiple calls to schedule
|
||||
* before being actually needing the work to complete before new
|
||||
* schedule.
|
||||
*/
|
||||
work_schedule(&instance1_worker_irq, chain);
|
||||
}
|
||||
|
||||
static void ticker_instance1_job_sched(uint8_t chain)
|
||||
{
|
||||
static struct work instance1_job_irq = {
|
||||
0, 0, 0, WORK_TICKER_JOB1_IRQ, (work_fp) ticker_job,
|
||||
&_instance[1]
|
||||
};
|
||||
|
||||
/* return value not checked as we allow multiple calls to schedule
|
||||
* before being actually needing the work to complete before new
|
||||
* schedule.
|
||||
*/
|
||||
work_schedule(&instance1_job_irq, chain);
|
||||
}
|
||||
|
||||
static void ticker_instance1_rtc_compare_set(uint32_t value)
|
||||
{
|
||||
rtc_compare_set(1, value);
|
||||
cntr_cmp_set(1, value);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -1268,21 +1534,15 @@ uint32_t ticker_init(uint8_t instance_index, uint8_t count_node, void *node,
|
|||
|
||||
switch (instance_index) {
|
||||
case 0:
|
||||
instance->fp_worker_sched =
|
||||
ticker_instance0_worker_sched;
|
||||
instance->fp_job_sched =
|
||||
ticker_instance0_job_sched;
|
||||
instance->fp_compare_set =
|
||||
ticker_instance0_rtc_compare_set;
|
||||
instance->fp_caller_id_get = ticker_instance0_caller_id_get;
|
||||
instance->fp_sched = ticker_instance0_sched;
|
||||
instance->fp_cmp_set = ticker_instance0_cmp_set;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
instance->fp_worker_sched =
|
||||
ticker_instance1_worker_sched;
|
||||
instance->fp_job_sched =
|
||||
ticker_instance1_job_sched;
|
||||
instance->fp_compare_set =
|
||||
ticker_instance1_rtc_compare_set;
|
||||
instance->fp_caller_id_get = ticker_instance1_caller_id_get;
|
||||
instance->fp_sched = ticker_instance1_sched;
|
||||
instance->fp_cmp_set = ticker_instance1_cmp_set;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1320,9 +1580,14 @@ uint32_t ticker_init(uint8_t instance_index, uint8_t count_node, void *node,
|
|||
|
||||
void ticker_trigger(uint8_t instance_index)
|
||||
{
|
||||
if (_instance[instance_index].fp_worker_sched) {
|
||||
_instance[instance_index].fp_worker_sched(1);
|
||||
DEBUG_TICKER_ISR(1);
|
||||
|
||||
if (_instance[instance_index].fp_sched) {
|
||||
_instance[instance_index].fp_sched(CALL_ID_TRIGGER,
|
||||
CALL_ID_WORKER, 1);
|
||||
}
|
||||
|
||||
DEBUG_TICKER_ISR(0);
|
||||
}
|
||||
|
||||
uint32_t ticker_start(uint8_t instance_index, uint8_t user_id,
|
||||
|
@ -1341,7 +1606,7 @@ uint32_t ticker_start(uint8_t instance_index, uint8_t user_id,
|
|||
user = &instance->user[user_id];
|
||||
|
||||
last = user->last + 1;
|
||||
if (last == user->count_user_op) {
|
||||
if (last >= user->count_user_op) {
|
||||
last = 0;
|
||||
}
|
||||
|
||||
|
@ -1366,7 +1631,7 @@ uint32_t ticker_start(uint8_t instance_index, uint8_t user_id,
|
|||
|
||||
user->last = last;
|
||||
|
||||
instance->fp_job_sched(0);
|
||||
instance->fp_sched(instance->fp_caller_id_get(user_id), CALL_ID_JOB, 0);
|
||||
|
||||
return user_op->status;
|
||||
}
|
||||
|
@ -1385,7 +1650,7 @@ uint32_t ticker_update(uint8_t instance_index, uint8_t user_id,
|
|||
user = &instance->user[user_id];
|
||||
|
||||
last = user->last + 1;
|
||||
if (last == user->count_user_op) {
|
||||
if (last >= user->count_user_op) {
|
||||
last = 0;
|
||||
}
|
||||
|
||||
|
@ -1408,7 +1673,7 @@ uint32_t ticker_update(uint8_t instance_index, uint8_t user_id,
|
|||
|
||||
user->last = last;
|
||||
|
||||
instance->fp_job_sched(0);
|
||||
instance->fp_sched(instance->fp_caller_id_get(user_id), CALL_ID_JOB, 0);
|
||||
|
||||
return user_op->status;
|
||||
}
|
||||
|
@ -1425,7 +1690,7 @@ uint32_t ticker_stop(uint8_t instance_index, uint8_t user_id,
|
|||
user = &instance->user[user_id];
|
||||
|
||||
last = user->last + 1;
|
||||
if (last == user->count_user_op) {
|
||||
if (last >= user->count_user_op) {
|
||||
last = 0;
|
||||
}
|
||||
|
||||
|
@ -1442,7 +1707,7 @@ uint32_t ticker_stop(uint8_t instance_index, uint8_t user_id,
|
|||
|
||||
user->last = last;
|
||||
|
||||
instance->fp_job_sched(0);
|
||||
instance->fp_sched(instance->fp_caller_id_get(user_id), CALL_ID_JOB, 0);
|
||||
|
||||
return user_op->status;
|
||||
}
|
||||
|
@ -1461,7 +1726,7 @@ uint32_t ticker_next_slot_get(uint8_t instance_index, uint8_t user_id,
|
|||
user = &instance->user[user_id];
|
||||
|
||||
last = user->last + 1;
|
||||
if (last == user->count_user_op) {
|
||||
if (last >= user->count_user_op) {
|
||||
last = 0;
|
||||
}
|
||||
|
||||
|
@ -1481,7 +1746,7 @@ uint32_t ticker_next_slot_get(uint8_t instance_index, uint8_t user_id,
|
|||
|
||||
user->last = last;
|
||||
|
||||
instance->fp_job_sched(0);
|
||||
instance->fp_sched(instance->fp_caller_id_get(user_id), CALL_ID_JOB, 0);
|
||||
|
||||
return user_op->status;
|
||||
}
|
||||
|
@ -1497,7 +1762,7 @@ uint32_t ticker_job_idle_get(uint8_t instance_index, uint8_t user_id,
|
|||
user = &instance->user[user_id];
|
||||
|
||||
last = user->last + 1;
|
||||
if (last == user->count_user_op) {
|
||||
if (last >= user->count_user_op) {
|
||||
last = 0;
|
||||
}
|
||||
|
||||
|
@ -1514,21 +1779,21 @@ uint32_t ticker_job_idle_get(uint8_t instance_index, uint8_t user_id,
|
|||
|
||||
user->last = last;
|
||||
|
||||
instance->fp_job_sched(0);
|
||||
instance->fp_sched(instance->fp_caller_id_get(user_id), CALL_ID_JOB, 0);
|
||||
|
||||
return user_op->status;
|
||||
}
|
||||
|
||||
void ticker_job_sched(uint8_t instance_index)
|
||||
void ticker_job_sched(uint8_t instance_index, uint8_t user_id)
|
||||
{
|
||||
struct ticker_instance *instance = &_instance[instance_index];
|
||||
|
||||
instance->fp_job_sched(0);
|
||||
instance->fp_sched(instance->fp_caller_id_get(user_id), CALL_ID_JOB, 0);
|
||||
}
|
||||
|
||||
uint32_t ticker_ticks_now_get(void)
|
||||
{
|
||||
return rtc_tick_get();
|
||||
return cntr_cnt_get();
|
||||
}
|
||||
|
||||
uint32_t ticker_ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old)
|
|
@ -131,7 +131,7 @@ uint32_t ticker_next_slot_get(uint8_t instance_index, uint8_t user_id,
|
|||
ticker_op_func fp_op_func, void *op_context);
|
||||
uint32_t ticker_job_idle_get(uint8_t instance_index, uint8_t user_id,
|
||||
ticker_op_func fp_op_func, void *op_context);
|
||||
void ticker_job_sched(uint8_t instance_index);
|
||||
void ticker_job_sched(uint8_t instance_index, uint8_t user_id);
|
||||
uint32_t ticker_ticks_now_get(void);
|
||||
uint32_t ticker_ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old);
|
||||
|
40
subsys/bluetooth/controller/util/config.h
Normal file
40
subsys/bluetooth/controller/util/config.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#define MAYFLY_CALL_ID_0 0
|
||||
#define MAYFLY_CALL_ID_1 1
|
||||
#define MAYFLY_CALL_ID_2 2
|
||||
#define MAYFLY_CALL_ID_PROGRAM 3
|
||||
#define MAYFLY_CALLER_COUNT 4
|
||||
#define MAYFLY_CALLEE_COUNT 4
|
||||
|
||||
#define TICKER_MAYFLY_CALL_ID_TRIGGER MAYFLY_CALL_ID_0
|
||||
#define TICKER_MAYFLY_CALL_ID_WORKER0 MAYFLY_CALL_ID_0
|
||||
#define TICKER_MAYFLY_CALL_ID_WORKER1 MAYFLY_CALL_ID_2
|
||||
#define TICKER_MAYFLY_CALL_ID_JOB0 MAYFLY_CALL_ID_1
|
||||
#define TICKER_MAYFLY_CALL_ID_JOB1 MAYFLY_CALL_ID_2
|
||||
#define TICKER_MAYFLY_CALL_ID_PROGRAM MAYFLY_CALL_ID_PROGRAM
|
||||
|
||||
#define TICKER_MAYFLY_CALL_ID_WORKER0_PRIO 0
|
||||
#define TICKER_MAYFLY_CALL_ID_WORKER1_PRIO 1
|
||||
#define TICKER_MAYFLY_CALL_ID_JOB0_PRIO 0
|
||||
#define TICKER_MAYFLY_CALL_ID_JOB1_PRIO 1
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _DEFINES_H_
|
||||
#define _DEFINES_H_
|
||||
|
||||
#include <toolchain.h>
|
||||
|
||||
#if !defined(ALIGNED)
|
||||
#define ALIGNED(x) __aligned(x)
|
||||
#endif
|
||||
|
||||
#define ALIGN4(x) (((uint32_t)(x)+3) & (~((uint32_t)3)))
|
||||
|
||||
#define DOUBLE_BUFFER_SIZE 2
|
||||
#define TRIPLE_BUFFER_SIZE 3
|
||||
|
||||
#define BDADDR_SIZE 6
|
||||
|
||||
#endif /* _DEFINES_H_ */
|
163
subsys/bluetooth/controller/util/mayfly.c
Normal file
163
subsys/bluetooth/controller/util/mayfly.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "memq.h"
|
||||
#include "mayfly.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
static struct {
|
||||
void *head;
|
||||
void *tail;
|
||||
} mft[MAYFLY_CALLEE_COUNT][MAYFLY_CALLER_COUNT];
|
||||
|
||||
static void *mfl[MAYFLY_CALLEE_COUNT][MAYFLY_CALLER_COUNT][2];
|
||||
|
||||
void mayfly_init(void)
|
||||
{
|
||||
uint8_t callee_id;
|
||||
|
||||
callee_id = MAYFLY_CALLEE_COUNT;
|
||||
while (callee_id--) {
|
||||
uint8_t caller_id;
|
||||
|
||||
caller_id = MAYFLY_CALLER_COUNT;
|
||||
while (caller_id--) {
|
||||
memq_init(mfl[callee_id][caller_id],
|
||||
&mft[callee_id][caller_id].head,
|
||||
&mft[callee_id][caller_id].tail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mayfly_enqueue(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
|
||||
struct mayfly *m)
|
||||
{
|
||||
uint8_t state;
|
||||
uint8_t ack;
|
||||
|
||||
chain = chain || !mayfly_prio_is_equal(caller_id, callee_id) ||
|
||||
!mayfly_is_enabled(caller_id, callee_id);
|
||||
|
||||
/* shadow the ack */
|
||||
ack = m->_ack;
|
||||
|
||||
/* already in queue */
|
||||
state = (m->_req - ack) & 0x03;
|
||||
if (state != 0) {
|
||||
if (chain) {
|
||||
if (state != 1) {
|
||||
/* mark as ready in queue */
|
||||
m->_req = ack + 1;
|
||||
|
||||
/* pend the callee for execution */
|
||||
mayfly_pend(caller_id, callee_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* already ready */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* mark as done in queue, and fall thru */
|
||||
m->_req = ack + 2;
|
||||
}
|
||||
|
||||
/* handle mayfly(s) that can be inline */
|
||||
if (!chain) {
|
||||
/* call fp */
|
||||
m->fp(m->param);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* new, add as ready in the queue */
|
||||
m->_req = ack + 1;
|
||||
memq_enqueue(m, m->_link, &mft[callee_id][caller_id].tail);
|
||||
|
||||
/* pend the callee for execution */
|
||||
mayfly_pend(caller_id, callee_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mayfly_run(uint8_t callee_id)
|
||||
{
|
||||
uint8_t caller_id;
|
||||
|
||||
/* iterate through each caller queue to this callee_id */
|
||||
caller_id = MAYFLY_CALLER_COUNT;
|
||||
while (caller_id--) {
|
||||
void *link;
|
||||
struct mayfly *m = 0;
|
||||
|
||||
/* fetch mayfly in callee queue, if any */
|
||||
link = memq_peek(mft[callee_id][caller_id].tail,
|
||||
mft[callee_id][caller_id].head,
|
||||
(void **)&m);
|
||||
while (link) {
|
||||
uint8_t state;
|
||||
uint8_t req;
|
||||
|
||||
/* execute work if ready */
|
||||
req = m->_req;
|
||||
state = (req - m->_ack) & 0x03;
|
||||
if (state == 1) {
|
||||
/* mark mayfly as ran */
|
||||
m->_ack--;
|
||||
|
||||
/* call the mayfly function */
|
||||
m->fp(m->param);
|
||||
}
|
||||
|
||||
/* dequeue if not re-pended */
|
||||
req = m->_req;
|
||||
if (((req - m->_ack) & 0x03) != 1) {
|
||||
memq_dequeue(mft[callee_id][caller_id].tail,
|
||||
&mft[callee_id][caller_id].head,
|
||||
0);
|
||||
|
||||
/* release link into dequeued mayfly struct */
|
||||
m->_link = link;
|
||||
|
||||
/* reset mayfly state to idle */
|
||||
m->_ack = req;
|
||||
}
|
||||
|
||||
/* fetch next mayfly in callee queue, if any */
|
||||
link = memq_peek(mft[callee_id][caller_id].tail,
|
||||
mft[callee_id][caller_id].head,
|
||||
(void **)&m);
|
||||
|
||||
/* yield out of mayfly_run if a mayfly function was
|
||||
* called.
|
||||
*/
|
||||
if (state == 1) {
|
||||
/* pend callee (tailchain) if mayfly queue is
|
||||
* not empty.
|
||||
*/
|
||||
if (link) {
|
||||
mayfly_pend(callee_id, callee_id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,24 +15,25 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _WORK_H_
|
||||
#define _WORK_H_
|
||||
#ifndef _MAYFLY_H_
|
||||
#define _MAYFLY_H_
|
||||
|
||||
typedef void (*work_fp) (void *params);
|
||||
|
||||
struct work {
|
||||
void *next;
|
||||
uint8_t req;
|
||||
uint8_t ack;
|
||||
uint8_t group;
|
||||
work_fp fp;
|
||||
void *params;
|
||||
struct mayfly {
|
||||
uint8_t volatile _req;
|
||||
uint8_t _ack;
|
||||
void *_link;
|
||||
void *param;
|
||||
void (*fp)(void *);
|
||||
};
|
||||
|
||||
void work_enable(uint8_t group);
|
||||
void work_disable(uint8_t group);
|
||||
uint32_t work_is_enabled(uint8_t group);
|
||||
uint32_t work_schedule(struct work *w, uint8_t chain);
|
||||
void work_run(uint8_t group);
|
||||
void mayfly_init(void);
|
||||
uint32_t mayfly_enqueue(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
|
||||
struct mayfly *m);
|
||||
void mayfly_run(uint8_t callee_id);
|
||||
|
||||
#endif /* _WORK_H_ */
|
||||
extern void mayfly_enable(uint8_t caller_id, uint8_t callee_id, uint8_t enable);
|
||||
extern uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id);
|
||||
extern uint32_t mayfly_prio_is_equal(uint8_t caller_id, uint8_t callee_id);
|
||||
extern void mayfly_pend(uint8_t caller_id, uint8_t callee_id);
|
||||
|
||||
#endif /* _MAYFLY_H_ */
|
|
@ -18,7 +18,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
|
@ -27,15 +27,17 @@ void mem_init(void *mem_pool, uint16_t mem_size, uint16_t mem_count,
|
|||
{
|
||||
*mem_head = mem_pool;
|
||||
|
||||
/* Store free mem_count after the list's next pointer */
|
||||
memcpy(((uint8_t *)mem_pool + sizeof(mem_pool)),
|
||||
(uint8_t *)&mem_count, sizeof(mem_count));
|
||||
/* Store free mem_count after the list's next pointer at an aligned
|
||||
* memory location to ensure atomic read/write (in ARM for now).
|
||||
*/
|
||||
*((uint16_t *)MROUND((uint8_t *)mem_pool + sizeof(mem_pool))) =
|
||||
mem_count;
|
||||
|
||||
/* Initialize next pointers to form a free list,
|
||||
* next pointer is stored in the first 32-bit of each block
|
||||
*/
|
||||
memset(((uint8_t *)mem_pool + (mem_size * (--mem_count))), 0,
|
||||
sizeof(mem_pool));
|
||||
sizeof(mem_pool));
|
||||
while (mem_count--) {
|
||||
uint32_t next;
|
||||
|
||||
|
@ -50,23 +52,24 @@ void *mem_acquire(void **mem_head)
|
|||
{
|
||||
if (*mem_head) {
|
||||
uint16_t free_count;
|
||||
void *head;
|
||||
void *mem;
|
||||
|
||||
/* Get the free count from the list and decrement it */
|
||||
memcpy((void *)&free_count,
|
||||
((uint8_t *)*mem_head + sizeof(mem_head)),
|
||||
sizeof(free_count));
|
||||
free_count = *((uint16_t *)MROUND((uint8_t *)*mem_head +
|
||||
sizeof(mem_head)));
|
||||
free_count--;
|
||||
|
||||
mem = *mem_head;
|
||||
memcpy(mem_head, mem, sizeof(*mem_head));
|
||||
memcpy(&head, mem, sizeof(head));
|
||||
|
||||
/* Store free mem_count after the list's next pointer */
|
||||
if (*mem_head) {
|
||||
memcpy(((uint8_t *)*mem_head + sizeof(mem_head)),
|
||||
(uint8_t *)&free_count, sizeof(free_count));
|
||||
if (head) {
|
||||
*((uint16_t *)MROUND((uint8_t *)head + sizeof(head))) =
|
||||
free_count;
|
||||
}
|
||||
|
||||
*mem_head = head;
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
@ -79,17 +82,17 @@ void mem_release(void *mem, void **mem_head)
|
|||
|
||||
/* Get the free count from the list and increment it */
|
||||
if (*mem_head) {
|
||||
memcpy(&free_count, ((uint8_t *)*mem_head + sizeof(mem_head)),
|
||||
sizeof(free_count));
|
||||
free_count = *((uint16_t *)MROUND((uint8_t *)*mem_head +
|
||||
sizeof(mem_head)));
|
||||
}
|
||||
free_count++;
|
||||
|
||||
memcpy(mem, mem_head, sizeof(mem));
|
||||
*mem_head = mem;
|
||||
|
||||
/* Store free mem_count after the list's next pointer */
|
||||
memcpy(((uint8_t *)*mem_head + sizeof(mem_head)),
|
||||
(uint8_t *)&free_count, sizeof(free_count));
|
||||
*((uint16_t *)MROUND((uint8_t *)mem + sizeof(mem))) = free_count;
|
||||
|
||||
*mem_head = mem;
|
||||
}
|
||||
|
||||
uint16_t mem_free_count_get(void *mem_head)
|
||||
|
@ -98,8 +101,8 @@ uint16_t mem_free_count_get(void *mem_head)
|
|||
|
||||
/* Get the free count from the list */
|
||||
if (mem_head) {
|
||||
memcpy(&free_count, ((uint8_t *)mem_head + sizeof(mem_head)),
|
||||
sizeof(free_count));
|
||||
free_count = *((uint16_t *)MROUND((uint8_t *)mem_head +
|
||||
sizeof(mem_head)));
|
||||
}
|
||||
|
||||
return free_count;
|
||||
|
@ -137,9 +140,9 @@ uint8_t mem_is_zero(uint8_t *src, uint16_t len)
|
|||
|
||||
uint32_t mem_ut(void)
|
||||
{
|
||||
#define BLOCK_SIZE ALIGN4(10)
|
||||
#define BLOCK_SIZE MROUND(10)
|
||||
#define BLOCK_COUNT 10
|
||||
uint8_t ALIGNED(4) pool[BLOCK_COUNT][BLOCK_SIZE];
|
||||
uint8_t MALIGN(4) pool[BLOCK_COUNT][BLOCK_SIZE];
|
||||
void *mem_free;
|
||||
void *mem_used;
|
||||
uint16_t mem_free_count;
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
#ifndef _MEM_H_
|
||||
#define _MEM_H_
|
||||
|
||||
#ifndef MALIGN
|
||||
#define MALIGN(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
|
||||
#ifndef MROUND
|
||||
#define MROUND(x) (((uint32_t)(x)+3) & (~((uint32_t)3)))
|
||||
#endif
|
||||
|
||||
void mem_init(void *mem_pool, uint16_t mem_size, uint16_t mem_count,
|
||||
void **mem_head);
|
||||
void *mem_acquire(void **mem_head);
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
#ifndef DOUBLE_BUFFER_SIZE
|
||||
#define DOUBLE_BUFFER_SIZE 2
|
||||
#endif
|
||||
|
||||
#ifndef TRIPLE_BUFFER_SIZE
|
||||
#define TRIPLE_BUFFER_SIZE 3
|
||||
#endif
|
||||
|
||||
uint8_t util_ones_count_get(uint8_t *octets, uint8_t octets_len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <irq.h>
|
||||
|
||||
#include "work.h"
|
||||
|
||||
static struct work *_work_head;
|
||||
|
||||
static int _irq_is_priority_equal(unsigned int irq)
|
||||
{
|
||||
unsigned int curr_ctx;
|
||||
int curr_prio;
|
||||
|
||||
curr_ctx = _ScbActiveVectorGet();
|
||||
if (curr_ctx > 15) {
|
||||
/* Interrupts */
|
||||
curr_prio = _NvicIrqPrioGet(curr_ctx - 16);
|
||||
} else if (curr_ctx > 3) {
|
||||
/* Execeptions */
|
||||
curr_prio = _ScbExcPrioGet(curr_ctx);
|
||||
} else if (curr_ctx > 0) {
|
||||
/* Fixed Priority Exceptions: -3, -2, -1 priority */
|
||||
curr_prio = curr_ctx - 4;
|
||||
} else {
|
||||
/* Thread mode */
|
||||
curr_prio = 256;
|
||||
}
|
||||
|
||||
return (_NvicIrqPrioGet(irq) == curr_prio);
|
||||
}
|
||||
|
||||
void work_enable(uint8_t group)
|
||||
{
|
||||
irq_enable(group);
|
||||
}
|
||||
|
||||
void work_disable(uint8_t group)
|
||||
{
|
||||
irq_disable(group);
|
||||
}
|
||||
|
||||
uint32_t work_is_enabled(uint8_t group)
|
||||
{
|
||||
return irq_is_enabled(group);
|
||||
}
|
||||
|
||||
uint32_t work_schedule(struct work *w, uint8_t chain)
|
||||
{
|
||||
uint32_t imask = irq_lock();
|
||||
struct work *prev;
|
||||
struct work *curr;
|
||||
|
||||
/* Dequeue expired work at head */
|
||||
while ((_work_head)
|
||||
&& (_work_head->ack == _work_head->req)
|
||||
) {
|
||||
_work_head = _work_head->next;
|
||||
}
|
||||
|
||||
/* Dequeue expired in between list and find last node */
|
||||
curr = _work_head;
|
||||
prev = curr;
|
||||
while (curr) {
|
||||
/* delete expired work */
|
||||
if (curr->ack == curr->req) {
|
||||
prev->next = curr->next;
|
||||
} else {
|
||||
prev = curr;
|
||||
}
|
||||
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
/* chain, if explicitly requested, or if work not at current level */
|
||||
chain = chain || (!_irq_is_priority_equal(w->group))
|
||||
|| (!irq_is_enabled(w->group));
|
||||
|
||||
/* Already in List */
|
||||
curr = _work_head;
|
||||
while (curr) {
|
||||
if (curr == w) {
|
||||
if (!chain) {
|
||||
break;
|
||||
}
|
||||
|
||||
irq_unlock(imask);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
/* handle work(s) that can be inline */
|
||||
if (!chain) {
|
||||
w->req = w->ack;
|
||||
|
||||
irq_unlock(imask);
|
||||
|
||||
if (w->fp) {
|
||||
w->fp(w->params);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* New, add to the list */
|
||||
w->req = w->ack + 1;
|
||||
w->next = 0;
|
||||
if (prev == curr) {
|
||||
_work_head = w;
|
||||
} else {
|
||||
prev->next = w;
|
||||
}
|
||||
|
||||
_NvicIrqPend(w->group);
|
||||
|
||||
irq_unlock(imask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void work_run(uint8_t group)
|
||||
{
|
||||
uint32_t imask = irq_lock();
|
||||
struct work *curr = _work_head;
|
||||
|
||||
while (curr) {
|
||||
if ((curr->group == group) && (curr->ack != curr->req)) {
|
||||
curr->ack = curr->req;
|
||||
|
||||
if (curr->fp) {
|
||||
if (curr->next) {
|
||||
_NvicIrqPend(group);
|
||||
}
|
||||
|
||||
irq_unlock(imask);
|
||||
|
||||
curr->fp(curr->params);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
irq_unlock(imask);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue