Arduino locks up

arduino, c++, embedded

Solution

There are a number of issues that may or may not be causing a problem, but it should be fixed in any case. These comments are general in nature; I am not familiar with Arduino or its library specifically.

It is almost certainly inappropriate to issue a `Serial.write()` call in an interrupt handler (ISR). If the Serial object is interrupt driven, it will have an associated buffer. If that buffer is not large enough to take all the data, the function may block, which is a no no in an interrupt handler. Moreover, if the timer interrupt is a higher priority that the serial interrupt, you will cause a deadlock when `Serial.write()` blocks. 0x40 (64 bytes) seems like a likely buffer size for serial output, so that is likely the primary cause. If you can increase the buffer size that may make it work, but it remains a bad idea to perform potentially blocking operations in an ISR.

Even if serial output is polled rather than interrupt driven, your interrupt handler will take rather long, which is also a bad idea, but probably not the issue in this case, but at 9600,n,8,1, 64 characters will take 67 milliseconds to clear the transmit register.

`stateLED` and `frame` are shared variables (between interrupt and main contexts) and should therefore be declared volatile.

It is not shown in your fragment how and where `frame` is updated, but since the interrupt will occur asynchronously, any update to `frame` should be in a critical section - with at least the timer1 interrupt disabled.

Update

In the light of A.H.'s response I downloaded the source code and took a look. `Serial` is a static object of class `HardwareSerial` defined in \arduino-1.0\hardware\arduino\cores\arduino\hardwareSerial.cpp/.h. The transmit buffer length is indeed 64 bytes, and the `HardwareSerial::write()` function does "busy-wait" if the buffer is full. You will need to modify and re-build the source to extend the buffer or add a non-blocking version of `write()`.

This is however certainly the cause of the lock-up - the buffer will never empty because the transmit interrupt cannot be serviced while the timer1 interrupt is running.

Problem

The intention of the program below is to periodically output a dataframe on serial. The period is defined by a timed interrupt, every second. The code worked on Arduino IDE version 0022, but on 1.0 I can't get it working. When using the timer routine and `maxFrameLength` is set to `0x40` or higher, the controller locks up. When using 0x39 or lower, the program keeps running (indicated by the flashing LED). What's going wrong here and why? Is it a bug? Am I doing something wrong? I'm using http://code.google.com/p/arduino-timerone/downloads/detail?name=TimerOne-v9.zip for the timer routine on a Mega1280. ``` #include "TimerOne.h" #define LED 13 #define maxFrameLength 0x40 boolean stateLED = true; byte frame[ maxFrameLength ]; void sendFrame() { digitalWrite( LED , stateLED ); stateLED = !stateLED; Serial.write( frame, maxFrameLength ); // ptr + bytes to send } void setup() { pinMode( LED , OUTPUT ); Timer1.initialize( 1000000 ); // initialize timer1 with 1 second period Timer1.attachInterrupt( sendFrame ); Serial.begin( 9600 ); }; void loop() { }; ```

Original source