2008-11-22
评论2
楼主 2008/11/22 13:29:03
在这个ISTR_CTR()函数中,定义了EP0、1、2的传输方式以及各自的缓冲描述符,其中EP0是默认端口,负责完成USB设备的枚举,一般情况是不需要更改的。其他端点配置则需根据实际应用而决定,如何设置请仔细理解STM32的参考手册。
值得说明的是STM32的端点RX/TX缓冲描述表是定义在PMA中的,他是基于分组缓冲区描述报表寄存器(BTABLE)而定位的,各端点RX/TX缓冲描述表说明是数据存储地址以及大小,这个概念需要了解,ST提供的固件很含糊,为此,我在usb_regs.h文件中进行了重新定义,如下:
// USB_IP Packet Memory Area base address
#define PMAAddr (0x40006000L)
// Buffer Table address register
#define BTABLE ((volatile unsigned *)(RegBase + 0x50))
// *****************************************************************************
// Packet memory area: Total 512Bytes
// *****************************************************************************
#define BASEADDR_BTABLE 0x0000
// *****************************************************************************
// PMAAddr + BASEADDR_BTABLE + 0x00000000 : EP0_TX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x00000002 : EP0_TX_COUNT
// PMAAddr + BASEADDR_BTABLE + 0x00000004 : EP0_RX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x00000006 : EP0_RX_COUNT
//
// PMAAddr + BASEADDR_BTABLE + 0x00000008 : EP1_TX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x0000000A : EP1_TX_COUNT
// PMAAddr + BASEADDR_BTABLE + 0x0000000C : EP1_RX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x0000000E : EP1_RX_COUNT
//
// PMAAddr + BASEADDR_BTABLE + 0x00000010 : EP2_TX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x00000012 : EP2_TX_COUNT
// PMAAddr + BASEADDR_BTABLE + 0x00000014 : EP2_RX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x00000016 : EP2_RX_COUNT
//
// PMAAddr + BASEADDR_BTABLE + 0x00000018 : EP3_TX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x0000001A : EP3_TX_COUNT
// PMAAddr + BASEADDR_BTABLE + 0x0000001C : EP3_RX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x0000001E : EP3_RX_COUNT
//
// PMAAddr + BASEADDR_BTABLE + 0x00000020 : EP4_TX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x00000022 : EP4_TX_COUNT
// PMAAddr + BASEADDR_BTABLE + 0x00000024 : EP4_RX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x00000026 : EP4_RX_COUNT
//
// PMAAddr + BASEADDR_BTABLE + 0x00000028 : EP5_TX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x0000002A : EP5_TX_COUNT
// PMAAddr + BASEADDR_BTABLE + 0x0000002C : EP5_RX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x0000002E : EP5_RX_COUNT
//
// PMAAddr + BASEADDR_BTABLE + 0x00000030 : EP6_TX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x00000032 : EP6_TX_COUNT
// PMAAddr + BASEADDR_BTABLE + 0x00000034 : EP6_RX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x00000036 : EP6_RX_COUNT
//
// PMAAddr + BASEADDR_BTABLE + 0x00000038 : EP7_TX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x0000003A : EP7_TX_COUNT
// PMAAddr + BASEADDR_BTABLE + 0x0000003C : EP7_RX_ADDR
// PMAAddr + BASEADDR_BTABLE + 0x0000003E : EP7_RX_COUNT
// *****************************************************************************
//
// PMAAddr + BASEADDR_BTABLE + (0x00000040 - 0x000001FF) : assigned to data buffer
//
// *****************************************************************************
#define BASEADDR_DATA (BASEADDR_BTABLE + 0x00000040)
// ENP0
#define ENDP0_PACKETSIZE 0x40
#define ENDP0_RXADDR BASEADDR_DATA
#define ENDP0_TXADDR (ENDP0_RXADDR + ENDP0_PACKETSIZE)
// ENP1
#define ENDP1_PACKETSIZE 0x40
#define ENDP1_RXADDR (ENDP0_TXADDR + ENDP0_PACKETSIZE)
#define ENDP1_TXADDR (ENDP1_RXADDR + ENDP1_PACKETSIZE)
// ENP2
#define ENDP2_PACKETSIZE 0x40
#define ENDP2_RXADDR (ENDP1_TXADDR + ENDP1_PACKETSIZE)
#define ENDP2_TXADDR (ENDP2_RXADDR + ENDP2_PACKETSIZE)
// ENP3
#define ENDP3_PACKETSIZE 0x40
#define ENDP3_RXADDR (ENDP2_TXADDR + ENDP2_PACKETSIZE)
#define ENDP3_TXADDR (ENDP3_RXADDR + ENDP3_PACKETSIZE)
// ENP4
#define ENDP4_PACKETSIZE 0x40
#define ENDP4_RXADDR (ENDP3_TXADDR + ENDP3_PACKETSIZE)
#define ENDP4_TXADDR (ENDP4_RXADDR + ENDP4_PACKETSIZE)
// ENP5
#define ENDP5_PACKETSIZE 0x40
#define ENDP5_RXADDR (ENDP4_TXADDR + ENDP4_PACKETSIZE)
#define ENDP5_TXADDR (ENDP5_RXADDR + ENDP5_PACKETSIZE)
// ENP6
#define ENDP6_PACKETSIZE 0x40
#define ENDP6_RXADDR (ENDP5_TXADDR + ENDP5_PACKETSIZE)
#define ENDP6_TXADDR (ENDP6_RXADDR + ENDP6_PACKETSIZE)
// ENP7
#define ENDP7_PACKETSIZE 0x40
#define ENDP7_RXADDR (ENDP6_TXADDR + ENDP6_PACKETSIZE)
#define ENDP7_TXADDR (ENDP7_RXADDR + ENDP7_PACKETSIZE)
这样,一般只要在PMA的大小区域内(512Bytes),修改端点EPnR的数据包大小就可以了,当然,实际情况可以根据需要进行更改。
楼主 2008/11/22 13:29:25
// *****************************************************************************
// Function Name : INT_ISTR_CTR
// Description : ISTR Correct Transfer Interrupt service routine.
// Input :
// Output :
// Return :
// *****************************************************************************
void INT_ISTR_CTR(void)
{
unsigned short wEPIndex;
unsigned short wValISTR;
unsigned short wValENDP;
while( ((wValISTR=GetISTR()) & ISTR_CTR) != 0 )
{
// Get the index number of the endpoints
wEPIndex = wValISTR & ISTR_EP_ID;
if(wEPIndex == 0)
{
// Set endpoint0 RX/TX status: NAK (Negative-Acknowlegment)
SetEPR_RXStatus(ENDP0, EP_RX_NAK);
SetEPR_TXStatus(ENDP0, EP_TX_NAK);
// Transfer direction
if((wValISTR & ISTR_DIR) == 0)
{
// DIR="0:" IN
// DIR="0" implies that EP_CTR_TX always 1
ClrEPR_CTR_TX(ENDP0);
CTR_IN0();
return;
}
else
{
// DIR="1:" SETUP or OUT
// DIR="1" implies that CTR_TX or CTR_RX always 1
wValENDP = GetEPR(ENDP0);
if((wValENDP & EP_CTR_TX) != 0)
{
ClrEPR_CTR_TX(ENDP0);
CTR_IN0();
return;
}
else if((wValENDP & EP_SETUP) != 0)
{
ClrEPR_CTR_RX(ENDP0);
CTR_SETUP0();
return;
}
else if((wValENDP & EP_CTR_RX) != 0)
{
ClrEPR_CTR_RX(ENDP0);
CTR_OUT0();
return;
}
}
}
// Other endpoints
else
{
wValENDP = GetEPR(wEPIndex);
SetEPR_RXStatus(wEPIndex, EP_RX_NAK);
SetEPR_TXStatus(wEPIndex, EP_TX_NAK);
if((wValENDP & EP_CTR_TX) != 0)
{
ClrEPR_CTR_TX(wEPIndex);
switch(wEPIndex)
{
case ENDP1: CTR_IN1(); break;
case ENDP2: CTR_IN2(); break;
case ENDP3: CTR_IN3(); break;
case ENDP4: CTR_IN4(); break;
case ENDP5: CTR_IN5(); break;
case ENDP6: CTR_IN6(); break;
case ENDP7: CTR_IN7(); break;
default: break;
}
}
if((wValENDP & EP_CTR_RX) != 0)
{
ClrEPR_CTR_RX(wEPIndex);
switch(wEPIndex)
{
case ENDP1: CTR_OUT1(); break;
case ENDP2: CTR_OUT2(); break;
case ENDP3: CTR_OUT3(); break;
case ENDP4: CTR_OUT4(); break;
case ENDP5: CTR_OUT5(); break;
case ENDP6: CTR_OUT6(); break;
case ENDP7: CTR_OUT7(); break;
default: break;
}
}
}
}
}
INT_ISTR_CTR()函数将各自响应事件提取出来,默认端点EP0也是最为复杂的,这个需要查看STM32的参考手册以及USB协议才能更好了解为何如此。到这里STM32 USB里数据传输事件就指向了各个对应的端点。下篇着重说明USB设备的枚举。