renesas / fsp

Flexible Software Package (FSP) for Renesas RA MCU Family
https://renesas.github.io/fsp/
Other
182 stars 81 forks source link

RTC configuration after initial power-up can hang up under FSP v4.5.0 (Fixed in v4.6.0) #291

Closed dsmith9000 closed 10 months ago

dsmith9000 commented 10 months ago

Note: I have verified that this bug has been fixed in v4.6.0. I'm am including the bug report here for completeness in the event that anyone using 4.5.0 sees a similar situation.

Symptom: Upon power-on reset of our RA2E1 processor using FSP v4.5.0, the following initialization code can result in the processor getting stuck in an infinite loop in the call to 'R_RTC_PeriodicIrqRateSet' that ultimately ends in a IWDT reset. The processor reboots and then gets hung up at exactly the same spot. The process continues repeatedly.

Problem Application Code:

    // Initialize the FSP RTC driver
    bSuccess = (R_RTC_Open(g_rtc0.p_ctrl, g_rtc0.p_cfg) == FSP_SUCCESS);
    ASSERT(bSuccess);

    // Set the RTC clock source.
    bSuccess &= (R_RTC_ClockSourceSet(g_rtc0.p_ctrl) == FSP_SUCCESS);
    ASSERT(bSuccess);

    // Set the periodic interrupt rate to 1 second
    // << ** NOTE: THE PROCESSOR NEVER RETURNS FROM THE NEXT FUNCTION CALL ** >>
    bSuccess &= (R_RTC_PeriodicIrqRateSet(g_rtc0.p_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND) == FSP_SUCCESS);
    ASSERT(bSuccess);

I've been able to identify the line of code in 'R_RTC_PeriodicIrqRateSet' that results in the hang-up as the following statement: FSP_HARDWARE_REGISTER_WAIT(R_RTC->RCR2_b.CNTMD, RTC_CALENDAR_MODE);

fsp_err_t R_RTC_PeriodicIrqRateSet (rtc_ctrl_t * const p_ctrl, rtc_periodic_irq_select_t const rate)
{
    rtc_instance_ctrl_t * p_instance_ctrl = (rtc_instance_ctrl_t *) p_ctrl;
#if RTC_CFG_PARAM_CHECKING_ENABLE
    FSP_ASSERT(NULL != p_instance_ctrl);
    FSP_ERROR_RETURN(RTC_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
    FSP_ERROR_RETURN(p_instance_ctrl->p_cfg->periodic_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED);
#endif
    fsp_err_t err = FSP_SUCCESS;

    uint8_t rcr1 = R_RTC->RCR1;
    rcr1       &= (uint8_t) ~R_RTC_RCR1_PES_Msk;
    R_RTC->RCR1 = (uint8_t) (rcr1 | (rate << R_RTC_RCR1_PES_Pos));

    /* When the RCR1 register is modified, check that all the bits are updated before proceeding
     * (see section 26.2.17 "RTC Control Register 1 (RCR1)" of the RA6M3 manual R01UH0886EJ0100)*/
    FSP_HARDWARE_REGISTER_WAIT(R_RTC->RCR1 >> R_RTC_RCR1_PES_Pos, rate);

The problem is actually triggered by the call in the application code to 'R_RTC_ClockSourceSet' at the following line in the code snippet below: R_RTC->RCR1 = 0

The issue is that the statement is not being followed by an 'FSP_HARDWARE_REGISTER_WAIT' to force the processor to wait for the value to be updated asynchronously by the RTC hardware. The datasheet for the RTC peripheral states that this is required of certain RTC registers that get updated asynchronously to the instruction clock.

static void r_rtc_set_clock_source (rtc_instance_ctrl_t * const p_ctrl, rtc_cfg_t const * const p_cfg)
{
    /* Select the count source (RCKSEL) */
    R_RTC->RCR4 = (uint8_t) p_ctrl->p_cfg->clock_source;

    /* Supply 6 clocks of the count source (LOCO/SOSC, 183us, 32kHZ).
     * See 26.3.2 "Clock and Count Mode Setting Procedure" of the RA6M3 manual R01UH0886EJ0100)*/
    R_BSP_SoftwareDelay(BSP_PRV_RTC_RESET_DELAY_US, BSP_DELAY_UNITS_MICROSECONDS);

    r_rtc_start_bit_update(0U);

    if (RTC_CLOCK_SOURCE_LOCO == p_ctrl->p_cfg->clock_source)
    {
        /* Write 0 before writing to the RFRL register after a cold start. (see section 26.2.20
         * Frequency Register (RFRH/RFRL)" of the RA6M3 manual R01UH0886EJ0100) */
        R_RTC->RFRH = 0;

        R_RTC->RFRL = (uint16_t) p_cfg->freq_compare_value_loco;
    }

    R_RTC->RCR2 = 0;

    /* When setting the count mode, execute an RTC software reset and start again from the initial settings.
     * This bit is updated synchronously with the count source, and its value is fixed before the RTC software
     * reset is completed (see section 26.2.18 "RTC Control Register 2 (RCR2)" of the RA6M3 manual R01UH0886EJ0100)*/
    FSP_HARDWARE_REGISTER_WAIT(R_RTC->RCR2_b.CNTMD, RTC_CALENDAR_MODE);

    r_rtc_software_reset();

    /* Disable RTC interrupts */
    R_RTC->RCR1 = 0;

    /* Force RTC to 24 hour mode. Set HR24 bit in the RCR2 register */
    R_RTC->RCR2_b.HR24 = 1U;

    //<Code continues ...>

I've been able to verify that I can eliminate the problem by adding the 'FSP_HARDWARE_REGISTER_WAIT' following the specified line. I have also been able to eliminate it as a workaround that doesn't require modifying the stock FSP v4.5.0 by adding the test to the application code as shown below:

    // Initialize the FSP RTC driver
    bSuccess = (R_RTC_Open(g_rtc0.p_ctrl, g_rtc0.p_cfg) == FSP_SUCCESS);
    ASSERT(bSuccess);

    // Set the RTC clock source.
    bSuccess &= (R_RTC_ClockSourceSet(g_rtc0.p_ctrl) == FSP_SUCCESS);
    ASSERT(bSuccess);

    // ** NOTE (FSP v4.5.0): The next line prevents a cold-restart lockup (boot reset loop) we were experiencing due to a bug in FSP v4.5.0. In it, this line should have been in 'R_RTC_ClockSourceSet' and is corrected in
    // FSP 4.6.0, but by adding it here, it prevents lockup while using stock FSP v4.5.0.
    /* When the RCR1 register is modified, check that all the bits are updated before proceeding
     * (see section 26.2.17 "RTC Control Register 1 (RCR1)" of the RA6M3 manual R01UH0886EJ0100)*/
    FSP_HARDWARE_REGISTER_WAIT(R_RTC->RCR1, 0);

    // Set the periodic interrupt rate to 1 second
    bSuccess &= (R_RTC_PeriodicIrqRateSet(g_rtc0.p_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND) == FSP_SUCCESS);
    ASSERT(bSuccess);

Again, this bug has been fixed in r_rtc.c in FSP v4.6.0, but I wanted to make sure it had some visibility for those that may be searching for a similar symptom in their systems.

renesas-brandon-hussey commented 10 months ago

Thanks for the detailed information @dsmith9000 !