@paramilo - Again it is hard to know what to suggest again as I don't really know what all you tested and what did not work.
For example in the modifications I suggested, only fixed certain cases of this, in particular when you call something like:
Serial2.write(buf, cnt);
It does NOT fix the case if you call Serial2.write(60);
That is because Serial2.write(60) does not call serial2_write, but instead calls serial2_putchar, so you would need to put in the same level of changes there.
I put in some instrumentation into a local copy of Serial2, and I believe it took care of those issues.
So for example with your test program, try, changing serial2_putchar function to be:
Code:
void serial2_putchar(uint32_t c)
{
uint32_t head, n;
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return;
head = tx_buffer_head;
if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART1_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= SERIAL2_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART1_C3 = (UART1_C3 & ~0x40) | ((n & 0x100) >> 2);
UART1_D = n;
tx_buffer_tail = tail;
}
} else if (priority >= 256) {
yield(); // wait
}
}
tx_buffer[head] = c;
transmitting = 1;
tx_buffer_head = head;
if (transmit_pin) transmit_assert();
UART1_C2 = C2_TX_ACTIVE;
}
Again I moved the transmit_assert to be just before we setup to do output...
Edit: Looks like I still get a few. I have gotten about 4 in maybe an hour...
Edit2: I disabled interrupts around the trnasmit_assert and UART1_C2 setting like:
Code:
__disable_irq();
if (transmit_pin) transmit_assert();
debug_in_serial2_write = 1; // BUGBUG DEBUG
UART1_C2 = C2_TX_ACTIVE;
__enable_irq();
debug_in_serial2_write = 0; // BUGBUG DEBUG
Disregard the debug_in ... I am using that in test app, where I put an ISR on the falling edge of the Enable pin to then check to see if I am in that window...
Code:
#define TTL_SERIAL (&Serial2)
uint32_t error_count = 0;
uint32_t error_count_prev = 0;
void setup()
{
Serial.begin(115200);
while (!Serial && millis() < 4000) ;
Serial.println("Start test");
Serial.flush();
delay(3000);
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
pinMode(13, OUTPUT);
Serial2.begin(1000000);
Serial2.transmitterEnable(5);
attachInterrupt(5, &tepin_interrupt, FALLING);
}
extern "C" {
extern volatile uint8_t debug_in_serial2_write;
}
void tepin_interrupt() {
if (debug_in_serial2_write) {
digitalWriteFast(4, !digitalRead(4));
error_count++;
}
digitalWrite(13, !digitalRead(13));
}
void loop()
{
while (1) {
for (uint16_t delay_us = 60; delay_us < 90; delay_us++) {
// send a burst of bytes
for (byte i = 50; i < 60; i++) {
Serial2.write(i);
}
// add a small interval so that we get next byte in, when the UART is already finsishing
// the transmission of the block above (i.e. UART1_C2 is in state TX_COMPLETING)
// On a Teensy 3.2 at 96Mhz 75 at 1Mbps did it for me.
// this is not deterministic so you need to look at several samples in the logic analyser
// some will be OK, others will exhibit the behaviour described
delayMicroseconds(delay_us);
Serial2.write(60);
if (error_count != error_count_prev) {
Serial.printf("Error %d: delay:%d\n", error_count, delay_us);
error_count_prev = error_count;
}
delay(2); // wait a bit to separate samples in the Logic analyser
}
}
}
It helped locate others before I made the chagnes