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 "b91_bt.h"
25 #include "b91_bt_init.h"
26 #include "compiler.h"
27 #include "plic.h"
28 #include "stack/ble/controller/ble_controller.h"
29
30 /* Module defines */
31 #define BLE_THREAD_STACK_SIZE CONFIG_B91_BLE_CTRL_THREAD_STACK_SIZE
32 #define BLE_THREAD_PRIORITY CONFIG_B91_BLE_CTRL_THREAD_PRIORITY
33 #define BLE_THREAD_PERIOD_MS CONFIG_B91_BLE_CTRL_THREAD_PERIOD_MS
34
35 #define BYTES_TO_UINT16(n, p) \
36 { \
37 n = ((u16)(p)[0] + ((u16)(p)[1] << 8)); \
38 }
39 #define BSTREAM_TO_UINT16(n, p) \
40 { \
41 BYTES_TO_UINT16(n, p); \
42 p += 2; \
43 }
44
45 static void b91_bt_controller_thread();
46
47 K_THREAD_DEFINE(ZephyrBleController, BLE_THREAD_STACK_SIZE, b91_bt_controller_thread, NULL, NULL,
48 NULL, BLE_THREAD_PRIORITY, 0, -1);
49
50 static struct b91_ctrl_t {
51 b91_bt_host_callback_t callbacks;
52 } b91_ctrl;
53
54 /**
55 * @brief RF driver interrupt handler
56 */
rf_irq_handler(void)57 _attribute_ram_code_ void rf_irq_handler(void) { blc_sdk_irq_handler(); }
58
59 /**
60 * @brief System Timer interrupt handler
61 */
stimer_irq_handler(void)62 _attribute_ram_code_ void stimer_irq_handler(void) { blc_sdk_irq_handler(); }
63
64 /**
65 * @brief BLE Controller HCI Tx callback implementation
66 */
b91_bt_hci_tx_handler(void)67 static int b91_bt_hci_tx_handler(void)
68 {
69 /* check for data available */
70 if (bltHci_txfifo.wptr == bltHci_txfifo.rptr) {
71 return 0;
72 }
73
74 /* Get HCI data */
75 u8 *p = bltHci_txfifo.p + (bltHci_txfifo.rptr & bltHci_txfifo.mask) * bltHci_txfifo.size;
76 if (p) {
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 b91_ctrl.callbacks.host_read_packet(p, len);
84 }
85 }
86
87 return 0;
88 }
89
90 /**
91 * @brief BLE Controller HCI Rx callback implementation
92 */
b91_bt_hci_rx_handler(void)93 static int b91_bt_hci_rx_handler(void)
94 {
95 /* Check for data available */
96 if (bltHci_rxfifo.wptr == bltHci_rxfifo.rptr) {
97 /* No data to process, send host_send_available message to the host */
98 if (b91_ctrl.callbacks.host_send_available) {
99 b91_ctrl.callbacks.host_send_available();
100 }
101
102 return 0;
103 }
104
105 /* Get HCI data */
106 u8 *p = bltHci_rxfifo.p + (bltHci_rxfifo.rptr & bltHci_rxfifo.mask) * bltHci_rxfifo.size;
107 if (p) {
108 /* Send data to the controller */
109 blc_hci_handler(&p[0], 0);
110 bltHci_rxfifo.rptr++;
111 }
112
113 return 0;
114 }
115
116 /**
117 * @brief Telink B91 BLE Controller thread
118 */
b91_bt_controller_thread()119 static void b91_bt_controller_thread()
120 {
121 while (1) {
122 blc_sdk_main_loop();
123 #ifndef CONFIG_PM
124 k_msleep(CONFIG_B91_BLE_CTRL_THREAD_PERIOD_MS);
125 #endif /* !CONFIG_PM */
126 }
127 }
128
129 /**
130 * @brief BLE Controller IRQs initialization
131 */
b91_bt_irq_init()132 static void b91_bt_irq_init()
133 {
134 /* Init STimer IRQ */
135 IRQ_CONNECT(IRQ1_SYSTIMER, 0, stimer_irq_handler, 0, 0);
136
137 /* Init RF IRQ */
138 IRQ_CONNECT(IRQ15_ZB_RT, 0, rf_irq_handler, 0, 0);
139 }
140
141 /**
142 * @brief Telink B91 BLE Controller initialization
143 * @return Status - 0: command succeeded; -1: command failed
144 */
b91_bt_controller_init()145 int b91_bt_controller_init()
146 {
147 int status;
148
149 /* Init IRQs */
150 b91_bt_irq_init();
151
152 /* Init RF driver */
153 rf_drv_ble_init();
154
155 /* Init BLE Controller stack */
156 status = b91_bt_blc_init(b91_bt_hci_rx_handler, b91_bt_hci_tx_handler);
157 if (status != INIT_OK) {
158 return status;
159 }
160
161 /* Start BLE thread */
162 k_thread_start(ZephyrBleController);
163
164 return status;
165 }
166
167 /**
168 * @brief Host send HCI packet to controller
169 * @param data the packet point
170 * @param len the packet length
171 */
b91_bt_host_send_packet(uint8_t type,uint8_t * data,uint16_t len)172 void b91_bt_host_send_packet(uint8_t type, uint8_t *data, uint16_t len)
173 {
174 u8 *p = bltHci_rxfifo.p + (bltHci_rxfifo.wptr & bltHci_rxfifo.mask) * bltHci_rxfifo.size;
175 *p++ = type;
176 memcpy(p, data, len);
177 bltHci_rxfifo.wptr++;
178 }
179
180 /**
181 * @brief Register the vhci reference callback
182 */
b91_bt_host_callback_register(const b91_bt_host_callback_t * pcb)183 void b91_bt_host_callback_register(const b91_bt_host_callback_t *pcb)
184 {
185 b91_ctrl.callbacks.host_read_packet = pcb->host_read_packet;
186 b91_ctrl.callbacks.host_send_available = pcb->host_send_available;
187 }
188