LPUART Hardware flow control

cancel
Showing results for 
Search instead for 
Did you mean: 

LPUART Hardware flow control

1,180 Views
brendan_cassidy
Contributor II

Trying to understand the MODIR values/settings for hardware handshaking

I have a simple setup, two SK146 EVBs sitting next to each other.

Connections are crossed, Rx to Tx and CTS to RTS.

Both boards have UART 0 configured in the same way, one od sending a short message out periodically.

For the purpose of this design, interrupts cannot be used and the receiver is polling the status register and so flow control is required.

There are 8 bits of MODIR involved in the configuration of the handshaking but I find the explanation very confusing.

Is there an application note for this?

Or can someone simply share a known working value for basic cross-connected handshaking?

Thanks

3 Replies

928 Views
brendan_cassidy
Contributor II

For some further info, here is the init code for UART0:

void UART0_Init(void)
{ 
 // set the pins for Rx and Tx
 PCC->PCCn[UART0_PIN_CLOCK] |= PCC_PCCn_CGC_MASK; // Enable clock for PORTA 

 UART0_GPIO_BASE->PDDR |= 1 << UART0_TX_PIN; // Set tx pin for output

 UART0_PIN_PORT_PAD->PCR[UART0_TX_PIN]|=PORT_PCR_MUX(4); // Port A27: MUX = ALT4,UART0 TX 
 UART0_PIN_PORT_PAD->PCR[UART0_RX_PIN]|=PORT_PCR_MUX(4); // Port A28: MUX = ALT4,UART0 RX

 
 PCC->PCCn[PCC_LPUART0_INDEX] &= ~PCC_PCCn_CGC_MASK; // Ensure clk disabled for config 
 PCC->PCCn[PCC_LPUART0_INDEX] |= PCC_PCCn_PCS(3);    // PCS=3: Select FIRC 
 PCC->PCCn[PCC_LPUART0_INDEX] |= PCC_PCCn_CGC_MASK; // Enable clock for LPUART0 regs 
 
 
 // set pins for HW handshake
 PCC->PCCn[UART0_HS_PIN_CLOCK] |= PCC_PCCn_CGC_MASK; // Enable clock for PORTA 
 
 UART0_HS_BASE->PDDR |= 1 << UART0_RTS_PIN; // Set RTS pin for output

 UART0_HS_PORT_PAD->PCR[UART0_CTS_PIN]|=PORT_PCR_MUX(2); // Port A0: MUX = ALT6,UART0 CTS
 UART0_HS_PORT_PAD->PCR[UART0_RTS_PIN]|=PORT_PCR_MUX(2); // Port A1: MUX = ALT6,UART0 RTS 
 
 // Enable the RTS and CTS function
 LPUART0->MODIR |= LPUART_MODIR_TXCTSE(1);
 
 
 // Bit 1 Tx RTS enable
LPUART0->MODIR |= LPUART_MODIR_TXRTSE(1);
 
 // Bit 2 Txt RTS polarity (active high / low)
 LPUART0->MODIR |= LPUART_MODIR_TXRTSPOL(0);
 
 
 // Bit 3 Rx RTS enable
 LPUART0->MODIR |= LPUART_MODIR_RXRTSE(0);
 
 
 // Bit 4 Tx CTS config
 LPUART0->MODIR |= LPUART_MODIR_TXCTSC(0);
 
 
 // Bit 5 Transmit CTS source

 LPUART0->MODIR |= LPUART_MODIR_TXCTSSRC(0);
 
 
 // Bits 8 & 9
 // Receive RTS Configuration
 
 LPUART0->MODIR |= LPUART_MODIR_RTSWATER(0);
 



 // 1000000 baud = 0x0F000003
 // 921600 baud = 0x0C000004 (good for Terra Term


LPUART0->BAUD = 0x0F000003; // Initialize for 1000000 baud, 1 stop: 
 // SBR=3 (0x3): baud divisor (48MHz/(BAUD_RATE/OSR)) 
 // OSR=15: Over sampling ratio = 15+1=16 
 // SBNS=0: One stop bit 
 // BOTHEDGE=0: receiver samples only on rising edge 
 // M10=0: Rx and Tx use 7 to 9 bit data characters 
 // RESYNCDIS=0: Resync during rec'd data word supported 
 // LBKDIE, RXEDGIE=0: interrupts disable 
 // TDMAE, RDMAE, TDMAE=0: DMA requests disabled 
 // MAEN1, MAEN2, MATCFG=0: Match disabled

LPUART0->CTRL=0x000C0000; // Enable transmitter & receiver, no parity, 8 bit char: 
 // RE=1: Receiver enabled 
 // TE=1: Transmitter enabled 
 // PE,PT=0: No hw parity generation or checking 
 // M7,M,R8T9,R9T8=0: 8-bit data characters
 // DOZEEN=0: LPUART enabled in Doze mode 
 // ORIE,NEIE,FEIE,PEIE,TIE,TCIE,RIE,ILIE,MA1IE,MA2IE=0: no IRQ
 // TxDIR=0: TxD pin is input if in single-wire mode 
 // TXINV=0: TRansmit data not inverted 
 // RWU,WAKE=0: normal operation; rcvr not in statndby 
 // IDLCFG=0: one idle character 
 // ILT=0: Idle char bit count starts after start bit 
 // SBK=0: Normal transmitter operation - no break char 
 // LOOPS,Rsrc=0: no loop back 
 

 
}

I know basic Rx and Tx works, I get comms in both directions but, as expected due to polling, I miss the odd character.

For a simple test, I set 

LPUART0->MODIR = LPUART_MODIR_TXRTSE(1)
As above.

Monitor UART0 Tx pin and pull the CTS pin both high and low.
In both cases data is transmitted rather than waiting for CTS to be asserted (pulled high I assume);


928 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi Brendan Cassidy

According to your description:


LPUART0->MODIR = LPUART_MODIR_TXRTSE(1)

Monitor UART0 Tx pin and pull the CTS pin both high and low.
In both cases data is transmitted rather than waiting for CTS to be asserted

You don't need the TXRTSE bit to enable, you need the TXCTSE bit.

The transmitter checks the state of CTS each time it is ready
to send a character. If CTS is asserted, the character is sent. If CTS is deasserted, the signal TXD
remains in the mark state and transmission is delayed until CTS is asserted.

I checked your configuration and I didn't see any problem with the flow control part, unfortunately, there isn't any example code that implements this.

It is not needed this part of the code:

UART0_HS_BASE->PDDR |= 1 << UART0_RTS_PIN; // Set RTS pin for output

And I also notice that you have the mux(2) and you need the mux(6)

UART0_HS_PORT_PAD->PCR[UART0_CTS_PIN]|=PORT_PCR_MUX(2); // Port A0: MUX = ALT6,UART0 CTS
 UART0_HS_PORT_PAD->PCR[UART0_RTS_PIN]|=PORT_PCR_MUX(2); // Port A1: MUX = ALT6,UART0 RTS 

Hope this could help you
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
-------------------------------------------------------------------------------

928 Views
brendan_cassidy
Contributor II

Hello Jorge

Thanks for the response.

After a few more hours of staring at the code, I did finally realise where the errors were.
The main one was I was using IART 0 but for some reason picked the CTS and RTS pins for UART 1
So we would never work.
Once I hade the correct pins sorted it was a matter of resolving what the did, I found these two:

// bit 0 Tx CTS enable, Enables clear-to-send operation. 
 // The transmitter checks the state of CTS each time it is ready to send a character. 
 // If CTS is asserted, the character is sent. 
 // If CTS is deasserted, the signal TXD remains in the mark state and transmission is delayed until CTS is asserted. 
 // Changes in CTS as a character is being sent do not affect its transmission.
 LPUART0->MODIR |= LPUART_MODIR_TXCTSE(1);
 // Confirmed for CTS input.
 // Pull CTS input low to enable tx, if not, board goes into error state as Tx locks up


 // Bit 3 Rx RTS enable 
 // RTS is deasserted if the receiver data register is full or 
 // a start bit has been detected that would cause the receiver data register to become full. 
 // RTS is asserted if the receiver data register is not full and 
 // has not detected a start bit that would cause the receiver data register to become full
 LPUART0->MODIR |= LPUART_MODIR_RXRTSE(1);
 // Confirmed
 // is asserted low when data can be sent

provided the required function.

It was not immediately clear as the descriptions sounded so similar but the fundamental facts are:

CTS is an input that hols up transmission 
RTS is an output that "says, I'm ready for data"

Thanks for the input and maybe, just maybe, this will help another confuse soul.