2
\$\begingroup\$

I've just integrated the code from ST's STM32 USB Virtual Com Port example (stm32_usb-fs-device_lib.zip from here) with my project in order to get the STM32 to appear as a Virtual Serial Port.

However the code example throttles the data it receives by having the callback function EP3_OUT_Callback block (in an interrupt) until all data is dealt with. The exact comment in the code is "USB data will be immediately processed, this allow next USB traffic being NAKed till the end of the USART Xfer"

In my project, I need to process the data that has been received in the main loop (outside of an interrupt), so I need a way of throttling the data that I get from USB without blocking in EP3_OUT_Callback.

What I would like is a function:

Do_Not_Call_EP3_OUT_Callback_Right_Now(bool yes_or_no);
Chetan Bhargava
4,6325 gold badges29 silver badges40 bronze badges
asked Oct 11, 2012 at 20:59
\$\endgroup\$
1
  • \$\begingroup\$ The more I look at this, the more I think that the answer could be calling SetEPRxStatus(ENDP3, EP_RX_?) and then setting it to EP_RX_VALID in the main loop when all data is processed. However I am unable to get this to work - so any input (or examples where this is done) would be appreciated. \$\endgroup\$ Commented Oct 12, 2012 at 9:13

2 Answers 2

1
\$\begingroup\$

I appear to have got this working:

void EP3_OUT_Callback(void) {
 ...
 //SetEPRxValid(ENDP3); //<-- Commented out
 SetEPRxStatus(ENDP3, Do_I_Have_Room_For_More_Data() ? EP_RX_VALID : EP_RX_NAK); //<-- Added this
}
void SOF_Callback(void) {
 if(bDeviceState == CONFIGURED) {
 SetEPRxStatus(ENDP3, Do_I_Have_Room_For_More_Data() ? EP_RX_VALID : EP_RX_NAK); //<-- Added this
 ...
 // Original TX code here
 }
}

What's happening is after getting data, and in the Start of Frame callback (every 1ms), I set whether the endpoint is accepting data.

Note: The docs never seem to say just how much data USB_SIL_Read will read - potentially leading to a buffer overrun. However I believe the maximum is what is in VIRTUAL_COM_PORT_DATA_SIZE - and this seems to work great for me.

This would appear to work - however I have no idea if it is the 'right' way of doing it. Please let me know if it's wrong and I'll update it!

answered Oct 12, 2012 at 11:22
\$\endgroup\$
1
  • \$\begingroup\$ Just to add, it seems that Windows will throw away packets of data after a few (5?) consecutive NAKs - making this work most of the time, but not when the micro is busy for any length of time \$\endgroup\$ Commented Sep 26, 2014 at 13:39
0
\$\begingroup\$

You should be able to do this by setting an atomic flag in the ISR that data is available, detecting that in the main loop to deal with it and then either sending the ack from there, or setting a flag so that it will be acked at the next opportunity

answered Oct 12, 2012 at 0:31
\$\endgroup\$
2
  • \$\begingroup\$ Do you have any example? The main loop knows data is there. The problem is that the ISR (or at least EP3_OUT_Callback) doesn't appear to explicitly ACK. Just the fact that EP3_OUT_Callback is called is an explicit ACK, and by then it is too late. \$\endgroup\$ Commented Oct 12, 2012 at 9:07
  • \$\begingroup\$ that last 'explicit' should be 'implicit'. I have a feeling that the STM32 has some hardware that handles the USB, so it may be a matter of telling that whether to send ACKs or not - rather than explicitly sending them from code. \$\endgroup\$ Commented Oct 12, 2012 at 9:17

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.