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.

Timers not working in CC2541_OAD_IMG_A

I've followed the guide (http://processors.wiki.ti.com/images/8/82/OAD_for_CC254x.pdf) to setup my project to compile into an OAD boot image. This causes a problem where OSAL timer events are not being called.  The OAD profile and a few others like battery level are working correctly, but the event manager never receives timer events. I think the BIM isn't successfully translating timer ISRs to the image location, or some problem in my OAD_IMAGE_A configuration.

Some things I've tried so far:

Verifying that the HAL_TIMER=TRUE precompiler macro is there.

Using different HAL Timers as the OSAL timer. (changing #define OSAL_TIMER  HAL_TIMER_3)

Putting the initial osal_start_timerEx function call in different sections of the code.


 

Here are some relevant code snipets:

define VELOCOMPUTER_READ_PERIOD      75
//75ms event period
#define VELOCOMPUTER_READ_EVT                    4
// Periodic timer event code. Does not overlap with other event codes.


osal_start_timerEx( velocomputerapp_TaskID, VELOCOMPUTER_READ_EVT, VELOCOMPUTER_READ_PERIOD );
//Within a BLE profile changed callback. Begins the timer when host sends command. I've tried moving this line to other locations like the startup event.


VelocompApp_ProcessEvent( uint8 task_id, uint16 events ){
.......
  if ( events & VELOCOMPUTER_READ_EVT){
.......
   osal_start_timerEx( velocomputerapp_TaskID, VELOCOMPUTER_READ_EVT, VELOCOMPUTER_READ_PERIOD );
}

// Restart the timer when timer event occurs.

  • Hello,

    We will look into this. Does your code work when not compiled for OAD? Also, make sure events are unique bit mapped.

    #define SBP_START_DEVICE_EVT 0x0001
    #define SBP_PERIODIC_EVT 0x0002
    #define SBP_ADV_IN_CONNECTION_EVT 0x0004

    BR,

    -Greg

  • Thank you for looking at this Greg. The code works properly when not compiled for OAD. The events are uniquely bit mapped.

    #define VELOCOMP_START_DEVICE_EVT                               1    
    #define VELOCOMPUTER_STOP_EVT                                       2   
    #define VELOCOMPUTER_READ_EVT                                       4    
    #define ADV_IN_CONNECTION_EVT                                          8   
    #define VELOCOMPUTER_PERIPHERIAL_ERROR_EVT        16    
    #define VELO_CALIBRATE_EVENT                                           32   

     

    VELOCOMPUTER_READ_EVT  is the one that should be called periodically by timers.

  • Hello.  I tested this using our SImpleBLEPeripheral-ImageA configuration and I do not see this issue.  I have it set so that an LCD counter is incremented every time the timer event triggers.  This seems to be working fine with the default period value of 5000 and also your value of 75.  I would double check your event values as suggested by Greg above.

  • Other things to try

    - Set breakpoint in OSAL timer code to see if timer is added.

    - Make sure other events do not clear timer event bit (maybe swap event No. with another)

    - Set start event on timer, and see if that gets hit.

    - Disable power saving. Is the rest of the code still running,  and are you able to stay in connection or advertise?

  • Thank you for the suggestions Greg. I've confirmed the timer event is added. I've tried changing the timer event bit and this has no effect. Disabling power saving improved the problem to some extent. With power disabled the timer runs, however the host is not receiving the BLE profile messages. The link layer is working correctly from what I can see, the host is successfully connecting and noticing when the device disconnects. The device is also receiving messages from the host, the communication problem is only in one direction. Disabling the power saving is not an acceptable solution for the timer problem. Battery efficiency is a priority on our product.

     

    This is the code that is called by the timer event. It should be sending sensor information back to the host through our BLE profile. Is it possible for the BIM to cause problems with certain profiles that operate normally outside of it? I've compared our profile to ones that came with the 1.3 stack and not found any glaring differences.

     

    uint16 veloConnHandle;
    #define TIME_ANG_ATTR                 2
    #define TIME_ANG_ATTR_LENGTH 16//10  

     

    timeAng[0] = (int)(angToSend & 0xFFFF);   
    timeAng[1] = GetSleepTime();
     timeAng[2] = fitPoint;
    timeAng[3] = ((keyPressCount << 8) & 0xFF00) | (0x0079 & 0x00FF);
    timeAng[4] = time;//time elapsed between magnetometer readings
    timeAng[5] = accelo.x/NumberOfAccelReadings;
    timeAng[6] = accelo.y/NumberOfAccelReadings;
    timeAng[7] = accelo.z/NumberOfAccelReadings;

     Angle_SetParameter(TIME_ANG_ATTR, TIME_ANG_ATTR_LENGTH, timeAng, veloConnHandle);

     

     

     

    bStatus_t Angle_SetParameter( uint8 param, uint8 len, void* value, uint16 vConnHandle )
    {
    bStatus_t ret = SUCCESS;
    switch ( param )
    {
    case AGNLE_ENABLER:
    if ( len == sizeof ( uint8 ) )
    {
    angleEnabled = *((uint8*)value);

    }
    else
    {
    ret = bleInvalidRange;
    }
    break;

    case ANGLE_ATTR:
    if ( len == sizeof ( int32 ) )
    {
    angleData = *((int8*)value);
    // See if Notification has been enabled
    GATTServApp_ProcessCharCfg( angleConfig, (uint8*)&angleData,
    FALSE, angleAttrTbl, GATT_NUM_ATTRS( angleAttrTbl ),
    INVALID_TASK_ID );
    }
    else
    {
    ret = bleInvalidRange;
    }
    break;
    case TIME_ANG_ATTR:
    if ( len == TIME_ANG_ATTR_LENGTH)//sizeof ( int32 ) )
    {
    for (int i = 0 ; i <TIME_ANG_ATTR_LENGTH; i++)
    {
    timeAngleData[i] = ((int8*)value)[i];
    }
    // Check for notification
    if ( (vConnHandle != INVALID_CONNHANDLE) &&
    (angleEnabled == TRUE) )
    {
    gattAttribute_t *attr;
    // Get the right table entry
    attr = GATTServApp_FindAttr( angleAttrTbl,
    GATT_NUM_ATTRS( angleAttrTbl ),
    //(uint8*)&timeAngleData );
    //(uint8*)timeAngleData );
    timeAngleData );
    uint16 value;
    value = GATTServApp_ReadCharCfg( vConnHandle, timeAngleConfig );
    if ( attr != NULL )
    {
    //if ( timeAngleConfig == GATT_CLIENT_CFG_NOTIFY )
    if ( value & GATT_CLIENT_CFG_NOTIFY )
    {
    attHandleValueNoti_t notify;
    // Send the notification
    notify.handle = attr->handle;
    notify.len = TIME_ANG_ATTR_LENGTH;
    for (int i = 0 ; i <TIME_ANG_ATTR_LENGTH; i++)
    {
    notify.value[i] = timeAngleData[i];
    }
    ret = GATT_Notification( vConnHandle, &notify, FALSE );
    }
    }
    }
    }
    else
    {
    ret = bleInvalidRange;
    }
    break;
    case ANGLE_INPUT:
    if ( len == sizeof ( int32 ) )
    {
    angleInput = *((int32*)value);
    }
    else
    {
    ret = bleInvalidRange;
    }
    break;
    case ANGLE_NOTIFICATION_PERIOD:
    if ( len == sizeof ( int32 ) )
    {
    angleNotifPeriod = *((int32*)value);
    }
    else
    {
    ret = bleInvalidRange;
    }
    break;
    case ANGLE_MAGNET_SENSITIVITY:
    if ( len == sizeof ( int8 ) )
    {
    angleMagnetSensitivity = *((int8*)value);
    }
    else
    {
    ret = bleInvalidRange;
    }
    break;
    case ANGLE_TABLE_SIZE:
    if ( len == sizeof ( int32 ) )
    {

    angleTableSize = *((int32*)value);
    }
    else
    {
    ret = bleInvalidRange;

    }
    break;
    case ANGLE_ACCLEROMETER_ENABLE:
    if ( len == sizeof ( int8 ) )
    {
    angleAccelerometerEnable = *((int8*)value);
    }
    else
    {
    ret = bleInvalidRange;
    }
    break;
    default:
    ret = INVALIDPARAMETER;
    break;
    }
    return ( ret );
    }