From f9018ffcb811ff2857e7f960322aae340f5fcbda Mon Sep 17 00:00:00 2001 From: XIVN1987 Date: Mon, 29 May 2023 22:08:24 +0800 Subject: [PATCH] UART DMA enable --- CH32V305/src/USBD/ch32v30x_usbhs_device.c | 3 +- CH32V305/src/main.c | 29 ++++ CH32V305/src/vcom_serial.c | 163 ++++++++++++---------- 3 files changed, 121 insertions(+), 74 deletions(-) diff --git a/CH32V305/src/USBD/ch32v30x_usbhs_device.c b/CH32V305/src/USBD/ch32v30x_usbhs_device.c index 47d15ca..65bdf67 100644 --- a/CH32V305/src/USBD/ch32v30x_usbhs_device.c +++ b/CH32V305/src/USBD/ch32v30x_usbhs_device.c @@ -644,7 +644,8 @@ void USBHS_IRQHandler( void ) USBHSD->UEP3_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1; USBHSD->UEP3_RX_CTRL = (USBHSD->UEP3_RX_CTRL & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK; - memcpy((uint8_t *)Vcom.out_buff, USBHS_EP3_Rx_Buf, len); + extern uint8_t TXBuffer[]; + memcpy(TXBuffer, USBHS_EP3_Rx_Buf, len); Vcom.out_bytes = len; Vcom.out_ready = 1; break; diff --git a/CH32V305/src/main.c b/CH32V305/src/main.c index 1a7b758..c52d27a 100644 --- a/CH32V305/src/main.c +++ b/CH32V305/src/main.c @@ -7,6 +7,12 @@ #include "hid_transfer.h" +volatile uint32_t SysTick_ms = 0; + + +void SysTick_Config(uint32_t ticks); + + void main(void) { DAP_Setup(); @@ -16,6 +22,8 @@ void main(void) USBHS_RCC_Init(); USBHS_Device_Init(ENABLE); + SysTick_Config(SystemCoreClock / 1000); + while(1) { usbd_hid_process(); @@ -23,3 +31,24 @@ void main(void) VCOM_TransferData(); } } + + +void SysTick_Config(uint32_t ticks) +{ + SysTick->CTLR= 0; + SysTick->SR = 0; + SysTick->CNT = 0; + SysTick->CMP = ticks; + SysTick->CTLR= 0x0F; + + NVIC_EnableIRQ(SysTicK_IRQn); +} + + +void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); +void SysTick_Handler(void) +{ + SysTick->SR = 0; + + SysTick_ms++; +} diff --git a/CH32V305/src/vcom_serial.c b/CH32V305/src/vcom_serial.c index efd3f8f..57a51e6 100644 --- a/CH32V305/src/vcom_serial.c +++ b/CH32V305/src/vcom_serial.c @@ -11,14 +11,24 @@ volatile VCOM Vcom; VCOM_LINE_CODING LineCfg = {115200, 0, 0, 8}; // Baud rate, stop bits, parity bits, data bits +volatile uint32_t RX_Timeout = (1000.0 / 115200) * (512 * 10) * 1.5; + + +#define BUF_SZ 1024 +uint8_t TXBuffer[BUF_SZ] __attribute__((aligned(4))); +uint8_t RXBuffer[BUF_SZ] __attribute__((aligned(4))); + void VCOM_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; + DMA_InitTypeDef DMA_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); + RCC_AHBPeriphClockCmd (RCC_AHBPeriph_DMA1, ENABLE); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; @@ -29,18 +39,38 @@ void VCOM_Init(void) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); // PA3 => USART2_RX - USART_InitStructure.USART_BaudRate = 115200; + + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; + DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DATAR; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryBaseAddr = (u32)TXBuffer; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_BufferSize = 0; + DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; + DMA_Init(DMA1_Channel7, &DMA_InitStructure); + DMA_Cmd(DMA1_Channel7, ENABLE); + + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; + DMA_InitStructure.DMA_MemoryBaseAddr = (u32)RXBuffer; + DMA_Init(DMA1_Channel6, &DMA_InitStructure); + DMA_Cmd(DMA1_Channel6, ENABLE); + + + USART_InitStructure.USART_BaudRate = LineCfg.u32DTERate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART2, &USART_InitStructure); - USART_Cmd(USART2, ENABLE); + USART_DMACmd(USART2, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE); - USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); - NVIC_EnableIRQ(USART2_IRQn); + USART_Cmd(USART2, ENABLE); } @@ -73,7 +103,7 @@ void VCOM_LineCoding(VCOM_LINE_CODING * LineCfgx) } USART_InitStructure.USART_BaudRate = LineCfgx->u32DTERate; - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; @@ -90,71 +120,69 @@ void VCOM_LineCoding(VCOM_LINE_CODING * LineCfgx) USART_Init(USART2, &USART_InitStructure); - __enable_irq(); -} - + RX_Timeout = (1000.0 / USART_InitStructure.USART_BaudRate) * (512 * 10) * 1.5; -void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); - -void USART2_IRQHandler(void) -{ - if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) - { - uint16_t chr = USART_ReceiveData(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_GetITStatus(USART2, USART_IT_TXE) != RESET) - { - if(Vcom.tx_bytes) - { - USART_SendData(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_ITConfig(USART2, USART_IT_TXE, DISABLE); - } - } + __enable_irq(); } +extern volatile uint32_t SysTick_ms; void VCOM_TransferData(void) { + uint8_t *rxdata = RXBuffer; + if(Vcom.in_ready) // 可以向主机发送数据 { - if(Vcom.rx_bytes) // 有新的数据可以发送 + if((DMA1->INTFR & (DMA1_FLAG_HT6 | DMA1_FLAG_TC6)) || (SysTick_ms > RX_Timeout)) { - Vcom.in_bytes = Vcom.rx_bytes; - if(Vcom.in_bytes > CDC_BULK_IN_SZ_HS) - Vcom.in_bytes = CDC_BULK_IN_SZ_HS; - - for(int i = 0; i < Vcom.in_bytes; i++) + if(DMA1->INTFR & DMA1_FLAG_HT6) { - Vcom.in_buff[i] = Vcom.rx_buff[Vcom.rx_rdptr++]; - if(Vcom.rx_rdptr >= RX_BUFF_SIZE) - Vcom.rx_rdptr = 0; + rxdata = &RXBuffer[0]; + + Vcom.in_bytes = BUF_SZ/2; + + DMA1->INTFCR = DMA1_FLAG_HT6; } + else if(DMA1->INTFR & DMA1_FLAG_TC6) + { + rxdata = &RXBuffer[BUF_SZ/2]; + + Vcom.in_bytes = BUF_SZ/2; - __disable_irq(); - Vcom.rx_bytes -= Vcom.in_bytes; - __enable_irq(); + DMA1->INTFCR = DMA1_FLAG_TC6; + + SysTick_ms = 0; + } + else + { + SysTick_ms = 0; + + uint32_t n_xfer = BUF_SZ - DMA_GetCurrDataCounter(DMA1_Channel6); + if(n_xfer == 0) + { + goto xfer_out; + } + if(n_xfer < BUF_SZ/2) + { + rxdata = &RXBuffer[0]; + + Vcom.in_bytes = n_xfer; + } + else + { + rxdata = &RXBuffer[BUF_SZ/2]; + + Vcom.in_bytes = n_xfer - BUF_SZ/2; + } + + DMA_Cmd(DMA1_Channel6, DISABLE); + DMA_SetCurrDataCounter(DMA1_Channel6, BUF_SZ); + DMA_Cmd(DMA1_Channel6, ENABLE); + } Vcom.in_ready = 0; - memcpy(USBHS_EP3_Tx_Buf, (uint8_t *)Vcom.in_buff, Vcom.in_bytes); + USBHSD->UEP3_TX_DMA = (uint32_t)rxdata; USBHSD->UEP3_TX_LEN = Vcom.in_bytes; USBHSD->UEP3_TX_CTRL = (USBHSD->UEP3_TX_CTRL & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK; } @@ -172,28 +200,17 @@ void VCOM_TransferData(void) } } +xfer_out: /* 从主机接收到数据,且 tx_buff 能够装下它们 */ - if(Vcom.out_ready && (Vcom.out_bytes <= TX_BUFF_SIZE - Vcom.tx_bytes)) + if(Vcom.out_ready && (DMA_GetCurrDataCounter(DMA1_Channel7) == 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; + DMA_Cmd(DMA1_Channel7, DISABLE); + DMA_SetCurrDataCounter(DMA1_Channel7, Vcom.out_bytes); + DMA_Cmd(DMA1_Channel7, ENABLE); + /* Ready for next BULK OUT */ USBHSD->UEP3_RX_CTRL = (USBHSD->UEP3_RX_CTRL & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_ACK; } - - if(Vcom.tx_bytes && ((USART2->CTLR1 & USART_CTLR1_TXEIE) == 0)) - { - USART_ITConfig(USART2, USART_IT_TXE, ENABLE); - } }