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.
This commit is contained in:
Wayne Lin 2020-12-29 19:35:43 +08:00
parent 0cfe292157
commit 1c4328e5a9
20 changed files with 2167 additions and 108 deletions

View File

@ -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)));

View File

@ -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)

View File

@ -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) */

View File

@ -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

View File

@ -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')

View File

@ -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. ***/

View File

@ -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. ***/

View File

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

View File

@ -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]*** |

View File

@ -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)"
bool "Enable 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)"
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

View File

@ -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')

View File

@ -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)));

View File

@ -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;
}

View File

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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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))
{
// format the ramdisk
dfs_mkfs("elm", RAMDISK_NAME);
LOG_E("cannot find %s device", RAMDISK_NAME);
goto exit_filesystem_init;
}
else
{
/* 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;
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_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);
}
INIT_DEVICE_EXPORT(ramdisk_device_init);
#endif
#if defined(BOARD_USING_STORAGE_SPIFLASH)

View File

@ -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)"
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 HSUSBH and USBD function mode at the same time.
config BOARD_USING_HSOTG
select BSP_USING_HSOTG
bool "Enable HSOTG(over USB2.0)"
help
Choose this option if you need HSOTG function mode.
Choose this option if you need both USB ports function mode.
endchoice

View File

@ -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)