📄 usbdevdma.c
字号:
/****************************************Copyright (c)****************************************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.embedtools.com
**
**--------------File Info---------------------------------------------------------------------------------
** File name: usbDevDMA.c
** Latest modified Date: 2008-05-10
** Latest Version: 1.1
** Descriptions: ZLG_USB2400 Device 软件包DMA层源文件
**
**--------------------------------------------------------------------------------------------------------
** Created by: ZhengMingyuan
** Created date: 2005-01-06
** Version: 1.0
** Descriptions: The original version
**
**--------------------------------------------------------------------------------------------------------
** Modified by: LingGuilin
** Modified date: 2008-05-10
** Version: 1.1
** Descriptions: 修改部分代码以符合代码规范v1.2
**
*********************************************************************************************************/
#include "config.h"
#if DMA_ENGINE_EN
/*********************************************************************************************************
** Function name: __usbDevDMAInitUdcaTable
** Descriptions: 初始化DMA引擎的UDCA头寄存器和UDCA表
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __usbDevDMAInitUdcaTable (void)
{
INT32U *pulUDCA = NULL;
USBUDCAH = USB_RAM_ADDRESS; /* 初始化UDCA头寄存器 */
pulUDCA = (INT32U *)USBUDCAH; /* 取出UDCA寄存器值 */
pulUDCA[2] = (INT32S)DD_ADDRESS_EP02; /* 建立UDCA表 */
pulUDCA[3] = (INT32S)DD_ADDRESS_EP03;
pulUDCA[4] = (INT32S)DD_ADDRESS_EP04;
pulUDCA[5] = (INT32S)DD_ADDRESS_EP05;
}
/*********************************************************************************************************
** Function name: __usbDevDMAGetDDPointer
** Descriptions: 获取端点的DD指针
** input parameters: ucEpIndex 物理端点索引
** output parameters: 无
** Returned value: 指向端点DD的指针
*********************************************************************************************************/
DD_DESCRIPTOR *__usbDevDMAGetDDPointer (INT8U ucEpIndex)
{
INT32U ulDdaddr = 0;
ulDdaddr = DD_BASE_ADDRESS + DD_SIZE * (ucEpIndex - 2); /* 计算地址 */
return (DD_DESCRIPTOR *)((INT32U *)ulDdaddr); /* 转换指针类型 */
}
/*********************************************************************************************************
** Function name: __usbDevDMAInitEndpointDD
** Descriptions: 初始化端点的DD
** input parameters: ucEpIndex 物理端点索引
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __usbDevDMAInitEndpointDD (INT8U ucEpIndex)
{
DD_DESCRIPTOR *pstDD = __usbDevDMAGetDDPointer(ucEpIndex); /* 取得 DD 指针 */
pstDD->next_dd_addr = 0; /* 清零两个成员 */
pstDD->status = 0;
switch(ucEpIndex) {
case 0x02:
pstDD->control = (EP1_PACKET_SIZE << 5) + /* 写端点数据包大小 */
(EP02_DMA_BUFFER_LENGTH << 16); /* 写DMA缓冲区大小 */
pstDD->start_addr = DMA_BUFFER_ADDR_EP02; /* 写DMA缓冲区起始地址 */
break;
case 0x03:
pstDD->control = (EP1_PACKET_SIZE << 5) +
(EP03_DMA_BUFFER_LENGTH << 16);
pstDD->start_addr = DMA_BUFFER_ADDR_EP03;
break;
case 0x04:
pstDD->control = (EP2_PACKET_SIZE << 5) +
(EP04_DMA_BUFFER_LENGTH << 16);
pstDD->start_addr = DMA_BUFFER_ADDR_EP04;
break;
case 0x05:
pstDD->control = (EP2_PACKET_SIZE << 5) +
(EP05_DMA_BUFFER_LENGTH << 16);
pstDD->start_addr = DMA_BUFFER_ADDR_EP05;
break;
default:
break;
}
}
/*********************************************************************************************************
** Function name: __usbDevDMASetTransLength
** Descriptions: 设置DMA传输长度
** input parameters: ucEpIndex 物理端点索引
** ulSetLen 设置传输字节长度
** output parameters: 无
** Returned value: 设置成功的传输字节长度
*********************************************************************************************************/
INT32U __usbDevDMASetTransLength (INT8U ucEpIndex, INT32U ulSetLen)
{
DD_DESCRIPTOR *pstDD = __usbDevDMAGetDDPointer(ucEpIndex); /* 取得 DD 指针 */
__usbDevDMAInitEndpointDD(ucEpIndex); /* 初始化DD */
if (ulSetLen > (pstDD->control >> 16)) { /* 长度超过本端点DMA缓冲区 */
ulSetLen = pstDD->control >> 16;
}
pstDD->control &= 0x0000FFFF;
pstDD->control |= (ulSetLen << 16); /* 将设置长度写入DD */
return ulSetLen; /* 返回设置成功的字节长度 */
}
/*********************************************************************************************************
** Function name: __usbDMAGetRecLength
** Descriptions: 取得当前DMA传输数据长度
** input parameters: ucEpIndex 物理端点索引
** output parameters: 无
** Returned value: DMA当前已传输字节数
*********************************************************************************************************/
INT32U __usbDevDMAGetRecLength (INT8U ucEpIndex)
{
DD_DESCRIPTOR *pstDD = __usbDevDMAGetDDPointer(ucEpIndex); /* 取得 DD 指针 */
return (pstDD->status & 0xFFFF0000) >> 16; /* 返回长度值 */
}
/*********************************************************************************************************
** Function name: usbDevDMAStartIN
** Descriptions: 启动 IN 端点的 DMA 传输
** input parameters: ucEpIndex 物理端点索引
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __usbDevDMAStartIN (INT8U ucEpIndex)
{
USBEpDMAEn |= (INT32U)(0x01 << ucEpIndex); /* 使能该端点的DMA功能 */
USBEpIntEn &= (INT32U)(~(0x01 << ucEpIndex)); /* 设置IN端点工作在DMA模式 */
}
/*********************************************************************************************************
** Function name: usbDevDMAGetBuffer
** Descriptions: 获取DMA缓冲区首地址
** input parameters: ucEpIndex 物理端点索引
** output parameters: 无
** Returned value: 物理端点的缓冲区指针
*********************************************************************************************************/
INT8U* __usbDevDMAGetBuffer (INT8U ucEpIndex)
{
const INT32U DmaTbl[4] = {DMA_BUFFER_ADDR_EP02, DMA_BUFFER_ADDR_EP03,
DMA_BUFFER_ADDR_EP04, DMA_BUFFER_ADDR_EP05};
return (INT8U *)((INT32U *)DmaTbl[ucEpIndex - 2]); /* 返回指向DMA缓冲区的指针 */
}
/*********************************************************************************************************
** Function name: __usbDevDMAReadISR
** Descriptions: DMA模式下,USB 端点接收中断服务程序
** input parameters: pstUsb: USB接收与发送控制结构体指针
** ucEpIndex: 物理端点号
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __usbDevDMAReadISR (CTRL_USB *pstUsb, INT8U ucEpIndex)
{
INT8U *pucDstBuf = NULL;
INT8U *pucSrcBuf = NULL;
INT32U ulRecLen = 0;
INT32U ulLeftLen = 0;
if (pstUsb->bEpUsed != 0) { /* 有任务在等待接收 */
ulLeftLen = pstUsb->len - pstUsb->cnt; /* 计算未接收字节数 */
pucDstBuf = pstUsb->buff;
if (ulLeftLen > 0) {
pucSrcBuf = __usbDevDMAGetBuffer(ucEpIndex); /* DMA接收缓冲区地址 */
ulRecLen = __usbDevDMAGetRecLength(ucEpIndex); /* 收到的字节数 */
if (ulLeftLen >= ulRecLen) {
memcpy(pucDstBuf + pstUsb->cnt, pucSrcBuf, ulRecLen);
pstUsb->cnt = pstUsb->cnt + ulRecLen; /* 累加已读取字节数 */
} else {
memcpy(pucDstBuf + pstUsb->cnt, pucSrcBuf, ulLeftLen); /* 从DMA缓冲区取出数据 */
pstUsb->cnt = pstUsb->cnt + ulLeftLen; /* 累加已读取字节数 */
}
}
if (pstUsb->cnt >= pstUsb->len) { /* 如果接收完毕 */
OSSemPost(Ctrl_Usb[ucEpIndex - 2].Ep_Sem);
} else {
USBEpDMAEn |= (INT32U)(0x01 << ucEpIndex); /* 使能该端点的DMA功能 */
ulLeftLen = pstUsb->len - pstUsb->cnt; /* 计算未读取字节数 */
__usbDevDMASetTransLength(ucEpIndex, ulLeftLen); /* 设置要接收的字节长度 */
}
}
}
/*********************************************************************************************************
** Function name: __usbDevDMAWriteISR
** Descriptions: DMA模式下,USB 端点发送中断服务程序
** input parameters: pstUsb: USB接收与发送控制结构体指针
** ucEpIndex: 物理端点号
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __usbDevDMAWriteISR (CTRL_USB *pstUsb, INT8U ucEpIndex)
{
INT8U *pucDstBuf = NULL;
INT8U *pucSrcBuf = NULL;
INT32U ulLeftLen = 0;
INT32U ulSetLen = 0;
if (pstUsb->bEpUsed != 0) {
/* 有任务在等待发送 */
if (pstUsb->cnt >= pstUsb->len) {
OSSemPost(Ctrl_Usb[ucEpIndex - 2].Ep_Sem); /* 数据全部发送完成 */
return;
}
ulLeftLen = pstUsb->len - pstUsb->cnt; /* 计算未发送字节数 */
pucSrcBuf = pstUsb->buff;
if (ulLeftLen > 0) {
pucDstBuf = __usbDevDMAGetBuffer(ucEpIndex);
ulSetLen = __usbDevDMASetTransLength(ucEpIndex,ulLeftLen);
memcpy(pucDstBuf, pucSrcBuf + pstUsb->cnt, ulSetLen);
pstUsb->cnt = pstUsb->cnt + ulSetLen;
__usbDevDMAStartIN(ucEpIndex); /* 启动 IN 端点的 DMA 传输 */
}
}
}
/*********************************************************************************************************
** Function name: __usbDevDMATransferEnd
** Descriptions: DMA方式端点传输数据结束中断服务程序
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __usbDevDMATransferEnd (void)
{
INT8U ucEpIndex = 0;
unsigned long ulEpIntState = 0;
DD_DESCRIPTOR *pstDD = NULL;
ulEpIntState = USBEoTIntSt; /* 读传输结束中断寄存器 */
for (ucEpIndex = 2; ucEpIndex <= 5; ucEpIndex++) {
if (ulEpIntState & ((INT32U)(0x01 << ucEpIndex))) {
/* 端点中断传输结束 */
if ((ucEpIndex % 2) != 0) {
USBEpIntEn |= (INT32U)(0x01 << ucEpIndex); /* 重新使能该端点从机中断 */
}
pstDD = __usbDevDMAGetDDPointer(ucEpIndex);
if ((pstDD->status & 0x1F) == DDS_OVER_RUN) { /* DMA错误 */
USBEpDMAEn = (INT32U)(0x01 << ucEpIndex); /* 重新使能该端点的DMA功能 */
}
if ((pstDD->status & 0x1F) == DDS_NORMAL_COMP) { /* DMA正常结束 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -