使用STM32的USB模块中后对USB缓冲区的认识
? STM32的USB模塊包緩沖區(qū)有512B,但是在STM32的參考手冊(cè)中的存儲(chǔ)器映像中卻表明0x40006000-0x400063ff,整整多了512B,怎么會(huì)這樣呢,同時(shí)在嘗試著編程時(shí)也遇到了一個(gè)問(wèn)題:
在usb_core.c文件的Setup0_Process(void)這個(gè)函數(shù)中,有這么一段:
uint16_t offset = 1;?
if (pInformation->ControlState != PAUSE)
??{
? ? pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */
? ? pInformation->USBbRequest = *pBuf.b++; /* bRequest */
? ? pBuf.w += offset;??/* word not accessed because of 32 bits addressing */
? ? pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */
? ? pBuf.w += offset;??/* word not accessed because of 32 bits addressing */
? ? pInformation->USBwIndex??= ByteSwap(*pBuf.w++); /* wIndex */
? ? pBuf.w += offset;??/* word not accessed because of 32 bits addressing */
? ? pInformation->USBwLength = *pBuf.w; /* wLength */
??}??
這其中又不太明白為什么需要pBuf.w += offset;而且后面的解釋也不太懂 /* word not accessed because of 32 bits addressing */
,我于是在這段之前加入調(diào)試以顯示收到什么數(shù)
? ? ? ? #ifdef DEBUG
? ? ? ? UARTSend_String("***??端點(diǎn)0收到SETUP數(shù)據(jù)??***\r\n");
? ? ? ? for(offset=0;offset<16;offset++)
? ? ? ? {
? ? ? ? ? ? ? ? UARTSend_Hex(*pBuf.b++);
? ? ? ? }
? ? ? ? #endif
結(jié)果串口調(diào)試顯示如下:
***??USB總線復(fù)位??***
***??USB總線CTR置位??***
***??進(jìn)入端點(diǎn)0??***
***??端點(diǎn)0收到SETUP包??***
***??端點(diǎn)0收到SETUP數(shù)據(jù)??***
0x80 0x06 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x40 0x00 0x00 0x00
本來(lái)應(yīng)該顯示0x80 0x06 0x00 0x01 0x00 0x000x40 0x00才對(duì),不太明白怎么0x80 0x06和0x00 0x01 后面多了兩個(gè) 0x00 ,難道USB模塊還會(huì)將收到的數(shù)據(jù)跳著放嗎?
?后來(lái)反復(fù)看參考手冊(cè),問(wèn)了些人,才知道原來(lái)STM32的USB緩沖區(qū)是一個(gè)雙端口的RAM,CPU一端需要使用32位方式訪問(wèn),但USB模塊一端使用16位方式訪問(wèn)。也就是說(shuō)每個(gè)USB模塊中的地址*2才能對(duì)應(yīng)到控制器中的實(shí)際地址,這樣每四個(gè)字節(jié)地址空間后兩個(gè)字節(jié)地址空間是空的。所以上面串口調(diào)試顯示的數(shù)據(jù)每正確兩個(gè)字節(jié)就會(huì)多出兩個(gè)字節(jié)的0x00。
這里也對(duì)STM32的USB庫(kù)函數(shù)中對(duì)緩沖區(qū)的操作函數(shù)做個(gè)說(shuō)明:
在usb_men.c文件有這么一個(gè)函數(shù)
void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
? uint32_t n = (wNBytes + 1) >> 1;/* /2*/
? uint32_t i;
? uint32_t *pdwVal;
? pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);
? for (i = n; i != 0; i--)
? {
??? *(uint16_t*)pbUsrBuf++ = *pdwVal++;
??? pbUsrBuf++;
? }
它的作用是將緩沖區(qū)中的數(shù)據(jù)拷貝到你所定義的uint8_t Receive_Buffer[];數(shù)組中。其它地方都好理解,這里說(shuō)說(shuō)
? pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);
? for (i = n; i != 0; i--)
? {
??? *(uint16_t*)pbUsrBuf++ = *pdwVal++;
??? pbUsrBuf++;
? }
首先是pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);這里wPMABufAddr * 2之所以要*2就是前面所述的USB模塊中的地址*2才能對(duì)應(yīng)到控制器中的實(shí)際地址,在取得對(duì)應(yīng)端點(diǎn)的緩沖區(qū)首地址后,將其(uint32_t*)強(qiáng)制指向uint32_t型,這樣每次*pdwVal++,pdwVal的地址都增加4個(gè)字節(jié),并且每次都會(huì)有四個(gè)字節(jié)的數(shù)據(jù)讀出。
在for循環(huán)中,*(uint16_t*)pbUsrBuf++ = *pdwVal++;這句重點(diǎn)說(shuō)說(shuō),++與指針*同優(yōu)先級(jí),結(jié)合順序?yàn)橹劣蚁蜃蠼Y(jié)合,因此相當(dāng)于*((uint16_t*)pbUsrBuf++),先*(uint16_t*)pbUsrBuf賦值只取*pdwVal++的32位數(shù)據(jù)的前16位,然后再將pbUsrBuf加上1個(gè)字節(jié)。到這里,前面定義的uint8_tReceive_Buffer[];數(shù)組中就有兩個(gè)數(shù)組變量被賦值了,但這時(shí)地址還指增加一個(gè)字節(jié),因此還需要pbUsrBuf++;讓其指向Receive_Buffer[];的下下個(gè)數(shù)組變量。一次循環(huán),知道讀出所有數(shù)據(jù)。
轉(zhuǎn)自http://blog.csdn.net/ringstart/article/details/6822377
轉(zhuǎn)載于:https://www.cnblogs.com/findstr/archive/2012/03/14/2803693.html
總結(jié)
以上是生活随笔為你收集整理的使用STM32的USB模块中后对USB缓冲区的认识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 梦到自己生儿子打什么奖
- 下一篇: ZFS 常见问题解答 及 ZFS Boo