[cpp] view plaincopyprint?
#include
#include
#include "usbreg.h"
#include "usbuser.h"
#include "usbcore.h"
#include "usb_hw.h"
#define _DEBUG_
#include "debug.h"
#define USB_EP_NUM 4
/*端點緩沖區(qū)的開始地址
*因為每個緩沖塊都需要一個端點描術表
*而所有的端點描述表放在,USB緩沖區(qū)的首部
*此地址是相對于USB緩沖區(qū)的地址,我認為加上Offset更好些
*這里使用2個端點
*端點0與端點1
*此時EP_BUF_ADDR指向緩沖區(qū)的內容
*/
#define EP_BUF_ADDR (sizeof(EP_BUF_DSCR)*USB_EP_NUM)
/*USB緩沖區(qū)首地址包括緩沖區(qū)描述表,絕對地址*/
EP_BUF_DSCR * pBUF_DSCR = (EP_BUF_DSCR *) USB_PMA_ADDR;
/*端點空閑緩沖區(qū)地址
*用于指示目前為止USB緩沖區(qū)中還沒有分配的空閑地址的首地址*/
WORD FreeBufAddr;
/*功能:用于初始化USB的時鐘等部分
*參數(shù):無
*返回值:無
*/
void USB_Init(void)
{
printf("進入USB_Init,進行初始化rn");
//使能USB時鐘
RCC->APB1ENR |= (1<<23);
//使能USB中斷
/*因為USB低優(yōu)先級中斷的中斷號為20,而NVIC——IPRX
*寄存器用四位來存儲中斷優(yōu)先級,所以20/4=5 ,
*然后使能第20位中斷*/
NVIC->IPR[5] |=0x10;
NVIC->ISER[0]|=(1<<20);
}
/*功能:用于復位USB模塊
*參數(shù):無
*返回值:無
*/
/*現(xiàn)在以我的水平還搞不懂雙緩沖為何物,所以先不搞^-^*/
/*一些資料:
*USB低優(yōu)先級中斷(通道20):可由所有USB事件觸發(fā)(正確傳輸,USB復位等).
*USB高優(yōu)先級中斷(通道19):僅能由同步和雙緩沖批量傳輸事件觸發(fā),目的是保證最大的傳輸速率.
*USB喚醒中斷(通道42):由USB掛起模式的喚醒事件觸發(fā). OTG_FS_WKUP喚醒
*
*復位要執(zhí)行的內容可以參見rm0008 21.4.2節(jié)
*/
void USB_Reset(void)
{
PrintS("USB_Resetrn");
/*復位了嘛,那所有以前產生的中斷都沒有用了,清了完事!*/
ISTR=0;
/*通過設置CNTR來控制stm32的USB模塊的工作方式
*所有的USB事件中斷都是在低優(yōu)先級中斷(通道20)上處理的
*好吧就先使能這么多吧,先跑起來再說!
*/
CNTR= CNTR_CTRM | // 使能正確傳輸中斷
CNTR_RESETM | //使能復位中斷
CNTR_SUSPM | //使能掛起中斷
CNTR_WKUPM ; //使能喚醒中斷
FreeBufAddr = EP_BUF_ADDR; //此時FreeBuff指向第一個緩沖區(qū)首地址(不包括描述符表),相對地址
BTABLE = 0x00; //設置緩沖區(qū)描述表的位置仍是相對地址
/*為端點0設置緩沖區(qū)及各種控制位*/
pBUF_DSCR->ADDR_TX = FreeBufAddr;
FreeBufAddr+=8; //端點0設置為8個字節(jié),一般控制數(shù)據為8個字節(jié)
pBUF_DSCR->ADDR_RX = FreeBufAddr;
FreeBufAddr+=8;
/*在count_Rx字段中10~14bit用來表示緩沖區(qū)字節(jié)的快數(shù)
*而15bit用來表示塊的大小
*0---2byte
*1---1byte
*我們這里使用了8個字節(jié),bit15為0,所以應該((8<<10)>>1)即8<<9;
*至于count_Rx我們在發(fā)送時再來賦值
*/
pBUF_DSCR->COUNT_RX= 8 << 9;
/*設置端點0為控制端點,接收緩沖區(qū)有效
*低四位代表端點地址
*/
EPxREG(0) = EP_CONTROL | EP_RX_VALID;
/*使能USB模塊,并設置USB地址為0,以響應枚舉*/
DADDR = DADDR_EF | 0;
}
/*功能:復位一個端點
*參數(shù): 端點號
* EPNum:bit3~bit0 ----> 端點號
* EPNum:bit7 ----> 端點方向
*
*返回值:無
*/
/*其實就是將下一個要發(fā)送的數(shù)據包變成DATA0*/
void EP_Reset(DWORD EPNum)
{
DWORD num,var;
PrintS("EP_Resetrn");
/*獲得端點號,低四位為端點號*/
num = EPNum & 0x0F;
var = EPxREG(num);
/*如果bit7為1則將此端點的發(fā)送toggle置為0,
*否則將此端點的接收toggle置為0
*因為數(shù)據總是從data0數(shù)據包開始發(fā)送的
*/
if(EPNum & 0x80)
EPxREG(num) = var & (EP_MASK | EP_DTOG_TX);/*輸入端點*/
else
EPxREG(num) = var & (EP_MASK | EP_DTOG_RX);/*輸出端點*/
}
/*功能:連接或斷開USB功能
*參數(shù):true -->連接USB
* false-->關閉USB
*返回值:無
*/
void USB_Connect(BOOL turnon)
{
/*需要注意一點的事,所有的USB寄存器盡量用=而不要用與或非
*在編程手冊上有明確表明,這樣可能會導至出一些問題*/
printf("進入連接USB程序rn");
/*將USB強制復位*/
CNTR = CNTR_FRES;
// printf("test1rn");
/*因為剛連接所以應該跟才啟動一樣,將所有沒有處理的中斷給清理掉*/
ISTR=0;
// printf("test2rn");
if(turnon)
{
// printf("test3rn");
/*使能GPIOA,然后將PA.8置低,使USB
*的D+加1.5K上接電阻,使USB集線器識別了高速設備
*這樣才能讓USB識別
*/
RCC->APB2ENR |= (1 << 2); /* enable clock for GPIOA */
GPIOA->CRH &= ~(0x0f << 0 * 4); /* clear port PA8 */
GPIOA->CRH |= (0x03 << 0 * 4); /* PA6 General purpose output open-drain, max speed 50 MHz */
GPIOA->BRR = ( 1 << 8 ); /* reset PA8 (set to low) */
/*經過調試發(fā)現(xiàn),這個語句的本意是:復位USB模塊
*然后在此使能CNTR_RESETM即復位中斷標志
*至于端點0的初始化留在USB低優(yōu)先級中進行處理
*當然,我們也只開了低優(yōu)先級中斷^_^!*/
CNTR = CNTR_RESETM; /*此處只使能了復位中斷,*/
}
else
CNTR = CNTR_FRES | CNTR_PDWN ;/*復位并關閉*/
}
/*功能:設置端點狀態(tài)
*參數(shù):EPnum --->端點號
* stat --->要設置的狀態(tài)值
*返回值:無
*/
void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR * pEPD)
{
DWORD num,val;
//取得端點號
num = pEPD->bEndpointAddress & 0xf;
val = pEPD->wMaxPacketSize;
//如果是IN端點
if(pEPD->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK)
{
//此處我只想說pBUF_DSCR是指針,剩下的就是語法問題了
(pBUF_DSCR + num)->ADDR_TX = FreeBufAddr;
/*取2的倍數(shù),因為緩沖區(qū)都是字對齊的,注意此處如果大于1023會出現(xiàn)浪費現(xiàn)象
*因為USB_COUNTn