|
|
|
@ -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) |
|
|
|
void USART2_IRQHandler(void) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) |
|
|
|
uint8_t *rxdata = RXBuffer; |
|
|
|
{ |
|
|
|
|
|
|
|
uint16_t chr = USART_ReceiveData(USART2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(Vcom.rx_bytes < RX_BUFF_SIZE) |
|
|
|
if(Vcom.in_ready) // 可以向主机发送数据
|
|
|
|
{ |
|
|
|
{ |
|
|
|
Vcom.rx_buff[Vcom.rx_wrptr++] = chr; |
|
|
|
if((DMA1->INTFR & (DMA1_FLAG_HT6 | DMA1_FLAG_TC6)) || (SysTick_ms > RX_Timeout)) |
|
|
|
if(Vcom.rx_wrptr == RX_BUFF_SIZE) |
|
|
|
{ |
|
|
|
Vcom.rx_wrptr = 0; |
|
|
|
if(DMA1->INTFR & DMA1_FLAG_HT6) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
rxdata = &RXBuffer[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.tx_bytes--; |
|
|
|
Vcom.in_bytes = BUF_SZ/2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t n_xfer = BUF_SZ - DMA_GetCurrDataCounter(DMA1_Channel6); |
|
|
|
void VCOM_TransferData(void) |
|
|
|
if(n_xfer == 0) |
|
|
|
{ |
|
|
|
|
|
|
|
if(Vcom.in_ready) // 可以向主机发送数据
|
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if(Vcom.rx_bytes) // 有新的数据可以发送
|
|
|
|
goto xfer_out; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|