I've tried a variety of devices with the software serial. Originally I started testing with connecting to a APC SmartUPS at 2400 baud through a MAX232. When I was getting the unexplained lockups, I connected next to a PC serial port (again through the MAX232) so I could manually send data to the software serial. Trying to eliminate the MAX232 as the possible problem, I next connected directly to a ID-12 RFID module which outputs TTL-level serial (at 9600 baud). In all cases the results were the same and the software serial locks up after a few rapid characters. It's random as to how many characters make it before the lock.
I tried AFSoftSerial and get the same lockups.
I did some digging in the source and was able to confirm the problem is somewhere in the recv() called by the interrupts. Commenting out the code (but leaving the definition) in NewSoftSerial::recv() stops the lockups - but obviously also stops any data. In playing with the code I find that if I leave any more code then the initial digitalRead if, I get lockups. So this code doesn't lock up (but also obviously doesn't return any data).
void NewSoftSerial::recv()
{
char i, d = 0;
if (digitalRead(_receivePin))
return; // not ready!
/*
tunedDelay(_bitDelay - 8);
for (i=0; i<8; i++) {
//PORTB |= _BV(5);
tunedDelay(_bitDelay*2 - 6); // digitalread takes some time
//PORTB &= ~_BV(5);
if (digitalRead(_receivePin))
d |= (1 << i);
}
tunedDelay(_bitDelay*2);
// buffer full?
if ((_receive_buffer_tail + 1) % _NewSS_MAX_RX_BUFF == _receive_buffer_head)
return;
_receive_buffer[_receive_buffer_tail++] = d; // save new byte
if (_receive_buffer_tail == _NewSS_MAX_RX_BUFF)
_receive_buffer_tail = 0;
*/
}
I think the problem might either have something to do with calling the digitalRead function or simply having the code running during the interrupt taking too long. As a trivial case, I replaced the recv() function with:
void NewSoftSerial::recv()
{
if (digitalRead(_receivePin))
return; // not ready!
}
While the code will obviously return no data, I also get no lockups. If I add one more digitalRead() like this:
void NewSoftSerial::recv()
{
if (digitalRead(_receivePin))
return; // not ready!
if (digitalRead(_receivePin))
return; // not ready!
}
Then I get the lockups.
Another probably unrelated weirdness that I stumbled across is with the tunedDelay() assembly. While commenting out different bits of code to test, I found that if I had two calls to tunedDelay() one after another, I would get the following compile errors:
/var/tmp//cc0RgyXU.s: Assembler messages:
/var/tmp//cc0RgyXU.s:940: Error: register r24, r26, r28 or r30 required
I don't know AVR assembly so I can't really debug further. Maybe there's a word alignment problem when the two assembly blocks are placed one after another?
I can't explain why your tests work fine and every test I try fails with lockups. I've tried an Arduino NG, an Adafruit Boardurino, and a bare ATmega 168 on a breadboard with the Diecimila bootloader and get the same results with each (all at 16MHz). I've even tried different pins for the software serial with no change.
Hopefully this info helps.
Thanks