2019-07-12 01:15 AM
Hello everyone.
I'm writing a code for stm32f103c8t6 to perform a kind of USB->SPI bridge.
USB periph configured as Virtual COM, based on the VCP example.
USB library I'm using is USB-FS-Device-Lib.
USB on the STM is configured for Bulk transfer, using 64-byte Receive_Buffer. So, according to USB specification, the host shouldn't send packets with length more than 64 bytes. But..
When I send data through USB to the STM, I'm also monitoring the bus with WireShark, and, on the receiving side, I wrote a simple counter data_size that counts the incoming data and then it's being sent back to the host at the end of reception. Also, I'm monitoring the Receive_length.
So, the issue is that everything works fine as long as the host sends packet of length no more than 64 bytes. But sometimes occasionally it decides to send more, for instance, 79 bytes:
And the STM responds with Receive_length = 64, i.e. it just cuts the data length resulting in data loss.
And, what's interesting, the USB on the STM's side doesn't raise any flags, like PMAOVR or whatever. It just cuts the data length, resulting in data loss.
Here's what I see in the terminal:
I'm constantly sending a 79-byte file each 200 ms. Sometimes it works correctly, sometimes not.
Here's a piece of my code:
int main (void)
{
//Init USB
SystemInit();
Set_System();
Set_USBClock();
USB_Interrupts_Config();
USB_Init();
spi1_master_init(); //init spi1 in master mode
_Bool eof_flag = FALSE; //End of File flag
GPIO_SetBits(GPIOC,GPIO_Pin_13); //LED off
while (1)
{
if (bDeviceState == CONFIGURED)
{
CDC_Receive_DATA(); //Receive data from USB
if(Receive_length) //if there's some data
{
//monitor receive_length:
sprintf(str_tx,"REC_LEN:%d\r\n",Receive_length);
//wait until USB isn't busy:
while(!packet_sent){}
//send byte counter to the terminal:
CDC_Send_DATA ((uint8_t*)str_tx,strlen(str_tx));
//clear the last character:
if(Receive_length<sizeof(Receive_Buffer)) {Receive_Buffer[Receive_length] = '\0';}
//+ data_size until the end of file ('*') is reached:
data_size += Receive_length;
//search for end of file('*'):
uint8_t eof = search_string((char*)Receive_Buffer,"*");
//if '*' occured, raise flag:
if(eof) {eof_flag = TRUE;}
//SPI
if(spi_upd)
//spi_upd flag raised in EP3_OUT_Callback function
{
GPIO_ResetBits(GPIOA,GPIO_Pin_4); //NSS \__
for(uint8_t i=0;i<Receive_length;i++)
{
//send buffer via SPI:
byte_cnt = spi1_sendbyte(Receive_Buffer[i]);
}
GPIO_SetBits(GPIOA,GPIO_Pin_4); //NSS __/
spi_upd = FALSE; //lower spi flag
} //end if(spi_upd)
Receive_length = 0; //clear Receive_length
} //end if(Receive_length)
else //if Receive_length = 0
{
//if there was some data and flag is set:
if(eof_flag)
{
//data_size echo:
sprintf(str_tx,"BYTES_SENT:%d\r\n",data_size);
while(!packet_sent){}
//send to host:
CDC_Send_DATA ((uint8_t*)str_tx,strlen(str_tx));
data_size = 0; //clear data counter
eof_flag = FALSE; //clear end of file flag
Receive_Buffer[0] = '\0'; //clear buffer
}//end if (eof)
}//end else
}//end if (bDeviceState==CONFIGURED)
}//end while(1)
}//end main()
The program receives a file with a '*' character(indicates end of file) in the end. It sends current Receive_length value back to the host, then adds it to the data_size var and searches for the '*'. When it reaches the end of file, it sends back its total size.
The Receive_length is updated in EP3_OUT_Callback function each time the USB_CTR interrupt is generated.
I just can't understand why does the host send me more than 64 bytes sometimes and how to deal with it.
The OS is Windows 7 x64, the USB driver is STM VCP 1.5.0.
Would appreciate any help