Help with some UART raw transmit code

Status
Not open for further replies.

shawn

Well-known member
Hello. I'm trying to transmit some serial data from within an ISR. My issue is that when I send, say an array of a dozen or two dozen bytes, what comes out the serial port, as measured by a logic analyzer, is not quite the same as what I'm sending. Differences occur at the 7th byte and then every 2-4 bytes after that. For example, if I send
Code:
01 02 03 04 05 06 18 08
Out comes:
Code:
01 02 03 04 05 06 04 08

Here is my code:
Code:
void uart0_tx(const uint8_t *b, int len) {
  if (len <= 0) {
    return;
  }

  // Enable transmission
  UART0_C2 = UART_C2_TE;

  while (len > 0) {
    // Wait for space to be available
    while ((UART0_S1 & UART_S1_TDRE) == 0) ;
#ifdef HAS_KINETISK_UART0_FIFO
    do {
      UART0_D = *(b++);
      len--;
    } while (len > 0 && UART0_TCFIFO < 8);
#else
    UART0_D = *(b++);
    len--;
#endif  // HAS_KINETISK_UART0_FIFO
  }

  // Wait for transmission complete
  while ((UART0_S1 & UART_S1_TC) == 0);

  // Disable transmission
  UART0_C2 &= ~UART_C2_TE;
}

This feels similar to what serial1.c is doing when sending bytes. Can anyone spot anything I'm doing wrong?
 
Normally I read the S1 register before I write anything into the D register.

Example if you look at Serial1.c... In the interrupt function you will see:
Code:
		do {
			if (tail == head) break;
			if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
			[COLOR="#FF0000"]avail = UART0_S1;[/COLOR]
			n = tx_buffer[tail];
			if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
			UART0_D = n;
		} while (UART0_TCFIFO < 8);
 
Adding code that checks the UART_S1 register before each write to UART_D causes no transmission to happen. Changing UART_TWFIFO to 0 also causes no transmission. I think when working with a FIFO, UART_S1 does not need to be checked before sending each byte. It is my belief that my original code is correct.

I even tried disabling TXFE to emulate having no FIFO, and that doesn't seem to work either.

I'm stumped. Basically, my summary is this: The bytes being sent to UART_D aren't the same bytes that appear on the TX pin, when measured by a logic analyzer. Only some of the bytes are wrong and not all of them.
 
Last edited:
A detail I didn’t add: I’m connected to some RDM-capable Enttec hardware. Maybe there’s something electrically wrong. My next test will be to just test my serial transmit code by itself with nothing hooked up.
 
Here is an update: With just the serial TX code and nothing connected and no other code running, I'm seeing the correct bytes appear at Serial1 via a logic analyzer. It must be something to do with being connected to another device. I'll update more as I continue to try to figure this out...
 
Would be easier to just use the perfectly working teensyduino version.. or to adapt it to your - whatever system :)
 
Status
Not open for further replies.
Back
Top