Explorar el Código

uart functions

Signed-off-by: huhui <huhui@sharkgulf.com>
huhui hace 5 años
padre
commit
42e5895b14

+ 8 - 4
Application/app/protocol.c

@@ -1,8 +1,8 @@
 #include "protocol.h"
 #include <string.h>
-
+#include "bsp/uart.h"
 static uint16_t _check_sum(uint8_t*data,uint16_t size);
-
+static uart_enum_t current_uart = SHARK_UART0;
 /*
  * 调用 protocol_send_xxx 接口的时候,需要注意需要多分配can_head_t 大小的内存,并且
  * 需要offset掉can_head_t 大小, 这样设计的原因是避免多次拷贝
@@ -15,7 +15,7 @@ void protocol_send_bms_info(protocol_head_t *head){
 	head->checksum = 0;
 	head->checksum = _check_sum((uint8_t *)head, head->size);
 
-	//send from uart
+	shark_uart_write_frame(current_uart, (char *)can, sizeof(can_head_t) + head->size);
 }
 
 
@@ -25,7 +25,11 @@ void protocol_send_debug_info(uint8_t dest, char *data, int size){
 	can->size = size;
 	can->can_key = 0x00;
 
-	//send from uart
+	shark_uart_write_frame(current_uart, (char *)can, sizeof(can_head_t) + size);
+}
+
+void protocol_recv_frame(uart_enum_t uart_no, char *data, int len){
+
 }
 
 static uint16_t _check_sum(uint8_t*data,uint16_t size)

+ 1 - 1
Application/app/protocol.h

@@ -15,7 +15,7 @@ typedef struct
 #pragma  pack (push,1)  
 typedef struct
 {
-	//憐몸관댕鬼
+	//憐몸관댕鬼,관벵protocol_head_t
 	uint8_t size;
 	//츱즈�구
 	uint8_t type;

+ 7 - 19
Application/app/sox/measure.c

@@ -28,7 +28,7 @@ static float vim0_50x = 0.0f;
 static float vim0_now;
 
 #define gain_default_50x 1
-
+#define CS1180_MAX_CURRENT 4500 //MA, cs1180的最大电流,超过这个使用ML5238
 #define r_pcb_resistor 0.0f // pcb resistor
 static const float r_sense = r_resistor + r_pcb_resistor;
 static const float v_gd_ref = 3300.0f; //adc ref = 3.3v
@@ -36,7 +36,6 @@ static const float max_gd_adc = 65535.0f;
 static const float v_cs1180_ref = 1235.0f;//cs1180 vref = 1.235v
 static const float max_cs1180_adc = 0x7FFFF;//
 static const float small_cur_r_sense = 360.0f;//欧姆
-static uint8_t adc_used = CS1180_ADC;//|GD32_ADC;
 
 static void __inline__ select_gain_10x(int select){	
 	if (select){
@@ -122,25 +121,14 @@ static float get_pack_current_by_cs1180(void){
 
 
 float get_pack_current(void){
-	if (adc_used == CS1180_ADC){
-		return get_pack_current_by_cs1180();
+	if (!cs1180_is_ready()){ //if cs1180 is not ready, just use gd adc
+		return get_pack_current_by_gd();
 	}
-	return get_pack_current_by_gd();
-}
-
-/*
- * select the gd32 internel adc or cs1180 adc
-*/
-void adc_select_for_pack_current(int adc){
-	if (adc != GD32_ADC && adc != CS1180_ADC){
-		return;
-	}
-	if (adc == GD32_ADC){
-		select_gain_10x(0);
-	}else {
-		ML5238_IMON_DISABLE();
+	float current = get_pack_current_by_cs1180();
+	if (abs(current) >= CS1180_MAX_CURRENT){
+		return get_pack_current_by_gd();
 	}
-	adc_used = adc;
+	return current;
 }
 
 

+ 0 - 1
Application/app/sox/measure.h

@@ -1,7 +1,6 @@
 #ifndef _IV_Measure_H__
 #define _IV_Measure_H__
 void measure_adc_init(void);
-void adc_select_for_pack_current(int adc);
 float get_pack_current(void);
 float get_cell_voltage(int cell);
 float get_small_current(void);

+ 2 - 1
Application/bsp/bsp.c

@@ -18,7 +18,8 @@ void bsp_init(void){
 	DCDC_VOL_OPEN(1);
 	system_clock_config(); //after dcdc open, MCU can run on full speed
 	SystemCoreClockUpdate();
-	shark_uart_init();
+	shark_uart_init(SHARK_UART0);
+	shark_uart_init(SHARK_UART1);
 }
 
 void wdog_start(int timeout){

+ 14 - 3
Application/bsp/cs1180.c

@@ -30,7 +30,10 @@ void cs_delay(void)
 	uint32_t  count = 60;
 	while(count--); 
 }
-
+static int _cs1180_ready = 0;
+int cs1180_is_ready(void){
+	return _cs1180_ready;
+}
 
 static void spi_write_reg(uint8_t reg, uint8_t *data, uint8_t len){
 	cs1180_send_cmd(CS1180_WREG|reg);
@@ -147,7 +150,7 @@ static void _cs1180_adc_set_gain(int gain){
 	cs1180_dumy_read();	
 }
 
-void cs1180_adc_set_gain(int gain){
+int cs1180_adc_set_gain(int gain){
 	int count = 0;
 	do {
 		cs1180_reset();
@@ -161,9 +164,15 @@ void cs1180_adc_set_gain(int gain){
 		}
 		count ++;
 	}while(count <= 20);
+	if (count >= 20) {
+		if (cs1180_dumy_read() != gain){
+			return -1;
+		}
+	}
 	delay_us(10*1000);
 	cs1180_sys_offset_calibrate();
 	cs1180_dumy_read();
+	return 0;
 }
 
 
@@ -176,19 +185,21 @@ static void cs1180_reset(void){
 }
 
 void cs1180_adc_init(void){
+	_cs1180_ready = 0;
 	CS1180_PWR_ENABLE(0);
 	delay_us(100 * 1000);
 	CS1180_PWR_ENABLE(1);
 	delay_us(200 * 1000);
 	spi1_init();
 	delay_us(10);
-	cs1180_adc_set_gain(CS1180_INIT_GAIN);
+	_cs1180_ready = cs1180_adc_set_gain(CS1180_INIT_GAIN) == 0;
 }
 
 
 void cs1180_adc_shutdown(void){
 	CS1180_PWR_ENABLE(0);
 	spi1_deinit();
+	_cs1180_ready = 0;
 }
 
 float cs1180_adc_sample(void)

+ 2 - 2
Application/bsp/cs1180.h

@@ -12,8 +12,8 @@
 
 void cs1180_adc_init(void);
 void cs1180_adc_shutdown(void);
-
-void cs1180_adc_set_gain(int gain);
+int cs1180_is_ready(void);
+int cs1180_adc_set_gain(int gain);
 void cs1180_sys_offset_calibrate(void);
 float cs1180_adc_sample(void);
 

+ 5 - 5
Application/bsp/gd32_adc.c

@@ -141,10 +141,10 @@ int adc_sample_avg(int chan, int times){
 		dma_channel_disable(DMA_ADC_CH);
 		adc_dma_mode_disable();
 		dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
-		adc_work = ADC_WORK_IDLE;
+		adc_work = ADC_WORK_INTERTUPED;
 	}
 	//hardware oversample to 16bit
-	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL256);
+	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_2B, ADC_OVERSAMPLING_RATIO_MUL64);
 	adc_oversample_mode_enable();
     /* use max convert time to make sure the adc work fine */
     adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);////55.5 + 12.5 = 68 cycle, 68 * 256/(7*1000000)
@@ -178,7 +178,7 @@ int adc_sample(int chan, int calibration){
 	int value = -0xFFFFFF;
 	int mask = 0xFFFF;
 	//hardware oversample to 16bit
-	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL256);
+	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_2B, ADC_OVERSAMPLING_RATIO_MUL64);
 	adc_oversample_mode_enable();
 
     /* use max convert time to make sure the adc work fine */
@@ -199,14 +199,14 @@ int adc_sample(int chan, int calibration){
 	return value & mask;
 }
 
-//times * 2.4ms
+//times * 0.6ms + 1ms
 int adc_sample_avg(int chan, int times){
 	int value = 0;
 	int count = 0;
 	int min = 0xFFFFF;
 	int max = -0xFFFFF;
 	//hardware oversample to 16bit
-	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL256);
+	adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_2B, ADC_OVERSAMPLING_RATIO_MUL64);
 	adc_oversample_mode_enable();
     /* use max convert time to make sure the adc work fine */
     adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);////55.5 + 12.5 = 68 cycle, 68 * 256/(7*1000000)

+ 1 - 0
Application/bsp/gd32_adc.h

@@ -14,6 +14,7 @@
 #define ADC_WORK_ING 1
 #define ADC_WORK_SAMPLE_COMPLTE 2
 #define ADC_WORK_FINISH 3
+#define ADC_WORK_INTERTUPED 4
 
 int adc_sample(int chan, int calibration);
 int adc_sample_avg(int chan, int times);

+ 1 - 0
Application/bsp/i2c.h

@@ -3,6 +3,7 @@
 #include <stdint.h>
 
 extern void gd32_i2c_init(uint32_t i2c_device, uint32_t rate);
+extern void gd32_i2c_deinit(uint32_t i2c_index);
 extern int gd32_i2c_read_byte(uint32_t index, uint8_t address, uint8_t reg, uint8_t *value);
 extern int gd32_i2c_read_nbytes(uint32_t index, uint8_t address, uint8_t reg, uint8_t *buffer, int length);
 extern int gd32_i2c_write_byte(uint32_t index, uint8_t address, uint8_t reg, uint8_t value);

+ 11 - 5
Application/bsp/mcu_power_sleep.c

@@ -3,6 +3,8 @@
 #include "bsp/cs1180.h"
 #include "bsp/gpio.h"
 #include "bsp/spi.h"
+#include "bsp/uart.h"
+#include "bsp/i2c.h"
 
 extern void system_clock_24m_irc8m(void);
 extern void system_clock_config(void);
@@ -28,12 +30,15 @@ static void pre_deepsleep(void){
 	RS485_PWR_ENABLE(0);
 #endif
 	CS1180_PWR_ENABLE(0);
-	//uart0_deinit();
-	//uart1_deinit();
+	shark_uart_deinit(SHARK_UART0);
+	shark_uart_deinit(SHARK_UART1);
 	//gd32_i2c_deinit();
+	UART0_IR_EN(0);
+	UART0_IR_EN(0);	
 	ml5238_power_save(1); //call, before spi0_deinit
 	spi0_deinit();
 	spi1_deinit();
+	gd32_i2c_deinit(0);
 	system_clock_24m_irc8m();//before dcdc off, should set clock to 24M, avoid ml5238's supply is not enough
 	DCDC_VOL_OPEN(0);
 	wdog_start(10);
@@ -53,9 +58,10 @@ static void post_deepsleep(void){
 #elif (CONFIG_BOARD_TYPE==SHARK_BOARD_SP600)
 	RS485_PWR_ENABLE(1);
 #endif
-	//uart0_init();
-	//uart1_init();
-	//gd32_i2c_init();
+	shark_uart_init(SHARK_UART0);
+	shark_uart_init(SHARK_UART1);
+
+	gd32_i2c_init(0, 100* 1000);
 	wdog_start(4);
 }
 

+ 977 - 0
Application/bsp/shark_uart.c

@@ -0,0 +1,977 @@
+#include "s600_turn_key.h"
+#include "ws2818_spi.h"
+#include "s600_uart.h"
+#include "s600_can.h"
+#include "s600_pwm.h"
+#include "s600_adc.h"
+#include "s600_dac.h"
+#include "string.h"
+#include "stdlib.h"
+
+#define S600_UART0_com					USART0
+#if CONFIG_UART_MAIN == 0
+#define S600_UART0_baudrate				500000
+#else
+#define S600_UART0_baudrate				115200
+#endif
+#define S600_UART0_tx_port				GPIOA
+#define S600_UART0_tx_pin				GPIO_PIN_9
+#define S600_UART0_rx_port				GPIOA
+#define S600_UART0_rx_pin				GPIO_PIN_10
+#define S600_UART0_irq					USART0_IRQn
+#define S600_UART0_clk					RCU_USART0
+#define S600_UART0_tx_gpio_clk			RCU_GPIOA
+#define S600_UART0_rx_gpio_clk			RCU_GPIOA
+#define S600_UART0_tx_dma				DMA0
+#define S600_UART0_tx_dma_ch			DMA_CH3
+#define S600_UART0_tx_dma_clk			RCU_DMA0
+#define S600_UART0_rx_dma				DMA0
+#define S600_UART0_rx_dma_ch			DMA_CH4
+#define S600_UART0_rx_dma_clk			RCU_DMA0
+#define S600_UART0_on_data_received		s600_uart0_received
+
+#define S600_UART1_com					USART1
+#if CONFIG_UART_MAIN == 1
+#define S600_UART1_baudrate				500000
+#else
+#define S600_UART1_baudrate				115200
+#endif
+#define S600_UART1_tx_port				GPIOA
+#define S600_UART1_tx_pin				GPIO_PIN_2
+#define S600_UART1_rx_port				GPIOA
+#define S600_UART1_rx_pin				GPIO_PIN_3
+#define S600_UART1_irq					USART1_IRQn
+#define S600_UART1_clk					RCU_USART1
+#define S600_UART1_tx_gpio_clk			RCU_GPIOA
+#define S600_UART1_rx_gpio_clk			RCU_GPIOA
+#define S600_UART1_tx_dma				DMA0
+#define S600_UART1_tx_dma_ch			DMA_CH6
+#define S600_UART1_tx_dma_clk			RCU_DMA0
+#define S600_UART1_rx_dma				DMA0
+#define S600_UART1_rx_dma_ch			DMA_CH5
+#define S600_UART1_rx_dma_clk			RCU_DMA0
+#define S600_UART1_on_data_received		s600_uart1_received
+
+#define S600_UART2_com					USART2
+#define S600_UART2_baudrate				115200
+#define S600_UART2_tx_port				GPIOB
+#define S600_UART2_tx_pin				GPIO_PIN_10
+#define S600_UART2_rx_port				GPIOB
+#define S600_UART2_rx_pin				GPIO_PIN_11
+#define S600_UART2_irq					USART2_IRQn
+#define S600_UART2_clk					RCU_USART2
+#define S600_UART2_tx_gpio_clk			RCU_GPIOB
+#define S600_UART2_rx_gpio_clk			RCU_GPIOB
+#define S600_UART2_tx_dma				DMA0
+#define S600_UART2_tx_dma_ch			DMA_CH1
+#define S600_UART2_tx_dma_clk			RCU_DMA0
+#define S600_UART2_rx_dma				DMA0
+#define S600_UART2_rx_dma_ch			DMA_CH2
+#define S600_UART2_rx_dma_clk			RCU_DMA0
+#define S600_UART2_on_data_received		s600_uart2_received
+
+#define S600_UART3_com					UART3
+#define S600_UART3_baudrate				115200
+#define S600_UART3_tx_port				GPIOC
+#define S600_UART3_tx_pin				GPIO_PIN_10
+#define S600_UART3_rx_port				GPIOC
+#define S600_UART3_rx_pin				GPIO_PIN_11
+#define S600_UART3_irq					UART3_IRQn
+#define S600_UART3_clk					RCU_UART3
+#define S600_UART3_tx_gpio_clk			RCU_GPIOC
+#define S600_UART3_rx_gpio_clk			RCU_GPIOC
+#define S600_UART3_tx_dma				DMA1
+#define S600_UART3_tx_dma_ch			DMA_CH4
+#define S600_UART3_tx_dma_clk			RCU_DMA1
+#define S600_UART3_rx_dma				DMA1
+#define S600_UART3_rx_dma_ch			DMA_CH2
+#define S600_UART3_rx_dma_clk			RCU_DMA1
+#define S600_UART3_on_data_received		s600_uart3_received
+
+#define S600_UART4_com					UART4
+#define S600_UART4_baudrate				38400
+#define S600_UART4_tx_port				GPIOC
+#define S600_UART4_tx_pin				GPIO_PIN_12
+#define S600_UART4_rx_port				GPIOD
+#define S600_UART4_rx_pin				GPIO_PIN_2
+#define S600_UART4_irq					UART4_IRQn
+#define S600_UART4_clk					RCU_UART4
+#define S600_UART4_tx_gpio_clk			RCU_GPIOC
+#define S600_UART4_rx_gpio_clk			RCU_GPIOD
+#define S600_UART4_on_data_received		s600_uart4_received
+
+// ================================================================================
+
+#define S600_UART_CACHE_SIZE \
+	((S600_UART_TX_MEM_SIZE + S600_UART_RX_MEM_SIZE) * (S600_UART_COUNT - 1) + S600_UART_MAIN_TX_MEM_SIZE + S600_UART_MAIN_RX_MEM_SIZE)
+
+#define S600_UART_DMA_ADDR(index) \
+	(S600_UART##index##_com + 0x04)
+
+#define S600_UART_DMA_CHCTL_TX(uart) \
+	DMA_CHCTL(uart->tx_dma, uart->tx_dma_ch)
+
+#define S600_UART_DMA_CHCNT_TX(uart) \
+	DMA_CHCNT(uart->tx_dma, uart->tx_dma_ch)
+
+#define S600_UART_DMA_CHMADDR_TX(uart) \
+	DMA_CHMADDR(uart->tx_dma, uart->tx_dma_ch)
+
+#define S600_UART_DMA_CHCTL_RX(uart) \
+	DMA_CHCTL(uart->rx_dma, uart->rx_dma_ch)
+
+#define S600_UART_DMA_CHCNT_RX(uart) \
+	DMA_CHCNT(uart->rx_dma, uart->rx_dma_ch)
+
+#define S600_UART_DMA_CHMADDR_RX(uart) \
+	DMA_CHMADDR(uart->rx_dma, uart->rx_dma_ch)
+
+#define S600_UART_DEVICE_INIT(index) \
+	do { \
+		s600_uarts[index].com = S600_UART##index##_com; \
+		s600_uarts[index].on_data_received = S600_UART##index##_on_data_received; \
+		byte_queue_init(&s600_uarts[index].tx_queue, s600_uarts[index].tx_cache, s600_uarts[index].tx_cache_size); \
+		byte_queue_init(&s600_uarts[index].rx_queue, s600_uarts[index].rx_cache, s600_uarts[index].rx_cache_size); \
+		rcu_periph_clock_enable(S600_UART##index##_clk); \
+		rcu_periph_clock_enable(S600_UART##index##_rx_gpio_clk); \
+		rcu_periph_clock_enable(S600_UART##index##_tx_gpio_clk); \
+		gpio_init(S600_UART##index##_tx_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, S600_UART##index##_tx_pin); \
+		gpio_init(S600_UART##index##_rx_port, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, S600_UART##index##_rx_pin); \
+		usart_deinit(S600_UART##index##_com); \
+		usart_baudrate_set(S600_UART##index##_com, S600_UART##index##_baudrate); \
+		usart_word_length_set(S600_UART##index##_com, USART_WL_8BIT); \
+		usart_stop_bit_set(S600_UART##index##_com, USART_STB_1BIT); \
+		usart_parity_config(S600_UART##index##_com, USART_PM_NONE); \
+		usart_hardware_flow_rts_config(S600_UART##index##_com, USART_RTS_DISABLE); \
+		usart_hardware_flow_cts_config(S600_UART##index##_com, USART_CTS_DISABLE); \
+		usart_receive_config(S600_UART##index##_com, USART_RECEIVE_ENABLE); \
+		usart_transmit_config(S600_UART##index##_com, USART_TRANSMIT_ENABLE); \
+	} while (0)
+
+#define S600_UART_TX_IRQ_INIT(index) \
+	do { \
+		s600_uarts[index].tx_poll = s600_uart_irq_tx; \
+		nvic_irq_enable(S600_UART##index##_irq, 0, 0); \
+	} while (0)
+
+#define S600_UART_RX_IRQ_INIT(index) \
+	do { \
+		s600_uarts[index].rx_poll = s600_uart_irq_rx; \
+		usart_interrupt_enable(S600_UART##index##_com, USART_INT_RBNE); \
+		nvic_irq_enable(S600_UART##index##_irq, 0, 0); \
+	} while (0)
+
+#if S600_UART_USE_DMA
+#define S600_UART_TX_DMA_INIT(index) \
+	do { \
+		dma_parameter_struct dma_init_struct; \
+		s600_uarts[index].tx_poll = s600_uart_dma_tx; \
+		s600_uarts[index].tx_dma = S600_UART##index##_tx_dma; \
+		s600_uarts[index].tx_dma_ch = S600_UART##index##_tx_dma_ch; \
+		rcu_periph_clock_enable(S600_UART##index##_tx_dma_clk); \
+		dma_deinit(S600_UART##index##_tx_dma, S600_UART##index##_tx_dma_ch); \
+		dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; \
+		dma_init_struct.memory_addr = (u32) s600_uarts[index].tx_cache; \
+		dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; \
+		dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; \
+		dma_init_struct.number = 0; \
+		dma_init_struct.periph_addr = S600_UART_DMA_ADDR(index); \
+		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(S600_UART##index##_tx_dma, S600_UART##index##_tx_dma_ch, &dma_init_struct); \
+		dma_circulation_disable(S600_UART##index##_tx_dma, S600_UART##index##_tx_dma_ch); \
+		usart_dma_transmit_config(S600_UART##index##_com, USART_DENT_ENABLE); \
+	} while (0)
+
+#define S600_UART_RX_DMA_INIT(index) \
+	do { \
+		dma_parameter_struct dma_init_struct; \
+		s600_uarts[index].rx_poll = s600_uart_dma_rx; \
+		s600_uarts[index].rx_dma = S600_UART##index##_rx_dma; \
+		s600_uarts[index].rx_dma_ch = S600_UART##index##_rx_dma_ch; \
+		rcu_periph_clock_enable(S600_UART##index##_rx_dma_clk); \
+		dma_deinit(S600_UART##index##_rx_dma, S600_UART##index##_rx_dma_ch); \
+		dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; \
+		dma_init_struct.memory_addr = (u32) s600_uarts[index].rx_cache; \
+		dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; \
+		dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; \
+		dma_init_struct.number = s600_uarts[index].rx_cache_size; \
+		dma_init_struct.periph_addr = S600_UART_DMA_ADDR(index); \
+		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(S600_UART##index##_rx_dma, S600_UART##index##_rx_dma_ch, &dma_init_struct); \
+		dma_circulation_enable(S600_UART##index##_rx_dma, S600_UART##index##_rx_dma_ch); \
+		dma_channel_enable(S600_UART##index##_rx_dma, S600_UART##index##_rx_dma_ch); \
+		usart_dma_receive_config(S600_UART##index##_com, USART_DENR_ENABLE); \
+	} while (0)
+#else
+#define S600_UART_TX_DMA_INIT(index) \
+	S600_UART_TX_IRQ_INIT(index)
+
+#define S600_UART_RX_DMA_INIT(index) \
+	S600_UART_RX_IRQ_INIT(index)
+#endif
+
+#define S600_UART_INIT_DMA(index) \
+	do { \
+		S600_UART_DEVICE_INIT(index); \
+		S600_UART_TX_DMA_INIT(index); \
+		S600_UART_RX_DMA_INIT(index); \
+	} while (0)
+
+	
+#define S600_UART_INIT_IRQ(index) \
+	do { \
+		S600_UART_DEVICE_INIT(index); \
+		S600_UART_TX_IRQ_INIT(index); \
+		S600_UART_RX_IRQ_INIT(index); \
+	} while (0)
+
+// ================================================================================
+
+static u16 s600_print_pos;
+static u8 s600_print_buff[S600_UART_FRAME_SIZE];
+
+static u16 s600_uart_index;
+static bool s600_uart_valid;
+static bool s600_uart_escape;
+static u8 s600_uart_frame[S600_UART_FRAME_SIZE];
+
+static u8 s600_uart_cache[S600_UART_CACHE_SIZE];
+
+s600_uart_device_t s600_uarts[S600_UART_COUNT];
+s600_uart_device_t *s600_uart_passthrough;
+
+// ================================================================================
+
+void s600_uart_dma_tx(s600_uart_device_t *uart)
+{
+	u32 value = S600_UART_DMA_CHCTL_TX(uart);
+
+    if (value & DMA_CHXCTL_CHEN) {
+		if (SET != dma_flag_get(uart->tx_dma, uart->tx_dma_ch, DMA_FLAG_FTF)) {
+			return;
+		}
+
+		byte_queue_skip(&uart->tx_queue, uart->tx_length);
+		S600_UART_DMA_CHCTL_TX(uart) = value & (~DMA_CHXCTL_CHEN);
+	}
+
+	uart->tx_length = byte_queue_peek(&uart->tx_queue);
+	if (uart->tx_length > 0) {
+		S600_UART_DMA_CHCNT_TX(uart) = uart->tx_length;
+		S600_UART_DMA_CHMADDR_TX(uart) = (u32) byte_queue_head(&uart->tx_queue);
+
+		dma_flag_clear(uart->tx_dma, uart->tx_dma_ch, DMA_FLAG_FTF);
+		S600_UART_DMA_CHCTL_TX(uart) = value | DMA_CHXCTL_CHEN;
+	}
+}
+
+void s600_uart_cache_data(s600_uart_device_t *uart, u8 *buff, u16 length)
+{
+#if S600_UART_USE_CACHE
+	while (length > 0) {
+		u8 remain = sizeof(uart->cache) - uart->cache_len;
+
+		uart->cache_times = S600_UART_CACHE_TIMES;
+
+		if (length < remain) {
+			memcpy(uart->cache + uart->cache_len, buff, length);
+			uart->cache_len += length;
+			break;
+		}
+
+		memcpy(uart->cache + uart->cache_len, buff, remain);
+		uart->on_data_received(uart->cache, sizeof(uart->cache));
+		uart->cache_len = 0;
+
+		length -= remain;
+		buff += remain;
+	}
+#else
+	if (length > 0) {
+		uart->on_data_received(buff, length);
+	}
+#endif
+}
+
+void s600_uart_dma_rx(s600_uart_device_t *uart)
+{
+	u16 index = uart->rx_index;
+
+	uart->rx_index = uart->rx_cache_size - S600_UART_DMA_CHCNT_RX(uart);
+
+	if (uart->rx_index < index) {
+		uart->do_cache_data(uart, uart->rx_cache + index, uart->rx_cache_size - index);
+		uart->do_cache_data(uart, uart->rx_cache, uart->rx_index);
+	} else {
+		uart->do_cache_data(uart, uart->rx_cache + index, uart->rx_index - index);
+	}
+}
+
+void s600_uart_irq_tx(s600_uart_device_t *uart)
+{
+}
+
+void s600_uart_irq_rx(s600_uart_device_t *uart)
+{
+	u8 buff[128];
+	u8 length;
+
+	length = s600_uart_read(uart, buff, sizeof(buff));
+	uart->do_cache_data(uart, buff, length);
+}
+
+void s600_uart_rx(s600_uart_device_t *uart)
+{
+	u32 com = uart->com;
+
+	while (usart_flag_get(com, USART_FLAG_RBNE) == SET) {
+		u8 value = usart_data_receive(com);
+		byte_queue_write(&uart->rx_queue, &value, 1);
+	}
+}
+
+void s600_uart_device_tx(s600_uart_device_t *uart)
+{
+	u32 com = uart->com;
+
+	if (usart_flag_get(com, USART_FLAG_TBE) == SET) {
+		u8 value;
+
+		if (byte_queue_read(&uart->tx_queue, &value, 1) > 0) {
+			usart_data_transmit(com, value);
+		} else {
+			usart_interrupt_disable(com, USART_INT_TBE);
+		}
+	}
+}
+
+void s600_uart_write(s600_uart_device_t *uart, const u8 *buff, u16 size)
+{
+	while (size > 0) {
+		u16 length = byte_queue_write(&uart->tx_queue, buff, size);
+
+		if (uart->tx_dma == 0) {
+			usart_interrupt_enable(uart->com, USART_INT_TBE);
+		}
+
+		if (length == size) {
+			break;
+		}
+
+		if (uart->tx_dma != 0) {
+			s600_uart_dma_tx(uart);
+		}
+
+		buff += length;
+		size -= length;
+	}
+}
+
+u16 s600_uart_read(s600_uart_device_t *uart, u8 *buff, u16 size)
+{
+	return byte_queue_read(&uart->rx_queue, buff, size);
+}
+
+void s600_uart_write_byte(s600_uart_device_t *uart, u8 value)
+{
+	s600_uart_write(uart, &value, 1);
+}
+
+u16 s600_uart_write_available(s600_uart_device_t *uart)
+{
+	return byte_queue_get_free(&uart->tx_queue);
+}
+
+bool s600_uart_write_full(s600_uart_device_t *uart, const u8 *buff, u16 size)
+{
+	if (s600_uart_write_available(uart) < size) {
+		return false;
+	}
+
+	s600_uart_write(uart, buff, size);
+
+	return true;
+}
+
+void s600_uart_write_byte_esc(s600_uart_device_t *uart, u8 value)
+{
+	switch (value) {
+	case CH_START:
+		s600_uart_write_byte(uart, CH_ESC);
+		value = CH_ESC_START;
+		break;
+
+	case CH_END:
+		s600_uart_write_byte(uart, CH_ESC);
+		value = CH_ESC_END;
+		break;
+
+	case CH_ESC:
+		s600_uart_write_byte(uart, CH_ESC);
+		value = CH_ESC_ESC;
+		break;
+	}
+
+	s600_uart_write_byte(uart, value);
+}
+
+void s600_uart_message_init(s600_uart_message_t *msg, const void *buff, u16 size)
+{
+	msg->buff = (u8 *) buff;
+	msg->size = size;
+}
+
+void s600_uart_write_messages(s600_uart_device_t *uart, const s600_uart_message_t *msgs, u8 count)
+{
+	const s600_uart_message_t *msg_end;
+	u16 crc = 0;
+
+#ifdef CONFIG_BOARD_M6_JIG
+	s600_uart_write_byte(uart, 0xAA);
+#endif
+
+	s600_uart_write_byte(uart, CH_START);
+
+	for (msg_end = msgs + count; msgs < msg_end; msgs++) {
+		const u8 *buff = msgs->buff;
+		const u8 *buff_end = buff + msgs->size;
+
+		while (buff < buff_end) {
+			u8 value = *buff++;
+			s600_uart_write_byte_esc(uart, value);
+			crc = s600_crc_put_byte(crc, value);
+		}
+	}
+
+	s600_uart_write_byte_esc(uart, crc);
+	s600_uart_write_byte_esc(uart, crc >> 8);
+
+	s600_uart_write_byte(uart, CH_END);
+}
+
+// ================================================================================
+
+static void s600_uart_process_cmd_can(u8 *buff, u16 length)
+{
+	s600_can_efid_t efid;
+
+	if (length < 5) {
+		return;
+	}
+
+	efid.value = s600_decode_u32(buff);
+
+	if (efid.dest == 0x00 && efid.src == 0x45) {
+		s600_can_process_frame(efid, buff + 4, length - 4);
+	} else {
+		u8 mailbox = s600_can_wait_mailbox();
+		if (mailbox != CAN_NOMAILBOX) {
+			s600_can_send_frame(mailbox, efid.value, buff + 4, length - 4);
+		}
+	}
+}
+
+static int s600_uart_process_cmd_version(u8 *buff, u16 length)
+{
+	length = sizeof(CONFIG_BOARD_NAME) - 1;
+	memcpy(buff, CONFIG_BOARD_NAME, length);
+	return length;
+}
+
+static int s600_uart_process_command(u16 command, u8 *buff, u16 length)
+{
+	return -1;
+}
+
+static s600_uart_device_t *s600_uart_get_device(int uart)
+{
+	if (uart < NELEM(s600_uarts)) {
+		return s600_uarts + uart;
+	}
+
+	return NULL;
+}
+
+static void s600_uart_passthrough_master(u8 *buff, u16 size)
+{
+	s600_uart_write(s600_uart_passthrough, buff, size);
+}
+
+static void s600_uart_passthrough_slave(u8 *buff, u16 size)
+{
+	s600_uart_write(s600_uart_get_main(), buff, size);
+}
+
+static int s600_uart_process_uart_config(u8 *buff, u16 length)
+{
+	s600_uart_device_t *uart;
+
+	if (length < 2) {
+		return -1;
+	}
+
+	uart = s600_uart_get_device(buff[0]);
+	if (uart == NULL) {
+		return -1;
+	}
+
+	if (length > 5) {
+		u32 baudrate = s600_decode_u32(buff + 2);
+		usart_baudrate_set(uart->com, baudrate);
+	}
+
+	if (buff[1]) {
+		usart_enable(uart->com);
+
+		if ((buff[1] & 0x02) != 0) {
+			s600_uart_passthrough = uart;
+			uart->on_data_received = s600_uart_passthrough_slave;
+			s600_uart_get_main()->on_data_received = s600_uart_passthrough_master;
+		}
+	} else {
+		usart_disable(uart->com);
+	}
+
+	return 0;
+}
+
+static u32 s600_uart_gpio_decode_port(u8 value)
+{
+	u8 index = value >> 5;
+	rcu_periph_clock_enable(s600_gpio_rcu_map[index]);
+	return s600_gpio_map[index];
+}
+
+static u32 s600_uart_gpio_decode_pin(u8 value)
+{
+	return 1 << (value & 0x1F);
+}
+
+static u32 s600_uart_exti_decode_port(u8 value)
+{
+	return value >> 5;
+}
+
+static u32 s600_uart_exti_decode_pin(u8 value)
+{
+	return value & 0x1F;
+}
+
+static int s600_uart_process_gpio_init(u8 *buff, u16 length)
+{
+	if (length < 6) {
+		u32 port = s600_uart_gpio_decode_port(buff[0]);
+		u32 pin = s600_uart_gpio_decode_pin(buff[0]);
+		gpio_init(port, buff[1], buff[2], pin);
+	} else {
+		gpio_pin_remap_config(s600_decode_u32(buff + 1), (ControlStatus) buff[5]);
+	}
+
+	return 1;
+}
+
+static int s600_uart_process_gpio_input_bit_get(u8 *buff, u16 length)
+{
+	u32 port = s600_uart_gpio_decode_port(buff[0]);
+	u32 pin = s600_uart_gpio_decode_pin(buff[0]);
+
+	if (length > 1) {
+		gpio_init(port, buff[1], GPIO_OSPEED_50MHZ, pin);
+	}
+
+	buff[1] = gpio_input_bit_get(port, pin);
+
+	return 2;
+}
+
+static int s600_uart_process_gpio_output_bit_set(u8 *buff, u16 length)
+{
+	u32 port = s600_uart_gpio_decode_port(buff[0]);
+	u32 pin = s600_uart_gpio_decode_pin(buff[0]);
+
+	if (length > 2) {
+		gpio_init(port, buff[2], GPIO_OSPEED_50MHZ, pin);
+	}
+
+	if (buff[1] == 0) {
+		gpio_bit_reset(port, pin);
+	} else {
+		gpio_bit_set(port, pin);
+	}
+
+	return 1;
+}
+
+static int s600_uart_process_gpio_output_bit_get(u8 *buff, u16 length)
+{
+	u32 port = s600_uart_gpio_decode_port(buff[0]);
+	u32 pin = s600_uart_gpio_decode_pin(buff[0]);
+
+	buff[1] = gpio_output_bit_get(port, pin);
+
+	return 2;
+}
+
+static int s600_uart_process_gpio_input_port_get(u8 *buff, u16 length)
+{
+	u32 port = s600_uart_gpio_decode_port(buff[0]);
+	s600_encode_u16(buff + 1, gpio_input_port_get(port));
+	return 3;
+}
+
+static int s600_uart_process_gpio_output_port_set(u8 *buff, u16 length)
+{
+	u32 port = s600_uart_gpio_decode_port(buff[0]);
+	gpio_port_write(port, s600_decode_u16(buff + 1));
+	return 1;
+}
+
+static int s600_uart_process_gpio_output_port_get(u8 *buff, u16 length)
+{
+	u32 port = s600_uart_gpio_decode_port(buff[0]);
+	s600_encode_u16(buff + 1, gpio_output_port_get(port));
+	return 3;
+}
+
+static int s600_uart_process_adc(u8 *buff, u16 length)
+{
+	return s600_adc_get_values(buff[0], buff + 1) - buff + 1;
+}
+
+static int s600_uart_process_write_dac(int index, u8 *buff, u16 length)
+{
+	length = s600_dac_write(index, buff, length);
+	s600_encode_u16(buff, length);
+	return 2;
+}
+
+static int s600_uart_process_dac_set_enable(u8 *buff, u16 length)
+{
+	u8 dac = buff[0];
+
+	if (buff[1] == 0) {
+		s600_dac_disable(dac);
+	} else {
+		s600_dac_enable(dac);
+	}
+
+	return 1;
+}
+
+static int s600_uart_process_dac_set_volume(u8 *buff, u16 length)
+{
+	s600_dac_set_volume(buff[0], buff[1]);
+	return 1;
+}
+
+static int s600_uart_process_dac_set_rate(u8 *buff, u16 length)
+{
+	s600_dac_set_rate(buff[0], s600_decode_u16(buff + 1));
+	return 1;
+}
+
+static int s600_uart_process_single_comm_config(u8 *buff, u16 length)
+{
+	if (length < 2) {
+		return -1;
+	}
+
+	if (buff[1]) {
+		u32 port, pin;
+
+		if (length < 3) {
+			return -1;
+		}
+
+		port = s600_uart_exti_decode_port(buff[2]);
+		pin = s600_uart_exti_decode_pin(buff[2]);
+		s600_turn_key_init(buff[0], port, pin);
+	} else {
+		s600_turn_key_deinit(buff[0]);
+	}
+
+	return 0;
+}
+
+static int s600_uart_process_spi_led_init(void)
+{
+	ws2818_spi_init();
+	return 0;
+}
+
+static int s600_uart_process_spi_led_commit(void)
+{
+	ws2818_commit();
+	return 0;
+}
+
+static int s600_uart_process_spi_led_clear(u8 *buff, u16 length)
+{
+	u32 color;
+	u8 index;
+	u8 count;
+
+	if (length > 0) {
+		index = buff[0];
+	} else {
+		index = 0;
+	}
+
+	if (length > 1) {
+		count = buff[1];
+	} else {
+		count = WS2818_LED_COUNT - index;
+	}
+
+	if (length < 5) {
+		color = 0x00000000;
+	} else {
+		color = s600_decode_u24(buff + 2);
+	}
+
+	ws2818_set_color_burst(index, index + count, color);
+
+	return 0;
+}
+
+static int s600_uart_process_spi_led_set_color(u8 *buff, u16 length)
+{
+	u8 index;
+
+	if (length < 1) {
+		return -1;
+	}
+
+	for (index = buff[0], buff++, length--; length >= 3; index++) {
+		ws2818_set_color(index, s600_decode_u24(buff));
+		length -= 3;
+		buff += 3;
+	}
+
+	return 0;
+}
+
+static int s600_uart_process_reg_rw(u8 *buff, u16 length)
+{
+	return 0;
+}
+
+static int s600_uart_process_mem_rw(u8 *buff, u16 length)
+{
+	return 0;
+}
+
+
+static void s600_uart_exti_notify(u8 index)
+{
+	exti_interrupt_flag_clear((exti_line_enum) BIT(index));
+	s600_uart_send_command(CMD_EXTI_NOTIFY, &index, 1);
+}
+
+
+static void s600_uart_put(struct s600_uart_device *uart, u8 *buff, u16 length)
+{
+	const u8 *buff_end;
+
+	for (buff_end = buff + length; buff < buff_end; buff++) {
+		u8 value = *buff;
+
+		switch (value) {
+		case CH_START:
+			s600_uart_index = 0;
+			s600_uart_valid = true;
+			s600_uart_escape = false;
+			break;
+
+		case CH_END:
+			if (s600_uart_valid && s600_uart_index > 0) {
+				s600_uart_process_frame(s600_uart_frame, s600_uart_index);
+				s600_uart_index = 0;
+			}
+
+			s600_uart_valid = false;
+			s600_uart_escape = false;
+			break;
+
+		case CH_ESC:
+			s600_uart_escape = true;
+			break;
+
+		default:
+			if (s600_uart_escape) {
+				s600_uart_escape = false;
+
+				switch (value) {
+				case CH_ESC_START:
+					value = CH_START;
+					break;
+
+				case CH_ESC_END:
+					value = CH_END;
+					break;
+
+				case CH_ESC_ESC:
+					value = CH_ESC;
+					break;
+
+				default:
+					s600_uart_valid = false;
+					break;
+				}
+			}
+
+			if (s600_uart_index < sizeof(s600_uart_frame)) {
+				s600_uart_frame[s600_uart_index++] = value;
+			} else {
+				s600_uart_valid = false;
+			}
+		}
+	}
+}
+
+void s600_uart_poll(void)
+{
+	int i;
+
+	for (i = 0; i < NELEM(s600_uarts); i++) {
+		s600_uart_device_t *uart = s600_uarts + i;
+		uart->tx_poll(uart);
+		uart->rx_poll(uart);
+
+#if S600_UART_USE_CACHE
+		if (uart->cache_times > 0) {
+			if (uart->cache_times == 1 && uart->cache_len > 0) {
+				uart->on_data_received(uart->cache, uart->cache_len);
+				uart->cache_len = 0;
+			}
+
+			uart->cache_times--;
+		}
+#endif
+	}
+}
+
+
+void s600_uart_print_flush(short_command_t cmd)
+{
+	s600_uart_send_command(cmd, s600_print_buff, s600_print_pos);
+	s600_print_pos = 0;
+}
+
+void s600_uart0_received(u8 *buff, u16 length)
+{
+	s600_uart_send_command(CMD_UART0, buff, length);
+}
+
+void s600_uart1_received(u8 *buff, u16 length)
+{
+	s600_uart_send_command(CMD_UART1, buff, length);
+}
+
+void s600_uart2_received(u8 *buff, u16 length)
+{
+	s600_uart_send_command(CMD_UART2, buff, length);
+}
+
+void s600_uart3_received(u8 *buff, u16 length)
+{
+	s600_uart_send_command(CMD_UART3, buff, length);
+}
+
+void s600_uart4_received(u8 *buff, u16 length)
+{
+	s600_uart_send_command(CMD_UART4, buff, length);
+}
+
+void s600_uart_rcu_config(void)
+{
+	u16 position = 0;
+	int i;
+
+	for (i = 0; i < NELEM(s600_uarts); i++) {
+		s600_uart_device_t *uart = s600_uarts + i;
+
+		if (i == CONFIG_UART_MAIN) {
+			uart->tx_cache_size = S600_UART_MAIN_TX_MEM_SIZE;
+			uart->rx_cache_size = S600_UART_MAIN_RX_MEM_SIZE;
+			uart->do_cache_data = s600_uart_put;
+		} else {
+			uart->tx_cache_size = S600_UART_TX_MEM_SIZE;
+			uart->rx_cache_size = S600_UART_RX_MEM_SIZE;
+			uart->do_cache_data = s600_uart_cache_data;
+		}
+
+		uart->tx_cache = s600_uart_cache + position;
+		uart->rx_cache = uart->tx_cache + uart->tx_cache_size;
+	}
+
+	S600_UART_INIT_DMA(0);
+	S600_UART_INIT_DMA(1);
+
+#ifdef CONFIG_BOARD_M6_CDL
+	S600_UART_INIT_IRQ(2);
+#else
+	S600_UART_INIT_DMA(2);
+#endif
+
+	S600_UART_INIT_DMA(3);
+	S600_UART_INIT_IRQ(4);
+
+	usart_enable(s600_uart_get_main()->com);
+}
+
+int fputc(int ch, FILE *f)
+{
+	if (ch == '\n') {
+		if (s600_print_pos > 0) {
+			s600_uart_print_flush(CMD_PRINT_END);
+		}
+	} else {
+		while (1) {
+			if (s600_print_pos < sizeof(s600_print_buff)) {
+				s600_print_buff[s600_print_pos] = ch;
+				s600_print_pos++;
+				break;
+			}
+
+			s600_uart_print_flush(CMD_PRINT_ADD);
+		}
+	}
+
+	return ch;
+}
+
+void USART0_IRQHandler(void)
+{
+	s600_uart_rx(s600_uarts);
+	s600_uart_device_tx(s600_uarts);
+}
+
+void USART1_IRQHandler(void)
+{
+	s600_uart_rx(s600_uarts + 1);
+	s600_uart_device_tx(s600_uarts + 1);
+}
+
+void USART2_IRQHandler(void)
+{
+	s600_uart_rx(s600_uarts + 2);
+	s600_uart_device_tx(s600_uarts + 2);
+}
+
+void UART3_IRQHandler(void)
+{
+	s600_uart_rx(s600_uarts + 3);
+	s600_uart_device_tx(s600_uarts + 3);
+}
+
+void UART4_IRQHandler(void)
+{
+	s600_uart_rx(s600_uarts + 4);
+	s600_uart_device_tx(s600_uarts + 4);
+}
+

+ 149 - 0
Application/bsp/shark_uart.h

@@ -0,0 +1,149 @@
+#pragma once
+
+#include "s600.h"
+#include "s600_can.h"
+#include "byte_queue.h"
+
+#define S600_UART_USE_DMA				1
+#define S600_UART_USE_CACHE				1
+#define S600_UART_CACHE_TIMES			200
+
+#define CH_START						0xF5
+#define CH_END							0xF6
+#define CH_ESC							0xF7
+#define CH_ESC_START					0x05
+#define CH_ESC_END						0x06
+#define CH_ESC_ESC						0x07
+
+#define S600_UART_FRAME_SIZE			2048
+
+#ifdef CONFIG_BOARD_S600
+#define S600_UART_TX_MEM_SIZE			512
+#define S600_UART_RX_MEM_SIZE			512
+#else
+#define S600_UART_TX_MEM_SIZE			1024
+#define S600_UART_RX_MEM_SIZE			1024
+#endif
+
+#define S600_UART_MAIN_TX_MEM_SIZE		2048
+#define S600_UART_MAIN_RX_MEM_SIZE		2048
+
+typedef enum {
+	CMD_CAN = 0,
+	CMD_PING,
+	CMD_VERSION,
+	CMD_PRINT_ADD,
+	CMD_PRINT_END,
+	CMD_PWM_SET_ENABLE, // 5
+	CMD_PWM_SET_VALUE,
+	CMD_UART0,
+	CMD_UART1,
+	CMD_UART2,
+	CMD_UART3, // 10
+	CMD_UART4,
+	CMD_UART_CONFIG,
+	CMD_GPIO_INIT,
+	CMD_GPIO_INPUT_BIT_GET,
+	CMD_GPIO_OUTPUT_BIT_SET, // 15
+	CMD_GPIO_OUTPUT_BIT_GET,
+	CMD_GPIO_INPUT_PORT_GET,
+	CMD_GPIO_OUTPUT_PORT_SET,
+	CMD_GPIO_OUTPUT_PORT_GET,
+	CMD_ADC, // 20
+	CMD_DAC0,
+	CMD_DAC1,
+	CMD_DAC_SET_ENABLE,
+	CMD_DAC_SET_VOLUME,
+	CMD_DAC_SET_RATE, // 25
+	CMD_SINGLE_COMM_CONFIG,
+	CMD_SINGLE_COMM_DATA,
+	CMD_SPI_LED_INIT,
+	CMD_SPI_LED_COMMIT,
+	CMD_SPI_LED_CLEAR, // 30
+	CMD_SPI_LED_SET_COLOR,
+	CMD_REG_RW,
+	CMD_MEM_RW,
+	CMD_I2C_INIT,
+	CMD_I2C_RW, // 35
+	CMD_EXTI_INIT,
+	CMD_EXTI_NOTIFY,
+} short_command_t;
+
+typedef enum {
+	S600_UART0,
+	S600_UART1,
+	S600_UART2,
+	S600_UART3,
+	S600_UART4,
+	S600_UART_COUNT
+} s600_uart_t;
+
+typedef struct s600_uart_device {
+	u32 com;
+	u32 tx_dma;
+	u32 rx_dma;
+	dma_channel_enum tx_dma_ch;
+	dma_channel_enum rx_dma_ch;
+
+#if S600_UART_USE_CACHE
+	u8 cache[64];
+	u8 cache_len;
+	u8 cache_times;
+#endif
+
+	u8 *tx_cache;
+	u8 *rx_cache;
+	u16 tx_cache_size;
+	u16 rx_cache_size;
+
+	u16 tx_length;
+	u16 rx_index;
+
+	byte_queue_t tx_queue;
+	byte_queue_t rx_queue;
+
+	void (*do_cache_data)(struct s600_uart_device *uart, u8 *buff, u16 size);
+	void (*on_data_received)(u8 *buff, u16 size);
+	void (*tx_poll)(struct s600_uart_device *uart);
+	void (*rx_poll)(struct s600_uart_device *uart);
+} s600_uart_device_t;
+
+typedef struct {
+	u8 *buff;
+	u16 size;
+} s600_uart_message_t;
+
+extern s600_uart_device_t s600_uarts[];
+
+extern void s600_uart_received(s600_uart_device_t *uart, u8 *buff, u16 length);
+extern void s600_uart0_received(u8 *buff, u16 length);
+extern void s600_uart1_received(u8 *buff, u16 length);
+extern void s600_uart2_received(u8 *buff, u16 length);
+extern void s600_uart3_received(u8 *buff, u16 length);
+extern void s600_uart4_received(u8 *buff, u16 length);
+
+void s600_uart_init(s600_uart_device_t *uart);
+void s600_uart_dma_tx(s600_uart_device_t *uart);
+void s600_uart_dma_rx(s600_uart_device_t *uart);
+void s600_uart_write(s600_uart_device_t *uart, const u8 *buff, u16 size);
+u16 s600_uart_read(s600_uart_device_t *uart, u8 *buff, u16 size);
+void s600_uart_write_byte(s600_uart_device_t *uart, u8 value);
+u16 s600_uart_write_available(s600_uart_device_t *uart);
+bool s600_uart_write_full(s600_uart_device_t *uart, const u8 *buff, u16 size);
+
+void s600_uart_message_init(s600_uart_message_t *msg, const void *buff, u16 size);
+void s600_uart_write_messages(s600_uart_device_t *uart, const s600_uart_message_t *msgs, u8 count);
+
+void s600_uart_rcu_config(void);
+void s600_uart_poll(void);
+void s600_uart_send_command(u8 cmd, const void *buff, u16 size);
+void s600_uart_send_command_u8(u8 cmd, u8 value);
+void s600_uart_send_command_bool(u8 cmd, bool value);
+
+void s600_uart_send_can_frame(const s600_can_frame_t *frame);
+void s600_uart_send_can_pack(const s600_can_pack_t *pack);
+
+__STATIC_INLINE s600_uart_device_t *s600_uart_get_main(void)
+{
+	return s600_uarts + CONFIG_UART_MAIN;
+}

+ 197 - 184
Application/bsp/uart.c

@@ -1,5 +1,6 @@
 #include "uart.h"
 #include "bsp/shark_bsp.h"
+#include "bsp/gpio.h"
 #include "libs/shark_libs.h"
 
 #define SHARK_UART_BAUDRATE				38400
@@ -36,188 +37,137 @@
 #define SHARK_UART1_rx_dma_ch			DMA_CH4
 #define SHARK_UART1_rx_dma_clk			RCU_DMA
 
-#define SHARK_UART_com					SHARK_UART0_com
-#define SHARK_UART_tx_port				SHARK_UART0_tx_port
-#define SHARK_UART_tx_pin				SHARK_UART0_tx_pin
-#define SHARK_UART_rx_port				SHARK_UART0_rx_port
-#define SHARK_UART_rx_pin				SHARK_UART0_rx_pin
-#define SHARK_UART_irq					SHARK_UART0_irq
-#define SHARK_UART_clk					SHARK_UART0_clk
-#define SHARK_UART_tx_gpio_clk			SHARK_UART0_tx_gpio_clk
-#define SHARK_UART_rx_gpio_clk			SHARK_UART0_rx_gpio_clk
-// #define SHARK_UART_tx_dma				SHARK_UART0_tx_dma
-#define SHARK_UART_tx_dma_ch			SHARK_UART0_tx_dma_ch
-#define SHARK_UART_tx_dma_clk			SHARK_UART0_tx_dma_clk
-// #define SHARK_UART_rx_dma				SHARK_UART0_rx_dma
-#define SHARK_UART_rx_dma_ch			SHARK_UART0_rx_dma_ch
-#define SHARK_UART_rx_dma_clk			SHARK_UART0_rx_dma_clk
-
 // ================================================================================
 
-#define SHARK_UART_CACHE_SIZE \
-	(SHARK_UART_TX_MEM_SIZE + SHARK_UART_RX_MEM_SIZE)
-
-#define SHARK_UART_DMA_ADDR(index) \
-	(SHARK_UART_com + 0x04)
-
-#define SHARK_UART_DMA_CHCTL_TX() \
-	DMA_CHCTL(SHARK_UART_tx_dma_ch)
-
-#define SHARK_UART_DMA_CHCNT_TX() \
-	DMA_CHCNT(SHARK_UART_tx_dma_ch)
-
-#define SHARK_UART_DMA_CHMADDR_TX() \
-	DMA_CHMADDR(SHARK_UART_tx_dma_ch)
-
-#define SHARK_UART_DMA_CHCTL_RX() \
-	DMA_CHCTL(SHARK_UART_rx_dma_ch)
-
-#define SHARK_UART_DMA_CHCNT_RX() \
-	DMA_CHCNT(SHARK_UART_rx_dma_ch)
-
-#define SHARK_UART_DMA_CHMADDR_RX() \
-	DMA_CHMADDR(SHARK_UART_rx_dma_ch)
-
-// ================================================================================
-
-static u8 shark_uart_tx_cache[SHARK_UART_TX_MEM_SIZE];
+static u8 shark_uart0_tx_cache[SHARK_UART_TX_MEM_SIZE];
+static u8 shark_uart1_tx_cache[SHARK_UART_TX_MEM_SIZE];
 static u8 shark_uart_rx_cache[SHARK_UART_RX_MEM_SIZE];
-
-static u16 shark_uart_tx_length;
-static u16 shark_uart_tx_crc16;
-
-static u16 shark_uart_rx_index;
-static byte_queue_t shark_uart_tx_queue;
-
+static shark_uart_t _shark_uart[SHARK_UART_COUNT];
+static shark_task_t _uart_task;
+static bool new_prococol = false;
+static u64 _rx_time;
+#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);
 // ================================================================================
-
-static bool shark_uart_on_frame_received(u8 *buff, u16 length)
+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(buff + length);
-	u16 crc1 = shark_crc16_check(buff, length);
+	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;
 	}
-
+	new_prococol = true;
+	protocol_recv_frame(_uart_index(uart->uart_com), (char *)uart->rx_frame, uart->rx_length);
 	return true;
 }
 
-static void shark_uart_on_data_received(u8 *buff, u16 size)
-{
-	static bool escape = false;
-	static u8 length = 0xFF;
-	static u8 frame[16];
-	u8 *buff_end;
-
-	for (buff_end = buff + size; buff < buff_end; buff++) {
-		u8 value = *buff;
-
-		switch (value) {
-		case CH_START:
-			length = 0;
-			escape = false;
-			break;
-
-		case CH_END:
-			if (length > 2 && length != 0xFF) {
-				shark_uart_on_frame_received(frame, length - 2);
+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, (char *)&data) != 1) {
+			if (!new_prococol){//通过老协议发送过来的,需要回复一个信息,告知使用新协议,霍尔移除,通信超时需要reset new_protocol
+				if (shark_get_mseconds() - _rx_time >= 30) {
+					_rx_time = 0xFFFFFFFFFFFFL;
+					protocol_recv_frame(_uart_index(uart->uart_com), NULL, 0);
+				}
 			}
-
-			length = 0xFF;
-			break;
-
-		case CH_ESC:
-			escape = true;
 			break;
-
-		default:
-			if (escape) {
-				escape = false;
-
-				switch (value) {
-				case CH_ESC_START:
-					value = CH_START;
-					break;
-
-				case CH_ESC_END:
-					value = CH_END;
-					break;
-
-				case CH_ESC_ESC:
-					value = CH_ESC;
-					break;
-
-				default:
-					length = 0xFF;
+		}
+		_rx_time = shark_get_mseconds();
+		switch(data){
+			case CH_START:
+				uart->rx_length = 0;
+				uart->escape = false;
+				break;
+			case CH_END:
+				if (uart->rx_length > 2 && uart->rx_length != 0xFF){
+					shark_uart_on_rx_frame(uart);
+				}
+				uart->rx_length = 0xFF;
+				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 (length < sizeof(frame)) {
-				frame[length] = value;
-				length++;
-			} else {
-				length = 0xFF;
-			}
+				if (uart->rx_length < sizeof(uart->rx_frame)) {
+					uart->rx_frame[uart->rx_length] = data;
+					uart->rx_length++;
+				} else {
+					uart->rx_length = 0xFF;
+				}			
 		}
 	}
 }
 
-static void shark_uart_dma_tx(void)
+
+static void shark_uart_dma_tx(shark_uart_t *uart)
 {
-	u32 value = SHARK_UART_DMA_CHCTL_TX();
+	u32 value = DMA_CHCTL(uart->tx_dma_ch);
 
 	if (value & DMA_CHXCTL_CHEN) {
-		if (SET != dma_flag_get(SHARK_UART_tx_dma_ch, DMA_FLAG_FTF)) {
+		if (SET != dma_flag_get(uart->tx_dma_ch, DMA_FLAG_FTF)) {
 			return;
 		}
 
-		byte_queue_skip(&shark_uart_tx_queue, shark_uart_tx_length);
-		SHARK_UART_DMA_CHCTL_TX() = value & (~DMA_CHXCTL_CHEN);
+		byte_queue_skip(&uart->tx_queue, uart->tx_length);
+		DMA_CHCTL(uart->tx_dma_ch) = value & (~DMA_CHXCTL_CHEN);
 	}
 
-	shark_uart_tx_length = byte_queue_peek(&shark_uart_tx_queue);
-	if (shark_uart_tx_length > 0) {
-		SHARK_UART_DMA_CHCNT_TX() = shark_uart_tx_length;
-		SHARK_UART_DMA_CHMADDR_TX() = (u32) byte_queue_head(&shark_uart_tx_queue);
+	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(SHARK_UART_tx_dma_ch, DMA_FLAG_FTF);
-		SHARK_UART_DMA_CHCTL_TX() = value | DMA_CHXCTL_CHEN;
+		dma_flag_clear(uart->tx_dma_ch, DMA_FLAG_FTF);
+		DMA_CHCTL(uart->tx_dma_ch) = value | DMA_CHXCTL_CHEN;
 	}
 }
 
-static void shark_uart_dma_rx(void)
-{
-	u16 index = shark_uart_rx_index;
-
-	shark_uart_rx_index = sizeof(shark_uart_rx_cache) - SHARK_UART_DMA_CHCNT_RX();
 
-	if (shark_uart_rx_index < index) {
-		shark_uart_on_data_received(shark_uart_rx_cache + index, sizeof(shark_uart_rx_cache) - index);
-		shark_uart_on_data_received(shark_uart_rx_cache, shark_uart_rx_index);
-	} else {
-		shark_uart_on_data_received(shark_uart_rx_cache + index, shark_uart_rx_index - index);
-	}
-}
 
-void shark_uart_write(const u8 *buff, u16 size)
+static void shark_uart_write(shark_uart_t *uart, const u8 *buff, u16 size)
 {
 	while (size > 0) {
-		u16 length = byte_queue_write(&shark_uart_tx_queue, buff, size);
+		u16 length = byte_queue_write(&uart->tx_queue, buff, size);
 
 		if (length == size) {
 			break;
 		}
 
-		shark_uart_dma_tx();
+		shark_uart_dma_tx(uart);
 		buff += length;
 		size -= length;
 	}
 }
 
-void shark_uart_write_byte(u8 value)
+static void shark_uart_write_byte(shark_uart_t *uart, u8 value)
 {
-	shark_uart_write(&value, 1);
+	shark_uart_write(uart, &value, 1);
 }
 
 void shark_uart_dma_init(dma_channel_enum channelx, u8 direction, u32 periph_addr, void *memory_addr, u16 length)
@@ -258,98 +208,161 @@ void shark_uart_dma_init(dma_channel_enum channelx, u8 direction, u32 periph_add
 
 static u32 shark_uart_handler(void)
 {
-	shark_uart_dma_rx();
-	shark_uart_dma_tx();
+	shark_uart_t *uart = _shark_uart + SHARK_UART0;
+	if (uart->uart_com != 0) {
+		shark_uart_rx(uart);
+		shark_uart_dma_tx(uart);
+	}
+	uart = _shark_uart + SHARK_UART1;
+	if (uart->uart_com != 0) {
+		shark_uart_rx(uart);
+		shark_uart_dma_tx(uart);
+	}
 	return 0;
 }
 
-static shark_task_t shark_uart_task = {
-	.handler = shark_uart_handler
-};
+static u8 *tx_cache_addr(uart_enum_t uart_no){
+	return (uart_no == SHARK_UART0)?shark_uart0_tx_cache:shark_uart1_tx_cache;
+}
 
-void shark_uart_init(void)
-{
-	byte_queue_init(&shark_uart_tx_queue, shark_uart_tx_cache, sizeof(shark_uart_tx_cache));
+void shark_uart_deinit(uart_enum_t uart_no){
+	shark_uart_t *uart = _shark_uart + uart_no;
+	if (uart->uart_com != 0) {
+		usart_deinit(uart->uart_com);
+		rcu_periph_clock_enable(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);
+	}
+	if (uart_no == SHARK_UART0) {
+		UART0_IR_EN(0);
+	}else {
+		UART1_IR_EN(0);
+	}	
+}
 
-	rcu_periph_clock_enable(SHARK_UART_clk);
-	rcu_periph_clock_enable(SHARK_UART_rx_gpio_clk);
-	rcu_periph_clock_enable(SHARK_UART_tx_gpio_clk);
 
-	gpio_mode_set(SHARK_UART_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, SHARK_UART_tx_pin);
-	gpio_mode_set(SHARK_UART_rx_port, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, SHARK_UART_rx_pin);
+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;
 
-	usart_deinit(SHARK_UART_com);
-	usart_baudrate_set(SHARK_UART_com, SHARK_UART_BAUDRATE);
+	circle_buffer_init(&uart->rx_queue, (char *)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);
 
-	usart_word_length_set(SHARK_UART_com, USART_WL_8BIT);
-	usart_stop_bit_set(SHARK_UART_com, USART_STB_1BIT);
-	usart_parity_config(SHARK_UART_com, USART_PM_NONE);
-	usart_hardware_flow_rts_config(SHARK_UART_com, USART_RTS_DISABLE);
-	usart_hardware_flow_cts_config(SHARK_UART_com, USART_CTS_DISABLE);
-	usart_receive_config(SHARK_UART_com, USART_RECEIVE_ENABLE);
-	usart_transmit_config(SHARK_UART_com, USART_TRANSMIT_ENABLE);
+	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;
 
-	rcu_periph_clock_enable(SHARK_UART_tx_dma_clk);
-	shark_uart_dma_init(SHARK_UART_tx_dma_ch, DMA_MEMORY_TO_PERIPHERAL, SHARK_UART_DMA_ADDR(), shark_uart_tx_cache, 0);
-	dma_circulation_disable(SHARK_UART_tx_dma_ch);
-	usart_dma_transmit_config(SHARK_UART_com, USART_DENT_ENABLE);
+	if (uart_no == 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);
 
-	rcu_periph_clock_enable(SHARK_UART_rx_dma_clk);
-	shark_uart_dma_init(SHARK_UART_rx_dma_ch, DMA_PERIPHERAL_TO_MEMORY, SHARK_UART_DMA_ADDR(), shark_uart_rx_cache, sizeof(shark_uart_rx_cache));
-	dma_circulation_enable(SHARK_UART_rx_dma_ch);
-	dma_channel_enable(SHARK_UART_rx_dma_ch);
-	usart_dma_receive_config(SHARK_UART_com, USART_DENR_ENABLE);
+		gpio_mode_set(SHARK_UART0_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, SHARK_UART0_tx_pin);
+		gpio_mode_set(SHARK_UART0_rx_port, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, 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);
 
-	usart_enable(SHARK_UART_com);
+		gpio_mode_set(SHARK_UART1_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, SHARK_UART1_tx_pin);
+		gpio_mode_set(SHARK_UART1_rx_port, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, SHARK_UART1_rx_pin);
 
-	shark_task_add(&shark_uart_task);
+	}
+	
+	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);
+
+	
+	rcu_periph_clock_enable(uart_no == SHARK_UART0?SHARK_UART0_tx_dma_clk:SHARK_UART1_tx_dma_clk);
+	shark_uart_dma_init(uart->tx_dma_ch, DMA_MEMORY_TO_PERIPHERAL, uart->uart_com + 0x04, tx_cache_addr(uart_no), 0);
+	dma_circulation_disable(uart->tx_dma_ch);
+	usart_dma_transmit_config(uart->uart_com, USART_DENT_ENABLE);
+
+	rcu_periph_clock_enable(uart_no == SHARK_UART0?SHARK_UART0_rx_dma_clk:SHARK_UART1_rx_dma_clk);
+	shark_uart_dma_init(uart->rx_dma_ch, DMA_PERIPHERAL_TO_MEMORY, uart->uart_com + 0x04, shark_uart_rx_cache, SHARK_UART_TX_MEM_SIZE);
+	dma_circulation_enable(uart->rx_dma_ch);
+	dma_channel_enable(uart->rx_dma_ch);
+	usart_dma_receive_config(uart->uart_com, USART_DENR_ENABLE);
+
+	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 = 0xFFFFFFFFFFFFL;
 }
 
-void shark_uart_write_byte_esc(u8 value)
+static void shark_uart_write_byte_esc(shark_uart_t *uart, u8 value)
 {
 	switch (value) {
 	case CH_START:
-		shark_uart_write_byte(CH_ESC);
+		shark_uart_write_byte(uart, CH_ESC);
 		value = CH_ESC_START;
 		break;
 
 	case CH_END:
-		shark_uart_write_byte(CH_ESC);
+		shark_uart_write_byte(uart, CH_ESC);
 		value = CH_ESC_END;
 		break;
 
 	case CH_ESC:
-		shark_uart_write_byte(CH_ESC);
+		shark_uart_write_byte(uart, CH_ESC);
 		value = CH_ESC_ESC;
 		break;
 	}
 
-	shark_uart_write_byte(value);
+	shark_uart_write_byte(uart, value);
 }
 
-void shark_uart_write_esc(const u8 *buff, u16 length)
+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(*buff);
+		shark_uart_write_byte_esc(uart, *buff);
 	}
 }
 
-void shark_uart_tx_start(void)
+static void shark_uart_tx_start(shark_uart_t *uart)
 {
-	shark_uart_write_byte(CH_START);
-	shark_uart_tx_crc16 = 0;
+	shark_uart_write_byte(uart, CH_START);
+	uart->tx_crc16 = 0;
 }
 
-void shark_uart_tx_continue(const void *buff, u16 length)
+static void shark_uart_tx_continue(shark_uart_t *uart, const void *buff, u16 length)
 {
-	shark_uart_write_esc((const u8 *) buff, length);
-	shark_uart_tx_crc16 = shark_crc16_update(shark_uart_tx_crc16, (const u8 *) buff, length);
+	shark_uart_write_esc(uart, (const u8 *) buff, length);
+	uart->tx_crc16 = shark_crc16_update(uart->tx_crc16, (const u8 *) buff, length);
 }
 
-void shark_uart_tx_end(void)
+static void shark_uart_tx_end(shark_uart_t *uart)
 {
-	shark_uart_write_esc((u8 *) &shark_uart_tx_crc16, sizeof(shark_uart_tx_crc16));
-	shark_uart_write_byte(CH_END);
+	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, char *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);
+}
+

+ 28 - 6
Application/bsp/uart.h

@@ -2,6 +2,7 @@
 
 #include "libs/shark_libs.h"
 #include "libs/byte_queue.h"
+#include "libs/circle_buffer.h"
 
 #define CH_START						0xF5
 #define CH_END							0xF6
@@ -13,9 +14,30 @@
 #define SHARK_UART_TX_MEM_SIZE			512
 #define SHARK_UART_RX_MEM_SIZE			512
 
-void shark_uart_init(void);
-void shark_uart_tx_start(void);
-void shark_uart_tx_continue(const void *buff, u16 length);
-void shark_uart_tx_end(void);
-bool shark_uart_tx_frame(u32 efid, const void *data);
-bool shark_uart_tx_command(u8 command, const void *args, u16 length);
+typedef enum {
+	SHARK_UART0,
+	SHARK_UART1,
+	SHARK_UART2,
+	SHARK_UART3,
+	SHARK_UART4,
+	SHARK_UART_COUNT
+} uart_enum_t;
+
+
+typedef struct {
+	byte_queue_t tx_queue;
+	c_buffer_t rx_queue;
+	dma_channel_enum rx_dma_ch;
+	dma_channel_enum tx_dma_ch;
+	uint16_t tx_length;
+	uint16_t tx_crc16;
+	uint32_t uart_com;//uart device
+	uint8_t rx_frame[256];
+	uint16_t rx_length;
+	bool escape;
+}shark_uart_t;
+
+void shark_uart_init(uart_enum_t uart_no);
+void shark_uart_deinit(uart_enum_t uart_no);
+void shark_uart_write_frame(uart_enum_t uart_no, char *bytes, int len);
+

+ 116 - 0
Application/libs/circle_buffer.c

@@ -0,0 +1,116 @@
+
+#include <string.h>
+#include "circle_buffer.h"
+
+static int circle_get_write_space(c_buffer_t *cbuff);
+static int circle_get_read_space(c_buffer_t *cbuff);
+
+void circle_buffer_init(c_buffer_t *cbuff, char *buffer, int16_t max_len){
+	cbuff->buffer = buffer;
+	cbuff->buffer_len = max_len;
+}
+
+void circle_reset(c_buffer_t *cbuff){
+	cbuff->r_pos = cbuff->w_pos = 0;
+}
+
+
+int circle_put_data(c_buffer_t *cbuff, char *data, int16_t len){
+	int16_t size = circle_get_write_space(cbuff);
+	int16_t w_len = len;
+	int16_t w1_len = len;
+	if (size < 0){
+		return size;
+	}
+	w_len = min(len, size);
+	while(w_len > 0){
+		//wrapper
+		if (cbuff->w_pos + w_len > cbuff->buffer_len){
+			w1_len = cbuff->buffer_len - cbuff->w_pos;
+		}else{
+			w1_len = w_len;
+		}
+		memcpy(cbuff->buffer + cbuff->w_pos, data, w1_len);
+		cbuff->w_pos = (cbuff->w_pos + w1_len);
+		if (cbuff->w_pos == cbuff->buffer_len){
+			cbuff->w_pos = 0;
+		}
+		w_len -= w1_len;
+		data += w1_len;
+	}
+	return min(len, size);
+}
+
+int circle_put_one_data(c_buffer_t *cbuff, char data){
+	int16_t size = circle_get_write_space(cbuff);
+	if (size < 0){
+		return size;
+	}
+	cbuff->buffer[cbuff->w_pos] = data;
+	cbuff->w_pos = cbuff->w_pos + 1;
+	if (cbuff->w_pos == cbuff->buffer_len){
+		cbuff->w_pos = 0;
+	}
+	return 1;
+}
+
+int circle_get_data(c_buffer_t *cbuff, char *data, int16_t len){
+	int16_t size = circle_get_read_space(cbuff);
+	int16_t r_len = len;
+	int16_t r1_len = 0;
+	if (size <= 0){
+		return size;
+	}
+
+	r_len = min(size, len);
+
+	while(r_len > 0){
+		if (cbuff->r_pos + r_len > cbuff->buffer_len){
+			r1_len = cbuff->buffer_len - cbuff->r_pos;
+		}else{
+			r1_len = r_len;
+		}
+		memcpy(data, cbuff->buffer + cbuff->r_pos, r1_len);
+		cbuff->r_pos = (cbuff->r_pos + r1_len);
+		if (cbuff->r_pos == cbuff->buffer_len){
+			cbuff->r_pos = 0;
+		}		
+		r_len -= r1_len;
+		data += r1_len;
+	}
+	return min(size, len);
+}
+
+
+int circle_get_one_data(c_buffer_t *cbuff, char *data){
+	int16_t size = circle_get_read_space(cbuff);
+	if (size <= 0){
+		return size;
+	}
+	*data = cbuff->buffer[cbuff->r_pos];
+	cbuff->r_pos = cbuff->r_pos + 1;
+	if (cbuff->r_pos == cbuff->buffer_len){
+		cbuff->r_pos = 0;
+	}
+	return 1;
+}
+
+
+static __inline__ int circle_get_write_space(c_buffer_t *cbuff){
+	int16_t size = (cbuff->w_pos >= cbuff->r_pos)?(cbuff->buffer_len - cbuff->w_pos + cbuff->r_pos):(cbuff->r_pos - cbuff->w_pos);
+	size -= 1;
+	if (size <= 0){
+		return CBUFF_FULL;
+	}
+	return size;
+}
+
+static __inline__ int circle_get_read_space(c_buffer_t *cbuff){
+	int16_t size = (cbuff->r_pos > cbuff->w_pos) ? (cbuff->buffer_len - cbuff->r_pos + cbuff->w_pos) : (cbuff->w_pos - cbuff->r_pos);
+	if (size <= 0){
+		return CBUFF_EMPTY;
+	}
+	return size;
+}
+
+

+ 37 - 0
Application/libs/circle_buffer.h

@@ -0,0 +1,37 @@
+#ifndef _Cirule_Buffer_h__
+#define _Cirule_Buffer_h__
+
+#include <stdint.h>
+#ifndef min
+#define min(x,y)(x<y)?x:y;
+#endif
+
+#define CBUFF_SUCCESS 0
+#define CBUFF_FULL -1
+#define CBUFF_EMPTY -2
+
+typedef struct {
+	char * buffer;
+	int16_t buffer_len;
+	int16_t w_pos;
+	int16_t r_pos;
+}c_buffer_t;
+
+//used by dma
+static __inline__ void circle_update_write_position(c_buffer_t *cbuff, int pos){
+	cbuff->w_pos = pos;
+}
+
+static __inline__ int circle_get_read_position(c_buffer_t *cbuff){
+	return cbuff->r_pos;
+}
+
+void circle_buffer_init(c_buffer_t *cbuff, char *buffer, int16_t max_len);
+void circle_reset(c_buffer_t *cbuff);
+int circle_put_one_data(c_buffer_t *cbuff, char data);
+int circle_put_data(c_buffer_t *cbuff, char *data, int16_t len);
+int circle_get_one_data(c_buffer_t *cbuff, char *data);
+int circle_get_data(c_buffer_t *cbuffer, char *data, int16_t len);
+
+#endif /* _Cirule_Buffer_h__ */
+

+ 37 - 25
Project/SP700.uvoptx

@@ -581,6 +581,18 @@
       <RteFlg>0</RteFlg>
       <bShared>0</bShared>
     </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>25</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\libs\circle_buffer.c</PathWithFileName>
+      <FilenameWithoutPath>circle_buffer.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
   </Group>
 
   <Group>
@@ -591,7 +603,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>25</FileNumber>
+      <FileNumber>26</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -603,7 +615,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>26</FileNumber>
+      <FileNumber>27</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -615,7 +627,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>27</FileNumber>
+      <FileNumber>28</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -627,7 +639,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>28</FileNumber>
+      <FileNumber>29</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -639,7 +651,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>29</FileNumber>
+      <FileNumber>30</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -651,7 +663,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>30</FileNumber>
+      <FileNumber>31</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -663,7 +675,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>31</FileNumber>
+      <FileNumber>32</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -675,7 +687,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>32</FileNumber>
+      <FileNumber>33</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -687,7 +699,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>33</FileNumber>
+      <FileNumber>34</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -699,7 +711,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>34</FileNumber>
+      <FileNumber>35</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -711,7 +723,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>35</FileNumber>
+      <FileNumber>36</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -723,7 +735,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>36</FileNumber>
+      <FileNumber>37</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -735,7 +747,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>37</FileNumber>
+      <FileNumber>38</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -747,7 +759,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>38</FileNumber>
+      <FileNumber>39</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -759,7 +771,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>39</FileNumber>
+      <FileNumber>40</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -771,7 +783,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>40</FileNumber>
+      <FileNumber>41</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -783,7 +795,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>41</FileNumber>
+      <FileNumber>42</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -795,7 +807,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>42</FileNumber>
+      <FileNumber>43</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -807,7 +819,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>43</FileNumber>
+      <FileNumber>44</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -819,7 +831,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>44</FileNumber>
+      <FileNumber>45</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -831,7 +843,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>45</FileNumber>
+      <FileNumber>46</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -843,7 +855,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>46</FileNumber>
+      <FileNumber>47</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -855,7 +867,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>47</FileNumber>
+      <FileNumber>48</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -875,7 +887,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>48</FileNumber>
+      <FileNumber>49</FileNumber>
       <FileType>2</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -887,7 +899,7 @@
     </File>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>49</FileNumber>
+      <FileNumber>50</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>

+ 5 - 0
Project/SP700.uvprojx

@@ -518,6 +518,11 @@
               <FileType>1</FileType>
               <FilePath>..\Application\libs\logger.c</FilePath>
             </File>
+            <File>
+              <FileName>circle_buffer.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\libs\circle_buffer.c</FilePath>
+            </File>
           </Files>
         </Group>
         <Group>