1*e25b4a2fSMatthias Ringwald /* 2*e25b4a2fSMatthias Ringwald * Copyright (C) 2015 BlueKitchen GmbH 3*e25b4a2fSMatthias Ringwald * 4*e25b4a2fSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*e25b4a2fSMatthias Ringwald * modification, are permitted provided that the following conditions 6*e25b4a2fSMatthias Ringwald * are met: 7*e25b4a2fSMatthias Ringwald * 8*e25b4a2fSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*e25b4a2fSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*e25b4a2fSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*e25b4a2fSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*e25b4a2fSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*e25b4a2fSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*e25b4a2fSMatthias Ringwald * contributors may be used to endorse or promote products derived 15*e25b4a2fSMatthias Ringwald * from this software without specific prior written permission. 16*e25b4a2fSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*e25b4a2fSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*e25b4a2fSMatthias Ringwald * monetary gain. 19*e25b4a2fSMatthias Ringwald * 20*e25b4a2fSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*e25b4a2fSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*e25b4a2fSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*e25b4a2fSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*e25b4a2fSMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*e25b4a2fSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*e25b4a2fSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*e25b4a2fSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*e25b4a2fSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*e25b4a2fSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*e25b4a2fSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*e25b4a2fSMatthias Ringwald * SUCH DAMAGE. 32*e25b4a2fSMatthias Ringwald * 33*e25b4a2fSMatthias Ringwald * Please inquire about commercial licensing options at 34*e25b4a2fSMatthias Ringwald * [email protected] 35*e25b4a2fSMatthias Ringwald * 36*e25b4a2fSMatthias Ringwald */ 37*e25b4a2fSMatthias Ringwald 38*e25b4a2fSMatthias Ringwald /* 39*e25b4a2fSMatthias Ringwald * hci_h4_transport_wiced.c 40*e25b4a2fSMatthias Ringwald * 41*e25b4a2fSMatthias Ringwald * HCI Transport API implementation for basic H4 protocol for use with btstack_run_loop_wiced.c 42*e25b4a2fSMatthias Ringwald */ 43*e25b4a2fSMatthias Ringwald 44*e25b4a2fSMatthias Ringwald #define __BTSTACK_FILE__ "hci_transport_h4_wiced.c" 45*e25b4a2fSMatthias Ringwald 46*e25b4a2fSMatthias Ringwald #include "btstack_config.h" 47*e25b4a2fSMatthias Ringwald #include "btstack_run_loop_wiced.h" 48*e25b4a2fSMatthias Ringwald 49*e25b4a2fSMatthias Ringwald #include "btstack_debug.h" 50*e25b4a2fSMatthias Ringwald #include "hci.h" 51*e25b4a2fSMatthias Ringwald #include "hci_transport.h" 52*e25b4a2fSMatthias Ringwald #include "platform_bluetooth.h" 53*e25b4a2fSMatthias Ringwald 54*e25b4a2fSMatthias Ringwald #include "wiced.h" 55*e25b4a2fSMatthias Ringwald 56*e25b4a2fSMatthias Ringwald #include <stdio.h> 57*e25b4a2fSMatthias Ringwald #include <string.h> 58*e25b4a2fSMatthias Ringwald 59*e25b4a2fSMatthias Ringwald // priority higher than WIFI to make sure RTS is set 60*e25b4a2fSMatthias Ringwald #define WICED_BT_UART_THREAD_PRIORITY (WICED_NETWORK_WORKER_PRIORITY - 2) 61*e25b4a2fSMatthias Ringwald #define WICED_BT_UART_THREAD_STACK_SIZE 300 62*e25b4a2fSMatthias Ringwald 63*e25b4a2fSMatthias Ringwald // assert pre-buffer for packet type is available 64*e25b4a2fSMatthias Ringwald #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0) 65*e25b4a2fSMatthias Ringwald #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h 66*e25b4a2fSMatthias Ringwald #endif 67*e25b4a2fSMatthias Ringwald 68*e25b4a2fSMatthias Ringwald // Default of 512 bytes should be fine. Only needed with BTSTACK_FLOW_CONTROL_UART 69*e25b4a2fSMatthias Ringwald #ifndef RX_RING_BUFFER_SIZE 70*e25b4a2fSMatthias Ringwald #define RX_RING_BUFFER_SIZE 512 71*e25b4a2fSMatthias Ringwald #endif 72*e25b4a2fSMatthias Ringwald 73*e25b4a2fSMatthias Ringwald // Use BTSTACK_FLOW_CONTROL_MANUAL is used when Bluetooth RTS/CTS are not connected to UART RTS/CTS pins 74*e25b4a2fSMatthias Ringwald // E.g. on RedBear Duo - WICED_BT_UART_MANUAL_CTS_RTS is defined 75*e25b4a2fSMatthias Ringwald 76*e25b4a2fSMatthias Ringwald static enum { 77*e25b4a2fSMatthias Ringwald BTSTACK_FLOW_CONTROL_OFF, 78*e25b4a2fSMatthias Ringwald BTSTACK_FLOW_CONTROL_UART, 79*e25b4a2fSMatthias Ringwald BTSTACK_FLOW_CONTROL_MANUAL, 80*e25b4a2fSMatthias Ringwald } btstack_flow_control_mode; 81*e25b4a2fSMatthias Ringwald 82*e25b4a2fSMatthias Ringwald static wiced_result_t btstack_uart_block_wiced_rx_worker_receive_block(void * arg); 83*e25b4a2fSMatthias Ringwald 84*e25b4a2fSMatthias Ringwald static wiced_worker_thread_t tx_worker_thread; 85*e25b4a2fSMatthias Ringwald static const uint8_t * tx_worker_data_buffer; 86*e25b4a2fSMatthias Ringwald static uint16_t tx_worker_data_size; 87*e25b4a2fSMatthias Ringwald 88*e25b4a2fSMatthias Ringwald static wiced_worker_thread_t rx_worker_thread; 89*e25b4a2fSMatthias Ringwald static uint8_t * rx_worker_read_buffer; 90*e25b4a2fSMatthias Ringwald static uint16_t rx_worker_read_size; 91*e25b4a2fSMatthias Ringwald 92*e25b4a2fSMatthias Ringwald static wiced_ring_buffer_t rx_ring_buffer; 93*e25b4a2fSMatthias Ringwald static uint8_t rx_data[RX_RING_BUFFER_SIZE]; 94*e25b4a2fSMatthias Ringwald 95*e25b4a2fSMatthias Ringwald // uart config 96*e25b4a2fSMatthias Ringwald static const btstack_uart_config_t * uart_config; 97*e25b4a2fSMatthias Ringwald 98*e25b4a2fSMatthias Ringwald // callbacks 99*e25b4a2fSMatthias Ringwald static void (*block_sent)(void); 100*e25b4a2fSMatthias Ringwald static void (*block_received)(void); 101*e25b4a2fSMatthias Ringwald 102*e25b4a2fSMatthias Ringwald // executed on main run loop 103*e25b4a2fSMatthias Ringwald static wiced_result_t btstack_uart_block_wiced_main_notify_block_send(void *arg){ 104*e25b4a2fSMatthias Ringwald if (block_sent){ 105*e25b4a2fSMatthias Ringwald block_sent(); 106*e25b4a2fSMatthias Ringwald } 107*e25b4a2fSMatthias Ringwald return WICED_SUCCESS; 108*e25b4a2fSMatthias Ringwald } 109*e25b4a2fSMatthias Ringwald 110*e25b4a2fSMatthias Ringwald // executed on main run loop 111*e25b4a2fSMatthias Ringwald static wiced_result_t btstack_uart_block_wiced_main_notify_block_read(void *arg){ 112*e25b4a2fSMatthias Ringwald if (block_received){ 113*e25b4a2fSMatthias Ringwald block_received(); 114*e25b4a2fSMatthias Ringwald } 115*e25b4a2fSMatthias Ringwald return WICED_SUCCESS; 116*e25b4a2fSMatthias Ringwald } 117*e25b4a2fSMatthias Ringwald 118*e25b4a2fSMatthias Ringwald // executed on tx worker thread 119*e25b4a2fSMatthias Ringwald static wiced_result_t btstack_uart_block_wiced_tx_worker_send_block(void * arg){ 120*e25b4a2fSMatthias Ringwald // wait for CTS to become low in manual flow control mode 121*e25b4a2fSMatthias Ringwald if (btstack_flow_control_mode == BTSTACK_FLOW_CONTROL_MANUAL && wiced_bt_uart_pins[WICED_BT_PIN_UART_CTS]){ 122*e25b4a2fSMatthias Ringwald while (platform_gpio_input_get(wiced_bt_uart_pins[WICED_BT_PIN_UART_CTS]) == WICED_TRUE){ 123*e25b4a2fSMatthias Ringwald wiced_rtos_delay_milliseconds(10); 124*e25b4a2fSMatthias Ringwald } 125*e25b4a2fSMatthias Ringwald } 126*e25b4a2fSMatthias Ringwald 127*e25b4a2fSMatthias Ringwald // blocking send 128*e25b4a2fSMatthias Ringwald platform_uart_transmit_bytes(wiced_bt_uart_driver, tx_worker_data_buffer, tx_worker_data_size); 129*e25b4a2fSMatthias Ringwald 130*e25b4a2fSMatthias Ringwald // let transport know 131*e25b4a2fSMatthias Ringwald btstack_run_loop_wiced_execute_code_on_main_thread(&btstack_uart_block_wiced_main_notify_block_send, NULL); 132*e25b4a2fSMatthias Ringwald return WICED_SUCCESS; 133*e25b4a2fSMatthias Ringwald } 134*e25b4a2fSMatthias Ringwald 135*e25b4a2fSMatthias Ringwald // executed on rx worker thread 136*e25b4a2fSMatthias Ringwald static wiced_result_t btstack_uart_block_wiced_rx_worker_receive_block(void * arg){ 137*e25b4a2fSMatthias Ringwald 138*e25b4a2fSMatthias Ringwald if (btstack_flow_control_mode == BTSTACK_FLOW_CONTROL_MANUAL && wiced_bt_uart_pins[WICED_BT_PIN_UART_CTS]){ 139*e25b4a2fSMatthias Ringwald platform_gpio_output_low(wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS]); 140*e25b4a2fSMatthias Ringwald } 141*e25b4a2fSMatthias Ringwald 142*e25b4a2fSMatthias Ringwald #ifdef WICED_UART_READ_DOES_NOT_RETURN_BYTES_READ 143*e25b4a2fSMatthias Ringwald // older API passes in number of bytes to read (checked in 3.3.1 and 3.4.0) 144*e25b4a2fSMatthias Ringwald platform_uart_receive_bytes(wiced_bt_uart_driver, rx_worker_read_buffer, rx_worker_read_size, WICED_NEVER_TIMEOUT); 145*e25b4a2fSMatthias Ringwald #else 146*e25b4a2fSMatthias Ringwald // newer API uses pointer to return number of read bytes 147*e25b4a2fSMatthias Ringwald uint32_t bytes = rx_worker_read_size; 148*e25b4a2fSMatthias Ringwald platform_uart_receive_bytes(wiced_bt_uart_driver, rx_worker_read_buffer, &bytes, WICED_NEVER_TIMEOUT); 149*e25b4a2fSMatthias Ringwald // assumption: bytes = bytes_to_read as timeout is never 150*e25b4a2fSMatthias Ringwald #endif 151*e25b4a2fSMatthias Ringwald 152*e25b4a2fSMatthias Ringwald if (btstack_flow_control_mode == BTSTACK_FLOW_CONTROL_MANUAL && wiced_bt_uart_pins[WICED_BT_PIN_UART_CTS]){ 153*e25b4a2fSMatthias Ringwald platform_gpio_output_high(wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS]); 154*e25b4a2fSMatthias Ringwald } 155*e25b4a2fSMatthias Ringwald 156*e25b4a2fSMatthias Ringwald // let transport know 157*e25b4a2fSMatthias Ringwald btstack_run_loop_wiced_execute_code_on_main_thread(&btstack_uart_block_wiced_main_notify_block_read, NULL); 158*e25b4a2fSMatthias Ringwald return WICED_SUCCESS; 159*e25b4a2fSMatthias Ringwald } 160*e25b4a2fSMatthias Ringwald 161*e25b4a2fSMatthias Ringwald static int btstack_uart_block_wiced_init(const btstack_uart_config_t * config){ 162*e25b4a2fSMatthias Ringwald uart_config = config; 163*e25b4a2fSMatthias Ringwald 164*e25b4a2fSMatthias Ringwald // determine flow control mode based on hardware config and uart config 165*e25b4a2fSMatthias Ringwald if (uart_config->flowcontrol){ 166*e25b4a2fSMatthias Ringwald #ifdef WICED_BT_UART_MANUAL_CTS_RTS 167*e25b4a2fSMatthias Ringwald btstack_flow_control_mode = BTSTACK_FLOW_CONTROL_MANUAL; 168*e25b4a2fSMatthias Ringwald #else 169*e25b4a2fSMatthias Ringwald btstack_flow_control_mode = BTSTACK_FLOW_CONTROL_UART; 170*e25b4a2fSMatthias Ringwald #endif 171*e25b4a2fSMatthias Ringwald } else { 172*e25b4a2fSMatthias Ringwald btstack_flow_control_mode = BTSTACK_FLOW_CONTROL_OFF; 173*e25b4a2fSMatthias Ringwald } 174*e25b4a2fSMatthias Ringwald return 0; 175*e25b4a2fSMatthias Ringwald } 176*e25b4a2fSMatthias Ringwald 177*e25b4a2fSMatthias Ringwald static int btstack_uart_block_wiced_open(void){ 178*e25b4a2fSMatthias Ringwald 179*e25b4a2fSMatthias Ringwald // UART config 180*e25b4a2fSMatthias Ringwald wiced_uart_config_t wiced_uart_config = 181*e25b4a2fSMatthias Ringwald { 182*e25b4a2fSMatthias Ringwald .baud_rate = uart_config->baudrate, 183*e25b4a2fSMatthias Ringwald .data_width = DATA_WIDTH_8BIT, 184*e25b4a2fSMatthias Ringwald .parity = NO_PARITY, 185*e25b4a2fSMatthias Ringwald .stop_bits = STOP_BITS_1, 186*e25b4a2fSMatthias Ringwald }; 187*e25b4a2fSMatthias Ringwald 188*e25b4a2fSMatthias Ringwald if (btstack_flow_control_mode == BTSTACK_FLOW_CONTROL_UART){ 189*e25b4a2fSMatthias Ringwald wiced_uart_config.flow_control = FLOW_CONTROL_CTS_RTS; 190*e25b4a2fSMatthias Ringwald } else { 191*e25b4a2fSMatthias Ringwald wiced_uart_config.flow_control = FLOW_CONTROL_DISABLED; 192*e25b4a2fSMatthias Ringwald } 193*e25b4a2fSMatthias Ringwald wiced_ring_buffer_t * ring_buffer = NULL; 194*e25b4a2fSMatthias Ringwald 195*e25b4a2fSMatthias Ringwald // configure HOST and DEVICE WAKE PINs 196*e25b4a2fSMatthias Ringwald platform_gpio_init(wiced_bt_control_pins[WICED_BT_PIN_HOST_WAKE], INPUT_HIGH_IMPEDANCE); 197*e25b4a2fSMatthias Ringwald platform_gpio_init(wiced_bt_control_pins[WICED_BT_PIN_DEVICE_WAKE], OUTPUT_PUSH_PULL); 198*e25b4a2fSMatthias Ringwald platform_gpio_output_low(wiced_bt_control_pins[WICED_BT_PIN_DEVICE_WAKE]); 199*e25b4a2fSMatthias Ringwald 200*e25b4a2fSMatthias Ringwald /* Configure Reg Enable pin to output. Set to HIGH */ 201*e25b4a2fSMatthias Ringwald if (wiced_bt_control_pins[ WICED_BT_PIN_POWER ]){ 202*e25b4a2fSMatthias Ringwald platform_gpio_init( wiced_bt_control_pins[ WICED_BT_PIN_POWER ], OUTPUT_OPEN_DRAIN_PULL_UP ); 203*e25b4a2fSMatthias Ringwald platform_gpio_output_high( wiced_bt_control_pins[ WICED_BT_PIN_POWER ] ); 204*e25b4a2fSMatthias Ringwald } 205*e25b4a2fSMatthias Ringwald 206*e25b4a2fSMatthias Ringwald wiced_rtos_delay_milliseconds( 100 ); 207*e25b4a2fSMatthias Ringwald 208*e25b4a2fSMatthias Ringwald // Configure RTS 209*e25b4a2fSMatthias Ringwald if (wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS]){ 210*e25b4a2fSMatthias Ringwald switch (btstack_flow_control_mode){ 211*e25b4a2fSMatthias Ringwald case BTSTACK_FLOW_CONTROL_OFF: 212*e25b4a2fSMatthias Ringwald // configure RTS pin as output and set to low - always on 213*e25b4a2fSMatthias Ringwald platform_gpio_init(wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS], OUTPUT_PUSH_PULL); 214*e25b4a2fSMatthias Ringwald platform_gpio_output_low(wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS]); 215*e25b4a2fSMatthias Ringwald break; 216*e25b4a2fSMatthias Ringwald case BTSTACK_FLOW_CONTROL_UART: 217*e25b4a2fSMatthias Ringwald // configuration done by platform_uart_init 218*e25b4a2fSMatthias Ringwald break; 219*e25b4a2fSMatthias Ringwald case BTSTACK_FLOW_CONTROL_MANUAL: 220*e25b4a2fSMatthias Ringwald // configure RTS pin as output and set to high - controlled by btstack_uart_block_wiced_rx_worker_receive_block 221*e25b4a2fSMatthias Ringwald platform_gpio_init(wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS], OUTPUT_PUSH_PULL); 222*e25b4a2fSMatthias Ringwald platform_gpio_output_high(wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS]); 223*e25b4a2fSMatthias Ringwald break; 224*e25b4a2fSMatthias Ringwald } 225*e25b4a2fSMatthias Ringwald } 226*e25b4a2fSMatthias Ringwald 227*e25b4a2fSMatthias Ringwald // Configure CTS 228*e25b4a2fSMatthias Ringwald if (wiced_bt_uart_pins[WICED_BT_PIN_UART_CTS]){ 229*e25b4a2fSMatthias Ringwald switch (btstack_flow_control_mode){ 230*e25b4a2fSMatthias Ringwald case BTSTACK_FLOW_CONTROL_OFF: 231*e25b4a2fSMatthias Ringwald // don't care 232*e25b4a2fSMatthias Ringwald break; 233*e25b4a2fSMatthias Ringwald case BTSTACK_FLOW_CONTROL_UART: 234*e25b4a2fSMatthias Ringwald // configuration done by platform_uart_init 235*e25b4a2fSMatthias Ringwald break; 236*e25b4a2fSMatthias Ringwald case BTSTACK_FLOW_CONTROL_MANUAL: 237*e25b4a2fSMatthias Ringwald // configure CTS to input, pull-up 238*e25b4a2fSMatthias Ringwald platform_gpio_init(wiced_bt_uart_pins[WICED_BT_PIN_UART_CTS], INPUT_PULL_UP); 239*e25b4a2fSMatthias Ringwald break; 240*e25b4a2fSMatthias Ringwald } 241*e25b4a2fSMatthias Ringwald } 242*e25b4a2fSMatthias Ringwald 243*e25b4a2fSMatthias Ringwald // use ring buffer to allow to receive RX_RING_BUFFER_SIZE/2 addition bytes - not needed with hardware UART 244*e25b4a2fSMatthias Ringwald if (btstack_flow_control_mode != BTSTACK_FLOW_CONTROL_UART){ 245*e25b4a2fSMatthias Ringwald ring_buffer_init((wiced_ring_buffer_t *) &rx_ring_buffer, (uint8_t*) rx_data, sizeof( rx_data ) ); 246*e25b4a2fSMatthias Ringwald ring_buffer = (wiced_ring_buffer_t *) &rx_ring_buffer; 247*e25b4a2fSMatthias Ringwald } 248*e25b4a2fSMatthias Ringwald 249*e25b4a2fSMatthias Ringwald platform_uart_init( wiced_bt_uart_driver, wiced_bt_uart_peripheral, &wiced_uart_config, ring_buffer ); 250*e25b4a2fSMatthias Ringwald 251*e25b4a2fSMatthias Ringwald 252*e25b4a2fSMatthias Ringwald // Reset Bluetooth via RESET line. Fallback to toggling POWER otherwise 253*e25b4a2fSMatthias Ringwald if ( wiced_bt_control_pins[ WICED_BT_PIN_RESET ]){ 254*e25b4a2fSMatthias Ringwald platform_gpio_init( wiced_bt_control_pins[ WICED_BT_PIN_RESET ], OUTPUT_PUSH_PULL ); 255*e25b4a2fSMatthias Ringwald platform_gpio_output_high( wiced_bt_control_pins[ WICED_BT_PIN_RESET ] ); 256*e25b4a2fSMatthias Ringwald 257*e25b4a2fSMatthias Ringwald platform_gpio_output_low( wiced_bt_control_pins[ WICED_BT_PIN_RESET ] ); 258*e25b4a2fSMatthias Ringwald wiced_rtos_delay_milliseconds( 100 ); 259*e25b4a2fSMatthias Ringwald platform_gpio_output_high( wiced_bt_control_pins[ WICED_BT_PIN_RESET ] ); 260*e25b4a2fSMatthias Ringwald } 261*e25b4a2fSMatthias Ringwald else if ( wiced_bt_control_pins[ WICED_BT_PIN_POWER ]){ 262*e25b4a2fSMatthias Ringwald platform_gpio_output_low( wiced_bt_control_pins[ WICED_BT_PIN_POWER ] ); 263*e25b4a2fSMatthias Ringwald wiced_rtos_delay_milliseconds( 100 ); 264*e25b4a2fSMatthias Ringwald platform_gpio_output_high( wiced_bt_control_pins[ WICED_BT_PIN_POWER ] ); 265*e25b4a2fSMatthias Ringwald } 266*e25b4a2fSMatthias Ringwald 267*e25b4a2fSMatthias Ringwald // wait for Bluetooth to start up 268*e25b4a2fSMatthias Ringwald wiced_rtos_delay_milliseconds( 500 ); 269*e25b4a2fSMatthias Ringwald 270*e25b4a2fSMatthias Ringwald // create worker threads for rx/tx. only single request is posted to their queues 271*e25b4a2fSMatthias Ringwald wiced_rtos_create_worker_thread(&tx_worker_thread, WICED_BT_UART_THREAD_PRIORITY, WICED_BT_UART_THREAD_STACK_SIZE, 1); 272*e25b4a2fSMatthias Ringwald wiced_rtos_create_worker_thread(&rx_worker_thread, WICED_BT_UART_THREAD_PRIORITY, WICED_BT_UART_THREAD_STACK_SIZE, 1); 273*e25b4a2fSMatthias Ringwald 274*e25b4a2fSMatthias Ringwald // tx is ready 275*e25b4a2fSMatthias Ringwald tx_worker_data_size = 0; 276*e25b4a2fSMatthias Ringwald return 0; 277*e25b4a2fSMatthias Ringwald } 278*e25b4a2fSMatthias Ringwald 279*e25b4a2fSMatthias Ringwald static int btstack_uart_block_wiced_close(void){ 280*e25b4a2fSMatthias Ringwald // not implemented 281*e25b4a2fSMatthias Ringwald return 0; 282*e25b4a2fSMatthias Ringwald } 283*e25b4a2fSMatthias Ringwald 284*e25b4a2fSMatthias Ringwald static void btstack_uart_block_wiced_set_block_received( void (*block_handler)(void)){ 285*e25b4a2fSMatthias Ringwald block_received = block_handler; 286*e25b4a2fSMatthias Ringwald } 287*e25b4a2fSMatthias Ringwald 288*e25b4a2fSMatthias Ringwald static void btstack_uart_block_wiced_set_block_sent( void (*block_handler)(void)){ 289*e25b4a2fSMatthias Ringwald block_sent = block_handler; 290*e25b4a2fSMatthias Ringwald } 291*e25b4a2fSMatthias Ringwald 292*e25b4a2fSMatthias Ringwald static int btstack_uart_block_wiced_set_baudrate(uint32_t baudrate){ 293*e25b4a2fSMatthias Ringwald 294*e25b4a2fSMatthias Ringwald #if defined(_STM32F205RGT6_) || defined(STM32F40_41xxx) 295*e25b4a2fSMatthias Ringwald 296*e25b4a2fSMatthias Ringwald // directly use STM peripheral functions to change baud rate dynamically 297*e25b4a2fSMatthias Ringwald 298*e25b4a2fSMatthias Ringwald // set TX to high 299*e25b4a2fSMatthias Ringwald log_info("set baud %u", (int) baudrate); 300*e25b4a2fSMatthias Ringwald const platform_gpio_t* gpio = wiced_bt_uart_pins[WICED_BT_PIN_UART_TX]; 301*e25b4a2fSMatthias Ringwald platform_gpio_output_high(gpio); 302*e25b4a2fSMatthias Ringwald 303*e25b4a2fSMatthias Ringwald // reconfigure TX pin as GPIO 304*e25b4a2fSMatthias Ringwald GPIO_InitTypeDef gpio_init_structure; 305*e25b4a2fSMatthias Ringwald gpio_init_structure.GPIO_Speed = GPIO_Speed_50MHz; 306*e25b4a2fSMatthias Ringwald gpio_init_structure.GPIO_Mode = GPIO_Mode_OUT; 307*e25b4a2fSMatthias Ringwald gpio_init_structure.GPIO_OType = GPIO_OType_PP; 308*e25b4a2fSMatthias Ringwald gpio_init_structure.GPIO_PuPd = GPIO_PuPd_NOPULL; 309*e25b4a2fSMatthias Ringwald gpio_init_structure.GPIO_Pin = (uint32_t) ( 1 << gpio->pin_number ); 310*e25b4a2fSMatthias Ringwald GPIO_Init( gpio->port, &gpio_init_structure ); 311*e25b4a2fSMatthias Ringwald 312*e25b4a2fSMatthias Ringwald // disable USART 313*e25b4a2fSMatthias Ringwald USART_Cmd( wiced_bt_uart_peripheral->port, DISABLE ); 314*e25b4a2fSMatthias Ringwald 315*e25b4a2fSMatthias Ringwald // setup init structure 316*e25b4a2fSMatthias Ringwald USART_InitTypeDef uart_init_structure; 317*e25b4a2fSMatthias Ringwald uart_init_structure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 318*e25b4a2fSMatthias Ringwald uart_init_structure.USART_BaudRate = baudrate; 319*e25b4a2fSMatthias Ringwald uart_init_structure.USART_WordLength = USART_WordLength_8b; 320*e25b4a2fSMatthias Ringwald uart_init_structure.USART_StopBits = USART_StopBits_1; 321*e25b4a2fSMatthias Ringwald uart_init_structure.USART_Parity = USART_Parity_No; 322*e25b4a2fSMatthias Ringwald 323*e25b4a2fSMatthias Ringwald if (btstack_flow_control_mode == BTSTACK_FLOW_CONTROL_UART){ 324*e25b4a2fSMatthias Ringwald uart_init_structure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS; 325*e25b4a2fSMatthias Ringwald } else { 326*e25b4a2fSMatthias Ringwald uart_init_structure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 327*e25b4a2fSMatthias Ringwald } 328*e25b4a2fSMatthias Ringwald USART_Init(wiced_bt_uart_peripheral->port, &uart_init_structure); 329*e25b4a2fSMatthias Ringwald 330*e25b4a2fSMatthias Ringwald // enable USART again 331*e25b4a2fSMatthias Ringwald USART_Cmd( wiced_bt_uart_peripheral->port, ENABLE ); 332*e25b4a2fSMatthias Ringwald 333*e25b4a2fSMatthias Ringwald // set TX pin as USART again 334*e25b4a2fSMatthias Ringwald gpio_init_structure.GPIO_Mode = GPIO_Mode_AF; 335*e25b4a2fSMatthias Ringwald GPIO_Init( gpio->port, &gpio_init_structure ); 336*e25b4a2fSMatthias Ringwald 337*e25b4a2fSMatthias Ringwald #else 338*e25b4a2fSMatthias Ringwald log_error("btstack_uart_block_wiced_set_baudrate not implemented for this WICED Platform"); 339*e25b4a2fSMatthias Ringwald #endif 340*e25b4a2fSMatthias Ringwald return 0; 341*e25b4a2fSMatthias Ringwald } 342*e25b4a2fSMatthias Ringwald 343*e25b4a2fSMatthias Ringwald static int btstack_uart_block_wiced_set_parity(int parity){ 344*e25b4a2fSMatthias Ringwald log_error("btstack_uart_block_wiced_set_parity not implemented"); 345*e25b4a2fSMatthias Ringwald return 0; 346*e25b4a2fSMatthias Ringwald } 347*e25b4a2fSMatthias Ringwald 348*e25b4a2fSMatthias Ringwald static void btstack_uart_block_wiced_send_block(const uint8_t *buffer, uint16_t length){ 349*e25b4a2fSMatthias Ringwald // store in request 350*e25b4a2fSMatthias Ringwald tx_worker_data_buffer = buffer; 351*e25b4a2fSMatthias Ringwald tx_worker_data_size = length; 352*e25b4a2fSMatthias Ringwald wiced_rtos_send_asynchronous_event(&tx_worker_thread, &btstack_uart_block_wiced_tx_worker_send_block, NULL); 353*e25b4a2fSMatthias Ringwald } 354*e25b4a2fSMatthias Ringwald 355*e25b4a2fSMatthias Ringwald static void btstack_uart_block_wiced_receive_block(uint8_t *buffer, uint16_t len){ 356*e25b4a2fSMatthias Ringwald rx_worker_read_buffer = buffer; 357*e25b4a2fSMatthias Ringwald rx_worker_read_size = len; 358*e25b4a2fSMatthias Ringwald wiced_rtos_send_asynchronous_event(&rx_worker_thread, &btstack_uart_block_wiced_rx_worker_receive_block, NULL); 359*e25b4a2fSMatthias Ringwald } 360*e25b4a2fSMatthias Ringwald 361*e25b4a2fSMatthias Ringwald 362*e25b4a2fSMatthias Ringwald // static void btstack_uart_block_wiced_set_sleep(uint8_t sleep){ 363*e25b4a2fSMatthias Ringwald // } 364*e25b4a2fSMatthias Ringwald // static void btstack_uart_block_wiced_set_csr_irq_handler( void (*csr_irq_handler)(void)){ 365*e25b4a2fSMatthias Ringwald // } 366*e25b4a2fSMatthias Ringwald 367*e25b4a2fSMatthias Ringwald static const btstack_uart_block_t btstack_uart_block_wiced = { 368*e25b4a2fSMatthias Ringwald /* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_block_wiced_init, 369*e25b4a2fSMatthias Ringwald /* int (*open)(void); */ &btstack_uart_block_wiced_open, 370*e25b4a2fSMatthias Ringwald /* int (*close)(void); */ &btstack_uart_block_wiced_close, 371*e25b4a2fSMatthias Ringwald /* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_block_wiced_set_block_received, 372*e25b4a2fSMatthias Ringwald /* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_block_wiced_set_block_sent, 373*e25b4a2fSMatthias Ringwald /* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_block_wiced_set_baudrate, 374*e25b4a2fSMatthias Ringwald /* int (*set_parity)(int parity); */ &btstack_uart_block_wiced_set_parity, 375*e25b4a2fSMatthias Ringwald /* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_block_wiced_receive_block, 376*e25b4a2fSMatthias Ringwald /* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_block_wiced_send_block, 377*e25b4a2fSMatthias Ringwald /* int (*get_supported_sleep_modes); */ NULL, 378*e25b4a2fSMatthias Ringwald /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL, 379*e25b4a2fSMatthias Ringwald /* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL, 380*e25b4a2fSMatthias Ringwald }; 381*e25b4a2fSMatthias Ringwald 382*e25b4a2fSMatthias Ringwald const btstack_uart_block_t * btstack_uart_block_wiced_instance(void){ 383*e25b4a2fSMatthias Ringwald return &btstack_uart_block_wiced; 384*e25b4a2fSMatthias Ringwald }