summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Lin <[email protected]>2020-12-29 19:35:43 +0800
committerWayne Lin <[email protected]>2020-12-29 19:35:43 +0800
commit1c4328e5a9f6e1cbb737f975e689fc21ea8f6cca (patch)
treeefc6ffe71d59c724f760fe7fd1bfd8e272928d2c
parent0cfe292157115d2bd095d6b9560d4c7dcb377891 (diff)
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.
-rw-r--r--bsp/nuvoton/libraries/m480/rtt_port/drv_can.c11
-rw-r--r--bsp/nuvoton/libraries/nu_packages/Demo/SConscript1
-rw-r--r--bsp/nuvoton/libraries/nu_packages/Demo/slcd_show_tick.c113
-rw-r--r--bsp/nuvoton/libraries/nu_packages/Demo/usbd_cdc_vcom_echo.c70
-rw-r--r--bsp/nuvoton/libraries/nu_packages/SLCD/SConscript12
-rw-r--r--bsp/nuvoton/libraries/nu_packages/SLCD/slcd_rhe6616tp01.c780
-rw-r--r--bsp/nuvoton/libraries/nu_packages/SLCD/slcd_rhe6616tp01.h139
-rw-r--r--bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h1
-rw-r--r--bsp/nuvoton/libraries/nuc980/README.md1
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig21
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/SConscript23
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c6
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c6
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c2
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbd.c909
-rw-r--r--bsp/nuvoton/nk-980iot/.config51
-rw-r--r--bsp/nuvoton/nk-980iot/README.md4
-rw-r--r--bsp/nuvoton/nk-980iot/applications/mnt.c79
-rw-r--r--bsp/nuvoton/nk-980iot/board/Kconfig39
-rw-r--r--bsp/nuvoton/nk-980iot/board/nu_pin_init.c7
20 files changed, 2167 insertions, 108 deletions
diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c
index 081610cca9..bee0c04219 100644
--- a/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c
+++ b/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)));
diff --git a/bsp/nuvoton/libraries/nu_packages/Demo/SConscript b/bsp/nuvoton/libraries/nu_packages/Demo/SConscript
index cfebf8d0a6..d0093f6bd2 100644
--- a/bsp/nuvoton/libraries/nu_packages/Demo/SConscript
+++ b/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)
diff --git a/bsp/nuvoton/libraries/nu_packages/Demo/slcd_show_tick.c b/bsp/nuvoton/libraries/nu_packages/Demo/slcd_show_tick.c
new file mode 100644
index 0000000000..26ef126f6f
--- /dev/null
+++ b/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) */
diff --git a/bsp/nuvoton/libraries/nu_packages/Demo/usbd_cdc_vcom_echo.c b/bsp/nuvoton/libraries/nu_packages/Demo/usbd_cdc_vcom_echo.c
new file mode 100644
index 0000000000..8567c38dbc
--- /dev/null
+++ b/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
diff --git a/bsp/nuvoton/libraries/nu_packages/SLCD/SConscript b/bsp/nuvoton/libraries/nu_packages/SLCD/SConscript
new file mode 100644
index 0000000000..5f8372725f
--- /dev/null
+++ b/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')
diff --git a/bsp/nuvoton/libraries/nu_packages/SLCD/slcd_rhe6616tp01.c b/bsp/nuvoton/libraries/nu_packages/SLCD/slcd_rhe6616tp01.c
new file mode 100644
index 0000000000..d58d0b90f4
--- /dev/null
+++ b/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. ***/
diff --git a/bsp/nuvoton/libraries/nu_packages/SLCD/slcd_rhe6616tp01.h b/bsp/nuvoton/libraries/nu_packages/SLCD/slcd_rhe6616tp01.h
new file mode 100644
index 0000000000..1f57607fe9
--- /dev/null
+++ b/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. ***/
diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h
index 7fb9aeac95..ce6086255b 100644
--- a/bsp/nuvoton/libraries/nuc980/Driver/Include/NuMicro.h
+++ b/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"
diff --git a/bsp/nuvoton/libraries/nuc980/README.md b/bsp/nuvoton/libraries/nuc980/README.md
index 15ba4f1a91..60eb3b538c 100644
--- a/bsp/nuvoton/libraries/nuc980/README.md
+++ b/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]*** |
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig
index 557a94b1d1..e1633de341 100644
--- a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig
+++ b/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
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/SConscript b/bsp/nuvoton/libraries/nuc980/rtt_port/SConscript
index d9e3c9961f..b92729931c 100644
--- a/bsp/nuvoton/libraries/nuc980/rtt_port/SConscript
+++ b/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')
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c
index 20e5007b9e..66d3a8f870 100644
--- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c
+++ b/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)));
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c
index cdba6f7a06..771130a326 100644
--- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c
+++ b/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;
}
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c
index 50271ccfa3..1bf574d835 100644
--- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c
+++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sys.c
@@ -217,8 +217,6 @@ void machine_shutdown(void)
/* Unlock */
SYS_UnlockReg();
- // TODO
-
while (1);
}
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbd.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbd.c
new file mode 100644
index 0000000000..e3ec1f6b58
--- /dev/null
+++ b/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
diff --git a/bsp/nuvoton/nk-980iot/.config b/bsp/nuvoton/nk-980iot/.config
index 2a6deb9b78..1366c6c4ca 100644
--- a/bsp/nuvoton/nk-980iot/.config
+++ b/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
diff --git a/bsp/nuvoton/nk-980iot/README.md b/bsp/nuvoton/nk-980iot/README.md
index 84e8739098..883545a556 100644
--- a/bsp/nuvoton/nk-980iot/README.md
+++ b/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:
diff --git a/bsp/nuvoton/nk-980iot/applications/mnt.c b/bsp/nuvoton/nk-980iot/applications/mnt.c
index 5f4800a8ec..f93229af9b 100644
--- a/bsp/nuvoton/nk-980iot/applications/mnt.c
+++ b/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)
diff --git a/bsp/nuvoton/nk-980iot/board/Kconfig b/bsp/nuvoton/nk-980iot/board/Kconfig
index a9a7751686..c14b95b0ae 100644
--- a/bsp/nuvoton/nk-980iot/board/Kconfig
+++ b/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
diff --git a/bsp/nuvoton/nk-980iot/board/nu_pin_init.c b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c
index 4177e03b82..1c03b7eb60 100644
--- a/bsp/nuvoton/nk-980iot/board/nu_pin_init.c
+++ b/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)