1 // 2 // BTstack Port for the Microchip PIC32 Harmony Platfrom 3 // 4 5 #include "btstack_port.h" 6 7 #include "system_config.h" 8 9 #include "btstack_chipset_csr.h" 10 #include "btstack_debug.h" 11 #include "btstack_event.h" 12 #include "btstack_run_loop.h" 13 #include "btstack_run_loop_embedded.h" 14 #include "btstack_uart_slip_wrapper.h" 15 #include "hci.h" 16 #include "hci_dump.h" 17 #include "hci_transport.h" 18 19 #include <stdint.h> 20 #include <stdbool.h> 21 #include <stddef.h> 22 #include <stdlib.h> 23 24 #include "driver/tmr/drv_tmr.h" 25 #include "peripheral/usart/plib_usart.h" 26 #include "system/ports/sys_ports.h" 27 28 // 29 int btstack_main(int argc, const char * argv[]); 30 31 32 /// HAL Tick /// 33 #include "hal_tick.h" 34 35 #define APP_TMR_ALARM_PERIOD 48825 36 #define APP_LED_PORT PORT_CHANNEL_A 37 #define APP_LED_PIN PORTS_BIT_POS_4 38 39 static void dummy_handler(void); 40 static void (*tick_handler)(void); 41 static int hal_uart_needed_during_sleep = 1; 42 43 static void dummy_handler(void){}; 44 static DRV_HANDLE handleTmr; 45 static bool ledIsOn; 46 47 static void sys_tick_handler ( uintptr_t context, uint32_t alarmCount ){ 48 if (!ledIsOn) { 49 ledIsOn = true; 50 SYS_PORTS_PinSet(PORTS_ID_0, APP_LED_PORT, APP_LED_PIN); 51 } 52 else 53 { 54 ledIsOn = false; 55 SYS_PORTS_PinClear(PORTS_ID_0, APP_LED_PORT, APP_LED_PIN); 56 } 57 58 (*tick_handler)(); 59 } 60 61 void hal_tick_init(void){ 62 ledIsOn = false; 63 handleTmr = DRV_TMR_Open(APP_TMR_DRV_INDEX, DRV_IO_INTENT_EXCLUSIVE); 64 if( DRV_HANDLE_INVALID == handleTmr ){ 65 log_error("Timer init failed"); 66 return; 67 } 68 DRV_TMR_Alarm16BitRegister(handleTmr, APP_TMR_ALARM_PERIOD, true, (uintptr_t)NULL, sys_tick_handler); 69 DRV_TMR_Start(handleTmr); 70 SYS_PORTS_PinDirectionSelect(PORTS_ID_0, SYS_PORTS_DIRECTION_OUTPUT, APP_LED_PORT, APP_LED_PIN); 71 } 72 73 int hal_tick_get_tick_period_in_ms(void){ 74 return 250; 75 } 76 77 void hal_tick_set_handler(void (*handler)(void)){ 78 if (handler == NULL){ 79 tick_handler = &dummy_handler; 80 return; 81 } 82 tick_handler = handler; 83 } 84 85 static void msleep(uint32_t delay) { 86 uint32_t wake = btstack_run_loop_embedded_get_ticks() + delay / hal_tick_get_tick_period_in_ms(); 87 while (wake > btstack_run_loop_embedded_get_ticks()){ 88 SYS_Tasks(); 89 }; 90 } 91 92 /// HAL CPU /// 93 #include "hal_cpu.h" 94 95 void hal_cpu_disable_irqs(void){ 96 // TODO implement 97 } 98 99 void hal_cpu_enable_irqs(void){ 100 // TODO implement 101 } 102 103 void hal_cpu_enable_irqs_and_sleep(void){ 104 // TODO implement 105 } 106 107 108 /// HAL UART DMA /// 109 #include "hal_uart_dma.h" 110 111 // handlers 112 static void (*rx_done_handler)(void) = dummy_handler; 113 static void (*tx_done_handler)(void) = dummy_handler; 114 static void (*cts_irq_handler)(void) = dummy_handler; 115 116 // rx state 117 static uint16_t bytes_to_read = 0; 118 static uint8_t * rx_buffer_ptr = 0; 119 120 // tx state 121 static uint16_t bytes_to_write = 0; 122 static uint8_t * tx_buffer_ptr = 0; 123 124 125 // reset Bluetooth using n_shutdown 126 static void bluetooth_power_cycle(void){ 127 printf("Bluetooth power cycle: Reset ON\n"); 128 SYS_PORTS_PinClear(PORTS_ID_0, BT_RESET_PORT, BT_RESET_BIT); 129 msleep(250); 130 printf("Bluetooth power cycle: Reset OFF\n"); 131 SYS_PORTS_PinSet(PORTS_ID_0, BT_RESET_PORT, BT_RESET_BIT); 132 } 133 134 void hal_uart_dma_init(void){ 135 136 bytes_to_write = 0; 137 bytes_to_read = 0; 138 139 /* PPS Input Remapping */ 140 PLIB_PORTS_RemapInput(PORTS_ID_0, INPUT_FUNC_U2RX, INPUT_PIN_RPF4 ); 141 PLIB_PORTS_RemapInput(PORTS_ID_0, INPUT_FUNC_U2CTS, INPUT_PIN_RPB2 ); 142 143 /* PPS Output Remapping */ 144 PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_U2RTS, OUTPUT_PIN_RPG9 ); 145 PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_U2TX, OUTPUT_PIN_RPF5 ); 146 147 /* Initialize USART */ 148 PLIB_USART_BaudRateSet(BT_USART_ID, SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_1), BT_USART_BAUD); 149 PLIB_USART_HandshakeModeSelect(BT_USART_ID, USART_HANDSHAKE_MODE_FLOW_CONTROL); 150 PLIB_USART_OperationModeSelect(BT_USART_ID, USART_ENABLE_TX_RX_CTS_RTS_USED); 151 PLIB_USART_LineControlModeSelect(BT_USART_ID, USART_8N1); 152 153 // BCSP on CSR requires even parity 154 // PLIB_USART_LineControlModeSelect(BT_USART_ID, USART_8E1); 155 156 PLIB_USART_TransmitterEnable(BT_USART_ID); 157 // PLIB_USART_TransmitterInterruptModeSelect(bluetooth_uart_id, USART_TRANSMIT_FIFO_IDLE); 158 159 // allow overrun mode: not needed for H4. CSR with BCSP/H5 does not enable RTS/CTS 160 PLIB_USART_RunInOverflowEnable(BT_USART_ID); 161 162 PLIB_USART_ReceiverEnable(BT_USART_ID); 163 // PLIB_USART_ReceiverInterruptModeSelect(bluetooth_uart_id, USART_RECEIVE_FIFO_ONE_CHAR); 164 165 PLIB_USART_Enable(BT_USART_ID); 166 167 // enable _RESET 168 SYS_PORTS_PinDirectionSelect(PORTS_ID_0, SYS_PORTS_DIRECTION_OUTPUT, BT_RESET_PORT, BT_RESET_BIT); 169 170 bluetooth_power_cycle(); 171 172 // After reset, CTS is high and we need to wait until CTS is low again 173 174 // HACK: CTS doesn't seem to work right now 175 msleep(250); 176 } 177 178 void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){ 179 rx_done_handler = the_block_handler; 180 } 181 182 void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){ 183 tx_done_handler = the_block_handler; 184 } 185 186 void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){ 187 // not needed for regular H4 module (but needed for TI's eHCILL) 188 } 189 void hal_uart_dma_set_sleep(uint8_t sleep){ 190 // not needed for regualr h4 module (but needed for eHCILL or h5) 191 UNUSED(sleep); 192 } 193 194 int hal_uart_dma_set_baud(uint32_t baud){ 195 // PLIB_USART_Disable(BT_USART_ID); 196 // PLIB_USART_BaudRateSet(BT_USART_ID, SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_1), baud); 197 // PLIB_USART_Enable(BT_USART_ID); 198 return 0; 199 } 200 201 void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){ 202 tx_buffer_ptr = (uint8_t *) data; 203 bytes_to_write = size;} 204 205 206 void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){ 207 // printf("hal_uart_dma_receive_block req size %u\n", size); 208 rx_buffer_ptr = data; 209 bytes_to_read = size; 210 } 211 212 /// 213 static hci_transport_config_uart_t config = { 214 HCI_TRANSPORT_CONFIG_UART, 215 115200, 216 0, // main baudrate 217 1, // flow control 218 NULL, 219 }; 220 221 static btstack_packet_callback_registration_t hci_event_callback_registration; 222 223 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 224 if (packet_type != HCI_EVENT_PACKET) return; 225 if (hci_event_packet_get_type(packet) != BTSTACK_EVENT_STATE) return; 226 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 227 printf("BTstack up and running.\n"); 228 } 229 230 void BTSTACK_Initialize ( void ) 231 { 232 printf("\n\nBTstack_Initialize()\n"); 233 234 btstack_memory_init(); 235 btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); 236 237 hci_dump_open(NULL, HCI_DUMP_STDOUT); 238 239 // setup uart driver 240 const btstack_uart_block_t * uart_block_driver = btstack_uart_block_embedded_instance(); 241 const btstack_uart_t * uart_slip_driver = btstack_uart_slip_wrapper_instance(uart_block_driver); 242 243 const hci_transport_t * transport = hci_transport_h5_instance(uart_slip_driver); 244 hci_init(transport, &config); 245 hci_set_chipset(btstack_chipset_csr_instance()); 246 247 // inform about BTstack state 248 hci_event_callback_registration.callback = &packet_handler; 249 hci_add_event_handler(&hci_event_callback_registration); 250 251 btstack_main(0, NULL); 252 } 253 254 255 void BTSTACK_Tasks(void){ 256 257 while (bytes_to_read && PLIB_USART_ReceiverDataIsAvailable(BT_USART_ID)) { 258 *rx_buffer_ptr++ = PLIB_USART_ReceiverByteReceive(BT_USART_ID); 259 bytes_to_read--; 260 if (bytes_to_read == 0){ 261 (*rx_done_handler)(); 262 } 263 } 264 265 if(PLIB_USART_ReceiverOverrunHasOccurred(BT_USART_ID)) 266 { 267 // printf("RX Overrun!\n"); 268 PLIB_USART_ReceiverOverrunErrorClear(BT_USART_ID); 269 } 270 271 while (bytes_to_write && !PLIB_USART_TransmitterBufferIsFull(BT_USART_ID)){ 272 PLIB_USART_TransmitterByteSend(BT_USART_ID, *tx_buffer_ptr++); 273 bytes_to_write--; 274 if (bytes_to_write == 0){ 275 (*tx_done_handler)(); 276 } 277 } 278 279 // BTstack Run Loop 280 btstack_run_loop_embedded_execute_once(); 281 } 282 283