This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

BLE APP TIMER

hi,

Our customer find BLE's app_timer emerge a deviation when use the BLE's app_timer. the customer is developing bracelet product , their programs with two app_timer, the one app_ timer generating 1 second timing for date and time information.another use in pedometer function.the app_timer wake up every 25ms when counting Steps,and it wake up every minute when not used in counting Steps. if Bracelet put on the table,or rarely walk. Calendar time is right, but the Calendar time will be faster when counting Steps frequently, it will be faster two or three minutes a day. However, it not emerge a deviation under s110 v6.0 SDK v5.2 and the same program , what is the reason?

Thanks and Best regards

Parents
  • my programer use two APP TIMER

    typedef struct{
    
        SoftWareRtcInterface Interface;
    
        //private:
    
        void (*mWakeUpIrq)(void * p_context);
    
        void (*mSecondIrq)(void * p_context);
    
        void (*mMinuteIrq)(void * p_context);
    
        void (*mHourIrq)(void *p_context);
    
        volatile uint32_t mWakeUpOverFlow;
    
        volatile uint32_t mSecondCount;
    
        volatile uint32_t mSecondtRecord;
    
        volatile uint32_t mPowerUpTime;
    
        //Used to generate one second timing to generate the date and time information
    
        app_timer_id_t    mSecondTimerId;  
    
        // Wake-up timer for system operation. Pedometer when 25MS wake every time.
    
        // Stationary wake every minute
    
        app_timer_id_t    mWakeUpTimerId;
    }SoftWareRtcHal;
    
    
    #define FW_APP_TIMER_MAX_TIMERS    6 
    
    #define FW_APP_TIMER_OP_QUEUE_SIZE 20 // I tried defined as 1 OR 20
    
    
    void lfclk_config(void)
    {
    
        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_CLOCK->EVENTS_LFCLKSTARTED = 0;
    }
    
    void AppTimeInit(void)
    {
    
        APP_TIMER_INIT(APP_TIMER_PRESCALER, FW_APP_TIMER_MAX_TIMERS, 
        FW_APP_TIMER_OP_QUEUE_SIZE, FALSE);
    
    }
    
    void InitSoftWareRtc(SoftWareRtcInterface *interface)
    {
    
        uint32_t err_code;
    
        SoftWareRtcHal *pRtcHal = (SoftWareRtcHal *)interface;    
    
    
        interface->SetWakeUpPeriod = &gRtcSetWakeUpPeriod;
    
        interface->GetSecond32 = &gRtcGetSecond32;
    
        interface->GetPowerUpTime = &gRtcGetPowerUpTime;
    
        interface->SetDate = &gRtcSetDate;
    
        interface->SetTime = &gRtcSetTime;
    
        interface->GetDate = &gRtcGetDate;
    
        interface->GetTime = &gRtcGetTime;
    
        interface->RegisterWakeUpIrq = &gRtcRegisterWakeUpIrq;
    
        interface->RegisterSecondIrq = &gRtcRegisterSecondIrq;
    
        interface->RegisterMinuteIrq = &gRtcRegisterMinuteIrq;
    
        interface->RegisterHourIrq = &gRtcRegisterHourIrq;
    
        interface->StateCheck = &gRtcStateCheck;
    
        //interface->IRQHandle = &gRtcIRQHandle;
    
        interface->RestStart = &gRtcRestStart;
    
        pRtcHal->mSecondtRecord = pRtcHal->mSecondCount;
    
        pRtcHal->mWakeUpIrq = NULL;
    
        pRtcHal->mSecondIrq = NULL;
    
        pRtcHal->mMinuteIrq = NULL;
    
        pRtcHal->mHourIrq = NULL;	
    
        TRACE2("pRtcHal->gRtcSecond = %x", pRtcHal->mSecondCount);
    
        err_code = app_timer_create(&pRtcHal->mSecondTimerId,
                     APP_TIMER_MODE_REPEATED,
                     gRtcAppTimerSecondHandle);
    
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_start(pRtcHal->mSecondTimerId,
                    APP_TIMER_TICKS(1000, APP_TIMER_PRESCALER),
                    pRtcHal);
    
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_create(&pRtcHal->mWakeUpTimerId,
                     APP_TIMER_MODE_REPEATED,
                     gRtcAppTimerWakeUpHandle);
    
        APP_ERROR_CHECK(err_code);
    }
    
    void gRtcAppTimerSecondHandle(void * p_context)
    {
    
        SoftWareRtcHal *pRTC = (SoftWareRtcHal *)p_context;
    
        pRTC->mSecondCount++;
    
        if(pRTC->mSecondIrq != NULL)
        {
            pRTC->mSecondIrq(NULL);
        }
    
        if((pRTC->mMinuteIrq != NULL) &&
            (pRTC->mSecondCount % 60 == 0))
        {
            pRTC->mMinuteIrq(NULL);
        }
    
        if((pRTC->mHourIrq != NULL) &&
            (pRTC->mSecondCount % 3600 == 0))
        {
            pRTC->mHourIrq(NULL);
        }
    
        //TRACE_INFO1("*");
    }
    
    bool gRtcSetWakeUpPeriod(SoftWareRtcInterface *RtcInterface, uint16_t period)
    {
    
        /*************************************
        *    Ftick = 1000mS/period;
        *    Ftick == 32768/(PRESCALER+1)
        *==> PRESCALER + 1 == 32768 / Ftick
        *==>
        *==> PRESCALER == 32768 * period / 1000 -1
        *
        *TICK = 32768 / (127+1); 128分频
        *T = 1/TICK;
        *PROID = T * WakeUpOverFlow = WakeUpOverFlow / TICK;
        *WakeUpOverFlow = PROID * (32768 / 128);
        *30mS => WakeUpOverFlow = 0.030 * (32768/128) = 8
        **************************************/
    
        uint32_t err_code;
    
        SoftWareRtcHal *pRTC;
    
        uint32_t mCurWakeUpOverFlow;
    
        if(RtcInterface == NULL)
            return -1;
    
        pRTC = (SoftWareRtcHal *)RtcInterface;
    
        mCurWakeUpOverFlow = APP_TIMER_TICKS(period, NRF_RTC1->PRESCALER);
    
        if(mCurWakeUpOverFlow == pRTC->mWakeUpOverFlow)
             return 0;
    
        pRTC->mWakeUpOverFlow = mCurWakeUpOverFlow;	
    
        TRACE2("pRTC->mWakeUpOverFlow = %x", pRTC->mWakeUpOverFlow);
    
        if((pRTC->mWakeUpOverFlow >= (MAX_RTC_CNT + 1 - RTC_COMPARE_OFFSET_MIN)) ||
    		(pRTC->mWakeUpOverFlow < 5))
        {
        
             TRACE_ERROR2("Rtc WakeUpPeriod Set ERR pRTC->mWakeUpOverFlow = %d",
    		              pRTC->mWakeUpOverFlow);
            while(1);			
        }    
    
        if(pRTC->mWakeUpIrq != NULL)
        {
             err_code = app_timer_stop(pRTC->mWakeUpTimerId);
             APP_ERROR_CHECK(err_code);
       
             err_code = app_timer_start(pRTC->mWakeUpTimerId,
                    pRTC->mWakeUpOverFlow,
                    pRTC);
             APP_ERROR_CHECK(err_code);
         }
    
        return 0;
    }
    
Reply
  • my programer use two APP TIMER

    typedef struct{
    
        SoftWareRtcInterface Interface;
    
        //private:
    
        void (*mWakeUpIrq)(void * p_context);
    
        void (*mSecondIrq)(void * p_context);
    
        void (*mMinuteIrq)(void * p_context);
    
        void (*mHourIrq)(void *p_context);
    
        volatile uint32_t mWakeUpOverFlow;
    
        volatile uint32_t mSecondCount;
    
        volatile uint32_t mSecondtRecord;
    
        volatile uint32_t mPowerUpTime;
    
        //Used to generate one second timing to generate the date and time information
    
        app_timer_id_t    mSecondTimerId;  
    
        // Wake-up timer for system operation. Pedometer when 25MS wake every time.
    
        // Stationary wake every minute
    
        app_timer_id_t    mWakeUpTimerId;
    }SoftWareRtcHal;
    
    
    #define FW_APP_TIMER_MAX_TIMERS    6 
    
    #define FW_APP_TIMER_OP_QUEUE_SIZE 20 // I tried defined as 1 OR 20
    
    
    void lfclk_config(void)
    {
    
        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_CLOCK->EVENTS_LFCLKSTARTED = 0;
    }
    
    void AppTimeInit(void)
    {
    
        APP_TIMER_INIT(APP_TIMER_PRESCALER, FW_APP_TIMER_MAX_TIMERS, 
        FW_APP_TIMER_OP_QUEUE_SIZE, FALSE);
    
    }
    
    void InitSoftWareRtc(SoftWareRtcInterface *interface)
    {
    
        uint32_t err_code;
    
        SoftWareRtcHal *pRtcHal = (SoftWareRtcHal *)interface;    
    
    
        interface->SetWakeUpPeriod = &gRtcSetWakeUpPeriod;
    
        interface->GetSecond32 = &gRtcGetSecond32;
    
        interface->GetPowerUpTime = &gRtcGetPowerUpTime;
    
        interface->SetDate = &gRtcSetDate;
    
        interface->SetTime = &gRtcSetTime;
    
        interface->GetDate = &gRtcGetDate;
    
        interface->GetTime = &gRtcGetTime;
    
        interface->RegisterWakeUpIrq = &gRtcRegisterWakeUpIrq;
    
        interface->RegisterSecondIrq = &gRtcRegisterSecondIrq;
    
        interface->RegisterMinuteIrq = &gRtcRegisterMinuteIrq;
    
        interface->RegisterHourIrq = &gRtcRegisterHourIrq;
    
        interface->StateCheck = &gRtcStateCheck;
    
        //interface->IRQHandle = &gRtcIRQHandle;
    
        interface->RestStart = &gRtcRestStart;
    
        pRtcHal->mSecondtRecord = pRtcHal->mSecondCount;
    
        pRtcHal->mWakeUpIrq = NULL;
    
        pRtcHal->mSecondIrq = NULL;
    
        pRtcHal->mMinuteIrq = NULL;
    
        pRtcHal->mHourIrq = NULL;	
    
        TRACE2("pRtcHal->gRtcSecond = %x", pRtcHal->mSecondCount);
    
        err_code = app_timer_create(&pRtcHal->mSecondTimerId,
                     APP_TIMER_MODE_REPEATED,
                     gRtcAppTimerSecondHandle);
    
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_start(pRtcHal->mSecondTimerId,
                    APP_TIMER_TICKS(1000, APP_TIMER_PRESCALER),
                    pRtcHal);
    
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_create(&pRtcHal->mWakeUpTimerId,
                     APP_TIMER_MODE_REPEATED,
                     gRtcAppTimerWakeUpHandle);
    
        APP_ERROR_CHECK(err_code);
    }
    
    void gRtcAppTimerSecondHandle(void * p_context)
    {
    
        SoftWareRtcHal *pRTC = (SoftWareRtcHal *)p_context;
    
        pRTC->mSecondCount++;
    
        if(pRTC->mSecondIrq != NULL)
        {
            pRTC->mSecondIrq(NULL);
        }
    
        if((pRTC->mMinuteIrq != NULL) &&
            (pRTC->mSecondCount % 60 == 0))
        {
            pRTC->mMinuteIrq(NULL);
        }
    
        if((pRTC->mHourIrq != NULL) &&
            (pRTC->mSecondCount % 3600 == 0))
        {
            pRTC->mHourIrq(NULL);
        }
    
        //TRACE_INFO1("*");
    }
    
    bool gRtcSetWakeUpPeriod(SoftWareRtcInterface *RtcInterface, uint16_t period)
    {
    
        /*************************************
        *    Ftick = 1000mS/period;
        *    Ftick == 32768/(PRESCALER+1)
        *==> PRESCALER + 1 == 32768 / Ftick
        *==>
        *==> PRESCALER == 32768 * period / 1000 -1
        *
        *TICK = 32768 / (127+1); 128分频
        *T = 1/TICK;
        *PROID = T * WakeUpOverFlow = WakeUpOverFlow / TICK;
        *WakeUpOverFlow = PROID * (32768 / 128);
        *30mS => WakeUpOverFlow = 0.030 * (32768/128) = 8
        **************************************/
    
        uint32_t err_code;
    
        SoftWareRtcHal *pRTC;
    
        uint32_t mCurWakeUpOverFlow;
    
        if(RtcInterface == NULL)
            return -1;
    
        pRTC = (SoftWareRtcHal *)RtcInterface;
    
        mCurWakeUpOverFlow = APP_TIMER_TICKS(period, NRF_RTC1->PRESCALER);
    
        if(mCurWakeUpOverFlow == pRTC->mWakeUpOverFlow)
             return 0;
    
        pRTC->mWakeUpOverFlow = mCurWakeUpOverFlow;	
    
        TRACE2("pRTC->mWakeUpOverFlow = %x", pRTC->mWakeUpOverFlow);
    
        if((pRTC->mWakeUpOverFlow >= (MAX_RTC_CNT + 1 - RTC_COMPARE_OFFSET_MIN)) ||
    		(pRTC->mWakeUpOverFlow < 5))
        {
        
             TRACE_ERROR2("Rtc WakeUpPeriod Set ERR pRTC->mWakeUpOverFlow = %d",
    		              pRTC->mWakeUpOverFlow);
            while(1);			
        }    
    
        if(pRTC->mWakeUpIrq != NULL)
        {
             err_code = app_timer_stop(pRTC->mWakeUpTimerId);
             APP_ERROR_CHECK(err_code);
       
             err_code = app_timer_start(pRTC->mWakeUpTimerId,
                    pRTC->mWakeUpOverFlow,
                    pRTC);
             APP_ERROR_CHECK(err_code);
         }
    
        return 0;
    }
    
Children
Related