xref: /btstack/port/samv71-xplained-atwilc3000/main.c (revision 13b8e9b1e4cbf8bcfce041f8e7f9060a6a3a2eb5)
11b2596b5SMatthias Ringwald #include "asf.h"
21b2596b5SMatthias Ringwald #include "stdio_serial.h"
31b2596b5SMatthias Ringwald #include "conf_board.h"
41b2596b5SMatthias Ringwald #include "conf_clock.h"
51b2596b5SMatthias Ringwald 
658a1b1bbSMatthias Ringwald // BTstack
7*13b8e9b1SMatthias Ringwald #include "btstack_chipset_atwilc3000.h"
8*13b8e9b1SMatthias Ringwald #include "btstack_debug.h"
9*13b8e9b1SMatthias Ringwald #include "btstack_memory.h"
1058a1b1bbSMatthias Ringwald #include "btstack_run_loop.h"
1158a1b1bbSMatthias Ringwald #include "btstack_run_loop_embedded.h"
1258a1b1bbSMatthias Ringwald #include "classic/btstack_link_key_db.h"
1358a1b1bbSMatthias Ringwald #include "hal_uart_dma.h"
1458a1b1bbSMatthias Ringwald #include "hal_cpu.h"
1558a1b1bbSMatthias Ringwald #include "hal_tick.h"
16*13b8e9b1SMatthias Ringwald #include "hci.h"
17*13b8e9b1SMatthias Ringwald #include "hci_dump.h"
18*13b8e9b1SMatthias Ringwald #include "wilc3000_bt_firmware.h"
1958a1b1bbSMatthias Ringwald 
20*13b8e9b1SMatthias Ringwald // #define USE_XDMAC_FOR_USART
2158a1b1bbSMatthias Ringwald #define XDMA_CH_UART_TX   0
2258a1b1bbSMatthias Ringwald #define XDMA_CH_UART_RX  1
231b2596b5SMatthias Ringwald 
2458a1b1bbSMatthias Ringwald /** All interrupt mask. */
2558a1b1bbSMatthias Ringwald #define ALL_INTERRUPT_MASK   0xffffffff
261b2596b5SMatthias Ringwald 
271b2596b5SMatthias Ringwald #ifdef __cplusplus
281b2596b5SMatthias Ringwald extern "C" {
291b2596b5SMatthias Ringwald #endif
30*13b8e9b1SMatthias Ringwald 
31*13b8e9b1SMatthias Ringwald extern int btstack_main(int argc, const char * argv[]);
32*13b8e9b1SMatthias Ringwald 
33*13b8e9b1SMatthias Ringwald static void dummy_handler(void){}
34*13b8e9b1SMatthias Ringwald static void (*tick_handler)(void) = &dummy_handler;
35*13b8e9b1SMatthias Ringwald 
36*13b8e9b1SMatthias Ringwald static btstack_uart_config_t uart_config;
37*13b8e9b1SMatthias Ringwald 
38*13b8e9b1SMatthias Ringwald static hci_transport_config_uart_t transport_config = {
39*13b8e9b1SMatthias Ringwald 	HCI_TRANSPORT_CONFIG_UART,
40*13b8e9b1SMatthias Ringwald 	115200,
41*13b8e9b1SMatthias Ringwald 	921600, // use 0 to skip baud rate change from 115200 to X for debugging purposes
42*13b8e9b1SMatthias Ringwald 	1,        // flow control
43*13b8e9b1SMatthias Ringwald 	NULL,
44*13b8e9b1SMatthias Ringwald };
451b2596b5SMatthias Ringwald 
461b2596b5SMatthias Ringwald /**
471b2596b5SMatthias Ringwald  *  \brief Handler for System Tick interrupt.
481b2596b5SMatthias Ringwald  */
491b2596b5SMatthias Ringwald void SysTick_Handler(void)
501b2596b5SMatthias Ringwald {
5158a1b1bbSMatthias Ringwald 	tick_handler();
521b2596b5SMatthias Ringwald }
531b2596b5SMatthias Ringwald 
541b2596b5SMatthias Ringwald /**
551b2596b5SMatthias Ringwald  *  Configure UART console.
561b2596b5SMatthias Ringwald  */
571b2596b5SMatthias Ringwald // [main_console_configure]
581b2596b5SMatthias Ringwald static void configure_console(void)
591b2596b5SMatthias Ringwald {
601b2596b5SMatthias Ringwald 	const usart_serial_options_t uart_serial_options = {
611b2596b5SMatthias Ringwald 		.baudrate = CONF_UART_BAUDRATE,
621b2596b5SMatthias Ringwald #ifdef CONF_UART_CHAR_LENGTH
631b2596b5SMatthias Ringwald 		.charlength = CONF_UART_CHAR_LENGTH,
641b2596b5SMatthias Ringwald #endif
651b2596b5SMatthias Ringwald 		.paritytype = CONF_UART_PARITY,
661b2596b5SMatthias Ringwald #ifdef CONF_UART_STOP_BITS
671b2596b5SMatthias Ringwald 		.stopbits = CONF_UART_STOP_BITS,
681b2596b5SMatthias Ringwald #endif
691b2596b5SMatthias Ringwald 	};
701b2596b5SMatthias Ringwald 
711b2596b5SMatthias Ringwald 	/* Configure console UART. */
721b2596b5SMatthias Ringwald 	sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
731b2596b5SMatthias Ringwald 	stdio_serial_init(CONF_UART, &uart_serial_options);
741b2596b5SMatthias Ringwald }
751b2596b5SMatthias Ringwald 
761b2596b5SMatthias Ringwald // [main_console_configure]
771b2596b5SMatthias Ringwald 
781b2596b5SMatthias Ringwald /**
7958a1b1bbSMatthias Ringwald  * \brief Wait for the given number of milliseconds (ticks
801b2596b5SMatthias Ringwald  * generated by the SAM's microcontrollers's system tick).
811b2596b5SMatthias Ringwald  *
821b2596b5SMatthias Ringwald  * \param ul_dly_ticks  Delay to wait for, in milliseconds.
831b2596b5SMatthias Ringwald  */
841b2596b5SMatthias Ringwald // [main_ms_delay]
8558a1b1bbSMatthias Ringwald static void mdelay(uint32_t delay_in_ms)
861b2596b5SMatthias Ringwald {
8758a1b1bbSMatthias Ringwald 	// delay_ms(delay_in_ms);
8858a1b1bbSMatthias Ringwald 	uint32_t time_to_wait = btstack_run_loop_get_time_ms() + delay_in_ms;
8958a1b1bbSMatthias Ringwald 	while (btstack_run_loop_get_time_ms() < time_to_wait);
901b2596b5SMatthias Ringwald }
911b2596b5SMatthias Ringwald // [main_ms_delay]
921b2596b5SMatthias Ringwald 
9358a1b1bbSMatthias Ringwald ////////////////////////////////////////////////////////////////////////////////
9458a1b1bbSMatthias Ringwald // hal_cpu.h implementation
9558a1b1bbSMatthias Ringwald ////////////////////////////////////////////////////////////////////////////////
9658a1b1bbSMatthias Ringwald // hal_led.h implementation
9758a1b1bbSMatthias Ringwald #include "hal_led.h"
9858a1b1bbSMatthias Ringwald void hal_led_off(void);
9958a1b1bbSMatthias Ringwald void hal_led_on(void);
10058a1b1bbSMatthias Ringwald 
10158a1b1bbSMatthias Ringwald void hal_led_off(void){
10258a1b1bbSMatthias Ringwald 	// gpio_set_pin_low(GPIOA, GPIO_LED2);
10358a1b1bbSMatthias Ringwald }
10458a1b1bbSMatthias Ringwald void hal_led_on(void){
10558a1b1bbSMatthias Ringwald 	// gpio_set_pin_high(GPIOA, GPIO_LED2);
10658a1b1bbSMatthias Ringwald }
10758a1b1bbSMatthias Ringwald void hal_led_toggle(void){
10858a1b1bbSMatthias Ringwald 	// gpio_toggle_pin(GPIOA, GPIO_LED2);
10958a1b1bbSMatthias Ringwald }
11058a1b1bbSMatthias Ringwald 
11158a1b1bbSMatthias Ringwald // hal_cpu.h implementation
11258a1b1bbSMatthias Ringwald #include "hal_cpu.h"
11358a1b1bbSMatthias Ringwald 
11458a1b1bbSMatthias Ringwald void hal_cpu_disable_irqs(void){
11558a1b1bbSMatthias Ringwald 	//__disable_irq();
11658a1b1bbSMatthias Ringwald }
11758a1b1bbSMatthias Ringwald 
11858a1b1bbSMatthias Ringwald void hal_cpu_enable_irqs(void){
11958a1b1bbSMatthias Ringwald 	// __enable_irq();
12058a1b1bbSMatthias Ringwald }
12158a1b1bbSMatthias Ringwald 
12258a1b1bbSMatthias Ringwald void hal_cpu_enable_irqs_and_sleep(void){
12358a1b1bbSMatthias Ringwald 	hal_led_off();
12458a1b1bbSMatthias Ringwald 	// __enable_irq();
12558a1b1bbSMatthias Ringwald 	// __asm__("wfe");	// go to sleep if event flag isn't set. if set, just clear it. IRQs set event flag
12658a1b1bbSMatthias Ringwald 
12758a1b1bbSMatthias Ringwald 	// note: hal_uart_needed_during_sleep can be used to disable peripheral clock if it's not needed for a timer
12858a1b1bbSMatthias Ringwald 	hal_led_on();
12958a1b1bbSMatthias Ringwald }
13058a1b1bbSMatthias Ringwald 
13158a1b1bbSMatthias Ringwald 
13258a1b1bbSMatthias Ringwald #ifndef USE_XDMAC_FOR_USART
13358a1b1bbSMatthias Ringwald // RX state
13458a1b1bbSMatthias Ringwald static volatile uint16_t  bytes_to_read = 0;
13558a1b1bbSMatthias Ringwald static volatile uint8_t * rx_buffer_ptr = 0;
13658a1b1bbSMatthias Ringwald 
13758a1b1bbSMatthias Ringwald // TX state
13858a1b1bbSMatthias Ringwald static volatile uint16_t  bytes_to_write = 0;
13958a1b1bbSMatthias Ringwald static volatile uint8_t * tx_buffer_ptr = 0;
14058a1b1bbSMatthias Ringwald #endif
14158a1b1bbSMatthias Ringwald 
14258a1b1bbSMatthias Ringwald // handlers
14358a1b1bbSMatthias Ringwald static void (*rx_done_handler)(void) = dummy_handler;
14458a1b1bbSMatthias Ringwald static void (*tx_done_handler)(void) = dummy_handler;
14558a1b1bbSMatthias Ringwald static void (*cts_irq_handler)(void) = dummy_handler;
14658a1b1bbSMatthias Ringwald 
14758a1b1bbSMatthias Ringwald // @note While the Atmel SAM S7x data sheet states
14858a1b1bbSMatthias Ringwald // "The hardware handshaking feature enables an out-of-band flow control by automatic management
14958a1b1bbSMatthias Ringwald //  of the pins RTS and CTS.",
15058a1b1bbSMatthias Ringwald // I didn't see RTS going up automatically up, ever. So, at least for RTS, the automatic management
15158a1b1bbSMatthias Ringwald // is just a glorified GPIO pin control feature, which provides no benefit, but irritates a lot
15258a1b1bbSMatthias Ringwald 
15358a1b1bbSMatthias Ringwald static void hal_uart_rts_high(void){
15458a1b1bbSMatthias Ringwald 	BOARD_USART->US_CR = US_CR_RTSEN;
15558a1b1bbSMatthias Ringwald }
15658a1b1bbSMatthias Ringwald static void hal_uart_rts_low(void){
15758a1b1bbSMatthias Ringwald 	BOARD_USART->US_CR = US_CR_RTSDIS;
15858a1b1bbSMatthias Ringwald }
15958a1b1bbSMatthias Ringwald 
16058a1b1bbSMatthias Ringwald /**
16158a1b1bbSMatthias Ringwald  */
16258a1b1bbSMatthias Ringwald void hal_uart_dma_init(void)
16358a1b1bbSMatthias Ringwald {
164*13b8e9b1SMatthias Ringwald 	// power on
165*13b8e9b1SMatthias Ringwald 	ioport_set_pin_dir(BLUETOOTH_CHP_EN, IOPORT_DIR_OUTPUT);
166*13b8e9b1SMatthias Ringwald 	ioport_set_pin_level(BLUETOOTH_CHP_EN, IOPORT_PIN_LEVEL_HIGH);
167*13b8e9b1SMatthias Ringwald 
168*13b8e9b1SMatthias Ringwald 	// reset
169*13b8e9b1SMatthias Ringwald 	ioport_set_pin_dir(BLUETOOTH_RESET, IOPORT_DIR_OUTPUT);
170*13b8e9b1SMatthias Ringwald 	ioport_set_pin_level(BLUETOOTH_RESET, IOPORT_PIN_LEVEL_LOW);
171*13b8e9b1SMatthias Ringwald 	mdelay(250);
172*13b8e9b1SMatthias Ringwald 	ioport_set_pin_level(BLUETOOTH_RESET, IOPORT_PIN_LEVEL_HIGH);
173*13b8e9b1SMatthias Ringwald 	mdelay(250);
174*13b8e9b1SMatthias Ringwald 
175*13b8e9b1SMatthias Ringwald 	/* Enable the peripheral clock in the PMC. */
176*13b8e9b1SMatthias Ringwald 	sysclk_enable_peripheral_clock(BOARD_ID_USART);
17758a1b1bbSMatthias Ringwald 
17858a1b1bbSMatthias Ringwald 	// configure Bluetooth USART
17958a1b1bbSMatthias Ringwald 	const sam_usart_opt_t bluetooth_settings = {
18058a1b1bbSMatthias Ringwald 		115200,
18158a1b1bbSMatthias Ringwald 		US_MR_CHRL_8_BIT,
18258a1b1bbSMatthias Ringwald 		US_MR_PAR_NO,
18358a1b1bbSMatthias Ringwald 		US_MR_NBSTOP_1_BIT,
18458a1b1bbSMatthias Ringwald 		US_MR_CHMODE_NORMAL,
18558a1b1bbSMatthias Ringwald 		/* This field is only used in IrDA mode. */
18658a1b1bbSMatthias Ringwald 		0
18758a1b1bbSMatthias Ringwald 	};
18858a1b1bbSMatthias Ringwald 
18958a1b1bbSMatthias Ringwald 	/* Configure USART mode. */
190*13b8e9b1SMatthias Ringwald #if 0
19158a1b1bbSMatthias Ringwald 	usart_init_hw_handshaking(BOARD_USART, &bluetooth_settings, sysclk_get_peripheral_hz());
192*13b8e9b1SMatthias Ringwald 	hal_uart_rts_low();
193*13b8e9b1SMatthias Ringwald #else
194*13b8e9b1SMatthias Ringwald 	usart_init_rs232(BOARD_USART, &bluetooth_settings, sysclk_get_peripheral_hz());
195*13b8e9b1SMatthias Ringwald #endif
19658a1b1bbSMatthias Ringwald 
19758a1b1bbSMatthias Ringwald 	/* Disable all the interrupts. */
19858a1b1bbSMatthias Ringwald 	usart_disable_interrupt(BOARD_USART, ALL_INTERRUPT_MASK);
19958a1b1bbSMatthias Ringwald 
20058a1b1bbSMatthias Ringwald 	/* Enable TX & RX function. */
20158a1b1bbSMatthias Ringwald 	usart_enable_tx(BOARD_USART);
20258a1b1bbSMatthias Ringwald 	usart_enable_rx(BOARD_USART);
20358a1b1bbSMatthias Ringwald 
20458a1b1bbSMatthias Ringwald 	/* Configure and enable interrupt of USART. */
20558a1b1bbSMatthias Ringwald 	NVIC_EnableIRQ(USART_IRQn);
20658a1b1bbSMatthias Ringwald 
20758a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
20858a1b1bbSMatthias Ringwald 
20958a1b1bbSMatthias Ringwald 	// setup XDMAC
21058a1b1bbSMatthias Ringwald 
21158a1b1bbSMatthias Ringwald 	/* Initialize and enable DMA controller */
21258a1b1bbSMatthias Ringwald 	pmc_enable_periph_clk(ID_XDMAC);
21358a1b1bbSMatthias Ringwald 
21458a1b1bbSMatthias Ringwald 	/* Enable XDMA interrupt */
21558a1b1bbSMatthias Ringwald 	NVIC_ClearPendingIRQ(XDMAC_IRQn);
21658a1b1bbSMatthias Ringwald 	NVIC_SetPriority( XDMAC_IRQn ,1);
21758a1b1bbSMatthias Ringwald 	NVIC_EnableIRQ(XDMAC_IRQn);
21858a1b1bbSMatthias Ringwald 
21958a1b1bbSMatthias Ringwald 	// Setup XDMA Channel for USART TX
22058a1b1bbSMatthias Ringwald 	xdmac_channel_set_destination_addr(XDMAC, XDMA_CH_UART_TX, (uint32_t)&BOARD_USART->US_THR);
22158a1b1bbSMatthias Ringwald 	xdmac_channel_set_config(XDMAC, XDMA_CH_UART_TX,
22258a1b1bbSMatthias Ringwald 		XDMAC_CC_TYPE_PER_TRAN |
22358a1b1bbSMatthias Ringwald 		XDMAC_CC_DSYNC_MEM2PER |
22458a1b1bbSMatthias Ringwald 		XDMAC_CC_MEMSET_NORMAL_MODE |
22558a1b1bbSMatthias Ringwald 		XDMAC_CC_MBSIZE_SINGLE |
22658a1b1bbSMatthias Ringwald 		XDMAC_CC_DWIDTH_BYTE |
22758a1b1bbSMatthias Ringwald 		XDMAC_CC_SIF_AHB_IF0 |
22858a1b1bbSMatthias Ringwald 		XDMAC_CC_DIF_AHB_IF1 |
22958a1b1bbSMatthias Ringwald 		XDMAC_CC_SAM_INCREMENTED_AM |
23058a1b1bbSMatthias Ringwald 		XDMAC_CC_DAM_FIXED_AM |
23158a1b1bbSMatthias Ringwald 		XDMAC_CC_CSIZE_CHK_1 |
23258a1b1bbSMatthias Ringwald 		XDMAC_CC_PERID(XDAMC_CHANNEL_HWID_USART0_TX)
23358a1b1bbSMatthias Ringwald 	);
23458a1b1bbSMatthias Ringwald 	xdmac_channel_set_descriptor_control(XDMAC, XDMA_CH_UART_TX, 0);
23558a1b1bbSMatthias Ringwald 	xdmac_channel_set_source_microblock_stride(XDMAC, XDMA_CH_UART_TX, 0);
23658a1b1bbSMatthias Ringwald 	xdmac_channel_set_destination_microblock_stride(XDMAC, XDMA_CH_UART_TX, 0);
23758a1b1bbSMatthias Ringwald 	xdmac_channel_set_datastride_mempattern(XDMAC, XDMA_CH_UART_TX, 0);
23858a1b1bbSMatthias Ringwald 	xdmac_channel_set_block_control(XDMAC, XDMA_CH_UART_TX, 0);
23958a1b1bbSMatthias Ringwald 	xdmac_enable_interrupt(XDMAC, XDMA_CH_UART_TX);
24058a1b1bbSMatthias Ringwald 	xdmac_channel_enable_interrupt(XDMAC, XDMA_CH_UART_TX, XDMAC_CIE_BIE);
24158a1b1bbSMatthias Ringwald 
24258a1b1bbSMatthias Ringwald 	// Setup XDMA Channel for USART RX
24358a1b1bbSMatthias Ringwald 	xdmac_channel_set_source_addr(XDMAC, XDMA_CH_UART_RX, (uint32_t)&BOARD_USART->US_RHR);
24458a1b1bbSMatthias Ringwald 	xdmac_channel_set_config(XDMAC, XDMA_CH_UART_RX,
24558a1b1bbSMatthias Ringwald 		XDMAC_CC_TYPE_PER_TRAN |
24658a1b1bbSMatthias Ringwald 		XDMAC_CC_DSYNC_PER2MEM |
24758a1b1bbSMatthias Ringwald 		XDMAC_CC_MEMSET_NORMAL_MODE |
24858a1b1bbSMatthias Ringwald 		XDMAC_CC_MBSIZE_SINGLE |
24958a1b1bbSMatthias Ringwald 		XDMAC_CC_DWIDTH_BYTE |
25058a1b1bbSMatthias Ringwald 		XDMAC_CC_SIF_AHB_IF1 |
25158a1b1bbSMatthias Ringwald 		XDMAC_CC_DIF_AHB_IF0 |
25258a1b1bbSMatthias Ringwald 		XDMAC_CC_SAM_FIXED_AM |
25358a1b1bbSMatthias Ringwald 		XDMAC_CC_DAM_INCREMENTED_AM |
25458a1b1bbSMatthias Ringwald 		XDMAC_CC_CSIZE_CHK_1 |
25558a1b1bbSMatthias Ringwald 		XDMAC_CC_PERID(XDAMC_CHANNEL_HWID_USART0_RX)
25658a1b1bbSMatthias Ringwald 	);
25758a1b1bbSMatthias Ringwald 	xdmac_channel_set_descriptor_control(XDMAC, XDMA_CH_UART_RX, 0);
25858a1b1bbSMatthias Ringwald 	xdmac_channel_set_source_microblock_stride(XDMAC, XDMA_CH_UART_RX, 0);
25958a1b1bbSMatthias Ringwald 	xdmac_channel_set_destination_microblock_stride(XDMAC, XDMA_CH_UART_RX, 0);
26058a1b1bbSMatthias Ringwald 	xdmac_channel_set_datastride_mempattern(XDMAC, XDMA_CH_UART_RX, 0);
26158a1b1bbSMatthias Ringwald 	xdmac_channel_set_block_control(XDMAC, XDMA_CH_UART_RX, 0);
26258a1b1bbSMatthias Ringwald 	xdmac_enable_interrupt(XDMAC, XDMA_CH_UART_RX);
26358a1b1bbSMatthias Ringwald 	xdmac_channel_enable_interrupt(XDMAC, XDMA_CH_UART_RX, XDMAC_CIE_BIE);
26458a1b1bbSMatthias Ringwald #endif
26558a1b1bbSMatthias Ringwald }
26658a1b1bbSMatthias Ringwald 
26758a1b1bbSMatthias Ringwald void hal_uart_dma_set_sleep(uint8_t sleep){
26858a1b1bbSMatthias Ringwald }
26958a1b1bbSMatthias Ringwald 
27058a1b1bbSMatthias Ringwald void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
27158a1b1bbSMatthias Ringwald 	rx_done_handler = the_block_handler;
27258a1b1bbSMatthias Ringwald }
27358a1b1bbSMatthias Ringwald 
27458a1b1bbSMatthias Ringwald void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
27558a1b1bbSMatthias Ringwald 	tx_done_handler = the_block_handler;
27658a1b1bbSMatthias Ringwald }
27758a1b1bbSMatthias Ringwald 
27858a1b1bbSMatthias Ringwald void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
27958a1b1bbSMatthias Ringwald 	cts_irq_handler = the_irq_handler;
28058a1b1bbSMatthias Ringwald }
28158a1b1bbSMatthias Ringwald 
28258a1b1bbSMatthias Ringwald int  hal_uart_dma_set_baud(uint32_t baud){
28358a1b1bbSMatthias Ringwald 	/* Disable TX & RX function. */
28458a1b1bbSMatthias Ringwald 	usart_disable_tx(BOARD_USART);
28558a1b1bbSMatthias Ringwald 	usart_disable_rx(BOARD_USART);
28658a1b1bbSMatthias Ringwald 	uint32_t res = usart_set_async_baudrate(BOARD_USART, baud, sysclk_get_peripheral_hz());
28758a1b1bbSMatthias Ringwald 	if (res){
28858a1b1bbSMatthias Ringwald 		log_error("hal_uart_dma_set_baud library call failed");
28958a1b1bbSMatthias Ringwald 	}
29058a1b1bbSMatthias Ringwald 
29158a1b1bbSMatthias Ringwald 	/* Enable TX & RX function. */
29258a1b1bbSMatthias Ringwald 	usart_enable_tx(BOARD_USART);
29358a1b1bbSMatthias Ringwald 	usart_enable_rx(BOARD_USART);
29458a1b1bbSMatthias Ringwald 
295*13b8e9b1SMatthias Ringwald 	log_info("set baud rate %u", (int) baud);
296*13b8e9b1SMatthias Ringwald 	return 0;
297*13b8e9b1SMatthias Ringwald }
29858a1b1bbSMatthias Ringwald 
299*13b8e9b1SMatthias Ringwald int  hal_uart_dma_set_flowcontrol(uint32_t flowcontrol){
300*13b8e9b1SMatthias Ringwald 	UNUSED(flowcontrol);
30158a1b1bbSMatthias Ringwald 	return 0;
30258a1b1bbSMatthias Ringwald }
30358a1b1bbSMatthias Ringwald 
30458a1b1bbSMatthias Ringwald void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){
305*13b8e9b1SMatthias Ringwald 	// log_info("send %u", size);
306*13b8e9b1SMatthias Ringwald 	// log_info_hexdump(data, size);
30758a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
30858a1b1bbSMatthias Ringwald 	xdmac_channel_get_interrupt_status( XDMAC, XDMA_CH_UART_TX);
30958a1b1bbSMatthias Ringwald 	xdmac_channel_set_source_addr(XDMAC, XDMA_CH_UART_TX, (uint32_t)data);
31058a1b1bbSMatthias Ringwald 	xdmac_channel_set_microblock_control(XDMAC, XDMA_CH_UART_TX, size);
31158a1b1bbSMatthias Ringwald 	xdmac_channel_enable(XDMAC, XDMA_CH_UART_TX);
31258a1b1bbSMatthias Ringwald #else
31358a1b1bbSMatthias Ringwald     tx_buffer_ptr = (uint8_t *) data;
31458a1b1bbSMatthias Ringwald     bytes_to_write = size;
31558a1b1bbSMatthias Ringwald 	usart_enable_interrupt(BOARD_USART, US_IER_TXRDY);
31658a1b1bbSMatthias Ringwald #endif
31758a1b1bbSMatthias Ringwald }
31858a1b1bbSMatthias Ringwald 
31958a1b1bbSMatthias Ringwald void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){
32058a1b1bbSMatthias Ringwald 
32158a1b1bbSMatthias Ringwald 	hal_uart_rts_low();
32258a1b1bbSMatthias Ringwald 
32358a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
32458a1b1bbSMatthias Ringwald 	xdmac_channel_get_interrupt_status( XDMAC, XDMA_CH_UART_RX);
32558a1b1bbSMatthias Ringwald 	xdmac_channel_set_destination_addr(XDMAC, XDMA_CH_UART_RX, (uint32_t)data);
32658a1b1bbSMatthias Ringwald 	xdmac_channel_set_microblock_control(XDMAC, XDMA_CH_UART_RX, size);
32758a1b1bbSMatthias Ringwald 	xdmac_channel_enable(XDMAC, XDMA_CH_UART_RX);
32858a1b1bbSMatthias Ringwald #else
32958a1b1bbSMatthias Ringwald     rx_buffer_ptr = data;
33058a1b1bbSMatthias Ringwald     bytes_to_read = size;
33158a1b1bbSMatthias Ringwald     usart_enable_interrupt(BOARD_USART, US_IER_RXRDY);
33258a1b1bbSMatthias Ringwald #endif
33358a1b1bbSMatthias Ringwald }
33458a1b1bbSMatthias Ringwald 
33558a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
33658a1b1bbSMatthias Ringwald void XDMAC_Handler(void)
33758a1b1bbSMatthias Ringwald {
33858a1b1bbSMatthias Ringwald 	uint32_t dma_status;
33958a1b1bbSMatthias Ringwald 	dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH_UART_TX);
34058a1b1bbSMatthias Ringwald 	if (dma_status & XDMAC_CIS_BIS) {
34158a1b1bbSMatthias Ringwald 		tx_done_handler();
34258a1b1bbSMatthias Ringwald 	}
34358a1b1bbSMatthias Ringwald 	dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH_UART_RX);
34458a1b1bbSMatthias Ringwald 	if (dma_status & XDMAC_CIS_BIS) {
34558a1b1bbSMatthias Ringwald 		hal_uart_rts_high();
34658a1b1bbSMatthias Ringwald 		rx_done_handler();
34758a1b1bbSMatthias Ringwald 	}
34858a1b1bbSMatthias Ringwald }
34958a1b1bbSMatthias Ringwald #else
35058a1b1bbSMatthias Ringwald void USART_Handler(void)
35158a1b1bbSMatthias Ringwald {
35258a1b1bbSMatthias Ringwald 	uint32_t ul_status;
35358a1b1bbSMatthias Ringwald 
35458a1b1bbSMatthias Ringwald 	/* Read USART status. */
35558a1b1bbSMatthias Ringwald 	ul_status = usart_get_status(BOARD_USART);
35658a1b1bbSMatthias Ringwald 
35758a1b1bbSMatthias Ringwald 	// handle ready to send
35858a1b1bbSMatthias Ringwald 	if(ul_status & US_IER_TXRDY) {
35958a1b1bbSMatthias Ringwald 		if (bytes_to_write){
36058a1b1bbSMatthias Ringwald 			// send next byte
36158a1b1bbSMatthias Ringwald 			usart_write(BOARD_USART, *tx_buffer_ptr);
36258a1b1bbSMatthias Ringwald 			tx_buffer_ptr++;
36358a1b1bbSMatthias Ringwald 			bytes_to_write--;
36458a1b1bbSMatthias Ringwald 		} else {
36558a1b1bbSMatthias Ringwald 			// done. disable tx ready interrupt to avoid starvation here
36658a1b1bbSMatthias Ringwald 			usart_disable_interrupt(BOARD_USART, US_IER_TXRDY);
36758a1b1bbSMatthias Ringwald 			tx_done_handler();
36858a1b1bbSMatthias Ringwald 		}
36958a1b1bbSMatthias Ringwald 	}
37058a1b1bbSMatthias Ringwald 
37158a1b1bbSMatthias Ringwald 	// handle byte available for read
37258a1b1bbSMatthias Ringwald 	if (ul_status & US_IER_RXRDY) {
37358a1b1bbSMatthias Ringwald 		uint32_t ch;
37458a1b1bbSMatthias Ringwald 		usart_read(BOARD_USART, (uint32_t *)&ch);
37558a1b1bbSMatthias Ringwald 		*rx_buffer_ptr++ = ch;
37658a1b1bbSMatthias Ringwald 		bytes_to_read--;
37758a1b1bbSMatthias Ringwald 		if (bytes_to_read == 0){
37858a1b1bbSMatthias Ringwald 			// done. disable rx ready interrupt, raise RTS
37958a1b1bbSMatthias Ringwald 			hal_uart_rts_high();
38058a1b1bbSMatthias Ringwald 			usart_disable_interrupt(BOARD_USART, US_IER_RXRDY);
38158a1b1bbSMatthias Ringwald 			rx_done_handler();
38258a1b1bbSMatthias Ringwald 		}
38358a1b1bbSMatthias Ringwald 	}
38458a1b1bbSMatthias Ringwald }
38558a1b1bbSMatthias Ringwald #endif
38658a1b1bbSMatthias Ringwald 
38758a1b1bbSMatthias Ringwald void hal_tick_init()
38858a1b1bbSMatthias Ringwald {
38958a1b1bbSMatthias Ringwald 	/* Configure systick for 1 ms */
39058a1b1bbSMatthias Ringwald 	puts("Configure system tick to get 1ms tick period.\r");
39158a1b1bbSMatthias Ringwald 	if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) {
39258a1b1bbSMatthias Ringwald 		puts("-F- Systick configuration error\r");
39358a1b1bbSMatthias Ringwald 		while (1);
39458a1b1bbSMatthias Ringwald 	}
39558a1b1bbSMatthias Ringwald }
39658a1b1bbSMatthias Ringwald 
39758a1b1bbSMatthias Ringwald void hal_tick_set_handler(void (*handler)(void)){
39858a1b1bbSMatthias Ringwald 	if (handler == NULL){
39958a1b1bbSMatthias Ringwald 		tick_handler = &dummy_handler;
40058a1b1bbSMatthias Ringwald 		return;
40158a1b1bbSMatthias Ringwald 	}
40258a1b1bbSMatthias Ringwald 	tick_handler = handler;
40358a1b1bbSMatthias Ringwald }
40458a1b1bbSMatthias Ringwald 
40558a1b1bbSMatthias Ringwald int  hal_tick_get_tick_period_in_ms(void){
40658a1b1bbSMatthias Ringwald 	return 1;
40758a1b1bbSMatthias Ringwald }
40858a1b1bbSMatthias Ringwald 
409*13b8e9b1SMatthias Ringwald static const btstack_uart_block_t * uart_driver;
410*13b8e9b1SMatthias Ringwald 
411*13b8e9b1SMatthias Ringwald static void phase2(int status){
412*13b8e9b1SMatthias Ringwald 
413*13b8e9b1SMatthias Ringwald     if (status){
414*13b8e9b1SMatthias Ringwald         printf("Download firmware failed\n");
415*13b8e9b1SMatthias Ringwald         return;
416*13b8e9b1SMatthias Ringwald     }
417*13b8e9b1SMatthias Ringwald 
418*13b8e9b1SMatthias Ringwald     printf("Phase 2: Main app\n");
419*13b8e9b1SMatthias Ringwald 
420*13b8e9b1SMatthias Ringwald     // init HCI
421*13b8e9b1SMatthias Ringwald     const hci_transport_t * transport = hci_transport_h4_instance(uart_driver);
422*13b8e9b1SMatthias Ringwald     // const btstack_link_key_db_t * link_key_db = btstack_link_key_db_fs_instance();
423*13b8e9b1SMatthias Ringwald     hci_init(transport, (void*) &transport_config);
424*13b8e9b1SMatthias Ringwald     hci_set_chipset(btstack_chipset_atwilc3000_instance());
425*13b8e9b1SMatthias Ringwald     // hci_set_link_key_db(link_key_db);
426*13b8e9b1SMatthias Ringwald 
427*13b8e9b1SMatthias Ringwald     // setup app
428*13b8e9b1SMatthias Ringwald     btstack_main(0, NULL);
429*13b8e9b1SMatthias Ringwald }
43058a1b1bbSMatthias Ringwald 
4311b2596b5SMatthias Ringwald /**
4321b2596b5SMatthias Ringwald  *  \brief getting-started Application entry point.
4331b2596b5SMatthias Ringwald  *
4341b2596b5SMatthias Ringwald  *  \return Unused (ANSI-C compatibility).
4351b2596b5SMatthias Ringwald  */
4361b2596b5SMatthias Ringwald // [main]
4371b2596b5SMatthias Ringwald int main(void)
4381b2596b5SMatthias Ringwald {
4391b2596b5SMatthias Ringwald 	/* Initialize the SAM system */
4401b2596b5SMatthias Ringwald 	sysclk_init();
4411b2596b5SMatthias Ringwald 	board_init();
4421b2596b5SMatthias Ringwald 
4431b2596b5SMatthias Ringwald 	/* Initialize the console uart */
4441b2596b5SMatthias Ringwald 	configure_console();
4451b2596b5SMatthias Ringwald 
446*13b8e9b1SMatthias Ringwald 	/* Output boot info */
447*13b8e9b1SMatthias Ringwald 	printf("BTstack on SAMV71 Xplained Ultra with ATWILC3000\n");
44858a1b1bbSMatthias Ringwald 	printf("CPU %lu hz, peripheral clock %lu hz\n", sysclk_get_cpu_hz(), sysclk_get_peripheral_hz());
449*13b8e9b1SMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
450*13b8e9b1SMatthias Ringwald 	printf("Using XDMA for Bluetooth UART\n");
451*13b8e9b1SMatthias Ringwald #else
452*13b8e9b1SMatthias Ringwald 	printf("Using IRQ driver for Bluetooth UART\n");
453*13b8e9b1SMatthias Ringwald #endif
454*13b8e9b1SMatthias Ringwald 	printf("--\n");
45558a1b1bbSMatthias Ringwald 
45658a1b1bbSMatthias Ringwald 	// start with BTstack init - especially configure HCI Transport
45758a1b1bbSMatthias Ringwald 	btstack_memory_init();
45858a1b1bbSMatthias Ringwald 	btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
45958a1b1bbSMatthias Ringwald 
46058a1b1bbSMatthias Ringwald 	// enable full log output while porting
461*13b8e9b1SMatthias Ringwald 	hci_dump_open(NULL, HCI_DUMP_STDOUT);
46258a1b1bbSMatthias Ringwald 
463*13b8e9b1SMatthias Ringwald 	// setup UART HAL + Run Loop integration
464*13b8e9b1SMatthias Ringwald 	uart_driver = btstack_uart_block_embedded_instance();
46558a1b1bbSMatthias Ringwald 
466*13b8e9b1SMatthias Ringwald     // extract UART config from transport config, but disable flow control
467*13b8e9b1SMatthias Ringwald     uart_config.baudrate    = transport_config.baudrate_init;
468*13b8e9b1SMatthias Ringwald     uart_config.flowcontrol = 0;
469*13b8e9b1SMatthias Ringwald     uart_config.device_name = transport_config.device_name;
470*13b8e9b1SMatthias Ringwald     uart_driver->init(&uart_config);
47158a1b1bbSMatthias Ringwald 
472*13b8e9b1SMatthias Ringwald     // phase #1 download firmware
473*13b8e9b1SMatthias Ringwald     printf("Phase 1: Download firmware\n");
474*13b8e9b1SMatthias Ringwald 
475*13b8e9b1SMatthias Ringwald     // phase #2 start main app
476*13b8e9b1SMatthias Ringwald     btstack_chipset_atwilc3000_download_firmware(uart_driver, transport_config.baudrate_main, transport_config.flowcontrol, atwilc3000_fw_data, atwilc3000_fw_size, &phase2);
47758a1b1bbSMatthias Ringwald 
47858a1b1bbSMatthias Ringwald 	// go
47958a1b1bbSMatthias Ringwald 	btstack_run_loop_execute();
48058a1b1bbSMatthias Ringwald 
48158a1b1bbSMatthias Ringwald 	// compiler happy
4821b2596b5SMatthias Ringwald 	while(1);
4831b2596b5SMatthias Ringwald }
4841b2596b5SMatthias Ringwald #ifdef __cplusplus
4851b2596b5SMatthias Ringwald }
4861b2596b5SMatthias Ringwald #endif
487