mirror of
https://github.com/XIVN1987/DAPLink.git
synced 2026-09-26 22:16:11 +00:00
add dual VCOM support
This commit is contained in:
+2
-2
@@ -120,7 +120,7 @@
|
|||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
<Key>DLGUARM</Key>
|
<Key>DLGUARM</Key>
|
||||||
<Name>?}w鳻??}w鳻?</Name>
|
<Name></Name>
|
||||||
</SetRegEntry>
|
</SetRegEntry>
|
||||||
<SetRegEntry>
|
<SetRegEntry>
|
||||||
<Number>0</Number>
|
<Number>0</Number>
|
||||||
@@ -269,7 +269,7 @@
|
|||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<GroupName>DAP</GroupName>
|
<GroupName>DAP</GroupName>
|
||||||
<tvExp>1</tvExp>
|
<tvExp>0</tvExp>
|
||||||
<tvExpOptDlg>0</tvExpOptDlg>
|
<tvExpOptDlg>0</tvExpOptDlg>
|
||||||
<cbSel>0</cbSel>
|
<cbSel>0</cbSel>
|
||||||
<RteFlg>0</RteFlg>
|
<RteFlg>0</RteFlg>
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
## DAPLink
|
## 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:
|
In the C/C++ page of Keil Option Window:
|
||||||
* Define `DAP_FW_V1`: generate CMSIS-DAP V1 firmware, using HID transport protocol.
|
* 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.
|
* Do not define `DAP_FW_V1`: Generate CMSIS-DAP V2 firmware, using WINUSB transfer protocol.
|
||||||
|
|
||||||
### Pin map
|
### Pin map
|
||||||
| FUNC | Pin |
|
| FUNC | Pin |
|
||||||
| :---- | :---- |
|
| :---- | :---- |
|
||||||
| SWD_CLK | PA.1 |
|
| SWD_CLK | PA.1 |
|
||||||
| SWD_DIO | PA.0 |
|
| SWD_DIO | PA.0 |
|
||||||
| SWD_RST | PF.4 |
|
| SWD_RST | PF.4 |
|
||||||
| CDC_TXD | PB.1 |
|
| CDC_TXD | PB.1 |
|
||||||
| CDC_RXD | PB.0 |
|
| CDC_RXD | PB.0 |
|
||||||
| LED_SWD | PA.2 |
|
| LED_SWD | PA.2 |
|
||||||
| LED_TXD | PC.1 |
|
| LED_TXD | PC.1 |
|
||||||
| LED_RXD | PC.0 |
|
| LED_RXD | PC.0 |
|
||||||
|
|
||||||
|
### Optional CDC2
|
||||||
|
| FUNC | Pin |
|
||||||
|
| :---- | :---- |
|
||||||
|
| CDC2_TXD | PB.3 |
|
||||||
|
| CDC2_RXD | PB.2 |
|
||||||
|
|||||||
Binary file not shown.
+87
-2
@@ -53,9 +53,9 @@ uint8_t gu8ConfigDescriptor[] =
|
|||||||
#else
|
#else
|
||||||
#define TOTAL_LEN_0 (LEN_CONFIG + (LEN_INTERFACE + LEN_ENDPOINT + LEN_ENDPOINT))
|
#define TOTAL_LEN_0 (LEN_CONFIG + (LEN_INTERFACE + LEN_ENDPOINT + LEN_ENDPOINT))
|
||||||
#endif
|
#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
|
TOTAL_LEN & 0xFF, TOTAL_LEN >> 8, // wTotalLength
|
||||||
0x03, // bNumInterfaces
|
(1 + 2*VCOM_COUNT), // bNumInterfaces
|
||||||
0x01, // bConfigurationValue
|
0x01, // bConfigurationValue
|
||||||
0x00, // iConfiguration
|
0x00, // iConfiguration
|
||||||
0x00, // bmAttributes, D6: self power D5: remote wake-up
|
0x00, // bmAttributes, D6: self power D5: remote wake-up
|
||||||
@@ -194,6 +194,91 @@ uint8_t gu8ConfigDescriptor[] =
|
|||||||
EP_BULK, // bmAttributes
|
EP_BULK, // bmAttributes
|
||||||
EP6_MAX_PKT_SIZE, 0x00, // wMaxPacketSize
|
EP6_MAX_PKT_SIZE, 0x00, // wMaxPacketSize
|
||||||
0x00, // bInterval
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+76
-4
@@ -42,6 +42,23 @@ void HID_Init(void)
|
|||||||
USBD_SET_EP_BUF_ADDR(EP6, EP6_BUF_BASE);
|
USBD_SET_EP_BUF_ADDR(EP6, EP6_BUF_BASE);
|
||||||
/* trigger receive OUT data */
|
/* trigger receive OUT data */
|
||||||
USBD_SET_PAYLOAD_LEN(EP6, EP6_MAX_PKT_SIZE);
|
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[];
|
extern uint8_t g_usbd_SetupPacket[];
|
||||||
if(g_usbd_SetupPacket[1] == SET_LINE_CODE)
|
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);
|
USBD_CLR_INT_FLAG(USBD_INTSTS_EP6);
|
||||||
|
|
||||||
EP6_Handler();
|
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;
|
break;
|
||||||
|
|
||||||
case GET_LINE_CODE:
|
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 */
|
/* Status stage */
|
||||||
USBD_PrepareCtrlOut(0,0);
|
USBD_PrepareCtrlOut(0,0);
|
||||||
@@ -225,7 +279,16 @@ void HID_ClassRequest(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SET_LINE_CODE:
|
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 */
|
/* Status stage */
|
||||||
USBD_SET_DATA1(EP0);
|
USBD_SET_DATA1(EP0);
|
||||||
@@ -233,7 +296,16 @@ void HID_ClassRequest(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SET_CONTROL_LINE:
|
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 */
|
/* Status stage */
|
||||||
USBD_SET_DATA1(EP0);
|
USBD_SET_DATA1(EP0);
|
||||||
|
|||||||
+14
-3
@@ -2,11 +2,14 @@
|
|||||||
#define __HID_TRANSFER_H__
|
#define __HID_TRANSFER_H__
|
||||||
|
|
||||||
|
|
||||||
|
#define VCOM_COUNT 1 // 1 or 2
|
||||||
|
|
||||||
|
|
||||||
#define USBD_VID 0x0416
|
#define USBD_VID 0x0416
|
||||||
#ifdef DAP_FW_V1
|
#ifdef DAP_FW_V1
|
||||||
#define USBD_PID 0x5021
|
#define USBD_PID (0x5021 + (VCOM_COUNT - 1))
|
||||||
#else
|
#else
|
||||||
#define USBD_PID 0x7687
|
#define USBD_PID (0x7687 + (VCOM_COUNT - 1))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -19,6 +22,9 @@
|
|||||||
#define CDC_INT_IN_EP 2
|
#define CDC_INT_IN_EP 2
|
||||||
#define CDC_BULK_IN_EP 3
|
#define CDC_BULK_IN_EP 3
|
||||||
#define CDC_BULK_OUT_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 */
|
/* Define EP maximum packet size */
|
||||||
@@ -29,7 +35,9 @@
|
|||||||
#define EP4_MAX_PKT_SIZE 8
|
#define EP4_MAX_PKT_SIZE 8
|
||||||
#define EP5_MAX_PKT_SIZE 64
|
#define EP5_MAX_PKT_SIZE 64
|
||||||
#define EP6_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_BASE 0
|
||||||
#define SETUP_BUF_SIZE 8
|
#define SETUP_BUF_SIZE 8
|
||||||
@@ -40,6 +48,9 @@
|
|||||||
#define EP4_BUF_BASE (EP3_BUF_BASE + EP3_MAX_PKT_SIZE)
|
#define EP4_BUF_BASE (EP3_BUF_BASE + EP3_MAX_PKT_SIZE)
|
||||||
#define EP5_BUF_BASE (EP4_BUF_BASE + EP4_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 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 */
|
/* HID Class Specific Request */
|
||||||
|
|||||||
+117
-70
@@ -20,10 +20,28 @@ void VCOM_Init(void)
|
|||||||
UART_ENABLE_INT(UART2, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
|
UART_ENABLE_INT(UART2, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
|
||||||
|
|
||||||
NVIC_EnableIRQ(UART2_IRQn);
|
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
|
void EP5_Handler(void) // Bulk IN
|
||||||
{
|
{
|
||||||
@@ -38,14 +56,28 @@ void EP6_Handler(void) // Bulk OUT
|
|||||||
Vcom.out_ready = 1;
|
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 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 5: data_len = UART_WORD_LEN_5; break;
|
||||||
case 6: data_len = UART_WORD_LEN_6; 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;
|
default: data_len = UART_WORD_LEN_8; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(LineCfg.u8ParityType)
|
switch(LineCfgx->u8ParityType)
|
||||||
{
|
{
|
||||||
case 0: parity = UART_PARITY_NONE; break;
|
case 0: parity = UART_PARITY_NONE; break;
|
||||||
case 1: parity = UART_PARITY_ODD; break;
|
case 1: parity = UART_PARITY_ODD; break;
|
||||||
@@ -64,7 +96,7 @@ void VCOM_LineCoding(void)
|
|||||||
default: parity = UART_PARITY_NONE; break;
|
default: parity = UART_PARITY_NONE; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(LineCfg.u8CharFormat)
|
switch(LineCfgx->u8CharFormat)
|
||||||
{
|
{
|
||||||
case 0: stop_len = UART_STOP_BIT_1; break;
|
case 0: stop_len = UART_STOP_BIT_1; break;
|
||||||
case 1: stop_len = UART_STOP_BIT_1_5; 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;
|
default: stop_len = UART_STOP_BIT_1; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NVIC_DisableIRQ(UART2_IRQn);
|
__disable_irq();
|
||||||
|
|
||||||
// Reset software FIFO
|
// Reset software FIFO
|
||||||
Vcom.rx_bytes = 0;
|
Vcomx->rx_bytes = 0;
|
||||||
Vcom.rx_head = 0;
|
Vcomx->rx_head = 0;
|
||||||
Vcom.rx_tail = 0;
|
Vcomx->rx_tail = 0;
|
||||||
|
|
||||||
Vcom.tx_bytes = 0;
|
Vcomx->tx_bytes = 0;
|
||||||
Vcom.tx_head = 0;
|
Vcomx->tx_head = 0;
|
||||||
Vcom.tx_tail = 0;
|
Vcomx->tx_tail = 0;
|
||||||
|
|
||||||
// Reset hardware FIFO
|
// 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;
|
uint8_t chr;
|
||||||
int32_t size;
|
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;
|
vcomx->rx_buff[vcomx->rx_tail++] = chr;
|
||||||
if(Vcom.rx_tail >= RX_BUFF_SIZE)
|
if(vcomx->rx_tail >= RX_BUFF_SIZE)
|
||||||
Vcom.rx_tail = 0;
|
vcomx->rx_tail = 0;
|
||||||
Vcom.rx_bytes++;
|
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 */
|
/* Fill the Tx FIFO */
|
||||||
size = Vcom.tx_bytes;
|
size = vcomx->tx_bytes;
|
||||||
if(size >= TX_FIFO_SIZE)
|
if(size >= TX_FIFO_SIZE)
|
||||||
{
|
{
|
||||||
size = TX_FIFO_SIZE;
|
size = TX_FIFO_SIZE;
|
||||||
@@ -126,104 +158,119 @@ void UART2_IRQHandler(void)
|
|||||||
|
|
||||||
while(size)
|
while(size)
|
||||||
{
|
{
|
||||||
UART2->DAT = Vcom.tx_buff[Vcom.tx_head++];
|
UARTx->DAT = vcomx->tx_buff[vcomx->tx_head++];
|
||||||
if(Vcom.tx_head >= TX_BUFF_SIZE)
|
if(vcomx->tx_head >= TX_BUFF_SIZE)
|
||||||
Vcom.tx_head = 0;
|
vcomx->tx_head = 0;
|
||||||
Vcom.tx_bytes--;
|
vcomx->tx_bytes--;
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No more data, just stop Tx (Stop work) */
|
/* 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;
|
void UART2_IRQHandler(void)
|
||||||
static uint32_t SysTick_Count_Save;
|
{
|
||||||
|
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;
|
int32_t i, len;
|
||||||
|
|
||||||
/* Check whether USB is ready for next packet or not */
|
/* 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 */
|
/* 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 = vcomx->rx_bytes;
|
||||||
|
if(len > INEP_PKT_SIZE)
|
||||||
len = Vcom.rx_bytes;
|
len = INEP_PKT_SIZE;
|
||||||
if(len > EP5_MAX_PKT_SIZE)
|
|
||||||
len = EP5_MAX_PKT_SIZE;
|
|
||||||
|
|
||||||
for(i = 0; i < len; i++)
|
for(i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
Vcom.in_buff[i] = Vcom.rx_buff[Vcom.rx_head++];
|
vcomx->in_buff[i] = vcomx->rx_buff[vcomx->rx_head++];
|
||||||
if(Vcom.rx_head >= RX_BUFF_SIZE)
|
if(vcomx->rx_head >= RX_BUFF_SIZE)
|
||||||
Vcom.rx_head = 0;
|
vcomx->rx_head = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
Vcom.rx_bytes -= len;
|
vcomx->rx_bytes -= len;
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
|
|
||||||
Vcom.in_bytes = len;
|
vcomx->in_bytes = len;
|
||||||
USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP5)), (uint8_t *)Vcom.in_buff, len);
|
USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(INEP)), (uint8_t *)vcomx->in_buff, len);
|
||||||
USBD_SET_PAYLOAD_LEN(EP5, len);
|
USBD_SET_PAYLOAD_LEN(INEP, len);
|
||||||
}
|
}
|
||||||
else
|
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 */
|
no more data to send at this moment to note Host the transfer has been done */
|
||||||
len = USBD_GET_PAYLOAD_LEN(EP5);
|
len = USBD_GET_PAYLOAD_LEN(INEP);
|
||||||
if(len == EP5_MAX_PKT_SIZE)
|
if(len == INEP_PKT_SIZE)
|
||||||
USBD_SET_PAYLOAD_LEN(EP5, 0);
|
USBD_SET_PAYLOAD_LEN(INEP, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process the Bulk out data when bulk out data is ready. */
|
/* 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];
|
vcomx->tx_buff[vcomx->tx_tail++] = vcomx->out_ptr[i];
|
||||||
if(Vcom.tx_tail >= TX_BUFF_SIZE)
|
if(vcomx->tx_tail >= TX_BUFF_SIZE)
|
||||||
Vcom.tx_tail = 0;
|
vcomx->tx_tail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
Vcom.tx_bytes += Vcom.out_bytes;
|
vcomx->tx_bytes += vcomx->out_bytes;
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
|
|
||||||
Vcom.out_bytes = 0;
|
vcomx->out_bytes = 0;
|
||||||
Vcom.out_ready = 0;
|
vcomx->out_ready = 0; /* Clear bulk out ready flag */
|
||||||
|
|
||||||
/* Ready to get next BULK out */
|
/* 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 */
|
/* Process the software Tx FIFO */
|
||||||
if(Vcom.tx_bytes)
|
if(vcomx->tx_bytes)
|
||||||
{
|
{
|
||||||
/* Check if Tx is working */
|
/* 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 */
|
/* Send one bytes out */
|
||||||
UART2->DAT = Vcom.tx_buff[Vcom.tx_head++];
|
UARTx->DAT = vcomx->tx_buff[vcomx->tx_head++];
|
||||||
if(Vcom.tx_head >= TX_BUFF_SIZE)
|
if(vcomx->tx_head >= TX_BUFF_SIZE)
|
||||||
Vcom.tx_head = 0;
|
vcomx->tx_head = 0;
|
||||||
|
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
Vcom.tx_bytes--;
|
vcomx->tx_bytes--;
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
|
|
||||||
/* Enable Tx Empty Interrupt. (Trigger first one) */
|
/* 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);
|
||||||
|
}
|
||||||
|
|||||||
+5
-3
@@ -16,7 +16,7 @@ typedef struct __attribute__((packed)) {
|
|||||||
uint8_t u8DataBits; // data bits: 5, 6, 7, 8, 16
|
uint8_t u8DataBits; // data bits: 5, 6, 7, 8, 16
|
||||||
} VCOM_LINE_CODING;
|
} VCOM_LINE_CODING;
|
||||||
|
|
||||||
extern VCOM_LINE_CODING LineCfg;
|
extern VCOM_LINE_CODING LineCfg, LineCfg2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ typedef struct {
|
|||||||
uint16_t out_ready;
|
uint16_t out_ready;
|
||||||
} VCOM;
|
} VCOM;
|
||||||
|
|
||||||
extern volatile VCOM Vcom;
|
extern volatile VCOM Vcom, Vcom2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -51,8 +51,10 @@ void VCOM_Init(void);
|
|||||||
|
|
||||||
void EP5_Handler(void);
|
void EP5_Handler(void);
|
||||||
void EP6_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);
|
void VCOM_TransferData(void);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user