9 bit UART and DMA

cancel
Showing results for 
Search instead for 
Did you mean: 

9 bit UART and DMA

712 Views
Contributor V

Hi everyone,

I'm developing a project based on K66, using MCUXpresso 11.2.0 and SDK 2.6.

I have to implement a serial protocol that uses 9 bit data length (with the ninth bit acting as address mark). I modified the uart drivers (fsl_uart and fsl_uart_freertos files) to handle the ninth bit (and to add a timeout handling): now everything is working fine.

Nevertheless the uart speed is high (125000 bps) and the UART used have an only 1 byte FIFO depth (UART4), so the character length is 88 µs: every character received an interrupt must be serviced. Sometimes it happens that a character is lost (and therefore all the packet is lost since there is a crc check) due to a delay in servicing the interrupt request, even if the UART interrupt priority is the highest (maybe this is caused by the FreeRTOS scheduler that can disable the interrupts for a little time).

In another application where the 8 bit data length is used, I developed an UART FreeRTOS driver that uses DMA that is working great.

My question is: can the UART DMA driver (even without FreeRTOS) handle the 9 bit data lenght? I've searched informations about it in the K66 reference manual and online, but with non success.

Many thanks

Biafra

9 Replies

525 Views
NXP TechSupport
NXP TechSupport

Hello Francesco and Confused Cake, 

You could do it the following way:

The C3 register that contains the 9 bit is contiguous to the data register, so you could set the DMA transmission for two bytes width and filter the C3 register to only take the R8 or T8 bit depending on if you are receiving or transmitting.

I will suggest checking how the LPUART_ReceiveEDMA/LPUART_TransmitEDMA configure the DMA and modify the byte width and change the Date address for the C3 address.

Best Regards,

Alexis Andalon

525 Views
Contributor V

Hi nxf46116‌,

I will try your suggestion.

Many thanks

Biafra

525 Views
Contributor I

I already modified the API on fsl_uart and fsl_uart_freertos files to handle the talktosonic 9 bit communication (and a tx/rx timeout) and it's working, but sometimes a character is lost. I think the reason is because it can't handle interrupts in time (speed is 125000 bps and the UART4 peripheral have only 1 byte FIFO); so I'd want to use DMA.

525 Views
Contributor V

Hi annettedunca18@gmail.com‌,

I don't understand your post.

Biafra

525 Views
NXP TechSupport
NXP TechSupport

Hello Francesco,

In the LPUARTx_CTRL the M bit is used to enable the 9-bit data character, unfortunately in the SDK still there isn't support for 9-bit communication, so you will need to modify the APIs and type data to support it.

pastedImage_1.png

Best Regards,

Alexis Andalon

525 Views
Contributor V

Hi nxf46116‌,

Many thanks for your answer, sorry for the late processing, but I was on holiday until this morning.

I don't use LPUART, I use UART (UART4).

I already modified the API on fsl_uart and fsl_uart_freertos files to handle the 9 bit communication (and a tx/rx timeout) and it's working, but sometimes a character is lost. I think the reason is because it can't handle interrupts in time (speed is 125000 bps and the UART4 peripheral have only 1 byte FIFO); so I'd want to use DMA.

I already developed a UART FreeRTOS driver that uses DMA for an application that uses 8 bit communication.

My doubt is if the DMA peripheral can handle the UART 9 bit communication.

Many thanks

Biafra

525 Views
NXP TechSupport
NXP TechSupport

Hello Francesco,

Should be possible to adapt the 9 bit UART with DMA if you adapt it to transfer the two bytes per transfer.

Best Regards,

Alexis Andalon

314 Views
Contributor IV

Hello Alexis,

I wanted to check the feasibility of a 16-bit access to the UART C3 register in order to write/read also the UART D register with a single 16-bit access like DMA would do.

I started modifying the UART_WriteBlocking() function in the fsl_uart.c SDK UART driver source file in order to transmit 9-bit data in blocking mode.

#define ACCESS_16_BIT	// enable 16-bit access to UART C3/D registers
typedef union
{
	unsigned short WORD;
	struct { unsigned char L, H;} BYTE;
} ACC16_UNION;
/*!
 * @brief Writes to the TX register using a blocking method.
 *
 * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO
 * to have room and writes data to the TX buffer.
 *
 * @note This function does not check whether all data is sent out to the bus.
 * Before disabling the TX, check kUART_TransmissionCompleteFlag to ensure that the TX is
 * finished.
 *
 * @param base UART peripheral base address.
 * @param data Start address of the data to write.
 * @param length Size of the data to write.
 * @param data9bit Start addresss of the ninth bit to write.
 */
void UART_WriteBlocking(UART_Type *base, const uint8_t *data, size_t length, const uint8_t *data9bit)
{
#ifdef ACCESS_16_BIT
	ACC16_UNION u;
	uint16_t *p = (uint16_t *)&base->C3;
#endif

    /* This API can only ensure that the data is written into the data buffer but can't
    ensure all data in the data buffer are sent into the transmit shift buffer. */
    while (length--)
    {
        while (!(base->S1 & UART_S1_TDRE_MASK))
        {
        }
    	if( data9bit != NULL )
    	{
		#ifdef ACCESS_16_BIT
			u.BYTE.L = base->C3;
			if( *(data9bit++) )
				u.BYTE.L |= UART_C3_T8_MASK;
			else
				u.BYTE.L &= ~UART_C3_T8_MASK;
			u.BYTE.H = *(data++);
			*p = u.WORD;
		#else
			if( *(data9bit++) )
				base->C3 |= UART_C3_T8_MASK;
			else
				base->C3 &= ~UART_C3_T8_MASK;
			base->D = *(data++);
		#endif
    	}
		else
		{
			base->D = *(data++);
		}
    }
}

But the instruction:

*p = u.WORD;

generates a Hard Fault error. The effective write access is executed with the following assembler instruction:

strh    r2, [r3, #0]

where R2 contains the 16-bit value to write at the address holded by R3. Both UART C3 and D registers remain not changed.

I wanted to make this test, because I just wrote code to configure DMA for a 16-bit write transfer to the UART C3/D registers, but when I start the transfer I get no hard fault neither no DMA transfer completed interrupt and nothing is transmitted from the UART TX pin.

It looks like those UART registers (at least) must be individually accessed. Is there any way (in compile-time or run-time) to achieve that?

 

0 Kudos

525 Views
Contributor V

Hi nxf46116‌,

I think this can be the way, but how to configure the DMA peripheral to put the ninth bit in the second byte?

Many thanks

Biafra