Arduino Randomly Freezing During Long Jobs

I've just looked at the HardwareSerial code for writing characters, and I think there may be a race condition bug in it. Here is the code from HardwareSerial.cpp (Arduino 1.02):

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)
    ;
	
  _tx_buffer->buffer[_tx_buffer->head] = c;
  _tx_buffer->head = i;
	
  sbi(*_ucsrb, _udrie);
  // clear the TXC bit -- "can be cleared by writing a one to its bit location"
  transmitting = true;
  sbi(*_ucsra, TXC0);
  
  return 1;
}

The first problem is that the 2-byte volatile variables tx_buffer and tx_buffer->tail are written and read without disabling interrupts. However, as the sizes of the transmit buffer are less than 256 bytes, the upper byte will always be zero, so the situation of inconsistent upper/lower bytes will not arise.

The second possible problem is the instruction to clear the TXC (transmit complete) bit. I can't see what this is for and I think it is harmful. Suppose this line is executed around the time that the UART has just finished sending a character. Then the TXC interrupt may never occur, and the data in the ring buffer will never be sent. So the ring buffer will become full and Serial.print calls will block.

If I'm right, then your code is blocking while trying to write "OK" to the serial port. You might like to try lighting a LED just before making the call and turning it off immediately after it returns. That will tell you whether the program is locking up during that call or somewhere else.

Are you definitely receiving "OK" at the PC for the penultimate command that gets executed?

EDIT: after looking at the code some more, I see that it is the Data Register Empty interrupt that is being used, not the Transmit Complete Interrupt. So my analysis above is not correct. However, I still don't see the point of clearing the TXC bit, and I still think it may be worth your while using an LED to see whether the lockup is inside Serial.print.