Pages: [1]   Go Down
Author Topic: Arduino locking up inside of Serial.write  (Read 918 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am dealing with a puzzling issue in my Arduino code, perhaps you can help. The setup is as follows:

I have an Arduino Uno communicating over Serial to a console program on OSX written using termios. For reference, the OSX application uses posix file descriptors and grand central dispatch to perform reads, though neither of these appears to be at fault. The baud rate is set at 460800 - lowering it has no effect on the problem.

The two devices use a packet structure to communicate over serial. Writes on the Arduino side are executed by taking data out of a buffer and writing it using Serial.write, like so:

Code:
uint8_t buffer[BUFFER_SIZE]; // BUFFER_SIZE has max value of 95 bytes

Serial.write(PREAMBLE); // PREAMBLE Is a constant that identifies new data

for (uint8_t i=0; i < BUFFER_SIZE; i++) {
Serial.write(buffer[i]);
}

During setup(), three packets are transmitted and are received without issue on the terminal. Once loop() has started, the terminal sends a packet to the device, which is received in a manner similar to:

Code:
void loop()
{
if (Serial.available())
{
// do Serial.read() until we detect the end of the packet (~10 bytes in this case), then stop

// write a response here
}
}

I should note that Serial.read() is only called until the end of the meaningful data is received, NOT until Serial.available() is false. The response is written in the form described above. serialEvent() is not used in this program.

The issue arises when the response is written - specifically the arduino stalls completely. I have managed to figure out (using LEDs) that the lock up takes place in HardwareSerial.cpp on line 390:

Code:
size_t HardwareSerial::write(uint8_t c)
{
  int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE;

  // If the output buffer is full, there's nothing for it other than to
  // wait for the interrupt handler to empty it a bit
  // ???: return 0 here instead?
  while (i == _tx_buffer->tail)    //    <-- PROGRAM STALLS HERE
;

  _tx_buffer->buffer[_tx_buffer->head] = c;
  _tx_buffer->head = i;

  sbi(*_ucsrb, _udrie);
 
  return 1;
}

The comments suggest that the necessary interrupt is not getting triggered. Even after googling around, I am at a loss as to how this could happen. A possible explanation is presented here: http://bleaklow.com/2012/02/29/why_im_ditching_the_arduino_software_platform.html

Any idea why the interrupt is not being triggered, or how Serial.write could be stalling indefinitely?

Cheers,
gcross2
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 201
Posts: 8669
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you have code anywhere in an ISR or which disables interrupts?
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Once loop() has started, the terminal sends a packet to the device, which is received in a manner similar to:
Well, perhaps the answer is similar to

Post your real code. All of it.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 211
Posts: 13479
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you send and receive simultaneously at 460800?

I used serial at 345600 baud many times without problem.

An idea, when testing high Serial speeds I found out that 500000 is a more stable speed than 460800 as 500K is a whole divider of the clock speed.
Give it a try.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry for the delayed reply, I've been having some computer difficulties. Apparently the FTDI serial to USB driver for the older Arduinos cause OSX 10.8 to fail at boot. That problem is unrelated to this one, however.

Do you have code anywhere in an ISR or which disables interrupts?

Nope, all my code is in setup() + loop().

An idea, when testing high Serial speeds I found out that 500000 is a more stable speed than 460800 as 500K is a whole divider of the clock speed.
Give it a try.

Termios will not allow me to use 500k - it produces an 'invalid argument' error. Additionally, even standard baud rates like 9600 and 115200 do not solve the issue.

Post your real code. All of it.

The code is spread across multiple files, so I shortened it while asking the question.

In any case, the error was in the Arduino code. Turns out I was using Arduino 1.0.1. The bug, which has been presented in the blog posting I linked, was fixed in 1.0.3. My bad for not checking for updates.
Logged

Pages: [1]   Go Up
Jump to: