748 lines
33 KiB
C
748 lines
33 KiB
C
/*
|
|
*********************************************************************************************************
|
|
* EXAMPLE CODE
|
|
*
|
|
* This file is provided as an example on how to use Micrium products.
|
|
*
|
|
* Please feel free to use any application code labeled as 'EXAMPLE CODE' in
|
|
* your application products. Example code may be used as is, in whole or in
|
|
* part, or may be used as a reference only. This file can be modified as
|
|
* required to meet the end-product requirements.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*
|
|
* USB DEVICE PHDC TEST APPLICATION
|
|
*
|
|
* TEMPLATE
|
|
*
|
|
* Filename : app_usbd_phdc.c
|
|
* Version : V4.06.01
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* INCLUDE FILES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#include <app_usbd.h>
|
|
|
|
#if (APP_CFG_USBD_EN == DEF_ENABLED) && \
|
|
(APP_CFG_USBD_PHDC_EN == DEF_ENABLED)
|
|
#include <Class/PHDC/usbd_phdc.h>
|
|
#include <Source/os.h>
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DEFINES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define APP_USBD_PHDC_ITEM_DATA_LEN_MIN 5u
|
|
#define APP_USBD_PHDC_ITEM_Q_NBR_MAX APP_CFG_USBD_PHDC_ITEM_NBR_MAX
|
|
#define APP_USBD_PHDC_ITEM_DFLT_PERIOD 100u
|
|
|
|
#ifndef APP_CFG_USBD_PHDC_MAX_NBR_TASKS
|
|
#define APP_CFG_USBD_PHDC_MAX_NBR_TASKS 1u
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DATA TYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* APPLICATION COMMANDS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef enum app_usbd_phdc_cmds {
|
|
APP_USBD_PHDC_CMD_NONE = 0u,
|
|
APP_USBD_PHDC_CMD_RESET = 1u,
|
|
APP_USBD_PHDC_CMD_ADD_ITEM = 2u
|
|
} APP_USBD_PHDC_CMDS;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* APPLICATION ITEM
|
|
*
|
|
* Note(s): (1) Data buffer of each item has the following mapping:
|
|
*
|
|
* +---------+---------------+-------------------+-----------------------------------+
|
|
* | Offset | Field | Size | Description |
|
|
* +---------+---------------+-------------------+-----------------------------------+
|
|
* | 0 | Cmd | 1 | Command from host. |
|
|
* +---------+---------------+-------------------+-----------------------------------+
|
|
* | 1 | Item index | 1 | Index of item. |
|
|
* +---------+---------------+-------------------+-----------------------------------+
|
|
* | 2 | Period (LSB) | 1 | Periodicity of transfer. |
|
|
* +---------+---------------+-------------------+-----------------------------------+
|
|
* | 3 | Period (MSB) | 1 | Periodicity of transfer. |
|
|
* +---------+---------------+-------------------+-----------------------------------+
|
|
* | 4 | Latency / | 1 | Latency / reliability (QoS) of |
|
|
* | | Reliability | | transfer. |
|
|
* +---------+---------------+-------------------+-----------------------------------+
|
|
* | 5 | Data | [0..DATA_LEN_MAX] | Data. |
|
|
* +---------+---------------+-------------------+-----------------------------------+
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef struct app_usbd_phdc_item {
|
|
CPU_INT16U Period; /* Periodicity of xfer. */
|
|
LATENCY_RELY_FLAGS LatencyRely; /* Latency / rely of xfer. */
|
|
CPU_INT08U Data[APP_CFG_USBD_PHDC_ITEM_DATA_LEN_MAX];
|
|
CPU_INT08U DataOpaque[USBD_PHDC_CFG_DATA_OPAQUE_MAX_LEN];
|
|
CPU_INT16U DataLen;
|
|
CPU_INT08U DataOpaqueLen;
|
|
OS_TMR *Tmr;
|
|
} APP_USBD_PHDC_ITEM;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONSTANTS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static const CPU_INT08U App_USBD_PHDC_OpaqueDataRx[] = {"Micrium PHDC Rx"};
|
|
static const CPU_INT08U App_USBD_PHDC_OpaqueDataTx[] = {"Micrium PHDC Tx"};
|
|
static const CPU_INT08U App_USBD_PHDC_OpaqueDataTxLowLatency[] = {"Micrium PHDC Tx low latency"};
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL GLOBAL VARIABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static OS_EVENT *App_USBD_PHDC_ItemQ[APP_CFG_USBD_PHDC_MAX_NBR_TASKS];
|
|
static void *App_USBD_PHDC_ItemQBuffer[APP_CFG_USBD_PHDC_MAX_NBR_TASKS][APP_USBD_PHDC_ITEM_Q_NBR_MAX];
|
|
|
|
static CPU_STK App_USBD_PHDC_TxCommTaskStk[APP_CFG_USBD_PHDC_MAX_NBR_TASKS][APP_CFG_USBD_PHDC_TASK_STK_SIZE];
|
|
static CPU_STK App_USBD_PHDC_RxCommTaskStk[APP_CFG_USBD_PHDC_TASK_STK_SIZE];
|
|
|
|
static CPU_INT16U App_USBD_PHDC_Ctr;
|
|
static CPU_BOOLEAN App_USBD_PHDC_PreambleEn;
|
|
static CPU_INT08U App_USBD_PHDC_ClassNbr;
|
|
|
|
static APP_USBD_PHDC_ITEM App_USBD_PHDC_Items[APP_CFG_USBD_PHDC_ITEM_NBR_MAX];
|
|
static CPU_INT16U App_USBD_PHDC_ItemNbrNext;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_BOOLEAN App_USBD_PHDC_Init (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_hs,
|
|
CPU_INT08U cfg_fs);
|
|
|
|
static void App_USBD_PHDC_RxCommTask (void *p_arg);
|
|
|
|
static void App_USBD_PHDC_TxCommTask (void *p_arg);
|
|
|
|
static void App_USBD_PHDC_SetPreambleEn(CPU_INT08U class_nbr,
|
|
CPU_BOOLEAN preamble_en);
|
|
|
|
static void App_USBD_PHDC_TmrCallback (void *p_tmr,
|
|
void *p_arg);
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONFIGURATION ERRORS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#if (OS_TMR_CFG_TICKS_PER_SEC < 100u)
|
|
#error "OS_TMR_CFG_TICKS_PER_SEC illegally #define'd in 'os_cfg.h'[MUST be >= 100]"
|
|
#endif
|
|
|
|
#if (OS_TASK_STAT_EN == 0u)
|
|
#error "OS_TASK_STAT_EN illegally #define'd in 'os_cfg.h' [MUST be DEF_ENABLED]"
|
|
#endif
|
|
|
|
#if (OS_TMR_EN == 0u)
|
|
#error "OS_TMR_EN illegally #define'd in 'os_cfg.h' [MUST be DEF_ENABLED]"
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* App_USBD_PHDC_Init()
|
|
*
|
|
* Description : Add a PHDC interface to the USB device stack and initialize it.
|
|
*
|
|
* Argument(s) : dev_nbr Device number.
|
|
*
|
|
* cfg_hs Index of high-speed configuration to which this interface will be added to.
|
|
*
|
|
* cfg_fs Index of high-speed configuration to which this interface will be added to.
|
|
*
|
|
* Return(s) : DEF_OK, if PHDC interface successfully added.
|
|
*
|
|
* DEF_FAIL, otherwise.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_BOOLEAN App_USBD_PHDC_Init (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_hs,
|
|
CPU_INT08U cfg_fs)
|
|
{
|
|
CPU_BOOLEAN valid_cfg_hs;
|
|
CPU_BOOLEAN valid_cfg_fs;
|
|
CPU_INT08U cnt;
|
|
CPU_INT32U tmr_period;
|
|
LATENCY_RELY_FLAGS latency_rely_flags;
|
|
APP_USBD_PHDC_ITEM *p_dflt_item;
|
|
USBD_ERR err;
|
|
OS_ERR os_err;
|
|
|
|
|
|
valid_cfg_hs = DEF_NO;
|
|
valid_cfg_fs = DEF_NO;
|
|
|
|
APP_TRACE_DBG((" Initializing PHDC class ... \r\n"));
|
|
|
|
USBD_PHDC_Init(&err); /* ------------------- INIT PHDC ---------------------- */
|
|
if (err != USBD_ERR_NONE) {
|
|
return (DEF_FAIL);
|
|
}
|
|
/* Add PHDC instance. */
|
|
App_USBD_PHDC_ClassNbr = USBD_PHDC_Add(DEF_NO, /* Vendor-defined data format. */
|
|
DEF_YES, /* Preamble capable. */
|
|
App_USBD_PHDC_SetPreambleEn,
|
|
8u,
|
|
&err);
|
|
if (err != USBD_ERR_NONE) {
|
|
return (DEF_FAIL);
|
|
}
|
|
|
|
latency_rely_flags = USBD_PHDC_LATENCY_VERYHIGH_RELY_BEST |
|
|
USBD_PHDC_LATENCY_HIGH_RELY_BEST |
|
|
USBD_PHDC_LATENCY_MEDIUM_RELY_BEST;
|
|
USBD_PHDC_RdCfg(App_USBD_PHDC_ClassNbr, /* Cfg rd xfers with all possible latency/rely flags. */
|
|
latency_rely_flags,
|
|
App_USBD_PHDC_OpaqueDataRx,
|
|
sizeof(App_USBD_PHDC_OpaqueDataRx),
|
|
&err);
|
|
if (err != USBD_ERR_NONE) {
|
|
return (DEF_FAIL);
|
|
}
|
|
|
|
latency_rely_flags = USBD_PHDC_LATENCY_VERYHIGH_RELY_BEST |
|
|
USBD_PHDC_LATENCY_HIGH_RELY_BEST |
|
|
USBD_PHDC_LATENCY_MEDIUM_RELY_BEST |
|
|
USBD_PHDC_LATENCY_MEDIUM_RELY_BETTER |
|
|
USBD_PHDC_LATENCY_MEDIUM_RELY_GOOD;
|
|
USBD_PHDC_WrCfg(App_USBD_PHDC_ClassNbr, /* Cfg very high, high and medium xfers with metadata. */
|
|
latency_rely_flags,
|
|
App_USBD_PHDC_OpaqueDataTx,
|
|
sizeof(App_USBD_PHDC_OpaqueDataTx),
|
|
&err);
|
|
|
|
if (err != USBD_ERR_NONE) {
|
|
return (DEF_FAIL);
|
|
}
|
|
|
|
USBD_PHDC_WrCfg(App_USBD_PHDC_ClassNbr, /* Cfg low latency xfers with specific metadadata. */
|
|
USBD_PHDC_LATENCY_LOW_RELY_GOOD,
|
|
App_USBD_PHDC_OpaqueDataTxLowLatency,
|
|
sizeof(App_USBD_PHDC_OpaqueDataTxLowLatency),
|
|
&err);
|
|
|
|
if (err != USBD_ERR_NONE) {
|
|
return (DEF_FAIL);
|
|
}
|
|
|
|
if (cfg_hs != USBD_CFG_NBR_NONE) {
|
|
valid_cfg_hs = USBD_PHDC_CfgAdd(App_USBD_PHDC_ClassNbr,
|
|
dev_nbr,
|
|
cfg_hs,
|
|
&err); /* Add PHDC class to HS dflt cfg. */
|
|
}
|
|
|
|
if (cfg_fs != USBD_CFG_NBR_NONE) {
|
|
valid_cfg_fs = USBD_PHDC_CfgAdd(App_USBD_PHDC_ClassNbr,
|
|
dev_nbr,
|
|
cfg_fs,
|
|
&err); /* Add PHDC class to FS dflt cfg. */
|
|
}
|
|
|
|
if ((valid_cfg_fs == DEF_NO) &&
|
|
(valid_cfg_hs == DEF_NO)) {
|
|
return (DEF_FAIL);
|
|
}
|
|
|
|
/* -------------------- INIT APP ---------------------- */
|
|
p_dflt_item = &App_USBD_PHDC_Items[0u]; /* Init dflt item. */
|
|
p_dflt_item->Period = APP_USBD_PHDC_ITEM_DFLT_PERIOD;
|
|
p_dflt_item->LatencyRely = USBD_PHDC_LATENCY_LOW_RELY_GOOD;
|
|
p_dflt_item->DataLen = APP_USBD_PHDC_ITEM_DATA_LEN_MIN + 3u;
|
|
p_dflt_item->DataOpaqueLen = 0u;
|
|
p_dflt_item->Data[1u] = 0u; /* See Note 1 of APPLICATION ITEM section. */
|
|
p_dflt_item->Data[2u] = (CPU_INT08U)APP_USBD_PHDC_ITEM_DFLT_PERIOD;
|
|
p_dflt_item->Data[3u] = (CPU_INT08U)(APP_USBD_PHDC_ITEM_DFLT_PERIOD >> 8u);
|
|
p_dflt_item->Data[5u] = 0u; /* Ctr value, 0 by dflt. */
|
|
p_dflt_item->Data[6u] = 0u;
|
|
p_dflt_item->Data[7u] = OSCPUUsage;
|
|
|
|
tmr_period = ((((INT32U)p_dflt_item->Period * OS_TMR_CFG_TICKS_PER_SEC) + 1000u - 1u) / 1000u);
|
|
p_dflt_item->Tmr = OSTmrCreate( tmr_period, /* Create tmr for dflt item. */
|
|
0,
|
|
OS_TMR_OPT_ONE_SHOT,
|
|
App_USBD_PHDC_TmrCallback,
|
|
(void *)p_dflt_item,
|
|
(INT8U *)0,
|
|
&os_err);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not add default item timer w/err = %d\r\n", os_err));
|
|
return (DEF_FAIL);
|
|
}
|
|
|
|
/* Create one Q per xfer priority. */
|
|
for (cnt = 0u; cnt < APP_CFG_USBD_PHDC_MAX_NBR_TASKS; cnt++) {
|
|
App_USBD_PHDC_ItemQ[cnt] = OSQCreate(&App_USBD_PHDC_ItemQBuffer[cnt][0u],
|
|
APP_USBD_PHDC_ITEM_Q_NBR_MAX);
|
|
if (App_USBD_PHDC_ItemQ[cnt] == (OS_EVENT *)0) {
|
|
APP_TRACE_DBG(("Could not create item Q w/err = %d\r\n", os_err));
|
|
return (DEF_FAIL);
|
|
}
|
|
}
|
|
|
|
App_USBD_PHDC_PreambleEn = DEF_DISABLED; /* Metadata msg preamble disabled by default. */
|
|
App_USBD_PHDC_ItemNbrNext = 1u;
|
|
App_USBD_PHDC_Ctr = 0u;
|
|
/* Create task that will handle rd procedures. */
|
|
#if (OS_TASK_CREATE_EXT_EN == 1u)
|
|
#if (OS_STK_GROWTH == 1u)
|
|
os_err = OSTaskCreateExt( App_USBD_PHDC_RxCommTask,
|
|
(void *)0,
|
|
&App_USBD_PHDC_RxCommTaskStk[APP_CFG_USBD_PHDC_TASK_STK_SIZE - 1u],
|
|
APP_CFG_USBD_PHDC_RX_COMM_TASK_PRIO,
|
|
APP_CFG_USBD_PHDC_RX_COMM_TASK_PRIO,
|
|
&App_USBD_PHDC_RxCommTaskStk[0],
|
|
APP_CFG_USBD_PHDC_TASK_STK_SIZE,
|
|
(void *)0,
|
|
OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK);
|
|
#else
|
|
os_err = OSTaskCreateExt( App_USBD_PHDC_RxCommTask,
|
|
(void *)0,
|
|
&App_USBD_PHDC_RxCommTaskStk[0],
|
|
APP_CFG_USBD_PHDC_RX_COMM_TASK_PRIO,
|
|
APP_CFG_USBD_PHDC_RX_COMM_TASK_PRIO,
|
|
&App_USBD_PHDC_RxCommTaskStk[APP_CFG_USBD_PHDC_TASK_STK_SIZE - 1u],
|
|
APP_CFG_USBD_PHDC_TASK_STK_SIZE,
|
|
(void *)0,
|
|
OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK);
|
|
#endif
|
|
|
|
#else /* Ext task creation is not avail. */
|
|
|
|
#if (OS_STK_GROWTH == 1u)
|
|
os_err = OSTaskCreate( App_USBD_PHDC_RxCommTask,
|
|
(void *)0,
|
|
&App_USBD_PHDC_RxCommTaskStk[APP_CFG_USBD_PHDC_TASK_STK_SIZE - 1u],
|
|
APP_CFG_USBD_PHDC_RX_COMM_TASK_PRIO);
|
|
#else
|
|
os_err = OSTaskCreate( App_USBD_PHDC_RxCommTask,
|
|
(void *)0,
|
|
&App_USBD_PHDC_RxCommTaskStk[0],
|
|
APP_CFG_USBD_PHDC_RX_COMM_TASK_PRIO);
|
|
#endif
|
|
#endif
|
|
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not add PHDC rx comm task w/err = %d\r\n", os_err));
|
|
return (DEF_FAIL);
|
|
}
|
|
|
|
#if (OS_TASK_NAME_EN > 0)
|
|
OSTaskNameSet(APP_CFG_USBD_PHDC_RX_COMM_TASK_PRIO, (INT8U *)"USB Device PHDC rx comm", &os_err);
|
|
#endif
|
|
|
|
/* Create one tx task per prio (QoS). */
|
|
for (cnt = 0; cnt < APP_CFG_USBD_PHDC_MAX_NBR_TASKS; cnt++) {
|
|
#if (OS_TASK_CREATE_EXT_EN == 1u) /* Ext task creation is avail. */
|
|
#if (OS_STK_GROWTH == 1u)
|
|
os_err = OSTaskCreateExt( App_USBD_PHDC_TxCommTask,
|
|
(void *)(CPU_ADDR)cnt,
|
|
&App_USBD_PHDC_TxCommTaskStk[cnt][APP_CFG_USBD_PHDC_TASK_STK_SIZE - 1u],
|
|
APP_CFG_USBD_PHDC_TX_COMM_TASK_PRIO + cnt,
|
|
APP_CFG_USBD_PHDC_TX_COMM_TASK_PRIO + cnt,
|
|
&App_USBD_PHDC_TxCommTaskStk[cnt][0u],
|
|
APP_CFG_USBD_PHDC_TASK_STK_SIZE,
|
|
(void *) 0,
|
|
OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK);
|
|
#else
|
|
os_err = OSTaskCreateExt( App_USBD_PHDC_TxCommTask,
|
|
(void *)(CPU_ADDR)cnt,
|
|
&App_USBD_PHDC_TxCommTaskStk[cnt][0u],
|
|
APP_CFG_USBD_PHDC_TX_COMM_TASK_PRIO + cnt,
|
|
APP_CFG_USBD_PHDC_TX_COMM_TASK_PRIO + cnt,
|
|
&App_USBD_PHDC_TxCommTaskStk[cnt][APP_CFG_USBD_PHDC_TASK_STK_SIZE - 1u],
|
|
APP_CFG_USBD_PHDC_TASK_STK_SIZE,
|
|
(void *) 0,
|
|
OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK);
|
|
#endif
|
|
|
|
#else /* Ext task creation is not avail. */
|
|
|
|
#if (OS_STK_GROWTH == 1u)
|
|
os_err = OSTaskCreate( App_USBD_PHDC_TxCommTask,
|
|
(void *)(CPU_ADDR)cnt,
|
|
&App_USBD_PHDC_TxCommTaskStk[cnt][APP_CFG_USBD_PHDC_TASK_STK_SIZE - 1u],
|
|
APP_CFG_USBD_PHDC_TX_COMM_TASK_PRIO + cnt);
|
|
#else
|
|
os_err = OSTaskCreate( App_USBD_PHDC_TxCommTask,
|
|
(void *)(CPU_ADDR)cnt,
|
|
&App_USBD_PHDC_TxCommTaskStk[cnt][0u],
|
|
APP_CFG_USBD_PHDC_TX_COMM_TASK_PRIO + cnt);
|
|
#endif
|
|
|
|
#endif
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not add PHDC tx comm task w/err = %d\r\n", os_err));
|
|
return (DEF_FAIL);
|
|
}
|
|
|
|
#if (OS_TASK_NAME_EN > 0)
|
|
OSTaskNameSet(APP_CFG_USBD_PHDC_RX_COMM_TASK_PRIO, (INT8U *)"USBD PHDC rx comm", &os_err);
|
|
#endif
|
|
|
|
}
|
|
|
|
return (DEF_OK);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* App_USBD_PHDC_RxCommTask()
|
|
*
|
|
* Description : Read PHDC data and opaque data from host. Then take action in function of the application
|
|
* command sent by the host.
|
|
*
|
|
* Argument(s) : p_arg Argument passed to the task.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void App_USBD_PHDC_RxCommTask (void *p_arg)
|
|
{
|
|
CPU_BOOLEAN is_conn;
|
|
CPU_INT08U data_opaque_len;
|
|
CPU_INT08U data_opaque[USBD_PHDC_CFG_DATA_OPAQUE_MAX_LEN];
|
|
CPU_INT08U data[APP_CFG_USBD_PHDC_ITEM_DATA_LEN_MAX];
|
|
CPU_INT08U nbr_xfer;
|
|
CPU_INT16U cnt;
|
|
CPU_INT16U xfer_len;
|
|
CPU_INT32U tmr_period;
|
|
APP_USBD_PHDC_ITEM *p_dflt_item;
|
|
APP_USBD_PHDC_ITEM *p_item;
|
|
USBD_ERR usb_err;
|
|
OS_ERR os_err;
|
|
|
|
|
|
(void)p_arg;
|
|
p_dflt_item = &App_USBD_PHDC_Items[0u];
|
|
|
|
while (DEF_TRUE) {
|
|
is_conn = USBD_PHDC_IsConn(App_USBD_PHDC_ClassNbr); /* Wait for configuration. */
|
|
while (is_conn == DEF_NO) {
|
|
OSTimeDlyHMSM(0u, 0u, 0u, 100u);
|
|
is_conn = USBD_PHDC_IsConn(App_USBD_PHDC_ClassNbr);
|
|
}
|
|
|
|
data_opaque_len = 0u;
|
|
if (App_USBD_PHDC_PreambleEn == DEF_ENABLED) { /* Host decide of preamble state. */
|
|
data_opaque_len = USBD_PHDC_PreambleRd( App_USBD_PHDC_ClassNbr,
|
|
(void *)data_opaque,
|
|
USBD_PHDC_CFG_DATA_OPAQUE_MAX_LEN,
|
|
&nbr_xfer,
|
|
0u,
|
|
&usb_err);
|
|
|
|
if ((usb_err != USBD_ERR_NONE) ||
|
|
(nbr_xfer != 1u )) {
|
|
if (usb_err != USBD_ERR_OS_ABORT) { /* Host changed preamble state when xfer is aborted. */
|
|
APP_TRACE_DBG(("Rd preamble failed w/err = %d\r\n", usb_err));
|
|
OSTimeDlyHMSM(0u, 0u, 0u, 250u);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
xfer_len = USBD_PHDC_Rd( App_USBD_PHDC_ClassNbr,
|
|
(void *)data,
|
|
APP_CFG_USBD_PHDC_ITEM_DATA_LEN_MAX,
|
|
0u,
|
|
&usb_err);
|
|
if (usb_err != USBD_ERR_NONE) {
|
|
if (usb_err != USBD_ERR_OS_ABORT) {
|
|
APP_TRACE_DBG(("Rd failed w/err = %d\r\n", usb_err));
|
|
OSTimeDlyHMSM(0u, 0u, 0u, 250u);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
switch (data[0u]) { /* First data octets is the cmd. */
|
|
case APP_USBD_PHDC_CMD_ADD_ITEM: /* Host added a new item. */
|
|
if (App_USBD_PHDC_ItemNbrNext < APP_CFG_USBD_PHDC_ITEM_NBR_MAX) {
|
|
p_item = &App_USBD_PHDC_Items[App_USBD_PHDC_ItemNbrNext];
|
|
p_item->Period = (CPU_INT16U) data[2u];
|
|
p_item->Period += (CPU_INT16U)(data[3u] << 8u);
|
|
p_item->LatencyRely = data[4u];
|
|
p_item->DataLen = xfer_len;
|
|
p_item->DataOpaqueLen = data_opaque_len;
|
|
|
|
Mem_Copy(p_item->Data,
|
|
data,
|
|
xfer_len);
|
|
|
|
Mem_Copy(p_item->DataOpaque,
|
|
data_opaque,
|
|
data_opaque_len);
|
|
|
|
tmr_period = ((((INT32U)p_item->Period * OS_TMR_CFG_TICKS_PER_SEC) + 1000u - 1u) / 1000u);
|
|
p_item->Tmr = OSTmrCreate(tmr_period, /* Create tmr for new item. */
|
|
0,
|
|
OS_TMR_OPT_ONE_SHOT,
|
|
App_USBD_PHDC_TmrCallback,
|
|
(void *)p_item,
|
|
(INT8U *)0,
|
|
&os_err);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not create timer w/err = %d\r\n", os_err));
|
|
break;
|
|
}
|
|
|
|
(void)OSTmrStart(p_item->Tmr,
|
|
&os_err);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Timer start failed w/err = %d\r\n", os_err));
|
|
break;
|
|
}
|
|
|
|
App_USBD_PHDC_ItemNbrNext++;
|
|
}
|
|
break;
|
|
|
|
case APP_USBD_PHDC_CMD_RESET: /* Host send reset cmd when app start. */
|
|
USBD_PHDC_Reset(App_USBD_PHDC_ClassNbr); /* Reset PHDC instance. */
|
|
|
|
/* Flush all Qs. */
|
|
for (cnt = 0; cnt < APP_CFG_USBD_PHDC_MAX_NBR_TASKS; cnt ++) {
|
|
os_err = OSQFlush(App_USBD_PHDC_ItemQ[cnt]);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not flush queue w/err = %d\r\n", os_err));
|
|
}
|
|
}
|
|
|
|
/* Delete all items tmr. */
|
|
for (cnt = 1u; cnt < App_USBD_PHDC_ItemNbrNext; cnt++) {
|
|
(void)OSTmrDel(App_USBD_PHDC_Items[cnt].Tmr,
|
|
&os_err);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not delete timer w/err = %d\r\n", os_err));
|
|
}
|
|
}
|
|
App_USBD_PHDC_ItemNbrNext = 1;
|
|
/* Start dflt item tmr. */
|
|
(void)OSTmrStart(p_dflt_item->Tmr,
|
|
&os_err);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not start default item timer w/err = %d\r\n", os_err));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* App_USBD_PHDC_TxCommTask()
|
|
*
|
|
* Description : Write next item data in queue along with its preamble.
|
|
*
|
|
* Argument(s) : p_arg Argument passed to the task.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void App_USBD_PHDC_TxCommTask (void *p_arg)
|
|
{
|
|
CPU_BOOLEAN is_conn;
|
|
CPU_INT08U nbr;
|
|
APP_USBD_PHDC_ITEM *p_item;
|
|
USBD_ERR usb_err;
|
|
OS_ERR os_err;
|
|
|
|
|
|
nbr = (CPU_INT08U)(CPU_ADDR)p_arg; /* p_arg contain task nbr. */
|
|
|
|
while (DEF_TRUE) {
|
|
is_conn = USBD_PHDC_IsConn(App_USBD_PHDC_ClassNbr); /* Wait for configuration. */
|
|
while (is_conn == DEF_NO) {
|
|
OSTimeDlyHMSM(0u, 0u, 0u, 100u);
|
|
is_conn = USBD_PHDC_IsConn(App_USBD_PHDC_ClassNbr);
|
|
}
|
|
/* Wait for data to wr on Q. */
|
|
p_item = (APP_USBD_PHDC_ITEM *)OSQPend(App_USBD_PHDC_ItemQ[nbr],
|
|
0,
|
|
&os_err);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Queue pend failed w/err = %d\r\n", os_err));
|
|
OSTimeDlyHMSM(0u, 0u, 0u, 100u);
|
|
continue;
|
|
}
|
|
|
|
if (p_item->Data[1u] == 0u) { /* If dflt item, update ctr and CPU usage value. */
|
|
App_USBD_PHDC_Ctr++;
|
|
p_item->Data[5u] = (CPU_INT08U) App_USBD_PHDC_Ctr;
|
|
p_item->Data[6u] = (CPU_INT08U)(App_USBD_PHDC_Ctr >> 8u);
|
|
p_item->Data[7u] = OSCPUUsage;
|
|
}
|
|
|
|
usb_err = USBD_ERR_NONE; /* Write preamble (if applicable) and data to host. */
|
|
if ((App_USBD_PHDC_PreambleEn == DEF_ENABLED ) &&
|
|
(p_item->LatencyRely != USBD_PHDC_LATENCY_LOW_RELY_GOOD)) {
|
|
|
|
USBD_PHDC_PreambleWr( App_USBD_PHDC_ClassNbr,
|
|
(void *)p_item->DataOpaque,
|
|
p_item->DataOpaqueLen,
|
|
p_item->LatencyRely,
|
|
1u,
|
|
0u,
|
|
&usb_err);
|
|
|
|
if (usb_err != USBD_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not write PHDC item #%d preamble w/err = %d\r\n",
|
|
p_item->Data[1],
|
|
usb_err));
|
|
}
|
|
}
|
|
|
|
if (usb_err == USBD_ERR_NONE) {
|
|
USBD_PHDC_Wr( App_USBD_PHDC_ClassNbr,
|
|
(void *)p_item->Data,
|
|
p_item->DataLen,
|
|
p_item->LatencyRely,
|
|
0u,
|
|
&usb_err);
|
|
|
|
if (usb_err != USBD_ERR_NONE) {
|
|
APP_TRACE_DBG(("Could not write PHDC item #%d w/err = %d\r\n",
|
|
p_item->Data[1u],
|
|
usb_err));
|
|
}
|
|
}
|
|
|
|
if (usb_err != USBD_ERR_OS_ABORT) { /* Start timer only if xfer not been aborted. */
|
|
(void)OSTmrStart(p_item->Tmr,
|
|
&os_err);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Timer start failed w/err = %d\r\n", os_err));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* App_USBD_PHDC_SetPreambleEn()
|
|
*
|
|
* Description : Callback called when host enable/disable preambles.
|
|
*
|
|
* Argument(s) : class_nbr PHDC instance number.
|
|
*
|
|
* preamble_en DEF_ENABLED, if preambles are enabled
|
|
* DEF_DISABLED, otherwise
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void App_USBD_PHDC_SetPreambleEn (CPU_INT08U class_nbr,
|
|
CPU_BOOLEAN preamble_en)
|
|
{
|
|
(void)class_nbr;
|
|
|
|
App_USBD_PHDC_PreambleEn = preamble_en;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* App_USBD_PHDC_TmrCallback()
|
|
*
|
|
* Description : Callback called upon timer count reach 0.
|
|
*
|
|
* Argument(s) : p_tmr Pointer to timer structure.
|
|
*
|
|
* p_arg Pointer to application argument.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void App_USBD_PHDC_TmrCallback (void *p_tmr,
|
|
void *p_arg)
|
|
{
|
|
CPU_INT08U nbr;
|
|
APP_USBD_PHDC_ITEM *p_item;
|
|
OS_ERR os_err;
|
|
|
|
|
|
(void)p_tmr;
|
|
p_item = (APP_USBD_PHDC_ITEM *)p_arg;
|
|
nbr = CPU_CntTrailZeros08(p_item->LatencyRely);
|
|
|
|
/* Post item on Q. */
|
|
os_err = OSQPost( App_USBD_PHDC_ItemQ[nbr],
|
|
(void *)p_item);
|
|
if (os_err != OS_ERR_NONE) {
|
|
APP_TRACE_DBG(("Q post failed w/err %d\r\n", os_err));
|
|
return;
|
|
}
|
|
}
|
|
#endif
|