#include "uart.h" #include "os/os_task.h" #include "libs/crc16.h" #include "libs/logger.h" #include "libs/utils.h" #define SHARK_UART_BAUDRATE 230400 #ifdef DEBUG_PORT_UART1 #define SHARK_UART0_com USART1 #define SHARK_UART0_tx_port GPIOA #define SHARK_UART0_tx_pin GPIO_PIN_2 #define SHARK_UART0_rx_port GPIOA #define SHARK_UART0_rx_pin GPIO_PIN_3 #define SHARK_UART0_irq USART1_IRQn #define SHARK_UART0_clk RCU_USART1 #define SHARK_UART0_tx_gpio_clk RCU_GPIOA #define SHARK_UART0_rx_gpio_clk RCU_GPIOA #define SHARK_UART0_tx_dma DMA0 #define SHARK_UART0_tx_dma_ch DMA_CH6 #define SHARK_UART0_tx_dma_clk RCU_DMA0 #define SHARK_UART0_rx_dma DMA0 #define SHARK_UART0_rx_dma_ch DMA_CH5 #define SHARK_UART0_rx_dma_clk RCU_DMA0 #define SHARK_UART0_DMA_TX_IRQ DMA0_Channel6_IRQn #define UART_DMA_IRQHandler DMA0_Channel6_IRQHandler #else #define SHARK_UART0_com USART3 #define SHARK_UART0_tx_port GPIOB #define SHARK_UART0_tx_pin GPIO_PINS_10 #define SHARK_UART0_rx_port GPIOB #define SHARK_UART0_rx_pin GPIO_PINS_11 #define SHARK_UART0_irq USART3_IRQn #define SHARK_UART0_clk CRM_USART3_PERIPH_CLOCK #define SHARK_UART0_tx_gpio_clk CRM_GPIOB_PERIPH_CLOCK #define SHARK_UART0_rx_gpio_clk CRM_GPIOB_PERIPH_CLOCK #define SHARK_UART0_tx_dma DMA1 #define SHARK_UART0_tx_dma_ch DMA1_CHANNEL2 #define SHARK_UART0_tx_dma_clk CRM_DMA1_PERIPH_CLOCK #define SHARK_UART0_rx_dma DMA1 #define SHARK_UART0_rx_dma_ch DMA1_CHANNEL3 #define SHARK_UART0_rx_dma_clk CRM_DMA1_PERIPH_CLOCK #define SHARK_UART0_DMA_TX_IRQ DMA0_Channel3_IRQn #define UART_DMA_IRQHandler DMA1_Channel3_IRQHandler #endif // ================================================================================ #define ENABLE_RX_DMA 1 static u8 shark_uart0_tx_cache[SHARK_UART_TX_MEM_SIZE]; static u8 shark_uart0_rx_cache[SHARK_UART_RX_MEM_SIZE]; static shark_uart_t _shark_uart[1]; ///static bool uart_no_data = false; #if ENABLE_RX_DMA==1 #define update_dma_w_pos(uart) circle_update_write_position(&uart->rx_queue, SHARK_UART_RX_MEM_SIZE - SHARK_UART0_rx_dma_ch->dtcnt) #else #define update_dma_w_pos(uart){} #endif // ================================================================================ static usart_type *_uart_index(usart_type* com){ return SHARK_UART0; } static bool shark_uart_on_rx_frame(shark_uart_t *uart) { u16 crc0 = decode_u16(uart->rx_frame + uart->rx_length); u16 crc1 = crc16_get(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 = 0; update_dma_w_pos(uart); if (circle_get_one_data(&uart->rx_queue, &data) != 1) { return; } switch(data){ case CH_START: uart->rx_length = 0; uart->escape = false; uart->start = true; 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; uart->start = false; 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; } } } } #define DMA_CHCTL(dma, dma_ch) ((dma_channel_type *)dma_ch)->ctrl #define DMA_CHMADDR(dma, dma_ch) ((dma_channel_type *)dma_ch)->maddr #define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ static void shark_uart_dma_tx(shark_uart_t *uart) { u32 value = DMA_CHCTL(SHARK_UART0_tx_dma, uart->tx_dma_ch); if (value & DMA_CHXCTL_CHEN) { if (SET != dma_flag_get(DMA1_FDT1_FLAG)) { return; } dma_flag_clear(DMA1_FDT1_FLAG); byte_queue_skip(&uart->tx_queue, uart->tx_length); DMA_CHCTL(SHARK_UART0_tx_dma, uart->tx_dma_ch) = value & (~DMA_CHXCTL_CHEN); } uart->tx_length = byte_queue_peek(&uart->tx_queue); if (uart->tx_length > 0) { dma_data_number_set(uart->tx_dma_ch, uart->tx_length); DMA_CHMADDR(SHARK_UART0_tx_dma, uart->tx_dma_ch) = (u32) byte_queue_head(&uart->tx_queue); DMA_CHCTL(SHARK_UART0_tx_dma, 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) { byte_queue_write(&uart->tx_queue, &value, 1); } void shark_uart_write_log(char *buffer){ int len = strlen(buffer); shark_uart_t *uart = (_shark_uart+SHARK_UART0); if (len > byte_queue_get_free(&uart->tx_queue)){ return; } byte_queue_write(&uart->tx_queue, (const u8 *)buffer, len); shark_uart_dma_tx(uart); } static void shark_uart_tx_dma_init(shark_uart_t *uart){ dma_init_type dma_init_struct; crm_periph_clock_enable(SHARK_UART0_tx_dma_clk, TRUE); dma_reset(uart->tx_dma_ch); dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc_enable = TRUE; dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; dma_init_struct.peripheral_base_addr = (u32) &(((usart_type *)uart->uart_com)->dt); dma_init_struct.peripheral_inc_enable = FALSE; dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; dma_init_struct.priority = DMA_PRIORITY_MEDIUM; dma_init_struct.loop_mode_enable = FALSE; dma_init(uart->tx_dma_ch, &dma_init_struct); /* config flexible dma for usart2 tx */ //dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART2_TX); usart_dma_transmitter_enable(uart->uart_com, TRUE); } #if ENABLE_RX_DMA==1 static void shark_uart_rx_dma_init(shark_uart_t *uart){ dma_init_type dma_init_struct; crm_periph_clock_enable(SHARK_UART0_rx_dma_clk, TRUE); /* dma1 channel2 for usart2 rx configuration */ dma_reset(uart->rx_dma_ch); dma_default_para_init(&dma_init_struct); dma_init_struct.buffer_size = SHARK_UART_RX_MEM_SIZE; dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_base_addr = (uint32_t)shark_uart0_rx_cache; dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; dma_init_struct.memory_inc_enable = TRUE; dma_init_struct.peripheral_base_addr = (u32) &(((usart_type *)uart->uart_com)->dt); dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; dma_init_struct.peripheral_inc_enable = FALSE; dma_init_struct.priority = DMA_PRIORITY_MEDIUM; dma_init_struct.loop_mode_enable = FALSE; dma_init(uart->rx_dma_ch, &dma_init_struct); /* config flexible dma for usart2 rx */ //dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_UART2_RX); usart_dma_receiver_enable(uart->uart_com, TRUE); } #endif static void shark_uart_pin_init(shark_uart_t *uart){ crm_periph_clock_enable(SHARK_UART0_rx_gpio_clk, TRUE); crm_periph_clock_enable(SHARK_UART0_tx_gpio_clk, TRUE); gpio_init_type gpio_init_struct; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = SHARK_UART0_tx_pin; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(SHARK_UART0_tx_port, &gpio_init_struct); /* configure the usart2 rx pin */ gpio_init_struct.gpio_mode = GPIO_MODE_INPUT; gpio_init_struct.gpio_pins = SHARK_UART0_rx_pin; gpio_init_struct.gpio_pull = GPIO_PULL_UP; gpio_init(SHARK_UART0_rx_port, &gpio_init_struct); } static void shark_uart_pin_deinit(shark_uart_t *uart){ if (_uart_index(uart->uart_com) == SHARK_UART0) { gpio_init_type gpio_init_struct; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_INPUT; gpio_init_struct.gpio_pins = SHARK_UART0_tx_pin; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(SHARK_UART0_tx_port, &gpio_init_struct); gpio_init_struct.gpio_pins = SHARK_UART0_rx_pin; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(SHARK_UART0_rx_port, &gpio_init_struct); } } static void shark_uart_device_init(shark_uart_t *uart){ crm_periph_clock_enable(SHARK_UART0_clk, TRUE); usart_reset(uart->uart_com); /* configure usart2 param */ usart_init(uart->uart_com, SHARK_UART_BAUDRATE, USART_DATA_8BITS, USART_STOP_1_BIT); usart_transmitter_enable(uart->uart_com, TRUE); usart_receiver_enable(uart->uart_com, TRUE); usart_enable(uart->uart_com, TRUE); } static u32 shark_uart_task(void *args) { shark_uart_t *uart = (shark_uart_t *)args; if(uart->uart_com != 0) { shark_uart_rx(uart); shark_uart_dma_tx(uart); } return 0; } void shark_uart_flush(void){ shark_uart_t *uart = _shark_uart + SHARK_UART0; if (uart->uart_com != 0) { while(!byte_queue_empty(&uart->tx_queue)) { shark_uart_dma_tx(uart); } } } #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){ return shark_uart0_tx_cache; } static u8 *rx_cache_addr(uart_enum_t uart_no){ return shark_uart0_rx_cache; } void shark_uart_deinit(uart_enum_t uart_no){ shark_uart_t *uart = _shark_uart + uart_no; if (uart->uart_com != 0) { usart_enable(uart->uart_com, FALSE); usart_reset(uart->uart_com); crm_periph_clock_enable(SHARK_UART0_clk, FALSE); dma_channel_enable(uart->rx_dma_ch, FALSE); dma_channel_enable(uart->tx_dma_ch, FALSE); crm_periph_clock_enable(SHARK_UART0_tx_dma_clk, FALSE); crm_periph_clock_enable(SHARK_UART0_rx_dma_clk, FALSE); shark_uart_pin_deinit(uart); } #if ENABLE_RX_DMA==0 nvic_irq_disable(SHARK_UART0_irq); #endif } 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 = SHARK_UART0_com; circle_buffer_init(&uart->rx_queue, rx_cache_addr(uart_no), SHARK_UART_RX_MEM_SIZE); byte_queue_init(&uart->tx_queue,tx_cache_addr(uart_no), SHARK_UART_TX_MEM_SIZE); uart->rx_dma_ch = SHARK_UART0_rx_dma_ch; uart->tx_dma_ch = SHARK_UART0_tx_dma_ch; shark_uart_pin_init(uart); shark_uart_device_init(uart); #if ENABLE_RX_DMA==1 shark_uart_rx_dma_init(uart); #endif shark_uart_tx_dma_init(uart); usart_enable(uart->uart_com, TRUE); shark_task_create(shark_uart_task, uart); #if ENABLE_RX_DMA==0 nvic_irq_enable(SHARK_UART0_irq, UART_IRQ_PRIORITY, 0); #endif uart->uart_no_data = false; } #if ENABLE_RX_DMA==0 void USART3_IRQHandler(void){ if(usart_flag_get(USART0, USART_FLAG_RBNE) == SET){ shark_uart_t *uart = _shark_uart + SHARK_UART0; u8 c = usart_data_receive(USART0); circle_put_one_data(&uart->rx_queue, c); } } #endif void UART_DMA_IRQHandler(void) { } 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 = 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); shark_uart_dma_tx(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); } int fputc(int c, FILE *fp){ shark_uart_write_byte(_shark_uart+SHARK_UART0, (u8)c); return 1; }