xref: /btstack/port/archive/pic32-harmony/src/btstack_port.c (revision 98451c7b102094e15e0a72ca2f7098d91aed2017)
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 
dummy_handler(void)43 static void dummy_handler(void){};
44 static DRV_HANDLE handleTmr;
45 static bool ledIsOn;
46 
sys_tick_handler(uintptr_t context,uint32_t alarmCount)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 
hal_tick_init(void)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 
hal_tick_get_tick_period_in_ms(void)73 int  hal_tick_get_tick_period_in_ms(void){
74     return 250;
75 }
76 
hal_tick_set_handler(void (* handler)(void))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 
msleep(uint32_t delay)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 
hal_cpu_disable_irqs(void)95 void hal_cpu_disable_irqs(void){
96     // TODO implement
97 }
98 
hal_cpu_enable_irqs(void)99 void hal_cpu_enable_irqs(void){
100     // TODO implement
101 }
102 
hal_cpu_enable_irqs_and_sleep(void)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
bluetooth_power_cycle(void)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 
hal_uart_dma_init(void)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 
hal_uart_dma_set_block_received(void (* the_block_handler)(void))178 void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
179     rx_done_handler = the_block_handler;
180 }
181 
hal_uart_dma_set_block_sent(void (* the_block_handler)(void))182 void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
183     tx_done_handler = the_block_handler;
184 }
185 
hal_uart_dma_set_csr_irq_handler(void (* the_irq_handler)(void))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 }
hal_uart_dma_set_sleep(uint8_t sleep)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 
hal_uart_dma_set_baud(uint32_t baud)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 
hal_uart_dma_send_block(const uint8_t * data,uint16_t size)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 
hal_uart_dma_receive_block(uint8_t * data,uint16_t size)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 
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)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 
BTSTACK_Initialize(void)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 
BTSTACK_Tasks(void)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