使用STM32的USB模块中后对USB缓冲区的认识
? STM32的USB模塊包緩沖區有512B,但是在STM32的參考手冊中的存儲器映像中卻表明0x40006000-0x400063ff,整整多了512B,怎么會這樣呢,同時在嘗試著編程時也遇到了一個問題:
在usb_core.c文件的Setup0_Process(void)這個函數中,有這么一段:
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 */
,我于是在這段之前加入調試以顯示收到什么數
? ? ? ? #ifdef DEBUG
? ? ? ? UARTSend_String("***??端點0收到SETUP數據??***\r\n");
? ? ? ? for(offset=0;offset<16;offset++)
? ? ? ? {
? ? ? ? ? ? ? ? UARTSend_Hex(*pBuf.b++);
? ? ? ? }
? ? ? ? #endif
結果串口調試顯示如下:
***??USB總線復位??***
***??USB總線CTR置位??***
***??進入端點0??***
***??端點0收到SETUP包??***
***??端點0收到SETUP數據??***
0x80 0x06 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x40 0x00 0x00 0x00
本來應該顯示0x80 0x06 0x00 0x01 0x00 0x000x40 0x00才對,不太明白怎么0x80 0x06和0x00 0x01 后面多了兩個 0x00 ,難道USB模塊還會將收到的數據跳著放嗎?
?后來反復看參考手冊,問了些人,才知道原來STM32的USB緩沖區是一個雙端口的RAM,CPU一端需要使用32位方式訪問,但USB模塊一端使用16位方式訪問。也就是說每個USB模塊中的地址*2才能對應到控制器中的實際地址,這樣每四個字節地址空間后兩個字節地址空間是空的。所以上面串口調試顯示的數據每正確兩個字節就會多出兩個字節的0x00。
這里也對STM32的USB庫函數中對緩沖區的操作函數做個說明:
在usb_men.c文件有這么一個函數
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++;
? }
它的作用是將緩沖區中的數據拷貝到你所定義的uint8_t Receive_Buffer[];數組中。其它地方都好理解,這里說說
? 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才能對應到控制器中的實際地址,在取得對應端點的緩沖區首地址后,將其(uint32_t*)強制指向uint32_t型,這樣每次*pdwVal++,pdwVal的地址都增加4個字節,并且每次都會有四個字節的數據讀出。
在for循環中,*(uint16_t*)pbUsrBuf++ = *pdwVal++;這句重點說說,++與指針*同優先級,結合順序為至右向左結合,因此相當于*((uint16_t*)pbUsrBuf++),先*(uint16_t*)pbUsrBuf賦值只取*pdwVal++的32位數據的前16位,然后再將pbUsrBuf加上1個字節。到這里,前面定義的uint8_tReceive_Buffer[];數組中就有兩個數組變量被賦值了,但這時地址還指增加一個字節,因此還需要pbUsrBuf++;讓其指向Receive_Buffer[];的下下個數組變量。一次循環,知道讀出所有數據。
轉自http://blog.csdn.net/ringstart/article/details/6822377
轉載于:https://www.cnblogs.com/findstr/archive/2012/03/14/2803693.html
總結
以上是生活随笔為你收集整理的使用STM32的USB模块中后对USB缓冲区的认识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到自己生儿子打什么奖
- 下一篇: ZFS 常见问题解答 及 ZFS Boo