#include "uart.h" #include "bsp/shark_bsp.h" #include "bsp/gpio.h" #include "libs/shark_libs.h" #define SHARK_UART_BAUDRATE 38400 #define SHARK_UART0_com USART0 #define SHARK_UART0_tx_port GPIOB #define SHARK_UART0_tx_pin GPIO_PIN_6 #define SHARK_UART0_rx_port GPIOB #define SHARK_UART0_rx_pin GPIO_PIN_7 #define SHARK_UART0_irq USART0_IRQn #define SHARK_UART0_clk RCU_USART0 #define SHARK_UART0_tx_gpio_clk RCU_GPIOB #define SHARK_UART0_rx_gpio_clk RCU_GPIOB #define SHARK_UART0_tx_dma DMA #define SHARK_UART0_tx_dma_ch DMA_CH1 #define SHARK_UART0_tx_dma_clk RCU_DMA #define SHARK_UART0_rx_dma DMA #define SHARK_UART0_rx_dma_ch DMA_CH2 #define SHARK_UART0_rx_dma_clk RCU_DMA #define SHARK_UART1_com USART1 #define SHARK_UART1_tx_port GPIOA #define SHARK_UART1_tx_pin GPIO_PIN_2 #define SHARK_UART1_rx_port GPIOA #define SHARK_UART1_rx_pin GPIO_PIN_3 #define SHARK_UART1_irq USART1_IRQn #define SHARK_UART1_clk RCU_USART1 #define SHARK_UART1_tx_gpio_clk RCU_GPIOA #define SHARK_UART1_rx_gpio_clk RCU_GPIOA #define SHARK_UART1_tx_dma DMA #define SHARK_UART1_tx_dma_ch DMA_CH3 #define SHARK_UART1_tx_dma_clk RCU_DMA #define SHARK_UART1_rx_dma DMA #define SHARK_UART1_rx_dma_ch DMA_CH4 #define SHARK_UART1_rx_dma_clk RCU_DMA // ================================================================================ static u8 shark_uart0_tx_cache[SHARK_UART_TX_MEM_SIZE]; #if UART_NUM==2 static u8 shark_uart1_tx_cache[SHARK_UART_TX_MEM_SIZE]; #endif static u8 shark_uart_rx_cache[SHARK_UART_RX_MEM_SIZE]; static shark_uart_t _shark_uart[UART_NUM]; static shark_task_t _uart_task; static u64 _rx_time; ///static bool uart_no_data = false; #define update_dma_w_pos(uart) circle_update_write_position(&uart->rx_queue, SHARK_UART_RX_MEM_SIZE - DMA_CHCNT(uart->rx_dma_ch)) extern void protocol_recv_frame(uart_enum_t uart_no, char *data, int len); extern void protocol_old_recv_frame(uart_enum_t uart_no, uint8_t *data, int len); // ================================================================================ static uart_enum_t _uart_index(uint32_t com){ return com == SHARK_UART0_com?SHARK_UART0:SHARK_UART1; } static bool shark_uart_on_rx_frame(shark_uart_t *uart) { u16 crc0 = shark_decode_u16(uart->rx_frame + uart->rx_length); u16 crc1 = shark_crc16_check(uart->rx_frame, uart->rx_length); if (crc0 != crc1) { return false; } protocol_recv_frame(_uart_index(uart->uart_com), (char *)uart->rx_frame, uart->rx_length); return true; } static void shark_uart_rx(shark_uart_t *uart){ while(1) { u8 data; update_dma_w_pos(uart); if (circle_get_one_data(&uart->rx_queue, &data) != 1) { if (shark_get_mseconds() >= (30 + _rx_time)) { //_rx_time = 0xFFFFFFFFFFFFL; if (uart->rx_length_old_prot > 0){ protocol_old_recv_frame(_uart_index(uart->uart_com), uart->rx_frame_old_prot, uart->rx_length_old_prot); uart->rx_length_old_prot = 0; } } if (shark_get_mseconds() >= (UART_TIMEOUT + _rx_time)){ uart->uart_no_data = true; }else { uart->uart_no_data = false; } break; } _rx_time = shark_get_mseconds(); uart->rx_frame_old_prot[uart->rx_length_old_prot ++] = data; if (uart->rx_length_old_prot == sizeof(uart->rx_frame_old_prot)){ uart->rx_length_old_prot = 0; } switch(data){ case CH_START: uart->rx_length = 0; uart->escape = false; break; case CH_END: if (uart->rx_length > 2 && uart->rx_length != 0xFFFF){ uart->rx_length -= 2; //skip crc shark_uart_on_rx_frame(uart); } uart->rx_length = 0xFFFF; break; case CH_ESC: uart->escape = true; break; default: if (uart->escape) { uart->escape = false; switch (data) { case CH_ESC_START: data = CH_START; break; case CH_ESC_END: data = CH_END; break; case CH_ESC_ESC: data = CH_ESC; break; default: data = 0xFF; } } if (uart->rx_length < sizeof(uart->rx_frame)) { uart->rx_frame[uart->rx_length] = data; uart->rx_length++; } else { uart->rx_length = 0xFFFF; } } } } static void shark_uart_dma_tx(shark_uart_t *uart) { u32 value = DMA_CHCTL(uart->tx_dma_ch); if (value & DMA_CHXCTL_CHEN) { if (SET != dma_flag_get(uart->tx_dma_ch, DMA_FLAG_FTF)) { return; } byte_queue_skip(&uart->tx_queue, uart->tx_length); DMA_CHCTL(uart->tx_dma_ch) = value & (~DMA_CHXCTL_CHEN); } uart->tx_length = byte_queue_peek(&uart->tx_queue); if (uart->tx_length > 0) { DMA_CHCNT(uart->tx_dma_ch) = uart->tx_length; DMA_CHMADDR(uart->tx_dma_ch) = (u32) byte_queue_head(&uart->tx_queue); dma_flag_clear(uart->tx_dma_ch, DMA_FLAG_FTF); DMA_CHCTL(uart->tx_dma_ch) = value | DMA_CHXCTL_CHEN; } } static void shark_uart_write(shark_uart_t *uart, const u8 *buff, u16 size) { while (size > 0) { u16 length = byte_queue_write(&uart->tx_queue, buff, size); if (length == size) { shark_uart_dma_tx(uart); break; } shark_uart_dma_tx(uart); buff += length; size -= length; } } static void shark_uart_write_byte(shark_uart_t *uart, u8 value) { shark_uart_write(uart, &value, 1); } static void shark_uart_tx_dma_init(shark_uart_t *uart){ dma_parameter_struct dma_init_struct; rcu_periph_clock_enable(_uart_index(uart->uart_com)== SHARK_UART0?SHARK_UART0_tx_dma_clk:SHARK_UART1_tx_dma_clk); dma_deinit(uart->tx_dma_ch); dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.periph_addr = (u32) &USART_TDATA(uart->uart_com); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; dma_init(uart->tx_dma_ch, &dma_init_struct); dma_circulation_disable(uart->tx_dma_ch); dma_memory_to_memory_disable(uart->tx_dma_ch); usart_dma_transmit_config(uart->uart_com, USART_DENT_ENABLE); #if 0 if (uart->tx_dma_ch == DMA_CH1) { nvic_irq_enable(DMA_Channel1_2_IRQn ,4, 0); }else { nvic_irq_enable(DMA_Channel3_4_IRQn ,4, 0); } dma_interrupt_enable(uart->tx_dma_ch, DMA_INT_FTF); #endif } static void shark_uart_rx_dma_init(shark_uart_t *uart){ dma_parameter_struct dma_init_struct; rcu_periph_clock_enable(_uart_index(uart->uart_com)== SHARK_UART0?SHARK_UART0_rx_dma_clk:SHARK_UART1_rx_dma_clk); dma_deinit(uart->rx_dma_ch); dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.memory_addr = (u32)uart->rx_queue.buffer; dma_init_struct.number = uart->rx_queue.buffer_len; dma_init_struct.periph_addr = (u32) &USART_RDATA(uart->uart_com); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; dma_init(uart->rx_dma_ch, &dma_init_struct); dma_circulation_enable(uart->rx_dma_ch); dma_memory_to_memory_disable(uart->rx_dma_ch); dma_channel_enable(uart->rx_dma_ch); usart_dma_receive_config(uart->uart_com, USART_DENR_ENABLE); } static void shark_uart_pin_init(shark_uart_t *uart){ if (_uart_index(uart->uart_com) == SHARK_UART0) { rcu_periph_clock_enable(SHARK_UART0_clk); rcu_periph_clock_enable(SHARK_UART0_rx_gpio_clk); rcu_periph_clock_enable(SHARK_UART0_tx_gpio_clk); gpio_af_set(SHARK_UART0_tx_port, GPIO_AF_0,SHARK_UART0_tx_pin); gpio_mode_set(SHARK_UART0_tx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SHARK_UART0_tx_pin); gpio_output_options_set(SHARK_UART0_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SHARK_UART0_tx_pin); gpio_af_set(SHARK_UART0_rx_port, GPIO_AF_0,SHARK_UART0_rx_pin); gpio_mode_set(SHARK_UART0_rx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SHARK_UART0_rx_pin); gpio_output_options_set(SHARK_UART0_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SHARK_UART0_rx_pin); }else { rcu_periph_clock_enable(SHARK_UART1_clk); rcu_periph_clock_enable(SHARK_UART1_rx_gpio_clk); rcu_periph_clock_enable(SHARK_UART1_tx_gpio_clk); gpio_af_set(SHARK_UART1_tx_port, GPIO_AF_1,SHARK_UART1_tx_pin); gpio_mode_set(SHARK_UART1_tx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SHARK_UART1_tx_pin); gpio_output_options_set(SHARK_UART1_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SHARK_UART1_tx_pin); gpio_af_set(SHARK_UART1_rx_port, GPIO_AF_1,SHARK_UART1_rx_pin); gpio_mode_set(SHARK_UART1_rx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SHARK_UART1_rx_pin); gpio_output_options_set(SHARK_UART1_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SHARK_UART1_rx_pin); } } static void shark_uart_pin_deinit(shark_uart_t *uart){ if (_uart_index(uart->uart_com) == SHARK_UART0) { gpio_mode_set(SHARK_UART0_tx_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SHARK_UART0_tx_pin); gpio_mode_set(SHARK_UART0_rx_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SHARK_UART0_rx_pin); }else { gpio_mode_set(SHARK_UART1_tx_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SHARK_UART1_tx_pin); gpio_mode_set(SHARK_UART1_rx_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SHARK_UART1_rx_pin); } } static void shark_uart_device_init(shark_uart_t *uart){ usart_deinit(uart->uart_com); usart_baudrate_set(uart->uart_com, SHARK_UART_BAUDRATE); usart_word_length_set(uart->uart_com, USART_WL_8BIT); usart_stop_bit_set(uart->uart_com, USART_STB_1BIT); usart_parity_config(uart->uart_com, USART_PM_NONE); usart_hardware_flow_rts_config(uart->uart_com, USART_RTS_DISABLE); usart_hardware_flow_cts_config(uart->uart_com, USART_CTS_DISABLE); usart_receive_config(uart->uart_com, USART_RECEIVE_ENABLE); usart_transmit_config(uart->uart_com, USART_TRANSMIT_ENABLE); } static u32 shark_uart_handler(void) { shark_uart_t *uart = _shark_uart + SHARK_UART0; if (uart->uart_com != 0) { shark_uart_rx(uart); shark_uart_dma_tx(uart); } #if UART_NUM==2 uart = _shark_uart + SHARK_UART1; if (uart->uart_com != 0) { shark_uart_rx(uart); shark_uart_dma_tx(uart); } #endif return 0; } void shark_uart_flush(void){ shark_uart_t *uart = _shark_uart + SHARK_UART0; if (uart->uart_com != 0) { shark_uart_dma_tx(uart); } #if UART_NUM==2 uart = _shark_uart + SHARK_UART1; if (uart->uart_com != 0) { shark_uart_dma_tx(uart); } #endif } #if 0 void DMA_Channel1_2_IRQHandler(void){ shark_uart_t *uart = _shark_uart + SHARK_UART0; if (dma_interrupt_flag_get(uart->tx_dma_ch, DMA_INT_FLAG_FTF) != RESET){ shark_uart_dma_tx(uart); dma_interrupt_flag_clear(uart->tx_dma_ch, DMA_INT_FLAG_FTF); } } void DMA_Channel3_4_IRQHandler(void){ shark_uart_t *uart = _shark_uart + SHARK_UART1; if (dma_interrupt_flag_get(uart->tx_dma_ch, DMA_INT_FLAG_FTF) != RESET){ shark_uart_dma_tx(uart); dma_interrupt_flag_clear(uart->tx_dma_ch, DMA_INT_FLAG_FTF); } } #endif static u8 *tx_cache_addr(uart_enum_t uart_no){ #if UART_NUM==2 return (uart_no == SHARK_UART0)?shark_uart0_tx_cache:shark_uart1_tx_cache; #else return shark_uart0_tx_cache; #endif } void shark_uart_deinit(uart_enum_t uart_no){ shark_uart_t *uart = _shark_uart + uart_no; if (uart->uart_com != 0) { usart_disable(uart->uart_com); usart_deinit(uart->uart_com); rcu_periph_clock_disable(uart_no == SHARK_UART0?SHARK_UART0_clk:SHARK_UART1_clk); dma_channel_disable(uart->rx_dma_ch); dma_channel_disable(uart->tx_dma_ch); rcu_periph_clock_disable(uart_no == SHARK_UART0?SHARK_UART0_tx_dma_clk:SHARK_UART1_tx_dma_clk); rcu_periph_clock_disable(uart_no == SHARK_UART0?SHARK_UART0_rx_dma_clk:SHARK_UART1_rx_dma_clk); shark_uart_pin_deinit(uart); } if (uart_no == SHARK_UART0) { UART0_IR_EN(0); }else { UART1_IR_EN(0); } } bool shark_uart_timeout(void){ #if UART_NUM==2 return (_shark_uart[0].uart_no_data && _shark_uart[1].uart_no_data)?TRUE:FALSE; #else return (_shark_uart[0].uart_no_data)?TRUE:FALSE; #endif } void shark_uart_init(uart_enum_t uart_no) { shark_uart_t *uart = _shark_uart + uart_no; uart->escape = false; uart->rx_length = 0; uart->tx_length = 0; uart->uart_com = (uart_no == SHARK_UART0)?SHARK_UART0_com:SHARK_UART1_com; circle_buffer_init(&uart->rx_queue, shark_uart_rx_cache, SHARK_UART_TX_MEM_SIZE); byte_queue_init(&uart->tx_queue,tx_cache_addr(uart_no), SHARK_UART_TX_MEM_SIZE); uart->rx_dma_ch = (uart_no == SHARK_UART0)?SHARK_UART0_rx_dma_ch:SHARK_UART1_rx_dma_ch; uart->tx_dma_ch = (uart_no == SHARK_UART0)?SHARK_UART0_tx_dma_ch:SHARK_UART1_tx_dma_ch; shark_uart_pin_init(uart); shark_uart_device_init(uart); shark_uart_rx_dma_init(uart); shark_uart_tx_dma_init(uart); usart_enable(uart->uart_com); if (_uart_task.handler == NULL) { _uart_task.handler = shark_uart_handler; shark_task_add(&_uart_task); } if (uart_no == SHARK_UART0) { UART0_IR_EN(1); }else { UART1_IR_EN(1); } _rx_time = shark_get_mseconds(); uart->uart_no_data = false; } static void shark_uart_write_byte_esc(shark_uart_t *uart, u8 value) { switch (value) { case CH_START: shark_uart_write_byte(uart, CH_ESC); value = CH_ESC_START; break; case CH_END: shark_uart_write_byte(uart, CH_ESC); value = CH_ESC_END; break; case CH_ESC: shark_uart_write_byte(uart, CH_ESC); value = CH_ESC_ESC; break; } shark_uart_write_byte(uart, value); } static void shark_uart_write_esc(shark_uart_t *uart, const u8 *buff, u16 length) { const u8 *buff_end; for (buff_end = buff + length; buff < buff_end; buff++) { shark_uart_write_byte_esc(uart, *buff); } } static void shark_uart_tx_start(shark_uart_t *uart) { shark_uart_write_byte(uart, CH_START); uart->tx_crc16 = 0; } static void shark_uart_tx_continue(shark_uart_t *uart, const void *buff, u16 length) { shark_uart_write_esc(uart, (const u8 *) buff, length); uart->tx_crc16 = shark_crc16_update(uart->tx_crc16, (const u8 *) buff, length); } static void shark_uart_tx_end(shark_uart_t *uart) { shark_uart_write_esc(uart, (u8 *)&uart->tx_crc16, sizeof(uart->tx_crc16)); shark_uart_write_byte(uart, CH_END); } void shark_uart_write_frame(uart_enum_t uart_no, uint8_t *bytes, int len){ shark_uart_t *uart = _shark_uart + uart_no; shark_uart_tx_start(uart); shark_uart_tx_continue(uart, bytes, len); shark_uart_tx_end(uart); } void shark_uart_frame_start(uart_enum_t uart_no, uint8_t *bytes, int len){ shark_uart_t *uart = _shark_uart + uart_no; shark_uart_tx_start(uart); shark_uart_tx_continue(uart, bytes, len); } void shark_uart_frame_continue(uart_enum_t uart_no, uint8_t *bytes, int len){ shark_uart_t *uart = _shark_uart + uart_no; shark_uart_tx_continue(uart, bytes, len); } void shark_uart_frame_end(uart_enum_t uart_no){ shark_uart_tx_end(_shark_uart + uart_no); } void shark_uart_write_bytes(uart_enum_t uart_no, u8 *buff, u16 size){ shark_uart_write(_shark_uart + uart_no, buff, size); }