xref: /btstack/port/samv71-xplained-atwilc3000/main.c (revision 99e6df5d021ce7c0f0fa2bbe682a5bad092f4f45)
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
713b8e9b1SMatthias Ringwald #include "btstack_chipset_atwilc3000.h"
813b8e9b1SMatthias Ringwald #include "btstack_debug.h"
913b8e9b1SMatthias 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"
1613b8e9b1SMatthias Ringwald #include "hci.h"
1713b8e9b1SMatthias Ringwald #include "hci_dump.h"
1813b8e9b1SMatthias Ringwald #include "wilc3000_bt_firmware.h"
1958a1b1bbSMatthias Ringwald 
2013b8e9b1SMatthias 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
3013b8e9b1SMatthias Ringwald 
3113b8e9b1SMatthias Ringwald extern int btstack_main(int argc, const char * argv[]);
3213b8e9b1SMatthias Ringwald 
3313b8e9b1SMatthias Ringwald static void dummy_handler(void){}
3413b8e9b1SMatthias Ringwald static void (*tick_handler)(void) = &dummy_handler;
3513b8e9b1SMatthias Ringwald 
3613b8e9b1SMatthias Ringwald static btstack_uart_config_t uart_config;
3713b8e9b1SMatthias Ringwald 
3813b8e9b1SMatthias Ringwald static hci_transport_config_uart_t transport_config = {
3913b8e9b1SMatthias Ringwald 	HCI_TRANSPORT_CONFIG_UART,
40c4572ab1SMatthias Ringwald 	2000000,  // directly use high baud rate after config
41cb9ff2fbSMatthias Ringwald 	0, 		  // use 0 to skip baud rate change from 115200 to X for debugging purposes
4213b8e9b1SMatthias Ringwald 	1,        // flow control
4313b8e9b1SMatthias Ringwald 	NULL,
4413b8e9b1SMatthias 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 
54*99e6df5dSMatthias Ringwald // Debug console Output
55*99e6df5dSMatthias Ringwald 
561b2596b5SMatthias Ringwald /**
571b2596b5SMatthias Ringwald  *  Configure UART console.
581b2596b5SMatthias Ringwald  */
591b2596b5SMatthias Ringwald // [main_console_configure]
601b2596b5SMatthias Ringwald static void configure_console(void)
611b2596b5SMatthias Ringwald {
621b2596b5SMatthias Ringwald 	const usart_serial_options_t uart_serial_options = {
631b2596b5SMatthias Ringwald 		.baudrate = CONF_UART_BAUDRATE,
641b2596b5SMatthias Ringwald #ifdef CONF_UART_CHAR_LENGTH
651b2596b5SMatthias Ringwald 		.charlength = CONF_UART_CHAR_LENGTH,
661b2596b5SMatthias Ringwald #endif
671b2596b5SMatthias Ringwald 		.paritytype = CONF_UART_PARITY,
681b2596b5SMatthias Ringwald #ifdef CONF_UART_STOP_BITS
691b2596b5SMatthias Ringwald 		.stopbits = CONF_UART_STOP_BITS,
701b2596b5SMatthias Ringwald #endif
711b2596b5SMatthias Ringwald 	};
721b2596b5SMatthias Ringwald 
731b2596b5SMatthias Ringwald 	/* Configure console UART. */
741b2596b5SMatthias Ringwald 	sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
751b2596b5SMatthias Ringwald 	stdio_serial_init(CONF_UART, &uart_serial_options);
761b2596b5SMatthias Ringwald }
771b2596b5SMatthias Ringwald 
78*99e6df5dSMatthias Ringwald // Debug console Input
79*99e6df5dSMatthias Ringwald 
80*99e6df5dSMatthias Ringwald #include "btstack_stdin.h"
81*99e6df5dSMatthias Ringwald 
82*99e6df5dSMatthias Ringwald static void (*stdin_handler)(char c);
83*99e6df5dSMatthias Ringwald static btstack_data_source_t stdin_data_source;
84*99e6df5dSMatthias Ringwald 
85*99e6df5dSMatthias Ringwald static void btstack_stdin_process(struct btstack_data_source *ds, btstack_data_source_callback_type_t callback_type){
86*99e6df5dSMatthias Ringwald 	// try to read from console
87*99e6df5dSMatthias Ringwald 	uint32_t stdin_character;
88*99e6df5dSMatthias Ringwald 	uint32_t res = usart_read(CONF_UART, &stdin_character);
89*99e6df5dSMatthias Ringwald 	if (res) return;
90*99e6df5dSMatthias Ringwald 
91*99e6df5dSMatthias Ringwald 	if (stdin_handler){
92*99e6df5dSMatthias Ringwald 		(*stdin_handler)(stdin_character & 0xff);
93*99e6df5dSMatthias Ringwald 	}
94*99e6df5dSMatthias Ringwald }
95*99e6df5dSMatthias Ringwald 
96*99e6df5dSMatthias Ringwald void btstack_stdin_setup(void (*handler)(char c)){
97*99e6df5dSMatthias Ringwald 	// set handler
98*99e6df5dSMatthias Ringwald 	stdin_handler = handler;
99*99e6df5dSMatthias Ringwald 
100*99e6df5dSMatthias Ringwald 	// set up polling data_source
101*99e6df5dSMatthias Ringwald 	btstack_run_loop_set_data_source_handler(&stdin_data_source, &btstack_stdin_process);
102*99e6df5dSMatthias Ringwald 	btstack_run_loop_enable_data_source_callbacks(&stdin_data_source, DATA_SOURCE_CALLBACK_POLL);
103*99e6df5dSMatthias Ringwald 	btstack_run_loop_add_data_source(&stdin_data_source);
104*99e6df5dSMatthias Ringwald }
105*99e6df5dSMatthias Ringwald 
1061b2596b5SMatthias Ringwald // [main_console_configure]
1071b2596b5SMatthias Ringwald 
1081b2596b5SMatthias Ringwald /**
10958a1b1bbSMatthias Ringwald  * \brief Wait for the given number of milliseconds (ticks
1101b2596b5SMatthias Ringwald  * generated by the SAM's microcontrollers's system tick).
1111b2596b5SMatthias Ringwald  *
1121b2596b5SMatthias Ringwald  * \param ul_dly_ticks  Delay to wait for, in milliseconds.
1131b2596b5SMatthias Ringwald  */
1141b2596b5SMatthias Ringwald // [main_ms_delay]
11558a1b1bbSMatthias Ringwald static void mdelay(uint32_t delay_in_ms)
1161b2596b5SMatthias Ringwald {
11758a1b1bbSMatthias Ringwald 	// delay_ms(delay_in_ms);
11858a1b1bbSMatthias Ringwald 	uint32_t time_to_wait = btstack_run_loop_get_time_ms() + delay_in_ms;
11958a1b1bbSMatthias Ringwald 	while (btstack_run_loop_get_time_ms() < time_to_wait);
1201b2596b5SMatthias Ringwald }
1211b2596b5SMatthias Ringwald // [main_ms_delay]
1221b2596b5SMatthias Ringwald 
12358a1b1bbSMatthias Ringwald ////////////////////////////////////////////////////////////////////////////////
12458a1b1bbSMatthias Ringwald // hal_cpu.h implementation
12558a1b1bbSMatthias Ringwald ////////////////////////////////////////////////////////////////////////////////
12658a1b1bbSMatthias Ringwald // hal_led.h implementation
12758a1b1bbSMatthias Ringwald #include "hal_led.h"
12858a1b1bbSMatthias Ringwald void hal_led_off(void);
12958a1b1bbSMatthias Ringwald void hal_led_on(void);
13058a1b1bbSMatthias Ringwald 
13158a1b1bbSMatthias Ringwald void hal_led_off(void){
13258a1b1bbSMatthias Ringwald 	// gpio_set_pin_low(GPIOA, GPIO_LED2);
13358a1b1bbSMatthias Ringwald }
13458a1b1bbSMatthias Ringwald void hal_led_on(void){
13558a1b1bbSMatthias Ringwald 	// gpio_set_pin_high(GPIOA, GPIO_LED2);
13658a1b1bbSMatthias Ringwald }
13758a1b1bbSMatthias Ringwald void hal_led_toggle(void){
13858a1b1bbSMatthias Ringwald 	// gpio_toggle_pin(GPIOA, GPIO_LED2);
13958a1b1bbSMatthias Ringwald }
14058a1b1bbSMatthias Ringwald 
14158a1b1bbSMatthias Ringwald // hal_cpu.h implementation
14258a1b1bbSMatthias Ringwald #include "hal_cpu.h"
14358a1b1bbSMatthias Ringwald 
14458a1b1bbSMatthias Ringwald void hal_cpu_disable_irqs(void){
14558a1b1bbSMatthias Ringwald 	//__disable_irq();
14658a1b1bbSMatthias Ringwald }
14758a1b1bbSMatthias Ringwald 
14858a1b1bbSMatthias Ringwald void hal_cpu_enable_irqs(void){
14958a1b1bbSMatthias Ringwald 	// __enable_irq();
15058a1b1bbSMatthias Ringwald }
15158a1b1bbSMatthias Ringwald 
15258a1b1bbSMatthias Ringwald void hal_cpu_enable_irqs_and_sleep(void){
15358a1b1bbSMatthias Ringwald 	hal_led_off();
15458a1b1bbSMatthias Ringwald 	// __enable_irq();
15558a1b1bbSMatthias Ringwald 	// __asm__("wfe");	// go to sleep if event flag isn't set. if set, just clear it. IRQs set event flag
15658a1b1bbSMatthias Ringwald 
15758a1b1bbSMatthias Ringwald 	// note: hal_uart_needed_during_sleep can be used to disable peripheral clock if it's not needed for a timer
15858a1b1bbSMatthias Ringwald 	hal_led_on();
15958a1b1bbSMatthias Ringwald }
16058a1b1bbSMatthias Ringwald 
16158a1b1bbSMatthias Ringwald 
16258a1b1bbSMatthias Ringwald #ifndef USE_XDMAC_FOR_USART
16358a1b1bbSMatthias Ringwald // RX state
16458a1b1bbSMatthias Ringwald static volatile uint16_t  bytes_to_read = 0;
16558a1b1bbSMatthias Ringwald static volatile uint8_t * rx_buffer_ptr = 0;
16658a1b1bbSMatthias Ringwald 
16758a1b1bbSMatthias Ringwald // TX state
16858a1b1bbSMatthias Ringwald static volatile uint16_t  bytes_to_write = 0;
16958a1b1bbSMatthias Ringwald static volatile uint8_t * tx_buffer_ptr = 0;
17058a1b1bbSMatthias Ringwald #endif
17158a1b1bbSMatthias Ringwald 
172c4572ab1SMatthias Ringwald static volatile int       rx_notify;
173c4572ab1SMatthias Ringwald static volatile int       tx_notify;
174c4572ab1SMatthias Ringwald 
175c267d18bSMatthias Ringwald static int simulate_flowcontrol;
176c267d18bSMatthias Ringwald 
17758a1b1bbSMatthias Ringwald // handlers
17858a1b1bbSMatthias Ringwald static void (*rx_done_handler)(void) = dummy_handler;
17958a1b1bbSMatthias Ringwald static void (*tx_done_handler)(void) = dummy_handler;
18058a1b1bbSMatthias Ringwald static void (*cts_irq_handler)(void) = dummy_handler;
18158a1b1bbSMatthias Ringwald 
18258a1b1bbSMatthias Ringwald // @note While the Atmel SAM S7x data sheet states
18358a1b1bbSMatthias Ringwald // "The hardware handshaking feature enables an out-of-band flow control by automatic management
18458a1b1bbSMatthias Ringwald //  of the pins RTS and CTS.",
18558a1b1bbSMatthias Ringwald // I didn't see RTS going up automatically up, ever. So, at least for RTS, the automatic management
18658a1b1bbSMatthias Ringwald // is just a glorified GPIO pin control feature, which provides no benefit, but irritates a lot
18758a1b1bbSMatthias Ringwald 
188cb9ff2fbSMatthias Ringwald // J505:6
189cb9ff2fbSMatthias Ringwald #define DEBUG_PIN_1 PIO_PD16_IDX
190cb9ff2fbSMatthias Ringwald // J505:5
191cb9ff2fbSMatthias Ringwald #define DEBUG_PIN_2 PIO_PD15_IDX
192cb9ff2fbSMatthias Ringwald 
193c267d18bSMatthias Ringwald static inline void hal_uart_rts_high(void){
194c267d18bSMatthias Ringwald 	if (!simulate_flowcontrol) return;
195cb9ff2fbSMatthias Ringwald 	ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_HIGH);
19658a1b1bbSMatthias Ringwald 	BOARD_USART->US_CR = US_CR_RTSEN;
19758a1b1bbSMatthias Ringwald }
198c267d18bSMatthias Ringwald static inline void hal_uart_rts_low(void){
199c267d18bSMatthias Ringwald 	if (!simulate_flowcontrol) return;
200cb9ff2fbSMatthias Ringwald 	ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW);
20158a1b1bbSMatthias Ringwald 	BOARD_USART->US_CR = US_CR_RTSDIS;
20258a1b1bbSMatthias Ringwald }
20358a1b1bbSMatthias Ringwald 
20458a1b1bbSMatthias Ringwald /**
20558a1b1bbSMatthias Ringwald  */
206cb9ff2fbSMatthias Ringwald static int hal_uart_dma_initialized = 0;
20758a1b1bbSMatthias Ringwald void hal_uart_dma_init(void)
20858a1b1bbSMatthias Ringwald {
209cb9ff2fbSMatthias Ringwald 	if (hal_uart_dma_initialized){
210cb9ff2fbSMatthias Ringwald 		log_info("hal_uart_dma_init already initialized");
211cb9ff2fbSMatthias Ringwald 		return;
212cb9ff2fbSMatthias Ringwald 	}
213cb9ff2fbSMatthias Ringwald 	hal_uart_dma_initialized = 1;
21467422dbdSMatthias Ringwald 
21567422dbdSMatthias Ringwald 	// debug
21667422dbdSMatthias Ringwald #ifdef DEBUG_PIN_1
21767422dbdSMatthias Ringwald 	ioport_set_pin_dir(DEBUG_PIN_1, IOPORT_DIR_OUTPUT);
21867422dbdSMatthias Ringwald 	ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_LOW);
21967422dbdSMatthias Ringwald #endif
22067422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2
22167422dbdSMatthias Ringwald 	ioport_set_pin_dir(DEBUG_PIN_2, IOPORT_DIR_OUTPUT);
22267422dbdSMatthias Ringwald 	ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW);
22367422dbdSMatthias Ringwald #endif
22413b8e9b1SMatthias Ringwald 	// power on
22513b8e9b1SMatthias Ringwald 	ioport_set_pin_dir(BLUETOOTH_CHP_EN, IOPORT_DIR_OUTPUT);
22613b8e9b1SMatthias Ringwald 	ioport_set_pin_level(BLUETOOTH_CHP_EN, IOPORT_PIN_LEVEL_HIGH);
22713b8e9b1SMatthias Ringwald 
22813b8e9b1SMatthias Ringwald 	// reset
22913b8e9b1SMatthias Ringwald 	ioport_set_pin_dir(BLUETOOTH_RESET, IOPORT_DIR_OUTPUT);
23013b8e9b1SMatthias Ringwald 	ioport_set_pin_level(BLUETOOTH_RESET, IOPORT_PIN_LEVEL_LOW);
23113b8e9b1SMatthias Ringwald 	mdelay(250);
23213b8e9b1SMatthias Ringwald 	ioport_set_pin_level(BLUETOOTH_RESET, IOPORT_PIN_LEVEL_HIGH);
23313b8e9b1SMatthias Ringwald 	mdelay(250);
23413b8e9b1SMatthias Ringwald 
23513b8e9b1SMatthias Ringwald 	/* Enable the peripheral clock in the PMC. */
23613b8e9b1SMatthias Ringwald 	sysclk_enable_peripheral_clock(BOARD_ID_USART);
23758a1b1bbSMatthias Ringwald 
23858a1b1bbSMatthias Ringwald 	// configure Bluetooth USART
23958a1b1bbSMatthias Ringwald 	const sam_usart_opt_t bluetooth_settings = {
24058a1b1bbSMatthias Ringwald 		115200,
24158a1b1bbSMatthias Ringwald 		US_MR_CHRL_8_BIT,
24258a1b1bbSMatthias Ringwald 		US_MR_PAR_NO,
24358a1b1bbSMatthias Ringwald 		US_MR_NBSTOP_1_BIT,
24458a1b1bbSMatthias Ringwald 		US_MR_CHMODE_NORMAL,
24558a1b1bbSMatthias Ringwald 		/* This field is only used in IrDA mode. */
24658a1b1bbSMatthias Ringwald 		0
24758a1b1bbSMatthias Ringwald 	};
24858a1b1bbSMatthias Ringwald 
24958a1b1bbSMatthias Ringwald 	/* Configure USART mode. */
250c267d18bSMatthias Ringwald 	simulate_flowcontrol = 0;
25113b8e9b1SMatthias Ringwald 	usart_init_rs232(BOARD_USART, &bluetooth_settings, sysclk_get_peripheral_hz());
252c267d18bSMatthias Ringwald 	// Set RTS = 0 (normal mode)
253c267d18bSMatthias Ringwald 	BOARD_USART->US_CR = US_CR_RTSEN;
25458a1b1bbSMatthias Ringwald 
25558a1b1bbSMatthias Ringwald 	/* Disable all the interrupts. */
25658a1b1bbSMatthias Ringwald 	usart_disable_interrupt(BOARD_USART, ALL_INTERRUPT_MASK);
25758a1b1bbSMatthias Ringwald 
25858a1b1bbSMatthias Ringwald 	/* Enable TX & RX function. */
25958a1b1bbSMatthias Ringwald 	usart_enable_tx(BOARD_USART);
26058a1b1bbSMatthias Ringwald 	usart_enable_rx(BOARD_USART);
26158a1b1bbSMatthias Ringwald 
26258a1b1bbSMatthias Ringwald 	/* Configure and enable interrupt of USART. */
26358a1b1bbSMatthias Ringwald 	NVIC_EnableIRQ(USART_IRQn);
26458a1b1bbSMatthias Ringwald 
26558a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
26658a1b1bbSMatthias Ringwald 
26758a1b1bbSMatthias Ringwald 	// setup XDMAC
26858a1b1bbSMatthias Ringwald 
26958a1b1bbSMatthias Ringwald 	/* Initialize and enable DMA controller */
27058a1b1bbSMatthias Ringwald 	pmc_enable_periph_clk(ID_XDMAC);
27158a1b1bbSMatthias Ringwald 
27258a1b1bbSMatthias Ringwald 	/* Enable XDMA interrupt */
27358a1b1bbSMatthias Ringwald 	NVIC_ClearPendingIRQ(XDMAC_IRQn);
27458a1b1bbSMatthias Ringwald 	NVIC_SetPriority( XDMAC_IRQn ,1);
27558a1b1bbSMatthias Ringwald 	NVIC_EnableIRQ(XDMAC_IRQn);
27658a1b1bbSMatthias Ringwald 
27758a1b1bbSMatthias Ringwald 	// Setup XDMA Channel for USART TX
27858a1b1bbSMatthias Ringwald 	xdmac_channel_set_destination_addr(XDMAC, XDMA_CH_UART_TX, (uint32_t)&BOARD_USART->US_THR);
27958a1b1bbSMatthias Ringwald 	xdmac_channel_set_config(XDMAC, XDMA_CH_UART_TX,
28058a1b1bbSMatthias Ringwald 		XDMAC_CC_TYPE_PER_TRAN |
28158a1b1bbSMatthias Ringwald 		XDMAC_CC_DSYNC_MEM2PER |
28258a1b1bbSMatthias Ringwald 		XDMAC_CC_MEMSET_NORMAL_MODE |
28358a1b1bbSMatthias Ringwald 		XDMAC_CC_MBSIZE_SINGLE |
28458a1b1bbSMatthias Ringwald 		XDMAC_CC_DWIDTH_BYTE |
28558a1b1bbSMatthias Ringwald 		XDMAC_CC_SIF_AHB_IF0 |
28658a1b1bbSMatthias Ringwald 		XDMAC_CC_DIF_AHB_IF1 |
28758a1b1bbSMatthias Ringwald 		XDMAC_CC_SAM_INCREMENTED_AM |
28858a1b1bbSMatthias Ringwald 		XDMAC_CC_DAM_FIXED_AM |
28958a1b1bbSMatthias Ringwald 		XDMAC_CC_CSIZE_CHK_1 |
29058a1b1bbSMatthias Ringwald 		XDMAC_CC_PERID(XDAMC_CHANNEL_HWID_USART0_TX)
29158a1b1bbSMatthias Ringwald 	);
29258a1b1bbSMatthias Ringwald 	xdmac_channel_set_descriptor_control(XDMAC, XDMA_CH_UART_TX, 0);
29358a1b1bbSMatthias Ringwald 	xdmac_channel_set_source_microblock_stride(XDMAC, XDMA_CH_UART_TX, 0);
29458a1b1bbSMatthias Ringwald 	xdmac_channel_set_destination_microblock_stride(XDMAC, XDMA_CH_UART_TX, 0);
29558a1b1bbSMatthias Ringwald 	xdmac_channel_set_datastride_mempattern(XDMAC, XDMA_CH_UART_TX, 0);
29658a1b1bbSMatthias Ringwald 	xdmac_channel_set_block_control(XDMAC, XDMA_CH_UART_TX, 0);
29758a1b1bbSMatthias Ringwald 	xdmac_enable_interrupt(XDMAC, XDMA_CH_UART_TX);
29858a1b1bbSMatthias Ringwald 	xdmac_channel_enable_interrupt(XDMAC, XDMA_CH_UART_TX, XDMAC_CIE_BIE);
29958a1b1bbSMatthias Ringwald 
30058a1b1bbSMatthias Ringwald 	// Setup XDMA Channel for USART RX
30158a1b1bbSMatthias Ringwald 	xdmac_channel_set_source_addr(XDMAC, XDMA_CH_UART_RX, (uint32_t)&BOARD_USART->US_RHR);
30258a1b1bbSMatthias Ringwald 	xdmac_channel_set_config(XDMAC, XDMA_CH_UART_RX,
30358a1b1bbSMatthias Ringwald 		XDMAC_CC_TYPE_PER_TRAN |
30458a1b1bbSMatthias Ringwald 		XDMAC_CC_DSYNC_PER2MEM |
30558a1b1bbSMatthias Ringwald 		XDMAC_CC_MEMSET_NORMAL_MODE |
30658a1b1bbSMatthias Ringwald 		XDMAC_CC_MBSIZE_SINGLE |
30758a1b1bbSMatthias Ringwald 		XDMAC_CC_DWIDTH_BYTE |
30858a1b1bbSMatthias Ringwald 		XDMAC_CC_SIF_AHB_IF1 |
30958a1b1bbSMatthias Ringwald 		XDMAC_CC_DIF_AHB_IF0 |
31058a1b1bbSMatthias Ringwald 		XDMAC_CC_SAM_FIXED_AM |
31158a1b1bbSMatthias Ringwald 		XDMAC_CC_DAM_INCREMENTED_AM |
31258a1b1bbSMatthias Ringwald 		XDMAC_CC_CSIZE_CHK_1 |
31358a1b1bbSMatthias Ringwald 		XDMAC_CC_PERID(XDAMC_CHANNEL_HWID_USART0_RX)
31458a1b1bbSMatthias Ringwald 	);
31558a1b1bbSMatthias Ringwald 	xdmac_channel_set_descriptor_control(XDMAC, XDMA_CH_UART_RX, 0);
31658a1b1bbSMatthias Ringwald 	xdmac_channel_set_source_microblock_stride(XDMAC, XDMA_CH_UART_RX, 0);
31758a1b1bbSMatthias Ringwald 	xdmac_channel_set_destination_microblock_stride(XDMAC, XDMA_CH_UART_RX, 0);
31858a1b1bbSMatthias Ringwald 	xdmac_channel_set_datastride_mempattern(XDMAC, XDMA_CH_UART_RX, 0);
31958a1b1bbSMatthias Ringwald 	xdmac_channel_set_block_control(XDMAC, XDMA_CH_UART_RX, 0);
32058a1b1bbSMatthias Ringwald 	xdmac_enable_interrupt(XDMAC, XDMA_CH_UART_RX);
32158a1b1bbSMatthias Ringwald 	xdmac_channel_enable_interrupt(XDMAC, XDMA_CH_UART_RX, XDMAC_CIE_BIE);
32258a1b1bbSMatthias Ringwald #endif
32358a1b1bbSMatthias Ringwald }
32458a1b1bbSMatthias Ringwald 
32558a1b1bbSMatthias Ringwald void hal_uart_dma_set_sleep(uint8_t sleep){
32658a1b1bbSMatthias Ringwald }
32758a1b1bbSMatthias Ringwald 
32858a1b1bbSMatthias Ringwald void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
32958a1b1bbSMatthias Ringwald 	rx_done_handler = the_block_handler;
33058a1b1bbSMatthias Ringwald }
33158a1b1bbSMatthias Ringwald 
33258a1b1bbSMatthias Ringwald void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
33358a1b1bbSMatthias Ringwald 	tx_done_handler = the_block_handler;
33458a1b1bbSMatthias Ringwald }
33558a1b1bbSMatthias Ringwald 
33658a1b1bbSMatthias Ringwald void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
33758a1b1bbSMatthias Ringwald 	cts_irq_handler = the_irq_handler;
33858a1b1bbSMatthias Ringwald }
33958a1b1bbSMatthias Ringwald 
34058a1b1bbSMatthias Ringwald int  hal_uart_dma_set_baud(uint32_t baud){
34158a1b1bbSMatthias Ringwald 	/* Disable TX & RX function. */
34258a1b1bbSMatthias Ringwald 	usart_disable_tx(BOARD_USART);
34358a1b1bbSMatthias Ringwald 	usart_disable_rx(BOARD_USART);
34458a1b1bbSMatthias Ringwald 	uint32_t res = usart_set_async_baudrate(BOARD_USART, baud, sysclk_get_peripheral_hz());
34558a1b1bbSMatthias Ringwald 	if (res){
34658a1b1bbSMatthias Ringwald 		log_error("hal_uart_dma_set_baud library call failed");
34758a1b1bbSMatthias Ringwald 	}
34858a1b1bbSMatthias Ringwald 
34958a1b1bbSMatthias Ringwald 	/* Enable TX & RX function. */
35058a1b1bbSMatthias Ringwald 	usart_enable_tx(BOARD_USART);
35158a1b1bbSMatthias Ringwald 	usart_enable_rx(BOARD_USART);
35258a1b1bbSMatthias Ringwald 
35313b8e9b1SMatthias Ringwald 	log_info("set baud rate %u", (int) baud);
35413b8e9b1SMatthias Ringwald 	return 0;
35513b8e9b1SMatthias Ringwald }
35658a1b1bbSMatthias Ringwald 
357c267d18bSMatthias Ringwald int  hal_uart_dma_set_flowcontrol(int flowcontrol){
358cb9ff2fbSMatthias Ringwald 	log_info("hal_uart_dma_set_flowcontrol %u", flowcontrol);
359c267d18bSMatthias Ringwald 	simulate_flowcontrol = flowcontrol;
360c267d18bSMatthias Ringwald 	if (flowcontrol){
361c267d18bSMatthias Ringwald 		/* Set hardware handshaking mode. */
362c267d18bSMatthias Ringwald 		BOARD_USART->US_MR = (BOARD_USART->US_MR & ~US_MR_USART_MODE_Msk) | US_MR_USART_MODE_HW_HANDSHAKING;
363cb9ff2fbSMatthias Ringwald 		hal_uart_rts_high();
364c267d18bSMatthias Ringwald 	} else {
365c267d18bSMatthias Ringwald 		/* Set nomal mode. */
366c267d18bSMatthias Ringwald 		BOARD_USART->US_MR = (BOARD_USART->US_MR & ~US_MR_USART_MODE_Msk) | US_MR_USART_MODE_NORMAL;
367c267d18bSMatthias Ringwald 		// Set RTS = 0 (normal mode)
368c267d18bSMatthias Ringwald 		BOARD_USART->US_CR = US_CR_RTSEN;
369c267d18bSMatthias Ringwald 	}
37058a1b1bbSMatthias Ringwald 	return 0;
37158a1b1bbSMatthias Ringwald }
37258a1b1bbSMatthias Ringwald 
37358a1b1bbSMatthias Ringwald void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){
37467422dbdSMatthias Ringwald 
37567422dbdSMatthias Ringwald 	tx_notify = 1;
37667422dbdSMatthias Ringwald 
37758a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
37858a1b1bbSMatthias Ringwald 	xdmac_channel_get_interrupt_status( XDMAC, XDMA_CH_UART_TX);
37958a1b1bbSMatthias Ringwald 	xdmac_channel_set_source_addr(XDMAC, XDMA_CH_UART_TX, (uint32_t)data);
38058a1b1bbSMatthias Ringwald 	xdmac_channel_set_microblock_control(XDMAC, XDMA_CH_UART_TX, size);
38158a1b1bbSMatthias Ringwald 	xdmac_channel_enable(XDMAC, XDMA_CH_UART_TX);
38258a1b1bbSMatthias Ringwald #else
38367422dbdSMatthias Ringwald 	if (bytes_to_write){
38467422dbdSMatthias Ringwald 		log_error("send block, bytes to write %u", bytes_to_write);
38567422dbdSMatthias Ringwald 		return;
38667422dbdSMatthias Ringwald 	}
38758a1b1bbSMatthias Ringwald     tx_buffer_ptr = (uint8_t *) data;
38858a1b1bbSMatthias Ringwald     bytes_to_write = size;
38958a1b1bbSMatthias Ringwald 	usart_enable_interrupt(BOARD_USART, US_IER_TXRDY);
39058a1b1bbSMatthias Ringwald #endif
39158a1b1bbSMatthias Ringwald }
39258a1b1bbSMatthias Ringwald 
39358a1b1bbSMatthias Ringwald void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){
39458a1b1bbSMatthias Ringwald 
395cb9ff2fbSMatthias Ringwald #ifdef DEBUG_PIN_1
396cb9ff2fbSMatthias Ringwald 	ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_HIGH);
397cb9ff2fbSMatthias Ringwald #endif
398cb9ff2fbSMatthias Ringwald 
39958a1b1bbSMatthias Ringwald 	hal_uart_rts_low();
40058a1b1bbSMatthias Ringwald 
401cb9ff2fbSMatthias Ringwald 	rx_notify = 1;
402cb9ff2fbSMatthias Ringwald 
40358a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
40458a1b1bbSMatthias Ringwald 	xdmac_channel_get_interrupt_status( XDMAC, XDMA_CH_UART_RX);
40558a1b1bbSMatthias Ringwald 	xdmac_channel_set_destination_addr(XDMAC, XDMA_CH_UART_RX, (uint32_t)data);
40658a1b1bbSMatthias Ringwald 	xdmac_channel_set_microblock_control(XDMAC, XDMA_CH_UART_RX, size);
40758a1b1bbSMatthias Ringwald 	xdmac_channel_enable(XDMAC, XDMA_CH_UART_RX);
40858a1b1bbSMatthias Ringwald #else
40958a1b1bbSMatthias Ringwald     rx_buffer_ptr = data;
41058a1b1bbSMatthias Ringwald     bytes_to_read = size;
41158a1b1bbSMatthias Ringwald     usart_enable_interrupt(BOARD_USART, US_IER_RXRDY);
41258a1b1bbSMatthias Ringwald #endif
41358a1b1bbSMatthias Ringwald }
41458a1b1bbSMatthias Ringwald 
41558a1b1bbSMatthias Ringwald #ifdef USE_XDMAC_FOR_USART
41658a1b1bbSMatthias Ringwald void XDMAC_Handler(void)
41758a1b1bbSMatthias Ringwald {
41858a1b1bbSMatthias Ringwald 	uint32_t dma_status;
41958a1b1bbSMatthias Ringwald 	dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH_UART_TX);
42058a1b1bbSMatthias Ringwald 	if (dma_status & XDMAC_CIS_BIS) {
42167422dbdSMatthias Ringwald 		if (tx_notify){
42267422dbdSMatthias Ringwald 			tx_notify = 0;
42358a1b1bbSMatthias Ringwald 			tx_done_handler();
42458a1b1bbSMatthias Ringwald 		}
42567422dbdSMatthias Ringwald 	}
42658a1b1bbSMatthias Ringwald 	dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH_UART_RX);
42758a1b1bbSMatthias Ringwald 	if (dma_status & XDMAC_CIS_BIS) {
42858a1b1bbSMatthias Ringwald 		hal_uart_rts_high();
429cb9ff2fbSMatthias Ringwald 		if (rx_notify){
430cb9ff2fbSMatthias Ringwald 			rx_notify = 0;
43158a1b1bbSMatthias Ringwald 			rx_done_handler();
43258a1b1bbSMatthias Ringwald 		}
43358a1b1bbSMatthias Ringwald 	}
434cb9ff2fbSMatthias Ringwald }
43558a1b1bbSMatthias Ringwald #else
43658a1b1bbSMatthias Ringwald void USART_Handler(void)
43758a1b1bbSMatthias Ringwald {
43867422dbdSMatthias Ringwald 
43967422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2
440cb9ff2fbSMatthias Ringwald 	// ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_HIGH);
44167422dbdSMatthias Ringwald #endif
44258a1b1bbSMatthias Ringwald 
44358a1b1bbSMatthias Ringwald 	/* Read USART status. */
44467422dbdSMatthias Ringwald 	uint32_t ul_status = usart_get_status(BOARD_USART);
44558a1b1bbSMatthias Ringwald 
44658a1b1bbSMatthias Ringwald 	// handle ready to send
44758a1b1bbSMatthias Ringwald 	if(ul_status & US_IER_TXRDY) {
44858a1b1bbSMatthias Ringwald 		if (bytes_to_write){
44958a1b1bbSMatthias Ringwald 			// send next byte
45058a1b1bbSMatthias Ringwald 			usart_write(BOARD_USART, *tx_buffer_ptr);
45158a1b1bbSMatthias Ringwald 			tx_buffer_ptr++;
45258a1b1bbSMatthias Ringwald 			bytes_to_write--;
45358a1b1bbSMatthias Ringwald 		} else {
45467422dbdSMatthias Ringwald 
45558a1b1bbSMatthias Ringwald 			// done. disable tx ready interrupt to avoid starvation here
45658a1b1bbSMatthias Ringwald 			usart_disable_interrupt(BOARD_USART, US_IER_TXRDY);
45767422dbdSMatthias Ringwald 			if (tx_notify){
45867422dbdSMatthias Ringwald 				tx_notify = 0;
45958a1b1bbSMatthias Ringwald 				tx_done_handler();
46058a1b1bbSMatthias Ringwald 			}
46158a1b1bbSMatthias Ringwald 		}
46267422dbdSMatthias Ringwald 	}
46358a1b1bbSMatthias Ringwald 
46458a1b1bbSMatthias Ringwald 	// handle byte available for read
46558a1b1bbSMatthias Ringwald 	if (ul_status & US_IER_RXRDY) {
4665c5e4857SMatthias Ringwald 		if (bytes_to_read){
46758a1b1bbSMatthias Ringwald 			uint32_t ch;
46858a1b1bbSMatthias Ringwald 			usart_read(BOARD_USART, (uint32_t *)&ch);
46958a1b1bbSMatthias Ringwald 			*rx_buffer_ptr++ = ch;
47058a1b1bbSMatthias Ringwald 			bytes_to_read--;
47158a1b1bbSMatthias Ringwald 			if (bytes_to_read == 0){
472cb9ff2fbSMatthias Ringwald 
473cb9ff2fbSMatthias Ringwald #ifdef DEBUG_PIN_1
474cb9ff2fbSMatthias Ringwald 			ioport_set_pin_level(DEBUG_PIN_1, IOPORT_PIN_LEVEL_LOW);
475cb9ff2fbSMatthias Ringwald #endif
476cb9ff2fbSMatthias Ringwald 
47758a1b1bbSMatthias Ringwald 				// done. disable rx ready interrupt, raise RTS
47858a1b1bbSMatthias Ringwald 				hal_uart_rts_high();
47958a1b1bbSMatthias Ringwald 				usart_disable_interrupt(BOARD_USART, US_IER_RXRDY);
480cb9ff2fbSMatthias Ringwald 				if (rx_notify){
481cb9ff2fbSMatthias Ringwald 					rx_notify = 0;
48258a1b1bbSMatthias Ringwald 					rx_done_handler();
48358a1b1bbSMatthias Ringwald 				}
484cb9ff2fbSMatthias Ringwald 			}
4855c5e4857SMatthias Ringwald 		} else {
4865c5e4857SMatthias Ringwald 			// shoult not happen, disable irq anyway
4875c5e4857SMatthias Ringwald 			usart_disable_interrupt(BOARD_USART, US_IER_RXRDY);
4885c5e4857SMatthias Ringwald 		}
48958a1b1bbSMatthias Ringwald 	}
49067422dbdSMatthias Ringwald #ifdef DEBUG_PIN_2
491cb9ff2fbSMatthias Ringwald 	// ioport_set_pin_level(DEBUG_PIN_2, IOPORT_PIN_LEVEL_LOW);
49267422dbdSMatthias Ringwald #endif
49367422dbdSMatthias Ringwald 
49458a1b1bbSMatthias Ringwald }
49558a1b1bbSMatthias Ringwald #endif
49658a1b1bbSMatthias Ringwald 
49758a1b1bbSMatthias Ringwald void hal_tick_init()
49858a1b1bbSMatthias Ringwald {
49958a1b1bbSMatthias Ringwald 	/* Configure systick for 1 ms */
50058a1b1bbSMatthias Ringwald 	puts("Configure system tick to get 1ms tick period.\r");
50158a1b1bbSMatthias Ringwald 	if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) {
50258a1b1bbSMatthias Ringwald 		puts("-F- Systick configuration error\r");
50358a1b1bbSMatthias Ringwald 		while (1);
50458a1b1bbSMatthias Ringwald 	}
50558a1b1bbSMatthias Ringwald }
50658a1b1bbSMatthias Ringwald 
50758a1b1bbSMatthias Ringwald void hal_tick_set_handler(void (*handler)(void)){
50858a1b1bbSMatthias Ringwald 	if (handler == NULL){
50958a1b1bbSMatthias Ringwald 		tick_handler = &dummy_handler;
51058a1b1bbSMatthias Ringwald 		return;
51158a1b1bbSMatthias Ringwald 	}
51258a1b1bbSMatthias Ringwald 	tick_handler = handler;
51358a1b1bbSMatthias Ringwald }
51458a1b1bbSMatthias Ringwald 
51558a1b1bbSMatthias Ringwald int  hal_tick_get_tick_period_in_ms(void){
51658a1b1bbSMatthias Ringwald 	return 1;
51758a1b1bbSMatthias Ringwald }
51858a1b1bbSMatthias Ringwald 
51913b8e9b1SMatthias Ringwald static const btstack_uart_block_t * uart_driver;
52013b8e9b1SMatthias Ringwald 
52113b8e9b1SMatthias Ringwald static void phase2(int status){
52213b8e9b1SMatthias Ringwald 
52313b8e9b1SMatthias Ringwald     if (status){
52413b8e9b1SMatthias Ringwald         printf("Download firmware failed\n");
52513b8e9b1SMatthias Ringwald         return;
52613b8e9b1SMatthias Ringwald     }
52713b8e9b1SMatthias Ringwald 
52813b8e9b1SMatthias Ringwald     printf("Phase 2: Main app\n");
52913b8e9b1SMatthias Ringwald 
53013b8e9b1SMatthias Ringwald     // init HCI
53113b8e9b1SMatthias Ringwald     const hci_transport_t * transport = hci_transport_h4_instance(uart_driver);
53213b8e9b1SMatthias Ringwald     // const btstack_link_key_db_t * link_key_db = btstack_link_key_db_fs_instance();
53313b8e9b1SMatthias Ringwald     hci_init(transport, (void*) &transport_config);
53413b8e9b1SMatthias Ringwald     hci_set_chipset(btstack_chipset_atwilc3000_instance());
53513b8e9b1SMatthias Ringwald     // hci_set_link_key_db(link_key_db);
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
57113b8e9b1SMatthias Ringwald 	hci_dump_open(NULL, HCI_DUMP_STDOUT);
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
5866e0d5aedSMatthias Ringwald     btstack_chipset_atwilc3000_download_firmware(uart_driver, transport_config.baudrate_init, transport_config.flowcontrol, atwilc3000_fw_data, atwilc3000_fw_size, &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