📄 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: usbDevLPC2400 固件程序 DMA 层源文件
**
**--------------------------------------------------------------------------------------------------------
** Created by: ZhengMingyuan
** Created date: 2005-08-08
** Version: 1.0
** Descriptions: The original version
**
**--------------------------------------------------------------------------------------------------------
** Modified by: LingGuilin
** Modified date: 2008-05-10
** Version: 1.1
** Descriptions: 处理传输短包数据的bug
** 修改部分代码以符合代码规范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: __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))) {
/* 端点中断传输结束 */
pstDD = __usbDevDMAGetDDPointer(ucEpIndex);
if ((pstDD->status & 0x1F) == DDS_OVER_RUN) { /* DMA错误 */
USBEpDMAEn = (INT32U)(0x01 << ucEpIndex); /* 重新使能该端点的DMA功能 */
}
if ((pstDD->status & 0x1F) == DDS_NORMAL_COMP) { /* DMA正常结束 */
if (ucEpIndex == 2) {
bEPPflags.bits.ep1_rxdma = 1; /* 标志逻辑端点1 DMA接收成功 */
}
if (ucEpIndex == 4) {
bEPPflags.bits.ep2_rxdma = 1; /* 标志逻辑端点2 DMA接收成功 */
}
}
USBEoTIntClr |= (INT32U)(0x01 << ucEpIndex); /* 清除传输结束中断状态寄存器 */
__usbDevDMAInitEndpointDD(ucEpIndex); /* 重新初始化DD */
if ((ucEpIndex % 2) != 0) {
USBEpIntEn |= (INT32U)(0x01 << ucEpIndex); /* 重新使能该端点从机中断 */
}
}
}
}
/*********************************************************************************************************
** Function name: __usbDevDMASystemError
** Descriptions: DMA 系统中断错误处理
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __usbDevDMASystemError (void)
{
unsigned long ulEpstat = 0;
INT8U ucEpIndex = 0;
ulEpstat = USBSysErrIntSt; /* 读取系统错误中断状态寄存器 */
for (ucEpIndex = 2; ucEpIndex < 5; ucEpIndex++) {
if(ulEpstat & ((INT32U)(0x01 << ucEpIndex))) {
__usbDevDMAInitEndpointDD(ucEpIndex); /* 重新初始化DD */
USBEpDMAEn = (INT32U)(0x01 << ucEpIndex); /* 重新使能该端点的DMA功能 */
USBSysErrIntClr |= (INT32U)(0x01 << ucEpIndex); /* 清除系统错误中断 */
if ((ucEpIndex % 2) != 0) {
USBEpIntEn |= (INT32U)(0x01 << ucEpIndex); /* 重新使能该 IN 端点从机中断 */
}
}
}
}
/*********************************************************************************************************
** Function name: __usbDevDMANewDDRequest
** Descriptions: DMA 新 DD 请求中断服务程序
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __usbDevDMANewDDRequest (void)
{
unsigned long ulEpstat = 0;
INT8U ucEpIndex = 0;
ulEpstat = USBNDDRIntSt; /* 读取新DD请求中断状态寄存器 */
for (ucEpIndex = 2; ucEpIndex <= 5; ucEpIndex++) {
if(ulEpstat & ((INT32U)(0x01 << ucEpIndex))) {
__usbDevDMAInitEndpointDD(ucEpIndex); /* 重新设置该端点的DD */
USBNDDRIntClr = (INT32U)(0x01 << ucEpIndex); /* 清除新DD请求中断 */
if ((ucEpIndex % 2) != 0) {
USBEpIntEn |= (unsigned long)(0x01 << ucEpIndex); /* 重新使能该端点从机中断 */
}
}
}
}
/*********************************************************************************************************
下面为 DMA 层的导出函数
*********************************************************************************************************/
/*********************************************************************************************************
** Function name: usbDevDMAInit
** Descriptions: 初始化LPC23xx USB设备控制器的DMA引擎
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void usbDevDMAInit (void)
{
__usbDevDMAInitUdcaTable(); /* 初始化UDCA表 */
__usbDevDMAInitEndpointDD(2); /* 初始化各端点的DD */
__usbDevDMAInitEndpointDD(3);
__usbDevDMAInitEndpointDD(4);
__usbDevDMAInitEndpointDD(5);
USBDMAIntEn = USBDMA_EOT_INT | /* 使能DMA的传输结束中断 */
USBDMA_NDD_INT | /* 使能DMA的新DD请求中断 */
USBDMA_ERR_INT; /* 使能DMA的系统错误中断 */
USBEpDMAEn = (0x01 << 2) | /* 使能端点DMA功能 */
(0x01 << 3) |
(0x01 << 4) |
(0x01 << 5);
}
/*********************************************************************************************************
** Function name: usbDevDMAService
** Descriptions: DMA 中断服务程序
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void usbDevDMAService (void)
{
unsigned long ulDmastat = 0;
ulDmastat = USBDMAIntSt; /* 读DMA中断状态寄存器 */
if (ulDmastat & USBDMA_EOT_INT) {
__usbDevDMATransferEnd(); /* 传输结束中断 */
}
if (ulDmastat & USBDMA_NDD_INT) {
__usbDevDMANewDDRequest(); /* 新DD请求中断 */
}
if (ulDmastat & USBDMA_ERR_INT) {
__usbDevDMASystemError(); /* 系统错误中断 */
}
}
/*********************************************************************************************************
** 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: usbDevDMASetTransLength
** Descriptions: 设置DMA传输长度
** input parameters: ucEpIndex 物理端点索引
** ulSetlen 设置传输字节长度
** output parameters: 无
** Returned value: 设置成功的传输字节长度
*********************************************************************************************************/
INT32U usbDevDMASetTransLength (INT8U ucEpIndex, INT32U ulSetlen)
{
DD_DESCRIPTOR *pDD = __usbDevDMAGetDDPointer(ucEpIndex); /* 取得 DD 指针 */
__usbDevDMAInitEndpointDD(ucEpIndex); /* 初始化DD */
if (ulSetlen > (pDD->control >> 16)) /* 长度超过本端点DMA缓冲区 */
ulSetlen = pDD->control >> 16;
pDD->control &= 0x0000FFFF;
pDD->control |= (ulSetlen << 16); /* 将设置长度写入DD */
return ulSetlen; /* 返回设置成功的字节长度 */
}
/*********************************************************************************************************
** 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模式 */
}
#endif
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -