Browse Source

Update NUC980 and M480

1. Add 980 drv_usbd.
2. EMAC - move MDC CLK divider before EMAC initialization.
3. Correct NUC980 and M480 CAN RX_MSG_ID_INDEX definition.
4. add USBD cdc demo - vcom_echo.
5. mnt - add mount_table definition.
Wayne Lin 4 years ago
parent
commit
1c4328e5a9

+ 6 - 5
bsp/nuvoton/libraries/m480/rtt_port/drv_can.c

@@ -212,15 +212,16 @@ static void nu_can_isr(nu_can_t can)
         }
     }
 #ifdef RT_CAN_USING_HDR
-    /*Number of Message Object which caused the interrupt*/
+    /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/
     else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32)
     {
-        rt_kprintf("=> Interrupt Pointer = %d\n", u32IIDRstatus - 1);
-        /*Message RAM 0~15 for CAN Tx using*/
-        if (u32IIDRstatus <= 16)
+        /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/
+        if (u32IIDRstatus <= RX_MSG_ID_INDEX)
+        {
             //rt_kprintf("[%s-Tx]IntId = %d\n", can->name, u32IIDRstatus);
             rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE);
-        else /*Message RAM 16~31 for CAN Rx using*/
+        }
+        else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/
         {
             //rt_kprintf("[%s-Rx]IntId = %d\n", can->name, u32IIDRstatus);
             rt_hw_can_isr(&can->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8)));

+ 1 - 0
bsp/nuvoton/libraries/nu_packages/Demo/SConscript

@@ -6,6 +6,7 @@ if GetDepend('NU_PKG_USING_DEMO'):
     src = Split("""
     usbd_hid_dance_mouse.c
     slcd_show_tick.c
+    usbd_cdc_vcom_echo.c
     """)
     CPPPATH = [cwd]
     group = DefineGroup('nu_pkgs_demo', src, depend = [''], CPPPATH = CPPPATH)

+ 113 - 0
bsp/nuvoton/libraries/nu_packages/Demo/slcd_show_tick.c

@@ -0,0 +1,113 @@
+/**************************************************************************//**
+*
+* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
+*
+* SPDX-License-Identifier: Apache-2.0
+*
+* Change Logs:
+* Date            Author       Notes
+* 2020-11-11      Wayne        First version
+*
+******************************************************************************/
+
+#include <rtconfig.h>
+
+#if defined(BSP_USING_SLCD)
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include "slcd_rhe6616tp01.h"
+
+const uint32_t au32SLCDSymbols [] =
+{
+    SYMBOL_NVT,
+    SYMBOL_WIFI,
+    SYMBOL_SOUND,
+    SYMBOL_NUMICRO,
+    SYMBOL_BAT_FRAME,
+    SYMBOL_BAT_1,
+    SYMBOL_BAT_2,
+    SYMBOL_BAT_3,
+    SYMBOL_PLUS,
+    SYMBOL_MINUS,
+    SYMBOL_V,
+    SYMBOL_A,
+    SYMBOL_W,
+    SYMBOL_ARROW_UP,
+    SYMBOL_ARROW_LEFT,
+    SYMBOL_ARROW_DOWN,
+    SYMBOL_ARROW_RIGHT,
+    SYMBOL_CIRCLE_UP,
+    SYMBOL_CIRCLE_LEFT,
+    SYMBOL_CIRCLE_RIGHT,
+    SYMBOL_PERCENTAGE,
+    SYMBOL_PPM,
+    SYMBOL_TEMP_C,
+    SYMBOL_TEMP_F,
+    SYMBOL_VERSION,
+    SYMBOL_MAIN_DIG_COL1,
+    SYMBOL_MAIN_DIG_COL2,
+    SYMBOL_MAIN_DIG_COL3,
+    SYMBOL_MAIN_DIG_COL4,
+    SYMBOL_MAIN_DIG_COL5,
+    SYMBOL_MAIN_DIG_COL6,
+    SYMBOL_MAIN_DIG_P1,
+    SYMBOL_MAIN_DIG_P2,
+    SYMBOL_MAIN_DIG_P3,
+    SYMBOL_MAIN_DIG_P4,
+    SYMBOL_MAIN_DIG_P5,
+    SYMBOL_MAIN_DIG_P6,
+    SYMBOL_VER_DIG_P1,
+    SYMBOL_VER_DIG_P2,
+    SYMBOL_TIME_DIG_COL1,
+    SYMBOL_TIME_DIG_P1,
+    SYMBOL_TIME_DIG_P2,
+    SYMBOL_TIME_DIG_P3
+};
+const int i32SLCDSymbolsSize  = sizeof(au32SLCDSymbols) / sizeof(au32SLCDSymbols[0]);
+
+void slcd_demo_hook(void)
+{
+    uint32_t u32CurTickCount = rt_tick_get();
+
+    /* ZONE_MAIN_DIGIT */
+    LCDLIB_PrintNumber(ZONE_MAIN_DIGIT, u32CurTickCount);
+
+    /* ZONE_PPM_DIGIT */
+    LCDLIB_PrintNumber(ZONE_PPM_DIGIT, u32CurTickCount);
+
+    /* ZONE_TEMP_DIGIT */
+    LCDLIB_PrintNumber(ZONE_TEMP_DIGIT, u32CurTickCount);
+
+    /* ZONE_VER_DIGIT */
+    LCDLIB_PrintNumber(ZONE_VER_DIGIT, u32CurTickCount);
+
+    /* ZONE_TIME_DIGIT */
+    LCDLIB_PrintNumber(ZONE_TIME_DIGIT, u32CurTickCount);
+
+    /* ZONE_NUMICRO_DIGIT */
+    LCDLIB_PrintNumber(ZONE_NUMICRO_DIGIT, u32CurTickCount);
+
+    /* Travel all symbols */
+    LCDLIB_SetSymbol(au32SLCDSymbols[u32CurTickCount % i32SLCDSymbolsSize], (u32CurTickCount / i32SLCDSymbolsSize) % 2);
+
+    /* Travel all dots */
+    LCDLIB_SetSymbol(SYMBOL_S(u32CurTickCount % 40 + 1), (u32CurTickCount / 40) % 2);
+}
+
+static int slcd_demo_init(void)
+{
+    rt_err_t err = rt_thread_idle_sethook(slcd_demo_hook);
+
+    if (err != RT_EOK)
+    {
+        rt_kprintf("set idle hook failed!\n");
+        return -1;
+    }
+
+    return 0;
+}
+INIT_APP_EXPORT(slcd_demo_init);
+
+#endif /* #if defined(BSP_USING_SLCD) */

+ 70 - 0
bsp/nuvoton/libraries/nu_packages/Demo/usbd_cdc_vcom_echo.c

@@ -0,0 +1,70 @@
+#include <rtthread.h>
+
+#if defined(RT_USB_DEVICE_CDC) && (defined(BSP_USING_USBD) || defined(BSP_USING_HSUSBD))
+
+static struct rt_semaphore rx_sem;
+
+static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
+{
+    rt_sem_release(&rx_sem);
+    return RT_EOK;
+}
+
+static void serial_thread_entry(void *parameter)
+{
+    rt_device_t serial = (rt_device_t)parameter;
+    char ch;
+    char szStr[64];
+    while (1)
+    {
+        while (rt_device_read(serial, -1, &ch, 1) != 1)
+        {
+            if (rt_sem_take(&rx_sem, 3 * RT_TICK_PER_SECOND) == -RT_ETIMEOUT)
+            {
+                time_t now;
+                /* output current time */
+                now = time(RT_NULL);
+                rt_snprintf(szStr, sizeof(szStr), "%.*s\n", 25, ctime(&now));
+                rt_device_write(serial, 0, &szStr[0], rt_strlen(szStr));
+                continue;
+            }
+        }
+        rt_device_write(serial, 0, &ch, 1);
+    }
+}
+
+static int vcom_echo_init(void)
+{
+    int err = 0;
+    rt_thread_t thread;
+    rt_device_t serial;
+
+    serial = rt_device_find("vcom");
+    if (!serial)
+    {
+        rt_kprintf("find failed!\n");
+        return RT_ERROR;
+    }
+    err = rt_device_init(serial);
+    if (err)
+    {
+        rt_kprintf("find failed!\n");
+        return -RT_ERROR;
+    }
+    err = rt_device_open(serial, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX/* | RT_DEVICE_FLAG_DMA_TX */);
+
+    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
+
+    rt_device_set_rx_indicate(serial, uart_input);
+
+    thread = rt_thread_create("serial", serial_thread_entry, (void *)serial, 1024, 25, 10);
+    if (thread != RT_NULL)
+    {
+        rt_thread_startup(thread);
+    }
+
+    return RT_EOK;
+}
+INIT_APP_EXPORT(vcom_echo_init);
+
+#endif

+ 12 - 0
bsp/nuvoton/libraries/nu_packages/SLCD/SConscript

@@ -0,0 +1,12 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd = GetCurrentDir()
+group = []
+if GetDepend('BSP_USING_SLCD'):
+	src = Glob('*.c') + Glob('*.cpp')
+	CPPPATH = [cwd]
+	group = DefineGroup('nu_pkgs_slcd', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 780 - 0
bsp/nuvoton/libraries/nu_packages/SLCD/slcd_rhe6616tp01.c

@@ -0,0 +1,780 @@
+/**************************************************************************//**
+ * @file     LCDLIB.c
+ * @version  V3.00
+ * @brief    RHE6616TP01(8-COM, 40-SEG, 1/4 Bias) LCD library source file
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * @copyright (C) 2019-2020 Nuvoton Technology Corp. All rights reserved.
+ *****************************************************************************/
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include "drv_slcd.h"
+#include "slcd_rhe6616tp01.h"
+
+#define DBG_SECTION_NAME "slcd_demo"
+#define DBG_LEVEL DBG_LOG
+#include <rtdbg.h>
+
+static rt_device_t g_psDev = RT_NULL;
+
+/**************************************************************************//**
+ *
+ * Defines each text's segment (alphabet+numeric) in terms of COM and SEG numbers,
+ * Using this way that text segment can be consisted of each bit in the
+ * following bit pattern:
+ * @illustration
+ *              A
+ *         -----------
+ *         |\   |   /|
+ *         F G  H  I B
+ *         |  \ | /  |
+ *         --J-- --K--
+ *         |   /| \  |
+ *         E  L M  N C
+ *         | /  |   \|
+ *         -----------
+ *              D
+ *
+ *              0
+ *         -----------
+ *         |\   |   /|
+ *        5| 6  7  8 |1
+ *         |  \ | /  |
+ *         --9-- -10--
+ *         |   /| \  |
+ *        4| 11 12 13|2
+ *         | /  |   \|
+ *         -----------
+ *              3
+ *
+ *****************************************************************************/
+static const char acMainDigitRawData[ZONE_MAIN_DIG_CNT][ZONE_MAIN_SEG_NUM][2] =
+{
+    {
+        // digit 1, {com, seg}
+        // A     // B     // C     // D
+        {0,  1}, {0,  0}, {3,  0}, {3,  1},
+        // E     // F     // G     // H
+        {2,  3}, {0,  3}, {0,  2}, {1,  1},
+        // I     // J     // K     // L
+        {1,  0}, {1,  2}, {2,  0}, {3,  2},
+        // M     // N
+        {2,  2}, {2,  1},
+    },
+    {
+        // digit 2, {com, seg}
+        // A     // B     // C     // D
+        {0, 18}, {0, 19}, {3, 19}, {3, 18},
+        // E     // F     // G     // H
+        {2, 16}, {0, 16}, {0, 17}, {1, 18},
+        // I     // J     // K     // L
+        {1, 19}, {1, 17}, {2, 19}, {3, 17},
+        // M     // N
+        {2, 17}, {2, 18},
+    },
+    {
+        // digit 3, {com, seg}
+        // A     // B     // C     // D
+        {0, 22}, {0, 23}, {3, 23}, {3, 22},
+        // E     // F     // G     // H
+        {2, 20}, {0, 20}, {0, 21}, {1, 22},
+        // I     // J     // K     // L
+        {1, 23}, {1, 21}, {2, 23}, {3, 21},
+        // M     // N
+        {2, 21}, {2, 22},
+    },
+    {
+        // digit 4, {com, seg}
+        // A     // B     // C     // D
+        {0, 26}, {0, 27}, {3, 27}, {3, 26},
+        // E     // F     // G     // H
+        {2, 24}, {0, 24}, {0, 25}, {1, 26},
+        // I     // J     // K     // L
+        {1, 27}, {1, 25}, {2, 27}, {3, 25},
+        // M     // N
+        {2, 25}, {2, 26},
+    },
+    {
+        // digit 5, {com, seg}
+        // A     // B     // C     // D
+        {0, 30}, {0, 31}, {3, 31}, {3, 30},
+        // E     // F     // G     // H
+        {2, 28}, {0, 28}, {0, 29}, {1, 30},
+        // I     // J     // K     // L
+        {1, 31}, {1, 29}, {2, 31}, {3, 29},
+        // M     // N
+        {2, 29}, {2, 30},
+    },
+    {
+        // digit 6, {com, seg}
+        // A     // B     // C     // D
+        {0, 34}, {0, 35}, {3, 35}, {3, 34},
+        // E     // F     // G     // H
+        {2, 32}, {0, 32}, {0, 33}, {1, 34},
+        // I     // J     // K     // L
+        {1, 35}, {1, 33}, {2, 35}, {3, 33},
+        // M     // N
+        {2, 33}, {2, 34},
+    },
+    {
+        // digit 7, {com, seg}
+        // A     // B     // C     // D
+        {0, 38}, {0, 39}, {3, 39}, {3, 38},
+        // E     // F     // G     // H
+        {2, 36}, {0, 36}, {0, 37}, {1, 38},
+        // I     // J     // K     // L
+        {1, 39}, {1, 37}, {2, 39}, {3, 37},
+        // M     // N
+        {2, 37}, {2, 38},
+    },
+};
+
+
+/**************************************************************************//**
+ *
+ * Defines each text's segment (numeric) in terms of COM and BIT numbers,
+ * Using this way that text segment can be consisted of each bit in the
+ * following bit pattern:
+ * @illustration
+ *
+ *         ---A---
+ *         |     |
+ *         F     B
+ *         |     |
+ *         ---G---
+ *         |     |
+ *         E     C
+ *         |     |
+ *         ---D---
+ *
+ *         ---0---
+ *         |     |
+ *         5     1
+ *         |     |
+ *         ---6---
+ *         |     |
+ *         4     2
+ *         |     |
+ *         ---3---
+ *
+ *****************************************************************************/
+static const char acPPMDigitRawData[ZONE_PPM_DIG_CNT][ZONE_PPM_SEG_NUM][2] =
+{
+    {
+        // digit 1, {com, seg}
+        // A     // B     // C     // D
+        {4, 16}, {5, 17}, {7, 17}, {7, 16},
+        // E     // F     // G
+        {6, 16}, {5, 16}, {6, 17},
+    },
+    {
+        // digit 2, {com, seg}
+        // A     // B     // C     // D
+        {4, 18}, {5, 19}, {7, 19}, {7, 18},
+        // E     // F     // G
+        {6, 18}, {5, 18}, {6, 19},
+    },
+    {
+        // digit 3, {com, seg}
+        // A     // B     // C     // D
+        {4, 20}, {5, 21}, {7, 21}, {7, 20},
+        // E     // F     // G
+        {6, 20}, {5, 20}, {6, 21},
+    },
+};
+
+static const char acTEMPDigitRawData[ZONE_TEMP_DIG_CNT][ZONE_TEMP_SEG_NUM][2] =
+{
+    {
+        // digit 1, {com, seg}
+        // A     // B     // C     // D
+        {4, 22}, {5, 23}, {7, 23}, {7, 22},
+        // E     // F     // G
+        {6, 22}, {5, 22}, {6, 23},
+    },
+    {
+        // digit 2, {com, seg}
+        // A     // B     // C     // D
+        {4, 24}, {5, 25}, {7, 25}, {7, 24},
+        // E     // F     // G
+        {6, 24}, {5, 24}, {6, 25},
+    },
+    {
+        // digit 3, {com, seg}
+        // A     // B     // C     // D
+        {4, 26}, {5, 27}, {7, 27}, {7, 26},
+        // E     // F     // G
+        {6, 26}, {5, 26}, {6, 27},
+    },
+};
+
+static const char acVERDigitRawData[ZONE_VER_DIG_CNT][ZONE_VER_SEG_NUM][2] =
+{
+    {
+        // digit 1, {com, seg}
+        // A     // B     // C     // D
+        {4, 28}, {5, 29}, {7, 29}, {7, 28},
+        // E     // F     // G
+        {6, 28}, {5, 28}, {6, 29},
+    },
+    {
+        // digit 2, {com, seg}
+        // A     // B     // C     // D
+        {4, 30}, {5, 31}, {7, 31}, {7, 30},
+        // E     // F     // G
+        {6, 30}, {5, 30}, {6, 31},
+    },
+    {
+        // digit 3, {com, seg}
+        // A     // B     // C     // D
+        {4, 32}, {5, 33}, {7, 33}, {7, 32},
+        // E     // F     // G
+        {6, 32}, {5, 32}, {6, 33},
+    },
+    {
+        // digit 4, {com, seg}
+        // A     // B     // C     // D
+        {4, 34}, {5, 35}, {7, 35}, {7, 34},
+        // E     // F     // G
+        {6, 34}, {5, 34}, {6, 35},
+    },
+    {
+        // digit 5, {com, seg}
+        // A     // B     // C     // D
+        {4, 36}, {5, 37}, {7, 37}, {7, 36},
+        // E     // F     // G
+        {6, 36}, {5, 36}, {6, 37},
+    },
+    {
+        // digit 6, {com, seg}
+        // A     // B     // C     // D
+        {4, 38}, {5, 39}, {7, 39}, {7, 38},
+        // E     // F     // G
+        {6, 38}, {5, 38}, {6, 39},
+    },
+};
+
+static const char acTimeDigitRawData[ZONE_TIME_DIG_CNT][ZONE_TIME_SEG_NUM][2] =
+{
+    {
+        // digit 1, {com, seg}
+        // A     // B     // C     // D
+        {7,  2}, {6,  3}, {4,  3}, {4,  2},
+        // E     // F     // G
+        {5,  2}, {6,  2}, {5, 3},
+    },
+    {
+        // digit 2, {com, seg}
+        // A     // B     // C     // D
+        {7,  4}, {6,  5}, {4,  5}, {4,  4},
+        // E     // F     // G
+        {5,  4}, {6,  4}, {5, 5},
+    },
+    {
+        // digit 3, {com, seg}
+        // A     // B     // C     // D
+        {7,  6}, {6,  7}, {4,  7}, {4,  6},
+        // E     // F     // G
+        {5,  6}, {6,  6}, {5, 7},
+    },
+    {
+        // digit 4, {com, seg}
+        // A     // B     // C     // D
+        {7,  8}, {6,  9}, {4,  9}, {4,  8},
+        // E     // F     // G
+        {5,  8}, {6,  8}, {5, 9},
+    },
+};
+
+static const char acNuMicroDigitRawData[ZONE_NUMICRO_DIG_CNT][ZONE_NUMICRO_SEG_NUM][2] =
+{
+    {
+        // digit 1, {com, seg}
+        // A     // B     // C     // D
+        {3,  4}, {2,  5}, {0,  5}, {0,  4},
+        // E     // F     // G
+        {1,  4}, {2,  4}, {1,  5},
+    },
+    {
+        // digit 2, {com, seg}
+        // A     // B     // C     // D
+        {3,  6}, {2,  7}, {0,  7}, {0,  6},
+        // E     // F     // G
+        {1,  6}, {2,  6}, {1,  7},
+    },
+    {
+        // digit 3, {com, seg}
+        // A     // B     // C     // D
+        {3,  8}, {2,  9}, {0,  9}, {0,  8},
+        // E     // F     // G
+        {1,  8}, {2,  8}, {1,  9},
+    },
+};
+
+/**************************************************************************//**
+ *
+ * Defines segments for the alphabet - ASCII table 0x20 to 0x7A
+ * Bit pattern below defined for alphabet (text segments)
+ *
+ *****************************************************************************/
+static const uint16_t auMainDigitMap[] =
+{
+    0x0000, /* space */
+    0x1100, /* ! */
+    0x0280, /* " */
+    0x0000, /* # */
+    0x0000, /* $ */
+    0x0000, /* % */
+    0x0000, /* & */
+    0x0000, /* ? */
+    0x0039, /* ( */
+    0x000f, /* ) */
+    0x3fc0, /* * */
+    0x1540, /* + */
+    0x0000, /* , */
+    0x0440, /* - */
+    0x8000, /* . */
+    0x2200, /* / */
+
+    0x003F, /* 0 */
+    0x0006, /* 1 */
+    0x061B, /* 2 */
+    0x060F, /* 3 */
+    0x0626, /* 4 */
+    0x062D, /* 5 */
+    0x063D, /* 6 */
+    0x0007, /* 7 */
+    0x063F, /* 8 */
+    0x062F, /* 9 */
+
+    0x0000, /* : */
+    0x0000, /* ; */
+    0x2100, /* < */
+    0x0000, /* = */
+    0x0840, /* > */
+    0x1403, /* ? */
+    0x3FFF, /* @ */
+
+    0x0637, /* A */
+    0x2339, /* B */
+    0x0039, /* C */
+    0x2139, /* D */
+    0x0639, /* E */
+    0x0631, /* F */
+    0x043D, /* G */
+    0x0636, /* H */
+    0x1080, /* I */
+    0x000E, /* J */
+    0x2330, /* K */
+    0x0038, /* L */
+    0x0176, /* M */
+    0x2076, /* N */
+    0x003F, /* O */
+    0x0633, /* P */
+    0x203F, /* Q */
+    0x2331, /* R */
+    0x062D, /* S */
+    0x1081, /* T */
+    0x003E, /* U */
+    0x0930, /* V */
+    0x2836, /* W */
+    0x2940, /* X */
+    0x1140, /* Y */
+    0x0909, /* Z */
+
+    0x0039, /* [ */
+    0x0900, /* backslash */
+    0x000F, /* ] */
+    0x2800, /* ^ */
+    0x0008, /* _ */
+    0x0040, /* ` */
+
+    0x1218, /* a */
+    0x063C, /* b */
+    0x0618, /* c */
+    0x061E, /* d */
+    0x0A18, /* e */
+    0x0231, /* f */
+    0x048F, /* g */
+    0x1230, /* h */
+    0x1000, /* i */
+    0x000E, /* j */
+    0x2330, /* k */
+    0x0038, /* l */
+    0x1614, /* m */
+    0x1404, /* n */
+    0x061C, /* o */
+    0x0331, /* p */
+    0x0447, /* q */
+    0x1400, /* r */
+    0x2408, /* s */
+    0x0238, /* t */
+    0x1018, /* u */
+    0x0810, /* v */
+    0x2814, /* w */
+    0x2940, /* x */
+    0x0446, /* y */
+    0x0A08, /* z */
+
+    0x0000,
+};
+
+/**************************************************************************//**
+ * Defines segments for the numeric display
+ *****************************************************************************/
+static const uint16_t auPPMDigitMap[] =
+{
+    0x3F, /* 0 */
+    0x06, /* 1 */
+    0x5B, /* 2 */
+    0x4F, /* 3 */
+    0x66, /* 4 */
+    0x6D, /* 5 */
+    0x7D, /* 6 */
+    0x07, /* 7 */
+    0x7F, /* 8 */
+    0x6F, /* 9 */
+};
+
+static const uint16_t auTEMPDigitMap[] =
+{
+    0x3F, /* 0 */
+    0x06, /* 1 */
+    0x5B, /* 2 */
+    0x4F, /* 3 */
+    0x66, /* 4 */
+    0x6D, /* 5 */
+    0x7D, /* 6 */
+    0x07, /* 7 */
+    0x7F, /* 8 */
+    0x6F, /* 9 */
+};
+
+static const uint16_t auVERDigitMap[] =
+{
+    0x3F, /* 0 */
+    0x06, /* 1 */
+    0x5B, /* 2 */
+    0x4F, /* 3 */
+    0x66, /* 4 */
+    0x6D, /* 5 */
+    0x7D, /* 6 */
+    0x07, /* 7 */
+    0x7F, /* 8 */
+    0x6F, /* 9 */
+};
+
+static const uint16_t auTimeDigitMap[] =
+{
+    0x3F, /* 0 */
+    0x06, /* 1 */
+    0x5B, /* 2 */
+    0x4F, /* 3 */
+    0x66, /* 4 */
+    0x6D, /* 5 */
+    0x7D, /* 6 */
+    0x07, /* 7 */
+    0x7F, /* 8 */
+    0x6F, /* 9 */
+};
+
+static const uint16_t auNuMicroDigitMap[] =
+{
+    0x3F, /* 0 */
+    0x06, /* 1 */
+    0x5B, /* 2 */
+    0x4F, /* 3 */
+    0x66, /* 4 */
+    0x6D, /* 5 */
+    0x7D, /* 6 */
+    0x07, /* 7 */
+    0x7F, /* 8 */
+    0x6F, /* 9 */
+};
+
+/* Zone information */
+static const LCD_ZONE_INFO_T g_LCDZoneInfo[] =
+{
+    {ZONE_MAIN_DIG_CNT,     ZONE_MAIN_SEG_NUM},
+    {ZONE_PPM_DIG_CNT,      ZONE_PPM_SEG_NUM},
+    {ZONE_TEMP_DIG_CNT,     ZONE_TEMP_SEG_NUM},
+    {ZONE_VER_DIG_CNT,      ZONE_VER_SEG_NUM},
+    {ZONE_TIME_DIG_CNT,     ZONE_TIME_SEG_NUM},
+    {ZONE_NUMICRO_DIG_CNT,  ZONE_NUMICRO_SEG_NUM},
+};
+
+/* Raw data table for each zone */
+static const char *g_GetLCDComSeg[] =
+{
+    (const char *)(acMainDigitRawData),
+    (const char *)(acPPMDigitRawData),
+    (const char *)(acTEMPDigitRawData),
+    (const char *)(acVERDigitRawData),
+    (const char *)(acTimeDigitRawData),
+    (const char *)(acNuMicroDigitRawData),
+};
+
+/* Display mapping table for each zone */
+static const uint16_t *g_LCDDispTable[] =
+{
+    (const uint16_t *)(auMainDigitMap),
+    (const uint16_t *)(auPPMDigitMap),
+    (const uint16_t *)(auTEMPDigitMap),
+    (const uint16_t *)(auVERDigitMap),
+    (const uint16_t *)(auTimeDigitMap),
+    (const uint16_t *)(auNuMicroDigitMap),
+};
+
+
+void SLCD_SetPixel(uint32_t u32Com, uint32_t u32Seg, uint32_t u32OnFlag)
+{
+    if (g_psDev)
+    {
+        struct nu_slcd_pixel sNuSLCDPxl;
+
+        sNuSLCDPxl.m_u32Com = u32Com;
+        sNuSLCDPxl.m_u32Seg = u32Seg;
+        sNuSLCDPxl.m_u32OnFlag = u32OnFlag;
+        rt_device_write(g_psDev, 0, (void *)&sNuSLCDPxl, sizeof(struct nu_slcd_pixel));
+    }
+}
+
+/**
+ *  @brief Display text on LCD
+ *
+ *  @param[in]  u32Zone     the assigned number of display area
+ *  @param[in]  InputStr    Text string to show on display
+ *
+ *  @return None
+ */
+void LCDLIB_Printf(uint32_t u32Zone, char *InputStr)
+{
+    uint32_t    i, index, ch, len;
+    uint16_t    DispData;
+    uint32_t    com, seg;
+
+    len = rt_strlen(InputStr);
+
+    /* Fill out all characters on display */
+    for (index = 0; index < g_LCDZoneInfo[u32Zone].u32DigitCnt; index++)
+    {
+        if (index < len)
+        {
+            ch = *InputStr;
+        }
+        else
+        {
+            /* Padding with SPACE */
+            ch = 0x20;
+        }
+
+        /* The Main Digit Table is an ASCII table beginning with "SPACE" (hex is 0x20) */
+        ch       = ch - 0x20;
+        DispData = *(g_LCDDispTable[u32Zone] + ch);
+
+        for (i = 0; i < g_LCDZoneInfo[u32Zone].u32MaxSegNum; i++)
+        {
+            com = *(g_GetLCDComSeg[u32Zone]
+                    + (index * g_LCDZoneInfo[u32Zone].u32MaxSegNum * 2)
+                    + (i * 2) + 0);
+            seg = *(g_GetLCDComSeg[u32Zone]
+                    + (index * g_LCDZoneInfo[u32Zone].u32MaxSegNum * 2)
+                    + (i * 2) + 1);
+
+            /* Turn off display */
+            SLCD_SetPixel(com, seg, 0);
+
+            if (DispData & (1 << i))
+            {
+                /* Turn on display */
+                SLCD_SetPixel(com, seg, 1);
+            }
+        }
+
+        InputStr++;
+    }
+}
+
+/**
+ *  @brief Display number on LCD
+ *
+ *  @param[in]  u32Zone     the assigned number of display area
+ *  @param[in]  InputNum    number to show on display
+ *
+ *  @return None
+ */
+void LCDLIB_PrintNumber(uint32_t u32Zone, uint32_t InputNum)
+{
+    uint32_t    i, index, val, div;
+    uint16_t    DispData;
+    uint32_t    com, seg;
+
+    /* Extract useful digits */
+    div = 1;
+
+    /* Fill out all characters on display */
+    index = g_LCDZoneInfo[u32Zone].u32DigitCnt;
+    while (index != 0)
+    {
+        index--;
+
+        val = (InputNum / div) % 10;
+        if (u32Zone == ZONE_MAIN_DIGIT)
+            val += 16; /* The Main Digit Table is an ASCII table beginning with "SPACE" */
+
+        DispData = *(g_LCDDispTable[u32Zone] + val);
+
+        for (i = 0; i < g_LCDZoneInfo[u32Zone].u32MaxSegNum; i++)
+        {
+            com = *(g_GetLCDComSeg[u32Zone]
+                    + (index * g_LCDZoneInfo[u32Zone].u32MaxSegNum * 2)
+                    + (i * 2) + 0);
+            seg = *(g_GetLCDComSeg[u32Zone]
+                    + (index * g_LCDZoneInfo[u32Zone].u32MaxSegNum * 2)
+                    + (i * 2) + 1);
+
+            /* Turn off display */
+            SLCD_SetPixel(com, seg, 0);
+
+            if (DispData & (1 << i))
+            {
+                /* Turn on display */
+                SLCD_SetPixel(com, seg, 1);
+            }
+        }
+
+        div = div * 10;
+    }
+}
+
+/**
+ *  @brief Display character on LCD
+ *
+ *  @param[in]  u32Zone     the assigned number of display area
+ *  @param[in]  u32Index    the requested display position in zone
+ *  @param[in]  u8Ch        Character to show on display
+ *
+ *  @return None
+ */
+void LCDLIB_PutChar(uint32_t u32Zone, uint32_t u32Index, uint8_t u8Ch)
+{
+    uint32_t    i, ch;
+    uint16_t    DispData;
+    uint32_t    com, seg;
+
+    if (u32Index <= g_LCDZoneInfo[u32Zone].u32DigitCnt)
+    {
+        /* Defined letters currently starts at "SPACE" - 0x20; */
+        ch       = u8Ch - 0x20;
+        DispData = *(g_LCDDispTable[u32Zone] + ch);
+
+        for (i = 0; i < g_LCDZoneInfo[u32Zone].u32MaxSegNum; i++)
+        {
+            com = *(g_GetLCDComSeg[u32Zone]
+                    + (u32Index * g_LCDZoneInfo[u32Zone].u32MaxSegNum * 2)
+                    + (i * 2) + 0);
+
+            seg = *(g_GetLCDComSeg[u32Zone]
+                    + (u32Index * g_LCDZoneInfo[u32Zone].u32MaxSegNum * 2)
+                    + (i * 2) + 1);
+
+            /* Turn off display */
+            SLCD_SetPixel(com, seg, 0);
+
+            if (DispData & (1 << i))
+            {
+                /* Turn on display */
+                SLCD_SetPixel(com, seg, 1);
+            }
+        }
+    }
+}
+
+/**
+ *  @brief Display symbol on LCD
+ *
+ *  @param[in]  u32Symbol   the combination of com, seg position
+ *  @param[in]  u32OnOff    1: display symbol
+ *                          0: not display symbol
+ *
+ *  @return     None
+ */
+void LCDLIB_SetSymbol(uint32_t u32Symbol, uint32_t u32OnOff)
+{
+    uint32_t com, seg;
+
+    com = (u32Symbol & 0xF);
+    seg = ((u32Symbol & 0xFF0) >> 4);
+
+    if (u32OnOff)
+        SLCD_SetPixel(com, seg, 1); /* Turn on display */
+    else
+        SLCD_SetPixel(com, seg, 0); /* Turn off display */
+
+}
+
+static S_LCD_CFG_T g_LCDCfg_RHE6616TP01 =
+{
+    __LXT,                      /*!< LCD clock source frequency */
+    LCD_COM_DUTY_1_8,           /*!< COM duty */
+    LCD_BIAS_LV_1_4,            /*!< Bias level */
+    64,                         /*!< Operation frame rate */
+    LCD_WAVEFORM_TYPE_A_NORMAL, /*!< Waveform type */
+    LCD_DISABLE_ALL_INT,        /*!< Interrupt source */
+    LCD_LOW_DRIVING_AND_BUF_ON, /*!< Driving mode */
+    LCD_VOLTAGE_SOURCE_CP,      /*!< Voltage source */
+};
+
+static int nu_slcd_panel_init(void)
+{
+    uint32_t u32CPVol;
+    rt_err_t ret = RT_EOK;
+
+    g_psDev = rt_device_find("slcd");
+    if (g_psDev == RT_NULL)
+    {
+        LOG_E("can't find slcd failed!\n");
+        goto fail_nu_slcd_panel_init;
+    }
+
+    /* Give owned SLCD configuration before openning. */
+    ret = rt_device_control(g_psDev, NU_SLCD_CMD_SET_LCD_CFG, (void *)&g_LCDCfg_RHE6616TP01);
+    if (ret != RT_EOK)
+    {
+        LOG_E("configure SLCD failed!\n");
+        goto fail_nu_slcd_panel_init;
+    }
+
+    /* Open SLCD. */
+    ret = rt_device_open(g_psDev, RT_DEVICE_FLAG_WRONLY);
+    if (ret != RT_EOK)
+    {
+        LOG_E("open dev failed!\n");
+        goto fail_nu_slcd_panel_init;
+    }
+
+    /* Note: This panel need inject 4.8v, but m2354 charge pump max voltage is 3.6v. */
+    u32CPVol = LCD_CP_VOLTAGE_LV_5;
+    ret = rt_device_control(g_psDev, NU_SLCD_CMD_SET_CP_VOLTAGE, (void *)&u32CPVol);
+    if (ret != RT_EOK)
+    {
+        LOG_E("faile to control cp voltage!\n");
+        goto fail_nu_slcd_panel_init;
+    }
+
+    return (int)ret;
+
+fail_nu_slcd_panel_init:
+
+    if (g_psDev)
+    {
+        rt_device_close(g_psDev);
+        g_psDev = RT_NULL;
+    }
+    return (int)ret;
+}
+INIT_COMPONENT_EXPORT(nu_slcd_panel_init);
+
+/*** (C) COPYRIGHT 2019-2020 Nuvoton Technology Corp. ***/

+ 139 - 0
bsp/nuvoton/libraries/nu_packages/SLCD/slcd_rhe6616tp01.h

@@ -0,0 +1,139 @@
+/**************************************************************************//**
+ * @file     LCDLIB.h
+ * @version  V3.00
+ * @brief    RHE6616TP01(8-COM, 40-SEG, 1/4 Bias) LCD library header file
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * @copyright (C) 2019-2020 Nuvoton Technology Corp. All rights reserved.
+ *****************************************************************************/
+#ifndef __M2354_LCDLIB_H
+#define __M2354_LCDLIB_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** @addtogroup LIBRARY Library
+  @{
+*/
+
+/** @addtogroup M2354_LCDLIB_Driver LCD Library
+  @{
+*/
+
+/** @addtogroup M2354_LCDLIB_EXPORTED_CONSTANTS LCDLIB Exported Constants
+  @{
+*/
+/*---------------------------------------------------------------------------------------------------------*/
+/*  Digit Zone Constant Definitions                                                                        */
+/*---------------------------------------------------------------------------------------------------------*/
+#define ZONE_MAIN_DIGIT         0   /*!< Main digit display zone index */
+#define ZONE_MAIN_DIG_CNT       7   /*!< Number of digits/texts, for number and alphabet display */
+#define ZONE_MAIN_SEG_NUM       14  /*!< Number of segments on each digit number */
+
+#define ZONE_PPM_DIGIT          1   /*!< PPM or percentage digit display zone index */
+#define ZONE_PPM_DIG_CNT        3   /*!< Number of digits, for ppm display */
+#define ZONE_PPM_SEG_NUM        7   /*!< Number of segments on each digit number */
+
+#define ZONE_TEMP_DIGIT         2   /*!< Temperature digit display zone index */
+#define ZONE_TEMP_DIG_CNT       3   /*!< Number of digits, for c/f display */
+#define ZONE_TEMP_SEG_NUM       7   /*!< Number of segments on each digit number */
+
+#define ZONE_VER_DIGIT          3   /*!< Version number digit display zone index */
+#define ZONE_VER_DIG_CNT        6   /*!< Number of digits, for version display */
+#define ZONE_VER_SEG_NUM        7   /*!< Number of segments on each digit number */
+
+#define ZONE_TIME_DIGIT         4   /*!< Time digit display zone index */
+#define ZONE_TIME_DIG_CNT       4   /*!< Number of digits */
+#define ZONE_TIME_SEG_NUM       7   /*!< Number of segments on each digit number */
+
+#define ZONE_NUMICRO_DIGIT      5   /*!< NuMicro digit display zone index */
+#define ZONE_NUMICRO_DIG_CNT    3   /*!< Number of digits */
+#define ZONE_NUMICRO_SEG_NUM    7   /*!< Number of segments on each digit number */
+
+/*---------------------------------------------------------------------------------------------------------*/
+/*  COM and SEG Position of Symbol Constant Definitions                                                    */
+/*---------------------------------------------------------------------------------------------------------*/
+#define SYMBOL_NVT              ((10)<<4 | (4)<<0)  /*!< T1 display on COM 4, SEG 10 */
+#define SYMBOL_WIFI             ((10)<<4 | (5)<<0)  /*!< T2 display on COM 5, SEG 10 */
+#define SYMBOL_SOUND            ((10)<<4 | (6)<<0)  /*!< T3 display on COM 6, SEG 10 */
+#define SYMBOL_NUMICRO          ((9)<<4  | (3)<<0)  /*!< Y3 display on COM 3, SEG 9 */
+#define SYMBOL_BAT_FRAME        ((10)<<4 | (0)<<0)  /*!< T7 display on COM 0, SEG 10 */
+#define SYMBOL_BAT_1            ((10)<<4 | (2)<<0)  /*!< T4 display on COM 2, SEG 10 */
+#define SYMBOL_BAT_2            ((10)<<4 | (3)<<0)  /*!< T5 display on COM 3, SEG 10 */
+#define SYMBOL_BAT_3            ((10)<<4 | (1)<<0)  /*!< T6 display on COM 1, SEG 10 */
+#define SYMBOL_PLUS             ((3)<<4  | (1)<<0)  /*!< T12 display on COM 1, SEG 3 */
+#define SYMBOL_MINUS            ((3)<<4  | (3)<<0)  /*!< T13 display on COM 3, SEG 3 */
+#define SYMBOL_V                ((39)<<4 | (4)<<0)  /*!< T26 display on COM 4, SEG 39 */
+#define SYMBOL_A                ((37)<<4 | (4)<<0)  /*!< T27 display on COM 4, SEG 37 */
+#define SYMBOL_W                ((35)<<4 | (4)<<0)  /*!< T28 display on COM 4, SEG 35 */
+#define SYMBOL_ARROW_UP         ((1)<<4  | (4)<<0)  /*!< T29 display on COM 4, SEG 1 */
+#define SYMBOL_ARROW_LEFT       ((1)<<4  | (6)<<0)  /*!< T30 display on COM 6, SEG 1 */
+#define SYMBOL_ARROW_DOWN       ((0)<<4  | (7)<<0)  /*!< T31 display on COM 7, SEG 0 */
+#define SYMBOL_ARROW_RIGHT      ((0)<<4  | (4)<<0)  /*!< T32 display on COM 4, SEG 0 */
+#define SYMBOL_CIRCLE_UP        ((1)<<4  | (5)<<0)  /*!< T33 display on COM 5, SEG 1 */
+#define SYMBOL_CIRCLE_LEFT      ((0)<<4  | (6)<<0)  /*!< T34 display on COM 6, SEG 0 */
+#define SYMBOL_CIRCLE_RIGHT     ((0)<<4  | (5)<<0)  /*!< T35 display on COM 5, SEG 0 */
+#define SYMBOL_PERCENTAGE       ((23)<<4 | (4)<<0)  /*!< Y2 display on COM 4, SEG 23 */
+#define SYMBOL_PPM              ((21)<<4 | (4)<<0)  /*!< Y1 display on COM 4, SEG 21 */
+#define SYMBOL_TEMP_C           ((25)<<4 | (4)<<0)  /*!< T37 display on COM 4, SEG 25 */
+#define SYMBOL_TEMP_F           ((27)<<4 | (4)<<0)  /*!< T38 display on COM 4, SEG 27 */
+#define SYMBOL_VERSION          ((31)<<4 | (4)<<0)  /*!< T41 display on COM 4, SEG 31 */
+#define SYMBOL_S(x)             (((((x)-1)%5)+11)<<4 | (((x)-1)/5)<<0)  /*!< S[x] display on COM x, SEG x. [x] range is 1 ~ 40. */
+#define SYMBOL_MAIN_DIG_COL1    ((16)<<4 | (1)<<0)  /*!< T14 display on COM 1, SEG 16 */
+#define SYMBOL_MAIN_DIG_COL2    ((20)<<4 | (1)<<0)  /*!< T16 display on COM 1, SEG 20 */
+#define SYMBOL_MAIN_DIG_COL3    ((24)<<4 | (1)<<0)  /*!< T18 display on COM 1, SEG 24 */
+#define SYMBOL_MAIN_DIG_COL4    ((28)<<4 | (1)<<0)  /*!< T20 display on COM 1, SEG 28 */
+#define SYMBOL_MAIN_DIG_COL5    ((32)<<4 | (1)<<0)  /*!< T22 display on COM 1, SEG 32 */
+#define SYMBOL_MAIN_DIG_COL6    ((36)<<4 | (1)<<0)  /*!< T24 display on COM 1, SEG 36 */
+#define SYMBOL_MAIN_DIG_P1      ((16)<<4 | (3)<<0)  /*!< T15 display on COM 3, SEG 16 */
+#define SYMBOL_MAIN_DIG_P2      ((20)<<4 | (3)<<0)  /*!< T17 display on COM 3, SEG 20 */
+#define SYMBOL_MAIN_DIG_P3      ((24)<<4 | (3)<<0)  /*!< T19 display on COM 3, SEG 24 */
+#define SYMBOL_MAIN_DIG_P4      ((28)<<4 | (3)<<0)  /*!< T21 display on COM 3, SEG 28 */
+#define SYMBOL_MAIN_DIG_P5      ((32)<<4 | (3)<<0)  /*!< T23 display on COM 3, SEG 32 */
+#define SYMBOL_MAIN_DIG_P6      ((36)<<4 | (3)<<0)  /*!< T25 display on COM 3, SEG 36 */
+#define SYMBOL_VER_DIG_P1       ((29)<<4 | (4)<<0)  /*!< T39 display on COM 4, SEG 29 */
+#define SYMBOL_VER_DIG_P2       ((33)<<4 | (4)<<0)  /*!< T40 display on COM 4, SEG 33 */
+#define SYMBOL_TIME_DIG_COL1    ((5)<<4  | (7)<<0)  /*!< T9 display on COM 7, SEG 5 */
+#define SYMBOL_TIME_DIG_P1      ((3)<<4  | (7)<<0)  /*!< T8 display on COM 7, SEG 3 */
+#define SYMBOL_TIME_DIG_P2      ((5)<<4  | (3)<<0)  /*!< T10 display on COM 3, SEG 5 */
+#define SYMBOL_TIME_DIG_P3      ((7)<<4  | (3)<<0)  /*!< T11 display on COM 3, SEG 7 */
+
+/**@}*/ /* end of group M2354_LCDLIB_EXPORTED_CONSTANTS */
+
+
+/** @addtogroup M2354_LCDLIB_EXPORTED_STRUCTS LCDLIB Exported Structs
+  @{
+*/
+typedef struct
+{
+    uint32_t u32DigitCnt;   /*!< Digit counts */
+    uint32_t u32MaxSegNum;  /*!< Maximum segment number */
+} LCD_ZONE_INFO_T;
+
+/**@}*/ /* end of group M2354_LCDLIB_EXPORTED_STRUCTS */
+
+
+/** @addtogroup M2354_LCDLIB_EXPORTED_FUNCTIONS LCD Exported Functions
+  @{
+*/
+
+void LCDLIB_Printf(uint32_t u32Zone, char *InputStr);
+void LCDLIB_PutChar(uint32_t u32Zone, uint32_t u32Index, uint8_t u8Ch);
+void LCDLIB_PrintNumber(uint32_t u32Zone, uint32_t InputNum);
+void LCDLIB_SetSymbol(uint32_t u32Symbol, uint32_t u32OnOff);
+
+/**@}*/ /* end of group M2354_LCDLIB_EXPORTED_FUNCTIONS */
+
+/**@}*/ /* end of group M2354_LCDLIB_Driver */
+
+/**@}*/ /* end of group LIBRARY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __M2354_LCDLIB_H */
+
+/*** (C) COPYRIGHT 2019-2020 Nuvoton Technology Corp. ***/

+ 1 - 0
bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h

@@ -28,6 +28,7 @@
 #include "nu_crypto.h"
 #include "nu_can.h"
 #include "nu_i2s.h"
+#include "nu_usbd.h"
 
 #include "nu_sys.h"
 

+ 1 - 0
bsp/nuvoton/libraries/nuc980/README.md

@@ -16,6 +16,7 @@
 | QSPI | RT_Device_Class_SPIBUS | ***qspi[0]*** |
 | RTC | RT_Device_Class_RTC | ***rtc*** |
 | PWM | RT_Device_Class_Miscellaneous (PWM) | ***pwm[0-1]*** |
+| USBD | RT_Device_Class_USBDevice | ***usbd*** |
 | SC (UART function) | RT_Device_Class_Char | ***scuart[0-1]*** |
 | SDH | RT_Device_Class_Block | ***sdh[0-1]*** |
 | SPI | RT_Device_Class_SPIBUS | ***spi[0-1]*** |

+ 6 - 15
bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig

@@ -628,24 +628,15 @@ config SOC_SERIES_NUC980
         default n
 
     config BSP_USING_USBD
-        bool "Enable Full-Speed USB Device Controller(USBD)"
-        select RT_USING_USB_DEVICE
-
-    config BSP_USING_HSUSBD
-        bool "Enable High-Speed USB Device Controller(HSUSBD)"
+        bool "Enable USB Device Controller(USBD)"
         select RT_USING_USB_DEVICE
 
     config BSP_USING_USBH
-        bool "Enable Full-Speed USB Host Controller(USBH)"
-        select RT_USING_USB_HOST
-        select RT_USBH_MSTORAGE
-
-    config BSP_USING_HSUSBH
-        bool "Enable High-Speed USB Host Controller(HSUSBH)"
+        bool "Enable USB Host Controller(USBH)"
         select RT_USING_USB_HOST
         select RT_USBH_MSTORAGE
 
-    config BSP_USING_HSOTG
-        bool "Enable High-Speed USB On-The-Go(HSOTG)"
-        select BSP_USING_HSUSBH
-        select BSP_USING_HSUSBD
+    config BSP_USING_OTG
+        bool "Enable USB On-The-Go(OTG)"
+        select BSP_USING_USBH
+        select BSP_USING_USBD

+ 1 - 22
bsp/nuvoton/libraries/nuc980/rtt_port/SConscript

@@ -9,27 +9,6 @@ CPPPATH = [cwd]
 group = []
 
 # USB driver constrain
-if GetDepend('BOARD_USING_HSUSBD') and ( GetDepend('BSP_USING_USBD') or GetDepend('BSP_USING_HSUSBH') or GetDepend('BSP_USING_HSOTG') ):
-    print 'Sorry, wrong selection.'
-    print '[Hint] You already select BOARD_USING_HSUSBD. Please de-select BSP_USING_USBD, BSP_USING_HSUSBH and BSP_USING_HSOTG options.'
-    sys.exit(1)
-elif GetDepend('BOARD_USING_HSUSBD_USBH') and ( GetDepend('BSP_USING_USBD') or GetDepend('BSP_USING_HSUSBH') or GetDepend('BSP_USING_HSOTG') ):
-    print 'Sorry, wrong selection.'
-    print '[Hint] You already select BOARD_USING_HSUSBD_USBH. Please de-select BSP_USING_USBD, BSP_USING_HSUSBH and BSP_USING_HSOTG options.'
-    sys.exit(1)
-elif GetDepend('BOARD_USING_HSUSBH') and ( GetDepend('BSP_USING_USBH') or GetDepend('BSP_USING_HSUSBD') or GetDepend('BSP_USING_HSOTG') ):
-    print 'Sorry, wrong selection.'
-    print '[Hint] You already select BOARD_USING_HSUSBH. Please de-select BSP_USING_USBH, BSP_USING_HSUSBD and BSP_USING_HSOTG options.'
-    sys.exit(1)
-elif GetDepend('BOARD_USING_HSUSBH_USBD') and ( GetDepend('BSP_USING_USBH') or GetDepend('BSP_USING_HSUSBD') or GetDepend('BSP_USING_HSOTG') ):
-    print 'Sorry, wrong selection.'
-    print '[Hint] You already select BOARD_USING_HSUSBH_USBD. Please de-select BSP_USING_USBH, BSP_USING_HSUSBD and BSP_USING_HSOTG options.'
-    sys.exit(1)
-elif GetDepend('BOARD_USING_HSOTG') and ( GetDepend('BSP_USING_USBD') or GetDepend('BSP_USING_USBH') ):
-    print 'Sorry, wrong selection.'
-    print '[Hint] You already select BOARD_USING_HSOTG. Please de-select BSP_USING_USBD and BSP_USING_USBH options.'
-    sys.exit(1)
-else:
-    group = DefineGroup('nuc980_rttport', src, depend = [''], CPPPATH = CPPPATH)
+group = DefineGroup('nuc980_rttport', src, depend = [''], CPPPATH = CPPPATH)
 
 Return('group')

+ 3 - 3
bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c

@@ -192,13 +192,13 @@ static void nu_can_isr(int vector, void *param)
     /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/
     else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32)
     {
-        /*Message RAM 0~15 for CAN Tx using*/
-        if (u32IIDRstatus <= 16)
+        /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/
+        if (u32IIDRstatus <= RX_MSG_ID_INDEX)
         {
             //rt_kprintf("[%s-Tx]IntId = %d\n", psNuCAN->name, u32IIDRstatus);
             rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE);
         }
-        else /*Message RAM 16~31 for CAN Rx using*/
+        else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/
         {
             //rt_kprintf("[%s-Rx]IntId = %d\n",  psNuCAN->name, u32IIDRstatus);
             rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8)));

+ 3 - 3
bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c

@@ -590,6 +590,9 @@ static int rt_hw_nu_emac_init(void)
     rt_err_t ret = RT_EOK;
     char szTmp[32];
 
+    /* MDC CLK divider */
+    outpw(REG_CLK_DIVCTL8, (inpw(REG_CLK_DIVCTL8) & ~0xFF) | 0xA0);
+
     for (i = (EMAC_START + 1); i < EMAC_CNT; i++)
     {
         nu_emac_t psNuEMAC = (nu_emac_t)&nu_emac_arr[i];
@@ -624,9 +627,6 @@ static int rt_hw_nu_emac_init(void)
         RT_ASSERT(ret == RT_EOK);
     }
 
-    /* MDC CLK divider */
-    outpw(REG_CLK_DIVCTL8, (inpw(REG_CLK_DIVCTL8) & ~0xFF) | 0xA0);
-
     return 0;
 }
 

+ 0 - 2
bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c

@@ -217,8 +217,6 @@ void machine_shutdown(void)
     /* Unlock */
     SYS_UnlockReg();
 
-    // TODO
-
     while (1);
 }
 

+ 909 - 0
bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbd.c

@@ -0,0 +1,909 @@
+/**************************************************************************//**
+*
+* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
+*
+* SPDX-License-Identifier: Apache-2.0
+*
+* Change Logs:
+* Date            Author           Notes
+* 2020-12-25      Wayne            First version
+*
+******************************************************************************/
+
+
+#include <rtconfig.h>
+
+#if defined(BSP_USING_USBD)
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <string.h>
+#include "NuMicro.h"
+#include <nu_bitutil.h>
+#include "drv_sys.h"
+
+#define LOG_TAG         "drv.usbd"
+#define DBG_ENABLE
+#define DBG_SECTION_NAME "drv.usbd"
+#define DBG_LEVEL DBG_INFO
+#define DBG_COLOR
+#include <rtdbg.h>
+
+/* Private define ---------------------------------------------------------------*/
+#define ENABLE_FULL_SPEED_MODE_ONLY 0 /* 0: default hi-speed mode; 1: full-speed mode only */
+
+/* Define EP maximum packet size */
+
+#define CEP_MAX_PKT_SIZE        64
+#define CEP_OTHER_MAX_PKT_SIZE  64
+
+#define EPA_MAX_PKT_SIZE        512
+#define EPA_OTHER_MAX_PKT_SIZE  64
+
+#define EPB_MAX_PKT_SIZE        512
+#define EPB_OTHER_MAX_PKT_SIZE  64
+
+#define EPC_MAX_PKT_SIZE        64
+#define EPC_OTHER_MAX_PKT_SIZE  64
+
+#define EPD_MAX_PKT_SIZE        64
+#define EPD_OTHER_MAX_PKT_SIZE  64
+
+#define EPE_MAX_PKT_SIZE        512
+#define EPE_OTHER_MAX_PKT_SIZE  64
+
+#define EPF_MAX_PKT_SIZE        512
+#define EPF_OTHER_MAX_PKT_SIZE  64
+
+#define EPG_MAX_PKT_SIZE        64
+#define EPG_OTHER_MAX_PKT_SIZE  64
+
+#define EPH_MAX_PKT_SIZE        64
+#define EPH_OTHER_MAX_PKT_SIZE  64
+
+#define EPI_MAX_PKT_SIZE        512
+#define EPI_OTHER_MAX_PKT_SIZE  64
+
+#define EPJ_MAX_PKT_SIZE        512
+#define EPJ_OTHER_MAX_PKT_SIZE  64
+
+#define EPK_MAX_PKT_SIZE        64
+#define EPK_OTHER_MAX_PKT_SIZE  64
+
+#define EPL_MAX_PKT_SIZE        64
+#define EPL_OTHER_MAX_PKT_SIZE  64
+
+#define CEP_BUF_BASE    0
+#define CEP_BUF_LEN     CEP_MAX_PKT_SIZE
+
+#define EPA_BUF_BASE    (CEP_BUF_BASE + CEP_BUF_LEN)
+#define EPA_BUF_LEN     EPA_MAX_PKT_SIZE
+
+#define EPB_BUF_BASE    (EPA_BUF_BASE + EPA_BUF_LEN)
+#define EPB_BUF_LEN     EPB_MAX_PKT_SIZE
+
+#define EPC_BUF_BASE    (EPB_BUF_BASE + EPB_BUF_LEN)
+#define EPC_BUF_LEN     EPC_MAX_PKT_SIZE
+
+#define EPD_BUF_BASE    (EPC_BUF_BASE + EPC_BUF_LEN)
+#define EPD_BUF_LEN     EPD_MAX_PKT_SIZE
+
+#define EPE_BUF_BASE    (EPD_BUF_BASE + EPD_BUF_LEN)
+#define EPE_BUF_LEN     EPE_MAX_PKT_SIZE
+
+#define EPF_BUF_BASE    (EPE_BUF_BASE + EPE_BUF_LEN)
+#define EPF_BUF_LEN     EPF_MAX_PKT_SIZE
+
+#define EPG_BUF_BASE    (EPF_BUF_BASE + EPF_BUF_LEN)
+#define EPG_BUF_LEN     EPG_MAX_PKT_SIZE
+
+#define EPH_BUF_BASE    (EPG_BUF_BASE + EPG_BUF_LEN)
+#define EPH_BUF_LEN     EPH_MAX_PKT_SIZE
+
+#define EPI_BUF_BASE    (EPH_BUF_BASE + EPH_BUF_LEN)
+#define EPI_BUF_LEN     EPI_MAX_PKT_SIZE
+
+#define EPJ_BUF_BASE    (EPI_BUF_BASE + EPI_BUF_LEN)
+#define EPJ_BUF_LEN     EPJ_MAX_PKT_SIZE
+
+#define EPK_BUF_BASE    (EPJ_BUF_BASE + EPJ_BUF_LEN)
+#define EPK_BUF_LEN     EPK_MAX_PKT_SIZE
+
+#define EPL_BUF_BASE    (EPK_BUF_BASE + EPK_BUF_LEN)
+#define EPL_BUF_LEN     EPL_MAX_PKT_SIZE
+
+
+#define EPADR_SW2HW(address) ((address & USB_EPNO_MASK) - 1) /* for non-control endpoint */
+#define EPADR_HW2SW(address) ((address & USB_EPNO_MASK) + 1) /* for non-control endpoint */
+
+/* Private typedef --------------------------------------------------------------*/
+typedef struct _nu_usbd_t
+{
+    USBD_T *base;     /* REG base */
+    char *name;
+    IRQn_Type irqn;
+    E_SYS_IPRST rstidx;
+    E_SYS_IPCLK clkidx;
+    uint8_t address_tmp;    /* Keep assigned address for flow control */
+} nu_usbd_t;
+
+
+typedef struct
+{
+
+    uint32_t u32BufferBase;
+    uint32_t u32BufferLength;
+
+    uint32_t u32OtherMaxPktSize;
+
+} S_EP_CXT;
+
+
+/* Private variables ------------------------------------------------------------*/
+
+static nu_usbd_t nu_usbd =
+{
+    .base        = USBD,
+    .name        = "usbd",
+    .irqn        = IRQ_UDC,
+    .rstidx      = USBDRST,
+    .clkidx      = USBDCKEN,
+    .address_tmp = 0,
+};
+
+static struct udcd _rt_obj_udc;
+
+static S_EP_CXT _ep_cxt_pool[] =
+{
+    { EPA_BUF_BASE, EPA_BUF_LEN, EPA_OTHER_MAX_PKT_SIZE}, //EPA
+    { EPB_BUF_BASE, EPB_BUF_LEN, EPB_OTHER_MAX_PKT_SIZE}, //EPB
+    { EPC_BUF_BASE, EPC_BUF_LEN, EPC_OTHER_MAX_PKT_SIZE}, //EPC
+    { EPD_BUF_BASE, EPD_BUF_LEN, EPD_OTHER_MAX_PKT_SIZE}, //EPD
+    { EPE_BUF_BASE, EPE_BUF_LEN, EPE_OTHER_MAX_PKT_SIZE}, //EPE
+    { EPF_BUF_BASE, EPF_BUF_LEN, EPF_OTHER_MAX_PKT_SIZE}, //EPF
+    { EPG_BUF_BASE, EPG_BUF_LEN, EPG_OTHER_MAX_PKT_SIZE}, //EPG
+    { EPH_BUF_BASE, EPH_BUF_LEN, EPH_OTHER_MAX_PKT_SIZE}, //EPH
+    { EPI_BUF_BASE, EPI_BUF_LEN, EPI_OTHER_MAX_PKT_SIZE}, //EPI
+    { EPJ_BUF_BASE, EPJ_BUF_LEN, EPJ_OTHER_MAX_PKT_SIZE}, //EPJ
+    { EPK_BUF_BASE, EPK_BUF_LEN, EPK_OTHER_MAX_PKT_SIZE}, //EPK
+    { EPL_BUF_BASE, EPL_BUF_LEN, EPL_OTHER_MAX_PKT_SIZE}  //EPL
+};
+
+static struct ep_id _ep_pool[] =
+{
+    {0x0,               USB_EP_ATTR_CONTROL,     USB_DIR_INOUT, CEP_MAX_PKT_SIZE,    ID_ASSIGNED  },
+
+    {EPADR_HW2SW(EPA),  USB_EP_ATTR_BULK,        USB_DIR_IN,    EPA_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPB),  USB_EP_ATTR_BULK,        USB_DIR_OUT,   EPB_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPC),  USB_EP_ATTR_INT,         USB_DIR_IN,    EPC_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPD),  USB_EP_ATTR_INT,         USB_DIR_OUT,   EPD_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPE),  USB_EP_ATTR_BULK,        USB_DIR_IN,    EPE_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPF),  USB_EP_ATTR_BULK,        USB_DIR_OUT,   EPF_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPG),  USB_EP_ATTR_INT,         USB_DIR_IN,    EPG_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPH),  USB_EP_ATTR_INT,         USB_DIR_OUT,   EPH_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPI),  USB_EP_ATTR_BULK,        USB_DIR_IN,    EPE_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPJ),  USB_EP_ATTR_BULK,        USB_DIR_OUT,   EPF_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPK),  USB_EP_ATTR_INT,         USB_DIR_IN,    EPG_MAX_PKT_SIZE,    ID_UNASSIGNED},
+    {EPADR_HW2SW(EPL),  USB_EP_ATTR_INT,         USB_DIR_OUT,   EPH_MAX_PKT_SIZE,    ID_UNASSIGNED},
+
+    {0xFF,              USB_EP_ATTR_TYPE_MASK,   USB_DIR_MASK,  0,                   ID_ASSIGNED  },
+};
+
+
+static void _nu_ep_partition_set(int isHighSpeed)
+{
+    int i;
+
+    for (i = 0; i < USBD_MAX_EP; i++)
+    {
+        uint32_t u32NuEPTypeDef = 0x0;
+        uint32_t u32NuEPDirDef = 0x0;
+
+        if (_ep_pool[i + 1].type == USB_EP_ATTR_BULK)
+            u32NuEPTypeDef =  USB_EP_CFG_TYPE_BULK;
+        else if (_ep_pool[i + 1].type == USB_EP_ATTR_INT)
+            u32NuEPTypeDef =  USB_EP_CFG_TYPE_INT;
+        else
+            continue;
+
+        if (_ep_pool[i + 1].dir == USB_DIR_IN)
+            u32NuEPDirDef =  USB_EP_CFG_DIR_IN;
+        else if (_ep_pool[i + 1].dir == USB_DIR_OUT)
+            u32NuEPDirDef =  USB_EP_CFG_DIR_OUT;
+        else
+            continue;
+
+        USBD_SetEpBufAddr(i, _ep_cxt_pool[i].u32BufferBase, _ep_cxt_pool[i].u32BufferLength);
+        if (isHighSpeed)
+            USBD_SET_MAX_PAYLOAD(i, _ep_cxt_pool[i].u32BufferLength);
+        else
+            USBD_SET_MAX_PAYLOAD(i, _ep_cxt_pool[i].u32OtherMaxPktSize);
+
+        USBD_ConfigEp(i, EPADR_HW2SW(i), u32NuEPTypeDef, u32NuEPDirDef);
+
+        if (u32NuEPDirDef ==  USB_EP_CFG_DIR_OUT)
+            USBD_ENABLE_EP_INT(i, USBD_EPINTEN_RXPKIEN_Msk);
+
+    } //for
+
+}
+
+static void _nu_ep_partition(void)
+{
+    /* Configure USB controller */
+    /* Enable USB BUS, CEP and EPA ~ EPH global interrupt */
+    USBD_ENABLE_USB_INT(USBD_GINTEN_USBIE_Msk
+                        | USBD_GINTEN_CEPIE_Msk
+                        | USBD_GINTEN_EPAIE_Msk
+                        | USBD_GINTEN_EPBIE_Msk
+                        | USBD_GINTEN_EPCIE_Msk
+                        | USBD_GINTEN_EPDIE_Msk
+                        | USBD_GINTEN_EPEIE_Msk
+                        | USBD_GINTEN_EPFIE_Msk
+                        | USBD_GINTEN_EPGIE_Msk
+                        | USBD_GINTEN_EPHIE_Msk
+                        | USBD_GINTEN_EPIIE_Msk
+                        | USBD_GINTEN_EPJIE_Msk
+                        | USBD_GINTEN_EPKIE_Msk
+                        | USBD_GINTEN_EPLIE_Msk);
+
+    /* Enable BUS interrupt */
+    USBD_ENABLE_BUS_INT(USBD_BUSINTEN_DMADONEIEN_Msk
+                        | USBD_BUSINTEN_RESUMEIEN_Msk
+                        | USBD_BUSINTEN_RSTIEN_Msk
+                        | USBD_BUSINTEN_VBUSDETIEN_Msk);
+    /* Reset Address to 0 */
+    USBD_SET_ADDR(0);
+
+    /*****************************************************/
+    /* Control endpoint */
+    USBD_SetEpBufAddr(CEP, CEP_BUF_BASE, CEP_BUF_LEN);
+    USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk
+                        | USBD_CEPINTEN_STSDONEIEN_Msk);
+
+    _nu_ep_partition_set(1);
+}
+
+static void NU_SetupStageCallback(nu_usbd_t *nu_udc)
+{
+    struct urequest setup_packet;
+
+    /* Setup packet process */
+    setup_packet.request_type   = (uint8_t)(nu_udc->base->SETUP1_0 & 0xfful);
+    setup_packet.bRequest       = (uint8_t)((nu_udc->base->SETUP1_0 >> 8) & 0xfful);
+    setup_packet.wValue         = (uint16_t)  nu_udc->base->SETUP3_2;
+    setup_packet.wIndex         = (uint16_t)  nu_udc->base->SETUP5_4;
+    setup_packet.wLength        = (uint16_t)  nu_udc->base->SETUP7_6;
+
+    rt_usbd_ep0_setup_handler(&_rt_obj_udc, (struct urequest *)&setup_packet);
+}
+
+static rt_err_t _ep_set_stall(rt_uint8_t address)
+{
+
+    if (address  & USB_EPNO_MASK)
+    {
+        USBD_SetEpStall(EPADR_SW2HW(address));
+    }
+    else
+    {
+        /* Not support. Reply STALL. */
+        USBD_SET_CEP_STATE(USBD_CEPCTL_STALLEN_Msk);
+        USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk);
+        USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk);
+    }
+    return RT_EOK;
+}
+
+static rt_err_t _ep_clear_stall(rt_uint8_t address)
+{
+    if (address  & USB_EPNO_MASK)
+    {
+        USBD_ClearEpStall(EPADR_SW2HW(address));
+    }
+
+    return RT_EOK;
+}
+
+
+static rt_err_t _set_address(rt_uint8_t address)
+{
+    if (0 != address)
+    {
+        nu_usbd.address_tmp = address;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t _set_config(rt_uint8_t address)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _ep_enable(uep_t ep)
+{
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+
+    USBD->EP[EPADR_SW2HW(ep->ep_desc->bEndpointAddress)].EPRSPCTL = USB_EP_RSPCTL_TOGGLE;
+    USBD->EP[EPADR_SW2HW(ep->ep_desc->bEndpointAddress)].EPCFG |= USB_EP_CFG_VALID;
+
+    return RT_EOK;
+}
+
+static rt_err_t _ep_disable(uep_t ep)
+{
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+    USBD->EP[EPADR_SW2HW(ep->ep_desc->bEndpointAddress)].EPCFG &= ~USB_EP_CFG_VALID;
+
+    return RT_EOK;
+}
+
+static rt_err_t _ep0_send_status(void)
+{
+    /* Status Stage */
+    USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk
+                          | USBD_CEPINTSTS_SETUPPKIF_Msk);
+
+    USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk);
+
+    USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR);
+
+    return RT_EOK;
+}
+
+__STATIC_INLINE void nu_buffer_cpy(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    rt_uint32_t i, cnt;
+    rt_uint32_t *_buf_word;
+    rt_uint8_t  *_buf_byte;
+
+    _buf_word = (rt_uint32_t *)buffer;
+    cnt = size >> 2;
+    _buf_byte = (rt_uint8_t *)((rt_uint8_t *)buffer + (cnt * 4));
+
+    if ((address & USB_EPNO_MASK)) //EPs
+    {
+        if (address &  USB_DIR_IN) //IN
+        {
+            /* Non-control endpoint IN*/
+            for (i = 0; i < cnt; i++)
+            {
+                USBD->EP[EPADR_SW2HW(address)].ep.EPDAT = _buf_word[i];
+            }
+
+            for (i = 0ul; i < (size % 4ul); i++)
+                USBD->EP[EPADR_SW2HW(address)].ep.EPDAT_BYTE = _buf_byte[i];
+        }
+        else //OUT
+        {
+            for (i = 0; i < cnt; i++)
+            {
+                _buf_word[i] = USBD->EP[EPADR_SW2HW(address)].ep.EPDAT;
+            }
+
+            for (i = 0ul; i < (size % 4ul); i++)
+                _buf_byte[i] = USBD->EP[EPADR_SW2HW(address)].ep.EPDAT_BYTE;
+        }
+    }
+    else //Control
+    {
+        if (address &  USB_DIR_IN) //IN
+        {
+            for (i = 0; i < cnt; i++)
+            {
+                USBD->cep.CEPDAT = _buf_word[i];
+            }
+
+            for (i = 0ul; i < (size % 4ul); i++)
+                USBD->cep.CEPDAT_BYTE = _buf_byte[i];
+
+        }
+        else //OUT
+        {
+            for (i = 0; i < cnt; i++)
+            {
+                _buf_word[i] = USBD->cep.CEPDAT;
+            }
+
+            for (i = 0ul; i < (size % 4ul); i++)
+                _buf_byte[i] = USBD->cep.CEPDAT_BYTE;
+        }
+    }
+}
+
+static rt_size_t _ep_read(rt_uint8_t address, void *buffer)
+{
+    rt_size_t size  = 0;
+
+    RT_ASSERT(!(address & USB_DIR_IN));
+
+    if ((address & USB_EPNO_MASK))
+    {
+        RT_ASSERT(buffer != RT_NULL);
+        size = USBD->EP[EPADR_SW2HW(address)].EPDATCNT & 0xffff;
+        nu_buffer_cpy(address, buffer, size);
+    }
+    else     //control transfer
+    {
+
+        size =  USBD->CEPRXCNT & 0xffff;
+        if (size)
+        {
+            RT_ASSERT(_rt_obj_udc.stage == STAGE_DOUT);
+            nu_buffer_cpy(address, buffer, size);
+        }
+
+        _ep0_send_status();
+    }
+
+    return size;
+}
+
+static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    RT_ASSERT(!(address & USB_DIR_IN));
+
+    if ((address & USB_EPNO_MASK))
+    {
+        USBD_ENABLE_EP_INT(EPADR_SW2HW(address),
+                           USBD_EPINTEN_RXPKIEN_Msk);
+    }
+    else //control transfer
+    {
+        if (size)
+        {
+            RT_ASSERT(_rt_obj_udc.stage == STAGE_DOUT);
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_OUTTKIEN_Msk);
+        }
+        else
+        {
+
+            RT_ASSERT(_rt_obj_udc.stage == STAGE_STATUS_OUT);
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk
+                                  | USBD_CEPINTSTS_STSDONEIF_Msk);
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk
+                                | USBD_CEPINTEN_STSDONEIEN_Msk);
+            USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR);
+        }
+
+    }
+
+    return size;
+}
+
+static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+
+    RT_ASSERT((address & USB_DIR_IN));
+
+    if (!(address & USB_EPNO_MASK)) //control transfer
+    {
+        if (size)
+        {
+            nu_buffer_cpy(address, buffer, size);
+            USBD_START_CEP_IN(size);
+        }
+        else//zero length
+        {
+            USBD_SET_CEP_STATE(USB_CEPCTL_ZEROLEN);
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk
+                                  | USBD_CEPINTSTS_SETUPPKIF_Msk);
+
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk
+                                | USBD_CEPINTEN_STSDONEIEN_Msk);
+        }
+
+        if (_rt_obj_udc.stage == STAGE_DIN)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk);
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_TXPKIEN_Msk);
+        }
+        else if (_rt_obj_udc.stage == STAGE_DOUT)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_RXPKIF_Msk);
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_RXPKIEN_Msk);
+        }
+    }
+    else
+    {
+        /* Non-control endpoint IN*/
+        nu_buffer_cpy(address, buffer, size);
+        USBD->EP[EPADR_SW2HW(address)].EPRSPCTL = USB_EP_RSPCTL_SHORTTXEN; // packet end
+        USBD->EP[EPADR_SW2HW(address)].EPTXCNT = size;
+
+        if ((USBD->EP[EPADR_SW2HW(address)].EPCFG & USBD_EPCFG_EPTYPE_Msk) == USB_EP_CFG_TYPE_INT)
+        {
+            USBD_ENABLE_EP_INT(EPADR_SW2HW(address), USBD_EPINTEN_INTKIEN_Msk);  //for interrupt transfer timing
+        }
+        else
+        {
+            USBD_ENABLE_EP_INT(EPADR_SW2HW(address), USBD_EPINTEN_TXPKIEN_Msk);  //for bulk transfer  timing
+        }
+    }
+
+    return size;
+}
+
+static rt_err_t _suspend(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _wakeup(void)
+{
+    return RT_EOK;
+}
+
+static void nu_usbd_isr(int vector, void *param)
+{
+    __IO rt_uint32_t IrqStL, IrqSt;
+    int i;
+    int IrqStAllEP;
+
+    IrqStL = USBD->GINTSTS & USBD->GINTEN;    /* get interrupt status */
+
+    if (!IrqStL)    return;
+
+    /* USB interrupt */
+    if (IrqStL & USBD_GINTSTS_USBIF_Msk)
+    {
+        IrqSt = USBD->BUSINTSTS & USBD->BUSINTEN;
+
+        if (IrqSt & USBD_BUSINTSTS_SOFIF_Msk)
+        {
+            USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_SOFIF_Msk);
+            rt_usbd_sof_handler(&_rt_obj_udc);
+        }
+        if (IrqSt & USBD_BUSINTSTS_RSTIF_Msk)
+        {
+            /* Reset USB device address */
+            USBD_SET_ADDR(0ul);
+
+            USBD_ResetDMA();
+            for (i = 0; i < USBD_MAX_EP; i++)
+                USBD->EP[i].EPRSPCTL = USBD_EPRSPCTL_FLUSH_Msk;
+
+            if (USBD->OPER & 0x04)    /* high speed */
+            {
+                LOG_I("-High Speed-");
+                _nu_ep_partition_set(1);
+            }
+            else                        /* full speed */
+            {
+                LOG_I("-Full Speed-");
+                _nu_ep_partition_set(0);
+            }
+
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk);
+            USBD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk
+                                | USBD_BUSINTEN_RESUMEIEN_Msk
+                                | USBD_BUSINTEN_SUSPENDIEN_Msk
+                                | USBD_BUSINTEN_VBUSDETIEN_Msk);
+            USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_RSTIF_Msk);
+            USBD_CLR_CEP_INT_FLAG(0x1ffc);
+
+            for (i = 0ul; i < USBD_MAX_EP; i++)
+            {
+                if ((USBD->EP[i].EPCFG & 0x1ul) == 0x1ul)
+                {
+                    USBD->EP[i].EPRSPCTL = USB_EP_RSPCTL_TOGGLE;
+                }
+            }
+            rt_usbd_reset_handler(&_rt_obj_udc);
+            USBD_ENABLE_USB();
+        }
+
+        if (IrqSt & USBD_BUSINTSTS_RESUMEIF_Msk)
+        {
+            LOG_I("-Resume-");
+            USBD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_SUSPENDIEN_Msk);
+            USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_RESUMEIF_Msk);
+        }
+
+        if (IrqSt & USBD_BUSINTSTS_SUSPENDIF_Msk)
+        {
+            LOG_I("-Suspend-");
+            USBD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_RESUMEIEN_Msk | USBD_BUSINTEN_VBUSDETIEN_Msk);
+            USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_SUSPENDIF_Msk);
+        }
+
+        if (IrqSt & USBD_BUSINTSTS_HISPDIF_Msk)
+        {
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk);
+            USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_HISPDIF_Msk);
+        }
+
+        if (IrqSt & USBD_BUSINTSTS_DMADONEIF_Msk)
+        {
+            USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_DMADONEIF_Msk);
+
+            if (!(USBD->DMACTL & USBD_DMACTL_DMARD_Msk))
+            {
+                USBD_ENABLE_EP_INT(EPD, USBD_EPINTEN_RXPKIEN_Msk);
+            }
+        }
+
+        if (IrqSt & USBD_BUSINTSTS_PHYCLKVLDIF_Msk)
+        {
+            USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_PHYCLKVLDIF_Msk);
+        }
+
+        if (IrqSt & USBD_BUSINTSTS_VBUSDETIF_Msk)
+        {
+            if (USBD_IS_ATTACHED())
+            {
+                LOG_I("PLUG IN");
+                /* USB Plug In */
+                USBD_ENABLE_USB();
+                rt_usbd_connect_handler(&_rt_obj_udc);
+            }
+            else
+            {
+                LOG_I("Un-Plug");
+                /* USB Un-plug */
+                USBD_DISABLE_USB();
+                rt_usbd_disconnect_handler(&_rt_obj_udc);
+            }
+            USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_VBUSDETIF_Msk);
+        }
+    } //if (IrqStL & USBD_GINTSTS_USBIF_Msk)
+
+    /* Control Transfer */
+    if (IrqStL & USBD_GINTSTS_CEPIF_Msk)
+    {
+        IrqSt = USBD->CEPINTSTS & USBD->CEPINTEN;
+
+        if (IrqSt & USBD_CEPINTSTS_SETUPTKIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPTKIF_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_SETUPPKIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk);
+            NU_SetupStageCallback(&nu_usbd);
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk
+                                  | USBD_CEPINTSTS_RXPKIF_Msk
+                                  | USBD_CEPINTSTS_STSDONEIF_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_OUTTKIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_OUTTKIF_Msk);
+            rt_usbd_ep0_out_handler(&_rt_obj_udc, 0);
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_RXPKIEN_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_INTKIF_Msk)
+        {
+            USBD_ENABLE_CEP_INT(0);
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk);
+            rt_usbd_ep0_in_handler(&_rt_obj_udc);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_PINGIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_PINGIF_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_TXPKIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk
+                                  | USBD_CEPINTSTS_SETUPPKIF_Msk
+                                  | USBD_CEPINTSTS_STSDONEIF_Msk);
+
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_INTKIEN_Msk
+                                | USBD_CEPINTEN_SETUPPKIEN_Msk
+                                | USBD_CEPINTEN_STSDONEIEN_Msk);
+
+            USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_RXPKIF_Msk)
+        {
+
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk
+                                  | USBD_CEPINTSTS_STSDONEIF_Msk
+                                  | USBD_CEPINTSTS_RXPKIF_Msk);
+            USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR);
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk
+                                | USBD_CEPINTEN_STSDONEIEN_Msk
+                                | USBD_CEPINTEN_RXPKIEN_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_NAKIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_NAKIF_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_STALLIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STALLIF_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_ERRIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_ERRIF_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_STSDONEIF_Msk)
+        {
+
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk | USBD_CEPINTSTS_SETUPPKIF_Msk);
+            USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk);
+
+            if ((USBD_GET_ADDR() == 0)
+                    && ((uint8_t)((nu_usbd.base->SETUP1_0 >> 8) & 0xfful) == SET_ADDRESS))
+            {
+                USBD_SET_ADDR(nu_usbd.address_tmp);
+                LOG_I("SET ADDR: 0x%02x", nu_usbd.address_tmp);
+                nu_usbd.address_tmp = 0;
+
+            }
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_BUFFULLIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_BUFFULLIF_Msk);
+            return;
+        }
+
+        if (IrqSt & USBD_CEPINTSTS_BUFEMPTYIF_Msk)
+        {
+            USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_BUFEMPTYIF_Msk);
+            return;
+        }
+
+    } //if (IrqStL & USBD_GINTSTS_CEPIF_Msk)
+
+    // For End-points
+    IrqStAllEP = (IrqStL >> USBD_GINTSTS_EPAIF_Pos) & ((1 << USBD_MAX_EP) - 1);
+
+    // Find the position of first '1' in allch_sts.
+    while ((i = nu_ctz(IrqStAllEP)) != 32)
+    {
+        IrqSt = USBD->EP[i].EPINTSTS & USBD->EP[i].EPINTEN;
+
+        if (_ep_pool[i + 1].dir == USB_DIR_IN)
+            USBD_ENABLE_EP_INT(i, 0);
+
+        USBD_CLR_EP_INT_FLAG(i, IrqSt);
+
+        rt_usbd_ep_in_handler(&_rt_obj_udc, _ep_pool[i + 1].dir | EPADR_HW2SW(i), 0);
+
+        IrqStAllEP &= ~(1 << i);
+    }
+}
+
+static rt_err_t _init(rt_device_t device)
+{
+#if !defined(BSP_USING_OTG)
+    uint32_t volatile i;
+
+    /* Initialize USB PHY */
+    SYS_UnlockReg();
+    SYS->USBPHY &= ~SYS_USBPHY_HSUSBROLE_Msk;    /* select USBD */
+
+    /* Enable USB PHY */
+    SYS->USBPHY = (SYS->USBPHY & ~(SYS_USBPHY_HSUSBROLE_Msk | SYS_USBPHY_HSUSBACT_Msk)) | SYS_USBPHY_HSUSBEN_Msk;
+
+    for (i = 0; i < 0x1000; i++)
+        __NOP();  // delay > 10 us
+
+    SYS->USBPHY |= SYS_USBPHY_HSUSBACT_Msk;
+    SYS_LockReg();
+#endif
+
+    nu_sys_ipclk_enable(nu_usbd.clkidx);
+
+    nu_sys_ip_reset(nu_usbd.rstidx);
+
+    /* USBD Open */
+    USBD->PHYCTL |= (USBD_PHYCTL_PHYEN_Msk | USBD_PHYCTL_DPPUEN_Msk);
+    while (1)
+    {
+        USBD->EP[EPA].EPMPS = 0x20ul;
+        if (USBD->EP[EPA].EPMPS == 0x20ul)
+        {
+            break;
+        }
+    }
+
+    /* Force SE0 */
+    USBD_SET_SE0();
+
+    _nu_ep_partition();
+
+#if ENABLE_FULL_SPEED_MODE_ONLY
+    USBD->OPER &= ~USBD_OPER_HISPDEN_Msk;
+#else
+    USBD->OPER |= USBD_OPER_HISPDEN_Msk;
+#endif
+
+    /* Install USBD interrupt */
+    rt_hw_interrupt_install(nu_usbd.irqn, nu_usbd_isr, &nu_usbd, nu_usbd.name);
+    rt_hw_interrupt_set_priority(nu_usbd.irqn, IRQ_LEVEL_1);
+
+    /* Enable USBD interrupt */
+    rt_hw_interrupt_umask(nu_usbd.irqn);
+
+    /* Start transaction */
+    USBD_Start();
+    return RT_EOK;
+}
+
+const static struct udcd_ops _udc_ops =
+{
+    _set_address,
+    _set_config,
+    _ep_set_stall,
+    _ep_clear_stall,
+    _ep_enable,
+    _ep_disable,
+    _ep_read_prepare,
+    _ep_read,
+    _ep_write,
+    _ep0_send_status,
+    _suspend,
+    _wakeup,
+};
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops _ops =
+{
+    _init,
+    RT_NULL,
+    RT_NULL,
+    RT_NULL,
+    RT_NULL,
+    RT_NULL,
+};
+#endif
+
+int nu_usbd_register(void)
+{
+    rt_err_t result = RT_EOK;
+
+    rt_memset((void *)&_rt_obj_udc, 0, sizeof(struct udcd));
+    _rt_obj_udc.parent.type = RT_Device_Class_USBDevice;
+
+#ifdef RT_USING_DEVICE_OPS
+    _rt_obj_udc.parent.ops = &_ops;
+#else
+    _rt_obj_udc.parent.init = _init;
+#endif
+
+    _rt_obj_udc.parent.user_data = &nu_usbd;
+    _rt_obj_udc.ops = &_udc_ops;
+
+    /* Register endpoint information */
+    _rt_obj_udc.ep_pool = _ep_pool;
+    _rt_obj_udc.ep0.id = &_ep_pool[0];
+
+#if ENABLE_FULL_SPEED_MODE_ONLY
+    _rt_obj_udc.device_is_hs = RT_FALSE; /* Enable Full-speed only */
+#else
+    _rt_obj_udc.device_is_hs = RT_TRUE; /* Support Hi-Speed */
+#endif
+
+    result = rt_device_register((rt_device_t)&_rt_obj_udc, nu_usbd.name, 0);
+    RT_ASSERT(result == RT_EOK);
+
+    return rt_usb_device_init();
+}
+INIT_DEVICE_EXPORT(nu_usbd_register);
+#endif

+ 34 - 17
bsp/nuvoton/nk-980iot/.config

@@ -109,10 +109,10 @@ CONFIG_FINSH_ARG_MAX=10
 #
 CONFIG_RT_USING_DFS=y
 CONFIG_DFS_USING_WORKDIR=y
-CONFIG_DFS_FILESYSTEMS_MAX=8
-CONFIG_DFS_FILESYSTEM_TYPES_MAX=8
+CONFIG_DFS_FILESYSTEMS_MAX=16
+CONFIG_DFS_FILESYSTEM_TYPES_MAX=16
 CONFIG_DFS_FD_MAX=64
-# CONFIG_RT_USING_DFS_MNTTABLE is not set
+CONFIG_RT_USING_DFS_MNTTABLE=y
 CONFIG_RT_USING_DFS_ELMFAT=y
 
 #
@@ -220,8 +220,29 @@ CONFIG_RT_HWCRYPTO_USING_RNG=y
 #
 # Using USB
 #
-# CONFIG_RT_USING_USB_HOST is not set
-# CONFIG_RT_USING_USB_DEVICE is not set
+CONFIG_RT_USING_USB_HOST=y
+CONFIG_RT_USBH_MSTORAGE=y
+CONFIG_UDISK_MOUNTPOINT="/"
+CONFIG_RT_USING_USB_DEVICE=y
+CONFIG_RT_USBD_THREAD_STACK_SZ=4096
+CONFIG_USB_VENDOR_ID=0x0FFE
+CONFIG_USB_PRODUCT_ID=0x0001
+CONFIG_RT_USB_DEVICE_COMPOSITE=y
+CONFIG_RT_USB_DEVICE_CDC=y
+CONFIG_RT_USB_DEVICE_NONE=y
+CONFIG_RT_USB_DEVICE_MSTORAGE=y
+# CONFIG_RT_USB_DEVICE_HID is not set
+# CONFIG_RT_USB_DEVICE_RNDIS is not set
+# CONFIG_RT_USB_DEVICE_ECM is not set
+# CONFIG_RT_USB_DEVICE_WINUSB is not set
+# CONFIG_RT_USB_DEVICE_AUDIO is not set
+CONFIG_RT_VCOM_TASK_STK_SIZE=2048
+CONFIG_RT_CDC_RX_BUFSIZE=128
+# CONFIG_RT_VCOM_TX_USE_DMA is not set
+CONFIG_RT_VCOM_SERNO="32021919830108"
+CONFIG_RT_VCOM_SER_LEN=14
+CONFIG_RT_VCOM_TX_TIMEOUT=1000
+CONFIG_RT_USB_MSTORAGE_DISK_NAME="ramdisk1"
 
 #
 # POSIX layer and C standard library
@@ -680,7 +701,7 @@ CONFIG_PKG_VI_VER="latest"
 # Nuvoton Packages Config
 #
 CONFIG_NU_PKG_USING_UTILS=y
-# CONFIG_NU_PKG_USING_DEMO is not set
+CONFIG_NU_PKG_USING_DEMO=y
 # CONFIG_NU_PKG_USING_BMX055 is not set
 # CONFIG_NU_PKG_USING_MAX31875 is not set
 # CONFIG_NU_PKG_USING_NAU88L25 is not set
@@ -779,11 +800,9 @@ CONFIG_BSP_USING_CRYPTO=y
 # CONFIG_BSP_USING_SOFT_I2C is not set
 CONFIG_BSP_USING_WDT=y
 # CONFIG_BSP_USING_EBI is not set
-# CONFIG_BSP_USING_USBD is not set
-# CONFIG_BSP_USING_HSUSBD is not set
-# CONFIG_BSP_USING_USBH is not set
-# CONFIG_BSP_USING_HSUSBH is not set
-# CONFIG_BSP_USING_HSOTG is not set
+CONFIG_BSP_USING_USBD=y
+CONFIG_BSP_USING_USBH=y
+CONFIG_BSP_USING_OTG=y
 
 #
 # On-board Peripheral Drivers
@@ -793,12 +812,10 @@ CONFIG_BOARD_USING_IP101GR=y
 CONFIG_BOARD_USING_NAU8822=y
 CONFIG_BOARD_USING_STORAGE_SDCARD=y
 CONFIG_BOARD_USING_STORAGE_SPIFLASH=y
-CONFIG_BOARD_USING_USB_NONE=y
-# CONFIG_BOARD_USING_HSUSBD is not set
-# CONFIG_BOARD_USING_HSUSBD_USBH is not set
-# CONFIG_BOARD_USING_HSUSBH is not set
-# CONFIG_BOARD_USING_HSUSBH_USBD is not set
-# CONFIG_BOARD_USING_HSOTG is not set
+# CONFIG_BOARD_USING_USB_NONE is not set
+# CONFIG_BOARD_USING_USB_HOST is not set
+# CONFIG_BOARD_USING_USB_OTG is not set
+CONFIG_BOARD_USING_USB_OTG_HOST=y
 
 #
 # Board extended module drivers

+ 3 - 1
bsp/nuvoton/nk-980iot/README.md

@@ -42,8 +42,10 @@ Nuvoton Technology provides industrial IoT development platform using NUC980DK61
 |Button |  | Supported |
 |LEDs |  | Supported |
 |Audio Codec | NAU8822, Supports MIC and earphone | Supported |
+|USB Device | VCOM + MStorage | Supported |
+|2xUSB Host | MStorage | Not ready |
 |SPI NAND flash | W25N01GVZE1G | Not ready |
-|Virtual COM | For console | Ready.(Need to install VCOM driver) |
+|VCOM | For console | Ready.(Need to install VCOM driver) |
 
 ## 2. Supported compiler
 Support GCC, MDK4 and MDK5 IDE/compilers. More information of these compiler version as following:

+ 65 - 14
bsp/nuvoton/nk-980iot/applications/mnt.c

@@ -32,6 +32,7 @@
 
 #if defined(PKG_USING_RAMDISK)
     #define RAMDISK_NAME         "ramdisk0"
+    #define RAMDISK_UDC          "ramdisk1"
     #define MOUNT_POINT_RAMDISK0 "/"
 #endif
 
@@ -40,8 +41,43 @@
     #define MOUNT_POINT_SPIFLASH0 "/mnt/"PARTITION_NAME_FILESYSTEM
 #endif
 
+#ifdef RT_USING_DFS_MNTTABLE
+
+/*
+const char   *device_name;
+const char   *path;
+const char   *filesystemtype;
+unsigned long rwflag;
+const void   *data;
+*/
+
+const struct dfs_mount_tbl mount_table[] =
+{
+    { RAMDISK_UDC, "/ramdisk_udc", "elm", 0, RT_NULL },
+    {0},
+};
+#endif
+
+
 #if defined(PKG_USING_RAMDISK)
 
+extern rt_err_t ramdisk_init(const char *dev_name, rt_uint8_t *disk_addr, rt_size_t block_size, rt_size_t num_block);
+int ramdisk_device_init(void)
+{
+    rt_err_t result = RT_EOK;
+
+    /* Create a 8MB RAMDISK */
+    result = ramdisk_init(RAMDISK_NAME, NULL, 512, 2 * 8192);
+    RT_ASSERT(result == RT_EOK);
+
+    /* Create a 4MB RAMDISK */
+    result = ramdisk_init(RAMDISK_UDC, NULL, 512, 2 * 4096);
+    RT_ASSERT(result == RT_EOK);
+
+    return 0;
+}
+INIT_DEVICE_EXPORT(ramdisk_device_init);
+
 /* Recursive mkdir */
 static int mkdir_p(const char *dir, const mode_t mode)
 {
@@ -115,11 +151,19 @@ exit_mkdir_p:
 /* Initialize the filesystem */
 int filesystem_init(void)
 {
+    rt_err_t result = RT_EOK;
+
     // ramdisk as root
-    if (rt_device_find(RAMDISK_NAME))
+    if (!rt_device_find(RAMDISK_NAME))
+    {
+        LOG_E("cannot find %s device", RAMDISK_NAME);
+        goto exit_filesystem_init;
+    }
+    else
     {
-        // format the ramdisk
-        dfs_mkfs("elm", RAMDISK_NAME);
+        /* Format these ramdisk */
+        result = (rt_err_t)dfs_mkfs("elm", RAMDISK_NAME);
+        RT_ASSERT(result == RT_EOK);
 
         /* mount ramdisk0 as root directory */
         if (dfs_mount(RAMDISK_NAME, "/", "elm", 0, RT_NULL) == 0)
@@ -127,6 +171,7 @@ int filesystem_init(void)
             LOG_I("ramdisk mounted on \"/\".");
 
             /* now you can create dir dynamically. */
+            mkdir_p("/ramdisk_udc", 0x777);
             mkdir_p("/mnt", 0x777);
             mkdir_p("/cache", 0x777);
             mkdir_p("/download", 0x777);
@@ -137,21 +182,27 @@ int filesystem_init(void)
         else
         {
             LOG_E("root folder creation failed!\n");
+            goto exit_filesystem_init;
         }
-        return RT_EOK;
     }
-    LOG_E("cannot find %s device", RAMDISK_NAME);
-    return -RT_ERROR;
-}
-INIT_ENV_EXPORT(filesystem_init);
 
-extern rt_err_t ramdisk_init(const char *dev_name, rt_uint8_t *disk_addr, rt_size_t block_size, rt_size_t num_block);
-int ramdisk_device_init(void)
-{
-    /* Create a 8MB RAMDISK */
-    return (int)ramdisk_init(RAMDISK_NAME, NULL, 512, 2 * 8192);
+    if (!rt_device_find(RAMDISK_UDC))
+    {
+        LOG_E("cannot find %s device", RAMDISK_UDC);
+        goto exit_filesystem_init;
+    }
+    else
+    {
+        /* Format these ramdisk */
+        result = (rt_err_t)dfs_mkfs("elm", RAMDISK_UDC);
+        RT_ASSERT(result == RT_EOK);
+    }
+
+exit_filesystem_init:
+
+    return -result;
 }
-INIT_DEVICE_EXPORT(ramdisk_device_init);
+INIT_ENV_EXPORT(filesystem_init);
 #endif
 
 #if defined(BOARD_USING_STORAGE_SPIFLASH)

+ 13 - 26
bsp/nuvoton/nk-980iot/board/Kconfig

@@ -39,44 +39,31 @@ menu "Hardware Drivers Config"
             default y
 
         choice
-            prompt "Select FS/HS USB Ports"
+            prompt "Select HS USB Ports"
 
             config BOARD_USING_USB_NONE
                 bool "Without any USB function"
                 help
                     Choose this option if you need not USB functions.
 
-            config BOARD_USING_HSUSBD
-                select BSP_USING_HSUSBD
-                bool "Enable HSUSBD(over USB2.0)"
-                help
-                    Choose this option if you need HSUSBD function mode.
-
-            config BOARD_USING_HSUSBD_USBH
+            config BOARD_USING_USB_HOST
                 select BSP_USING_USBH
-                select BSP_USING_HSUSBD
-                bool "Enable HSUSBD(over USB2.0) and USBH(over USB1.1)"
+                bool "Enable USBH"
                 help
-                    Choose this option if you need HSUSBD and USBH function mode at the same time.
+                    Choose this option if you need USB HOST function mode.
 
-            config BOARD_USING_HSUSBH
-                select BSP_USING_HSUSBH
-                bool "Enable HSUSBH(over USB2.0)"
+            config BOARD_USING_USB_OTG
+                select BSP_USING_OTG
+                bool "Enable OTG"
                 help
-                    Choose this option if you need HSUSBH function mode.
+                    Choose this option if you need USB HOST function mode.
 
-            config BOARD_USING_HSUSBH_USBD
-                select BSP_USING_HSUSBH
-                select BSP_USING_USBD
-                bool "Enable HSUSBH(over USB2.0) and USBD(over USB1.1)"
-                help
-                    Choose this option if you need HSUSBH and USBD function mode at the same time.
-
-            config BOARD_USING_HSOTG
-                select BSP_USING_HSOTG
-                bool "Enable HSOTG(over USB2.0)"
+            config BOARD_USING_USB_OTG_HOST
+                select BSP_USING_USBH
+                select BSP_USING_OTG
+                bool "Enable OTG AND USBH"
                 help
-                    Choose this option if you need HSOTG function mode.
+                    Choose this option if you need both USB ports function mode.
 
         endchoice
 

+ 7 - 0
bsp/nuvoton/nk-980iot/board/nu_pin_init.c

@@ -78,6 +78,12 @@ static void nu_pin_can_init(void)
 
 }
 
+static void nu_pin_usbd_init(void)
+{
+    /* USB0_VBUSVLD, PE.11  */
+    //outpw(REG_SYS_GPE_MFPH, (inpw(REG_SYS_GPE_MFPH) & ~0x0000F000) | 0x00001000);
+}
+
 void nu_pin_init(void)
 {
     nu_pin_uart_init();
@@ -89,6 +95,7 @@ void nu_pin_init(void)
     nu_pin_pwm_init();
     nu_pin_i2s_init();
     nu_pin_can_init();
+    nu_pin_usbd_init();
 }
 
 void nu_pin_deinit(void)