About 5748G UART interrupt

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

About 5748G UART interrupt

Jump to solution
3,491 Views
xinweichang
Contributor III

I have written a uart polling receive demo on 5748G, and now want to use receive interrupt.

Previously in the main function there is:

if(checkLINFlexD_2())

   d[0]=rxLINFlexD_2();

   txLINFlexD_2(d[0]);

   GPIO_toggle();

The demo works well on PC,  if I send 5748G a byte, I can receive it back.

Then I and this to the initialize function:

LINFlexD_2.LINIER.B.DTIE = 1;     /* Enable UART2 TX Interrupt */

LINFlexD_2.LINIER.B.DRIE=1;       /* Enable UART2 RX Interrupt*/

It is said that this will enable an interrupt when uart2 receives message. If I don't add a interrupt function, the chip will enter a while(1) loop when interrupt occurs, right? But this is not the case since the polling function still works, and I can still receive a message when I send it on PC.

Labels (1)
Tags (1)
1 Solution
2,590 Views
alexvinchev
Contributor V

In the Freescale examples (AN4830) all IRQs have default handlers for projects, demonstrating IRQ usage. I guess that xinweichang missed INTC initialization or something else. Enabling of IRQ through LINFlex configuration is not sufficient to get interrupt working. In addition, I don't see in the message above which core is in use. If core used is not Core0, then interrupt handling should be also directed to the right core...

I'm attaching one example (based on Freescale example, published some time ago). This one uses PIT interrupt, so controller is configured to handle IRQs properly.

xinweichang​, code below configures LINFlex to use interrupts. It is directly taken from the OS driver I wrote, but you'll get the idea:

static void mpc57xx_linflex_init(SerialDriver *sdp, const SerialConfig *config) {

    uint32_t div;

    volatile struct LINFlexD_tag *linflexp = sdp->linflexp;

    sdp->errNoise = sdp->errParity = sdp->errOverRun = sdp->errFraming = sdp->errBreak = 0;

    /* Enters the configuration mode.*/

    linflexp->LINCR1.B.INIT  = 1;               /* Put LIN in INIT mode     */

    linflexp->LINCR1.B.SLEEP = 0;               /* No sleep                 */

    /* Configures the LINFlex in UART mode with all the required parameters.*/

    linflexp->UARTCR.B.UART  = 1;               /* Switch first to UART     */

    linflexp->UARTCR.R  = MPC57XX_UARTCR_UART | MPC57XX_UARTCR_RXEN | MPC57XX_UARTCR_RFBM | config->mode;

    div = sdp->clock / config->speed;

    linflexp->LINIBRR.R = (uint16_t)(div >> 4); /* Integer divider.         */

    linflexp->LINFBRR.R = (uint16_t)(div & 15); /* Fractional divider.      */

    linflexp->UARTSR.R  = 0xFFFF;               /* Clearing UARTSR register.*/

    linflexp->LINIER.R  = MPC57XX_LINIER_DTIE | MPC57XX_LINIER_DRIE |

                          MPC57XX_LINIER_BOIE | MPC57XX_LINIER_FEIE |

                          MPC57XX_LINIER_SZIE;  /* Interrupts enabled.      */

    /* Leaves the configuration mode.*/

    linflexp->LINCR1.R  = 0;                    /* Put LIN in NORM mode     */

}

This is the receive interrupt routine:

static void mpc57xxxx_serve_rxi_interrupt(SerialDriver *sdp) {

    flagsmask_t sts = 0;

    uint16_t sr = sdp->linflexp->UARTSR.R;

    sdp->linflexp->UARTSR.R = MPC57XX_UARTSR_NF | MPC57XX_UARTSR_DRF |

        MPC57XX_UARTSR_PE0;

    if (sr & MPC57XX_UARTSR_NF) {

        sts |= SD_NOISE_ERROR;

        sdp->errNoise++;

    }

    if (sr & MPC57XX_UARTSR_PE0) {

        sts |= SD_PARITY_ERROR;

        sdp->errParity++;

    }

    DISABLE_INTERRUPTS();

    if (sts)

        chnAddFlagsI(sdp, sts);

    if (sr & MPC57XX_UARTSR_DRF) {

        sdIncomingDataI(sdp, sdp->linflexp->BDRM.B.DATA4);

        sdp->linflexp->UARTSR.R = MPC57XX_UARTSR_RMB;

    }

    ENABLE_INTERRUPTS();

}

This is the transmit interrupt routine:

static void mpc57xxxx_serve_txi_interrupt(SerialDriver *sdp) {

    msg_t b;

    sdp->linflexp->UARTSR.R = MPC57XX_UARTSR_DTF;

    DISABLE_INTERRUPTS();

    b = chOQGetI(&sdp->oqueue);

    if (b < Q_OK) {

        chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);

        sdp->linflexp->UARTCR.B.TxEn = 0;

    } else {

        sdp->linflexp->BDRL.B.DATA0 = b;

    }

    ENABLE_INTERRUPTS();

}

Don't forget that you have to handle error interrupt as well. In addition to all initialization done here, you have to set IRQ priority for the core which will handle the IRQ like this:

INTC.

INTC.PSR[vector].B.PRC_SELN<core> = 1;

INTC.PSR[vector].B.PRIN = <priority>;

Good luck!

View solution in original post

6 Replies
971 Views
Anilpatil_SasvaAuto
Contributor III

I'm trying to test out the UART peripheral on MPC5748G, but I’m stuck at where I’m trying to read data from the LINFlexD_7.BDRM.B.DATA4 data buffer.

My requirement: Try to transmit and receive 9 bytes of hex values as shown below.
TxBuffer[9] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}

I am attempting to read all 9 bytes using the above Rx ISR, but I am only receiving the first byte repeatedly, which is 0x11.

Expected Output:
TxBuffer[9] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19};
RxBuffer[9] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19};
 
Actual Output:
TxBuffer[9] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19};
RxBuffer[9] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
 
Could you please suggest what the issue is in the RxISR routine?
 
Please provide the correct Uart7_Rx_Isr routine to read valid 9 bytes and Uart7_Tx_Isr and Transmit function as well.
 

Please review my Uart7_Rx_Isr code below:

void Uart7_Rx_Isr (void)
{
    unsigned char Channel = 7U;
    unsigned char Data;
 
    if (1 == LINFlexD_7.UARTSR.B.DRFRFE)
    {
        Data = LINFlexD_7.BDRM.B.DATA4;
 
        LINFlexD_7.UARTSR.R &= UART_DRFRFE;      /* Clear data reception flag W1C */
 
       /*Save received data*/
       if (BufferTxdisplay_index < UART_7_TX_MAX_LENGTH)   //0 <12
      {
           BufferTxdisplay[BufferTxdisplay_index] = Data;
 
           BufferTxdisplay_index++;
      }
 
     if( (BufferTxdisplay_index >= 9) )
     {
        BufferTxdisplay_index = 0;
     }
   }
}
 
0 Kudos
Reply
2,591 Views
alexvinchev
Contributor V

In the Freescale examples (AN4830) all IRQs have default handlers for projects, demonstrating IRQ usage. I guess that xinweichang missed INTC initialization or something else. Enabling of IRQ through LINFlex configuration is not sufficient to get interrupt working. In addition, I don't see in the message above which core is in use. If core used is not Core0, then interrupt handling should be also directed to the right core...

I'm attaching one example (based on Freescale example, published some time ago). This one uses PIT interrupt, so controller is configured to handle IRQs properly.

xinweichang​, code below configures LINFlex to use interrupts. It is directly taken from the OS driver I wrote, but you'll get the idea:

static void mpc57xx_linflex_init(SerialDriver *sdp, const SerialConfig *config) {

    uint32_t div;

    volatile struct LINFlexD_tag *linflexp = sdp->linflexp;

    sdp->errNoise = sdp->errParity = sdp->errOverRun = sdp->errFraming = sdp->errBreak = 0;

    /* Enters the configuration mode.*/

    linflexp->LINCR1.B.INIT  = 1;               /* Put LIN in INIT mode     */

    linflexp->LINCR1.B.SLEEP = 0;               /* No sleep                 */

    /* Configures the LINFlex in UART mode with all the required parameters.*/

    linflexp->UARTCR.B.UART  = 1;               /* Switch first to UART     */

    linflexp->UARTCR.R  = MPC57XX_UARTCR_UART | MPC57XX_UARTCR_RXEN | MPC57XX_UARTCR_RFBM | config->mode;

    div = sdp->clock / config->speed;

    linflexp->LINIBRR.R = (uint16_t)(div >> 4); /* Integer divider.         */

    linflexp->LINFBRR.R = (uint16_t)(div & 15); /* Fractional divider.      */

    linflexp->UARTSR.R  = 0xFFFF;               /* Clearing UARTSR register.*/

    linflexp->LINIER.R  = MPC57XX_LINIER_DTIE | MPC57XX_LINIER_DRIE |

                          MPC57XX_LINIER_BOIE | MPC57XX_LINIER_FEIE |

                          MPC57XX_LINIER_SZIE;  /* Interrupts enabled.      */

    /* Leaves the configuration mode.*/

    linflexp->LINCR1.R  = 0;                    /* Put LIN in NORM mode     */

}

This is the receive interrupt routine:

static void mpc57xxxx_serve_rxi_interrupt(SerialDriver *sdp) {

    flagsmask_t sts = 0;

    uint16_t sr = sdp->linflexp->UARTSR.R;

    sdp->linflexp->UARTSR.R = MPC57XX_UARTSR_NF | MPC57XX_UARTSR_DRF |

        MPC57XX_UARTSR_PE0;

    if (sr & MPC57XX_UARTSR_NF) {

        sts |= SD_NOISE_ERROR;

        sdp->errNoise++;

    }

    if (sr & MPC57XX_UARTSR_PE0) {

        sts |= SD_PARITY_ERROR;

        sdp->errParity++;

    }

    DISABLE_INTERRUPTS();

    if (sts)

        chnAddFlagsI(sdp, sts);

    if (sr & MPC57XX_UARTSR_DRF) {

        sdIncomingDataI(sdp, sdp->linflexp->BDRM.B.DATA4);

        sdp->linflexp->UARTSR.R = MPC57XX_UARTSR_RMB;

    }

    ENABLE_INTERRUPTS();

}

This is the transmit interrupt routine:

static void mpc57xxxx_serve_txi_interrupt(SerialDriver *sdp) {

    msg_t b;

    sdp->linflexp->UARTSR.R = MPC57XX_UARTSR_DTF;

    DISABLE_INTERRUPTS();

    b = chOQGetI(&sdp->oqueue);

    if (b < Q_OK) {

        chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);

        sdp->linflexp->UARTCR.B.TxEn = 0;

    } else {

        sdp->linflexp->BDRL.B.DATA0 = b;

    }

    ENABLE_INTERRUPTS();

}

Don't forget that you have to handle error interrupt as well. In addition to all initialization done here, you have to set IRQ priority for the core which will handle the IRQ like this:

INTC.

INTC.PSR[vector].B.PRC_SELN<core> = 1;

INTC.PSR[vector].B.PRIN = <priority>;

Good luck!

2,590 Views
xinweichang
Contributor III

Thank you very much for giving me so much details:smileyhappy:.

I am using core0 with other core closed, and have done the following:

    1. add a interrupt function to intc_SW_mode_isr_vectors_MPC5748G.C:

(uint32_t) &uart2_rx_interrupt, /* Vector # 382 LinFlex2_0 LinFlex_2_RXI */

     2. enable rx interrupt in the initLINFlexD functioin:

LINFlexD_2.LINIER.B.DRIE=1;       /* Enable UART2 RX Interrupt*/

   3. call the xcptn_xmpl() function in main():

int main(void)
{
int i,j;
unsigned char d[100];
MC_ME.RUN_PC[0].R = 0x000000fe;
system160mhz();
InitMCU();
initGPIO();
initLINFlexD_2(80, 115200);
xcptn_xmpl ();              /* Configure and Enable Interrupts */
for(;;) {

  if(checkLINFlexD_2()){
   d[0]=rxLINFlexD_2();
   txLINFlexD_2(d[0]);
  }


  }
return 0;
}

Is there something I still missed?

0 Kudos
Reply
2,589 Views
alexvinchev
Contributor V

I don't know what is in the xcptn_xmpl() function, but would be nice to have somewhere:

INTC.PSR[382].B.PRC_SELN0 = 1; INTC.PSR[382].B.PRC_SELN1 = 0; INTC.PSR[382].B.PRC_SELN2 = 0;

INTC.PSR[383].B.PRC_SELN0 = 1; INTC.PSR[383].B.PRC_SELN1 = 0; INTC.PSR[383].B.PRC_SELN2 = 0;

INTC.PSR[384].B.PRC_SELN0 = 1; INTC.PSR[384].B.PRC_SELN1 = 0; INTC.PSR[384].B.PRC_SELN2 = 0;

INTC.PSR[382].B.PRIN = 8;

INTC.PSR[383].B.PRIN = 8;

INTC.PSR[384].B.PRIN = 8;

Let me know if this helps.

2,590 Views
xinweichang
Contributor III

Finally I found the problem is I forgot to set interrupt priority, which you mentioned at first time:smileyconfused:. On mc9s12xep100 the interrupt setting is rather simple, so I take it for granted that there is a default interrupt priority. Thank you for spending so much time on my question!:smileyhappy:

0 Kudos
Reply
2,590 Views
martin_kovar
NXP Employee
NXP Employee

Hi,

if you enable interrupt and do not implement interrupt handler, micro does not respond to interrupt flag and continue with the actual task.

For example, if micro executes some function and interrupt occurs, micro continues with executing the function. There is no reaction to the interrupt. 

Regards,

Martin