1# 2 3In this section, we highlight the BTstack components that need to be 4adjusted for different hardware platforms. 5 6 7## Time Abstraction Layer {#sec:timeAbstractionPorting} 8 9BTstack requires a way to learn about passing time. 10*btstack_run_loop_embedded.c* supports two different modes: system ticks or a 11system clock with millisecond resolution. BTstack’s timing requirements 12are quite low as only Bluetooth timeouts in the second range need to be 13handled. 14 15 16### Tick Hardware Abstraction {#sec:tickAbstractionPorting} 17 18 19If your platform doesn’t require a system clock or if you already have a 20system tick (as it is the default with CMSIS on ARM Cortex devices), you 21can use that to implement BTstack’s time abstraction in 22*include/btstack/hal_tick.h\>*. 23 24For this, you need to define *HAVE_EMBEDDED_TICK* in *btstack_config.h*: 25 26 #define HAVE_EMBEDDED_TICK 27 28Then, you need to implement the functions *hal_tick_init* and 29*hal_tick_set_handler*, which will be called during the 30initialization of the run loop. 31 32 void hal_tick_init(void); 33 void hal_tick_set_handler(void (*tick_handler)(void)); 34 int hal_tick_get_tick_period_in_ms(void); 35 36After BTstack calls *hal_tick_init()* and 37*hal_tick_set_handler(tick_handler)*, it expects that the 38*tick_handler* gets called every 39*hal_tick_get_tick_period_in_ms()* ms. 40 41 42### Time MS Hardware Abstraction {#sec:timeMSAbstractionPorting} 43 44 45If your platform already has a system clock or it is more convenient to 46provide such a clock, you can use the Time MS Hardware Abstraction in 47*include/btstack/hal_time_ms.h*. 48 49For this, you need to define *HAVE_EMBEDDED_TIME_MS* in *btstack_config.h*: 50 51 #define HAVE_EMBEDDED_TIME_MS 52 53Then, you need to implement the function *hal_time_ms()*, which will 54be called from BTstack’s run loop and when setting a timer for the 55future. It has to return the time in milliseconds. 56 57 uint32_t hal_time_ms(void); 58 59 60## Bluetooth Hardware Control API {#sec:btHWControlPorting} 61 62 63The Bluetooth hardware control API can provide the HCI layer with a 64custom initialization script, a vendor-specific baud rate change 65command, and system power notifications. It is also used to control the 66power mode of the Bluetooth module, i.e., turning it on/off and putting 67to sleep. In addition, it provides an error handler *hw_error* that is 68called when a Hardware Error is reported by the Bluetooth module. The 69callback allows for persistent logging or signaling of this failure. 70 71Overall, the struct *btstack_control_t* encapsulates common functionality 72that is not covered by the Bluetooth specification. As an example, the 73*btstack_chipset_cc256x_in-stance* function returns a pointer to a control 74struct suitable for the CC256x chipset. 75 76 77 78## HCI Transport Implementation {#sec:hciTransportPorting} 79 80 81On embedded systems, a Bluetooth module can be connected via USB or an 82UART port. BTstack implements three UART based protocols for carrying HCI 83commands, events and data between a host and a Bluetooth module: HCI 84UART Transport Layer (H4), H4 with eHCILL support, a lightweight 85low-power variant by Texas Instruments, and the Three-Wire UART Transport Layer (H5). 86 87 88### HCI UART Transport Layer (H4) {#sec:hciUARTPorting} 89 90 91Most embedded UART interfaces operate on the byte level and generate a 92processor interrupt when a byte was received. In the interrupt handler, 93common UART drivers then place the received data in a ring buffer and 94set a flag for further processing or notify the higher-level code, i.e., 95in our case the Bluetooth stack. 96 97Bluetooth communication is packet-based and a single packet may contain 98up to 1021 bytes. Calling a data received handler of the Bluetooth stack 99for every byte creates an unnecessary overhead. To avoid that, a 100Bluetooth packet can be read as multiple blocks where the amount of 101bytes to read is known in advance. Even better would be the use of 102on-chip DMA modules for these block reads, if available. 103 104The BTstack UART Hardware Abstraction Layer API reflects this design 105approach and the underlying UART driver has to implement the following 106API: 107 108 void hal_uart_dma_init(void); 109 void hal_uart_dma_set_block_received(void (*block_handler)(void)); 110 void hal_uart_dma_set_block_sent(void (*block_handler)(void)); 111 int hal_uart_dma_set_baud(uint32_t baud); 112 void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t len); 113 void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len); 114 115 116The main HCI H4 implementations for embedded system is 117*hci_h4_transport-_dma* function. This function calls the following 118sequence: *hal_uart_dma_init*, *hal_uart_dma_set_block_received* 119and *hal_uart_dma_set_block_sent* functions. this sequence, the HCI 120layer will start packet processing by calling 121*hal_uart-_dma_receive_block* function. The HAL implementation is 122responsible for reading the requested amount of bytes, stopping incoming 123data via the RTS line when the requested amount of data was received and 124has to call the handler. By this, the HAL implementation can stay 125generic, while requiring only three callbacks per HCI packet. 126 127### H4 with eHCILL support 128 129With the standard H4 protocol interface, it is not possible for either 130the host nor the baseband controller to enter a sleep mode. Besides the 131official H5 protocol, various chip vendors came up with proprietary 132solutions to this. The eHCILL support by Texas Instruments allows both 133the host and the baseband controller to independently enter sleep mode 134without loosing their synchronization with the HCI H4 Transport Layer. 135In addition to the IRQ-driven block-wise RX and TX, eHCILL requires a 136callback for CTS interrupts. 137 138 void hal_uart_dma_set_cts_irq_handler(void(*cts_irq_handler)(void)); 139 void hal_uart_dma_set_sleep(uint8_t sleep); 140 141 142### H5 143 144H5, makes use of the SLIP protocol to transmit a packet and can deal 145with packet loss and bit-errors by retransmission. Since it can recover 146from packet loss, it's also possible for either side to enter sleep 147mode without loosing synchronization. 148 149The use of hardware flow control in H5 is optional, however, since 150BTstack uses hardware flow control to avoid packet buffers, it's 151recommended to only use H5 with RTS/CTS as well. 152 153For porting, the implementation follows the regular H4 protocol described above. 154 155## Persistent Storage APIs {#sec:persistentStoragePorting} 156 157On embedded systems there is no generic way to persist data like link 158keys or remote device names, as every type of a device has its own 159capabilities, particularities and limitations. The persistent storage 160APIs provides an interface to implement concrete drivers for a particular 161system. 162 163### Link Key DB 164 165As an example and for testing purposes, BTstack provides the 166memory-only implementation *btstack_link_key_db_memory*. An 167implementation has to conform to the interface in Listing [below](#lst:persistentDB). 168 169~~~~ {#lst:persistentDB .c caption="{Persistent storage interface.}"} 170 171 typedef struct { 172 // management 173 void (*open)(); 174 void (*close)(); 175 176 // link key 177 int (*get_link_key)(bd_addr_t bd_addr, link_key_t link_key); 178 void (*put_link_key)(bd_addr_t bd_addr, link_key_t key); 179 void (*delete_link_key)(bd_addr_t bd_addr); 180 } btstack_link_key_db_t; 181~~~~ 182