UART DMA enable

pull/13/head
XIVN1987 3 years ago
parent ce8fa732f8
commit f9018ffcb8
  1. 3
      CH32V305/src/USBD/ch32v30x_usbhs_device.c
  2. 29
      CH32V305/src/main.c
  3. 143
      CH32V305/src/vcom_serial.c

@ -644,7 +644,8 @@ void USBHS_IRQHandler( void )
USBHSD->UEP3_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1; 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; 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_bytes = len;
Vcom.out_ready = 1; Vcom.out_ready = 1;
break; break;

@ -7,6 +7,12 @@
#include "hid_transfer.h" #include "hid_transfer.h"
volatile uint32_t SysTick_ms = 0;
void SysTick_Config(uint32_t ticks);
void main(void) void main(void)
{ {
DAP_Setup(); DAP_Setup();
@ -16,6 +22,8 @@ void main(void)
USBHS_RCC_Init(); USBHS_RCC_Init();
USBHS_Device_Init(ENABLE); USBHS_Device_Init(ENABLE);
SysTick_Config(SystemCoreClock / 1000);
while(1) while(1)
{ {
usbd_hid_process(); usbd_hid_process();
@ -23,3 +31,24 @@ void main(void)
VCOM_TransferData(); 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++;
}

@ -11,14 +11,24 @@ volatile VCOM Vcom;
VCOM_LINE_CODING LineCfg = {115200, 0, 0, 8}; // Baud rate, stop bits, parity bits, data bits 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) void VCOM_Init(void)
{ {
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure; USART_InitTypeDef USART_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_AHBPeriphClockCmd (RCC_AHBPeriph_DMA1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
@ -29,18 +39,38 @@ void VCOM_Init(void)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure); // PA3 => USART2_RX 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_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No; 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_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART2, &USART_InitStructure); 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); USART_Cmd(USART2, ENABLE);
NVIC_EnableIRQ(USART2_IRQn);
} }
@ -73,7 +103,7 @@ void VCOM_LineCoding(VCOM_LINE_CODING * LineCfgx)
} }
USART_InitStructure.USART_BaudRate = LineCfgx->u32DTERate; 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; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
@ -90,71 +120,69 @@ void VCOM_LineCoding(VCOM_LINE_CODING * LineCfgx)
USART_Init(USART2, &USART_InitStructure); USART_Init(USART2, &USART_InitStructure);
RX_Timeout = (1000.0 / USART_InitStructure.USART_BaudRate) * (512 * 10) * 1.5;
__enable_irq(); __enable_irq();
} }
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); extern volatile uint32_t SysTick_ms;
void VCOM_TransferData(void)
{
uint8_t *rxdata = RXBuffer;
void USART2_IRQHandler(void) if(Vcom.in_ready) // 可以向主机发送数据
{ {
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) if((DMA1->INTFR & (DMA1_FLAG_HT6 | DMA1_FLAG_TC6)) || (SysTick_ms > RX_Timeout))
{ {
uint16_t chr = USART_ReceiveData(USART2); if(DMA1->INTFR & DMA1_FLAG_HT6)
if(Vcom.rx_bytes < RX_BUFF_SIZE)
{ {
Vcom.rx_buff[Vcom.rx_wrptr++] = chr; rxdata = &RXBuffer[0];
if(Vcom.rx_wrptr == RX_BUFF_SIZE)
Vcom.rx_wrptr = 0;
Vcom.rx_bytes++; Vcom.in_bytes = BUF_SZ/2;
}
}
if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET) DMA1->INTFCR = DMA1_FLAG_HT6;
{ }
if(Vcom.tx_bytes) else if(DMA1->INTFR & DMA1_FLAG_TC6)
{ {
USART_SendData(USART2, Vcom.tx_buff[Vcom.tx_rdptr++]); rxdata = &RXBuffer[BUF_SZ/2];
if(Vcom.tx_rdptr == TX_BUFF_SIZE)
Vcom.tx_rdptr = 0; Vcom.in_bytes = BUF_SZ/2;
Vcom.tx_bytes--; DMA1->INTFCR = DMA1_FLAG_TC6;
SysTick_ms = 0;
} }
else else
{ {
/* No more data, just stop Tx (Stop work) */ SysTick_ms = 0;
USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
}
}
}
void VCOM_TransferData(void) uint32_t n_xfer = BUF_SZ - DMA_GetCurrDataCounter(DMA1_Channel6);
if(n_xfer == 0)
{ {
if(Vcom.in_ready) // 可以向主机发送数据 goto xfer_out;
{ }
if(Vcom.rx_bytes) // 有新的数据可以发送 if(n_xfer < BUF_SZ/2)
{ {
Vcom.in_bytes = Vcom.rx_bytes; rxdata = &RXBuffer[0];
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++) Vcom.in_bytes = n_xfer;
}
else
{ {
Vcom.in_buff[i] = Vcom.rx_buff[Vcom.rx_rdptr++]; rxdata = &RXBuffer[BUF_SZ/2];
if(Vcom.rx_rdptr >= RX_BUFF_SIZE)
Vcom.rx_rdptr = 0; Vcom.in_bytes = n_xfer - BUF_SZ/2;
} }
__disable_irq(); DMA_Cmd(DMA1_Channel6, DISABLE);
Vcom.rx_bytes -= Vcom.in_bytes; DMA_SetCurrDataCounter(DMA1_Channel6, BUF_SZ);
__enable_irq(); DMA_Cmd(DMA1_Channel6, ENABLE);
}
Vcom.in_ready = 0; 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_LEN = Vcom.in_bytes;
USBHSD->UEP3_TX_CTRL = (USBHSD->UEP3_TX_CTRL & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK; 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 能够装下它们 */ /* 从主机接收到数据,且 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; 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 */ /* Ready for next BULK OUT */
USBHSD->UEP3_RX_CTRL = (USBHSD->UEP3_RX_CTRL & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_ACK; 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);
}
} }

Loading…
Cancel
Save