📄 d12driver.c
字号:
INT8U *pBuff,i,endpstatus;
D12_ReadLastTransactionStatus(endp); //复位中断寄存器
if (pUsb->Grp != 0){
if (pUsb->Cnt >= pUsb->Max[pUsb->Prio]){ //独占任务全部数据写入缓冲区
endpstatus = D12_ReadEndpointStatus(endp) & 0x60;
if (endpstatus == 0){ //缓冲区中的数据全部发送完毕
pUsb->Sem = 0; //释放该端点的发送资源
pUsb->Max[pUsb->Prio] = 0; //置正确发送标志为0
USB_DelPrio(pUsb,pUsb->Prio); //将该任务从等待队列中删除
if (pUsb->bSuspend[pUsb->Prio] == 1)
OSTaskResume(pUsb->Prio);
else
OSTimeDlyResume(pUsb->Prio); //使该任务就绪
}else
return;
}
}
else
return;
if (pUsb->Grp != 0){ //还有任务在等待发送数据
if (pUsb->Sem == 0){ //该发送端点可以使用
pUsb->Prio = USB_GetHighPrio(pUsb);
pUsb->Cnt = 0; //发送计数清0
pUsb->Sem = 1; //使该任务独占该发送资源
}
pBuff = pUsb->pBuff[pUsb->Prio]; //得到发送缓冲区指针
for (i = 0; i < buffnums; i++){
endpstatus = D12_ReadEndpointStatus(endp) & 0x60;
if (endpstatus == 0x60) break; //如果缓冲区全部都满,那么不可以再写入
len = pUsb->Max[pUsb->Prio] - pUsb->Cnt;
if (len > 0){ //有空的缓冲区而且等待发送字节数大于0
if (len >= eppsize) //写满缓冲区
len = D12_WriteEndpoint(endp,(INT8U)eppsize,pBuff + pUsb->Cnt);
else //写len个字节
len = D12_WriteEndpoint(endp,(INT8U)len,pBuff + pUsb->Cnt);
pUsb->Cnt = pUsb->Cnt + len; //发送计数器加上实际上发送的字节
}//end of if (len > 0)
}//end of for()
}//end of if (pUsb->Grp != 0)
}
/**********************************************************************************
** 函数名称: INT8U USB_ReadPort(INT8U endp,CTRL_USB *pUsb,INT32U len,INT8U *recbuff,INT16U timeout)
** 功能描述: 读端点函数
** 输 入: INT8U endp: 端点索引号
CTRL_USB *pUsb: USB 接收与发送控制块指针
INT32U len: 接收字节个数
INT8U *recbuff: 接收缓冲区
INT16U timeout: 等待超时时间
** 输 出: 0: 读成功 > 0 读失败(错误码)
**********************************************************************************/
INT8U USB_ReadPort(INT8U endp, INT32U eppsize, INT8U buffnums, CTRL_USB *pUsb, INT32U len, INT8U *recbuff, INT16U timeout)
{
INT8U err,i,endpstatus;
INT32U length;
INT8U *pbuf;
OS_ENTER_CRITICAL();
err = USB_RW_Param(pUsb, len, recbuff); //填写USB接收或发送控制块参数
if (err != USB_NO_ERR)
{
OS_EXIT_CRITICAL();
return err;
}
/*** 如果端点接收缓冲区已经有数据, 执行下面的程序 ****/
if ((pUsb->Sem == 0) && (pUsb->NoTask == 1) && (pUsb->Grp != 0))
{ //接收缓冲区中有数据
pUsb->Sem = 1; //独占该端点
pUsb->Cnt = 0; //发送计数值清0
pUsb->Prio = USB_GetHighPrio(pUsb); //保存该任务优先级
pbuf = pUsb->pBuff[pUsb->Prio];
for (i = 0; i < buffnums; i++){
length = pUsb->Max[pUsb->Prio] - pUsb->Cnt; //计算未发送字节个数
if (length > 0){ //未发送字节数大于0
if (length >= eppsize) //写满缓冲区
length = D12_ReadEndpoint(endp,(INT8U)eppsize,pbuf + pUsb->Cnt);
else //写length个字节
length = D12_ReadEndpoint(endp,(INT8U)length,pbuf + pUsb->Cnt);
pUsb->Cnt = pUsb->Cnt + length; //发送计数器加length
}
if (pUsb->Cnt >= pUsb->Max[pUsb->Prio]){
pUsb->Max[pUsb->Prio] = 0;
pUsb->Sem = 0;
USB_DelPrio(pUsb, pUsb->Prio);
break;
}
endpstatus = D12_ReadEndpointStatus(endp); //读该端点状态寄存器
if ((endpstatus & 0x60) == 0)
break; //如果缓冲为空,立即跳出循环
}
pUsb->NoTask = 0;
}//end of if (pUsb->Sem == 0)
OS_EXIT_CRITICAL();
OS_ENTER_CRITICAL();
if (pUsb->Max[OSPrioCur] != 0){ //如果还没接收完成
if (timeout != 0){
pUsb->bSuspend[OSPrioCur] = 0;
OSTimeDly(timeout); //定义超时等待
}
else{
pUsb->bSuspend[OSPrioCur] = 1; //置位挂起标志
OSTaskSuspend(OSPrioCur);
}
}
OS_EXIT_CRITICAL(); //已接收完成,开中断
return (USB_RW_Result(endp,pUsb,timeout)); //返回接收结果
}
/*****************************************************************
** 函数名称: INT8U USB_WritePort(INT8U endp,INT32U eppsize,INT8U buffnums,CTRL_USB *pUsb,
INT8U *sendbuff,INT32U len,INT16U timeout)
** 功能描述:
** 输 入: INT8U endp : 端点索引号
INT32U eppsize : 该端点的的信息包大小
INT8U buffnums : 该端点发送缓冲区个数
CTRL_USB *pUsb : 该端点的接收或发送控制块指针
INT8U *sendbuff : 发送数据字节指针
INT32U len : 发送数据字节长度
INT16U timeout : 等待超时时间
** 输 出: 0 发送成功 > 0 发送失败(错误码)
******************************************************************/
INT8U USB_WritePort(INT8U endp,INT32U eppsize,INT8U buffnums,CTRL_USB *pUsb,
INT8U *sendbuff,INT32U len,INT16U timeout)
{
INT8U err,i;
INT32U length;
OS_ENTER_CRITICAL();
err = USB_RW_Param(pUsb,len,sendbuff); //填写USB接收或发送控制块参数
if (err != USB_NO_ERR)
{
OS_EXIT_CRITICAL();
return err;
}
if (pUsb->Sem == 0){ //该端点没有被独占
pUsb->Sem = 1; //独占该端点
pUsb->Cnt = 0; //发送计数值清0
pUsb->Prio = OSPrioCur; //保存独占该端点的任务优先级
for (i = 0; i < buffnums; i++){
length = pUsb->Max[pUsb->Prio] - pUsb->Cnt; //计算未发送字节个数
if (length > 0){ //未发送字节数大于0
if (length >= eppsize) //写满缓冲区
length = D12_WriteEndpoint(endp,(INT8U)eppsize,sendbuff + pUsb->Cnt);
else //写length个字节
length = D12_WriteEndpoint(endp,(INT8U)length,sendbuff + pUsb->Cnt);
pUsb->Cnt = pUsb->Cnt + length; //发送计数器加length
}
}
}//end of if (pUsb->Sem == 0)
OS_EXIT_CRITICAL();
OS_ENTER_CRITICAL();
if (pUsb->Max[OSPrioCur] != 0){ //还未发送完成
if (timeout != 0){
pUsb->bSuspend[OSPrioCur] = 0;
OSTimeDly(timeout); //定义超时等待
}
else{
pUsb->bSuspend[OSPrioCur] = 1;
OSTaskSuspend(OSPrioCur); //置位挂起标志
}
}
OS_EXIT_CRITICAL(); //发送完成
return (USB_RW_Result(endp,pUsb,timeout)); //返回发送结果
}
/*****************************************************************
** 函数名称: INT8U USB_RW_Param(CTRL_USB *pUsb,INT32U len,INT8U *buff)
** 功能描述: 填写USB接收或发送控制块有关参数
** 输 入: CTRL_USB *pUsb : USB接收或发送控制块指针
INT32U len : 接收或发送字节数
INT8U *buff : 接收或发送缓冲区指针
** 输 出: 0 调用成功 > 0 调用失败(错误码)
******************************************************************/
INT8U USB_RW_Param(CTRL_USB *pUsb,INT32U len,INT8U *pbuff)
{
OS_ENTER_CRITICAL();
if (bEPPflags.bits.configuration == 0){ //USB总线未配置完成
OS_EXIT_CRITICAL();
return (USB_ERR_NO_CONFIG); //USB总线未配置错误
}
if (pbuff == 0){
OS_EXIT_CRITICAL();
return (USB_ERR_BUFF_INVALID); //缓冲区指针无效错误
}
pUsb->pBuff[OSPrioCur] = pbuff; //保存该任务的接收缓冲区首址
pUsb->Max[OSPrioCur] = len; //保存要收发的字节数
USB_InsertPrio(pUsb,OSPrioCur); //插入等待任务列表中
OS_EXIT_CRITICAL();
return (USB_NO_ERR);
}
/*****************************************************************
** 函数名称: INT8U USB_RW_Result(INT8U endp,CTRL_USB *pUsb,INT16U timeout)
** 功能描述: 判断当前任务的数据是否收发成功
** 输 入: INT8U endp : 端点索引号
CTRL_USB *pUsb : USB接收或发送控制块指针
INT16U timeout : 超过等待时间
** 输 出: 0 收发成功 > 0 收发失败(错误码)
******************************************************************/
INT8U USB_RW_Result(INT8U endp,CTRL_USB *pUsb,INT16U timeout)
{
OS_ENTER_CRITICAL();
if (pUsb->Max[OSPrioCur] != 0){ //收发完成标志不为0,说明收发错误
if (pUsb->Prio == OSPrioCur){ //该任务占用了端点的收发资源
pUsb->Sem = 0; //必须释放资源
D12_ClearBuff(endp); //清空收发缓冲区
}
USB_DelPrio(pUsb,OSPrioCur); //将该任务从等待列表中删除
OS_EXIT_CRITICAL();
return (USB_ERR_WR_TIMEOUT); //收发超时错误
}else{
OS_EXIT_CRITICAL();
return (USB_NO_ERR); //收发成功
}
}
/************************************************************
下面的函数操作 USB接收或发送控制块等待列表
*************************************************************/
/************************************************************
** 函数名称: void USB_DelPrio(CTRL_USB *pUsb,INT8U prio)
** 功能描述: 将一任务从USB接收或发送控制块等待列表中删除
** 输 入: CTRL_USB *pUsb: USB接收或发送控制块指针
INT8U prio: 删除的任务的优先级
** 输 出: 无
************************************************************/
void USB_DelPrio(CTRL_USB *pUsb,INT8U prio)
{
if ((pUsb -> Tbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
pUsb -> Grp &= ~OSMapTbl[prio >> 3];
}
/************************************************************
** 函数名称: void USB_InsertPrio(CTRL_USB *pUsb,INT8U prio)
** 功能描述: 将一任务插入到USB接收或发送控制块等待列表中
** 输 入: CTRL_USB *pUsb: USB接收或发送控制块指针
INT8U prio: 插入任务的优先级
** 输 出: 无
************************************************************/
void USB_InsertPrio(CTRL_USB *pUsb,INT8U prio)
{
pUsb -> Grp |= OSMapTbl[prio >> 3];
pUsb -> Tbl[prio >> 3] |= OSMapTbl[prio & 0x07];
}
/*********************************************************************
** 函数名称: INT8U USB_GetHighPrio(CTRL_USB *pUsb)
** 功能描述: 取得USB接收或发送控制块等待列表中优先级最高的任务优先级
** 输 入: CTRL_USB *pUsb: USB 接收或发送控制块指针
** 输 出: 等待列表中优先级最高的任务优先级
**********************************************************************/
INT8U USB_GetHighPrio(CTRL_USB *pUsb)
{
INT8U x,y;
INT8U prio;
y = OSUnMapTbl[pUsb->Grp];
x = OSUnMapTbl[pUsb->Tbl[y]];
prio = (INT8U)((y << 3) + x);
return prio;
}
/*********************************************************************
** 函数名称: INT16U USB_Get_ZLGUSBD12_Ver()
** 功能描述: 取得 ZLG/USBD12 软件包的固件版本号
** 输 入: NULL
** 输 出: 固件版本号
**********************************************************************/
INT16U USB_Get_ZLGUSBD12_Ver(void)
{
return 0x0150; //当前固件软件版本号为1.50
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -