Serial.flush?

Status
Not open for further replies.

duff

Well-known member
Does Serial.flush() actually block until all the bytes are transfered when configured for RAWHID or Serial for that matter? I'm having a problem where if I'm send a string, call Serial.flush() then go to sleep the serial transmission gets cut off before it's done sending or doesn't send at all indicating that the flush is not waiting for all the bytes to send before moving on. I have to put in delay before sleeping. I thought this was fixed some time ago?

Code:
#include <LowPower_Teensy3.h>


TEENSY3_LP LP = TEENSY3_LP();


void callbackhandler() {

  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
}


void setup() {
  delay(2000);
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(0, INPUT_PULLUP);
  attachInterrupt(0, callbackhandler, RISING);
}


void loop() {
  Serial.println("abcdefghijklmnopqrstuvwxyz1234567890");
  Serial.flush();
  //delay(100);[COLOR=#ff0000] //Need this to print to serial monitor before sleeping![/COLOR]
  LP.Sleep();
}
 
Does Serial.flush() actually block until all the bytes are transfered when configured for RAWHID or Serial for that matter?

No, not really. This has never been fully implemented.

The trouble is the low-level USB stack doesn't provide visibility to the high-level side for when packets queued for transmission have actually been sent and acknowledged by the USB host. This may happen someday, but probably in the very distant future, if ever. It will require more code inside the USB interrupt, and more data structures per endpoint to give the status info back to the higher level, since the actual packet buffers are returned to the free memory pool after transmission is done.

This is the kind of thing that needs to be done very carefully. The USB stack today has excellent performance. It's easy to wreck the efficiency, and still get full USB speed utilization, but with less CPU time left over. I care very deeply about having a lot of leftover CPU time, so we can build awesome things on top of the USB. Over the next couple years, I plan to build a lot more USB stuff and higher level "middleware" libraries. So I'm reluctant to risk bloat in the USB stack.

For now, and probably for quite a long time, a brief delay will be needed as a workaround. Delay of 1 ms, plus 1 ms per buffered packet should be plenty, since the USB host almost always sends an IN token on every USB frame.

This is a bug. I've created a new issue on github, so it won't be forgotten.

https://github.com/PaulStoffregen/cores/issues/43
 
Ok thanks for the info I'm reading up on the USB spec now, I'm wondering if cutting off the USB transmission mid stream and shutting off the USB clocks will have ill effects on the device or host? From what limited material I've read I haven't figured out what happens if the (host/device)? doesn't see an EOP and then the J State. Heck I don't even know what putting the cpu into low power state does to the USB controller, it's really confusing right now.

Also does your USB stack utilize the suspend state? I set it implicitly before going to sleep if that matters.
 
Hey @duff. It's funny how I seem to keep finding you addressing the same things I have questions about. I'm trying to get USB to work reliably when transitioning through low power and reset situations. I find if I wait enough time before shutting the USB device down and enabling low power operation the windows host drops the connection cleanly and when you start USB back up it opens it up again cleanly. But sometimes things get hung up and you have to unplug and replug the USB connector. Certainly, knowing when flushing output was complete would help but I'm not sure what all the other related issues are. Just wanted to mention that I'll be hunting through this stuff too as a side project over the next few weeks. I'll post back if I find anything useful.
 
Also does your USB stack utilize the suspend state?

No, not really.

There's this interrupt, but today it's merely ignored.

https://github.com/PaulStoffregen/cores/blob/master/teensy3/usb_dev.c#L913

Other stuff should probably be done too, for excellent low-power response. What, I'm honestly not sure. Well, I might have an idea or too, but I don't have any definitive answers. The truth is I've mostly ignored suspend and low power stuff so far. After a couple more products are released, and I've managed to publish another audio library version with lots of stuff people want, and maybe a few other things... well, eventually, I'd like to really work on pervasive low-power support. But it's a distant priority, with so many other things pending that people really, *really* want.
 
Hey @duff. It's funny how I seem to keep finding you addressing the same things I have questions about. I'm trying to get USB to work reliably when transitioning through low power and reset situations.

Good to hear, what I wanted to do was make it so I don't have to reopen the serial monitor in the Arduino IDE when sleeping but to no avail. It enumerates every time it wakes back up. I was testing it in LLS sleep mode. Also it seems the USB buffer get all jumbled up when printing after sleeping. Not sure how to tackle that, I don't have USB analyzer.

But it's a distant priority, with so many other things pending that people really, *really* want.

Fair enough... can't wait to see the new products.

When you do decide to do the low power stuff, It seems you could do the VLLS wakeup startup code (ResetHandler) a bit different. Don't think the teensy needs to go through the whole startup code as if we came out of normal reset which could make it faster to get to user code. I'm working on it so I'll post it if I get it working.
 
I did find a Freescale post about resetting a Windows USB connection:
https://community.freescale.com/message/436041
I find if I include:
USB0_CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG;
Statement in my code that disables USB that Windows does close out the connection before I reset the processor. When the processor starts back up the connection comes back. I'm still trying to experiment with delays and the order of operations on the host to allow reliable reconnects from an application. But I can get it to work if I delay long enough after disabling the pull up and triggering the restart to close the host side USB virtual terminal connection that I can reconnect without having to pull out and replug the USB connection.

Just an FYI.
 
what I wanted to do was make it so I don't have to reopen the serial monitor in the Arduino IDE when sleeping but to no avail. It enumerates every time it wakes back up. I was testing it in LLS sleep mode. Also it seems the USB buffer get all jumbled up when printing after sleeping. Not sure how to tackle that, I don't have USB analyzer.

Hi Duff, So, from everything I found it's a Windows issue that you have to close a virtual serial USB connection before it enumerates again or else the Windows driver gets hung up. Supposedly no way around it. So there isn't a way to keep the Arduino serial monitor open (or any host program). BTW, in my case I only allow USB communication for certain periods while plugged in (say 1 minute after a button push or 1 minute after some communication). I stay out of low power mode during those periods. Since our device is plugged in, the Teensy is getting powered from USB and our battery is getting charged.

I did add the code to lower and raise the D+ pullup to the USB disable/enable code to force a new enumeration. But I think that just the act of forcing the USB into suspend mode for over 3 msec causes the host to shut down the connection anyways. There is some way to handle all this more cleanly through some sort of target request but it looks complicated and what I'm doing works well enough for my use case. The Freescale embedded USB stack that is freely available at Freescale USB stack has code to support this suspend/resume stuff but I gave up on trying to do anything with it relative to Paul's nice USB code.

Last thing. I just bit the bullet and put delays in after doing IO and before shutting down the USB to allow the data to flush through to the host. I agree it would be nice if there was a programmatic way to get notification of that happening.
 
The USB sleep (LLS) thing is quite frustrating and I'm still looking at how to handle it in the most graceful way. The most perplexing problem I found is printing to the serial monitor after sleeping. The USB stack is not handling data transmission right after sleep, missing data. Here is example to show what i mean based on my latest library snooze.
Code:
// USE RAW HID
#include <Snooze.h>


SnoozeBlock config;


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  config.setTimer(1000); //sleep for 1000 msec.
}


void loop() {
  Snooze.deepSleep( config );// Sleeping in LLS sleep mode
  delay(1);
  for(int i = 0; i < 20; i++) {
    Serial.printf("Index: %i\n", i);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(20);
    digitalWrite(LED_BUILTIN, LOW);
    delay(20);
  }
  Serial.println();
}
I'm thinking it's going to take a real look at Pauls USB stack to handle this right. I've tried in both HID and Serial modes of USB and the same thing, printing right after sleeping will mess up or miss the data sent. Also if you use dtr in Serial mode it will still register as connected after waking from sleep even though the USB seems to enumerated again. I'm wondering if reseting the USB like in the ResetHandler would be how to go about this?

I think the Serial Flush thing will be quite useful for sleeping teensy's and probably many other things.

Anyway hopefully this thread can be used as a reference for anyone wanting help tackle this problem. Once I get this project I'm working on now (non low-power) I can devote more attention to the whole USB thing. Maybe I'll even bite the bullet and get a USB analyzer.
 
Status
Not open for further replies.
Back
Top