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?