155ab84a4SMatthias Ringwald #define __BTSTACK_FILE__ "main.c" 255ab84a4SMatthias Ringwald 31b2596b5SMatthias Ringwald #include "asf.h" 41b2596b5SMatthias Ringwald #include "stdio_serial.h" 51b2596b5SMatthias Ringwald #include "conf_board.h" 61b2596b5SMatthias Ringwald #include "conf_clock.h" 71b2596b5SMatthias Ringwald 858a1b1bbSMatthias Ringwald // BTstack 913b8e9b1SMatthias Ringwald #include "btstack_chipset_atwilc3000.h" 1013b8e9b1SMatthias Ringwald #include "btstack_debug.h" 1113b8e9b1SMatthias Ringwald #include "btstack_memory.h" 1258a1b1bbSMatthias Ringwald #include "btstack_run_loop.h" 1358a1b1bbSMatthias Ringwald #include "btstack_run_loop_embedded.h" 1458a1b1bbSMatthias Ringwald #include "hal_uart_dma.h" 1558a1b1bbSMatthias Ringwald #include "hal_cpu.h" 1658a1b1bbSMatthias Ringwald #include "hal_tick.h" 1713b8e9b1SMatthias Ringwald #include "hci.h" 1813b8e9b1SMatthias Ringwald #include "hci_dump.h" 19*25d9a2cdSMatthias Ringwald #include "hci_dump_embedded_stdout.h" 20a15efc86SMatthias Ringwald #include "wilc3000_ble_firmware.h" 2158a1b1bbSMatthias Ringwald 2213b8e9b1SMatthias Ringwald // #define USE_XDMAC_FOR_USART 2358a1b1bbSMatthias Ringwald #define XDMA_CH_UART_TX 0 2458a1b1bbSMatthias Ringwald #define XDMA_CH_UART_RX 1 251b2596b5SMatthias Ringwald 2658a1b1bbSMatthias Ringwald /** All interrupt mask. */ 2758a1b1bbSMatthias Ringwald #define ALL_INTERRUPT_MASK 0xffffffff 281b2596b5SMatthias Ringwald 291b2596b5SMatthias Ringwald #ifdef __cplusplus 301b2596b5SMatthias Ringwald extern "C" { 311b2596b5SMatthias Ringwald #endif 3213b8e9b1SMatthias Ringwald 3313b8e9b1SMatthias Ringwald extern int btstack_main(int argc, const char * argv[]); 3413b8e9b1SMatthias Ringwald 3513b8e9b1SMatthias Ringwald static void dummy_handler(void){} 3613b8e9b1SMatthias Ringwald static void (*tick_handler)(void) = &dummy_handler; 3713b8e9b1SMatthias Ringwald 3813b8e9b1SMatthias Ringwald static btstack_uart_config_t uart_config; 3913b8e9b1SMatthias Ringwald 4013b8e9b1SMatthias Ringwald static hci_transport_config_uart_t transport_config = { 4113b8e9b1SMatthias Ringwald HCI_TRANSPORT_CONFIG_UART, 42c4572ab1SMatthias Ringwald 2000000, // directly use high baud rate after config 43cb9ff2fbSMatthias Ringwald 0, // use 0 to skip baud rate change from 115200 to X for debugging purposes 4413b8e9b1SMatthias Ringwald 1, // flow control 4513b8e9b1SMatthias Ringwald NULL, 4613b8e9b1SMatthias Ringwald }; 471b2596b5SMatthias Ringwald 481b2596b5SMatthias Ringwald /** 491b2596b5SMatthias Ringwald * \brief Handler for System Tick interrupt. 501b2596b5SMatthias Ringwald */ 511b2596b5SMatthias Ringwald void SysTick_Handler(void) 521b2596b5SMatthias Ringwald { 5358a1b1bbSMatthias Ringwald tick_handler(); 541b2596b5SMatthias Ringwald } 551b2596b5SMatthias Ringwald 5699e6df5dSMatthias Ringwald // Debug console Output 5799e6df5dSMatthias Ringwald 581b2596b5SMatthias Ringwald /** 591b2596b5SMatthias Ringwald * Configure UART console. 601b2596b5SMatthias Ringwald */ 611b2596b5SMatthias Ringwald // [main_console_configure] 621b2596b5SMatthias Ringwald static void configure_console(void) 631b2596b5SMatthias Ringwald { 641b2596b5SMatthias Ringwald const usart_serial_options_t uart_serial_options = { 651b2596b5SMatthias Ringwald .baudrate = CONF_UART_BAUDRATE, 661b2596b5SMatthias Ringwald #ifdef CONF_UART_CHAR_LENGTH 671b2596b5SMatthias Ringwald .charlength = CONF_UART_CHAR_LENGTH, 681b2596b5SMatthias Ringwald #endif 691b2596b5SMatthias Ringwald .paritytype = CONF_UART_PARITY, 701b2596b5SMatthias Ringwald #ifdef CONF_UART_STOP_BITS 711b2596b5SMatthias Ringwald .stopbits = CONF_UART_STOP_BITS, 721b2596b5SMatthias Ringwald #endif 731b2596b5SMatthias Ringwald }; 741b2596b5SMatthias Ringwald 751b2596b5SMatthias Ringwald /* Configure console UART. */ 761b2596b5SMatthias Ringwald sysclk_enable_peripheral_clock(CONSOLE_UART_ID); 771b2596b5SMatthias Ringwald stdio_serial_init(CONF_UART, &uart_serial_options); 781b2596b5SMatthias Ringwald } 791b2596b5SMatthias Ringwald 8099e6df5dSMatthias Ringwald // Debug console Input 8199e6df5dSMatthias Ringwald 8299e6df5dSMatthias Ringwald #include "btstack_stdin.h" 8399e6df5dSMatthias Ringwald 8499e6df5dSMatthias Ringwald static void (*stdin_handler)(char c); 8599e6df5dSMatthias Ringwald static btstack_data_source_t stdin_data_source; 8699e6df5dSMatthias Ringwald 8799e6df5dSMatthias Ringwald static void btstack_stdin_process(struct btstack_data_source *ds, btstack_data_source_callback_type_t callback_type){ 8899e6df5dSMatthias Ringwald // try to read from console 8999e6df5dSMatthias Ringwald uint32_t stdin_character; 9099e6df5dSMatthias Ringwald uint32_t res = usart_read(CONF_UART, &stdin_character); 9199e6df5dSMatthias Ringwald if (res) return; 9299e6df5dSMatthias Ringwald 9399e6df5dSMatthias Ringwald if (stdin_handler){ 9499e6df5dSMatthias Ringwald (*stdin_handler)(stdin_character & 0xff); 9599e6df5dSMatthias Ringwald } 9699e6df5dSMatthias Ringwald } 9799e6df5dSMatthias Ringwald 9899e6df5dSMatthias Ringwald void btstack_stdin_setup(void (*handler)(char c)){ 9999e6df5dSMatthias Ringwald // set handler 10099e6df5dSMatthias Ringwald stdin_handler = handler; 10199e6df5dSMatthias Ringwald 10299e6df5dSMatthias Ringwald // set up polling data_source 10399e6df5dSMatthias Ringwald btstack_run_loop_set_data_source_handler(&stdin_data_source, &btstack_stdin_process); 10499e6df5dSMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(&stdin_data_source, DATA_SOURCE_CALLBACK_POLL); 10599e6df5dSMatthias Ringwald btstack_run_loop_add_data_source(&stdin_data_source); 10699e6df5dSMatthias Ringwald } 10799e6df5dSMatthias Ringwald 1081b2596b5SMatthias Ringwald // [main_console_configure] 1091b2596b5SMatthias Ringwald 1101b2596b5SMatthias Ringwald /** 11158a1b1bbSMatthias Ringwald * \brief Wait for the given number of milliseconds (ticks 1121b2596b5SMatthias Ringwald * generated by the SAM's microcontrollers's system tick). 1131b2596b5SMatthias Ringwald * 1141b2596b5SMatthias Ringwald * \param ul_dly_ticks Delay to wait for, in milliseconds. 1151b2596b5SMatthias Ringwald */ 1161b2596b5SMatthias Ringwald // [main_ms_delay] 11758a1b1bbSMatthias Ringwald static void mdelay(uint32_t delay_in_ms) 1181b2596b5SMatthias Ringwald { 11958a1b1bbSMatthias Ringwald // delay_ms(delay_in_ms); 12058a1b1bbSMatthias Ringwald uint32_t time_to_wait = btstack_run_loop_get_time_ms() + delay_in_ms; 12158a1b1bbSMatthias Ringwald while (btstack_run_loop_get_time_ms() < time_to_wait); 1221b2596b5SMatthias Ringwald } 1231b2596b5SMatthias Ringwald // [main_ms_delay] 1241b2596b5SMatthias Ringwald 12558a1b1bbSMatthias Ringwald //////////////////////////////////////////////////////////////////////////////// 12658a1b1bbSMatthias Ringwald // hal_cpu.h implementation 12758a1b1bbSMatthias Ringwald //////////////////////////////////////////////////////////////////////////////// 12858a1b1bbSMatthias Ringwald // hal_led.h implementation 12958a1b1bbSMatthias Ringwald #include "hal_led.h" 13058a1b1bbSMatthias Ringwald void hal_led_off(void); 13158a1b1bbSMatthias Ringwald void hal_led_on(void); 13258a1b1bbSMatthias Ringwald 13358a1b1bbSMatthias Ringwald void hal_led_off(void){ 13458a1b1bbSMatthias Ringwald // gpio_set_pin_low(GPIOA, GPIO_LED2); 13558a1b1bbSMatthias Ringwald } 13658a1b1bbSMatthias Ringwald void hal_led_on(void){ 13758a1b1bbSMatthias Ringwald // gpio_set_pin_high(GPIOA, GPIO_LED2); 13858a1b1bbSMatthias Ringwald } 13958a1b1bbSMatthias Ringwald void hal_led_toggle(void){ 14058a1b1bbSMatthias Ringwald // gpio_toggle_pin(GPIOA, GPIO_LED2); 14158a1b1bbSMatthias Ringwald } 14258a1b1bbSMatthias Ringwald 14358a1b1bbSMatthias Ringwald // hal_cpu.h implementation 14458a1b1bbSMatthias Ringwald #include "hal_cpu.h" 14558a1b1bbSMatthias Ringwald 14658a1b1bbSMatthias Ringwald void hal_cpu_disable_irqs(void){ 14758a1b1bbSMatthias Ringwald //__disable_irq(); 14858a1b1bbSMatthias Ringwald } 14958a1b1bbSMatthias Ringwald 15058a1b1bbSMatthias Ringwald void hal_cpu_enable_irqs(void){ 15158a1b1bbSMatthias Ringwald // __enable_irq(); 15258a1b1bbSMatthias Ringwald } 15358a1b1bbSMatthias Ringwald 15458a1b1bbSMatthias Ringwald void hal_cpu_enable_irqs_and_sleep(void){ 15558a1b1bbSMatthias Ringwald hal_led_off(); 15658a1b1bbSMatthias Ringwald // __enable_irq(); 15758a1b1bbSMatthias Ringwald // __asm__("wfe"); // go to sleep if event flag isn't set. if set, just clear it. IRQs set event flag 15858a1b1bbSMatthias Ringwald 15958a1b1bbSMatthias Ringwald // note: hal_uart_needed_during_sleep can be used to disable peripheral clock if it's not needed for a timer 16058a1b1bbSMatthias Ringwald hal_led_on(); 16158a1b1bbSMatthias Ringwald } 16258a1b1bbSMatthias Ringwald 16358a1b1bbSMatthias Ringwald 16458a1b1bbSMatthias Ringwald #ifndef USE_XDMAC_FOR_USART 16558a1b1bbSMatthias Ringwald // RX state 16658a1b1bbSMatthias Ringwald static volatile uint16_t bytes_to_read = 0; 16758a1b1bbSMatthias Ringwald static volatile uint8_t * rx_buffer_ptr = 0; 16858a1b1bbSMatthias Ringwald 16958a1b1bbSMatthias Ringwald // TX state 17058a1b1bbSMatthias Ringwald static volatile uint16_t bytes_to_write = 0; 17158a1b1bbSMatthias Ringwald static volatile uint8_t * tx_buffer_ptr = 0; 17258a1b1bbSMatthias Ringwald #endif 17358a1b1bbSMatthias Ringwald 174c4572ab1SMatthias Ringwald static volatile int rx_notify; 175c4572ab1SMatthias Ringwald static volatile int tx_notify; 176c4572ab1SMatthias Ringwald 177c267d18bSMatthias Ringwald static int simulate_flowcontrol; 178c267d18bSMatthias Ringwald 17958a1b1bbSMatthias Ringwald // handlers 18058a1b1bbSMatthias Ringwald static void (*rx_done_handler)(void) = dummy_handler; 18158a1b1bbSMatthias Ringwald static void (*tx_done_handler)(void) = dummy_handler; 18258a1b1bbSMatthias Ringwald static void (*cts_irq_handler)(void) = dummy_handler; 18358a1b1bbSMatthias Ringwald 18458a1b1bbSMatthias Ringwald // @note While the Atmel SAM S7x data sheet states 18558a1b1bbSMatthias Ringwald // "The hardware handshaking feature enables an out-of-band flow control by automatic management 18658a1b1bbSMatthias Ringwald // of the pins RTS and CTS.", 18758a1b1bbSMatthias Ringwald // I didn't see RTS going up automatically up, ever. So, at least for RTS, the automatic management 18858a1b1bbSMatthias Ringwald // is just a glorified GPIO pin control feature, which provides no benefit, but irritates a lot 18958a1b1bbSMatthias Ringwald 190cb9ff2fbSMatthias Ringwald // J505:6 191cb9ff2fbSMatthias Ringwald #define DEBUG_PIN_1 PIO_PD16_IDX 192cb9ff2fbSMatthias Ringwald // J505:5 193cb9ff2fbSMatthias Ringwald #define DEBUG_PIN_2 PIO_PD15_IDX 194cb9ff2fbSMatthias Ringwald 195c267d18bSMatthias Ringwald static inline void hal_uart_rts_high(void){ 196c267d18bSMatthias Ringwald if (!simulate_flowcontrol) return; 197cb9ff2fbSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_HIGH); 19858a1b1bbSMatthias Ringwald BOARD_USART->US_CR = US_CR_RTSEN; 19958a1b1bbSMatthias Ringwald } 200c267d18bSMatthias Ringwald static inline void hal_uart_rts_low(void){ 201c267d18bSMatthias Ringwald if (!simulate_flowcontrol) return; 202cb9ff2fbSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW); 20358a1b1bbSMatthias Ringwald BOARD_USART->US_CR = US_CR_RTSDIS; 20458a1b1bbSMatthias Ringwald } 20558a1b1bbSMatthias Ringwald 20658a1b1bbSMatthias Ringwald /** 20758a1b1bbSMatthias Ringwald */ 208cb9ff2fbSMatthias Ringwald static int hal_uart_dma_initialized = 0; 20958a1b1bbSMatthias Ringwald void hal_uart_dma_init(void) 21058a1b1bbSMatthias Ringwald { 211cb9ff2fbSMatthias Ringwald if (hal_uart_dma_initialized){ 212cb9ff2fbSMatthias Ringwald log_info("hal_uart_dma_init already initialized"); 213cb9ff2fbSMatthias Ringwald return; 214cb9ff2fbSMatthias Ringwald } 215cb9ff2fbSMatthias Ringwald hal_uart_dma_initialized = 1; 21667422dbdSMatthias Ringwald 21767422dbdSMatthias Ringwald // debug 21867422dbdSMatthias Ringwald #ifdef DEBUG_PIN_1 21967422dbdSMatthias Ringwald ioport_set_pin_dir(DEBUG_PIN_1, IOPORT_DIR_OUTPUT); 22067422dbdSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_LOW); 22167422dbdSMatthias Ringwald #endif 22267422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2 22367422dbdSMatthias Ringwald ioport_set_pin_dir(DEBUG_PIN_2, IOPORT_DIR_OUTPUT); 22467422dbdSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW); 22567422dbdSMatthias Ringwald #endif 22613b8e9b1SMatthias Ringwald // power on 22713b8e9b1SMatthias Ringwald ioport_set_pin_dir(BLUETOOTH_CHP_EN, IOPORT_DIR_OUTPUT); 22813b8e9b1SMatthias Ringwald ioport_set_pin_level(BLUETOOTH_CHP_EN, IOPORT_PIN_LEVEL_HIGH); 22913b8e9b1SMatthias Ringwald 23013b8e9b1SMatthias Ringwald // reset 23113b8e9b1SMatthias Ringwald ioport_set_pin_dir(BLUETOOTH_RESET, IOPORT_DIR_OUTPUT); 23213b8e9b1SMatthias Ringwald ioport_set_pin_level(BLUETOOTH_RESET, IOPORT_PIN_LEVEL_LOW); 23313b8e9b1SMatthias Ringwald mdelay(250); 23413b8e9b1SMatthias Ringwald ioport_set_pin_level(BLUETOOTH_RESET, IOPORT_PIN_LEVEL_HIGH); 23513b8e9b1SMatthias Ringwald mdelay(250); 23613b8e9b1SMatthias Ringwald 23713b8e9b1SMatthias Ringwald /* Enable the peripheral clock in the PMC. */ 23813b8e9b1SMatthias Ringwald sysclk_enable_peripheral_clock(BOARD_ID_USART); 23958a1b1bbSMatthias Ringwald 24058a1b1bbSMatthias Ringwald // configure Bluetooth USART 24158a1b1bbSMatthias Ringwald const sam_usart_opt_t bluetooth_settings = { 24258a1b1bbSMatthias Ringwald 115200, 24358a1b1bbSMatthias Ringwald US_MR_CHRL_8_BIT, 24458a1b1bbSMatthias Ringwald US_MR_PAR_NO, 24558a1b1bbSMatthias Ringwald US_MR_NBSTOP_1_BIT, 24658a1b1bbSMatthias Ringwald US_MR_CHMODE_NORMAL, 24758a1b1bbSMatthias Ringwald /* This field is only used in IrDA mode. */ 24858a1b1bbSMatthias Ringwald 0 24958a1b1bbSMatthias Ringwald }; 25058a1b1bbSMatthias Ringwald 25158a1b1bbSMatthias Ringwald /* Configure USART mode. */ 252c267d18bSMatthias Ringwald simulate_flowcontrol = 0; 25313b8e9b1SMatthias Ringwald usart_init_rs232(BOARD_USART, &bluetooth_settings, sysclk_get_peripheral_hz()); 254c267d18bSMatthias Ringwald // Set RTS = 0 (normal mode) 255c267d18bSMatthias Ringwald BOARD_USART->US_CR = US_CR_RTSEN; 25658a1b1bbSMatthias Ringwald 25758a1b1bbSMatthias Ringwald /* Disable all the interrupts. */ 25858a1b1bbSMatthias Ringwald usart_disable_interrupt(BOARD_USART, ALL_INTERRUPT_MASK); 25958a1b1bbSMatthias Ringwald 26058a1b1bbSMatthias Ringwald /* Enable TX & RX function. */ 26158a1b1bbSMatthias Ringwald usart_enable_tx(BOARD_USART); 26258a1b1bbSMatthias Ringwald usart_enable_rx(BOARD_USART); 26358a1b1bbSMatthias Ringwald 26458a1b1bbSMatthias Ringwald /* Configure and enable interrupt of USART. */ 26558a1b1bbSMatthias Ringwald NVIC_EnableIRQ(USART_IRQn); 26658a1b1bbSMatthias Ringwald 26758a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART 26858a1b1bbSMatthias Ringwald 26958a1b1bbSMatthias Ringwald // setup XDMAC 27058a1b1bbSMatthias Ringwald 27158a1b1bbSMatthias Ringwald /* Initialize and enable DMA controller */ 27258a1b1bbSMatthias Ringwald pmc_enable_periph_clk(ID_XDMAC); 27358a1b1bbSMatthias Ringwald 27458a1b1bbSMatthias Ringwald /* Enable XDMA interrupt */ 27558a1b1bbSMatthias Ringwald NVIC_ClearPendingIRQ(XDMAC_IRQn); 27658a1b1bbSMatthias Ringwald NVIC_SetPriority( XDMAC_IRQn ,1); 27758a1b1bbSMatthias Ringwald NVIC_EnableIRQ(XDMAC_IRQn); 27858a1b1bbSMatthias Ringwald 27958a1b1bbSMatthias Ringwald // Setup XDMA Channel for USART TX 28058a1b1bbSMatthias Ringwald xdmac_channel_set_destination_addr(XDMAC, XDMA_CH_UART_TX, (uint32_t)&BOARD_USART->US_THR); 28158a1b1bbSMatthias Ringwald xdmac_channel_set_config(XDMAC, XDMA_CH_UART_TX, 28258a1b1bbSMatthias Ringwald XDMAC_CC_TYPE_PER_TRAN | 28358a1b1bbSMatthias Ringwald XDMAC_CC_DSYNC_MEM2PER | 28458a1b1bbSMatthias Ringwald XDMAC_CC_MEMSET_NORMAL_MODE | 28558a1b1bbSMatthias Ringwald XDMAC_CC_MBSIZE_SINGLE | 28658a1b1bbSMatthias Ringwald XDMAC_CC_DWIDTH_BYTE | 28758a1b1bbSMatthias Ringwald XDMAC_CC_SIF_AHB_IF0 | 28858a1b1bbSMatthias Ringwald XDMAC_CC_DIF_AHB_IF1 | 28958a1b1bbSMatthias Ringwald XDMAC_CC_SAM_INCREMENTED_AM | 29058a1b1bbSMatthias Ringwald XDMAC_CC_DAM_FIXED_AM | 29158a1b1bbSMatthias Ringwald XDMAC_CC_CSIZE_CHK_1 | 29258a1b1bbSMatthias Ringwald XDMAC_CC_PERID(XDAMC_CHANNEL_HWID_USART0_TX) 29358a1b1bbSMatthias Ringwald ); 29458a1b1bbSMatthias Ringwald xdmac_channel_set_descriptor_control(XDMAC, XDMA_CH_UART_TX, 0); 29558a1b1bbSMatthias Ringwald xdmac_channel_set_source_microblock_stride(XDMAC, XDMA_CH_UART_TX, 0); 29658a1b1bbSMatthias Ringwald xdmac_channel_set_destination_microblock_stride(XDMAC, XDMA_CH_UART_TX, 0); 29758a1b1bbSMatthias Ringwald xdmac_channel_set_datastride_mempattern(XDMAC, XDMA_CH_UART_TX, 0); 29858a1b1bbSMatthias Ringwald xdmac_channel_set_block_control(XDMAC, XDMA_CH_UART_TX, 0); 29958a1b1bbSMatthias Ringwald xdmac_enable_interrupt(XDMAC, XDMA_CH_UART_TX); 30058a1b1bbSMatthias Ringwald xdmac_channel_enable_interrupt(XDMAC, XDMA_CH_UART_TX, XDMAC_CIE_BIE); 30158a1b1bbSMatthias Ringwald 30258a1b1bbSMatthias Ringwald // Setup XDMA Channel for USART RX 30358a1b1bbSMatthias Ringwald xdmac_channel_set_source_addr(XDMAC, XDMA_CH_UART_RX, (uint32_t)&BOARD_USART->US_RHR); 30458a1b1bbSMatthias Ringwald xdmac_channel_set_config(XDMAC, XDMA_CH_UART_RX, 30558a1b1bbSMatthias Ringwald XDMAC_CC_TYPE_PER_TRAN | 30658a1b1bbSMatthias Ringwald XDMAC_CC_DSYNC_PER2MEM | 30758a1b1bbSMatthias Ringwald XDMAC_CC_MEMSET_NORMAL_MODE | 30858a1b1bbSMatthias Ringwald XDMAC_CC_MBSIZE_SINGLE | 30958a1b1bbSMatthias Ringwald XDMAC_CC_DWIDTH_BYTE | 31058a1b1bbSMatthias Ringwald XDMAC_CC_SIF_AHB_IF1 | 31158a1b1bbSMatthias Ringwald XDMAC_CC_DIF_AHB_IF0 | 31258a1b1bbSMatthias Ringwald XDMAC_CC_SAM_FIXED_AM | 31358a1b1bbSMatthias Ringwald XDMAC_CC_DAM_INCREMENTED_AM | 31458a1b1bbSMatthias Ringwald XDMAC_CC_CSIZE_CHK_1 | 31558a1b1bbSMatthias Ringwald XDMAC_CC_PERID(XDAMC_CHANNEL_HWID_USART0_RX) 31658a1b1bbSMatthias Ringwald ); 31758a1b1bbSMatthias Ringwald xdmac_channel_set_descriptor_control(XDMAC, XDMA_CH_UART_RX, 0); 31858a1b1bbSMatthias Ringwald xdmac_channel_set_source_microblock_stride(XDMAC, XDMA_CH_UART_RX, 0); 31958a1b1bbSMatthias Ringwald xdmac_channel_set_destination_microblock_stride(XDMAC, XDMA_CH_UART_RX, 0); 32058a1b1bbSMatthias Ringwald xdmac_channel_set_datastride_mempattern(XDMAC, XDMA_CH_UART_RX, 0); 32158a1b1bbSMatthias Ringwald xdmac_channel_set_block_control(XDMAC, XDMA_CH_UART_RX, 0); 32258a1b1bbSMatthias Ringwald xdmac_enable_interrupt(XDMAC, XDMA_CH_UART_RX); 32358a1b1bbSMatthias Ringwald xdmac_channel_enable_interrupt(XDMAC, XDMA_CH_UART_RX, XDMAC_CIE_BIE); 32458a1b1bbSMatthias Ringwald #endif 32558a1b1bbSMatthias Ringwald } 32658a1b1bbSMatthias Ringwald 32758a1b1bbSMatthias Ringwald void hal_uart_dma_set_sleep(uint8_t sleep){ 32858a1b1bbSMatthias Ringwald } 32958a1b1bbSMatthias Ringwald 33058a1b1bbSMatthias Ringwald void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){ 33158a1b1bbSMatthias Ringwald rx_done_handler = the_block_handler; 33258a1b1bbSMatthias Ringwald } 33358a1b1bbSMatthias Ringwald 33458a1b1bbSMatthias Ringwald void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){ 33558a1b1bbSMatthias Ringwald tx_done_handler = the_block_handler; 33658a1b1bbSMatthias Ringwald } 33758a1b1bbSMatthias Ringwald 33858a1b1bbSMatthias Ringwald void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){ 33958a1b1bbSMatthias Ringwald cts_irq_handler = the_irq_handler; 34058a1b1bbSMatthias Ringwald } 34158a1b1bbSMatthias Ringwald 34258a1b1bbSMatthias Ringwald int hal_uart_dma_set_baud(uint32_t baud){ 34358a1b1bbSMatthias Ringwald /* Disable TX & RX function. */ 34458a1b1bbSMatthias Ringwald usart_disable_tx(BOARD_USART); 34558a1b1bbSMatthias Ringwald usart_disable_rx(BOARD_USART); 34658a1b1bbSMatthias Ringwald uint32_t res = usart_set_async_baudrate(BOARD_USART, baud, sysclk_get_peripheral_hz()); 34758a1b1bbSMatthias Ringwald if (res){ 34858a1b1bbSMatthias Ringwald log_error("hal_uart_dma_set_baud library call failed"); 34958a1b1bbSMatthias Ringwald } 35058a1b1bbSMatthias Ringwald 35158a1b1bbSMatthias Ringwald /* Enable TX & RX function. */ 35258a1b1bbSMatthias Ringwald usart_enable_tx(BOARD_USART); 35358a1b1bbSMatthias Ringwald usart_enable_rx(BOARD_USART); 35458a1b1bbSMatthias Ringwald 35513b8e9b1SMatthias Ringwald log_info("set baud rate %u", (int) baud); 35613b8e9b1SMatthias Ringwald return 0; 35713b8e9b1SMatthias Ringwald } 35858a1b1bbSMatthias Ringwald 359c267d18bSMatthias Ringwald int hal_uart_dma_set_flowcontrol(int flowcontrol){ 360cb9ff2fbSMatthias Ringwald log_info("hal_uart_dma_set_flowcontrol %u", flowcontrol); 361c267d18bSMatthias Ringwald simulate_flowcontrol = flowcontrol; 362c267d18bSMatthias Ringwald if (flowcontrol){ 363c267d18bSMatthias Ringwald /* Set hardware handshaking mode. */ 364c267d18bSMatthias Ringwald BOARD_USART->US_MR = (BOARD_USART->US_MR & ~US_MR_USART_MODE_Msk) | US_MR_USART_MODE_HW_HANDSHAKING; 365cb9ff2fbSMatthias Ringwald hal_uart_rts_high(); 366c267d18bSMatthias Ringwald } else { 367c267d18bSMatthias Ringwald /* Set nomal mode. */ 368c267d18bSMatthias Ringwald BOARD_USART->US_MR = (BOARD_USART->US_MR & ~US_MR_USART_MODE_Msk) | US_MR_USART_MODE_NORMAL; 369c267d18bSMatthias Ringwald // Set RTS = 0 (normal mode) 370c267d18bSMatthias Ringwald BOARD_USART->US_CR = US_CR_RTSEN; 371c267d18bSMatthias Ringwald } 37258a1b1bbSMatthias Ringwald return 0; 37358a1b1bbSMatthias Ringwald } 37458a1b1bbSMatthias Ringwald 37558a1b1bbSMatthias Ringwald void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){ 37667422dbdSMatthias Ringwald 37767422dbdSMatthias Ringwald tx_notify = 1; 37867422dbdSMatthias Ringwald 37958a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART 38058a1b1bbSMatthias Ringwald xdmac_channel_get_interrupt_status( XDMAC, XDMA_CH_UART_TX); 38158a1b1bbSMatthias Ringwald xdmac_channel_set_source_addr(XDMAC, XDMA_CH_UART_TX, (uint32_t)data); 38258a1b1bbSMatthias Ringwald xdmac_channel_set_microblock_control(XDMAC, XDMA_CH_UART_TX, size); 38358a1b1bbSMatthias Ringwald xdmac_channel_enable(XDMAC, XDMA_CH_UART_TX); 38458a1b1bbSMatthias Ringwald #else 38567422dbdSMatthias Ringwald if (bytes_to_write){ 38667422dbdSMatthias Ringwald log_error("send block, bytes to write %u", bytes_to_write); 38767422dbdSMatthias Ringwald return; 38867422dbdSMatthias Ringwald } 38958a1b1bbSMatthias Ringwald tx_buffer_ptr = (uint8_t *) data; 39058a1b1bbSMatthias Ringwald bytes_to_write = size; 39158a1b1bbSMatthias Ringwald usart_enable_interrupt(BOARD_USART, US_IER_TXRDY); 39258a1b1bbSMatthias Ringwald #endif 39358a1b1bbSMatthias Ringwald } 39458a1b1bbSMatthias Ringwald 39558a1b1bbSMatthias Ringwald void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){ 39658a1b1bbSMatthias Ringwald 397cb9ff2fbSMatthias Ringwald #ifdef DEBUG_PIN_1 398cb9ff2fbSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_HIGH); 399cb9ff2fbSMatthias Ringwald #endif 400cb9ff2fbSMatthias Ringwald 40158a1b1bbSMatthias Ringwald hal_uart_rts_low(); 40258a1b1bbSMatthias Ringwald 403cb9ff2fbSMatthias Ringwald rx_notify = 1; 404cb9ff2fbSMatthias Ringwald 40558a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART 40658a1b1bbSMatthias Ringwald xdmac_channel_get_interrupt_status( XDMAC, XDMA_CH_UART_RX); 40758a1b1bbSMatthias Ringwald xdmac_channel_set_destination_addr(XDMAC, XDMA_CH_UART_RX, (uint32_t)data); 40858a1b1bbSMatthias Ringwald xdmac_channel_set_microblock_control(XDMAC, XDMA_CH_UART_RX, size); 40958a1b1bbSMatthias Ringwald xdmac_channel_enable(XDMAC, XDMA_CH_UART_RX); 41058a1b1bbSMatthias Ringwald #else 41158a1b1bbSMatthias Ringwald rx_buffer_ptr = data; 41258a1b1bbSMatthias Ringwald bytes_to_read = size; 41358a1b1bbSMatthias Ringwald usart_enable_interrupt(BOARD_USART, US_IER_RXRDY); 41458a1b1bbSMatthias Ringwald #endif 41558a1b1bbSMatthias Ringwald } 41658a1b1bbSMatthias Ringwald 41758a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART 41858a1b1bbSMatthias Ringwald void XDMAC_Handler(void) 41958a1b1bbSMatthias Ringwald { 42058a1b1bbSMatthias Ringwald uint32_t dma_status; 42158a1b1bbSMatthias Ringwald dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH_UART_TX); 42258a1b1bbSMatthias Ringwald if (dma_status & XDMAC_CIS_BIS) { 42367422dbdSMatthias Ringwald if (tx_notify){ 42467422dbdSMatthias Ringwald tx_notify = 0; 42558a1b1bbSMatthias Ringwald tx_done_handler(); 42658a1b1bbSMatthias Ringwald } 42767422dbdSMatthias Ringwald } 42858a1b1bbSMatthias Ringwald dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH_UART_RX); 42958a1b1bbSMatthias Ringwald if (dma_status & XDMAC_CIS_BIS) { 43058a1b1bbSMatthias Ringwald hal_uart_rts_high(); 431cb9ff2fbSMatthias Ringwald if (rx_notify){ 432cb9ff2fbSMatthias Ringwald rx_notify = 0; 43358a1b1bbSMatthias Ringwald rx_done_handler(); 43458a1b1bbSMatthias Ringwald } 43558a1b1bbSMatthias Ringwald } 436cb9ff2fbSMatthias Ringwald } 43758a1b1bbSMatthias Ringwald #else 43858a1b1bbSMatthias Ringwald void USART_Handler(void) 43958a1b1bbSMatthias Ringwald { 44067422dbdSMatthias Ringwald 44167422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2 442cb9ff2fbSMatthias Ringwald // ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_HIGH); 44367422dbdSMatthias Ringwald #endif 44458a1b1bbSMatthias Ringwald 44558a1b1bbSMatthias Ringwald /* Read USART status. */ 44667422dbdSMatthias Ringwald uint32_t ul_status = usart_get_status(BOARD_USART); 44758a1b1bbSMatthias Ringwald 44858a1b1bbSMatthias Ringwald // handle ready to send 44958a1b1bbSMatthias Ringwald if(ul_status & US_IER_TXRDY) { 45058a1b1bbSMatthias Ringwald if (bytes_to_write){ 45158a1b1bbSMatthias Ringwald // send next byte 45258a1b1bbSMatthias Ringwald usart_write(BOARD_USART, *tx_buffer_ptr); 45358a1b1bbSMatthias Ringwald tx_buffer_ptr++; 45458a1b1bbSMatthias Ringwald bytes_to_write--; 45558a1b1bbSMatthias Ringwald } else { 45667422dbdSMatthias Ringwald 45758a1b1bbSMatthias Ringwald // done. disable tx ready interrupt to avoid starvation here 45858a1b1bbSMatthias Ringwald usart_disable_interrupt(BOARD_USART, US_IER_TXRDY); 45967422dbdSMatthias Ringwald if (tx_notify){ 46067422dbdSMatthias Ringwald tx_notify = 0; 46158a1b1bbSMatthias Ringwald tx_done_handler(); 46258a1b1bbSMatthias Ringwald } 46358a1b1bbSMatthias Ringwald } 46467422dbdSMatthias Ringwald } 46558a1b1bbSMatthias Ringwald 46658a1b1bbSMatthias Ringwald // handle byte available for read 46758a1b1bbSMatthias Ringwald if (ul_status & US_IER_RXRDY) { 4685c5e4857SMatthias Ringwald if (bytes_to_read){ 46958a1b1bbSMatthias Ringwald uint32_t ch; 47058a1b1bbSMatthias Ringwald usart_read(BOARD_USART, (uint32_t *)&ch); 47158a1b1bbSMatthias Ringwald *rx_buffer_ptr++ = ch; 47258a1b1bbSMatthias Ringwald bytes_to_read--; 47358a1b1bbSMatthias Ringwald if (bytes_to_read == 0){ 474cb9ff2fbSMatthias Ringwald 475cb9ff2fbSMatthias Ringwald #ifdef DEBUG_PIN_1 476cb9ff2fbSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_LOW); 477cb9ff2fbSMatthias Ringwald #endif 478cb9ff2fbSMatthias Ringwald 47958a1b1bbSMatthias Ringwald // done. disable rx ready interrupt, raise RTS 48058a1b1bbSMatthias Ringwald hal_uart_rts_high(); 48158a1b1bbSMatthias Ringwald usart_disable_interrupt(BOARD_USART, US_IER_RXRDY); 482cb9ff2fbSMatthias Ringwald if (rx_notify){ 483cb9ff2fbSMatthias Ringwald rx_notify = 0; 48458a1b1bbSMatthias Ringwald rx_done_handler(); 48558a1b1bbSMatthias Ringwald } 486cb9ff2fbSMatthias Ringwald } 4875c5e4857SMatthias Ringwald } else { 4885c5e4857SMatthias Ringwald // shoult not happen, disable irq anyway 4895c5e4857SMatthias Ringwald usart_disable_interrupt(BOARD_USART, US_IER_RXRDY); 4905c5e4857SMatthias Ringwald } 49158a1b1bbSMatthias Ringwald } 49267422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2 493cb9ff2fbSMatthias Ringwald // ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW); 49467422dbdSMatthias Ringwald #endif 49567422dbdSMatthias Ringwald 49658a1b1bbSMatthias Ringwald } 49758a1b1bbSMatthias Ringwald #endif 49858a1b1bbSMatthias Ringwald 49958a1b1bbSMatthias Ringwald void hal_tick_init() 50058a1b1bbSMatthias Ringwald { 50158a1b1bbSMatthias Ringwald /* Configure systick for 1 ms */ 50258a1b1bbSMatthias Ringwald puts("Configure system tick to get 1ms tick period.\r"); 50358a1b1bbSMatthias Ringwald if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) { 50458a1b1bbSMatthias Ringwald puts("-F- Systick configuration error\r"); 50558a1b1bbSMatthias Ringwald while (1); 50658a1b1bbSMatthias Ringwald } 50758a1b1bbSMatthias Ringwald } 50858a1b1bbSMatthias Ringwald 50958a1b1bbSMatthias Ringwald void hal_tick_set_handler(void (*handler)(void)){ 51058a1b1bbSMatthias Ringwald if (handler == NULL){ 51158a1b1bbSMatthias Ringwald tick_handler = &dummy_handler; 51258a1b1bbSMatthias Ringwald return; 51358a1b1bbSMatthias Ringwald } 51458a1b1bbSMatthias Ringwald tick_handler = handler; 51558a1b1bbSMatthias Ringwald } 51658a1b1bbSMatthias Ringwald 51758a1b1bbSMatthias Ringwald int hal_tick_get_tick_period_in_ms(void){ 51858a1b1bbSMatthias Ringwald return 1; 51958a1b1bbSMatthias Ringwald } 52058a1b1bbSMatthias Ringwald 52113b8e9b1SMatthias Ringwald static const btstack_uart_block_t * uart_driver; 52213b8e9b1SMatthias Ringwald 52313b8e9b1SMatthias Ringwald static void phase2(int status){ 52413b8e9b1SMatthias Ringwald 52513b8e9b1SMatthias Ringwald if (status){ 52613b8e9b1SMatthias Ringwald printf("Download firmware failed\n"); 52713b8e9b1SMatthias Ringwald return; 52813b8e9b1SMatthias Ringwald } 52913b8e9b1SMatthias Ringwald 53013b8e9b1SMatthias Ringwald printf("Phase 2: Main app\n"); 53113b8e9b1SMatthias Ringwald 53213b8e9b1SMatthias Ringwald // init HCI 53313b8e9b1SMatthias Ringwald const hci_transport_t * transport = hci_transport_h4_instance(uart_driver); 53413b8e9b1SMatthias Ringwald hci_init(transport, (void*) &transport_config); 53513b8e9b1SMatthias Ringwald hci_set_chipset(btstack_chipset_atwilc3000_instance()); 53613b8e9b1SMatthias Ringwald 53713b8e9b1SMatthias Ringwald // setup app 53813b8e9b1SMatthias Ringwald btstack_main(0, NULL); 53913b8e9b1SMatthias Ringwald } 54058a1b1bbSMatthias Ringwald 5411b2596b5SMatthias Ringwald /** 5421b2596b5SMatthias Ringwald * \brief getting-started Application entry point. 5431b2596b5SMatthias Ringwald * 5441b2596b5SMatthias Ringwald * \return Unused (ANSI-C compatibility). 5451b2596b5SMatthias Ringwald */ 5461b2596b5SMatthias Ringwald // [main] 5471b2596b5SMatthias Ringwald int main(void) 5481b2596b5SMatthias Ringwald { 5491b2596b5SMatthias Ringwald /* Initialize the SAM system */ 5501b2596b5SMatthias Ringwald sysclk_init(); 5511b2596b5SMatthias Ringwald board_init(); 5521b2596b5SMatthias Ringwald 5531b2596b5SMatthias Ringwald /* Initialize the console uart */ 5541b2596b5SMatthias Ringwald configure_console(); 5551b2596b5SMatthias Ringwald 55613b8e9b1SMatthias Ringwald /* Output boot info */ 55713b8e9b1SMatthias Ringwald printf("BTstack on SAMV71 Xplained Ultra with ATWILC3000\n"); 55858a1b1bbSMatthias Ringwald printf("CPU %lu hz, peripheral clock %lu hz\n", sysclk_get_cpu_hz(), sysclk_get_peripheral_hz()); 55913b8e9b1SMatthias Ringwald #ifdef USE_XDMAC_FOR_USART 56013b8e9b1SMatthias Ringwald printf("Using XDMA for Bluetooth UART\n"); 56113b8e9b1SMatthias Ringwald #else 56213b8e9b1SMatthias Ringwald printf("Using IRQ driver for Bluetooth UART\n"); 56313b8e9b1SMatthias Ringwald #endif 56413b8e9b1SMatthias Ringwald printf("--\n"); 56558a1b1bbSMatthias Ringwald 56658a1b1bbSMatthias Ringwald // start with BTstack init - especially configure HCI Transport 56758a1b1bbSMatthias Ringwald btstack_memory_init(); 56858a1b1bbSMatthias Ringwald btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); 56958a1b1bbSMatthias Ringwald 57058a1b1bbSMatthias Ringwald // enable full log output while porting 571*25d9a2cdSMatthias Ringwald // hci_dump_init(hci_dump_embedded_stdout_get_instance()); 57258a1b1bbSMatthias Ringwald 57313b8e9b1SMatthias Ringwald // setup UART HAL + Run Loop integration 57413b8e9b1SMatthias Ringwald uart_driver = btstack_uart_block_embedded_instance(); 57558a1b1bbSMatthias Ringwald 5766e0d5aedSMatthias Ringwald // extract UART config from transport config, but disable flow control and use default baudrate 5776e0d5aedSMatthias Ringwald uart_config.baudrate = HCI_DEFAULT_BAUDRATE; 57813b8e9b1SMatthias Ringwald uart_config.flowcontrol = 0; 57913b8e9b1SMatthias Ringwald uart_config.device_name = transport_config.device_name; 58013b8e9b1SMatthias Ringwald uart_driver->init(&uart_config); 58158a1b1bbSMatthias Ringwald 58213b8e9b1SMatthias Ringwald // phase #1 download firmware 58313b8e9b1SMatthias Ringwald printf("Phase 1: Download firmware\n"); 58413b8e9b1SMatthias Ringwald 58513b8e9b1SMatthias Ringwald // phase #2 start main app 586a15efc86SMatthias Ringwald btstack_chipset_atwilc3000_download_firmware(uart_driver, transport_config.baudrate_init, transport_config.flowcontrol, (const uint8_t *) firmware_ble, sizeof(firmware_ble), &phase2); 58758a1b1bbSMatthias Ringwald 58858a1b1bbSMatthias Ringwald // go 58958a1b1bbSMatthias Ringwald btstack_run_loop_execute(); 59058a1b1bbSMatthias Ringwald 59158a1b1bbSMatthias Ringwald // compiler happy 5921b2596b5SMatthias Ringwald while(1); 5931b2596b5SMatthias Ringwald } 5941b2596b5SMatthias Ringwald #ifdef __cplusplus 5951b2596b5SMatthias Ringwald } 5961b2596b5SMatthias Ringwald #endif 597