1 #define BTSTACK_FILE__ "port.c"
2
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <signal.h>
6
7 // include STM32 first to avoid warning about redefinition of UNUSED
8 #include "stm32f4xx_hal.h"
9 #include "main.h"
10
11 #include "port.h"
12 #include "btstack.h"
13 #include "btstack_debug.h"
14 #include "btstack_audio.h"
15 #include "btstack_chipset_cc256x.h"
16 #include "btstack_run_loop_embedded.h"
17 #include "btstack_tlv.h"
18 #include "btstack_tlv_flash_bank.h"
19 #include "hci_transport.h"
20 #include "hci_transport_h4.h"
21 #include "ble/le_device_db_tlv.h"
22 #include "classic/btstack_link_key_db_static.h"
23 #include "classic/btstack_link_key_db_tlv.h"
24 #include "hal_flash_bank_stm32.h"
25
26 #ifdef ENABLE_SEGGER_RTT
27 #include "SEGGER_RTT.h"
28 #include "hci_dump_segger_rtt_stdout.h"
29 #else
30 #include "hci_dump_embedded_stdout.h"
31 #endif
32
33 //
34 extern UART_HandleTypeDef huart2;
35 extern UART_HandleTypeDef huart3;
36
37 //
38 static btstack_packet_callback_registration_t hci_event_callback_registration;
39
40 static const hci_transport_config_uart_t config = {
41 HCI_TRANSPORT_CONFIG_UART,
42 115200,
43 4000000,
44 1,
45 NULL,
46 BTSTACK_UART_PARITY_OFF
47 };
48
49 // hal_time_ms.h
50 #include "hal_time_ms.h"
hal_time_ms(void)51 uint32_t hal_time_ms(void){
52 return HAL_GetTick();
53 }
54
55 // hal_cpu.h implementation
56 #include "hal_cpu.h"
57
hal_cpu_disable_irqs(void)58 void hal_cpu_disable_irqs(void){
59 __disable_irq();
60 }
61
hal_cpu_enable_irqs(void)62 void hal_cpu_enable_irqs(void){
63 __enable_irq();
64 }
65
hal_cpu_enable_irqs_and_sleep(void)66 void hal_cpu_enable_irqs_and_sleep(void){
67 __enable_irq();
68 __asm__("wfe"); // go to sleep if event flag isn't set. if set, just clear it. IRQs set event flag
69 }
70
71 // hal_stdin.h
72 #include "hal_stdin.h"
73 static uint8_t stdin_buffer[1];
74 static void (*stdin_handler)(char c);
hal_stdin_setup(void (* handler)(char c))75 void hal_stdin_setup(void (*handler)(char c)){
76 stdin_handler = handler;
77 // start receiving
78 HAL_UART_Receive_IT(&huart2, &stdin_buffer[0], 1);
79 }
80
stdin_rx_complete(void)81 static void stdin_rx_complete(void){
82 if (stdin_handler){
83 (*stdin_handler)(stdin_buffer[0]);
84 }
85 HAL_UART_Receive_IT(&huart2, &stdin_buffer[0], 1);
86 }
87
88 // hal_uart_dma.h
89
90 // hal_uart_dma.c implementation
91 #include "hal_uart_dma.h"
92
93 static void dummy_handler(void);
94
95 // handlers
96 static void (*rx_done_handler)(void) = &dummy_handler;
97 static void (*tx_done_handler)(void) = &dummy_handler;
98 static void (*cts_irq_handler)(void) = &dummy_handler;
99
100 static int hal_uart_needed_during_sleep;
101
dummy_handler(void)102 static void dummy_handler(void){}
103
hal_uart_dma_set_sleep(uint8_t sleep)104 void hal_uart_dma_set_sleep(uint8_t sleep){
105
106 // RTS is on PD12 - manually set it during sleep
107 GPIO_InitTypeDef RTS_InitStruct;
108 RTS_InitStruct.Pin = GPIO_PIN_12;
109 RTS_InitStruct.Pull = GPIO_NOPULL;
110 RTS_InitStruct.Alternate = GPIO_AF7_USART3;
111 if (sleep){
112 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
113 RTS_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
114 RTS_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
115 } else {
116 RTS_InitStruct.Mode = GPIO_MODE_AF_PP;
117 RTS_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
118 }
119
120 HAL_GPIO_Init(GPIOD, &RTS_InitStruct);
121
122 // if (sleep){
123 // HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
124 // }
125 hal_uart_needed_during_sleep = !sleep;
126 }
127
128 // reset Bluetooth using n_shutdown
bluetooth_power_cycle(void)129 static void bluetooth_power_cycle(void){
130 printf("Bluetooth power cycle\n");
131 HAL_GPIO_WritePin( CC_nSHUTD_GPIO_Port, CC_nSHUTD_Pin, GPIO_PIN_RESET );
132 HAL_Delay( 250 );
133 HAL_GPIO_WritePin( CC_nSHUTD_GPIO_Port, CC_nSHUTD_Pin, GPIO_PIN_SET );
134 HAL_Delay( 500 );
135 }
136
HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart)137 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
138 if (huart == &huart3){
139 (*tx_done_handler)();
140 }
141 }
142
HAL_UART_RxCpltCallback(UART_HandleTypeDef * huart)143 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
144 if (huart == &huart3){
145 (*rx_done_handler)();
146 }
147 if (huart == &huart2){
148 stdin_rx_complete();
149 }
150 }
151
hal_uart_dma_init(void)152 void hal_uart_dma_init(void){
153 bluetooth_power_cycle();
154 }
hal_uart_dma_set_block_received(void (* the_block_handler)(void))155 void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
156 rx_done_handler = the_block_handler;
157 }
158
hal_uart_dma_set_block_sent(void (* the_block_handler)(void))159 void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
160 tx_done_handler = the_block_handler;
161 }
162
EXTI15_10_IRQHandler(void)163 void EXTI15_10_IRQHandler(void){
164 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_11);
165 if (cts_irq_handler){
166 (*cts_irq_handler)();
167 }
168 }
169
hal_uart_dma_set_csr_irq_handler(void (* the_irq_handler)(void))170 void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
171
172 GPIO_InitTypeDef CTS_InitStruct = {
173 .Pin = GPIO_PIN_11,
174 .Mode = GPIO_MODE_AF_PP,
175 .Pull = GPIO_PULLUP,
176 .Speed = GPIO_SPEED_FREQ_VERY_HIGH,
177 .Alternate = GPIO_AF7_USART3,
178 };
179
180 if( the_irq_handler ) {
181 /* Configure the EXTI11 interrupt (USART3_CTS is on PD11) */
182 HAL_NVIC_EnableIRQ( EXTI15_10_IRQn );
183 CTS_InitStruct.Mode = GPIO_MODE_IT_RISING;
184 CTS_InitStruct.Pull = GPIO_NOPULL;
185 HAL_GPIO_Init( GPIOD, &CTS_InitStruct );
186 log_info("enabled CTS irq");
187 }
188 else {
189 CTS_InitStruct.Mode = GPIO_MODE_AF_PP;
190 CTS_InitStruct.Pull = GPIO_PULLUP;
191 HAL_GPIO_Init( GPIOD, &CTS_InitStruct );
192 HAL_NVIC_DisableIRQ( EXTI15_10_IRQn );
193 log_info("disabled CTS irq");
194 }
195 cts_irq_handler = the_irq_handler;
196 }
197
hal_uart_dma_set_baud(uint32_t baud)198 int hal_uart_dma_set_baud(uint32_t baud){
199 huart3.Init.BaudRate = baud;
200 HAL_UART_Init(&huart3);
201 return 0;
202 }
203
hal_uart_dma_send_block(const uint8_t * data,uint16_t size)204 void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){
205 HAL_UART_Transmit_DMA( &huart3, (uint8_t *) data, size);
206 }
207
hal_uart_dma_receive_block(uint8_t * data,uint16_t size)208 void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){
209 HAL_UART_Receive_DMA( &huart3, data, size );
210 }
211
212 #ifndef ENABLE_SEGGER_RTT
213
214 /**
215 * Use USART_CONSOLE as a console.
216 * This is a syscall for newlib
217 * @param file
218 * @param ptr
219 * @param len
220 * @return
221 */
222
223 ssize_t _write(int file, const void *buf, size_t len);
_write(int file,const void * buf,size_t len)224 ssize_t _write(int file, const void *buf, size_t len){
225 #if 1
226 uint8_t cr = '\r';
227 int i;
228 uint8_t *ptr = buf;
229 if (file == STDOUT_FILENO || file == STDERR_FILENO) {
230 for (i = 0; i < len; i++) {
231 if (ptr[i] == '\n') {
232 HAL_UART_Transmit( &huart2, &cr, 1, HAL_MAX_DELAY );
233 }
234 HAL_UART_Transmit( &huart2, &ptr[i], 1, HAL_MAX_DELAY );
235 }
236 return i;
237 }
238 errno = EIO;
239 return -1;
240 #else
241 return len;
242 #endif
243 }
244 #endif
245
_read(int fd,void * buf,size_t count)246 ssize_t _read(int fd, void * buf, size_t count){
247 UNUSED(fd);
248 UNUSED(buf);
249 UNUSED(count);
250 return -1;
251 }
252
_close(int file)253 int _close(int file){
254 UNUSED(file);
255 return -1;
256 }
257
_isatty(int file)258 int _isatty(int file){
259 UNUSED(file);
260 return -1;
261 }
262
_lseek(int file)263 int _lseek(int file){
264 UNUSED(file);
265 return -1;
266 }
267
_fstat(int file)268 int _fstat(int file){
269 UNUSED(file);
270 return -1;
271 }
272
_kill(pid_t pid,int sig)273 int _kill (pid_t pid, int sig) {
274 UNUSED(pid);
275 UNUSED(sig);
276 return -1;
277 }
278
_getpid(void)279 pid_t _getpid (void) {
280 return 0;
281 }
282
283 // main.c
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)284 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
285 UNUSED(size);
286 UNUSED(channel);
287 bd_addr_t local_addr;
288 if (packet_type != HCI_EVENT_PACKET) return;
289 switch(hci_event_packet_get_type(packet)){
290 case BTSTACK_EVENT_STATE:
291 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
292 gap_local_bd_addr(local_addr);
293 printf("BTstack up and running on %s.\n", bd_addr_to_str(local_addr));
294 break;
295 case HCI_EVENT_COMMAND_COMPLETE:
296 if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION){
297 uint16_t manufacturer = little_endian_read_16(packet, 10);
298 uint16_t lmp_subversion = little_endian_read_16(packet, 12);
299 // assert manufacturer is TI
300 if (manufacturer != BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){
301 printf("ERROR: Expected Bluetooth Chipset from TI but got manufacturer 0x%04x\n", manufacturer);
302 break;
303 }
304 // assert correct init script is used based on expected lmp_subversion
305 if (lmp_subversion != btstack_chipset_cc256x_lmp_subversion()){
306 printf("Error: LMP Subversion does not match initscript! ");
307 printf("Your initscripts is for %s chipset\n", btstack_chipset_cc256x_lmp_subversion() < lmp_subversion ? "an older" : "a newer");
308 printf("Please update Makefile to include the appropriate bluetooth_init_cc256???.c file\n");
309 break;
310 }
311 }
312 break;
313 default:
314 break;
315 }
316 }
317
318
319 static btstack_tlv_flash_bank_t btstack_tlv_flash_bank_context;
320 static hal_flash_bank_stm32_t hal_flash_bank_context;
321
322 #define HAL_FLASH_BANK_SIZE (128 * 1024)
323 #define HAL_FLASH_BANK_0_ADDR 0x080C0000
324 #define HAL_FLASH_BANK_1_ADDR 0x080E0000
325 #define HAL_FLASH_BANK_0_SECTOR FLASH_SECTOR_10
326 #define HAL_FLASH_BANK_1_SECTOR FLASH_SECTOR_11
327
328 //
329 int btstack_main(int argc, char ** argv);
port_main(void)330 void port_main(void){
331
332 // start with BTstack init - especially configure HCI Transport
333 btstack_memory_init();
334 btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
335
336 // uncomment to enable packet logger
337 #ifdef ENABLE_SEGGER_RTT
338 // hci_dump_init(hci_dump_segger_rtt_stdout_get_instance());
339 #else
340 // hci_dump_init(hci_dump_embedded_stdout_get_instance());
341 #endif
342
343 // init HCI
344 hci_init(hci_transport_h4_instance(btstack_uart_block_embedded_instance()), (void*) &config);
345 hci_set_chipset(btstack_chipset_cc256x_instance());
346
347 // setup TLV Flash Sector implementation
348 const hal_flash_bank_t * hal_flash_bank_impl = hal_flash_bank_stm32_init_instance(
349 &hal_flash_bank_context,
350 HAL_FLASH_BANK_SIZE,
351 HAL_FLASH_BANK_0_SECTOR,
352 HAL_FLASH_BANK_1_SECTOR,
353 HAL_FLASH_BANK_0_ADDR,
354 HAL_FLASH_BANK_1_ADDR);
355 const btstack_tlv_t * btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(
356 &btstack_tlv_flash_bank_context,
357 hal_flash_bank_impl,
358 &hal_flash_bank_context);
359
360 // setup global tlv
361 btstack_tlv_set_instance(btstack_tlv_impl, &btstack_tlv_flash_bank_context);
362
363 // setup Link Key DB using TLV
364 const btstack_link_key_db_t * btstack_link_key_db = btstack_link_key_db_tlv_get_instance(btstack_tlv_impl, &btstack_tlv_flash_bank_context);
365 hci_set_link_key_db(btstack_link_key_db);
366
367 // setup LE Device DB using TLV
368 le_device_db_tlv_configure(btstack_tlv_impl, &btstack_tlv_flash_bank_context);
369
370 #ifdef HAVE_HAL_AUDIO
371 // setup audio
372 btstack_audio_sink_set_instance(btstack_audio_embedded_sink_get_instance());
373 btstack_audio_source_set_instance(btstack_audio_embedded_source_get_instance());
374 #endif
375
376 // inform about BTstack state
377 hci_event_callback_registration.callback = &packet_handler;
378 hci_add_event_handler(&hci_event_callback_registration);
379
380 // hand over to btstack embedded code
381 btstack_main(0, NULL);
382
383 // go
384 btstack_run_loop_execute();
385 }
386
387 #if 0
388
389 // Help with debugging hard faults - from FreeRTOS docu
390 // https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html
391
392 void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress );
393 void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress ) {
394
395 /* These are volatile to try and prevent the compiler/linker optimising them
396 away as the variables never actually get used. If the debugger won't show the
397 values of the variables, make them global my moving their declaration outside
398 of this function. */
399 volatile uint32_t r0;
400 volatile uint32_t r1;
401 volatile uint32_t r2;
402 volatile uint32_t r3;
403 volatile uint32_t r12;
404 volatile uint32_t lr; /* Link register. */
405 volatile uint32_t pc; /* Program counter. */
406 volatile uint32_t psr;/* Program status register. */
407
408 r0 = pulFaultStackAddress[ 0 ];
409 r1 = pulFaultStackAddress[ 1 ];
410 r2 = pulFaultStackAddress[ 2 ];
411 r3 = pulFaultStackAddress[ 3 ];
412
413 r12 = pulFaultStackAddress[ 4 ];
414 lr = pulFaultStackAddress[ 5 ];
415 pc = pulFaultStackAddress[ 6 ];
416 psr = pulFaultStackAddress[ 7 ];
417
418 /* When the following line is hit, the variables contain the register values. */
419 for( ;; );
420 }
421
422 /* The prototype shows it is a naked function - in effect this is just an
423 assembly function. */
424 void HardFault_Handler( void ) __attribute__( ( naked ) );
425
426 /* The fault handler implementation calls a function called
427 prvGetRegistersFromStack(). */
428 void HardFault_Handler(void)
429 {
430 __asm volatile
431 (
432 " tst lr, #4 \n"
433 " ite eq \n"
434 " mrseq r0, msp \n"
435 " mrsne r0, psp \n"
436 " ldr r1, [r0, #24] \n"
437 " ldr r2, handler2_address_const \n"
438 " bx r2 \n"
439 " handler2_address_const: .word prvGetRegistersFromStack \n"
440 );
441 }
442
443 #endif
444