Go Down

Topic: Arduino locking up inside of Serial.write (Read 977 times) previous topic - next topic

dicktasting

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: [Select]

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: [Select]

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: [Select]

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

johnwasser

Do you have code anywhere in an ISR or which disables interrupts?
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

PaulS

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.

robtillaart

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.
Rob Tillaart

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

dicktasting

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.

Go Up