xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/controller/include/controller/ble_ll_sched.h (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef H_BLE_LL_SCHED_
21 #define H_BLE_LL_SCHED_
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 /* Time per BLE scheduler slot */
28 #define BLE_LL_SCHED_USECS_PER_SLOT         (1250)
29 #define BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT   (41)    /* 1 tick = 30.517 usecs */
30 
31 /*
32  * Worst case time needed for scheduled advertising item. This is the longest
33  * possible time to receive a scan request and send a scan response (with the
34  * appropriate IFS time between them). This number is calculated using the
35  * following formula: IFS + SCAN_REQ + IFS + SCAN_RSP = 150 + 176 + 150 + 376.
36  * Note: worst case time to tx adv, rx scan req and send scan rsp is 1228 usecs.
37  * This assumes maximum sized advertising PDU and scan response PDU.
38  *
39  * For connectable advertising events no scan request is allowed. In this case
40  * we just need to receive a connect request PDU: IFS + CONNECT_REQ = 150 + 352.
41  * Note: worst-case is 376 + 150 + 352 = 878 usecs
42  *
43  * NOTE: The advertising PDU transmit time is NOT included here since we know
44  * how long that will take (worst-case is 376 usecs).
45  */
46 #define BLE_LL_SCHED_ADV_MAX_USECS          (852)
47 #define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS   (502)
48 #define BLE_LL_SCHED_MAX_ADV_PDU_USECS      (376)
49 
50 /* We don't know how big aux packet will be. It depends on adv packet len which
51  * can be up to 256. For now we fix it to 128 bytes, but we can optimize it.
52  */
53 #define BLE_LL_SCHED_AUX_PTR_DFLT_BYTES_NUM  (128)
54 
55 /*
56  * This is the offset from the start of the scheduled item until the actual
57  * tx/rx should occur, in ticks.
58  */
59 extern uint8_t g_ble_ll_sched_offset_ticks;
60 
61 /*
62  * This is the number of slots needed to transmit and receive a maximum
63  * size PDU, including an IFS time before each. The actual time is
64  * 2120 usecs for tx/rx and 150 for IFS = 4540 usecs.
65  */
66 #define BLE_LL_SCHED_MAX_TXRX_SLOT  (4 * BLE_LL_SCHED_USECS_PER_SLOT)
67 
68 /* BLE scheduler errors */
69 #define BLE_LL_SCHED_ERR_OVERLAP    (1)
70 
71 /* Types of scheduler events */
72 #define BLE_LL_SCHED_TYPE_ADV       (1)
73 #define BLE_LL_SCHED_TYPE_SCAN      (2)
74 #define BLE_LL_SCHED_TYPE_CONN      (3)
75 #define BLE_LL_SCHED_TYPE_AUX_SCAN  (4)
76 #define BLE_LL_SCHED_TYPE_DTM       (5)
77 
78 /* Return values for schedule callback. */
79 #define BLE_LL_SCHED_STATE_RUNNING  (0)
80 #define BLE_LL_SCHED_STATE_DONE     (1)
81 
82 /* Callback function */
83 struct ble_ll_sched_item;
84 typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch);
85 typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch);
86 /*
87  * Strict connection scheduling (for the master) is different than how
88  * connections are normally scheduled. With strict connection scheduling we
89  * introduce the concept of a "period". A period is a collection of slots. Each
90  * slot is 1.25 msecs in length. The number of slots in a period is determined
91  * by the syscfg value BLE_LL_CONN_INIT_SLOTS. A collection of periods is called
92  * an epoch. The length of an epoch is determined by the number of connections
93  * (BLE_MAX_CONNECTIONS plus BLE_LL_ADD_STRICT_SCHED_PERIODS). Connections
94  * will be scheduled at period boundaries. Any scanning/initiating/advertising
95  * will be done in unused periods, if possible.
96  */
97 #if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
98 #define BLE_LL_SCHED_PERIODS    (MYNEWT_VAL(BLE_MAX_CONNECTIONS) + \
99                                  MYNEWT_VAL(BLE_LL_ADD_STRICT_SCHED_PERIODS))
100 
101 struct ble_ll_sched_obj
102 {
103     uint8_t sch_num_occ_periods;
104     uint32_t sch_occ_period_mask;
105     uint32_t sch_ticks_per_period;
106     uint32_t sch_ticks_per_epoch;
107     uint32_t sch_epoch_start;
108 };
109 
110 extern struct ble_ll_sched_obj g_ble_ll_sched_data;
111 
112 /*
113  * XXX: TODO:
114  * -> How do we know epoch start is up to date? Not wrapped?
115  * -> for now, only do this with no more than 32 connections.
116  * -> Do not let initiating occur if no empty sched slots
117  */
118 #endif
119 
120 /*
121  * Schedule item
122  *  sched_type: This is the type of the schedule item.
123  *  enqueued: Flag denoting if item is on the scheduler list. 0: no, 1:yes
124  *  remainder: # of usecs from offset till tx/rx should occur
125  *  txrx_offset: Number of ticks from start time until tx/rx should occur.
126  *
127  */
128 struct ble_ll_sched_item
129 {
130     uint8_t         sched_type;
131     uint8_t         enqueued;
132     uint8_t         remainder;
133     uint32_t        start_time;
134     uint32_t        end_time;
135     void            *cb_arg;
136     sched_cb_func   sched_cb;
137     TAILQ_ENTRY(ble_ll_sched_item) link;
138 };
139 
140 /* Initialize the scheduler */
141 int ble_ll_sched_init(void);
142 
143 /* Remove item(s) from schedule */
144 int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch);
145 
146 void ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb);
147 
148 /* Schedule a new master connection */
149 struct ble_ll_conn_sm;
150 int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
151                             struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len);
152 
153 /* Schedule a new slave connection */
154 int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm);
155 
156 struct ble_ll_adv_sm;
157 typedef void ble_ll_sched_adv_new_cb(struct ble_ll_adv_sm *advsm,
158                                      uint32_t sch_start, void *arg);
159 
160 /* Schedule a new advertising event */
161 int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch,
162                          ble_ll_sched_adv_new_cb cb, void *arg);
163 
164 /* Reschedule an advertising event */
165 int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
166                                 uint32_t max_delay_ticks);
167 
168 /* Reschedule and advertising pdu */
169 int ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch);
170 
171 /* Reschedule a connection that had previously been scheduled or that is over */
172 int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm);
173 
174 /**
175  * Called to determine when the next scheduled event will occur.
176  *
177  * If there are not scheduled events this function returns 0; otherwise it
178  * returns 1 and *next_event_time is set to the start time of the next event.
179  *
180  * @param next_event_time cputime at which next scheduled event will occur
181  *
182  * @return int 0: No events are scheduled 1: there is an upcoming event
183  */
184 int ble_ll_sched_next_time(uint32_t *next_event_time);
185 
186 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
187 struct ble_ll_scan_sm;
188 struct ble_ll_aux_data;
189 int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
190                           struct ble_ll_scan_sm *scansm,
191                           struct ble_ll_aux_data *aux_scan);
192 
193 int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode);
194 #endif
195 
196 /* Stop the scheduler */
197 void ble_ll_sched_stop(void);
198 
199 #ifdef BLE_XCVR_RFCLK
200 /* Check if RF clock needs to be restarted */
201 void ble_ll_sched_rfclk_chk_restart(void);
202 #endif
203 
204 #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
205 int ble_ll_sched_dtm(struct ble_ll_sched_item *sch);
206 #endif
207 
208 #ifdef __cplusplus
209 }
210 #endif
211 
212 #endif /* H_LL_SCHED_ */
213