diff --git a/DAPLink.uvoptx b/DAPLink.uvoptx
index 0f9e9b7..366d30f 100644
--- a/DAPLink.uvoptx
+++ b/DAPLink.uvoptx
@@ -120,7 +120,7 @@
0
DLGUARM
- ?}wé³»??}wé³»?
+
0
@@ -269,7 +269,7 @@
DAP
- 1
+ 0
0
0
0
diff --git a/README.md b/README.md
index f767067..12b3aad 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,24 @@
## DAPLink
-DAPLink (CMSIS-DAP) based on Nuvoton M480, supports SWD and CDC.
+DAPLink (CMSIS-DAP) based on Nuvoton M480, supports SWD and CDC (1 or 2).
In the C/C++ page of Keil Option Window:
* Define `DAP_FW_V1`: generate CMSIS-DAP V1 firmware, using HID transport protocol.
* Do not define `DAP_FW_V1`: Generate CMSIS-DAP V2 firmware, using WINUSB transfer protocol.
### Pin map
-| FUNC | Pin |
-| :---- | :---- |
-| SWD_CLK | PA.1 |
-| SWD_DIO | PA.0 |
-| SWD_RST | PF.4 |
-| CDC_TXD | PB.1 |
-| CDC_RXD | PB.0 |
-| LED_SWD | PA.2 |
-| LED_TXD | PC.1 |
-| LED_RXD | PC.0 |
+| FUNC | Pin |
+| :---- | :---- |
+| SWD_CLK | PA.1 |
+| SWD_DIO | PA.0 |
+| SWD_RST | PF.4 |
+| CDC_TXD | PB.1 |
+| CDC_RXD | PB.0 |
+| LED_SWD | PA.2 |
+| LED_TXD | PC.1 |
+| LED_RXD | PC.0 |
+
+### Optional CDC2
+| FUNC | Pin |
+| :---- | :---- |
+| CDC2_TXD | PB.3 |
+| CDC2_RXD | PB.2 |
diff --git a/doc/DAPLink.pcapng b/doc/DAPLink.pcapng
deleted file mode 100644
index e6526da..0000000
Binary files a/doc/DAPLink.pcapng and /dev/null differ
diff --git a/src/descriptors.c b/src/descriptors.c
index 51e9f92..b8a7291 100644
--- a/src/descriptors.c
+++ b/src/descriptors.c
@@ -53,9 +53,9 @@ uint8_t gu8ConfigDescriptor[] =
#else
#define TOTAL_LEN_0 (LEN_CONFIG + (LEN_INTERFACE + LEN_ENDPOINT + LEN_ENDPOINT))
#endif
-#define TOTAL_LEN (TOTAL_LEN_0 + (8 + LEN_INTERFACE + 5 + 5 + 4 + 5 + LEN_ENDPOINT + LEN_INTERFACE + LEN_ENDPOINT + LEN_ENDPOINT))
+#define TOTAL_LEN (TOTAL_LEN_0 + (8 + LEN_INTERFACE + 5 + 5 + 4 + 5 + LEN_ENDPOINT + LEN_INTERFACE + LEN_ENDPOINT + LEN_ENDPOINT) * VCOM_COUNT)
TOTAL_LEN & 0xFF, TOTAL_LEN >> 8, // wTotalLength
- 0x03, // bNumInterfaces
+ (1 + 2*VCOM_COUNT), // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0x00, // bmAttributes, D6: self power D5: remote wake-up
@@ -194,6 +194,91 @@ uint8_t gu8ConfigDescriptor[] =
EP_BULK, // bmAttributes
EP6_MAX_PKT_SIZE, 0x00, // wMaxPacketSize
0x00, // bInterval
+
+#if VCOM_COUNT > 1
+ // Interface Association Descriptor (IAD)
+ 0x08, // bLength
+ 0x0B, // bDescriptorType: IAD
+ 0x03, // bFirstInterface
+ 0x02, // bInterfaceCount
+ 0x02, // bFunctionClass: CDC
+ 0x02, // bFunctionSubClass
+ 0x01, // bFunctionProtocol
+ 0x00, // iFunction, ÃèÊö×Ö·û´®Ë÷Òý
+
+ // I/F descriptor: VCOM
+ LEN_INTERFACE, // bLength
+ DESC_INTERFACE, // bDescriptorType
+ 0x03, // bInterfaceNumber
+ 0x00, // bAlternateSetting
+ 0x01, // bNumEndpoints
+ 0x02, // bInterfaceClass
+ 0x02, // bInterfaceSubClass
+ 0x01, // bInterfaceProtocol
+ 0x00, // iInterface
+
+ // Communication Class Specified INTERFACE descriptor
+ 0x05, // Size of the descriptor, in bytes
+ 0x24, // CS_INTERFACE descriptor type
+ 0x00, // Header functional descriptor subtype
+ 0x10, 0x01, // Communication device compliant to the communication spec. ver. 1.10
+
+ // Communication Class Specified INTERFACE descriptor
+ 0x05, // Size of the descriptor, in bytes
+ 0x24, // CS_INTERFACE descriptor type
+ 0x01, // Call management functional descriptor
+ 0x00, // BIT0: Whether device handle call management itself.
+ // BIT1: Whether device can send/receive call management information over a Data Class Interface 0
+ 0x04, // Interface number of data class interface optionally used for call management
+
+ // Communication Class Specified INTERFACE descriptor
+ 0x04, // Size of the descriptor, in bytes
+ 0x24, // CS_INTERFACE descriptor type
+ 0x02, // Abstract control management functional descriptor subtype
+ 0x00, // bmCapabilities
+
+ // Communication Class Specified INTERFACE descriptor
+ 0x05, // bLength
+ 0x24, // bDescriptorType: CS_INTERFACE descriptor type
+ 0x06, // bDescriptorSubType
+ 0x03, // bMasterInterface
+ 0x04, // bSlaveInterface0
+
+ // ENDPOINT descriptor
+ LEN_ENDPOINT, // bLength
+ DESC_ENDPOINT, // bDescriptorType
+ (EP_INPUT | CDC2_INT_IN_EP), // bEndpointAddress
+ EP_INT, // bmAttributes
+ EP7_MAX_PKT_SIZE, 0x00, // wMaxPacketSize
+ 10, // bInterval
+
+ // I/F descriptor
+ LEN_INTERFACE, // bLength
+ DESC_INTERFACE, // bDescriptorType
+ 0x04, // bInterfaceNumber
+ 0x00, // bAlternateSetting
+ 0x02, // bNumEndpoints
+ 0x0A, // bInterfaceClass
+ 0x00, // bInterfaceSubClass
+ 0x00, // bInterfaceProtocol
+ 0x00, // iInterface
+
+ // ENDPOINT descriptor
+ LEN_ENDPOINT, // bLength
+ DESC_ENDPOINT, // bDescriptorType
+ (EP_INPUT | CDC2_BULK_IN_EP), // bEndpointAddress
+ EP_BULK, // bmAttributes
+ EP8_MAX_PKT_SIZE, 0x00, // wMaxPacketSize
+ 0x00, // bInterval
+
+ // ENDPOINT descriptor
+ LEN_ENDPOINT, // bLength
+ DESC_ENDPOINT, // bDescriptorType
+ (EP_OUTPUT | CDC2_BULK_OUT_EP), // bEndpointAddress
+ EP_BULK, // bmAttributes
+ EP9_MAX_PKT_SIZE, 0x00, // wMaxPacketSize
+ 0x00, // bInterval
+#endif
};
diff --git a/src/hid_transfer.c b/src/hid_transfer.c
index ce2e717..db080a3 100644
--- a/src/hid_transfer.c
+++ b/src/hid_transfer.c
@@ -42,6 +42,23 @@ void HID_Init(void)
USBD_SET_EP_BUF_ADDR(EP6, EP6_BUF_BASE);
/* trigger receive OUT data */
USBD_SET_PAYLOAD_LEN(EP6, EP6_MAX_PKT_SIZE);
+
+#if VCOM_COUNT > 1
+ /*****************************************************/
+ /* EP7 ==> Interrupt IN endpoint, address 4 */
+ USBD_CONFIG_EP(EP7, USBD_CFG_EPMODE_IN | CDC2_INT_IN_EP);
+ USBD_SET_EP_BUF_ADDR(EP7, EP7_BUF_BASE);
+
+ /* EP8 ==> Bulk IN endpoint, address 5 */
+ USBD_CONFIG_EP(EP8, USBD_CFG_EPMODE_IN | CDC2_BULK_IN_EP);
+ USBD_SET_EP_BUF_ADDR(EP8, EP8_BUF_BASE);
+
+ /* EP9 ==> Bulk Out endpoint, address 5 */
+ USBD_CONFIG_EP(EP9, USBD_CFG_EPMODE_OUT | CDC2_BULK_OUT_EP);
+ USBD_SET_EP_BUF_ADDR(EP9, EP9_BUF_BASE);
+ /* trigger receive OUT data */
+ USBD_SET_PAYLOAD_LEN(EP9, EP9_MAX_PKT_SIZE);
+#endif
}
@@ -132,7 +149,16 @@ void USBD_IRQHandler(void)
extern uint8_t g_usbd_SetupPacket[];
if(g_usbd_SetupPacket[1] == SET_LINE_CODE)
{
- VCOM_LineCoding();
+ switch(g_usbd_SetupPacket[4]) // Interface number
+ {
+ case 1:
+ VCOM_LineCoding(UART2, &LineCfg, &Vcom);
+ break;
+
+ case 3:
+ VCOM_LineCoding(UART1, &LineCfg2, &Vcom2);
+ break;
+ }
}
}
@@ -167,6 +193,25 @@ void USBD_IRQHandler(void)
USBD_CLR_INT_FLAG(USBD_INTSTS_EP6);
EP6_Handler();
+ }
+
+ if(u32IntSts & USBD_INTSTS_EP7)
+ {
+ USBD_CLR_INT_FLAG(USBD_INTSTS_EP7);
+ }
+
+ if(u32IntSts & USBD_INTSTS_EP8) // Bulk IN
+ {
+ USBD_CLR_INT_FLAG(USBD_INTSTS_EP8);
+
+ EP8_Handler();
+ }
+
+ if(u32IntSts & USBD_INTSTS_EP9) // Bulk OUT
+ {
+ USBD_CLR_INT_FLAG(USBD_INTSTS_EP9);
+
+ EP9_Handler();
}
}
}
@@ -189,7 +234,16 @@ void HID_ClassRequest(void)
break;
case GET_LINE_CODE:
- USBD_PrepareCtrlIn((uint8_t *)&LineCfg, 7);
+ switch(buf[4]) // Interface number
+ {
+ case 1:
+ USBD_PrepareCtrlIn((uint8_t *)&LineCfg, 7);
+ break;
+
+ case 3:
+ USBD_PrepareCtrlIn((uint8_t *)&LineCfg2, 7);
+ break;
+ }
/* Status stage */
USBD_PrepareCtrlOut(0,0);
@@ -225,7 +279,16 @@ void HID_ClassRequest(void)
break;
case SET_LINE_CODE:
- USBD_PrepareCtrlOut((uint8_t *)&LineCfg, 7);
+ switch(buf[4]) // Interface number
+ {
+ case 1:
+ USBD_PrepareCtrlOut((uint8_t *)&LineCfg, 7);
+ break;
+
+ case 3:
+ USBD_PrepareCtrlOut((uint8_t *)&LineCfg2, 7);
+ break;
+ }
/* Status stage */
USBD_SET_DATA1(EP0);
@@ -233,7 +296,16 @@ void HID_ClassRequest(void)
break;
case SET_CONTROL_LINE:
- Vcom.hw_flow = (buf[3] << 8) | buf[2];
+ switch(buf[4]) // Interface number
+ {
+ case 1:
+ Vcom.hw_flow = (buf[3] << 8) | buf[2];
+ break;
+
+ case 3:
+ Vcom2.hw_flow = (buf[3] << 8) | buf[2];
+ break;
+ }
/* Status stage */
USBD_SET_DATA1(EP0);
diff --git a/src/hid_transfer.h b/src/hid_transfer.h
index 6e65543..f4bd82f 100644
--- a/src/hid_transfer.h
+++ b/src/hid_transfer.h
@@ -2,11 +2,14 @@
#define __HID_TRANSFER_H__
+#define VCOM_COUNT 1 // 1 or 2
+
+
#define USBD_VID 0x0416
#ifdef DAP_FW_V1
-#define USBD_PID 0x5021
+#define USBD_PID (0x5021 + (VCOM_COUNT - 1))
#else
-#define USBD_PID 0x7687
+#define USBD_PID (0x7687 + (VCOM_COUNT - 1))
#endif
@@ -19,6 +22,9 @@
#define CDC_INT_IN_EP 2
#define CDC_BULK_IN_EP 3
#define CDC_BULK_OUT_EP 3
+#define CDC2_INT_IN_EP 4
+#define CDC2_BULK_IN_EP 5
+#define CDC2_BULK_OUT_EP 5
/* Define EP maximum packet size */
@@ -29,7 +35,9 @@
#define EP4_MAX_PKT_SIZE 8
#define EP5_MAX_PKT_SIZE 64
#define EP6_MAX_PKT_SIZE 64
-
+#define EP7_MAX_PKT_SIZE 8
+#define EP8_MAX_PKT_SIZE 64
+#define EP9_MAX_PKT_SIZE 64
#define SETUP_BUF_BASE 0
#define SETUP_BUF_SIZE 8
@@ -40,6 +48,9 @@
#define EP4_BUF_BASE (EP3_BUF_BASE + EP3_MAX_PKT_SIZE)
#define EP5_BUF_BASE (EP4_BUF_BASE + EP4_MAX_PKT_SIZE)
#define EP6_BUF_BASE (EP5_BUF_BASE + EP5_MAX_PKT_SIZE)
+#define EP7_BUF_BASE (EP6_BUF_BASE + EP6_MAX_PKT_SIZE)
+#define EP8_BUF_BASE (EP7_BUF_BASE + EP7_MAX_PKT_SIZE)
+#define EP9_BUF_BASE (EP8_BUF_BASE + EP8_MAX_PKT_SIZE)
/* HID Class Specific Request */
diff --git a/src/vcom_serial.c b/src/vcom_serial.c
index eaa5bd9..5f97a96 100644
--- a/src/vcom_serial.c
+++ b/src/vcom_serial.c
@@ -20,10 +20,28 @@ void VCOM_Init(void)
UART_ENABLE_INT(UART2, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
NVIC_EnableIRQ(UART2_IRQn);
+
+#if VCOM_COUNT > 1
+ GPIO_SetPullCtl(PB, BIT2, GPIO_PUSEL_PULL_UP);
+ SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB2MFP_Msk | SYS_GPB_MFPL_PB3MFP_Msk);
+ SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB2MFP_UART1_RXD | SYS_GPB_MFPL_PB3MFP_UART1_TXD);
+
+ CLK_SetModuleClock(UART1_MODULE, CLK_CLKSEL1_UART1SEL_HXT, CLK_CLKDIV0_UART1(1));
+ CLK_EnableModuleClock(UART1_MODULE);
+
+ UART_Open(UART1, 115200);
+
+ UART1->FIFO = (UART1->FIFO & (~UART_FIFO_RFITL_Msk)) | UART_FIFO_RFITL_8BYTES;
+ UART_SetTimeoutCnt(UART1, 50);
+
+ UART_ENABLE_INT(UART1, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
+
+ NVIC_EnableIRQ(UART1_IRQn);
+#endif
}
-volatile VCOM Vcom;
+volatile VCOM Vcom, Vcom2;
void EP5_Handler(void) // Bulk IN
{
@@ -38,14 +56,28 @@ void EP6_Handler(void) // Bulk OUT
Vcom.out_ready = 1;
}
+void EP8_Handler(void) // Bulk IN
+{
+ Vcom2.in_bytes = 0;
+}
+
+void EP9_Handler(void) // Bulk OUT
+{
+ Vcom2.out_bytes = USBD_GET_PAYLOAD_LEN(EP9);
+ Vcom2.out_ptr = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP9));
+
+ Vcom2.out_ready = 1;
+}
+
VCOM_LINE_CODING LineCfg = {115200, 0, 0, 8}; // Baud rate, stop bits, parity bits, data bits
+VCOM_LINE_CODING LineCfg2 = {115200, 0, 0, 8};
-void VCOM_LineCoding(void)
+void VCOM_LineCoding(UART_T * UARTx, VCOM_LINE_CODING * LineCfgx, volatile VCOM * Vcomx)
{
- uint32_t data_len, parity, stop_len;
+ uint32_t data_len, parity, stop_len;
- switch(LineCfg.u8DataBits)
+ switch(LineCfgx->u8DataBits)
{
case 5: data_len = UART_WORD_LEN_5; break;
case 6: data_len = UART_WORD_LEN_6; break;
@@ -54,7 +86,7 @@ void VCOM_LineCoding(void)
default: data_len = UART_WORD_LEN_8; break;
}
- switch(LineCfg.u8ParityType)
+ switch(LineCfgx->u8ParityType)
{
case 0: parity = UART_PARITY_NONE; break;
case 1: parity = UART_PARITY_ODD; break;
@@ -64,7 +96,7 @@ void VCOM_LineCoding(void)
default: parity = UART_PARITY_NONE; break;
}
- switch(LineCfg.u8CharFormat)
+ switch(LineCfgx->u8CharFormat)
{
case 0: stop_len = UART_STOP_BIT_1; break;
case 1: stop_len = UART_STOP_BIT_1_5; break;
@@ -72,53 +104,53 @@ void VCOM_LineCoding(void)
default: stop_len = UART_STOP_BIT_1; break;
}
- NVIC_DisableIRQ(UART2_IRQn);
+ __disable_irq();
// Reset software FIFO
- Vcom.rx_bytes = 0;
- Vcom.rx_head = 0;
- Vcom.rx_tail = 0;
+ Vcomx->rx_bytes = 0;
+ Vcomx->rx_head = 0;
+ Vcomx->rx_tail = 0;
- Vcom.tx_bytes = 0;
- Vcom.tx_head = 0;
- Vcom.tx_tail = 0;
+ Vcomx->tx_bytes = 0;
+ Vcomx->tx_head = 0;
+ Vcomx->tx_tail = 0;
// Reset hardware FIFO
- UART2->FIFO |= (UART_FIFO_RXRST_Msk | UART_FIFO_TXRST_Msk);
+ UARTx->FIFO |= (UART_FIFO_RXRST_Msk | UART_FIFO_TXRST_Msk);
- UART_SetLineConfig(UART2, LineCfg.u32DTERate, data_len, parity, stop_len);
+ UART_SetLineConfig(UARTx, LineCfgx->u32DTERate, data_len, parity, stop_len);
- NVIC_EnableIRQ(UART2_IRQn);
+ __enable_irq();
}
-void UART2_IRQHandler(void)
+void UARTX_IRQHandler(UART_T * UARTx, volatile VCOM * vcomx)
{
uint8_t chr;
int32_t size;
- if((UART2->INTSTS & UART_INTSTS_RDAIF_Msk) || (UART2->INTSTS & UART_INTSTS_RXTOIF_Msk))
+ if((UARTx->INTSTS & UART_INTSTS_RDAIF_Msk) || (UARTx->INTSTS & UART_INTSTS_RXTOIF_Msk))
{
- while((UART2->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0)
+ while((UARTx->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) == 0)
{
- chr = UART2->DAT;
+ chr = UARTx->DAT;
- if(Vcom.rx_bytes < RX_BUFF_SIZE) // Check if buffer full
+ if(vcomx->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++;
+ vcomx->rx_buff[vcomx->rx_tail++] = chr;
+ if(vcomx->rx_tail >= RX_BUFF_SIZE)
+ vcomx->rx_tail = 0;
+ vcomx->rx_bytes++;
}
}
}
- if(UART2->INTSTS & UART_INTSTS_THREIF_Msk)
+ if(UARTx->INTSTS & UART_INTSTS_THREIF_Msk)
{
- if(Vcom.tx_bytes)
+ if(vcomx->tx_bytes)
{
/* Fill the Tx FIFO */
- size = Vcom.tx_bytes;
+ size = vcomx->tx_bytes;
if(size >= TX_FIFO_SIZE)
{
size = TX_FIFO_SIZE;
@@ -126,104 +158,119 @@ void UART2_IRQHandler(void)
while(size)
{
- UART2->DAT = Vcom.tx_buff[Vcom.tx_head++];
- if(Vcom.tx_head >= TX_BUFF_SIZE)
- Vcom.tx_head = 0;
- Vcom.tx_bytes--;
+ UARTx->DAT = vcomx->tx_buff[vcomx->tx_head++];
+ if(vcomx->tx_head >= TX_BUFF_SIZE)
+ vcomx->tx_head = 0;
+ vcomx->tx_bytes--;
size--;
}
}
else
{
/* No more data, just stop Tx (Stop work) */
- UART2->INTEN &= ~UART_INTEN_THREIEN_Msk;
+ UARTx->INTEN &= ~UART_INTEN_THREIEN_Msk;
}
}
}
-extern uint32_t SysTick_Count;
-static uint32_t SysTick_Count_Save;
+void UART2_IRQHandler(void)
+{
+ UARTX_IRQHandler(UART2, &Vcom);
+}
-void VCOM_TransferData(void)
+
+void UART1_IRQHandler(void)
+{
+ UARTX_IRQHandler(UART1, &Vcom2);
+}
+
+
+
+void VCOMX_TransferData(volatile VCOM * vcomx, UART_T * UARTx, uint32_t INEP, uint32_t INEP_PKT_SIZE, uint32_t OUTEP, uint32_t OUTEP_PKT_SIZE)
{
int32_t i, len;
/* Check whether USB is ready for next packet or not */
- if(Vcom.in_bytes == 0)
+ if(vcomx->in_bytes == 0)
{
/* Check whether we have new COM Rx data to send to USB or not */
- if(Vcom.rx_bytes && ((Vcom.rx_bytes >= EP5_MAX_PKT_SIZE) || (SysTick_Count_Save != SysTick_Count)))
+ if(vcomx->rx_bytes)
{
- SysTick_Count_Save = SysTick_Count;
-
- len = Vcom.rx_bytes;
- if(len > EP5_MAX_PKT_SIZE)
- len = EP5_MAX_PKT_SIZE;
+ len = vcomx->rx_bytes;
+ if(len > INEP_PKT_SIZE)
+ len = INEP_PKT_SIZE;
for(i = 0; i < len; i++)
{
- Vcom.in_buff[i] = Vcom.rx_buff[Vcom.rx_head++];
- if(Vcom.rx_head >= RX_BUFF_SIZE)
- Vcom.rx_head = 0;
+ vcomx->in_buff[i] = vcomx->rx_buff[vcomx->rx_head++];
+ if(vcomx->rx_head >= RX_BUFF_SIZE)
+ vcomx->rx_head = 0;
}
__disable_irq();
- Vcom.rx_bytes -= len;
+ vcomx->rx_bytes -= len;
__enable_irq();
- Vcom.in_bytes = len;
- USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP5)), (uint8_t *)Vcom.in_buff, len);
- USBD_SET_PAYLOAD_LEN(EP5, len);
+ vcomx->in_bytes = len;
+ USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(INEP)), (uint8_t *)vcomx->in_buff, len);
+ USBD_SET_PAYLOAD_LEN(INEP, len);
}
else
{
- /* Prepare a zero packet if previous packet size is EP5_MAX_PKT_SIZE and
+ /* Prepare a zero packet if previous packet size is EP2_MAX_PKT_SIZE and
no more data to send at this moment to note Host the transfer has been done */
- len = USBD_GET_PAYLOAD_LEN(EP5);
- if(len == EP5_MAX_PKT_SIZE)
- USBD_SET_PAYLOAD_LEN(EP5, 0);
+ len = USBD_GET_PAYLOAD_LEN(INEP);
+ if(len == INEP_PKT_SIZE)
+ USBD_SET_PAYLOAD_LEN(INEP, 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))
+ if(vcomx->out_ready && (vcomx->out_bytes <= TX_BUFF_SIZE - vcomx->tx_bytes))
{
- for(i = 0; i < Vcom.out_bytes; i++)
+ for(i = 0; i < vcomx->out_bytes; i++)
{
- Vcom.tx_buff[Vcom.tx_tail++] = Vcom.out_ptr[i];
- if(Vcom.tx_tail >= TX_BUFF_SIZE)
- Vcom.tx_tail = 0;
+ vcomx->tx_buff[vcomx->tx_tail++] = vcomx->out_ptr[i];
+ if(vcomx->tx_tail >= TX_BUFF_SIZE)
+ vcomx->tx_tail = 0;
}
__disable_irq();
- Vcom.tx_bytes += Vcom.out_bytes;
+ vcomx->tx_bytes += vcomx->out_bytes;
__enable_irq();
- Vcom.out_bytes = 0;
- Vcom.out_ready = 0;
+ vcomx->out_bytes = 0;
+ vcomx->out_ready = 0; /* Clear bulk out ready flag */
/* Ready to get next BULK out */
- USBD_SET_PAYLOAD_LEN(EP6, EP6_MAX_PKT_SIZE);
+ USBD_SET_PAYLOAD_LEN(OUTEP, OUTEP_PKT_SIZE);
}
/* Process the software Tx FIFO */
- if(Vcom.tx_bytes)
+ if(vcomx->tx_bytes)
{
/* Check if Tx is working */
- if((UART2->INTEN & UART_INTEN_THREIEN_Msk) == 0)
+ if((UARTx->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;
+ UARTx->DAT = vcomx->tx_buff[vcomx->tx_head++];
+ if(vcomx->tx_head >= TX_BUFF_SIZE)
+ vcomx->tx_head = 0;
__disable_irq();
- Vcom.tx_bytes--;
+ vcomx->tx_bytes--;
__enable_irq();
/* Enable Tx Empty Interrupt. (Trigger first one) */
- UART2->INTEN |= UART_INTEN_THREIEN_Msk;
+ UARTx->INTEN |= UART_INTEN_THREIEN_Msk;
}
}
}
+
+
+void VCOM_TransferData(void)
+{
+ VCOMX_TransferData(&Vcom, UART2, EP5, EP5_MAX_PKT_SIZE, EP6, EP6_MAX_PKT_SIZE);
+ VCOMX_TransferData(&Vcom2, UART1, EP8, EP8_MAX_PKT_SIZE, EP9, EP9_MAX_PKT_SIZE);
+}
diff --git a/src/vcom_serial.h b/src/vcom_serial.h
index 9f752c1..a8e3bc3 100644
--- a/src/vcom_serial.h
+++ b/src/vcom_serial.h
@@ -16,7 +16,7 @@ typedef struct __attribute__((packed)) {
uint8_t u8DataBits; // data bits: 5, 6, 7, 8, 16
} VCOM_LINE_CODING;
-extern VCOM_LINE_CODING LineCfg;
+extern VCOM_LINE_CODING LineCfg, LineCfg2;
@@ -43,7 +43,7 @@ typedef struct {
uint16_t out_ready;
} VCOM;
-extern volatile VCOM Vcom;
+extern volatile VCOM Vcom, Vcom2;
@@ -51,8 +51,10 @@ void VCOM_Init(void);
void EP5_Handler(void);
void EP6_Handler(void);
+void EP8_Handler(void);
+void EP9_Handler(void);
-void VCOM_LineCoding(void);
+void VCOM_LineCoding(UART_T * UARTx, VCOM_LINE_CODING * LineCfgx, volatile VCOM * Vcomx);
void VCOM_TransferData(void);