This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Add Cap touch sample code generate from Sensor Controller Studio into SimpleBLEPeripheral, system will lost response sooner or later

Other Parts Discussed in Thread: CC2540, SYSBIOS, CC2640

I am trying to add Cap touch sample code generate from Sensor Controller Studio into SimpleBLEPeripheral.

Cap touch part works as a scif task.

void scTaskAlertCallback(void) {

  // Clear the ALERT interrupt source
    scifClearAlertIntSource();

    // Transfer the TDC values to the application buffer
    if (scifGetTaskIoStructAvailCount(SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_TASK_ID, SCIF_STRUCT_OUTPUT) == 1) {
        SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_OUTPUT_T* pOutput = (SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_OUTPUT_T*) scifGetTaskStruct(SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_TASK_ID, SCIF_STRUCT_OUTPUT);
        uint16_t* pBuffer = ppTdcValueBuffer[tdcValueBufferHead];
        int n;
        for (n = 0; n < PIN_COUNT; n++) {
            pBuffer[n] = pOutput->pTdcValueRaw[n];
        }
        tdcValueBufferHead = (tdcValueBufferHead + 1) & 0x07;
        scifHandoffTaskStruct(SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_TASK_ID, SCIF_STRUCT_OUTPUT);
    }

       if (tdcValueBufferHead != tdcValueBufferTail) {
            uint16_t* pBuffer = ppTdcValueBuffer[tdcValueBufferTail];
            int pos = 0;
            int n, i;
            for (n = 0; n < PIN_COUNT; n++) {
                uint32_t value = pBuffer[n];
               
            tdcValueBufferTail = (tdcValueBufferTail + 1) & 0x07;
            }
        }
   
   
    // Acknowledge the ALERT event
    scifAckAlertEvents();
  
} // scTaskAlertCallback

void taskFxn(UArg a0, UArg a1) {

    // Initialize the Sensor Controller
    scifOsalInit();
    scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback);
    scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);
    scifInit(&scifDriverSetup);
    //scifStartRtcTicksNow(0x00010000 / 32);
    scifStartRtcTicksNow(0x00010000 / 14);
    


    IntMasterEnable();
    AONRTCEnable();

    scifStartTasksNbl(BV(SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_TASK_ID));

 
    // Main loop
    while (1) {

//        // Wait for an ALERT callback
       Semaphore_pend(Semaphore_handle(&semScTaskAlert), BIOS_WAIT_FOREVER);
       
    }

} // taskFxn

Then connect SimpleBLEPeripheral with LightBlue running on iOS. Sooner or later connection will lost, and in this case, SimpleBLEPeripheral will not be able to connect or scan by LightBlue. System seems hang in somewhere. Only repower/ reset can recover the system.

Is there any low level conflict need to be take care? 

  

  • Barbara,

    Does the problem go away when you remove the code between scifClearAlertIntSource and scifAckAlertEvents?

    Regards,
    Svend

  • No. The problem still exists.

    So it seems from something low level in scif.c...

  • Have you done any other modifications to simpleBLEPeripheral other than just adding the sensor controller task?
  • Hi Eirik,

    No, I did not modify anything other than just adding the sensor controller task.

    Best Regards,

    Barbara Wu

  • - Where is the program stuck when you see the issue?
    - Can you follow Chapter 9 of the BLE SW Developers user guide (SWRU393) to see if everything is OK in your program and provide us the details of why the chip crashed?
    - Does the issue go away if you never start up the Sensor Controller task?

    Regards,
    Svend
  • Hi Svend,

    -It is hard to catch in IAR where the program stuck at. When system crashed, the IAR lost debugger connection too.
    -I will try to follow Chapter 9 as you suggest.
    - The issue is gone if scif_createtask is never called.

    I did not modify SimpleBLEPeripheral and use original Cap touch sample code generated from Sensor Controller Studio. I think this issue can be simplily reproduced..

    Best Regards,
    Barbara Wu
  • Barbara,

    I am not able to reproduce the issue when connecting with BTool + CC2540 dongle using the following code:

    #include <ti/sysbios/knl/Semaphore.h>
    #include <scif.h>
    
    Task_Struct scTask;
    uint8_t     scTaskStack[512];
    
    Semaphore_Struct scSem;
    Semaphore_Handle hScSem;
    
    
    void scCtrlReadyCallback(void) {
    
    }
    
    void scTaskAlertCallback(void) {
    
      scifClearAlertIntSource();
    
      if( scifGetTaskIoStructAvailCount(SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_TASK_ID, SCIF_STRUCT_OUTPUT) == 1) {
        scifHandoffTaskStruct(SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_TASK_ID, SCIF_STRUCT_OUTPUT);
      }
    
      scifAckAlertEvents();
    
    }
    
    
    void scTaskFxn(UArg a0, UArg a1) {
    
       // Initialize the Sensor Controller
        scifOsalInit();
        scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback);
        scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);
        scifInit(&scifDriverSetup);
    
        scifStartRtcTicksNow(0x00010000 / 14);
    
    
    
        IntMasterEnable(); //Not needed, done by TI RTOS
        AONRTCEnable(); // Not needed, done by TI RTOS
    
        scifStartTasksNbl(BV(SCIF_CAPACITIVE_TOUCH_DATA_LOGGER_TASK_ID));
    
    
        // Main loop
        while (1) {
    
          Semaphore_pend(hScSem, BIOS_WAIT_FOREVER);
    
        }
    
    }
    
    void sc_createTask() {
    
      Task_Params params;
      Task_Params_init(&params);
      params.priority   = 1;
      params.stack      = scTaskStack;
      params.stackSize  = sizeof(scTaskStack);
    
      Task_construct(&scTask, scTaskFxn, &params, NULL);
    
      Semaphore_Params sp;
      Semaphore_Params_init(&sp);
      sp.mode = Semaphore_Mode_BINARY;
    
      Semaphore_construct(&scSem, 0, &sp);
      hScSem = Semaphore_handle(&scSem);
    }
    

    What do you do to trigger the issue?

    Svend

  • Hello Barbara,

    Remove the following two lines from your code:

        IntMasterEnable();
        AONRTCEnable();

    You have to much processing in your HWI (scTaskAlertCallback()). You should instead do the processing in your task by simply posting a semaphore in your HWI. Look at the analog light sensor TI-RTOS example:

    // Wake up the OS task
    Semaphore_post(Semaphore_handle(&semScTaskAlert));

    Make sure to keep the peripheral sharing calls in the sensor controller code so that you acquire and release the peripheral correctly.

  • Hi Eirik,

    Thanks for pointing out the problem in the code.

    I have removed IntMasterEnable(); and AONRTCEnable(); and used Semaphore_post.

    But the issue is still existing.

    Best Regards,

    Barbara Wu

  • Have you tried Svends version?

    Try to reduce the number of pins you measure on (i.e. reduce PIN_COUNT). This will reduce the time you use the TDC.
    // For each pin ...
    for (U16 n = 0; n < PIN_COUNT; n++) {
  • Hi Eirik,

    I have already moved to TI RTOS SimpleLink 2.13.00.06 and also use the latest SCS 1.0.1.26452 to generate code.

    I have tried to just measure Pin=0 in execution code.. But issue is still existing...

    Best Regards,

    Barbara Wu 

  • Did you try the same code as Svend?
  • Hi Eirik,

    I have tried Svend code. It works with original SCS cap touch sample code.

    But if modify cap touch sample code in SCS from :

    // Schedule the next execution

    fwScheduleTask(10);

    to

    // Schedule the next execution

    fwScheduleTask(5); or fwScheduleTask(1);

    Crash issue will shows.

    Best Regards,

    Barbara

  • Hello Barbara,
    Can you try to disable power saving in simpleBLEPeripheral and verify if the application will "crash"?
  • Hi Eirik,

    Disable power saving seems helpful.

    Why power saving may cause "system crash"? How to avoid "crash" when enable power saving? 

    Best Regards,

    Barbara Wu 

  • Hello Barbara, Eirik,

     I have same problem and none of the answers have worked with enable POWER_SAVING.

    Has this problem been solved?

    Thanks,

    Owen

  • Hi all,

    We found an issue today regarding this which might be the reason for the issue.

    What happens is that the TDC is also used for calibrating the RCOSC_HF whenever the HF XTAL is enabled.  There is a state machine in the power driver which got a bit confused since the TDC_DONE interrupt was still enabled after the calibration was done so when the TDC is used for CapSense as well, this caused issues.

    I have attached a file for TI RTOS 2.13.00.06 (C:\ti\tirtos_simplelink_2_13_00_06\products\bios_6_42_00_08\packages\ti\sysbios\family\arm\cc26xx\Power_calibrateRCOSC.c) that can should replace the old one in there.

    After doing this, clean the workspace and re-build everything. For IAR, delete the CC26xx\IAR\Config\src and CC26xx\IAR\Application\CC2640\configPkg folders before re-building.

    Note: This is not a verified fix so we would like your feedback on whether this resolves the issue you are seeing.

    /*
     * Copyright (c) 2014-2015, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQueueNTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    /*
     *  ======== Power_calibrateRCOSC.c ========
     */
    
    #include <xdc/std.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/family/arm/cc26xx/Power.h>
    #include <ti/sysbios/family/arm/cc26xx/PowerCC2650.h>
    
    #include <driverlib/ddi.h>
    #include <driverlib/ioc.h>
    #include <driverlib/osc.h>
    #include <driverlib/gpio.h>
    #include <driverlib/sys_ctrl.h>
    #include <driverlib/aux_wuc.h>
    #include <inc/hw_aux_evctl.h>
    #include <inc/hw_aux_smph.h>
    #include <inc/hw_aux_wuc.h>
    #include <inc/hw_aux_tdc.h>
    #include <inc/hw_ddi_0_osc.h>
    #include <inc/hw_ddi.h>
    #include <inc/hw_ccfg.h>
    
    #define AUX_TDC_SEMAPHORE_NUMBER        1  /* semaphore 1 protects TDC */
    #define NUM_RCOSC_LF_PERIODS_TO_MEASURE 32 /* x RCOSC_LF periods vs XOSC_HF */
    #define NUM_RCOSC_HF_PERIODS_TO_MEASURE 1  /* x RCOSC_HF periods vs XOSC_HF */
    #define ACLK_REF_SRC_RCOSC_HF           0  /* Use RCOSC_HF for ACLK REF */
    #define ACLK_REF_SRC_RCOSC_LF           2  /* Use RCOSC_LF for ACLK REF */
    
    #define SCLK_LF_OPTION_RCOSC_LF         3  /* defined in cc26_ccfg.xls */
    
    #define DDI_0_OSC_O_CTL1_LOCAL                   0x00000004     /* offset */
    #define DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_M 0x007C0000     /* mask */
    #define DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_S    18          /* shift */
    #define DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_EN_LOCAL_M 0x00020000  /* mask */
    #define DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_EN_LOCAL_S 17          /* shift */
    
    /* AUX ISR states */
    #define WAIT_SMPH       0   /* just took SMPH, start RCOSC_LF */
    #define CAL_RCOSC_LF    1   /* just finished RCOSC_LF, start first RCOSC_HF */
    #define CAL_RCOSC_HF1   2   /* just finished 1st RCOSC_HF, start 2nd */
    #define CAL_RCOSC_HF2   3   /* just finished 2nd RCOSC_HF, decide best */
    
    /* macros */
    #define MIN(a,b) (((a)<(b))?(a):(b))
    #define MAX(a,b) (((a)>(b))?(a):(b))
    
    /* forward declarations */
    static Int abs(Int i);
    static Void calibrateRcoscHf1(Int32 tdcResult);
    static Void calibrateRcoscHf2(Int32 tdcResult);
    static Void cleanupAfterMeasurements(Void);
    static Bool getTdcSemaphore(Void);
    static Int32 scaleRndInf(Int32 x);
    static Void tdcInit();
    static Void tdcPerformRcOscMeasurement(UInt32 refClkSrc,
        UInt32 numEdgesToCount);
    static Void updateSubSecInc(UInt32 tdcResult);
    
    /* static globals */
    static UInt32 calibrateStep;
    static Bool doLF = FALSE;
    static Bool firstLF = TRUE;
    static Int32 nDeltaFreqCurr;
    static Int32 nCtrimCurr;
    static Int32 nCtrimFractCurr;
    static Int32 nCtrimNew;
    static Int32 nCtrimFractNew;
    
    #define INSTRUMENT 0
    
    #if INSTRUMENT
    volatile UInt gotSEM = 0;
    volatile UInt calLF = 0;
    volatile UInt calHF1 = 0;
    volatile UInt calHF2 = 0;
    UInt tdcResult_LF = 0;
    UInt tdcResult_HF1 = 0;
    UInt tdcResult_HF2 = 0;
    UInt numISRs = 0;
    #endif
    
    /*
     *  ======== calibrateRCOSCs ========
     *  Initiate calibration of RCOSC_LF and RCOSCHF
     */
    Bool Power_initiateCalibration()
    {
        Bool status;
        Bool gotSem;
        UInt32 ccfgLfClkSrc;
    
        /* set contraints to prohibit powering down during calibration sequence */
        Power_setConstraint(Power_SB_DISALLOW);
        Power_setConstraint(Power_IDLE_PD_DISALLOW);
    
        /* set dependency to keep XOSC_HF active during calibration sequence */
        Power_setDependency(XOSC_HF);
    
        /* read the LF clock source from CCFG */
        ccfgLfClkSrc = (HWREG(CCFG_BASE + CCFG_O_MODE_CONF) &
            CCFG_MODE_CONF_SCLK_LF_OPTION_M) >> CCFG_MODE_CONF_SCLK_LF_OPTION_S;
    
        /* check to see if should do RCOSC_LF calibration,  */
        if (ccfgLfClkSrc == SCLK_LF_OPTION_RCOSC_LF) {
            doLF = TRUE;
        }
        else {
            doLF = FALSE;
        }
    
        /* initiate acquisition of semaphore protecting TDC */
        gotSem = getTdcSemaphore();
    
        /* if didn't acquire semaphore, must wait for autotake ISR */
        if (gotSem == FALSE) {
            calibrateStep = WAIT_SMPH;
            status = FALSE;  /* FALSE: don't do anything else until acquire SMPH */
        }
    
        /* else, semaphore acquired, OK to proceed with first measurement */
        else {
    #if INSTRUMENT
            gotSEM = 1;
    #endif
            status = TRUE;   /* TRUE: OK to start first measurement */
        }
    
        return (status);
    }
    
    /*
     *  ======== startFirstMeasurment ========
     *  Start the first RCOSC measurement
     */
    Void Power_startFirstMeasurement()
    {
        /* setup TDC */
        tdcInit();
    
        /* if LF clock is from RCOSC_LF then do compensation */
        if (doLF == TRUE) {
            /* clear UPD_REQ, new sub-second increment is NOT available */
            HWREG(AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINCCTL) = 0;
    
            /* initiate measurement of RCOSC_LF */
            tdcPerformRcOscMeasurement(ACLK_REF_SRC_RCOSC_LF,
                NUM_RCOSC_LF_PERIODS_TO_MEASURE);
    
            /* next state is RCOSC_LF measurement */
            calibrateStep = CAL_RCOSC_LF;
    
        }
    
        /* else, if LF clock is from XOSC_LF, start XOSC_HF calibration */
        else {
            /* initiate first measurement of RCOSC_HF */
            tdcPerformRcOscMeasurement(ACLK_REF_SRC_RCOSC_HF,
                NUM_RCOSC_HF_PERIODS_TO_MEASURE);
    
            /* next state is RCOSC_HF meas. #1 */
            calibrateStep = CAL_RCOSC_HF1;
        }
    
    }
    
    /*
     *  ======== Power_auxISR ========
     *  ISR for the AUX combo interrupt event.  Implements state machine to
     *  step through the RCOSC calibration steps.
     */
    Void ti_sysbios_family_arm_cc26xx_Power_auxISR(UArg arg)
    {
        UInt32 tdcResult;
    
    #if INSTRUMENT
        numISRs++;
    #endif
    
        /* read the interrupt source */
        UInt32 auxEvent = HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_EVTOMCUFLAGS);
    
        /* disable interrupts (clearing them does not clear the source (bug)) */
        HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_COMBEVTOMCUMASK) &= ~auxEvent;
    
        /* clear the interrupt source */
        HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_EVTOMCUFLAGSCLR) = auxEvent;
    
        /* ****** state = WAIT_SMPH: arrive here if just took the SMPH ****** */
        if (calibrateStep == WAIT_SMPH) {
    #if INSTRUMENT
            gotSEM = 1;
    #endif
            Power_startFirstMeasurement();
        }
    
        /* **** state = CAL_RCOSC_LF: here when just finished LF counting **** */
        else if (calibrateStep == CAL_RCOSC_LF) {
            calibrateStep = CAL_RCOSC_HF1;    /* next state is RCOSC_HF meas. #1 */
            tdcResult = HWREG(AUX_TDCIF_BASE + AUX_TDC_O_RESULT);
    
    #if INSTRUMENT
            tdcResult_LF = tdcResult;
    #endif
            /* update the RTC SUBSECINC register based on LF measurement result */
            updateSubSecInc(tdcResult);
    
    #if INSTRUMENT
            calLF = 1;
    #endif
            /* initiate first measurement of RCOSC_HF */
            tdcPerformRcOscMeasurement(ACLK_REF_SRC_RCOSC_HF,
                NUM_RCOSC_HF_PERIODS_TO_MEASURE);
        }
    
        /* ****** state = CAL_RCOSC_HF1: here when just finished 1st RCOSC_HF */
        else if (calibrateStep == CAL_RCOSC_HF1) {
            tdcResult = HWREG(AUX_TDCIF_BASE + AUX_TDC_O_RESULT);
    
    #if INSTRUMENT
            tdcResult_HF1 = tdcResult;
    #endif
            if (tdcResult == 1536)
            {
                /* settings perfect, nothing more to do, calibration is done.*/
                calibrateStep = WAIT_SMPH;
                cleanupAfterMeasurements();
            }
            else
            {
                /* next state is RCOSC_HF meas. #2 */
                calibrateStep = CAL_RCOSC_HF2;
                /* use first HF measurement to setup new trim values */
                calibrateRcoscHf1(tdcResult);
                /* initiate second measurement of RCOSC_HF */
                tdcPerformRcOscMeasurement(ACLK_REF_SRC_RCOSC_HF,
                                           NUM_RCOSC_HF_PERIODS_TO_MEASURE);
            }
    
    #if INSTRUMENT
            calHF1 = 1;
    #endif
    
        }
    
        /* ****** state = just finished second RCOSC_HF measurement ****** */
        else if (calibrateStep == CAL_RCOSC_HF2) {
            calibrateStep = WAIT_SMPH;  /* restart state will be for re-take SMPH */
            tdcResult = HWREG(AUX_TDCIF_BASE + AUX_TDC_O_RESULT);
    
    #if INSTRUMENT
            tdcResult_HF2 = tdcResult;
    #endif
            /* look for improvement on #2, else revert to previous trim values */
            calibrateRcoscHf2(tdcResult);
    
            /* done with this cal sequence, cleanup */
            cleanupAfterMeasurements();
    
        }
    }
    
    /*
     *  ======== getTdcSemaphore ========
     *  Get TDC semaphore (number 1)
     */
    static Bool getTdcSemaphore()
    {
        UInt own;
    
        /* try to acquire SMPH */
        own = HWREG(AUX_SMPH_BASE + AUX_SMPH_O_SMPH1);
    
        /* if acquired SMPH: done */
        if (own != 0) {
            return (TRUE);
        }
    
        /*
         * else, did not acquire the semaphore, enable SMPH_AUTOTAKE_DONE event
         * (don't OR, write entire register, no other interrupts can be enabled!)
         */
        HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_COMBEVTOMCUMASK) =
            AUX_EVCTL_COMBEVTOMCUMASK_SMPH_AUTOTAKE_DONE;
    
        /* start AUTOTAKE of semaphore for TDC access */
        HWREG(AUX_SMPH_BASE + AUX_SMPH_O_AUTOTAKE) = AUX_TDC_SEMAPHORE_NUMBER;
    
        return (FALSE);
    }
    
    /*
     *  ======== tdcInit ========
     *  Initialize the TDC
     */
    static Void tdcInit()
    {
        /* Turn on clock to TDC module */
        AUXWUCClockEnable(AUX_WUC_TDCIF_CLOCK);
    
        /* Set saturation config to 2^24 */
        HWREG(AUX_TDCIF_BASE + AUX_TDC_O_SATCFG) = AUX_TDC_SATCFG_LIMIT_ROVF;
    
        /* Set start and stop trigger sources and polarity */
        HWREG(AUX_TDCIF_BASE + AUX_TDC_O_TRIGSRC) =
            (AUX_TDC_TRIGSRC_STOP_SRC_ACLK_REF | AUX_TDC_TRIGSRC_STOP_POL_HIGH) |
            (AUX_TDC_TRIGSRC_START_SRC_ACLK_REF | AUX_TDC_TRIGSRC_START_POL_HIGH);
    
        /* Set TDC_SRC clock to be XOSC_HF/2 = 24 MHz */
        DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
                               DDI_0_OSC_CTL0_ACLK_TDC_SRC_SEL_M,
                               DDI_0_OSC_CTL0_ACLK_TDC_SRC_SEL_S,
                               2);
    
        /* Set AUX_WUC:TDCCLKCTL.REQ... */
        HWREG(AUX_WUC_BASE + AUX_WUC_O_TDCCLKCTL) = AUX_WUC_TDCCLKCTL_REQ;
    
        /* Wait for AUX_WUC:TDCCLKCTL.ACK to be set... */
        while(!(HWREG(AUX_WUC_BASE + AUX_WUC_O_TDCCLKCTL) & AUX_WUC_TDCCLKCTL_ACK));
    
        /* Enable trig count */
        HWREG(AUX_TDCIF_BASE + AUX_TDC_O_TRIGCNTCFG) = AUX_TDC_TRIGCNTCFG_EN;
    }
    
    /*
     *  ======== tdcPerformRcOscMeasurement ========
     *  Initiate counting of clock edges versus XOSC_HF clock source
     *
     *  refClkSrc: The reference clock source:
     *      0 = RCOSC_HF (divided by 1536) = 31.25 kHz
     *      2 = RCOSC_LF
     *
     *  numEdgesToCount: Number of edges to count
     *
     *  Returns: The 32-bit TDC result count value
     *
     */
    static Void tdcPerformRcOscMeasurement(UInt32 refClkSrc, UInt32 numEdgesToCount)
    {
        /* Abort TDC */
        HWREG(AUX_TDCIF_BASE + AUX_TDC_O_CTL) = AUX_TDC_CTL_CMD_ABORT;
    
        /* Clear AUX_WUC:REFCLKCTL.REQ... */
        HWREG(AUX_WUC_BASE + AUX_WUC_O_REFCLKCTL) = 0;
    
        /* ...and wait for AUX_WUC:REFCLKCTL.ACK to be cleared */
        while(HWREG(AUX_WUC_BASE + AUX_WUC_O_REFCLKCTL) & AUX_WUC_REFCLKCTL_ACK);
    
        /* Set the ACLK reference clock */
        DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
                               DDI_0_OSC_CTL0_ACLK_REF_SRC_SEL_M,
                               DDI_0_OSC_CTL0_ACLK_REF_SRC_SEL_S,
                               refClkSrc);
    
        /* ...and AUX_WUC:REFCLKCTL.REQ */
        HWREG(AUX_WUC_BASE + AUX_WUC_O_REFCLKCTL) = AUX_WUC_REFCLKCTL_REQ;
    
        /* Wait for AUX_WUC:REFCLKCTL.ACK to be set... */
        while(!(HWREG(AUX_WUC_BASE + AUX_WUC_O_REFCLKCTL) & AUX_WUC_REFCLKCTL_ACK));
    
        /* Set number of periods of ACLK to count */
        HWREG(AUX_TDCIF_BASE + AUX_TDC_O_TRIGCNTLOAD) = numEdgesToCount;
    
        /* Reset/clear result of TDC */
        HWREG(AUX_TDCIF_BASE + AUX_TDC_O_CTL) = AUX_TDC_CTL_CMD_CLR_RESULT;
    
        /* Clear possible pending interrupt source */
        HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_EVTOMCUFLAGSCLR) =
            AUX_EVCTL_EVTOMCUFLAGSCLR_TDC_DONE;
    
        /* Enable TDC done interrupt as part of AUX_COMBINED interrupt */
        HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_COMBEVTOMCUMASK) =
            AUX_EVCTL_COMBEVTOMCUMASK_TDC_DONE;
    
        /* Run TDC (start synchronously) */
        HWREG(AUX_TDCIF_BASE + AUX_TDC_O_CTL) = AUX_TDC_CTL_CMD_RUN_SYNC_START;
    }
    
    /*
     *  ======== updateSubSecInc ========
     *  Update the SUBSECINC register based on measured RCOSC_LF frequency
     */
    static Void updateSubSecInc(UInt32 tdcResult)
    {
        UInt32 newSubSecInc;
        UInt32 oldSubSecInc;
        UInt32 subSecInc;
    
        /*
         * Calculate the new SUBSECINC
         * Here's the formula: AON_RTC:SUBSECINC = (45813 * NR) / 256
         */
        newSubSecInc = (45813 * tdcResult) / 256;
    
        /* Apply filter, but not for first calibration */
        if (firstLF) {
            /* Don't apply filter first time, to converge faster */
            subSecInc = newSubSecInc;
            /* No longer first measurement */
            firstLF = FALSE;
        }
        else {
            /* Read old SUBSECINC value */
            oldSubSecInc = HWREG(AON_RTC_BASE + AON_RTC_O_SUBSECINC) & 0x00FFFFFF;
            /* Apply filter, 0.5 times old value, 0.5 times new value */
            subSecInc = (oldSubSecInc * 1 + newSubSecInc * 1) / 2;
        }
    
        /* Update SUBSECINC values */
        HWREG(AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINC0) = subSecInc;
        HWREG(AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINC1) = subSecInc >> 16;
    
        /* update to use new values */
        HWREG(AUX_WUC_BASE + AUX_WUC_O_RTCSUBSECINCCTL) =
            AUX_WUC_RTCSUBSECINCCTL_UPD_REQ;
    }
    
    /*
     *  ======== calibrateRcoscHf1 ========
     *  Calibrate RCOSC_HF agains XOSC_HF: compute and setup new trims
     */
    static Void calibrateRcoscHf1(Int32 tdcResult)
    {
        /* read current trims */
        nCtrimCurr = (DDI32RegRead(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_RCOSCHFCTL) &
            DDI_0_OSC_RCOSCHFCTL_RCOSCHF_CTRIM_M) >>
            DDI_0_OSC_RCOSCHFCTL_RCOSCHF_CTRIM_S;
    
        nCtrimFractCurr = (DDI32RegRead(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL1_LOCAL)
            & DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_M) >>
            DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_S;
    
        /*
         * Find RCOSC_HF-XOSC_HF frequency offset with current trim settings
         *   Positive value => RCOSC_HF runs slow, CTRIM(FRACT) should be increased
         *   Negative value => RCOSC_HF runs fast, CTRIM(FRACT) should be decreased
         * Resolution: 31.25 kHz; CTRIMFRACT resolution ~30 kHz
         */
        nDeltaFreqCurr = (Int32) tdcResult - 1536;
    
        /*
         * Calculate change to CTRIMFRACT with safe assumptions of gain,
         * apply delta to current CTRIMFRACT and convert to valid CTRIM/CTRIMFRACT
         */
        nCtrimFractNew = nCtrimFractCurr + scaleRndInf(nDeltaFreqCurr);
        nCtrimNew = nCtrimCurr;
    
        /* One step of CTRIM is about 500 kHz, so limit to one CTRIM step */
        if (nCtrimFractNew < 2)
        {
            /* Below sweet spot of current CTRIM => decrease CTRIM */
            nCtrimNew = MAX(-0x40, nCtrimNew-1);
            nCtrimFractNew = MAX(0, nCtrimFractNew+16);
        }
        else if (nCtrimFractNew > 29)
        {
            /* Above sweet spot of current CTRIM => increase CTRIM */
            nCtrimNew = MIN(0x3F, nCtrimNew+1);
            nCtrimFractNew = MIN(31, nCtrimFractNew-16);
        }
        else
        {
            /* We're within sweet spot of current CTRIM => no change */
        }
    
        /* Find RCOSC_HF vs XOSC_HF frequency offset with new trim settings */
        DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_RCOSCHFCTL,
                               DDI_0_OSC_RCOSCHFCTL_RCOSCHF_CTRIM_M,
                               DDI_0_OSC_RCOSCHFCTL_RCOSCHF_CTRIM_S,
                               nCtrimNew);
    
        /* Enable RCOSCHFCTRIMFRACT_EN */
        DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL1_LOCAL,
                               DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_EN_LOCAL_M,
                               DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_EN_LOCAL_S,
                               1);
    
        /* Modify CTRIM_FRACT */
        DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL1_LOCAL,
                               DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_M,
                               DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_S,
                               nCtrimFractNew);
    }
    
    /*
     *  ======== calibrateRcoscHf2 ========
     *  Calibrate RCOSC_HF agains XOSC_HF: determine better result, set new trims
     */
    static Void calibrateRcoscHf2(Int32 tdcResult)
    {
        Int32 nDeltaFreqNew;
    
        /* Calculate new delta freq */
        nDeltaFreqNew = (Int32) tdcResult - 1536;
    
        /* Determine whether the new settings are better or worse */
        if (abs(nDeltaFreqNew) <= abs(nDeltaFreqCurr))
        {
            /* new settings are better or same, keep them in registers */
        }
        else
        {
            /*
             * Current setting were better, check whether we are getting fooled
             * by non-monotonicity in CTRIM
             */
            nCtrimFractNew += scaleRndInf(nDeltaFreqNew);
            if (nCtrimCurr != nCtrimNew && abs(nCtrimFractCurr - 16) >
                abs(nCtrimFractNew - 16)) {
    
                /*
                 * New settings updated based on frequency measurements are more
                 * centered in its CTRIM than the current settings in its
                 * CTRIM -> use updated new settings
                 */
                DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL1_LOCAL,
                               DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_M,
                               DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_S,
                               nCtrimFractNew);
            }
            else {
                /* New settings updated based on frequency measurements are less
                 * centered in its CTRIM than the current settings in its CTRIM,
                 * or they are both in the same CTRIM -> revert to old settings
                 */
                DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_RCOSCHFCTL,
                               DDI_0_OSC_RCOSCHFCTL_RCOSCHF_CTRIM_M,
                               DDI_0_OSC_RCOSCHFCTL_RCOSCHF_CTRIM_S,
                               nCtrimCurr);
                DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL1_LOCAL,
                               DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_M,
                               DDI_0_OSC_CTL1_RCOSCHFCTRIMFRACT_LOCAL_S,
                               nCtrimFractCurr);
            }
        }
    }
    
    /*
     *  ======== abs ========
     *  Absolute value
     */
    static Int abs(Int i)
    {
        /* compute absolute value of int argument */
        return (i < 0 ? -i : i);
    }
    
    /*
     *  ======== scaleRndInf ========
     */
    static Int32 scaleRndInf(Int32 x)
    {
        return (2*x + ((x<0) ? -2 : 2))/3;
    }
    
    /*
     *  ======== cleanupAfterMeasurements ========
     */
    static Void cleanupAfterMeasurements(Void)
    {
        /* disable TDC counter clock source */
        HWREG(AUX_WUC_BASE + AUX_WUC_O_TDCCLKCTL) = 0;
    
        /* wait for AUX_WUC:TDCCLKCTL.ACK to be set... */
        while ((HWREG(AUX_WUC_BASE + AUX_WUC_O_TDCCLKCTL) &
            AUX_WUC_TDCCLKCTL_ACK));
    
        /* release the TDC clock request */
        HWREG(AUX_WUC_BASE + AUX_WUC_O_TDCCLKCTL) = 0;
    
        /* relese the TDC reference clock request */
        HWREG(AUX_WUC_BASE + AUX_WUC_O_REFCLKCTL) = 0;
    
    	/* Disable interrupts going to the CPU */
    	HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_COMBEVTOMCUMASK) = 0;
    	
        /* release AUX semaphore */
        HWREG(AUX_SMPH_BASE + AUX_SMPH_O_SMPH1) = 1;
    
        /* release the power down constraints and XOSC_HF dependency */
        Power_releaseDependency(XOSC_HF);
        Power_releaseConstraint(Power_IDLE_PD_DISALLOW);
        Power_releaseConstraint(Power_SB_DISALLOW);
    
    #if INSTRUMENT
            calHF2 = 1;
    #endif
    }
    

    Regards,

    Svend

  • Hi Svend,

    Thank you very much for your reply. Your solution works for me. I think you've got the root cause.
    Thanks for help:)

    Best Regards,
    Barbara Wu
  • Hi Svend,

    The issue still exists after according to yours method operation.

    Have I missed anything ?

    Attached is the my source code.

    SimpleBLEPeripheral_cap_touch_data_logger.rar

    Thanks for your help.

    Best Regards,

    Owen

  • Hello Owen,

    It might be that your issue is a different one since you have integrated this into the SBP task.
    Did you delete the folders described in the previous post?

    Can you try to increase the stack size (SBP_TASK_STACK_SIZE) with for example 200 bytes and see if your issue persists?

    Thanks,
    Svend
  • Hi Svend,

    I found this issues is related to connection interval.

    When the applications want to establish a connection at a faster Connection Interval(<50ms), the peripheral will disconnect and crash in half an hour.

    Thanks,

    Owen

  • Hi Svend,

    I add a new task to handle the cap touch functionality, but the issue is still existing.

    Application.rar

    11:08:00.321 > Characteristic Discovery done [0.280] sec
    11:08:05.677 > GAP Link Param Update: 0 0 16 0 1000
    11:08:05.677 > Connection parameters updated
    11:08:18.170 > ReadCharValue[FFF1]
    11:08:18.220 > ReadResp[FFF1]: status=0 n=1, 01
    11:24:06.233 > GAP Link Terminated: status=0 h=0 reason=0x08
    11:24:06.233 > SimpleBLEPeripheral disconnected

    Thanks for your help.

    Best Regards,

    Owen

  • Hi Svend,

    I have followed the 9.8 Deciphering CPU Exceptions, but the issue does not occur.

    Thanks for your help.

    Best Regards,

    Owen

    .

  • Hello Owen,

    We are looking into this issue but have not found the reason for the problem yet.

    Regards,
    Svend