STM32_USB之完全雙緩存(包括發(fā)送和接收) -- 更新中斷處理
STM32的USB雙緩存接收代碼其實(shí)已經(jīng)可以在ST提供的USB示例代碼中找到,只要稍加修改,就可以得到將近1MB的數(shù)據(jù)接收性能。雖然Datasheet中說(shuō)明USB發(fā)送也同樣可以使用雙緩存,但并沒(méi)有示例代碼,由于為了測(cè)試性能,自己做了一個(gè),測(cè)試中沒(méi)有發(fā)現(xiàn)問(wèn)題,雖然對(duì)性能的提升不如在USB接收上實(shí)現(xiàn)雙緩存那么多。
注意:
FreeUserBuffer的作用是切換當(dāng)前的USB緩存。
1.接收雙緩沖:
EPX_OUT_Callback中,此代碼只是在ST的示例程序的基礎(chǔ)上稍加修改,并且不是偶寫(xiě)的,而是一個(gè)網(wǎng)友測(cè)試的:
if(GetENDPOINT(ENDP3) & EP_DTOG_TX)
{
FreeUserBuffer(ENDP3, EP_DBUF_OUT);
pkg_len = GetEPDblBuf0Count(ENDP3);
PMAToUserBufferCopy(buffer_out + count_out, ENDP3_RXADDR0, pkg_len);
}
else
{
FreeUserBuffer(ENDP3, EP_DBUF_OUT);
pkg_len = GetEPDblBuf1Count(ENDP3);
PMAToUserBufferCopy(buffer_out + count_out, ENDP3_RXADDR1, pkg_len);
}
2.發(fā)送雙緩沖:
發(fā)送雙緩沖也可以類(lèi)似的實(shí)現(xiàn),不過(guò)代碼要比接收雙緩沖復(fù)雜得多。不過(guò)了解原理的話(huà),應(yīng)該也差不多。
ST的STM32論壇里,也有人提出這個(gè)問(wèn)題:http://www.st.com/mcu/forums-cat-7768-23.html,不過(guò)一直都沒(méi)有人回答。
不過(guò)他的代碼還有一些問(wèn)題,或者可以說(shuō),他對(duì)原理還不夠了解。實(shí)際代碼還要比他的這個(gè)復(fù)雜。
中斷處理代碼:
// 有發(fā)送程序計(jì)算總共的數(shù)據(jù)表數(shù)量(包括ZLP)
// 每次IN中斷,則把總共要發(fā)送的數(shù)據(jù)包數(shù)量-1
usb_in_numofpackage--;
if(GetENDPOINT(ENDP2) & EP_DTOG_RX)
{
if(usb_in_numofpackage > 0)
{
// enable next package
// FreeUserBuffer的作用是切換當(dāng)前的緩存
// 如果還有數(shù)據(jù)包要發(fā)送,則切換緩存(數(shù)據(jù)已經(jīng)準(zhǔn)備好了)
FreeUserBuffer(ENDP2, EP_DBUF_IN);
}
// usb_in_data_remain是需要放入緩存的數(shù)據(jù)長(zhǎng)度
//在USB發(fā)送函數(shù)中,首先會(huì)填充2個(gè)緩沖,usb_in_data_remain為總長(zhǎng)度-2個(gè)緩沖的長(zhǎng)度
if(usb_in_data_remain > 0)
{
// 還有數(shù)據(jù)要發(fā)送
if(usb_in_data_remain > VIRTUAL_COM_PORT_DATA_SIZE)
{
len = VIRTUAL_COM_PORT_DATA_SIZE;
}
else
{
len = usb_in_data_remain;
}
//把數(shù)據(jù)拷貝到空閑的緩沖區(qū)中,并且設(shè)置長(zhǎng)度
UserToPMABufferCopy(buffer_in, ENDP2_TXADDR0, len);
SetEPDblBuf0Count(ENDP2, EP_DBUF_IN, len);
// usb_in_data_remain減去已經(jīng)放入緩沖區(qū)的長(zhǎng)度
usb_in_data_remain -= len;
//更新數(shù)據(jù)指針
buffer_in += len;
}
else
{
// 數(shù)據(jù)都已放入緩沖,設(shè)置空閑緩沖區(qū)長(zhǎng)度為0
SetEPDblBuf0Count(ENDP2, EP_DBUF_IN, 0);
}
}
else
{
if(usb_in_numofpackage > 0)
{
// enable next package
FreeUserBuffer(ENDP2, EP_DBUF_IN);
}
if(usb_in_data_remain > 0)
{
if(usb_in_data_remain > VIRTUAL_COM_PORT_DATA_SIZE)
{
len = VIRTUAL_COM_PORT_DATA_SIZE;
}
else
{
len = usb_in_data_remain;
}
UserToPMABufferCopy(buffer_in, ENDP2_TXADDR1, len);
SetEPDblBuf1Count(ENDP2, EP_DBUF_IN, len);
usb_in_data_remain -= len;
buffer_in += len;
}
else
{
SetEPDblBuf1Count(ENDP2, EP_DBUF_IN, 0);
}
}