Nested interrupt for Rx130 Controller - Part Number R5F51306B

Hello,

I am using two SCI channels SCI0 and SC8 for following purpose -

1. SCI0 is used for serial UART communication.

2. SCI8 is used for serial SPI communication.

Both channels have their interrupts of transmit and receive configured. SCI0 i.e., UART comms having higher priority (15) than SCI8 means SPI comms (14).

From receive interrupt of SCI0, we are calling SPI read write to EEPROM.

However, in this case SPI interrupts are not getting called.

If I interchange priorities of SCI0 and SCI8 channels i.e., SCI0 UART comms having lower priority than SCI8 SPI comms then SPI interrupts as well as UART works for few 100 milliseconds, but after that UART frames are missed and further communication is stopped.

Is there anything specific configuration that needs to be done for enabling nested interrupts work in correct fashion.

Am I doing anything wrong? 

Best Regards,

Satish

  • Hi Satish. 

    Thanks for reaching out to Renesas Engineering Community. We are working on this and will get back to you.

    Regards,
    Jayesh

  • Hello Satish.

    I'm more than willing to assist you with the issue you're facing. However, to provide you with the most accurate guidance, it would be extremely helpful if you could share some details about the IDE you're using and your current configuration of peripherals and interrupts.

    Could you please provide information such as your IDE version and any relevant code snippets, including interrupt callbacks and interrupt controller configurations? This will enable me to better understand your setup and offer a more precise solution.

    Best regards

  • the only thing you have to do is to re-enable interrupts in interrupt call using keyword 'enable' in interrupt definition. Using E2S and CCRX is this to do in 'vect.h'.

    here an example for Rx interrupt:

    #pragma interrupt (Excep_SCI6_RXI6(vect=86, enable))

  • Hello All,

    Apologies I couldn't add much information though, it was mostly related to overrun error in SPI communication. 

    Currently I see Serial communication is up and running. However, due to overrun error SPI communication after 15-18 frames are transmitted and received. 

    @Janek D thanks for your suggestion to enable Interrupts I could see this was needed to reenable interrupts.

    I will soon add code as reference as better solution on overrun issue is needed

    Thanks and regards,

    Satish

  • Here is SPI & UART Init and Interrupt code for reference -

    SPI Init - 

    void R_Config_SCI8_Create(void)

    {

    /* Cancel SCI8 module stop state */

    MSTP(SCI8) = 0U;

    /* Set interrupt priority */

    IPR(SCI8,TXI8) =_0F_SCI_PRIORITY_LEVEL15;

    /* Clear the control register */

    SCI8.SCR.BYTE = 0x00U;

    /* Set clock enable */

    SCI8.SCR.BYTE |= _01_SCI_INTERNAL_SCK_OUTPUT;

    /* Clear the SIMR1.IICM */

    SCI8.SIMR1.BIT.IICM = 0U;

    /* Set control registers */

    SCI8.SPMR.BYTE = _00_SCI_SS_PIN_DISABLE | _00_SCI_SPI_MASTER | _00_SCI_CLOCK_NOT_INVERTED |

    _00_SCI_CLOCK_NOT_DELAYED;

    SCI8.SMR.BYTE = _80_SCI_CLOCK_SYNCHRONOUS_OR_SPI_MODE | _00_SCI_CLOCK_PCLK;

    SCI8.SCMR.BYTE = _00_SCI_SERIAL_MODE | _00_SCI_DATA_INVERT_NONE | _08_SCI_DATA_MSB_FIRST |

    _10_SCI_DATA_LENGTH_8_OR_7 | _62_SCI_SCMR_DEFAULT;

    SCI8.SEMR.BYTE = _00_SCI_BIT_MODULATION_DISABLE;

    /* Set bit rate */

    SCI8.BRR = 0x28U; /*To be reviewed 100kbps*/

    /* Set SMISO8 pin */

    MPC.PC6PFS.BYTE = 0x0AU;

    PORTC.PMR.BYTE |= 0x40U;

    /* Set SMOSI8 pin */

    MPC.PC7PFS.BYTE = 0x0AU;

    PORTC.PMR.BYTE |= 0x80U;

    /* Set SCK8 pin */

    MPC.PC5PFS.BYTE = 0x0AU;

    PORTC.PMR.BYTE |= 0x20U;

    }

    static void _near SCI8_SPI_TrasmitInterrupt(void)
    {
    if (0U < g_sci8_tx_count)
    {
    SCI8.TDR = *gp_sci8_tx_address;
    gp_sci8_tx_address++;
    g_sci8_tx_count--;
    }
    else
    {
    SCI8.SCR.BIT.TIE = 0U;
    SCI8.SCR.BIT.TEIE = 1U;
    }
    }
    /***********************************************************************************************************************
    * Function Name: SCI8_SPI_TrasmitendInterrupt
    * Description : This function is a callback function when SCI8 finishes transmission
    * Arguments : None
    * Return Value : None
    ***********************************************************************************************************************/
    static void SCI8_SPI_TrasmitendInterrupt(void)
    {
    /* Start user code for r_Config_callback_transmitend. Do not edit comment generated here */
    SCI8.SCR.BIT.TIE = 0U;
    SCI8.SCR.BIT.TEIE = 0U;

    /* Clear TE and RE bits */
    if(0U == SCI8.SCR.BIT.RIE)
    {
    SCI8.SCR.BYTE &= 0xCFU;
    }

    SCI8_callback_transmitend();
    /* End user code. Do not edit comment generated here */
    }
    /***********************************************************************************************************************
    * Function Name: SCI8_SPI_ReceiveInterrupt
    * Description : This function is RXI8 interrupt service routine
    * Arguments : None
    * Return Value : None
    ***********************************************************************************************************************/
    static void SCI8_SPI_ReceiveInterrupt(void)
    {
    if (g_sci8_rx_length > g_sci8_rx_count)
    {
    *gp_sci8_rx_address = SCI8.RDR;
    gp_sci8_rx_address++;
    g_sci8_rx_count++;

    if (g_sci8_rx_length == g_sci8_rx_count)
    {
    SCI8.SCR.BIT.RIE = 0;

    /* Clear TE and RE bits */
    if((0U == SCI8.SCR.BIT.TIE) && (0U == SCI8.SCR.BIT.TEIE))
    {
    SCI8.SCR.BYTE &= 0xCFU;
    }

    SCI8_callback_receiveend();
    }
    }
    }
    /***********************************************************************************************************************
    * Function Name: SCI8_SPI_ReceiveErrorInterrupt
    * Description : This function is a callback function when CSI01 reception error occurs.
    * Arguments : err_type -
    * error type value
    * Return Value : None
    ***********************************************************************************************************************/
    static void SCI8_SPI_ReceiveErrorInterrupt(void)
    {
    uint8_t err_type;
    SCI8_callback_receiveerror();

    /* Clear overrun error flag */
    err_type = SCI8.SSR.BYTE;
    err_type &= 0xDFU;
    err_type |= 0xC0U;
    SCI8.SSR.BYTE = err_type;
    /* End user code. Do not edit comment generated here */
    }

    static void SCI8_callback_transmitend(void)
    {
    /* Start user code for r_Config_callback_receiveend. Do not edit comment generated here */
    if ( (g_sci8_tx_count == 0) && (CallbackComplete != NULL) )
    {
    CallbackeComplete(TRUE) ;
    }
    /* End user code. Do not edit comment generated here */
    }

    /***********************************************************************************************************************
    * Function Name: SCI8_callback_receiveend
    * Description : This function is a callback function when SCI8 reception encounters error
    * Arguments : None
    * Return Value : None
    ***********************************************************************************************************************/

    static void SCI8_callback_receiveend(void)
    {
    /* Start user code for r_Config_callback_receiveerror. Do not edit comment generated here */
    if ((gp_sci8_tx_address == NULL) && (g_sci8_rx_count == g_sci8_rx_length) && (CallbackComplete != NULL))
    {
    CallbackComplete(TRUE) ;
    }
    /* End user code. Do not edit comment generated here */
    }
    /***********************************************************************************************************************
    * Function Name: SCI8_callback_receiveerror
    * Description : This function is a callback function when SCI8 reception encounters error
    * Arguments : None
    * Return Value : None
    ***********************************************************************************************************************/

    static void SCI8_callback_receiveerror(void)
    {
    /* Start user code for r_Config_callback_receiveerror. Do not edit comment generated here */
    /* End user code. Do not edit comment generated here */
    }

    UART Init -

    void R_Config_SCI0_Create(void)

    {

    /* Cancel SCI stop state */

    MSTP(SCI0) = 0U;

    /* Set interrupt priority */

    IPR(SCI0, TXI0) = _0E_SCI_PRIORITY_LEVEL14 ;

    /* Clear the control register */

    SCI0.SCR.BYTE = 0x00U;

    /* Set clock enable */

    SCI0.SCR.BYTE = _00_SCI_INTERNAL_SCK_UNUSED;

    /* Clear the SIMR1.IICM, SPMR.CKPH, and CKPOL bit, and set SPMR */

    SCI0.SIMR1.BIT.IICM = 0U;

    SCI0.SPMR.BYTE = _00_SCI_RTS | _00_SCI_CLOCK_NOT_INVERTED | _00_SCI_CLOCK_NOT_DELAYED;

    /* Set control registers */

    SCI0.SMR.BYTE = _01_SCI_CLOCK_PCLK_4 | _00_SCI_MULTI_PROCESSOR_DISABLE | _08_SCI_STOP_2 | _00_SCI_PARITY_EVEN |

    _20_SCI_PARITY_ENABLE | _00_SCI_DATA_LENGTH_8 | _00_SCI_ASYNCHRONOUS_OR_I2C_MODE;

    SCI0.SCMR.BYTE = _00_SCI_SERIAL_MODE | _00_SCI_DATA_INVERT_NONE | _00_SCI_DATA_LSB_FIRST |

    _10_SCI_DATA_LENGTH_8_OR_7 | _62_SCI_SCMR_DEFAULT;

    SCI0.SEMR.BYTE = _00_SCI_BIT_MODULATION_DISABLE | _10_SCI_8_BASE_CLOCK | _00_SCI_NOISE_FILTER_DISABLE |

    _00_SCI_BAUDRATE_SINGLE | _80_SCI_FALLING_EDGE_START_BIT;

    /* Set bit rate */

    SCI0.BRR = 0x0CU;

    /* Set RXD0 pin */

    MPC.P21PFS.BYTE = 0x0AU;

    PORT2.PMR.BYTE |= 0x02U;

    /* Set TXD0 pin */

    MPC.P20PFS.BYTE = 0x0AU;

    PORT2.PODR.BYTE |= 0x01U;

    PORT2.PDR.BYTE |= 0x01U;

    }

    static void _near SCI0_RX_IRQHandler(void)

    {

    #ifdef DBG_DATA_SERIAL_PORT

    /* add debug code here */

    #else

    uint8_t rx_temp = 0 ;

    R_Config_SCI0_Receive(&App.Buffer[_RxIndex]);

    /* has a complete spot packet been received ?*/

    _RxIndex++;

    if(_RxIndex >= PACKET_LENGTH)

    {

    if (ServiceEEPROMReadWrite () == TRUE)

    {

    /* wait for between 500 and 1000us to respond */

    _CommsTxCounter = COMMS_TX_TIMEOUT;

    }

    _RxIndex = (UCHAR)0;

    _CommsIdleCounter = (UCHAR)0;

    }

    else

    {

    /* load timeout period for next byte */

    _CommsIdleCounter = COMMS_IDLE_TIMEOUT;

    }

    #endif

    }

    static void _near SCI0_RX_Error_IRQHandler(void)
    {
    uint8_t err_type;

    /* Clear overrun, framing and parity error flags */
    err_type = SCI0.SSR.BYTE;
    err_type &= 0xC7U;
    err_type |= 0xC0U;
    SCI0.SSR.BYTE = err_type;
    }
    /***********************************************************************************************************************
    * Function Name: SCI0_TX_IRQHandler
    * Description : None
    * Arguments : None
    * Return Value : None
    ***********************************************************************************************************************/
    static void _near SCI0_TX_IRQHandler(void)
    {
    #ifdef DBG_DATA_SERIAL_PORT
    if (g_uart2_tx_count > 0U)
    {
    SCI0.TDR = *gp_sci0_tx_address;
    gp_sci0_tx_address++;
    g_sci0_tx_count--;
    }
    #else
    /* any more bytes to send? */
    if(_TxIndex < PACKET_LENGTH)
    {
    R_Config_SCI0_Serial_Send((&G_TxPacket.Buffer[_TxIndex++]));
    }
    else
    {
    /* disable Spot Transmit interrupt and enable Spot Transmit Completed interrupt for single spot frame */
    DisableTxIRQ() ;
    EnableTxEndIRQ();
    _CommsIdleCounter = TX_RELEASE_TIMEOUT;
    }
    #endif

    }

    /***********************************************************************************************************************
    * Function Name: SCI0_TX_End_IRQHandler
    * Description : None
    * Arguments : None
    * Return Value : None
    ***********************************************************************************************************************/
    static void _near SCI0_TX_End_IRQHandler(void)
    {
    /* Set TXD0 pin */
    PORT2.PMR.BYTE &= 0xFEU;

    DisableTxIRQ() ;
    DisableTx() ;
    DisableTxEndIRQ();
    /* Set Transmit Index to 0 for next frame transmission */
    _TxIndex = 0;
    }

  • Controller Used is Rx130 series R5F5130B

    IDE Used - e2Studio

    Compiler - CCRX -3.5.0 

     

    Clock for Peripherals is configured 16MHz

     

    SPI configuration is configured with following configuration -

    8 bit data length 

    1000kbps

    MSB first No Reverse/Invert enabled in data transfer

    Internal Clock

    Interrupts configured are - Transmit, Transmit End, Receive, Error along with it all callbacks are configured

    Priority 15

     

    UART configuration is configured with following configuration -

    8 bit data length 

    19200kbps

    LSB first No Reverse/Invert enabled in data transfer

    Internal Clock

    Interrupts configured are - Transmit, Transmit End, Receive, Error along with it all callbacks are configured

    Priority 14

     

    HAL code is generated using smart config. Initialization and interrupts are same as they are when generated.

    Some application and SPI EEPROM read/write code change is added in callbacks.

     

    As mentioned in first message of this thread in our application SPI read/write is happening in Receive Interrupt context of UART.

    Sequence of operation is as below -

    Parameter write request is receieved over UART comms

    Current value of Parameter read from  EEPROM using SPI comms

    New value to be written to EEPROM is sent over SPI comms.

     

    Earlier I faced issue of interrupts not hitting properly which got resolved by enabling global interrupts again within UART interrupt.

    However now I am facing issue of overrun. after 10-15 cycles of read/write I face overrun in SPI comms. 

    BRR configuration is not changed and its value is 3 and PCLK is 16 (no pre-scalar). As per information in user manual of RX family (page 720) where in table of BRR and Clock settings are given; it shows 0% error shall be generated with n=0 and N=3 with PCLK =16MHz.

  • Hello All,

    ,  

    Any suggestions or support is much appreciated.

  • Did you try to use the DTC for SPI communication? DTC is ideal because you use the SPI for EEPROM, So you now the number of bytes on before hand and it will reduce the number of interrupts.

  • Nop. Haven't tried with DTC. Though it is nice idea, it requires to re-design software part for that...as UART and EEPROM SPI comms are linked...so currently we are trying to go with existing software flow...but sure we will give it try if I don't get any further help/suggestions on above design

  • Hello Satish,

    Thank you for reaching out to the Renesas community and for providing a detailed explanation of the issue.

    As I can see from your program's structure, you're handling multiple tasks within the interrupt service routines, and each interrupt call consumes CPU cycles. Here are a few things to keep in mind:

    As you may already know:

    • An SPI overrun error can occur when data is sent from the slave device (EEPROM), but the CPU fails to retrieve the data from the RDR register, causing the buffer to fill up. Since SCI only has a double buffer for data caching, it's crucial to continuously read data to prevent overruns, especially at higher baud rates.

    • When reading data from the SPI slave (EEPROM), it's vital to treat this as an atomic operation, ensuring that no other interrupt can access the CPU while data is being read. This prevents the CPU from becoming busy during SPI transfers and minimizes the risk of overruns.

    To address these issues, consider keeping interrupt service routines as short as possible, increasing the CPU clock speed to 32MHz, and reducing the SPI baud rate. Additionally, as dear NGE suggested, you can utilize DTC for more efficient SCI communication handling, especially for frequent data transfers.

    I encourage you to try these suggestions and assess their effectiveness.

    If you have any further questions or need clarifications, please feel free to reach out. Happy debugging!

    Best regards.