nrf5-calendar-example SOFTDEVICE: INVALID MEMORY ACCESS

I try to integrate https://github.com/NordicPlayground/nrf5-calendar-example into Keil project. But the following error messages shown when accessing NRF_CLOCK.

error messages

nrf5-calendar-example SOFTDEVICE: INVALID MEMORY ACCESS

source code

int main(void) {
    _initVariables();
    

    // Initialize.
    log_init(); // Power_saving
    uart_init(); // Power_saving
    //_showInfo();
    fstorageInit();
    batteryVoltageInit();
    timerInit();
    button_events_init();
    scheduler_init();
    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    db_discovery_init();
    services_init();
    advertising_init();
    conn_params_init();
    timerPeriodStart();
    timerStart();
    

    //  SOFTDEVICE: INVALID MEMORY ACCESS occurred when running the following code
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;
    while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    
     nrf_cal_init();
     nrf_cal_set_callback(calendar_updated, 4);

}

Parents
  • Hello,

    The app does not have write access to the CLOCK peripheral when the Softdevice is enabled, hence the assert (See Hardware peripherals). Instead you have to access it via the provided Softdevice APIs such as sd_clock_hfclk_request().

    However, it should not be necessary to start HF crystal oscillator for the calendar library, so my suggestion would be to simply not include this code:

        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART = 1;
        while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);

    Best regards,

    Vidar

  • Thanks for your reply! I have changed above code to the following code.

    const ret_code_t errCode = sd_clock_hfclk_request();
        if (errCode != NRF_SUCCESS) {
            NRF_LOG_WARNING("sd_clock_hfclk_request() failed\n");
        }    

        uint32_t hfclkIsRunning = 0;

        while (!hfclkIsRunning) {
            APP_ERROR_CHECK(sd_clock_hfclk_is_running(&hfclkIsRunning) );
        }

    Now it hangs at nrf_cal_init() as the following error messages.

    <debug> app: nrf_cal_init() e
     0>
     0> <error> app: SOFTDEVICE: INVALID MEMORY ACCESS

    void nrf_cal_init(void) {
        NRF_LOG_DEBUG("nrf_cal_init() e\n");
        // Select the 32 kHz crystal and start the 32 kHz clock
        NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos;
        NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_LFCLKSTART = 1;
        while(NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);
        NRF_LOG_DEBUG("1\n");
        
        // Configure the RTC for 1 minute wakeup (default)
        CAL_RTC->PRESCALER = 0xFFF;
        CAL_RTC->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
        CAL_RTC->INTENSET = RTC_INTENSET_COMPARE0_Msk;
        CAL_RTC->CC[0] = m_rtc_increment * 8;
        CAL_RTC->TASKS_START = 1;

    }

  • You don't need to start the LF clock either as the Softdevice does it when you enable it. So uou can remove this from cal_init():

        NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos;
        NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_LFCLKSTART = 1;
        while(NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);

  • I have removed NRF_CLOCK related code from nrf_cal_init().Do you have any suggestion about how to change CAL_RTC related code to Softdevice APIs?

    void nrf_cal_init(void) {
        NRF_LOG_DEBUG("nrf_cal_init() e\n");
        
        // Configure the RTC for 1 minute wakeup (default)
        CAL_RTC->PRESCALER = 0xFFF;
        CAL_RTC->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
        CAL_RTC->INTENSET = RTC_INTENSET_COMPARE0_Msk;
        CAL_RTC->CC[0] = m_rtc_increment * 8;
        CAL_RTC->TASKS_START = 1;

    }

  • Yes, RTC0 is reserved to the Softdevice as well, so you need to select another RTC instance.

    In nrf_calendar.h, change:

    // Change the following defines to change the RTC timer used or the interrupt priority
    #define CAL_RTC                 NRF_RTC0
    #define CAL_RTC_IRQn            RTC0_IRQn
    #define CAL_RTC_IRQHandler      RTC0_IRQHandler
    #define CAL_RTC_IRQ_Priority    3

    To:

    // Change the following defines to change the RTC timer used or the interrupt priority
    #define CAL_RTC                 NRF_RTC2
    #define CAL_RTC_IRQn            RTC2_IRQn
    #define CAL_RTC_IRQHandler      RTC2_IRQHandler
    #define CAL_RTC_IRQ_Priority    6

  • Thanks for your suggetion. I have changed nrf_calendar.h as follows.

    // Change the following defines to change the RTC timer used or the interrupt priority
    #define CAL_RTC                 NRF_RTC2
    #define CAL_RTC_IRQn            RTC2_IRQn
    #define CAL_RTC_IRQHandler      RTC2_IRQHandler
    #define CAL_RTC_IRQ_Priority  

  • Are you still getting the assert, or does it work now?

Reply Children
  • No assert now. But time is not correct after calling nrf_cal_set_time(). The log message is as follows.

     <debug> app: 2022-6-28 17:24:45
     0>
     0> <debug> app: nrf_cal_set_time(2022, 6, 28, 17, 24, 45
     0>
     0> <info> app:
     0>
     0> <debug> app: Uncalibrated time:    07/28/22 - 17:39:40
     0>

  • 4657.nrf_calendar.h

    /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
     *
     * The information contained herein is property of Nordic Semiconductor ASA.
     * Terms and conditions of usage are described in detail in NORDIC
     * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
     *
     * Licensees are granted free, non-transferable use of the information. NO
     * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
     * the file.
     *
     */
     
    #include "nrf_calendar.h"
    #include "nrf.h"
    #include "nrf_log.h"
    
    static bool gCalTimeSet = false;
    static struct tm time_struct, m_tm_return_time; 
    static time_t m_time, m_last_calibrate_time = 0;
    static float m_calibrate_factor = 0.0f;
    static uint32_t m_rtc_increment = 60;
    static void (*nrf_cal_event_callback)(void) = 0;
    
    void nrf_cal_updated(void) {
        //nrf_cal_print_current_time();
    }
    
    void nrf_cal_init(void) {
        gCalTimeSet          = false;
        CAL_RTC->EVTENSET    = RTC_EVTENSET_COMPARE0_Msk;
        CAL_RTC->INTENSET    = RTC_INTENSET_COMPARE0_Msk;
        CAL_RTC->CC[0]       = m_rtc_increment * 8;
        CAL_RTC->TASKS_START = 1;
        NVIC_SetPriority(CAL_RTC_IRQn, CAL_RTC_IRQ_Priority);
        NVIC_EnableIRQ(CAL_RTC_IRQn);
        nrf_cal_set_callback(nrf_cal_updated, 4);
    }
    
    void nrf_cal_set_callback(void (*callback)(void), uint32_t interval) {
        // Set the calendar callback, and set the callback interval in seconds
        nrf_cal_event_callback = callback;
        m_rtc_increment = interval;
        m_time += CAL_RTC->COUNTER / 8;
        CAL_RTC->TASKS_CLEAR = 1;
        CAL_RTC->CC[0] = interval * 8;  
    }
     
    void nrf_cal_set_time(uint32_t year, uint32_t month, uint32_t day, uint32_t hour, uint32_t minute, uint32_t second) {
        NRF_LOG_DEBUG("nrf_cal_set_time(%u, %u, %u, %u, %u, %u\n", year, month, day, hour, minute, second);
        static time_t uncal_difftime, difftime, newtime;
        time_struct.tm_year = year - 1900;
        time_struct.tm_mon  = month;
        time_struct.tm_mday = day;
        time_struct.tm_hour = hour;
        time_struct.tm_min  = minute;
        time_struct.tm_sec  = second;   
        newtime = mktime(&time_struct);
        CAL_RTC->TASKS_CLEAR = 1;  
        
        // Calculate the calibration offset 
        if (m_last_calibrate_time != 0) {
            difftime = newtime - m_last_calibrate_time;
            uncal_difftime = m_time - m_last_calibrate_time;
            m_calibrate_factor = (float)difftime / (float)uncal_difftime;
        }
        
        // Assign the new time to the local time variables
        m_time = m_last_calibrate_time = newtime;
        gCalTimeSet = true;
    }    
    
    struct tm *nrf_cal_get_time(void) {
        time_t return_time;
        return_time = m_time + CAL_RTC->COUNTER / 8;
        m_tm_return_time = *localtime(&return_time);
        return &m_tm_return_time;
    }
    
    struct tm *nrf_cal_get_time_calibrated(void) {
        time_t uncalibrated_time, calibrated_time;
        if(m_calibrate_factor != 0.0f)
        {
            uncalibrated_time = m_time + CAL_RTC->COUNTER / 8;
            calibrated_time = m_last_calibrate_time + (time_t)((float)(uncalibrated_time - m_last_calibrate_time) * m_calibrate_factor + 0.5f);
            m_tm_return_time = *localtime(&calibrated_time);
            return &m_tm_return_time;
        }
        else return nrf_cal_get_time();
    }
    
    char *nrf_cal_get_time_string(bool calibrated) {
        static char cal_string[80];
        strftime(cal_string, 80, "%x - %H:%M:%S", (calibrated ? nrf_cal_get_time_calibrated() : nrf_cal_get_time()));
        return cal_string;
    }
     
    void CAL_RTC_IRQHandler(void) {
        if (CAL_RTC->EVENTS_COMPARE[0]) {
            CAL_RTC->EVENTS_COMPARE[0] = 0;
            CAL_RTC->TASKS_CLEAR = 1;
            m_time += m_rtc_increment;
            if (nrf_cal_event_callback != NULL) {
                nrf_cal_event_callback();
            }    
        }
    }
    void nrf_cal_print_current_time(void) {
        if (gCalTimeSet) {
            NRF_LOG_DEBUG("Uncalibrated time:\t%s\r\n", nrf_cal_get_time_string(false));
            NRF_LOG_DEBUG("Calibrated time:\t%s\r\n", nrf_cal_get_time_string(true));
        }    
    }
    # SEGGER J-Link RTT Viewer V6.32i Terminal Log File
    # Compiled: 15:22:50 on Jul 24 2018
    # Logging started @ 28 Jun 2022 17:23:49
     0> <info> app: ========| flash info |========
     0> <info> app: erase unit:   4096 bytes
     0> <info> app: program unit: 4 bytes
     0> <info> app: end address: 0x7FFFF
     0> <info> app: ==============================
     0> <info> app_timer: RTC: initialized.
     0> <debug> app: NOR_DATA_PERIOD=819
     0> 
     0> <debug> app: NOR_RECORD_PERIOD=8192
     0> 
     0> <info> app: bsp_button_longkey_handler 0.
     0> <info> app: POWER_ON.
     0> <info> app: External devices initializing start
     0> <info> app: Reg 0 20
     0> <info> app: Reg 9 A
     0> <info> app: Reg A D
     0> <info> app: Reg 1 B
     0> <info> app: Reg 2 D
     0> <info> app: Reg D F
     0> <info> app: Reg E 13
     0> <info> app: Reg 36 10
     0> <info> app: Reg 37 13
     0> <info> app: Reg 5 11
     0> <info> app: Reg 6 13
     0> <info> app: Reg F 15
     0> <info> app: Reg 10 19
     0> <info> app: Reg 3 16
     0> <info> app: Reg 4 19
     0> <info> app: Reg 7 17
     0> <info> app: Reg 8 19
     0> <info> app: Reg 11 1B
     0> <info> app: Reg 12 1F
     0> <info> app: Reg 43 0
     0> <info> app: Reg 44 0
     0> <info> app: Reg B 1D
     0> <info> app: Reg C 1F
     0> <info> app: Reg 13 21
     0> <info> app: Reg 14 25
     0> <info> app: Reg 1D 3F
     0> <info> app: Reg 64 0
     0> <info> app: Reg 65 27
     0> <info> app: Reg 66 0
     0> <info> app: Reg 67 27
     0> <info> app: Reg 68 0
     0> <info> app: Reg 69 27
     0> <info> app: Reg 52 2C
     0> <info> app: Reg 53 2C
     0> <info> app: Reg 6A 32
     0> <info> app: Reg 6B 38
     0> <info> app: Reg 1E 101
     0> <info> app: Reg 20 3
     0> <info> app: Reg 21 2
     0> <info> app: Reg 22 802084
     0> <info> app: Reg 23 124218
     0> <info> app: Reg 4B F
     0> <info> app: Reg 50 18
     0> <info> app: Reg 31 20
     0> <info> app: Reg 39 5
     0> <info> app: Reg 4E 0
     0> <info> app: Reg 4E 8
     0> <info> app: Reg 45 8
     0> <info> app: Reg 46 13
     0> <info> app: Reg 47 14
     0> <info> app: Reg 48 1F
     0> <info> app: Reg 0 21
     0> <info> app: External devices initializing finish
     0> <info> app: bsp_button_longkey_handler 1.
     0> <debug> nrf_ble_gatt: Requesting to update ATT MTU to 185 bytes on connection 0x0.
     0> <info> app: Connected.
     0> <debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 527 bytes.
     0> <debug> nrf_ble_gatt: Updating ATT MTU to 185 bytes (desired: 185) on connection 0x0.
     0> <debug> nrf_ble_gatt: ATT MTU updated to 185 bytes on connection 0x0 (response).
     0> <debug> nrf_ble_gatt: Peer on connection 0x0 requested a data length of 251 bytes.
     0> <debug> nrf_ble_gatt: Updating data length to 27 on connection 0x0.
     0> <debug> nrf_ble_gatt: Data length updated to 27 on connection 0x0.
     0> <debug> nrf_ble_gatt: max_rx_octets: 27
     0> <debug> nrf_ble_gatt: max_tx_octets: 27
     0> <debug> nrf_ble_gatt: max_rx_time: 2120
     0> <debug> nrf_ble_gatt: max_tx_time: 2120
     0> <info> app: Received data from BLE NUS. Writing data on UART.
     0> <debug> app:  54 49 4D 45 20 32 30 32|TIME 202
     0> <debug> app:  32 2D 30 36 2D 32 38 20|2-06-28 
     0> <debug> app:  31 37 3A 32 34 3A 34 35|17:24:45
     0> <debug> app: length=24
     0> <debug> app: data[0]=0x54 T
     0> <debug> app: data[1]=0x49 I
     0> <debug> app: data[2]=0x4D M
     0> <debug> app: data[3]=0x45 E
     0> <debug> app: data[4]=0x20  
     0> <debug> app: data[5]=0x32 2
     0> <debug> app: data[6]=0x30 0
     0> <debug> app: data[7]=0x32 2
     0> <debug> app: data[8]=0x32 2
     0> <debug> app: data[9]=0x2D -
     0> <debug> app: data[10]=0x30 0
     0> <debug> app: data[11]=0x36 6
     0> <debug> app: data[12]=0x2D -
     0> <debug> app: data[13]=0x32 2
     0> <debug> app: data[14]=0x38 8
     0> <debug> app: data[15]=0x20  
     0> <debug> app: data[16]=0x31 1
     0> <debug> app: data[17]=0x37 7
     0> <debug> app: data[18]=0x3A :
     0> <debug> app: data[19]=0x32 2
     0> <debug> app: data[20]=0x34 4
     0> <debug> app: data[21]=0x3A :
     0> <debug> app: data[22]=0x34 4
     0> <debug> app: data[23]=0x35 5
     0> <debug> app: state=1
     0> 
     0> <debug> app: 2 2
     0> 
     0> <debug> app: 0 0
     0> 
     0> <debug> app: 2 2
     0> 
     0> <debug> app: 2 2
     0> 
     0> <debug> app: 6 6
     0> 
     0> <debug> app: 0 0
     0> 
     0> <debug> app: 8 8
     0> 
     0> <debug> app: 2 2
     0> 
     0> <debug> app: 7 7
     0> 
     0> <debug> app: 1 1
     0> 
     0> <debug> app: 4 4
     0> 
     0> <debug> app: 2 2
     0> 
     0> <debug> app: 5 5
     0> 
     0> <debug> app: 4 4
     0> 
     0> <debug> app: 2022-6-28 17:24:45
     0> 
     0> <debug> app: nrf_cal_set_time(2022, 6, 28, 17, 24, 45
     0> 
     0> <info> app: 
     0> 
     0> <debug> app: Uncalibrated time:	07/28/22 - 17:39:40
     0> 
     0> <debug> app: Calibrated time:	07/28/22 - 17:39:40
     0> 
     0> <debug> app: Uncalibrated time:	07/28/22 - 18:12:48
     0> 
     0> <debug> app: Calibrated time:	07/28/22 - 18:12:48
     0> 
     0> <debug> app: Uncalibrated time:	07/28/22 - 18:45:52
     0> 
     0> <debug> app: Calibrated time:	07/28/22 - 18:45:52
     0> 
     0> <debug> app: Uncalibrated time:	07/28/22 - 19:18:56
     0> 
     0> <debug> app: Calibrated time:	07/28/22 - 19:18:56
     0> 
     0> <debug> app: Uncalibrated time:	07/28/22 - 19:52:04
     0> 
     0> <debug> app: Calibrated time:	07/28/22 - 19:52:04
     0> 
     0> <debug> app: Uncalibrated time:	07/28/22 - 20:25:03
     0> 
     0> <debug> app: Calibrated time:	07/28/22 - 20:25:03
     0> 
     0> <debug> app: Uncalibrated time:	07/28/22 - 20:58:11
     0> 
     0> <debug> app: Calibrated time:	07/28/22 - 20:58:11
     0> 
     0> <debug> app: Uncalibrated time:	07/28/22 - 21:31:11
     0> 
     0> <debug> app: Calibrated time:	07/28/22 - 21:31:11
     0> 
    

  • After I modified nrf_cal_init() as follows. Time is almost correct except month.

    void nrf_cal_init(void) {
        gCalTimeSet          = false;
        // Configure the RTC for 1 minute wakeup (default)
        CAL_RTC->PRESCALER   = 0xFFF;
        CAL_RTC->EVTENSET    = RTC_EVTENSET_COMPARE0_Msk;
        CAL_RTC->INTENSET    = RTC_INTENSET_COMPARE0_Msk;
        CAL_RTC->CC[0]       = m_rtc_increment * 8;
        CAL_RTC->TASKS_START = 1;
        NVIC_SetPriority(CAL_RTC_IRQn, CAL_RTC_IRQ_Priority);
        NVIC_EnableIRQ(CAL_RTC_IRQn);
        nrf_cal_set_callback(nrf_cal_updated, 4);
    }

    Log messages.

    <debug> app: nrf_cal_set_time(2022, 6, 28, 18, 0, 14)
     0>
     0> <info> app:
     0>
     0> <debug> app: Uncalibrated time:    07/28/22 - 18:00:14

  • The month is off by one because time.h counts the first month from zero.

Related