How do I call fclose on a UART for which another task has a blocked fgetc call?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How do I call fclose on a UART for which another task has a blocked fgetc call?

916 Views
waynetaylor
Contributor II

I want to be able to dynamically disconnect the pins used by the UART from my DTE that is wired wrong on some products. Instead of having the UART drive Rx & Tx, I want to close the UART using fclose() and then reassign the pins as high impedance inputs with weak pull-down resistors. However... I have a task that uses a blocking UART read, fgetc(). So what is the proper way to dynamically start and stop using this UART?

I did find that a call to fgetc() drills all the way down to the serial ISR call, and when there is no character ready, it places the task in a task queue and changes it's state to suspended. What I don't know how to do is bring that task back to life, so it can release a mutex used to guard access to the Rx port.

Thanks,

Wayne Taylor

Tags (3)
0 Kudos
4 Replies

736 Views
matthewkendall
Contributor V

Do you actually need to unblock the other task and then close the port? It is perfectly possible to furtle with the low-level pin configuration while the port is open.

I have had a situation where some production test code needed to test the operation of serial port pins at a time where the port was already open by another task. This code worked:

        /* Do something horrid to test that RTS and CTS are looped back if appropriate */

        switch (port) {

        case 1: // RS232 lower

            _bsp_serial_io_init(3, IO_PERIPHERAL_PIN_MUX_DISABLE);

            lwgpio_init(&pinRTS, LWGPIO_PORT_E | LWGPIO_PIN7, LWGPIO_DIR_OUTPUT, LWGPIO_VALUE_LOW);

            lwgpio_init(&pinCTS, LWGPIO_PORT_E | LWGPIO_PIN6, LWGPIO_DIR_INPUT, LWGPIO_VALUE_LOW);

            lwgpio_set_functionality(&pinRTS, LWGPIO_MUX_E7_GPIO);

            lwgpio_set_functionality(&pinCTS, LWGPIO_MUX_E6_GPIO);

            lwgpio_set_value(&pinRTS, LWGPIO_VALUE_LOW); _time_delay(10);

            if (lwgpio_get_value(&pinCTS) != LWGPIO_VALUE_LOW) result = false;

            lwgpio_set_value(&pinRTS, LWGPIO_VALUE_HIGH); _time_delay(10);

            if (lwgpio_get_value(&pinCTS) != LWGPIO_VALUE_HIGH) result = false;

            _bsp_serial_io_init(3, IO_PERIPHERAL_PIN_MUX_ENABLE);

            break;

etc...

0 Kudos

736 Views
waynetaylor
Contributor II

I think it is one thing to meddle with the RTS & CTS lines, but if I manipulate the RX line, won't I create a break condition? I want the TX & RX lines to be high impedance and pulled slightly low because some equipment connected to my modem is wired wrong creating a high current draw. Also, won't the UART just drive the pin the way it needs when the next TX happens?

0 Kudos

736 Views
matthewkendall
Contributor V

I don't know what processor you are using; my example was for Kinetis. The way it works there, which is fairly common, is that there is a multiplexer associated with each pin which allows the pin to be driven by (or to drive) any one of a number of sources. Once you configure the pin to be connected to the GPIO driver logic rather than the UART peripheral, it no longer matters what the UART does. The UART's RX signal won't see the signals present on the input pin and the UART's Tx signal won't drive the output pin.

0 Kudos

736 Views
waynetaylor
Contributor II
0 Kudos