Skip to content

Comments

kinetis/serial: Enable RTS as GPIO for RS485CONTROL#18417

Open
ghnotgood wants to merge 1 commit intoapache:masterfrom
ghnotgood:master
Open

kinetis/serial: Enable RTS as GPIO for RS485CONTROL#18417
ghnotgood wants to merge 1 commit intoapache:masterfrom
ghnotgood:master

Conversation

@ghnotgood
Copy link
Contributor

@ghnotgood ghnotgood commented Feb 20, 2026

When using CONFIG_UART?_RS485CONTROL, RTS pin is used as a transmit enable pin, i.e., it is set high when sending data and low otherwise. PIN_UART?_RTS is defined in the board.h file as the appropriate ALT functionality of the chip's port.

However, it may happen that PIN_UART?_RTS is wired to another pin of the chip that does not support the RTS as ALT functionality of the UART? in question. This commit addresses such a situation.

When UART?_RS485CONTROL_RTSISGPIO is set in menuconfig for the given UART?, it is expected that the PIN_UART?_RTS is defined as GPIO_OUTPUT, and the PIN_UART?_RTS is set high when sending data and low otherwise.

Summary

When working on NuttX port for our board, I found out that RTS of our UARTs 1, 2, and 3 are wired to Kinetis K60's pins that do not support RTS as an alternate functionality of the given UARTs. It looks like that in the original system of our board, RTSs were wired to GPIOs that were set to high when sending data and low otherwise. This is not considered in NuttX -- it is expected that only pins that support ALT functionality are used.

The commit in this PR allows any chip's pin that is defined as PIN_UART?_RTS and configured as GPIO_OUTPUT to work as RTS for the RS485CONTROL.

Impact

  • There is new UART configuration option UART?_RS485CONTROL_RTSISGPIO for each ? in 0 to 5. Each option depends on the appropriate UART?_RS485CONTROL.

  • The up_send procedure of the kinetis_serial.c is changed. If the configuration option is enabled for the given UART, the appropriate GPIO is set high before up_serialout and set low after 150 us delay when up_serialout returned.

Testing

On our board I work on, I configured CONFIG_UART1_RS485CONTROL_RTSISGPIO=y and CONFIG_UART2_RS485CONTROL_RTSISGPIO=y. UART0 is mapped to /dev/ttyS1 and UART1 is mapped to /dev/ttyS2. Then, I run the following test code:

static const char *devusart1 = "/dev/ttyS1";
static const char *devusart2 = "/dev/ttyS2";

int main(int argc, char **argv)
{
        _info("test from %s to %s", devusart1, devusart2);

        int from = open(devusart1, O_RDWR);
        if (0 > from) {
                _err("ERROR: failed to open %s: %s", devusart1, strerror(errno));
                return 1;
        } else {
                _info("from is %d", from);
        }   

        int to = open(devusart2, O_RDWR);
        if (0 > to) {
                _err("ERROR: failed to open %s: %s", devusart2, strerror(errno));
                return 1;
        } else {
                _info("to is %d", to);
        }   

        int i, r;
        uint8_t sb, rb; 

        for (i = 0; i < 260; i++) {
                sb = i;

                r = write(from, &sb, 1); 

                _info("(%d.) wrote %d byte(s): %d", i, r, sb);
                _info("now, try to read it");

                r = read(to, &rb, 1); 

                _info("read %d byte(s): %d", r, rb);

                rb++;

                _info("incremented what was read, sending back");

                r = write(to, &rb, 1); 

                _info("back %d byte(s): %d", r, rb);
                _info("now, try to back-read it");

                r = read(from, &sb, 1); 

                _info("back-read %d byte(s): %d", r, sb);

                if (1 + i == sb && 1 + i == rb) {
                        _info("GOOD %d -> %d == %d", i, sb, rb);
                } else {
                        _info("BAAD %d -> %d == %d", i, sb, rb);
                }   
        }   

        close(from);
        close(to);
        return 0;
}

and checked that the program finishes and the printed output makes sense.

When using CONFIG_UART?_RS485CONTROL, RTS pin is set high when sending
data and low otherwise. PIN_UART?_RTS is defined in the board.h file as
the appropriate ALT functionality of the chip's port.

However, it may happen that PIN_UART?_RTS is wired to another pin of the
chip that does not support the RTS as ALT functionality of the UART?  in
question. This commit addresses such a situation.

When UART?_RS485CONTROL_RTSISGPIO is set in menuconfig for the given
UART?, it is expected that the PIN_UART?_RTS is defined as GPIO_OUTPUT,
and the PIN_UART?_RTS is set high when sending data and low otherwise.

Signed-off-by: Jiri Vlasak <jvlasak@elektroline.cz>
@github-actions github-actions bot added Arch: arm Issues related to ARM (32-bit) architecture Size: M The size of the change in this PR is medium labels Feb 20, 2026
@cederom
Copy link
Contributor

cederom commented Feb 21, 2026

Thank you @ghnotgood :-)

  • Can you please provide runtime build and test logs? Build log can be short build invocation and summary to show that firmware builds fine. Runtime log should contain commands and their results from boot, uname -a, and your testing application run and execution.
  • So you are manually asserting the RTS pin before and deasserting after sending data. Are you sure that receive mode is available right after boot? Do you deassert RTS pin (low) by the custom board init or this is done by up_setup()?

{
/* We need some time before RTS is set low. 150 us works for LTM2881. */

up_udelay(150);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to disable the GPIO once UART_S1_TC interrupt is received instead of magic 150 us wait.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants