S32K FLEXIO UART

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

S32K FLEXIO UART

6,896 Views
liulei1
Contributor II

I use FLEXIO to simulate UART serial port, but I can only achieve the sending function but not the receiving function.

void FLEXIO_UART_port_init (void)
{
/*!
* Pins definitions
* ===================================================
*
* Pin number | Function
* ----------------- |------------------
* PTA11 | FXIO_D1 Rx (J6-01)
* PTA0 | FXIO_D2 Tx (J6-02)
*
*/
PCC->PCCn[PCC_PORTA_INDEX]|=PCC_PCCn_CGC_MASK; /* Enable clock for PORTD */

PORTA->PCR[0] = PORT_PCR_MUX(4); /* Port A0: MUX = FXIO_D2 */
PORTA->PCR[11] = PORT_PCR_MUX(4); /* Port A11: MUX = FXIO_D1 */
PTA->PDDR |= 1<<0; /* Port A0: Data Direction = output */
PTA->PDDR &= ~(1<<11); /* Port A11: Data Direction= input (default) */
}

void FLEXIO_UART_init(void)
{

PCC->PCCn[PCC_FlexIO_INDEX] &= ~PCC_PCCn_CGC_MASK; /* Disable FLEXIO clock for config. */
PCC->PCCn[PCC_FlexIO_INDEX] |= PCC_PCCn_PCS(2) /* Select clk option 2 = SIRCDIV2_CLK */
| PCC_PCCn_CGC_MASK; /* Enable FLEXIO clock */

/*Init Flexio*/
FLEXIO->CTRL &= (uint32_t)(~(FLEXIO_CTRL_SWRST_MASK));
FLEXIO->CTRL = FLEXIO_CTRL_SWRST(1);
FLEXIO->CTRL = 0x0U;
INT_SYS_EnableIRQ(FLEXIO_IRQn);
/*enable Flexio*/
FLEXIO->CTRL &= (uint32_t)(~(FLEXIO_CTRL_FLEXEN_MASK));
FLEXIO->CTRL |= FLEXIO_CTRL_FLEXEN(1);

/*!
* FlexIO Timer Configuration:
* =============================
*/
FLEXIO->TIMCFG[0] |=
FLEXIO_TIMCFG_TIMRST(6) /* Timer reset on trigger rising edge */
|FLEXIO_TIMCFG_TIMOUT(0) /* Output logic 1 when enabled */
|FLEXIO_TIMCFG_TIMDIS(2) /* Timer disabled on Timer compare */
|FLEXIO_TIMCFG_TIMENA(2) /* Timer enabled on Trigger high */
|FLEXIO_TIMCFG_TSTART(1) /* Start bit enabled */
|FLEXIO_TIMCFG_TSTOP(3); /* Stop bit is enabled on timer compare and timer disable */

/*!
* FlexIO Timer Control:
* ============================
*/
FLEXIO->TIMCTL[0] |=
FLEXIO_TIMCTL_TRGSEL(1) /* Trigger select: Shifter 0 status flag */
|FLEXIO_TIMCTL_TRGPOL(1) /* Trigger active low */
|FLEXIO_TIMCTL_TIMOD(1) /* Dual 8-bit counters baud mode */
|FLEXIO_TIMCTL_TRGSRC(1) /* Internal trigger */
|FLEXIO_TIMCTL_PINSEL(2) /* Select FXIO_D2 */
|FLEXIO_TIMCTL_PINCFG(0); /* timer pin output disabled */

/*!
* FlexIO Timer Compare Value:
* =============================
* In 8-bit baud counter mode, the lower 8-bits configure the baud rate
* divider equal to (CMP[7:0] + 1) * 2. The upper 8-bits configure the
* number of bits in each word equal to (CMP[15:8] + 1) / 2.
*/
FLEXIO->TIMCMP[0] = 0x0FCF; /* 8 bits Transfer */
/* Baud Rate = 9600/s */

/*!
* FlexIO Shifter Configuration:
* ===============================
*/
FLEXIO->SHIFTCFG[0] |=
FLEXIO_SHIFTCFG_SSTART(2) /* Start bit '0' */
|FLEXIO_SHIFTCFG_SSTOP(3); /* Stop bit '1' */

/*!
* FlexIO Shifter Control:
* =============================
*/
FLEXIO->SHIFTCTL[0] |=
FLEXIO_SHIFTCTL_TIMSEL(0) /* Select Timer 0 */
|FLEXIO_SHIFTCTL_PINSEL(2) /* Select FXIO_D2 */
|FLEXIO_SHIFTCTL_PINCFG(3) /* Shifter pin as Output */
|FLEXIO_SHIFTCTL_SMOD(2); /* Transmit mode */


/* setup FLEX_D1 to receive */

/*!
* FlexIO Timer Configuration:
* =============================
*/
FLEXIO->TIMCFG[1] |=
FLEXIO_TIMCFG_TIMOUT(2) /* Timer output is logic one when enabled and is not affected by timer reset */
/* FLEXIO_TIMER_INITOUT_ONE_RESET = 0x02U */
/* Tx/Rx */
|FLEXIO_TIMCFG_TIMDEC(0) /* Decrement counter on FlexIO clock, Shift clock equals Timer output. */
/*FLEXIO_TIMER_DECREMENT_CLK_SHIFT_TMR = 0x00U */
|FLEXIO_TIMCFG_TIMRST(2) /* Timer never reset */
/* FLEXIO_TIMER_INITOUT_ONE_RESET = 0x02U */
|FLEXIO_TIMCFG_TIMDIS(2) /* 2 - Timer disabled on Timer compare (upper 8-bits match and decrement) */
/* 3 - Timer disabled on Timer compare (upper 8-bits match and decrement) and Trigger Low */
/* FLEXIO_TIMER_DISABLE_TIM_CMP = 0x02U, */
|FLEXIO_TIMCFG_TIMENA(4) /* Timer enabled on Pin rising edge */
/* FLEXIO_TIMER_ENABLE_PIN_POSEDGE = 0x04U */
|FLEXIO_TIMCFG_TSTOP(2) /* Stop bit is enabled on timer disable;FLEXIO_TIMER_STOP_BIT_TIM_DIS = 0x02U */
|FLEXIO_TIMCFG_TSTART(1); /* Start bit enabled; FLEXIO_TIMER_START_BIT_ENABLED = 0x01U */

/*!
* FlexIO Timer Control:
* ============================
*/
FLEXIO->TIMCTL[1] |=
FLEXIO_TIMCTL_TIMOD(0) /* Dual 8-bit counters baud mode */
/* Tx/Rx */
|FLEXIO_TIMCTL_TRGSEL(0) /* External trigger D0 input FLEXIO_TRIGGER_SOURCE_EXTERNAL = 0x00U*/
|FLEXIO_TIMCTL_TRGPOL(0) /* Trigger active high FLEXIO_TRIGGER_POLARITY_HIGH = 0x00U,*/
|FLEXIO_TIMCTL_TRGSRC(0) /* External trigger FLEXIO_TRIGGER_SOURCE_EXTERNAL = 0x00U*/
|FLEXIO_TIMCTL_PINSEL(1) /* 1: Select FXIO_D1, 0: Select FXIO_D0 */
|FLEXIO_TIMCTL_PINCFG(0) /* timer pin output disabled */
|FLEXIO_TIMCTL_PINPOL(1);
/*!
* FlexIO Timer Compare Value:
* =============================
* In 8-bit baud counter mode, the lower 8-bits configure the baud rate
* divider equal to (CMP[7:0] + 1) * 2. The upper 8-bits configure the
* number of bits in each word equal to (CMP[15:8] + 1) / 2.
*/
FLEXIO->TIMCMP[1] = 0x0FCF; /* 8 bits Transfer */
/* Baud Rate = 19200b/s */

/*!
* FlexIO Shifter Configuration:
* ===============================
*/
FLEXIO->SHIFTCFG[1] |=
FLEXIO_SHIFTCFG_INSRC(0) /* Input source is selected pin */
|FLEXIO_SHIFTCFG_SSTART(2) /* Start bit '0';FLEXIO_SHIFTER_START_BIT_0 = 0x02U*/
|FLEXIO_SHIFTCFG_SSTOP(3); /* Stop bit '1'; FLEXIO_SHIFTER_STOP_BIT_1 = 0x03U */

/*!
* FlexIO Shifter Control:
* =============================
*/
FLEXIO->SHIFTCTL[1] |=
FLEXIO_SHIFTCTL_TIMSEL(1) /* Select Timer 1 */
|FLEXIO_SHIFTCTL_PINSEL(1) /* Select FXIO_D1*/
/* Tx/Rx */
|FLEXIO_SHIFTCTL_TIMPOL(1) /* Shift on negedge of Shift clock; FLEXIO_TIMER_POLARITY_NEGEDGE = 0x01U */
|FLEXIO_SHIFTCTL_PINCFG(0) /* Shifter pin output disabled; FLEXIO_PIN_CONFIG_DISABLED = 0x00U */
|FLEXIO_SHIFTCTL_PINPOL(0) /* Pin is active high ; FLEXIO_PIN_POLARITY_HIGH = 0x00U*/
|FLEXIO_SHIFTCTL_SMOD(1); /* Receive mode; FLEXIO_SHIFTER_MODE_RECEIVE = 0x01U */

}

This is the sending function.

void FLEXIO_UART_transmit_char(char send)
{
/*!
* Transmit a single char:
* =======================
*/
while(! (FLEXIO->SHIFTSTAT & 0x1) ); /* Wait for buffer empty */
FLEXIO->SHIFTBUF[0] = send; /* Send data to PTA0(Tx line) */
}

static int rx_char = 0;
static int rx_loop_cnt = 0;
char FLEXIO_UART_receive_char(void)
{
char byte;
/*!
* Receive a single char:
* =======================
*/
while( !(FLEXIO->SHIFTSTAT&(1<<(1)<<FLEXIO_SHIFTSTAT_SSF_SHIFT))){};
byte = FLEXIO->SHIFTBUFBYS[1];
if ((byte == 'g') ||(byte == 'G'))
{
rx_char++;
}
return byte;
}

Labels (1)
0 Kudos
Reply
13 Replies

6,236 Views
liulei1
Contributor II

Yes, I modified the clock source to work well, but I changed the clock SIRCDIV2_CLK from 8 Mhz to 4 Mhz, and the data received and received were normal. Why can the frequency be used instead of decreasing?

0 Kudos
Reply

6,236 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello Lei,

You can decrease the baud rate or increase the clock source frequency for the FlexIO module.

I'm not sure if you decreased the SIRCDIV2_CLK from 8 MHz to 4 MHz if the data are received correctly with 115200 baud rate.

Also, the increase the interrupt priority can be useful.

I hope it helps.

Best Regards,

Diana

0 Kudos
Reply

6,236 Views
liulei1
Contributor II

Hello Diana,

I tried the routine in S32DS (flexio_uart_s32k144). When setting the clock source at 8Mhz, 115200 could be communicated, but 9600 was out of order. When I changed to 4Mhz, it was normal. Compared with my own code, it's just the opposite. When I set it to 8Mhz, 115200 was scrambled and 9600 was normal. It's normal at 4Mhz.

Best Regards,

lei liu

0 Kudos
Reply

6,236 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello Lei,

I would like to check your clock settings, can you, please, share it?

Also, what can you see on the bus? 

Can you measure SIRCDIV2_CLK  4 MHz?

Thank you.

Best Regards,

Diana

0 Kudos
Reply

5,044 Views
ywjack
Contributor III

Hello NXP Technical Support:
Can you provide a DEMO about flexio's simulation of uart, which uses the interrupt method,Operation register, not SDK driver. I think the examples here are basically polling.,

0 Kudos
Reply

6,236 Views
liulei1
Contributor II

Hello Diana,

Here's my clock settings。

void SIRC_init_8MHz(void)
{
SCG->SIRCCSR = 0U; /* Init SIRC */
SCG->SIRCDIV = (SCG_SIRCDIV_SIRCDIV1(1U) | SCG_SIRCDIV_SIRCDIV2(2U)); /* Setup SIRCDIV1_CLK SIRCDIV2_CLK. */
SCG->SIRCCFG = SCG_SIRCCFG_RANGE(1U); /* Set SIRC high range(8 MHz ) */
SCG->SIRCCSR = SCG_SIRCCSR_SIRCEN(1U); /* Enable clock. */

while (!(SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD(1U))) __NOP(); /* Wait for SIRC clock to be valid. */
}

PCC->PCCn[PCC_FlexIO_INDEX] &= ~PCC_PCCn_CGC_MASK; /* Disable FLEXIO clock for config. */
PCC->PCCn[PCC_FlexIO_INDEX] |= PCC_PCCn_PCS(2) /* Select clk option 2 = SIRCDIV2_CLK */
| PCC_PCCn_CGC_MASK; /* Enable FLEXIO clock */

0 Kudos
Reply

6,236 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello Lei,

Your clock settings are correct.

However, the reason for the wrong received data can be because of the wrong baud rate settings in TIMCMP register (there can be an error between the actual baudrate and required baudrate).

You can refer to RM rev 9. to the section "52.3.1.21 Timer Compare N Register (TIMCMP0 - TIMCMP3)"

For example:

"In 8-bit baud counter mode, the lower 8-bits configure the baud rate divider equal to (CMP[7:0] + 1) * 2.
The upper 8-bits configure the number of bits in each word equal to (CMP[15:8] + 1) / 2."

I hope it helps.

Best Regards,

Diana

0 Kudos
Reply

6,236 Views
liulei1
Contributor II

Hello, I found the problem.

The TIMCMP register is configured in the S32DS as follows:

Static void FLEXIO_UART_DRV_ComputeBaudRateDivider (uint32_t baudRate, Uint16_t*divider, Uint32_t inputClock)

{

Int32_t tmpDiv;

/* Compute divider: ((input_clock/baud_rate)/ 2) - 1. Round to nearest integer*/

TmpDiv = ((int32_t) inputClock + (int32_t) baudRate) / (2* (int32_t) baudRate) - 1;

/* Enforce upper/lower limits*/

If (tmpDiv < DIVIDER_MIN_VALUE)

{

TmpDiv = DIVIDER_MIN_VALUE;

}

If (tmpDiv > DIVIDER_MAX_VALUE)

{

TmpDiv = DIVIDER_MAX_VALUE;

}

* divider = uint16_t tmpDiv;

}

Because PCC_PCCn_PCS=2 and inputClock=8Mhz, when the baud rate is 9600, it exceeds DIVIDER_MAX_VALUE, when TIMCMP [7:0]=0xff, the baud rate is wrong. If you want to configure the baud rate of 9600, you must reduce the inputClock, so when inputClock = 4Mhz, 115200 and 9600 are normal.

I also read the manual to show that I don't quite understand the calculation method in S32DS.

But according to this algorithm, if we want to set a large baud rate, we must increase the inputClock, and set a small baud rate, we must reduce the inputClock.

0 Kudos
Reply

6,236 Views
liulei1
Contributor II

I modified the code. Now there is no problem in communication between 1900b/s and 9600b/s. The data I received at 115200 is wrong. What is the reason?

0 Kudos
Reply

6,236 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello,

One of the reason can be overrun error which can occur with a higher baud rate.

The solution for you can be the select higher frequency of clock option for the FlexIO.

Now you are using SIRCDIV2_CLK which is too slow. So, for example, you can try to use Fast IRC clock (FIRC_CLK) and select as clock option FIRCDIV2_CLK.

I hope it helps.

Best Regards,

Diana

0 Kudos
Reply

5,404 Views
lucaswang
Contributor I

你好,我按照你这个修改,还是会出现问题。只是能正常运行的时间更久而已。还有什么解决办法么

0 Kudos
Reply

6,236 Views
liulei1
Contributor II

Hello, I modified the code, now send and receive can be successful. When I receive a byte, there is no problem. When I receive a string of data, there will be FLEXIO - > SHIFTERR = 0x02. This is the time when only the first byte is correct and the next byte is wrong. Here is my receiver function.

void FLEXIO_IRQHandler (void)
{

char byte;
if(FLEXIO->SHIFTSTAT==0x03)
{
byte = (FLEXIO->SHIFTBUF[1] >> 24 ) & 0xFF;
}
if(FLEXIO->SHIFTERR==0x02)
{
FLEXIO->SHIFTERR=0x02;
FLEXIO->TIMSTAT=0x02;
}
}

0 Kudos
Reply

6,236 Views
dianabatrlova
NXP TechSupport
NXP TechSupport

Hello,

I have checked your settings and in the receiver settings "TIMOD" bit you have set 0 which means Timer Disabled.

FLEXIO->TIMCTL[1] |=
FLEXIO_TIMCTL_TIMOD(0) /* Timer Disabled */

It should be:

FLEXIO_TIMCTL_TIMOD(1) /* Dual 8-bit counters baud mode */

Also, two notes:

- I would like to recommend you to enable the FlexIO after configuration shifters and timers.

- The PDDR settings are related to GPIO function. It does not need to configure PDDR register when the pins are set as FlexIO.

I hope it helps.

Best Regards,

Diana

0 Kudos
Reply