EC_M032_USBD_VCOM_And_HID_MMKey_V1.00.zip
(1.63 MB, 下载次数: 3)
USB接口模拟虚拟串口与键盘。
- /******************************************************************************
- * [url=home.php?mod=space&uid=288409]@file[/url] main.c
- * [url=home.php?mod=space&uid=895143]@version[/url] V1.00
- * $Revision: 12 $
- * $Date: 18/07/18 3:38p $
- * [url=home.php?mod=space&uid=247401]@brief[/url] Demonstrate how to implement a composite device.(VCOM and HID MMkey)
- *
- * @note
- * SPDX-License-Identifier: Apache-2.0
- * Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
- *****************************************************************************/
- #include <stdio.h>
- #include "NuMicro.h"
- #include "VCOM_and_HID_keyboard.h"
- #define CRYSTAL_LESS 1 /* CRYSTAL_LESS must be 1 if USB clock source is HIRC */
- #define TRIM_INIT (SYS_BASE+0x118)
- int IsDebugFifoEmpty(void);
- /*--------------------------------------------------------------------------*/
- STR_VCOM_LINE_CODING gLineCoding = {115200, 0, 0, 8}; /* Baud rate : 115200 */
- /* Stop bit */
- /* parity */
- /* data bits */
- uint16_t gCtrlSignal = 0; /* BIT0: DTR(Data Terminal Ready) , BIT1: RTS(Request To Send) */
- extern uint8_t volatile g_u8Suspend;
- /*--------------------------------------------------------------------------*/
- #define RX_BUFSIZE 512 /* RX buffer size */
- #define TX_BUFSIZE 512 /* RX buffer size */
- #define TX_FIFO_SIZE 16 /* TX Hardware FIFO size */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Global variables */
- /*---------------------------------------------------------------------------------------------------------*/
- /* UART0 */
- volatile uint8_t comRbuf[RX_BUFSIZE];
- volatile uint16_t comRbytes = 0;
- volatile uint16_t comRhead = 0;
- volatile uint16_t comRtail = 0;
- volatile uint8_t comTbuf[TX_BUFSIZE];
- volatile uint16_t comTbytes = 0;
- volatile uint16_t comThead = 0;
- volatile uint16_t comTtail = 0;
- uint8_t gRxBuf[64] = {0};
- uint8_t *gpu8RxBuf = 0;
- uint32_t gu32RxSize = 0;
- uint32_t gu32TxSize = 0;
- volatile int8_t gi8BulkOutReady = 0;
- void SYS_Init(void)
- {
- /* Unlock protected registers */
- SYS_UnlockReg();
- /* Enable HIRC clock */
- CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
- /* Waiting for HIRC clock ready */
- CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
- /* Switch HCLK clock source to HIRC and HCLK source divide 1 */
- CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));
- /* Switch UART0 clock source to HIRC */
- CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
- /* Enable UART0 clock */
- CLK_EnableModuleClock(UART0_MODULE);
- /* Switch USB clock source to HIRC & USB Clock = HIRC / 1 */
- CLK_SetModuleClock(USBD_MODULE, CLK_CLKSEL0_USBDSEL_HIRC, CLK_CLKDIV0_USB(1));
- /* Enable USB clock */
- CLK_EnableModuleClock(USBD_MODULE);
- /* Update System Core Clock */
- SystemCoreClockUpdate();
- /* Set PB multi-function pins for UART0 RXD=PB.12 and TXD=PB.13 */
- SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk))
- |(SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
- UART_ENABLE_INT(UART0, (UART_INTEN_RDAIEN_Msk | UART_INTEN_THREIEN_Msk | UART_INTEN_RXTOIEN_Msk));
- /* Lock protected registers */
- SYS_LockReg();
- }
- void PowerDown()
- {
- /* Unlock protected registers */
- SYS_UnlockReg();
- printf("Enter power down ...\n");
- while(!IsDebugFifoEmpty());
- /* Wakeup Enable */
- USBD_ENABLE_INT(USBD_INTEN_WKEN_Msk);
- CLK_PowerDown();
- /* Clear PWR_DOWN_EN if it is not clear by itself */
- if(CLK->PWRCTL & CLK_PWRCTL_PDEN_Msk)
- CLK->PWRCTL ^= CLK_PWRCTL_PDEN_Msk;
- printf("device wakeup!\n");
- /* Lock protected registers */
- SYS_LockReg();
- }
- /*---------------------------------------------------------------------------------------------------------*/
- /* UART Callback function */
- /*---------------------------------------------------------------------------------------------------------*/
- void UART02_IRQHandler(void)
- {
- uint8_t bInChar;
- int32_t size;
- uint32_t u32IntStatus;
- u32IntStatus = UART0->INTSTS;
- if((u32IntStatus & UART_INTSTS_RDAIF_Msk) || (u32IntStatus & UART_INTSTS_RXTOIF_Msk))
- {
- /* Receiver FIFO threshold level is reached or Rx time out */
- /* Get all the input characters */
- while (UART_GET_RX_EMPTY(UART0) == 0)
- {
- /* Get the character from UART Buffer */
- bInChar = UART0->DAT;
- /* Check if buffer full */
- if(comRbytes < RX_BUFSIZE)
- {
- /* Enqueue the character */
- comRbuf[comRtail++] = bInChar;
- if(comRtail >= RX_BUFSIZE)
- comRtail = 0;
- comRbytes++;
- }
- else
- {
- /* FIFO over run */
- }
- }
- }
- if(u32IntStatus & UART_INTSTS_THREIF_Msk)
- {
- if(comTbytes && (UART0->INTEN & UART_INTEN_THREIEN_Msk))
- {
- /* Fill the Tx FIFO */
- size = comTbytes;
- if(size >= TX_FIFO_SIZE)
- {
- size = TX_FIFO_SIZE;
- }
- while(size)
- {
- bInChar = comTbuf[comThead++];
- UART0->DAT = bInChar;
- if(comThead >= TX_BUFSIZE)
- comThead = 0;
- comTbytes--;
- size--;
- }
- }
- else
- {
- /* No more data, just stop Tx (Stop work) */
- UART_DISABLE_INT(UART0, UART_INTEN_THREIEN_Msk);
- }
- }
- }
- void VCOM_TransferData(void)
- {
- int32_t i, i32Len;
- /* Check whether USB is ready for next packet or not*/
- if(gu32TxSize == 0)
- {
- /* Check whether we have new COM Rx data to send to USB or not */
- if(comRbytes)
- {
- i32Len = comRbytes;
- if(i32Len > EP2_MAX_PKT_SIZE)
- i32Len = EP2_MAX_PKT_SIZE;
- for(i = 0; i < i32Len; i++)
- {
- gRxBuf[i] = comRbuf[comRhead++];
- if(comRhead >= RX_BUFSIZE)
- comRhead = 0;
- }
- __set_PRIMASK(1);
- comRbytes -= i32Len;
- __set_PRIMASK(0);
- gu32TxSize = i32Len;
- USBD_MemCopy((uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP2)), (uint8_t *)gRxBuf, i32Len);
- USBD_SET_PAYLOAD_LEN(EP2, i32Len);
- }
- else
- {
- /* 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 */
- i32Len = USBD_GET_PAYLOAD_LEN(EP2);
- if(i32Len == EP2_MAX_PKT_SIZE)
- USBD_SET_PAYLOAD_LEN(EP2, 0);
- }
- }
- /* Process the Bulk out data when bulk out data is ready. */
- if(gi8BulkOutReady && (gu32RxSize <= TX_BUFSIZE - comTbytes))
- {
- for(i = 0; i < gu32RxSize; i++)
- {
- comTbuf[comTtail++] = gpu8RxBuf[i];
- if(comTtail >= TX_BUFSIZE)
- comTtail = 0;
- }
- __set_PRIMASK(1);
- comTbytes += gu32RxSize;
- __set_PRIMASK(0);
- gu32RxSize = 0;
- gi8BulkOutReady = 0; /* Clear bulk out ready flag */
- /* Ready to get next BULK out */
- USBD_SET_PAYLOAD_LEN(EP3, EP3_MAX_PKT_SIZE);
- }
- /* Process the software Tx FIFO */
- if(comTbytes)
- {
- /* Check if Tx is working */
- if((UART0->INTEN & UART_INTEN_THREIEN_Msk) == 0)
- {
- /* Send one bytes out */
- UART0->DAT = comTbuf[comThead++];
- if(comThead >= TX_BUFSIZE)
- comThead = 0;
- comTbytes--;
- /* Enable Tx Empty Interrupt. (Trigger first one) */
- UART_ENABLE_INT(UART0, UART_INTEN_THREIEN_Msk);
- }
- }
- }
- /*---------------------------------------------------------------------------------------------------------*/
- /* Main Function */
- /*---------------------------------------------------------------------------------------------------------*/
- int32_t main(void)
- {
- #if CRYSTAL_LESS
- uint32_t u32TrimInit;
- #endif
- /* Unlock protected registers */
- SYS_UnlockReg();
- /* Init System, peripheral clock and multi-function I/O */
- SYS_Init();
- /* Init UART0 to 115200-8n1 for print message */
- UART_Open(UART0, 115200);
- printf("\n\n");
- printf("+--------------------------------------------------------------+\n");
- printf("| NuMicro USB Virtual COM and HID Media Key Sample Code |\n");
- printf("+--------------------------------------------------------------+\n");
- printf("Use PD0 to report key - Brightness + when PD0 = 0\n");
- printf("Use PD1 to report key - Brightness - when PD1 = 0\n");
- printf("Use PD2 to report key - Volume + when PD2 = 0\n");
- printf("Use PD3 to report key - Volume - when PD3 = 0\n");
- printf("Use PD4 to report key - Keyboard Brightness + when PD4 = 0\n");
- printf("Use PD5 to report key - Keyboard Brightness - when PD5 = 0\n");
- printf("Use PD6 to report key - Mute when PD6 = 0\n");
- /* Set PD.0 ~ PD.6 as Quasi-bidirectional mode */
- GPIO_SetMode(PD, (BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT6), GPIO_MODE_QUASI);
- /* Open USB controller */
- USBD_Open(&gsInfo, HID_ClassRequest, NULL);
- /* Endpoint configuration */
- HID_Init();
- /* Start USB device */
- USBD_Start();
- g_u8EP5Ready=1;
- NVIC_EnableIRQ(USBD_IRQn);
- NVIC_EnableIRQ(UART02_IRQn);
- #if CRYSTAL_LESS
- /* Backup default trim */
- u32TrimInit = M32(TRIM_INIT);
- #endif
- /* Clear SOF */
- USBD->INTSTS = USBD_INTSTS_SOFIF_Msk;
- while(1)
- {
- #if CRYSTAL_LESS
- /* Start USB trim if it is not enabled. */
- if((SYS->HIRCTRIMCTL & SYS_HIRCTRIMCTL_FREQSEL_Msk) != 1)
- {
- /* Start USB trim only when SOF */
- if(USBD->INTSTS & USBD_INTSTS_SOFIF_Msk)
- {
- /* Clear SOF */
- USBD->INTSTS = USBD_INTSTS_SOFIF_Msk;
- /* Re-enable crystal-less */
- SYS->HIRCTRIMCTL = 0x01;
- SYS->HIRCTRIMCTL |= SYS_HIRCTRIMCTL_REFCKSEL_Msk;
- }
- }
- /* Disable USB Trim when error */
- if(SYS->HIRCTRIMSTS & (SYS_HIRCTRIMSTS_CLKERIF_Msk | SYS_HIRCTRIMSTS_TFAILIF_Msk))
- {
- /* Init TRIM */
- M32(TRIM_INIT) = u32TrimInit;
- /* Disable crystal-less */
- SYS->HIRCTRIMCTL = 0;
- /* Clear error flags */
- SYS->HIRCTRIMSTS = SYS_HIRCTRIMSTS_CLKERIF_Msk | SYS_HIRCTRIMSTS_TFAILIF_Msk;
- /* Clear SOF */
- USBD->INTSTS = USBD_INTSTS_SOFIF_Msk;
- }
- #endif
- /* Enter power down when USB suspend */
- if(g_u8Suspend)
- PowerDown();
- VCOM_TransferData();
- HID_UpdateKbData();
- }
- }
- /*** (C) COPYRIGHT 2021 Nuvoton Technology Corp. ***/
|