diff --git a/AT32F425/DAPLink.uvoptx b/AT32F425/DAPLink.uvoptx index 32bdac9..4c09f4b 100644 --- a/AT32F425/DAPLink.uvoptx +++ b/AT32F425/DAPLink.uvoptx @@ -135,7 +135,7 @@ 0 DLGUARM - + d 0 @@ -221,6 +221,16 @@ + + + System Viewer\DMA1 + 35905 + + + System Viewer\USB_OTG1_DEVICE + 35904 + + @@ -282,7 +292,7 @@ DAP - 1 + 0 0 0 0 @@ -326,7 +336,7 @@ SWD_host - 1 + 0 0 0 0 @@ -478,6 +488,18 @@ 0 0 + + 5 + 19 + 1 + 0 + 0 + 0 + .\src\CSL\AT32F425_StdPeriph_Driver\at32f425_dma.c + at32f425_dma.c + 0 + 0 + @@ -488,7 +510,7 @@ 0 6 - 19 + 20 1 0 0 @@ -500,7 +522,7 @@ 6 - 20 + 21 2 0 0 diff --git a/AT32F425/DAPLink.uvprojx b/AT32F425/DAPLink.uvprojx index 11db102..b08474e 100644 --- a/AT32F425/DAPLink.uvprojx +++ b/AT32F425/DAPLink.uvprojx @@ -492,6 +492,11 @@ 1 .\src\CSL\AT32F425_StdPeriph_Driver\at32f425_usb.c + + at32f425_dma.c + 1 + .\src\CSL\AT32F425_StdPeriph_Driver\at32f425_dma.c + diff --git a/AT32F425/src/hid_transfer.c b/AT32F425/src/hid_transfer.c index b1709c6..63420b7 100644 --- a/AT32F425/src/hid_transfer.c +++ b/AT32F425/src/hid_transfer.c @@ -20,8 +20,6 @@ static usb_sts_type class_init_handler(void *udev) { usbd_core_type *usbd = (usbd_core_type *)udev; - VCOM_Init(); - #ifdef DAP_FW_V1 usbd_ept_open(usbd, HID_INT_IN_EP, EPT_INT_TYPE, HID_INT_IN_SZ); usbd_ept_open(usbd, HID_INT_OUT_EP, EPT_INT_TYPE, HID_INT_OUT_SZ); @@ -242,6 +240,7 @@ static usb_sts_type class_event_handler(void *udev, usbd_event_type event) switch(event) { case USBD_RESET_EVENT: + Vcom.in_ready = 1; break; case USBD_SUSPEND_EVENT: diff --git a/AT32F425/src/main.c b/AT32F425/src/main.c index 96b722b..eeca533 100644 --- a/AT32F425/src/main.c +++ b/AT32F425/src/main.c @@ -18,6 +18,8 @@ int main(void) systemInit(); DAP_Setup(); + + VCOM_Init(); USB_Config(); diff --git a/AT32F425/src/vcom_serial.c b/AT32F425/src/vcom_serial.c index faa495f..f7b0a8a 100644 --- a/AT32F425/src/vcom_serial.c +++ b/AT32F425/src/vcom_serial.c @@ -1,3 +1,4 @@ +#include #include "at32f425.h" #include "usbd_sdr.h" #include "usbd_core.h" @@ -5,17 +6,25 @@ #include "hid_transfer.h" -volatile VCOM Vcom = {.in_ready = 1}; +volatile VCOM Vcom; VCOM_LINE_CODING LineCfg = {115200, 0, 0, 8}; // Baud rate, stop bits, parity bits, data bits +#define RXDMA_SZ (CDC_BULK_IN_SZ * 2) +uint8_t RXBuffer[RXDMA_SZ] __attribute__((aligned(4))); +uint8_t TXBuffer[CDC_BULK_OUT_SZ] __attribute__((aligned(4))); + + void VCOM_Init(void) { + gpio_init_type gpio_init_struct; + dma_init_type dma_init_struct; + crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_USART2_PERIPH_CLOCK, TRUE); + crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE); - gpio_init_type gpio_init_struct; gpio_default_para_init(&gpio_init_struct); gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = GPIO_PINS_2 | GPIO_PINS_3; @@ -24,13 +33,42 @@ void VCOM_Init(void) gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE2, GPIO_MUX_1); // PA2 => USART2_TX gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE3, GPIO_MUX_1); // PA3 => USART2_RX + + dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART2_TX); + dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_base_addr = (uint32_t)TXBuffer; + dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; + dma_init_struct.memory_inc_enable = TRUE; + dma_init_struct.peripheral_base_addr = (uint32_t)&USART2->dt; + dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; + dma_init_struct.peripheral_inc_enable = FALSE; + dma_init_struct.buffer_size = 0; + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init_struct.loop_mode_enable = FALSE; + dma_init(DMA1_CHANNEL1, &dma_init_struct); + dma_channel_enable(DMA1_CHANNEL1, TRUE); + + dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_UART2_RX); + dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY; + dma_init_struct.memory_base_addr = (uint32_t)RXBuffer; + dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE; + dma_init_struct.memory_inc_enable = TRUE; + dma_init_struct.peripheral_base_addr = (uint32_t)&USART2->dt; + dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; + dma_init_struct.peripheral_inc_enable = FALSE; + dma_init_struct.buffer_size = RXDMA_SZ; + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init_struct.loop_mode_enable = TRUE; + dma_init(DMA1_CHANNEL2, &dma_init_struct); + dma_channel_enable(DMA1_CHANNEL2, TRUE); + + usart_init(USART2, 115200, USART_DATA_8BITS, USART_STOP_1_BIT); - usart_interrupt_enable(USART2, USART_RDBF_INT, TRUE); + usart_dma_transmitter_enable(USART2, TRUE); + usart_dma_receiver_enable(USART2, TRUE); usart_transmitter_enable(USART2, TRUE); usart_receiver_enable(USART2, TRUE); usart_enable(USART2, TRUE); - - NVIC_EnableIRQ(USART2_IRQn); } @@ -65,15 +103,6 @@ void VCOM_LineCoding(VCOM_LINE_CODING * LineCfgx) __disable_irq(); - // Reset software FIFO - Vcom.rx_bytes = 0; - Vcom.rx_wrptr = 0; - Vcom.rx_rdptr = 0; - - Vcom.tx_bytes = 0; - Vcom.tx_wrptr = 0; - Vcom.tx_rdptr = 0; - usart_init(USART2, LineCfgx->u32DTERate, data_len, stop_len); usart_parity_selection_config(USART2, parity); @@ -81,66 +110,35 @@ void VCOM_LineCoding(VCOM_LINE_CODING * LineCfgx) } -void USART2_IRQHandler(void) -{ - if(usart_flag_get(USART2, USART_RDBF_FLAG) != RESET) - { - uint16_t chr = usart_data_receive(USART2); - - if(Vcom.rx_bytes < RX_BUFF_SIZE) - { - Vcom.rx_buff[Vcom.rx_wrptr++] = chr; - if(Vcom.rx_wrptr == RX_BUFF_SIZE) - Vcom.rx_wrptr = 0; - - Vcom.rx_bytes++; - } - } - - if(usart_flag_get(USART2, USART_TDBE_FLAG) != RESET) - { - if(Vcom.tx_bytes) - { - usart_data_transmit(USART2, Vcom.tx_buff[Vcom.tx_rdptr++]); - if(Vcom.tx_rdptr == TX_BUFF_SIZE) - Vcom.tx_rdptr = 0; - - Vcom.tx_bytes--; - } - else - { - /* No more data, just stop Tx (Stop work) */ - usart_interrupt_enable(USART2, USART_TDBE_INT, FALSE); - } - } -} - - extern otg_core_type Otg; +extern volatile uint32_t SysTick_ms; void VCOM_TransferData(void) { + static uint32_t last_ms = 0; + static uint32_t last_pos = 0; + if(Vcom.in_ready) // 可以向主机发送数据 { - if(Vcom.rx_bytes) // 有新的数据可以发送 + uint32_t pos = RXDMA_SZ - dma_data_number_get(DMA1_CHANNEL2); + if((pos - last_pos >= CDC_BULK_IN_SZ) || ((pos != last_pos) && (SysTick_ms != last_ms))) { - Vcom.in_bytes = Vcom.rx_bytes; - if(Vcom.in_bytes > CDC_BULK_IN_SZ) - Vcom.in_bytes = CDC_BULK_IN_SZ; + if(pos < last_pos) + pos = RXDMA_SZ; - for(int i = 0; i < Vcom.in_bytes; i++) - { - Vcom.in_buff[i] = Vcom.rx_buff[Vcom.rx_rdptr++]; - if(Vcom.rx_rdptr >= RX_BUFF_SIZE) - Vcom.rx_rdptr = 0; - } + if(pos - last_pos > CDC_BULK_IN_SZ) + pos = last_pos + CDC_BULK_IN_SZ; - __disable_irq(); - Vcom.rx_bytes -= Vcom.in_bytes; - __enable_irq(); + Vcom.in_bytes = pos - last_pos; Vcom.in_ready = 0; + + memcpy((uint8_t *)Vcom.in_buff, &RXBuffer[last_pos], Vcom.in_bytes); usbd_ept_send(&Otg.dev, CDC_BULK_IN_EP, (uint8_t *)Vcom.in_buff, Vcom.in_bytes); + + last_pos = pos % RXDMA_SZ; + + last_ms = SysTick_ms; } else { @@ -150,33 +148,23 @@ void VCOM_TransferData(void) { Vcom.in_bytes = 0; - usbd_ept_send(&Otg.dev, CDC_BULK_IN_EP, 0, 0); + usbd_ept_send(&Otg.dev, CDC_BULK_IN_EP, (uint8_t *)0, 0); } } } - /* 从主机接收到数据,且 tx_buff 能够装下它们 */ - if(Vcom.out_ready && (Vcom.out_bytes <= TX_BUFF_SIZE - Vcom.tx_bytes)) + /* 从主机接收到数据,且前面的数据 DMA 已发送完 */ + if(Vcom.out_ready && (dma_data_number_get(DMA1_CHANNEL1) == 0)) { - for(int i = 0; i < Vcom.out_bytes; i++) - { - Vcom.tx_buff[Vcom.tx_wrptr++] = Vcom.out_buff[i]; - if(Vcom.tx_wrptr >= TX_BUFF_SIZE) - Vcom.tx_wrptr = 0; - } - - __disable_irq(); - Vcom.tx_bytes += Vcom.out_bytes; - __enable_irq(); - Vcom.out_ready = 0; + + memcpy(TXBuffer, (uint8_t *)Vcom.out_buff, Vcom.out_bytes); + + dma_channel_enable(DMA1_CHANNEL1, FALSE); + dma_data_number_set(DMA1_CHANNEL1, Vcom.out_bytes); + dma_channel_enable(DMA1_CHANNEL1, TRUE); /* Ready for next BULK OUT */ usbd_ept_recv(&Otg.dev, CDC_BULK_OUT_EP, (uint8_t *)Vcom.out_buff, CDC_BULK_OUT_SZ); } - - if((Vcom.tx_bytes) && (USART2->ctrl1_bit.tdbeien == 0)) - { - usart_interrupt_enable(USART2, USART_TDBE_INT, TRUE); - } }