1*bc6a318fSMatthias 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"
1925d9a2cdSMatthias Ringwald #include "hci_dump_embedded_stdout.h"
20c8dfe071SMatthias Ringwald #include "hci_transport.h"
21c8dfe071SMatthias Ringwald #include "hci_transport_h4.h"
22a15efc86SMatthias Ringwald #include "wilc3000_ble_firmware.h"
2358a1b1bbSMatthias Ringwald
2413b8e9b1SMatthias Ringwald // #define USE_XDMAC_FOR_USART
2558a1b1bbSMatthias Ringwald #define XDMA_CH_UART_TX 0
2658a1b1bbSMatthias Ringwald #define XDMA_CH_UART_RX 1
271b2596b5SMatthias Ringwald
2858a1b1bbSMatthias Ringwald /** All interrupt mask. */
2958a1b1bbSMatthias Ringwald #define ALL_INTERRUPT_MASK 0xffffffff
301b2596b5SMatthias Ringwald
311b2596b5SMatthias Ringwald #ifdef __cplusplus
321b2596b5SMatthias Ringwald extern "C" {
331b2596b5SMatthias Ringwald #endif
3413b8e9b1SMatthias Ringwald
3513b8e9b1SMatthias Ringwald extern int btstack_main(int argc, const char * argv[]);
3613b8e9b1SMatthias Ringwald
dummy_handler(void)3713b8e9b1SMatthias Ringwald static void dummy_handler(void){}
3813b8e9b1SMatthias Ringwald static void (*tick_handler)(void) = &dummy_handler;
3913b8e9b1SMatthias Ringwald
4013b8e9b1SMatthias Ringwald static btstack_uart_config_t uart_config;
4113b8e9b1SMatthias Ringwald
4213b8e9b1SMatthias Ringwald static hci_transport_config_uart_t transport_config = {
4313b8e9b1SMatthias Ringwald HCI_TRANSPORT_CONFIG_UART,
44c4572ab1SMatthias Ringwald 2000000, // directly use high baud rate after config
45cb9ff2fbSMatthias Ringwald 0, // use 0 to skip baud rate change from 115200 to X for debugging purposes
4613b8e9b1SMatthias Ringwald 1, // flow control
4713b8e9b1SMatthias Ringwald NULL,
4813b8e9b1SMatthias Ringwald };
491b2596b5SMatthias Ringwald
501b2596b5SMatthias Ringwald /**
511b2596b5SMatthias Ringwald * \brief Handler for System Tick interrupt.
521b2596b5SMatthias Ringwald */
SysTick_Handler(void)531b2596b5SMatthias Ringwald void SysTick_Handler(void)
541b2596b5SMatthias Ringwald {
5558a1b1bbSMatthias Ringwald tick_handler();
561b2596b5SMatthias Ringwald }
571b2596b5SMatthias Ringwald
5899e6df5dSMatthias Ringwald // Debug console Output
5999e6df5dSMatthias Ringwald
601b2596b5SMatthias Ringwald /**
611b2596b5SMatthias Ringwald * Configure UART console.
621b2596b5SMatthias Ringwald */
631b2596b5SMatthias Ringwald // [main_console_configure]
configure_console(void)641b2596b5SMatthias Ringwald static void configure_console(void)
651b2596b5SMatthias Ringwald {
661b2596b5SMatthias Ringwald const usart_serial_options_t uart_serial_options = {
671b2596b5SMatthias Ringwald .baudrate = CONF_UART_BAUDRATE,
681b2596b5SMatthias Ringwald #ifdef CONF_UART_CHAR_LENGTH
691b2596b5SMatthias Ringwald .charlength = CONF_UART_CHAR_LENGTH,
701b2596b5SMatthias Ringwald #endif
711b2596b5SMatthias Ringwald .paritytype = CONF_UART_PARITY,
721b2596b5SMatthias Ringwald #ifdef CONF_UART_STOP_BITS
731b2596b5SMatthias Ringwald .stopbits = CONF_UART_STOP_BITS,
741b2596b5SMatthias Ringwald #endif
751b2596b5SMatthias Ringwald };
761b2596b5SMatthias Ringwald
771b2596b5SMatthias Ringwald /* Configure console UART. */
781b2596b5SMatthias Ringwald sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
791b2596b5SMatthias Ringwald stdio_serial_init(CONF_UART, &uart_serial_options);
801b2596b5SMatthias Ringwald }
811b2596b5SMatthias Ringwald
8299e6df5dSMatthias Ringwald // Debug console Input
8399e6df5dSMatthias Ringwald
8499e6df5dSMatthias Ringwald #include "btstack_stdin.h"
8599e6df5dSMatthias Ringwald
8699e6df5dSMatthias Ringwald static void (*stdin_handler)(char c);
8799e6df5dSMatthias Ringwald static btstack_data_source_t stdin_data_source;
8899e6df5dSMatthias Ringwald
btstack_stdin_process(struct btstack_data_source * ds,btstack_data_source_callback_type_t callback_type)8999e6df5dSMatthias Ringwald static void btstack_stdin_process(struct btstack_data_source *ds, btstack_data_source_callback_type_t callback_type){
9099e6df5dSMatthias Ringwald // try to read from console
9199e6df5dSMatthias Ringwald uint32_t stdin_character;
9299e6df5dSMatthias Ringwald uint32_t res = usart_read(CONF_UART, &stdin_character);
9399e6df5dSMatthias Ringwald if (res) return;
9499e6df5dSMatthias Ringwald
9599e6df5dSMatthias Ringwald if (stdin_handler){
9699e6df5dSMatthias Ringwald (*stdin_handler)(stdin_character & 0xff);
9799e6df5dSMatthias Ringwald }
9899e6df5dSMatthias Ringwald }
9999e6df5dSMatthias Ringwald
btstack_stdin_setup(void (* handler)(char c))10099e6df5dSMatthias Ringwald void btstack_stdin_setup(void (*handler)(char c)){
10199e6df5dSMatthias Ringwald // set handler
10299e6df5dSMatthias Ringwald stdin_handler = handler;
10399e6df5dSMatthias Ringwald
10499e6df5dSMatthias Ringwald // set up polling data_source
10599e6df5dSMatthias Ringwald btstack_run_loop_set_data_source_handler(&stdin_data_source, &btstack_stdin_process);
10699e6df5dSMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(&stdin_data_source, DATA_SOURCE_CALLBACK_POLL);
10799e6df5dSMatthias Ringwald btstack_run_loop_add_data_source(&stdin_data_source);
10899e6df5dSMatthias Ringwald }
10999e6df5dSMatthias Ringwald
1101b2596b5SMatthias Ringwald // [main_console_configure]
1111b2596b5SMatthias Ringwald
1121b2596b5SMatthias Ringwald /**
11358a1b1bbSMatthias Ringwald * \brief Wait for the given number of milliseconds (ticks
1141b2596b5SMatthias Ringwald * generated by the SAM's microcontrollers's system tick).
1151b2596b5SMatthias Ringwald *
1161b2596b5SMatthias Ringwald * \param ul_dly_ticks Delay to wait for, in milliseconds.
1171b2596b5SMatthias Ringwald */
1181b2596b5SMatthias Ringwald // [main_ms_delay]
mdelay(uint32_t delay_in_ms)11958a1b1bbSMatthias Ringwald static void mdelay(uint32_t delay_in_ms)
1201b2596b5SMatthias Ringwald {
12158a1b1bbSMatthias Ringwald // delay_ms(delay_in_ms);
12258a1b1bbSMatthias Ringwald uint32_t time_to_wait = btstack_run_loop_get_time_ms() + delay_in_ms;
12358a1b1bbSMatthias Ringwald while (btstack_run_loop_get_time_ms() < time_to_wait);
1241b2596b5SMatthias Ringwald }
1251b2596b5SMatthias Ringwald // [main_ms_delay]
1261b2596b5SMatthias Ringwald
12758a1b1bbSMatthias Ringwald ////////////////////////////////////////////////////////////////////////////////
12858a1b1bbSMatthias Ringwald // hal_cpu.h implementation
12958a1b1bbSMatthias Ringwald ////////////////////////////////////////////////////////////////////////////////
13058a1b1bbSMatthias Ringwald // hal_led.h implementation
13158a1b1bbSMatthias Ringwald #include "hal_led.h"
13258a1b1bbSMatthias Ringwald void hal_led_off(void);
13358a1b1bbSMatthias Ringwald void hal_led_on(void);
13458a1b1bbSMatthias Ringwald
hal_led_off(void)13558a1b1bbSMatthias Ringwald void hal_led_off(void){
13658a1b1bbSMatthias Ringwald // gpio_set_pin_low(GPIOA, GPIO_LED2);
13758a1b1bbSMatthias Ringwald }
hal_led_on(void)13858a1b1bbSMatthias Ringwald void hal_led_on(void){
13958a1b1bbSMatthias Ringwald // gpio_set_pin_high(GPIOA, GPIO_LED2);
14058a1b1bbSMatthias Ringwald }
hal_led_toggle(void)14158a1b1bbSMatthias Ringwald void hal_led_toggle(void){
14258a1b1bbSMatthias Ringwald // gpio_toggle_pin(GPIOA, GPIO_LED2);
14358a1b1bbSMatthias Ringwald }
14458a1b1bbSMatthias Ringwald
14558a1b1bbSMatthias Ringwald // hal_cpu.h implementation
14658a1b1bbSMatthias Ringwald #include "hal_cpu.h"
14758a1b1bbSMatthias Ringwald
hal_cpu_disable_irqs(void)14858a1b1bbSMatthias Ringwald void hal_cpu_disable_irqs(void){
14958a1b1bbSMatthias Ringwald //__disable_irq();
15058a1b1bbSMatthias Ringwald }
15158a1b1bbSMatthias Ringwald
hal_cpu_enable_irqs(void)15258a1b1bbSMatthias Ringwald void hal_cpu_enable_irqs(void){
15358a1b1bbSMatthias Ringwald // __enable_irq();
15458a1b1bbSMatthias Ringwald }
15558a1b1bbSMatthias Ringwald
hal_cpu_enable_irqs_and_sleep(void)15658a1b1bbSMatthias Ringwald void hal_cpu_enable_irqs_and_sleep(void){
15758a1b1bbSMatthias Ringwald hal_led_off();
15858a1b1bbSMatthias Ringwald // __enable_irq();
15958a1b1bbSMatthias Ringwald // __asm__("wfe"); // go to sleep if event flag isn't set. if set, just clear it. IRQs set event flag
16058a1b1bbSMatthias Ringwald
16158a1b1bbSMatthias Ringwald // note: hal_uart_needed_during_sleep can be used to disable peripheral clock if it's not needed for a timer
16258a1b1bbSMatthias Ringwald hal_led_on();
16358a1b1bbSMatthias Ringwald }
16458a1b1bbSMatthias Ringwald
16558a1b1bbSMatthias Ringwald
16658a1b1bbSMatthias Ringwald #ifndef USE_XDMAC_FOR_USART
16758a1b1bbSMatthias Ringwald // RX state
16858a1b1bbSMatthias Ringwald static volatile uint16_t bytes_to_read = 0;
16958a1b1bbSMatthias Ringwald static volatile uint8_t * rx_buffer_ptr = 0;
17058a1b1bbSMatthias Ringwald
17158a1b1bbSMatthias Ringwald // TX state
17258a1b1bbSMatthias Ringwald static volatile uint16_t bytes_to_write = 0;
17358a1b1bbSMatthias Ringwald static volatile uint8_t * tx_buffer_ptr = 0;
17458a1b1bbSMatthias Ringwald #endif
17558a1b1bbSMatthias Ringwald
176c4572ab1SMatthias Ringwald static volatile int rx_notify;
177c4572ab1SMatthias Ringwald static volatile int tx_notify;
178c4572ab1SMatthias Ringwald
179c267d18bSMatthias Ringwald static int simulate_flowcontrol;
180c267d18bSMatthias Ringwald
18158a1b1bbSMatthias Ringwald // handlers
18258a1b1bbSMatthias Ringwald static void (*rx_done_handler)(void) = dummy_handler;
18358a1b1bbSMatthias Ringwald static void (*tx_done_handler)(void) = dummy_handler;
18458a1b1bbSMatthias Ringwald static void (*cts_irq_handler)(void) = dummy_handler;
18558a1b1bbSMatthias Ringwald
18658a1b1bbSMatthias Ringwald // @note While the Atmel SAM S7x data sheet states
18758a1b1bbSMatthias Ringwald // "The hardware handshaking feature enables an out-of-band flow control by automatic management
18858a1b1bbSMatthias Ringwald // of the pins RTS and CTS.",
18958a1b1bbSMatthias Ringwald // I didn't see RTS going up automatically up, ever. So, at least for RTS, the automatic management
19058a1b1bbSMatthias Ringwald // is just a glorified GPIO pin control feature, which provides no benefit, but irritates a lot
19158a1b1bbSMatthias Ringwald
192cb9ff2fbSMatthias Ringwald // J505:6
193cb9ff2fbSMatthias Ringwald #define DEBUG_PIN_1 PIO_PD16_IDX
194cb9ff2fbSMatthias Ringwald // J505:5
195cb9ff2fbSMatthias Ringwald #define DEBUG_PIN_2 PIO_PD15_IDX
196cb9ff2fbSMatthias Ringwald
hal_uart_rts_high(void)197c267d18bSMatthias Ringwald static inline void hal_uart_rts_high(void){
198c267d18bSMatthias Ringwald if (!simulate_flowcontrol) return;
199cb9ff2fbSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_HIGH);
20058a1b1bbSMatthias Ringwald BOARD_USART->US_CR = US_CR_RTSEN;
20158a1b1bbSMatthias Ringwald }
hal_uart_rts_low(void)202c267d18bSMatthias Ringwald static inline void hal_uart_rts_low(void){
203c267d18bSMatthias Ringwald if (!simulate_flowcontrol) return;
204cb9ff2fbSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW);
20558a1b1bbSMatthias Ringwald BOARD_USART->US_CR = US_CR_RTSDIS;
20658a1b1bbSMatthias Ringwald }
20758a1b1bbSMatthias Ringwald
20858a1b1bbSMatthias Ringwald /**
20958a1b1bbSMatthias Ringwald */
210cb9ff2fbSMatthias Ringwald static int hal_uart_dma_initialized = 0;
hal_uart_dma_init(void)21158a1b1bbSMatthias Ringwald void hal_uart_dma_init(void)
21258a1b1bbSMatthias Ringwald {
213cb9ff2fbSMatthias Ringwald if (hal_uart_dma_initialized){
214cb9ff2fbSMatthias Ringwald log_info("hal_uart_dma_init already initialized");
215cb9ff2fbSMatthias Ringwald return;
216cb9ff2fbSMatthias Ringwald }
217cb9ff2fbSMatthias Ringwald hal_uart_dma_initialized = 1;
21867422dbdSMatthias Ringwald
21967422dbdSMatthias Ringwald // debug
22067422dbdSMatthias Ringwald #ifdef DEBUG_PIN_1
22167422dbdSMatthias Ringwald ioport_set_pin_dir(DEBUG_PIN_1, IOPORT_DIR_OUTPUT);
22267422dbdSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_LOW);
22367422dbdSMatthias Ringwald #endif
22467422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2
22567422dbdSMatthias Ringwald ioport_set_pin_dir(DEBUG_PIN_2, IOPORT_DIR_OUTPUT);
22667422dbdSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW);
22767422dbdSMatthias Ringwald #endif
22813b8e9b1SMatthias Ringwald // power on
22913b8e9b1SMatthias Ringwald ioport_set_pin_dir(BLUETOOTH_CHP_EN, IOPORT_DIR_OUTPUT);
23013b8e9b1SMatthias Ringwald ioport_set_pin_level(BLUETOOTH_CHP_EN, IOPORT_PIN_LEVEL_HIGH);
23113b8e9b1SMatthias Ringwald
23213b8e9b1SMatthias Ringwald // reset
23313b8e9b1SMatthias Ringwald ioport_set_pin_dir(BLUETOOTH_RESET, IOPORT_DIR_OUTPUT);
23413b8e9b1SMatthias Ringwald ioport_set_pin_level(BLUETOOTH_RESET, IOPORT_PIN_LEVEL_LOW);
23513b8e9b1SMatthias Ringwald mdelay(250);
23613b8e9b1SMatthias Ringwald ioport_set_pin_level(BLUETOOTH_RESET, IOPORT_PIN_LEVEL_HIGH);
23713b8e9b1SMatthias Ringwald mdelay(250);
23813b8e9b1SMatthias Ringwald
23913b8e9b1SMatthias Ringwald /* Enable the peripheral clock in the PMC. */
24013b8e9b1SMatthias Ringwald sysclk_enable_peripheral_clock(BOARD_ID_USART);
24158a1b1bbSMatthias Ringwald
24258a1b1bbSMatthias Ringwald // configure Bluetooth USART
24358a1b1bbSMatthias Ringwald const sam_usart_opt_t bluetooth_settings = {
24458a1b1bbSMatthias Ringwald 115200,
24558a1b1bbSMatthias Ringwald US_MR_CHRL_8_BIT,
24658a1b1bbSMatthias Ringwald US_MR_PAR_NO,
24758a1b1bbSMatthias Ringwald US_MR_NBSTOP_1_BIT,
24858a1b1bbSMatthias Ringwald US_MR_CHMODE_NORMAL,
24958a1b1bbSMatthias Ringwald /* This field is only used in IrDA mode. */
25058a1b1bbSMatthias Ringwald 0
25158a1b1bbSMatthias Ringwald };
25258a1b1bbSMatthias Ringwald
25358a1b1bbSMatthias Ringwald /* Configure USART mode. */
254c267d18bSMatthias Ringwald simulate_flowcontrol = 0;
25513b8e9b1SMatthias Ringwald usart_init_rs232(BOARD_USART, &bluetooth_settings, sysclk_get_peripheral_hz());
256c267d18bSMatthias Ringwald // Set RTS = 0 (normal mode)
257c267d18bSMatthias Ringwald BOARD_USART->US_CR = US_CR_RTSEN;
25858a1b1bbSMatthias Ringwald
25958a1b1bbSMatthias Ringwald /* Disable all the interrupts. */
26058a1b1bbSMatthias Ringwald usart_disable_interrupt(BOARD_USART, ALL_INTERRUPT_MASK);
26158a1b1bbSMatthias Ringwald
26258a1b1bbSMatthias Ringwald /* Enable TX & RX function. */
26358a1b1bbSMatthias Ringwald usart_enable_tx(BOARD_USART);
26458a1b1bbSMatthias Ringwald usart_enable_rx(BOARD_USART);
26558a1b1bbSMatthias Ringwald
26658a1b1bbSMatthias Ringwald /* Configure and enable interrupt of USART. */
26758a1b1bbSMatthias Ringwald NVIC_EnableIRQ(USART_IRQn);
26858a1b1bbSMatthias Ringwald
26958a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
27058a1b1bbSMatthias Ringwald
27158a1b1bbSMatthias Ringwald // setup XDMAC
27258a1b1bbSMatthias Ringwald
27358a1b1bbSMatthias Ringwald /* Initialize and enable DMA controller */
27458a1b1bbSMatthias Ringwald pmc_enable_periph_clk(ID_XDMAC);
27558a1b1bbSMatthias Ringwald
27658a1b1bbSMatthias Ringwald /* Enable XDMA interrupt */
27758a1b1bbSMatthias Ringwald NVIC_ClearPendingIRQ(XDMAC_IRQn);
27858a1b1bbSMatthias Ringwald NVIC_SetPriority( XDMAC_IRQn ,1);
27958a1b1bbSMatthias Ringwald NVIC_EnableIRQ(XDMAC_IRQn);
28058a1b1bbSMatthias Ringwald
28158a1b1bbSMatthias Ringwald // Setup XDMA Channel for USART TX
28258a1b1bbSMatthias Ringwald xdmac_channel_set_destination_addr(XDMAC, XDMA_CH_UART_TX, (uint32_t)&BOARD_USART->US_THR);
28358a1b1bbSMatthias Ringwald xdmac_channel_set_config(XDMAC, XDMA_CH_UART_TX,
28458a1b1bbSMatthias Ringwald XDMAC_CC_TYPE_PER_TRAN |
28558a1b1bbSMatthias Ringwald XDMAC_CC_DSYNC_MEM2PER |
28658a1b1bbSMatthias Ringwald XDMAC_CC_MEMSET_NORMAL_MODE |
28758a1b1bbSMatthias Ringwald XDMAC_CC_MBSIZE_SINGLE |
28858a1b1bbSMatthias Ringwald XDMAC_CC_DWIDTH_BYTE |
28958a1b1bbSMatthias Ringwald XDMAC_CC_SIF_AHB_IF0 |
29058a1b1bbSMatthias Ringwald XDMAC_CC_DIF_AHB_IF1 |
29158a1b1bbSMatthias Ringwald XDMAC_CC_SAM_INCREMENTED_AM |
29258a1b1bbSMatthias Ringwald XDMAC_CC_DAM_FIXED_AM |
29358a1b1bbSMatthias Ringwald XDMAC_CC_CSIZE_CHK_1 |
29458a1b1bbSMatthias Ringwald XDMAC_CC_PERID(XDAMC_CHANNEL_HWID_USART0_TX)
29558a1b1bbSMatthias Ringwald );
29658a1b1bbSMatthias Ringwald xdmac_channel_set_descriptor_control(XDMAC, XDMA_CH_UART_TX, 0);
29758a1b1bbSMatthias Ringwald xdmac_channel_set_source_microblock_stride(XDMAC, XDMA_CH_UART_TX, 0);
29858a1b1bbSMatthias Ringwald xdmac_channel_set_destination_microblock_stride(XDMAC, XDMA_CH_UART_TX, 0);
29958a1b1bbSMatthias Ringwald xdmac_channel_set_datastride_mempattern(XDMAC, XDMA_CH_UART_TX, 0);
30058a1b1bbSMatthias Ringwald xdmac_channel_set_block_control(XDMAC, XDMA_CH_UART_TX, 0);
30158a1b1bbSMatthias Ringwald xdmac_enable_interrupt(XDMAC, XDMA_CH_UART_TX);
30258a1b1bbSMatthias Ringwald xdmac_channel_enable_interrupt(XDMAC, XDMA_CH_UART_TX, XDMAC_CIE_BIE);
30358a1b1bbSMatthias Ringwald
30458a1b1bbSMatthias Ringwald // Setup XDMA Channel for USART RX
30558a1b1bbSMatthias Ringwald xdmac_channel_set_source_addr(XDMAC, XDMA_CH_UART_RX, (uint32_t)&BOARD_USART->US_RHR);
30658a1b1bbSMatthias Ringwald xdmac_channel_set_config(XDMAC, XDMA_CH_UART_RX,
30758a1b1bbSMatthias Ringwald XDMAC_CC_TYPE_PER_TRAN |
30858a1b1bbSMatthias Ringwald XDMAC_CC_DSYNC_PER2MEM |
30958a1b1bbSMatthias Ringwald XDMAC_CC_MEMSET_NORMAL_MODE |
31058a1b1bbSMatthias Ringwald XDMAC_CC_MBSIZE_SINGLE |
31158a1b1bbSMatthias Ringwald XDMAC_CC_DWIDTH_BYTE |
31258a1b1bbSMatthias Ringwald XDMAC_CC_SIF_AHB_IF1 |
31358a1b1bbSMatthias Ringwald XDMAC_CC_DIF_AHB_IF0 |
31458a1b1bbSMatthias Ringwald XDMAC_CC_SAM_FIXED_AM |
31558a1b1bbSMatthias Ringwald XDMAC_CC_DAM_INCREMENTED_AM |
31658a1b1bbSMatthias Ringwald XDMAC_CC_CSIZE_CHK_1 |
31758a1b1bbSMatthias Ringwald XDMAC_CC_PERID(XDAMC_CHANNEL_HWID_USART0_RX)
31858a1b1bbSMatthias Ringwald );
31958a1b1bbSMatthias Ringwald xdmac_channel_set_descriptor_control(XDMAC, XDMA_CH_UART_RX, 0);
32058a1b1bbSMatthias Ringwald xdmac_channel_set_source_microblock_stride(XDMAC, XDMA_CH_UART_RX, 0);
32158a1b1bbSMatthias Ringwald xdmac_channel_set_destination_microblock_stride(XDMAC, XDMA_CH_UART_RX, 0);
32258a1b1bbSMatthias Ringwald xdmac_channel_set_datastride_mempattern(XDMAC, XDMA_CH_UART_RX, 0);
32358a1b1bbSMatthias Ringwald xdmac_channel_set_block_control(XDMAC, XDMA_CH_UART_RX, 0);
32458a1b1bbSMatthias Ringwald xdmac_enable_interrupt(XDMAC, XDMA_CH_UART_RX);
32558a1b1bbSMatthias Ringwald xdmac_channel_enable_interrupt(XDMAC, XDMA_CH_UART_RX, XDMAC_CIE_BIE);
32658a1b1bbSMatthias Ringwald #endif
32758a1b1bbSMatthias Ringwald }
32858a1b1bbSMatthias Ringwald
hal_uart_dma_set_sleep(uint8_t sleep)32958a1b1bbSMatthias Ringwald void hal_uart_dma_set_sleep(uint8_t sleep){
33058a1b1bbSMatthias Ringwald }
33158a1b1bbSMatthias Ringwald
hal_uart_dma_set_block_received(void (* the_block_handler)(void))33258a1b1bbSMatthias Ringwald void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
33358a1b1bbSMatthias Ringwald rx_done_handler = the_block_handler;
33458a1b1bbSMatthias Ringwald }
33558a1b1bbSMatthias Ringwald
hal_uart_dma_set_block_sent(void (* the_block_handler)(void))33658a1b1bbSMatthias Ringwald void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
33758a1b1bbSMatthias Ringwald tx_done_handler = the_block_handler;
33858a1b1bbSMatthias Ringwald }
33958a1b1bbSMatthias Ringwald
hal_uart_dma_set_csr_irq_handler(void (* the_irq_handler)(void))34058a1b1bbSMatthias Ringwald void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
34158a1b1bbSMatthias Ringwald cts_irq_handler = the_irq_handler;
34258a1b1bbSMatthias Ringwald }
34358a1b1bbSMatthias Ringwald
hal_uart_dma_set_baud(uint32_t baud)34458a1b1bbSMatthias Ringwald int hal_uart_dma_set_baud(uint32_t baud){
34558a1b1bbSMatthias Ringwald /* Disable TX & RX function. */
34658a1b1bbSMatthias Ringwald usart_disable_tx(BOARD_USART);
34758a1b1bbSMatthias Ringwald usart_disable_rx(BOARD_USART);
34858a1b1bbSMatthias Ringwald uint32_t res = usart_set_async_baudrate(BOARD_USART, baud, sysclk_get_peripheral_hz());
34958a1b1bbSMatthias Ringwald if (res){
35058a1b1bbSMatthias Ringwald log_error("hal_uart_dma_set_baud library call failed");
35158a1b1bbSMatthias Ringwald }
35258a1b1bbSMatthias Ringwald
35358a1b1bbSMatthias Ringwald /* Enable TX & RX function. */
35458a1b1bbSMatthias Ringwald usart_enable_tx(BOARD_USART);
35558a1b1bbSMatthias Ringwald usart_enable_rx(BOARD_USART);
35658a1b1bbSMatthias Ringwald
35713b8e9b1SMatthias Ringwald log_info("set baud rate %u", (int) baud);
35813b8e9b1SMatthias Ringwald return 0;
35913b8e9b1SMatthias Ringwald }
36058a1b1bbSMatthias Ringwald
hal_uart_dma_set_flowcontrol(int flowcontrol)361c267d18bSMatthias Ringwald int hal_uart_dma_set_flowcontrol(int flowcontrol){
362cb9ff2fbSMatthias Ringwald log_info("hal_uart_dma_set_flowcontrol %u", flowcontrol);
363c267d18bSMatthias Ringwald simulate_flowcontrol = flowcontrol;
364c267d18bSMatthias Ringwald if (flowcontrol){
365c267d18bSMatthias Ringwald /* Set hardware handshaking mode. */
366c267d18bSMatthias Ringwald BOARD_USART->US_MR = (BOARD_USART->US_MR & ~US_MR_USART_MODE_Msk) | US_MR_USART_MODE_HW_HANDSHAKING;
367cb9ff2fbSMatthias Ringwald hal_uart_rts_high();
368c267d18bSMatthias Ringwald } else {
369c267d18bSMatthias Ringwald /* Set nomal mode. */
370c267d18bSMatthias Ringwald BOARD_USART->US_MR = (BOARD_USART->US_MR & ~US_MR_USART_MODE_Msk) | US_MR_USART_MODE_NORMAL;
371c267d18bSMatthias Ringwald // Set RTS = 0 (normal mode)
372c267d18bSMatthias Ringwald BOARD_USART->US_CR = US_CR_RTSEN;
373c267d18bSMatthias Ringwald }
37458a1b1bbSMatthias Ringwald return 0;
37558a1b1bbSMatthias Ringwald }
37658a1b1bbSMatthias Ringwald
hal_uart_dma_send_block(const uint8_t * data,uint16_t size)37758a1b1bbSMatthias Ringwald void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){
37867422dbdSMatthias Ringwald
37967422dbdSMatthias Ringwald tx_notify = 1;
38067422dbdSMatthias Ringwald
38158a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
38258a1b1bbSMatthias Ringwald xdmac_channel_get_interrupt_status( XDMAC, XDMA_CH_UART_TX);
38358a1b1bbSMatthias Ringwald xdmac_channel_set_source_addr(XDMAC, XDMA_CH_UART_TX, (uint32_t)data);
38458a1b1bbSMatthias Ringwald xdmac_channel_set_microblock_control(XDMAC, XDMA_CH_UART_TX, size);
38558a1b1bbSMatthias Ringwald xdmac_channel_enable(XDMAC, XDMA_CH_UART_TX);
38658a1b1bbSMatthias Ringwald #else
38767422dbdSMatthias Ringwald if (bytes_to_write){
38867422dbdSMatthias Ringwald log_error("send block, bytes to write %u", bytes_to_write);
38967422dbdSMatthias Ringwald return;
39067422dbdSMatthias Ringwald }
39158a1b1bbSMatthias Ringwald tx_buffer_ptr = (uint8_t *) data;
39258a1b1bbSMatthias Ringwald bytes_to_write = size;
39358a1b1bbSMatthias Ringwald usart_enable_interrupt(BOARD_USART, US_IER_TXRDY);
39458a1b1bbSMatthias Ringwald #endif
39558a1b1bbSMatthias Ringwald }
39658a1b1bbSMatthias Ringwald
hal_uart_dma_receive_block(uint8_t * data,uint16_t size)39758a1b1bbSMatthias Ringwald void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){
39858a1b1bbSMatthias Ringwald
399cb9ff2fbSMatthias Ringwald #ifdef DEBUG_PIN_1
400cb9ff2fbSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_HIGH);
401cb9ff2fbSMatthias Ringwald #endif
402cb9ff2fbSMatthias Ringwald
40358a1b1bbSMatthias Ringwald hal_uart_rts_low();
40458a1b1bbSMatthias Ringwald
405cb9ff2fbSMatthias Ringwald rx_notify = 1;
406cb9ff2fbSMatthias Ringwald
40758a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
40858a1b1bbSMatthias Ringwald xdmac_channel_get_interrupt_status( XDMAC, XDMA_CH_UART_RX);
40958a1b1bbSMatthias Ringwald xdmac_channel_set_destination_addr(XDMAC, XDMA_CH_UART_RX, (uint32_t)data);
41058a1b1bbSMatthias Ringwald xdmac_channel_set_microblock_control(XDMAC, XDMA_CH_UART_RX, size);
41158a1b1bbSMatthias Ringwald xdmac_channel_enable(XDMAC, XDMA_CH_UART_RX);
41258a1b1bbSMatthias Ringwald #else
41358a1b1bbSMatthias Ringwald rx_buffer_ptr = data;
41458a1b1bbSMatthias Ringwald bytes_to_read = size;
41558a1b1bbSMatthias Ringwald usart_enable_interrupt(BOARD_USART, US_IER_RXRDY);
41658a1b1bbSMatthias Ringwald #endif
41758a1b1bbSMatthias Ringwald }
41858a1b1bbSMatthias Ringwald
41958a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
XDMAC_Handler(void)42058a1b1bbSMatthias Ringwald void XDMAC_Handler(void)
42158a1b1bbSMatthias Ringwald {
42258a1b1bbSMatthias Ringwald uint32_t dma_status;
42358a1b1bbSMatthias Ringwald dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH_UART_TX);
42458a1b1bbSMatthias Ringwald if (dma_status & XDMAC_CIS_BIS) {
42567422dbdSMatthias Ringwald if (tx_notify){
42667422dbdSMatthias Ringwald tx_notify = 0;
42758a1b1bbSMatthias Ringwald tx_done_handler();
42858a1b1bbSMatthias Ringwald }
42967422dbdSMatthias Ringwald }
43058a1b1bbSMatthias Ringwald dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH_UART_RX);
43158a1b1bbSMatthias Ringwald if (dma_status & XDMAC_CIS_BIS) {
43258a1b1bbSMatthias Ringwald hal_uart_rts_high();
433cb9ff2fbSMatthias Ringwald if (rx_notify){
434cb9ff2fbSMatthias Ringwald rx_notify = 0;
43558a1b1bbSMatthias Ringwald rx_done_handler();
43658a1b1bbSMatthias Ringwald }
43758a1b1bbSMatthias Ringwald }
438cb9ff2fbSMatthias Ringwald }
43958a1b1bbSMatthias Ringwald #else
USART_Handler(void)44058a1b1bbSMatthias Ringwald void USART_Handler(void)
44158a1b1bbSMatthias Ringwald {
44267422dbdSMatthias Ringwald
44367422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2
444cb9ff2fbSMatthias Ringwald // ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_HIGH);
44567422dbdSMatthias Ringwald #endif
44658a1b1bbSMatthias Ringwald
44758a1b1bbSMatthias Ringwald /* Read USART status. */
44867422dbdSMatthias Ringwald uint32_t ul_status = usart_get_status(BOARD_USART);
44958a1b1bbSMatthias Ringwald
45058a1b1bbSMatthias Ringwald // handle ready to send
45158a1b1bbSMatthias Ringwald if(ul_status & US_IER_TXRDY) {
45258a1b1bbSMatthias Ringwald if (bytes_to_write){
45358a1b1bbSMatthias Ringwald // send next byte
45458a1b1bbSMatthias Ringwald usart_write(BOARD_USART, *tx_buffer_ptr);
45558a1b1bbSMatthias Ringwald tx_buffer_ptr++;
45658a1b1bbSMatthias Ringwald bytes_to_write--;
45758a1b1bbSMatthias Ringwald } else {
45867422dbdSMatthias Ringwald
45958a1b1bbSMatthias Ringwald // done. disable tx ready interrupt to avoid starvation here
46058a1b1bbSMatthias Ringwald usart_disable_interrupt(BOARD_USART, US_IER_TXRDY);
46167422dbdSMatthias Ringwald if (tx_notify){
46267422dbdSMatthias Ringwald tx_notify = 0;
46358a1b1bbSMatthias Ringwald tx_done_handler();
46458a1b1bbSMatthias Ringwald }
46558a1b1bbSMatthias Ringwald }
46667422dbdSMatthias Ringwald }
46758a1b1bbSMatthias Ringwald
46858a1b1bbSMatthias Ringwald // handle byte available for read
46958a1b1bbSMatthias Ringwald if (ul_status & US_IER_RXRDY) {
4705c5e4857SMatthias Ringwald if (bytes_to_read){
47158a1b1bbSMatthias Ringwald uint32_t ch;
47258a1b1bbSMatthias Ringwald usart_read(BOARD_USART, (uint32_t *)&ch);
47358a1b1bbSMatthias Ringwald *rx_buffer_ptr++ = ch;
47458a1b1bbSMatthias Ringwald bytes_to_read--;
47558a1b1bbSMatthias Ringwald if (bytes_to_read == 0){
476cb9ff2fbSMatthias Ringwald
477cb9ff2fbSMatthias Ringwald #ifdef DEBUG_PIN_1
478cb9ff2fbSMatthias Ringwald ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_LOW);
479cb9ff2fbSMatthias Ringwald #endif
480cb9ff2fbSMatthias Ringwald
48158a1b1bbSMatthias Ringwald // done. disable rx ready interrupt, raise RTS
48258a1b1bbSMatthias Ringwald hal_uart_rts_high();
48358a1b1bbSMatthias Ringwald usart_disable_interrupt(BOARD_USART, US_IER_RXRDY);
484cb9ff2fbSMatthias Ringwald if (rx_notify){
485cb9ff2fbSMatthias Ringwald rx_notify = 0;
48658a1b1bbSMatthias Ringwald rx_done_handler();
48758a1b1bbSMatthias Ringwald }
488cb9ff2fbSMatthias Ringwald }
4895c5e4857SMatthias Ringwald } else {
4905c5e4857SMatthias Ringwald // shoult not happen, disable irq anyway
4915c5e4857SMatthias Ringwald usart_disable_interrupt(BOARD_USART, US_IER_RXRDY);
4925c5e4857SMatthias Ringwald }
49358a1b1bbSMatthias Ringwald }
49467422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2
495cb9ff2fbSMatthias Ringwald // ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW);
49667422dbdSMatthias Ringwald #endif
49767422dbdSMatthias Ringwald
49858a1b1bbSMatthias Ringwald }
49958a1b1bbSMatthias Ringwald #endif
50058a1b1bbSMatthias Ringwald
hal_tick_init()50158a1b1bbSMatthias Ringwald void hal_tick_init()
50258a1b1bbSMatthias Ringwald {
50358a1b1bbSMatthias Ringwald /* Configure systick for 1 ms */
50458a1b1bbSMatthias Ringwald puts("Configure system tick to get 1ms tick period.\r");
50558a1b1bbSMatthias Ringwald if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) {
50658a1b1bbSMatthias Ringwald puts("-F- Systick configuration error\r");
50758a1b1bbSMatthias Ringwald while (1);
50858a1b1bbSMatthias Ringwald }
50958a1b1bbSMatthias Ringwald }
51058a1b1bbSMatthias Ringwald
hal_tick_set_handler(void (* handler)(void))51158a1b1bbSMatthias Ringwald void hal_tick_set_handler(void (*handler)(void)){
51258a1b1bbSMatthias Ringwald if (handler == NULL){
51358a1b1bbSMatthias Ringwald tick_handler = &dummy_handler;
51458a1b1bbSMatthias Ringwald return;
51558a1b1bbSMatthias Ringwald }
51658a1b1bbSMatthias Ringwald tick_handler = handler;
51758a1b1bbSMatthias Ringwald }
51858a1b1bbSMatthias Ringwald
hal_tick_get_tick_period_in_ms(void)51958a1b1bbSMatthias Ringwald int hal_tick_get_tick_period_in_ms(void){
52058a1b1bbSMatthias Ringwald return 1;
52158a1b1bbSMatthias Ringwald }
52258a1b1bbSMatthias Ringwald
52313b8e9b1SMatthias Ringwald static const btstack_uart_block_t * uart_driver;
52413b8e9b1SMatthias Ringwald
phase2(int status)52513b8e9b1SMatthias Ringwald static void phase2(int status){
52613b8e9b1SMatthias Ringwald
52713b8e9b1SMatthias Ringwald if (status){
52813b8e9b1SMatthias Ringwald printf("Download firmware failed\n");
52913b8e9b1SMatthias Ringwald return;
53013b8e9b1SMatthias Ringwald }
53113b8e9b1SMatthias Ringwald
53213b8e9b1SMatthias Ringwald printf("Phase 2: Main app\n");
53313b8e9b1SMatthias Ringwald
53413b8e9b1SMatthias Ringwald // init HCI
53513b8e9b1SMatthias Ringwald const hci_transport_t * transport = hci_transport_h4_instance(uart_driver);
53613b8e9b1SMatthias Ringwald hci_init(transport, (void*) &transport_config);
53713b8e9b1SMatthias Ringwald hci_set_chipset(btstack_chipset_atwilc3000_instance());
53813b8e9b1SMatthias Ringwald
53913b8e9b1SMatthias Ringwald // setup app
54013b8e9b1SMatthias Ringwald btstack_main(0, NULL);
54113b8e9b1SMatthias Ringwald }
54258a1b1bbSMatthias Ringwald
5431b2596b5SMatthias Ringwald /**
5441b2596b5SMatthias Ringwald * \brief getting-started Application entry point.
5451b2596b5SMatthias Ringwald *
5461b2596b5SMatthias Ringwald * \return Unused (ANSI-C compatibility).
5471b2596b5SMatthias Ringwald */
5481b2596b5SMatthias Ringwald // [main]
main(void)5491b2596b5SMatthias Ringwald int main(void)
5501b2596b5SMatthias Ringwald {
5511b2596b5SMatthias Ringwald /* Initialize the SAM system */
5521b2596b5SMatthias Ringwald sysclk_init();
5531b2596b5SMatthias Ringwald board_init();
5541b2596b5SMatthias Ringwald
5551b2596b5SMatthias Ringwald /* Initialize the console uart */
5561b2596b5SMatthias Ringwald configure_console();
5571b2596b5SMatthias Ringwald
55813b8e9b1SMatthias Ringwald /* Output boot info */
55913b8e9b1SMatthias Ringwald printf("BTstack on SAMV71 Xplained Ultra with ATWILC3000\n");
56058a1b1bbSMatthias Ringwald printf("CPU %lu hz, peripheral clock %lu hz\n", sysclk_get_cpu_hz(), sysclk_get_peripheral_hz());
56113b8e9b1SMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
56213b8e9b1SMatthias Ringwald printf("Using XDMA for Bluetooth UART\n");
56313b8e9b1SMatthias Ringwald #else
56413b8e9b1SMatthias Ringwald printf("Using IRQ driver for Bluetooth UART\n");
56513b8e9b1SMatthias Ringwald #endif
56613b8e9b1SMatthias Ringwald printf("--\n");
56758a1b1bbSMatthias Ringwald
56858a1b1bbSMatthias Ringwald // start with BTstack init - especially configure HCI Transport
56958a1b1bbSMatthias Ringwald btstack_memory_init();
57058a1b1bbSMatthias Ringwald btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
57158a1b1bbSMatthias Ringwald
57258a1b1bbSMatthias Ringwald // enable full log output while porting
57325d9a2cdSMatthias Ringwald // hci_dump_init(hci_dump_embedded_stdout_get_instance());
57458a1b1bbSMatthias Ringwald
57513b8e9b1SMatthias Ringwald // setup UART HAL + Run Loop integration
57613b8e9b1SMatthias Ringwald uart_driver = btstack_uart_block_embedded_instance();
57758a1b1bbSMatthias Ringwald
5786e0d5aedSMatthias Ringwald // extract UART config from transport config, but disable flow control and use default baudrate
5796e0d5aedSMatthias Ringwald uart_config.baudrate = HCI_DEFAULT_BAUDRATE;
58013b8e9b1SMatthias Ringwald uart_config.flowcontrol = 0;
58113b8e9b1SMatthias Ringwald uart_config.device_name = transport_config.device_name;
58213b8e9b1SMatthias Ringwald uart_driver->init(&uart_config);
58358a1b1bbSMatthias Ringwald
58413b8e9b1SMatthias Ringwald // phase #1 download firmware
58513b8e9b1SMatthias Ringwald printf("Phase 1: Download firmware\n");
58613b8e9b1SMatthias Ringwald
58713b8e9b1SMatthias Ringwald // phase #2 start main app
588a15efc86SMatthias Ringwald btstack_chipset_atwilc3000_download_firmware(uart_driver, transport_config.baudrate_init, transport_config.flowcontrol, (const uint8_t *) firmware_ble, sizeof(firmware_ble), &phase2);
58958a1b1bbSMatthias Ringwald
59058a1b1bbSMatthias Ringwald // go
59158a1b1bbSMatthias Ringwald btstack_run_loop_execute();
59258a1b1bbSMatthias Ringwald
59358a1b1bbSMatthias Ringwald // compiler happy
5941b2596b5SMatthias Ringwald while(1);
5951b2596b5SMatthias Ringwald }
5961b2596b5SMatthias Ringwald #ifdef __cplusplus
5971b2596b5SMatthias Ringwald }
5981b2596b5SMatthias Ringwald #endif
599