mirror of https://github.com/XIVN1987/DAPLink
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
6.1 KiB
218 lines
6.1 KiB
#include "NuMicro.h" |
|
#include "vcom_serial.h" |
|
#include "hid_transfer.h" |
|
|
|
|
|
void VCOM_Init(void) |
|
{ |
|
GPIO_SetPullCtl(PB, BIT0, GPIO_PUSEL_PULL_UP); |
|
SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB0MFP_Msk | SYS_GPB_MFPL_PB1MFP_Msk); |
|
SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB0MFP_UART2_RXD | SYS_GPB_MFPL_PB1MFP_UART2_TXD); |
|
|
|
CLK_SetModuleClock(UART2_MODULE, CLK_CLKSEL3_UART2SEL_HXT, CLK_CLKDIV4_UART2(1)); |
|
CLK_EnableModuleClock(UART2_MODULE); |
|
|
|
UART_Open(UART2, 115200); |
|
|
|
UART2->FIFO = (UART2->FIFO & (~UART_FIFO_RFITL_Msk)) | UART_FIFO_RFITL_8BYTES; |
|
UART_SetTimeoutCnt(UART2, 50); |
|
|
|
UART_ENABLE_INT(UART2, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk)); |
|
|
|
NVIC_EnableIRQ(UART2_IRQn); |
|
} |
|
|
|
|
|
volatile VCOM Vcom = {.in_ready = 1}; |
|
|
|
void EP5_Handler(void) // Bulk IN |
|
{ |
|
Vcom.in_ready = 1; |
|
} |
|
|
|
void EP6_Handler(void) // Bulk OUT |
|
{ |
|
Vcom.out_bytes = USBD_GET_PAYLOAD_LEN(EP6); |
|
USBD_MemCopy((uint8_t *)Vcom.out_buff, (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP6)), Vcom.out_bytes); |
|
|
|
Vcom.out_ready = 1; |
|
} |
|
|
|
|
|
VCOM_LINE_CODING LineCfg = {115200, 0, 0, 8}; // Baud rate, stop bits, parity bits, data bits |
|
|
|
void VCOM_LineCoding(VCOM_LINE_CODING * LineCfgx) |
|
{ |
|
uint32_t data_len, parity, stop_len; |
|
|
|
switch(LineCfgx->u8DataBits) |
|
{ |
|
case 5: data_len = UART_WORD_LEN_5; break; |
|
case 6: data_len = UART_WORD_LEN_6; break; |
|
case 7: data_len = UART_WORD_LEN_7; break; |
|
case 8: data_len = UART_WORD_LEN_8; break; |
|
default: data_len = UART_WORD_LEN_8; break; |
|
} |
|
|
|
switch(LineCfgx->u8ParityType) |
|
{ |
|
case 0: parity = UART_PARITY_NONE; break; |
|
case 1: parity = UART_PARITY_ODD; break; |
|
case 2: parity = UART_PARITY_EVEN; break; |
|
case 3: parity = UART_PARITY_MARK; break; |
|
case 4: parity = UART_PARITY_SPACE; break; |
|
default: parity = UART_PARITY_NONE; break; |
|
} |
|
|
|
switch(LineCfgx->u8CharFormat) |
|
{ |
|
case 0: stop_len = UART_STOP_BIT_1; break; |
|
case 1: stop_len = UART_STOP_BIT_1_5; break; |
|
case 2: stop_len = UART_STOP_BIT_2; break; |
|
default: stop_len = UART_STOP_BIT_1; break; |
|
} |
|
|
|
__disable_irq(); |
|
|
|
// Reset software FIFO |
|
Vcom.rx_bytes = 0; |
|
Vcom.rx_head = 0; |
|
Vcom.rx_tail = 0; |
|
|
|
Vcom.tx_bytes = 0; |
|
Vcom.tx_head = 0; |
|
Vcom.tx_tail = 0; |
|
|
|
// Reset hardware FIFO |
|
UART2->FIFO |= (UART_FIFO_RXRST_Msk | UART_FIFO_TXRST_Msk); |
|
|
|
UART_SetLineConfig(UART2, LineCfgx->u32DTERate, data_len, parity, stop_len); |
|
|
|
__enable_irq(); |
|
} |
|
|
|
|
|
void UART2_IRQHandler(void) |
|
{ |
|
if((UART2->INTSTS & UART_INTSTS_RDAIF_Msk) || (UART2->INTSTS & UART_INTSTS_RXTOIF_Msk)) |
|
{ |
|
while((UART2->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0) |
|
{ |
|
uint8_t chr = UART2->DAT; |
|
|
|
if(Vcom.rx_bytes < RX_BUFF_SIZE) // Check if buffer full |
|
{ |
|
Vcom.rx_buff[Vcom.rx_tail++] = chr; |
|
if(Vcom.rx_tail >= RX_BUFF_SIZE) |
|
Vcom.rx_tail = 0; |
|
Vcom.rx_bytes++; |
|
} |
|
} |
|
} |
|
|
|
if(UART2->INTSTS & UART_INTSTS_THREIF_Msk) |
|
{ |
|
if(Vcom.tx_bytes) |
|
{ |
|
/* Fill the Tx FIFO */ |
|
int size = Vcom.tx_bytes; |
|
if(size >= TX_FIFO_SIZE) |
|
{ |
|
size = TX_FIFO_SIZE; |
|
} |
|
|
|
while(size) |
|
{ |
|
UART2->DAT = Vcom.tx_buff[Vcom.tx_head++]; |
|
if(Vcom.tx_head >= TX_BUFF_SIZE) |
|
Vcom.tx_head = 0; |
|
Vcom.tx_bytes--; |
|
size--; |
|
} |
|
} |
|
else |
|
{ |
|
/* No more data, just stop Tx (Stop work) */ |
|
UART2->INTEN &= ~UART_INTEN_THREIEN_Msk; |
|
} |
|
} |
|
} |
|
|
|
|
|
void VCOM_TransferData(void) |
|
{ |
|
/* Check whether USB is ready for next packet or not */ |
|
if(Vcom.in_ready) |
|
{ |
|
/* Check whether we have new COM Rx data to send to USB or not */ |
|
if(Vcom.rx_bytes) |
|
{ |
|
Vcom.in_bytes = Vcom.rx_bytes; |
|
if(Vcom.in_bytes > EP5_MAX_PKT_SIZE) |
|
Vcom.in_bytes = EP5_MAX_PKT_SIZE; |
|
|
|
for(int i = 0; i < Vcom.in_bytes; i++) |
|
{ |
|
Vcom.in_buff[i] = Vcom.rx_buff[Vcom.rx_head++]; |
|
if(Vcom.rx_head >= RX_BUFF_SIZE) |
|
Vcom.rx_head = 0; |
|
} |
|
|
|
__disable_irq(); |
|
Vcom.rx_bytes -= Vcom.in_bytes; |
|
__enable_irq(); |
|
|
|
Vcom.in_ready = 0; |
|
USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP5)), (uint8_t *)Vcom.in_buff, Vcom.in_bytes); |
|
USBD_SET_PAYLOAD_LEN(EP5, Vcom.in_bytes); |
|
} |
|
else |
|
{ |
|
/* Prepare a zero packet if previous packet size is InEP_MAX_PKT_SIZE and |
|
no more data to send at this moment to note Host the transfer has been done */ |
|
if(Vcom.in_bytes == EP5_MAX_PKT_SIZE) |
|
USBD_SET_PAYLOAD_LEN(EP5, 0); |
|
} |
|
} |
|
|
|
/* Process the Bulk out data when bulk out data is ready. */ |
|
if(Vcom.out_ready && (Vcom.out_bytes <= TX_BUFF_SIZE - Vcom.tx_bytes)) |
|
{ |
|
for(int i = 0; i < Vcom.out_bytes; i++) |
|
{ |
|
Vcom.tx_buff[Vcom.tx_tail++] = Vcom.out_buff[i]; |
|
if(Vcom.tx_tail >= TX_BUFF_SIZE) |
|
Vcom.tx_tail = 0; |
|
} |
|
|
|
__disable_irq(); |
|
Vcom.tx_bytes += Vcom.out_bytes; |
|
__enable_irq(); |
|
|
|
Vcom.out_bytes = 0; |
|
Vcom.out_ready = 0; /* Clear bulk out ready flag */ |
|
|
|
/* Ready to get next BULK out */ |
|
USBD_SET_PAYLOAD_LEN(EP6, EP6_MAX_PKT_SIZE); |
|
} |
|
|
|
/* Process the software Tx FIFO */ |
|
if(Vcom.tx_bytes) |
|
{ |
|
/* Check if Tx is working */ |
|
if((UART2->INTEN & UART_INTEN_THREIEN_Msk) == 0) |
|
{ |
|
/* Send one bytes out */ |
|
UART2->DAT = Vcom.tx_buff[Vcom.tx_head++]; |
|
if(Vcom.tx_head >= TX_BUFF_SIZE) |
|
Vcom.tx_head = 0; |
|
|
|
__disable_irq(); |
|
Vcom.tx_bytes--; |
|
__enable_irq(); |
|
|
|
/* Enable Tx Empty Interrupt. (Trigger first one) */ |
|
UART2->INTEN |= UART_INTEN_THREIEN_Msk; |
|
} |
|
} |
|
}
|
|
|