Serial.flush() and 32u4

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Serial.flush() is empty for Adafruit FONA. In Print.h:
virtual void flush() { /* Empty implementation for backward compatibility */ }

I need to make sure that all Serial.print() statements are completed before I enter sleep mode for the FONA, otherwise it will be subsequently woken up in Serial.print code (and crashes) instead of in loop().

Is there any code that can accomplish this?

 

Regards, Peter

Last Edited: Thu. Oct 19, 2017 - 10:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What did Adafruit support say when you asked them?

 

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That it "should" work. Well, it does not.

Regards, Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What did Adafruit support say when you told them that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The FONA is a radio, and is often the case will draw considerable power when transmitting, is your power supply adequate for this module?

I could not find on the Adafruit product page a spec sheet for the module with that info, so will leave that to the OP to find and post.

In any case, a small but complete sketch that demo's the problem should be posted for us to look at would be helpful, as of now, it's a shot in the dark!!!

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know that the FONA is power-hungry and that part is taken care of.

Code example as requested:

 

void setup()

{

Serial.begin(115200);

}

void loop()

{

Serial.println("Many characters Many characters Many characters Many characters Many characters Many characters ");

Serial.flush();  // This should flush the output buffer and wait until it's empty but it just skip past it

Sleep();          // This puts the FONA to sleep by means of  Low-Power library with the function: LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

                     // It works ok but the sleep is invoked before the output buffer is emptied so when the FONA is awakened by an external interrupt it resumes

                     // running code in Serial.print (and crashes of course) instead of resuming in loop()

}

 

Regards, Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

[never mind; responded to wrong thread]

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Thu. Oct 19, 2017 - 03:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

peakpeak wrote:
should flush the output buffer and wait until it's empty but it just skip past it

Looks like you're going to have to implement code to do that, then.

 

Or ask for such code from Sparkfun  Adafruit ...

 

EDIT

 

Adafruit - not Sparkfun.

 

blush

Last Edited: Thu. Oct 19, 2017 - 03:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your sketch does not compile, errors on Sleep();

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One thing to try if the radio supports a higher baud rate, it set to max baud rate.

The Arduino HW serial will not buffer high speed serial comms as the interrupt overhead becomes greater at higher baud rates, so they just don't do it.

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sleep() is just a placeholder for code invoking power down. What Sleep() does is explained in the comments. I was asked to produce a simple example and I did

Regards, Peter

Last Edited: Thu. Oct 19, 2017 - 03:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The radio part has nothing to do with this

Regards, Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil: Well, I have threads there too ... no joy as of yet ....

Regards, Peter

Last Edited: Thu. Oct 19, 2017 - 04:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Another possible workaround is use softserial, as it does not buffer TX so function will not return until all is sent.

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

I'm not sure if you understand the whole concept. The ATmega 32u4 has a BUILT-IN UART. You do not have options to select libraries there. It's part hardware, part software but neither SoftwareSerial nor HardwareSerial.

 

Regards, Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

peakpeak wrote:
 I was asked to produce a simple example

Actually, what Jim asked for - as is the usual request - was 

a small but complete sketch that demo's the problem

the point being to allow  others to reproduce the problem.

 

I have threads there too

Give links - so that people can see what has - and hasn't - already been covered.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

peakpeak wrote:
I'm not sure if you understand the whole concept. The ATmega 32u4 has a BUILT-IN UART. You do not have options to select libraries there. It's part hardware, part software but neither SoftwareSerial nor HardwareSerial.

 

Actually I do, so far you have shown only Arduino sketches which have both hardware(USART) and software(bit-bang) drivers.  The HW drivers are interrupt driven fifo buffered output, until the baud rate is too high,

or you bit-bang via softuart to any port pin pair, with out tx buffering.

Your problem stems from going to sleep before the serial.print has emptied its tx buffer and the library your using does not have a working flush function....

 

So, either up the baud rate to the the point a tx buffer is skipped and goes directly to the USART, or switch to using Softserial which does not have a tx buffer, or write your own USART tx function that does not buffer.

 

OR... state clearly you are not using Arduino libs, and tell us what you are using!

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I assume the OP is using a Leonardo?

 

Here's Serial.flush() built for a 328P:

void HardwareSerial::flush()
{
  while (_tx_buffer->head != _tx_buffer->tail)
 3d0:    fc 01           movw    r30, r24
 3d2:    86 85           ldd    r24, Z+14    ; 0x0e
 3d4:    97 85           ldd    r25, Z+15    ; 0x0f
 3d6:    dc 01           movw    r26, r24
 3d8:    a0 5c           subi    r26, 0xC0    ; 192
 3da:    bf 4f           sbci    r27, 0xFF    ; 255
 3dc:    fc 01           movw    r30, r24
 3de:    ee 5b           subi    r30, 0xBE    ; 190
 3e0:    ff 4f           sbci    r31, 0xFF    ; 255
 3e2:    2d 91           ld    r18, X+
 3e4:    3c 91           ld    r19, X
 3e6:    11 97           sbiw    r26, 0x01    ; 1
 3e8:    80 81           ld    r24, Z
 3ea:    91 81           ldd    r25, Z+1    ; 0x01
 3ec:    28 17           cp    r18, r24
 3ee:    39 07           cpc    r19, r25
 3f0:    c1 f7           brne    .-16         ; 0x3e2 <_ZN14HardwareSerial5flushEv+0x12>
    ;
}
 3f2:    08 95           ret

Ugly, but the upshot is likely that the buffer is actually flushed before returning.  I expect there is still at least one character in the TX hardware buffer and shift register though.  For that the OP will have to test hardware flags himself.

 

Now for the 32U4:

00000494 <_ZN7Serial_5flushEv>:
    return c;
}

void Serial_::flush(void)
{
    USB_Flush(CDC_TX);
 494:    83 e0           ldi    r24, 0x03    ; 3
 496:    0e 94 66 04     call    0x8cc    ; 0x8cc <_Z9USB_Flushh>
}
 49a:    08 95           ret

 

... and:

000008cc <_Z9USB_Flushh>:
    UEDATX = d;
}

static inline void SetEP(u8 ep)
{
    UENUM = ep;
 8cc:    80 93 e9 00     sts    0x00E9, r24
}

static inline u8 FifoByteCount()
{
    return UEBCLX;
 8d0:    80 91 f2 00     lds    r24, 0x00F2
}

void USB_Flush(u8 ep)
{
    SetEP(ep);
    if (FifoByteCount())
 8d4:    88 23           and    r24, r24
 8d6:    19 f0           breq    .+6          ; 0x8de <_Z9USB_Flushh+0x12>
    UEINTX = 0x6B;    // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
}

static inline void ReleaseTX()
{
    UEINTX = 0x3A;    // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
 8d8:    8a e3           ldi    r24, 0x3A    ; 58
 8da:    80 93 e8 00     sts    0x00E8, r24
 8de:    08 95           ret

By all appearances (and without digging deeper), this achieves the same result with the USB hardware.

 

Mind you this was built with Arduino 1.0 and AVR GCC 4.3.4, but I expect the OP should be seeing something similar, yet he complained that:

In Print.h:
virtual void flush() { /* Empty implementation for backward compatibility */ }

OP, we need more.  Where is this Print.h?  Where did you get it?  None of the files name Print.h which shipped with any of the versions of the Arduino IDE I have on my machine contain that empty function.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
I expect there is still at least one character in the TX hardware buffer and shift register though. For that the OP will have to test hardware flags himself.

Indeed -- I did a bit of Googling on Serial.Flush.  Never found any code, but there were mentions in discussions about TXC.

 

The head<=>tail would work -- IF the buffering mechanism uses TXC and not UDRE, and only updates the rig buffer pointers/indices at TXC time (versus when the byte is stuffed into UDR).

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
did a bit of Googling on Serial.Flush. Never found any code,
Well some code here:

 

https://github.com/arduino/Ardui...

 

HOWEVER the code there on github.com/arduino/ appears to be the "basic" (Uno etc) variant. What I'm not clear of is where online one finds sources for the 32U4 based Arduino as that clearly does "USB stuff" that is going to be quite different.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK a bit more poking about got me to here:

 

https://github.com/arduino/Ardui...

 

and from thence to...

 

https://github.com/arduino/Ardui...