Author Topic: Different UARTs for send and recieve  (Read 14207 times)

Offline jharvey

  • Newbie
  • *
  • Posts: 7
    • View Profile
Different UARTs for send and recieve
« on: April 27, 2008, 06:48:06 PM »
Hey Mark,
I've checked through the documentation but haven't been able to find the answer to whether or not there is an easy way to use a different UART channel for sending and receiving.

With the default implementation, it looks like both use the SerialPortID which gets set to DEMO_UART in fnSetNewSerialMode.

It looks as if I will have to create a new SerialPortID using a different channel, that way I will have one for input and one for output.

Then I will have to replace all references to SerialPortID that are used in reads with SerialPortIDIn and all that are used in outs with SerialPortIDOut.

Is there an easier way to do this?

Thanks,
Jesse

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3240
    • View Profile
    • uTasker
Re: Different UARTs for send and recieve
« Reply #1 on: April 27, 2008, 07:37:33 PM »
Hi Jesse

For each UART you need a handle. This is allocated when the UART is opened and then used to change the UART state (eg. enable TX or RX) and then send and receive over it.

Each UART has a channel number starting at 0 for UART0, continuing with 1, 2, 3 etc. for UARTs 1, 2, 3 etc. (the limit depends on the processor hardware).

This means that an open will configure one UART and afterwards the handle corresponds to this HW UART. This one UART handle can be used for input and output via this UART (it is not necessary to have one handle for input and one for output).
eg. fnWrite(SerialPortID, buffer, length); and fnRead(SerialPortID, buffer, length;

Assuming the processor has 3 UARTs the open can be repeated 3 times (with same or different paremeters) and then there are 3 handles (say, SerialPortID, SerialPortID1 and SerialPortID2 for UARTs 0, 1 and 2).

To send something over UART 1 use fnWrite(SerialPortID1, buffer, length); and to send something over UART2 use fnWrite(SerialPortID2, buffer, length);, etc.

When opening the serial port you pass the task responsible for handling receptions from it:
(eg. tInterfaceParameters.Task_to_wake = OWN_TASK;).

There can be one task for each UART input or one single task can handle all inputs.
To handle all inputs in one task, the task has to simply check each one when it is worken (eg.):

    while (fnMsgs(SerialPortID)) {
        // read reception from this UART
    }
    while (fnMsgs(SerialPortID1)) {
        // read reception from this UART
    }
    while (fnMsgs(SerialPortID2)) {
        // read reception from this UART
    }

If there is one task for each input it is a little more efficient since the task only has to check one serial port input.

Since Rx and Tx of a UART are actually independent (apart from Baud and configuration settings) it is possible to implement a connection with Tx from UART0 and Rx from UART1. In this case writes use SerialPortID and reads use SerialPortID1, however usually the RX and TX lines of a physical UART are used together.

To send the same data to all UARTs is very simple:
fnWrite(SerialPortID, buffer, length);
fnWrite(SerialPortID1, buffer, length);
fnWrite(SerialPortID2, buffer, length);
The same message is sent to all three outputs.


The following thread is possibly the best overview for using the serial interface:
http://www.utasker.com/forum/index.php?topic=54.msg220#msg220

Regards

Mark

Offline jharvey

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Different UARTs for send and recieve
« Reply #2 on: April 28, 2008, 02:49:13 PM »
Thanks for the reply Mark, that is what I figured....

I've done the following:
1) Made global variables for the interface parameters:
Code: [Select]
TTYTABLE tInterfaceParametersIn;
TTYTABLE tInterfaceParametersOut;

2) Modified fnSetNewSerialMode to set up the appropriate channel based on the additional param:
Code: [Select]
#ifdef SERIAL_INTERFACE
// After changes, we set up the new serial configuration
//
extern QUEUE_HANDLE fnSetNewSerialMode(unsigned char ucDriverMode, unsigned int uiUartChannel)
{
    //TTYTABLE tInterfaceParameters;                                       // table for passing information to driver
    //Jesse //tInterfaceParameters.Channel = DEMO_UART;                            // set UART channel for serial use
    if(uiUartChannel == 1)
    { 
    tInterfaceParametersIn.Channel = uiUartChannel;                            // set UART channel for serial use
    tInterfaceParametersIn.ucSpeed = temp_pars->temp_parameters.ucSerialSpeed; // baud rate
    tInterfaceParametersIn.Rx_tx_sizes.RxQueueSize = RX_BUFFER_SIZE;       // input buffer size
    tInterfaceParametersIn.Rx_tx_sizes.TxQueueSize = TX_BUFFER_SIZE;       // output buffer size
    tInterfaceParametersIn.Task_to_wake = OWN_TASK;                        // wake self when messages have been received
    #ifdef SUPPORT_FLOW_HIGH_LOW
    tInterfaceParametersIn.ucFlowHighWater = temp_pars->temp_parameters.ucFlowHigh;// set the flow control high and low water levels in %
    tInterfaceParametersIn.ucFlowLowWater = temp_pars->temp_parameters.ucFlowLow;
    #endif
    tInterfaceParametersIn.usConfig = temp_pars->temp_parameters.usSerialMode;
    #ifdef TEST_MSG_MODE
        tInterfaceParametersIn.usConfig |= (MSG_MODE);
        #if defined (TEST_MSG_CNT_MODE) && defined (SUPPORT_MSG_CNT)
            tInterfaceParametersIn.usConfig |= (MSG_MODE_RX_CNT);
        #endif
        tInterfaceParametersIn.usConfig &= ~USE_XON_OFF;
        tInterfaceParametersIn.ucMessageTerminator = '\r';
    #endif
    #ifdef SERIAL_SUPPORT_DMA
        tInterfaceParametersIn.ucDMAConfig = UART_TX_DMA;                  // activate DMA on transmission
    #endif

    if (SerialPortIDIn = fnOpen( TYPE_TTY, ucDriverMode, &tInterfaceParametersIn )) { // open or change the channel with defined configurations (initially inactive)
        fnDriver( SerialPortIDIn, ( RX_ON ), 0 );                  // enable rx and tx
    }
    return SerialPortIDIn;
    }
    else if( uiUartChannel == 0 )
    {
    tInterfaceParametersOut.Channel = uiUartChannel;                            // set UART channel for serial use
    tInterfaceParametersOut.ucSpeed = temp_pars->temp_parameters.ucSerialSpeed; // baud rate
    tInterfaceParametersOut.Rx_tx_sizes.RxQueueSize = RX_BUFFER_SIZE;       // input buffer size
    tInterfaceParametersOut.Rx_tx_sizes.TxQueueSize = TX_BUFFER_SIZE;       // output buffer size
    tInterfaceParametersOut.Task_to_wake = OWN_TASK;                        // wake self when messages have been received
    #ifdef SUPPORT_FLOW_HIGH_LOW
    tInterfaceParametersOut.ucFlowHighWater = temp_pars->temp_parameters.ucFlowHigh;// set the flow control high and low water levels in %
    tInterfaceParametersOut.ucFlowLowWater = temp_pars->temp_parameters.ucFlowLow;
    #endif
    tInterfaceParametersOut.usConfig = temp_pars->temp_parameters.usSerialMode;
    #ifdef TEST_MSG_MODE
        tInterfaceParametersOut.usConfig |= (MSG_MODE);
        #if defined (TEST_MSG_CNT_MODE) && defined (SUPPORT_MSG_CNT)
            tInterfaceParametersOut.usConfig |= (MSG_MODE_RX_CNT);
        #endif
        tInterfaceParametersOut.usConfig &= ~USE_XON_OFF;
        tInterfaceParametersOut.ucMessageTerminator = '\r';
    #endif
    #ifdef SERIAL_SUPPORT_DMA
        tInterfaceParametersOut.ucDMAConfig = UART_TX_DMA;                  // activate DMA on transmission
    #endif

    if (SerialPortIDOut = fnOpen( TYPE_TTY, ucDriverMode, &tInterfaceParametersOut )) { // open or change the channel with defined configurations (initially inactive)
        fnDriver( SerialPortIDOut, ( TX_ON ), 0 );                  // enable rx and tx
    }
    return SerialPortIDOut;
    }
}
#endif

It may not be the cleanest approach, but it's working for me....

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3240
    • View Profile
    • uTasker
Re: Different UARTs for send and recieve
« Reply #3 on: April 28, 2008, 03:29:27 PM »
Hi Jesse

That is good.

You know what they say - "If it works, don't try to fix it!!"


However,  .... 
 I think that you only actually need to put the following in the if..else

if (uiUartChannel == 1) {
    fnDriver( SerialPortIDIn, ( RX_ON ), 0 );                  // enable rx
}
else {
    fnDriver( SerialPortIDOut, ( TX_ON ), 0 );                // enable tx
}

If you are using only rx or tx of each channel you could also leave the other (tx/rx) buffer size at 0 to optimise RAM.

Regards

Mark