data logging: 3 kByte/sec serial in, going to microSD (SDFAT) out

Thank you so much fat16lib for coding up an example so quickly! I made the RX_BUFFER_SIZE 128 change to HardwareSerial.cpp as suggested, and made just a few changes to your code. Below is the version that's working for me- I added a few comments to myself, I think the only real change I made is to drop down to half speed on the SPI bus, given my poor wiring configuration at the moment.

This code does "mostly" work for me. Randomly, maybe once every few thousand lines, I get some dropped characters. Right now my packet format contains six comma-separated hex values, and below is an example showing one too-long line due to dropped characters (line #7524 from my log file, in this case). It seems every "so often" there is a long pause for writing. Perhaps my uSD card is just too slow, I have a faster one on order. Also, I guess I should try formatting it first; this card already had some other files on it.

Sample data from recorded file:
[...]
41,2B,29,29,158,0
3E,30,25,27,154,0
3F,2F,25,28,15E,0
3F,30,2D,28,155,0
3F,32,25,29,15C,0
43,35,26,28,154,0
3E,32,24,29,15D,0
3E,39,2C,2A,154,0
3F,2D,2B3F,33,25,28,15B,0
40,32,2B,2C,15E,0
3F,32,25,28,155,0
[...]
// Serial data logger example
//
// To achive maximum speed, increase the size of the Serial buffer.
// Edit \hardware\arduino\cores\arduino\HardwareSerial.cpp
// Make the buffer as large as possible in this line for Arduino 0022
// #define RX_BUFFER_SIZE 128
// In Arduino 1.0 edit this line
// #define SERIAL_BUFFER_SIZE 64
//
#include <SdFat.h>
SdFat sd;
SdFile file;

const uint8_t SdChipSelect = SS_PIN;  // default is Arduino digital pin 10

// Idle time for sync call.  If Serial is idle for this time call sync.
const uint32_t IDLE_SYNC_TIME_MSEC = 1000;

// Maximum time between sync() calls in milliseconds.  If MAX_SYNC_TIME_MSEC is
// set to zero, you must provide a way to stop the program and close the file.
// You can also stop the serial stream for at least IDLE_SYNC_TIME_MSEC to
// flush the last data to the file.
const uint32_t MAX_SYNC_TIME_MSEC = 1000;
//------------------------------------------------------------------------------
// pin for error LED
const uint8_t ERROR_LED_PIN = 3;

// Error codes repeat as errno short blinks with a delay between codes.
const uint8_t ERROR_INIT  = 1;  // SD init error
const uint8_t ERROR_OPEN  = 2;  // file open error
const uint8_t ERROR_WRITE = 3;  // write error
const uint8_t ERROR_SYNC  = 4;  // sync error
void errorBlink(uint8_t errno) {
  uint8_t i;
  while (1) {
    for (i = 0; i < errno; i++) {
      digitalWrite(ERROR_LED_PIN, HIGH);
      delay(200);
      digitalWrite(ERROR_LED_PIN, LOW);
      delay(200);
    }
    delay(1600);
  }
}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);            // highest working serial port speed
  
  pinMode(ERROR_LED_PIN, OUTPUT);  // error signal output on this pin
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!sd.init(SPI_HALF_SPEED, SdChipSelect)) {
    errorBlink(ERROR_INIT);
  }
  
  if (!file.open("SERLOG.CSV", O_WRITE | O_CREAT | O_APPEND)) {
    errorBlink(ERROR_OPEN);
  }
}
//------------------------------------------------------------------------------
// cluster for last sync
uint32_t syncCluster = 0;

// time of last sync
uint32_t syncTime = 0;

// write time
uint32_t writeTime = 0;

uint8_t buf[26];    // longest expected serial packet
void loop() {
  uint8_t n = Serial.available();
  if (n > sizeof(buf)) {
    n = sizeof(buf);
  } else if (n == 0) {  // no serial characters to handle... Is it time to SYNC yet?
    if ((millis() - writeTime) < IDLE_SYNC_TIME_MSEC) return;
    if (!file.sync()) errorBlink(ERROR_SYNC);
    return;
  }
  for (uint8_t i = 0; i < n; i++) { // load n serial characters into our write buffer
    buf[i] = Serial.read();
  }
  if (file.write(buf, n) != n) {  // ...and write to SD card
    errorBlink(ERROR_WRITE);
  }
  writeTime = millis();
  
  // never sync if zero
  if (MAX_SYNC_TIME_MSEC == 0) return;
  
  if (syncCluster == file.curCluster()
    && (millis() - syncTime) < MAX_SYNC_TIME_MSEC) return;
    
  if (!file.sync()) {
    errorBlink(ERROR_SYNC);
  }
  syncCluster = file.curCluster();
  syncTime = millis();  
}