1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18
19 #include <zephyr.h>
20 #undef irq_enable
21 #undef irq_disable
22 #undef ARRAY_SIZE
23
24 #include "plic.h"
25 #include "compiler.h"
26 #include "b91_bt.h"
27 #include "b91_bt_init.h"
28 #include "stack/ble/controller/ble_controller.h"
29
30
31 /* Module defines */
32 #define BLE_THREAD_STACK_SIZE CONFIG_B91_BLE_CTRL_THREAD_STACK_SIZE
33 #define BLE_THREAD_PRIORITY CONFIG_B91_BLE_CTRL_THREAD_PRIORITY
34 #define BLE_THREAD_PERIOD_MS CONFIG_B91_BLE_CTRL_THREAD_PERIOD_MS
35
36 #define BYTES_TO_UINT16(n, p) {n = ((u16)(p)[0] + ((u16)(p)[1]<<8));}
37 #define BSTREAM_TO_UINT16(n, p) {BYTES_TO_UINT16(n, p); p += 2;}
38
39
40 static struct b91_ctrl_t
41 {
42 bool is_initialized;
43 b91_bt_host_callback_t callbacks;
44 } b91_ctrl;
45
46 /**
47 * @brief RF driver interrupt handler
48 */
rf_irq_handler(void)49 _attribute_ram_code_ void rf_irq_handler(void)
50 {
51 blc_sdk_irq_handler();
52 }
53
54 /**
55 * @brief System Timer interrupt handler
56 */
stimer_irq_handler(void)57 _attribute_ram_code_ void stimer_irq_handler(void)
58 {
59 blc_sdk_irq_handler();
60 }
61
62 /**
63 * @brief BLE Controller HCI Tx callback implementation
64 */
b91_bt_hci_tx_handler(void)65 static int b91_bt_hci_tx_handler(void)
66 {
67 /* check for data available */
68 if(bltHci_txfifo.wptr == bltHci_txfifo.rptr)
69 {
70 return 0;
71 }
72
73 /* Get HCI data */
74 u8 *p = bltHci_txfifo.p + (bltHci_txfifo.rptr & bltHci_txfifo.mask) * bltHci_txfifo.size;
75 if(p)
76 {
77 u32 len;
78 BSTREAM_TO_UINT16(len, p);
79 bltHci_txfifo.rptr++;
80
81 /* Send data to the host */
82 if(b91_ctrl.callbacks.host_read_packet)
83 {
84 b91_ctrl.callbacks.host_read_packet(p, len);
85 }
86 }
87
88 return 0;
89 }
90
91 /**
92 * @brief BLE Controller HCI Rx callback implementation
93 */
b91_bt_hci_rx_handler(void)94 static int b91_bt_hci_rx_handler(void)
95 {
96 /* Check for data available */
97 if(bltHci_rxfifo.wptr == bltHci_rxfifo.rptr)
98 {
99 /* No data to process, send host_send_available message to the host */
100 if(b91_ctrl.callbacks.host_send_available)
101 {
102 b91_ctrl.callbacks.host_send_available();
103 }
104
105 return 0;
106 }
107
108 /* Get HCI data */
109 u8 *p = bltHci_rxfifo.p + (bltHci_rxfifo.rptr & bltHci_rxfifo.mask) * bltHci_rxfifo.size;
110 if(p)
111 {
112 /* Send data to the controller */
113 blc_hci_handler(&p[0], 0);
114 bltHci_rxfifo.rptr++;
115 }
116
117 return 0;
118 }
119
120 /**
121 * @brief Telink B91 BLE Controller thread
122 */
b91_bt_controller_thread()123 static void b91_bt_controller_thread()
124 {
125 while(1)
126 {
127 if(b91_ctrl.is_initialized)
128 {
129 blc_sdk_main_loop();
130 }
131
132 k_msleep(BLE_THREAD_PERIOD_MS);
133 }
134 }
135
136 /**
137 * @brief BLE Controller IRQs initialization
138 */
b91_bt_irq_init()139 static void b91_bt_irq_init()
140 {
141 /* Init STimer IRQ */
142 IRQ_CONNECT(IRQ1_SYSTIMER, 0, stimer_irq_handler, 0, 0);
143
144 /* Init RF IRQ */
145 IRQ_CONNECT(IRQ15_ZB_RT, 0, rf_irq_handler, 0, 0);
146 }
147
148 /**
149 * @brief Telink B91 BLE Controller initialization
150 * @return Status - 0: command succeeded; -1: command failed
151 */
b91_bt_controller_init()152 int b91_bt_controller_init()
153 {
154 int status;
155
156 /* Init IRQs */
157 b91_bt_irq_init();
158
159 /* Init RF driver */
160 rf_drv_ble_init();
161
162 /* Init BLE Controller stack */
163 status = b91_bt_blc_init(b91_bt_hci_rx_handler, b91_bt_hci_tx_handler);
164 if(status != INIT_OK)
165 {
166 return status;
167 }
168
169 /* Init controller data */
170 b91_ctrl.is_initialized = TRUE;
171
172 return status;
173 }
174
175 /**
176 * @brief Host send HCI packet to controller
177 * @param data the packet point
178 * @param len the packet length
179 */
b91_bt_host_send_packet(uint8_t type,uint8_t * data,uint16_t len)180 void b91_bt_host_send_packet(uint8_t type, uint8_t *data, uint16_t len)
181 {
182 u8 *p = bltHci_rxfifo.p + (bltHci_rxfifo.wptr & bltHci_rxfifo.mask) * bltHci_rxfifo.size;
183 *p++ = type;
184 memcpy(p, data, len);
185 bltHci_rxfifo.wptr++;
186 }
187
188 /**
189 * @brief Register the vhci reference callback
190 */
b91_bt_host_callback_register(const b91_bt_host_callback_t * pcb)191 void b91_bt_host_callback_register(const b91_bt_host_callback_t *pcb)
192 {
193 b91_ctrl.callbacks.host_read_packet = pcb->host_read_packet;
194 b91_ctrl.callbacks.host_send_available = pcb->host_send_available;
195 }
196
197 K_THREAD_DEFINE(ZephyrBleController, BLE_THREAD_STACK_SIZE, b91_bt_controller_thread,
198 NULL, NULL, NULL, BLE_THREAD_PRIORITY, 0, 0);
199