RX630 SCI5 and ERI group error interrupts

Folks,

I am developing a high speed RS232 on RX630 Micro controller using SCI5 and receive characters using a DMA ring capture buffer. I'm getting pretty solid communication at 115200 baud. Currently experiencing spurious over runs which cause communications to halt after relatively long sessions. Root cause seems to be when restarting the DMA interrupt as the buffer wraps. This wrap executes without dropping characters reasonably well however occasionally the overrun occurs. With e2studio and E20 emulator debugger I can halt code and clear the ORER bit in the SSR register and communications restart. Seems reasonable if I could clear this error condition as it happens the port can remain functional. Hardware manual indicates ERI5 is part of ICU group 12 interrupts. I could use guidance to implement their services. Can you point me to example code to implement the ERI5 error interrupt?

Thanks for your help,

Russ

  • Hi Russ,
     
    There is a FIT driver module for the SCI peripheral that implements SCI error interrupt processing. So it should provide a solid code example for how the group interrupts are setup for this peripheral.
     
    The FIT module doesn't list RX630 as supported, but the RX630 has the same interrupt controller and SCI peripheral as the RX631/63N that is supported. So I think that part of the code would be compatible.
     
    In general, since group interrupt vectors are shared, it is necessary to examine the status registers of the peripheral that generated the interrupt to see which event raised the interrupt. So the interrupt handler has to  look for this.
     
    The SCI driver is contained within the RX Family Driver Package that can be downloaded at this link:
     
    The SCI driver is in module "r_sci_rx_v1.xx"
     
    There are a couple of parts to the interrupt configuration and handling. Here are snippets from the source file, "r_sci_rx.c".
    /*****************************************************************************
    * Function Name: sci_enable_ints
    * Description  : This function sets priority, clears flags, and enables
    *                interrupts in both the ICU and SCI peripheral. These include
    *                RXI, TXI, TEI, and ERI/GROUP12.
    *                interrupts.
    * Arguments    : hdl -
    *                    handle for channel (ptr to chan control block)
    *                priority -
    *                    priority for interrupts
    * Return Value : none
    ******************************************************************************/
    static void sci_enable_ints(sci_hdl_t const hdl,
                                uint8_t const   priority)
    {
       
        /* SET PRIORITY FOR RXI, TXI, and TEI INTERRUPTS */
        *hdl->rom->ipr = priority;                  // includes ERI (non-63x)
    #ifdef BSP_MCU_RX63_ALL
        IPR(ICU,GROUP12) = SCI_CFG_RXERR_PRIORITY;  // RX63x ERI equivalent
    #endif

        /* CLEAR INTERRUPT FLAGS */
        *hdl->rom->ir_rxi = 0;
        *hdl->rom->ir_txi = 0;
        *hdl->rom->ir_tei = 0;
    #ifndef BSP_MCU_RX63_ALL
        *hdl->rom->ir_eri = 0;
    #endif
        // Do not clear group12 flag on RX63x. May be set for another channel
        /* ENABLE INTERRUPTS IN ICU */
    #if (SCI_CFG_ASYNC_INCLUDED)
        if (hdl->mode == SCI_MODE_ASYNC)
        {
            ENABLE_TXI_INT;                 // Do not have TXI int for SSPI/SYNC
        }
    #endif
        ENABLE_RXI_INT;
    #ifdef BSP_MCU_RX63_ALL
        IEN(ICU,GROUP12) = 1;               // enable RX63x rx err interrupts
    #else
        ENABLE_ERI_INT;
    #endif
        // ENABLE_TEI_INT occurs in sci_put_byte()

        /* ENABLE INTERRUPTS IN SCI PERIPHERAL */
        /* Note: Enable interrupts after xcvr or will get "extra" interrupt */
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;    // TE | RE
    #ifdef BSP_MCU_RX63_ALL
        ICU.GEN[12].BIT.EN2 = 1;            // enable RX err GROUP12 for 63x
    #endif
        hdl->rom->regs->SCR.BYTE |= 0xC0U;  // enable RXI, [ERI], and TXI
                                            // TEI is enabled via R_SCI_Control()
        return;   
    }
     
    and the ISR:
    #ifdef BSP_MCU_RX63_ALL
    /*****************************************************************************
    * Function Name: icu_group12_isr
    * Description  : SCI receiver error interrupt handler for all channels
    * Arguments    : none
    * Return Value : none
    ******************************************************************************/
    #pragma interrupt icu_group12_isr(vect=VECT(ICU,GROUP12))
    static void icu_group12_isr(void)
    {
    sci_cb_args_t   args;
    uint32_t        err,mask;
    uint8_t         i,byte;
        /*
        * Get group12 error value. Bit 0 corresponds to ch0, bit 1 to ch1, etc.
        * If a bit is set, an error occurred on that corresponding channel.
        * Loop through each bit (channel), and if an error occurred on that
        * channel and it is enabled by this driver, process the error.
        */
        err = ICU.GRP[12].LONG;
        for (i=0,mask=1; i < SCI_NUM_CH; i++, mask<<=1)
        {
            if ((err & mask & SCI_CFG_CH_INCLUDED_MASK) != 0)
            {
                /* Flush register */
                byte = g_handles[i]->rom->regs->RDR;
                /* Do callback for error */
                if ((g_handles[i]->callback != NULL) && (g_handles[i]->callback != FIT_NO_FUNC))
                {
                    args.hdl = g_handles[i];
                    args.byte = byte;
                    if (g_handles[i]->rom->regs->SSR.BIT.ORER == 1)
                    {
                        args.event = SCI_EVT_OVFL_ERR;
                    }
    #if (SCI_CFG_ASYNC_INCLUDED)
                    else if (g_handles[i]->rom->regs->SSR.BIT.PER == 1)
                    {
                        args.event = SCI_EVT_PARITY_ERR;
                    }
                    else if (g_handles[i]->rom->regs->SSR.BIT.FER == 1)
                    {
                        args.event = SCI_EVT_FRAMING_ERR;
                    }
    #endif
                    g_handles[i]->callback((void *)&args);
                }

                /* Clear error condition */
                g_handles[i]->rom->regs->SSR.BYTE &= ~SCI_RCVR_ERR_MASK;
                while ((g_handles[i]->rom->regs->SSR.BYTE & SCI_RCVR_ERR_MASK) != 0)
                {
                    byte = g_handles[i]->rom->regs->RDR;
                    g_handles[i]->rom->regs->SSR.BYTE &= ~SCI_RCVR_ERR_MASK;
                }
            }
        }  
    }
    Sorry, the code is a bit hard to follow due to the levels of pointer indirection, but hopefully you can get an idea of what it's doing.
     
    Regards,
    Gerald
     
     
  • Russell Vogel,

    Has your question been answered?

    Mike Clements
    RenesasRulz Moderator