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.

LAUNCHXL-CC1352R1: Converting Project Zero BLE Example to a Static Library – Build Errors

Part Number: LAUNCHXL-CC1352R1

Tool/software:

I am trying to convert the Project Zero BLE example from the SimpleLink CC13x2 SDK into a static library so I can reuse it across multiple projects. However, I am facing compilation errors after removing hardware-specific files like ble_user_config.c.

Here’s what I have done so far:

  1. Removed OAD (Over-the-Air Download) support since I don’t need it.

  2. Excluded ble_user_config.c from the static library because it contains hardware-dependent configurations that should remain in the main project.

  3. Defined necessary preprocessor symbols from the example project in the library.

Issues & Errors

After compiling, I encountered the following errors:

shell
CopyEdit
#1965 cannot open source file "xdc/std.h" #20 identifier "coexUseCaseConfig_t" is undefined #20 identifier "cteAntProp_t" is undefined #20 identifier "ECCParams_CurveParams" is undefined #20 identifier "rfOpCmd_cntBranch_t" is undefined #20 identifier "rfOpCmd_runImmedCmd_t" is undefined #20 identifier "rtosApiTblPtr_t" is undefined

These errors seem to be related to missing dependencies from ble_user_config.c.

Questions:

  1. What is the recommended way to handle ble_user_config.c when converting a BLE project into a static library?

    • Should I manually define missing structs (coexUseCaseConfig_t, cteAntProp_t, etc.) in main.c?

    • Or should I include a minimal version of ble_user_config.c inside the library?

  2. How can I properly handle dependencies on xdc/std.h and TI-RTOS headers when building a static library?

    • The library does not seem to recognize xdc/std.h even though I have included TI-RTOS paths.

  3. Are there any best practices for structuring a BLE project as a static library in Code Composer Studio?

Any insights would be greatly appreciated!

System Details:

  • Platform: TI LaunchPad CC1352R1

  • SDK Version: simplelink_cc13x2_26x2_sdk_5_20_00_52

  • Compiler: TI Clang / TI ARM Compiler

Thank you!

//#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>


#include <icall.h>
#include <icall_ble_api.h>
#include <gapbondmgr.h>
#include <gapgattserver.h>
#include <gattservapp.h>
#include <devinfoservice.h>
#include <linkdb.h>

#include <project_zero.h>
#include <led_service.h>
#include <button_service.h>
#include <data_service.h>

// Task configuration
#define PZ_TASK_PRIORITY   1
#define PZ_TASK_STACK_SIZE 2048

static Task_Struct pzTask;
static uint8_t pzTaskStack[PZ_TASK_STACK_SIZE];

// Application events
#define PZ_STATE_CHANGE_EVT         0x0001
#define PZ_READ_RPA_EVT             0x0002
#define PZ_SEND_PARAM_UPDATE_EVT    0x0004
#define PZ_CONN_EVT                 0x0008

// Internal Events for RTOS application
#define PZ_ICALL_EVT                ICALL_MSG_EVENT_ID
#define PZ_QUEUE_EVT                UTIL_QUEUE_EVENT_ID
#define PZ_PERIODIC_EVT             Event_Id_00

// Service events
#define PZ_SERVICE_WRITE_EVT        Event_Id_01  /* A characteristic value has been written     */
#define PZ_SERVICE_CFG_EVT          Event_Id_02  /* A characteristic configuration has changed  */

#define PZ_ALL_EVENTS               (PZ_ICALL_EVT | PZ_QUEUE_EVT | PZ_PERIODIC_EVT | \
                                     PZ_SERVICE_WRITE_EVT | PZ_SERVICE_CFG_EVT)

// Connection handle of current connection
#define INVALID_CONNHANDLE          0xFFFF

// Suggested TX time for DLE (us)
#define APP_SUGGESTED_TX_TIME       2120

// Struct for messages sent to the application task
typedef struct {
    uint32_t event;
    void *pData;
} pzMsg_t;

// Struct for messages about characteristic data
typedef struct {
    uint16_t svcUUID; // UUID of the service
    uint16_t dataLen; //
    uint8_t paramID; // Index of the characteristic
    uint8_t data[]; // Flexible array member, extended to malloc - sizeof(.)
} pzCharacteristicData_t;

// Connection event structure
typedef struct {
    uint16_t connHandle;
    uint8_t  role;
    uint8_t  addrType;
    uint8_t  addr[B_ADDR_LEN];
} pzConnRec_t;

// Application state
static ICall_EntityID selfEntity;
static ICall_SyncHandle syncEvent;
static Queue_Struct appMsgQueue;
static Queue_Handle appMsgQueueHandle;
static Clock_Struct clkRpaRead;
static Clock_Struct clkSendParamUpdate;
static pzConnRec_t *connList = NULL;
static PzHardwareAbstraction_t hwAbstraction;
static PzBleConfig_t bleConfig;

// GAP Bond Manager Callbacks
static gapBondCBs_t ProjectZero_BondMgrCBs = {
    NULL, // Passcode callback
    NULL  // Pairing state callback
};

// LED Service Callbacks
static ledServiceCBs_t ProjectZero_LED_ServiceCBs = {
    .pfnChangeCb = ProjectZero_LedService_ValueChangeCB,  // Characteristic value change callback handler
    .pfnCfgChangeCb = NULL  // No notification-/indication enabled chars in LED Service
};

// Button Service Callbacks
static buttonServiceCBs_t ProjectZero_Button_ServiceCBs = {
    .pfnChangeCb = NULL,  // No writable chars in Button Service, so no change handler
    .pfnCfgChangeCb = ProjectZero_ButtonService_CfgChangeCB  // Noti/ind configuration callback handler
};

// Data Service Callbacks
static dataServiceCBs_t ProjectZero_Data_ServiceCBs = {
    .pfnChangeCb = ProjectZero_DataService_ValueChangeCB,  // Characteristic value change callback handler
    .pfnCfgChangeCb = ProjectZero_DataService_CfgChangeCB  // Noti/ind configuration callback handler
};

// Function prototypes
static void ProjectZero_taskFxn(UArg a0, UArg a1);
static void ProjectZero_processAppMsg(uint32_t evt, void *pMsg);
static void ProjectZero_processGapMessage(gapEventHdr_t *pMsg);
static void ProjectZero_processGATTMsg(gattMsgEvent_t *pMsg);
static void ProjectZero_processConnEvt(uint16_t connHandle, uint8_t event);
static void ProjectZero_clearConnListEntry(uint16_t connHandle);
static void ProjectZero_clockHandler(UArg arg);
static pzConnRec_t *ProjectZero_findConnRec(uint16_t connHandle);
static uint8_t ProjectZero_addConn(uint16_t connHandle);
static uint8_t ProjectZero_removeConn(uint16_t connHandle);
static status_t ProjectZero_enqueueMsg(uint32_t event, void *pData);
static void ProjectZero_LedService_ValueChangeCB(uint16_t connHandle, uint8_t paramID, uint16_t len, uint8_t *pValue);
static void ProjectZero_DataService_ValueChangeCB(uint16_t connHandle, uint8_t paramID, uint16_t len, uint8_t *pValue);
static void ProjectZero_ButtonService_CfgChangeCB(uint16_t connHandle, uint8_t paramID, uint16_t len, uint8_t *pValue);
static void ProjectZero_DataService_CfgChangeCB(uint16_t connHandle, uint8_t paramID, uint16_t len, uint8_t *pValue);
static void ProjectZero_LedService_ValueChangeHandler(pzCharacteristicData_t *pCharData);
static void ProjectZero_DataService_ValueChangeHandler(pzCharacteristicData_t *pCharData);
static void ProjectZero_ButtonService_CfgChangeHandler(pzCharacteristicData_t *pCharData);
static void ProjectZero_DataService_CfgChangeHandler(pzCharacteristicData_t *pCharData);

// Initialize the Project Zero library
void ProjectZero_initWithConfig(const PzHardwareAbstraction_t *hwAbstractionPtr, const PzBleConfig_t *bleConfigPtr, ICall_EntityID entity)
{
    // Store the hardware abstraction, BLE configuration, and selfEntity
    hwAbstraction = *hwAbstractionPtr;
    bleConfig = *bleConfigPtr;
    selfEntity = entity;

    // Create a sync event for event processing
    syncEvent = ICall_createSyncHandle();

    // Initialize queue for application messages
    Queue_construct(&appMsgQueue, NULL);
    appMsgQueueHandle = Queue_handle(&appMsgQueue);

    // Dynamically allocate the connection list based on maxNumBleConns
    connList = ICall_malloc(sizeof(pzConnRec_t) * bleConfig.maxNumBleConns);
    if (!connList) {
        if (hwAbstraction.logCallback) {
            hwAbstraction.logCallback("Failed to allocate connection list");
        }
        return;
    }
    memset(connList, 0, sizeof(pzConnRec_t) * bleConfig.maxNumBleConns);

    // Set the Device Name characteristic in the GAP GATT Service
    GGS_SetParameter(GGS_DEVICE_NAME_ATT, bleConfig.deviceNameLen, (void *)bleConfig.deviceName);

    // Configure GAP for param update
    GAP_SetParameter(GAP_PARAM_LINK_UPDATE_DECISION, bleConfig.paramUpdateDecision);

    // BLE Service initialization
    GGS_AddService(GATT_ALL_SERVICES);
    GATTServApp_AddService(GATT_ALL_SERVICES);
    DevInfo_AddService();
    LedService_AddService(selfEntity);
    ButtonService_AddService(selfEntity);
    DataService_AddService(selfEntity);

    // Register callbacks with the services
    LedService_RegisterAppCBs(&ProjectZero_LED_ServiceCBs);
    ButtonService_RegisterAppCBs(&ProjectZero_Button_ServiceCBs);
    DataService_RegisterAppCBs(&ProjectZero_Data_ServiceCBs);

    // Placeholder variable for characteristic initialization
    uint8_t initVal[40] = {0};
    uint8_t initString[] = "This is a pretty long string, isn't it!";

    // Initialization of characteristics in LED_Service that can provide data
    LedService_SetParameter(LS_LED0_ID, LS_LED0_LEN, initVal);
    LedService_SetParameter(LS_LED1_ID, LS_LED1_LEN, initVal);

    // Initialization of characteristics in Button_Service that can provide data
    ButtonService_SetParameter(BS_BUTTON0_ID, BS_BUTTON0_LEN, initVal);
    ButtonService_SetParameter(BS_BUTTON1_ID, BS_BUTTON1_LEN, initVal);

    // Initialization of characteristics in Data_Service that can provide data
    DataService_SetParameter(DS_STRING_ID, sizeof(initString), initString);
    DataService_SetParameter(DS_STREAM_ID, DS_STREAM_LEN, initVal);

    // Start Bond Manager and register callback
    VOID GAPBondMgr_Register(&ProjectZero_BondMgrCBs);

    // Register with GAP for HCI/Host messages
    GAP_RegisterForMsgs(selfEntity);

    // Register for GATT local events and ATT Responses
    GATT_RegisterForMsgs(selfEntity);

    // Set default values for Data Length Extension
    HCI_LE_WriteSuggestedDefaultDataLenCmd(bleConfig.maxPduSize, APP_SUGGESTED_TX_TIME);

    // Initialize GATT Client
    GATT_InitClient();

    // Initialize Connection List
    ProjectZero_clearConnListEntry(LINKDB_CONNHANDLE_ALL);

    // Create one-shot clock for RPA check event if using random address
    if (bleConfig.addressMode > ADDRMODE_RANDOM) {
        Util_constructClock(&clkRpaRead, ProjectZero_clockHandler, bleConfig.readRpaPeriod, 0, true, PZ_READ_RPA_EVT);
    }
}

// Create the Project Zero task
void ProjectZero_createTask(void)
{
    Task_Params taskParams;
    Task_Params_init(&taskParams);
    taskParams.stack = pzTaskStack;
    taskParams.stackSize = PZ_TASK_STACK_SIZE;
    taskParams.priority = PZ_TASK_PRIORITY;
    Task_construct(&pzTask, ProjectZero_taskFxn, &taskParams, NULL);
}

// Update button state (called by the main executable)
void ProjectZero_updateButtonState(uint8_t buttonId, uint8_t state)
{
    // Update the Button Service characteristic (implementation depends on button_service.c)
    ButtonService_SetParameter(buttonId, sizeof(state), &state);
    if (hwAbstraction.logCallback) {
        hwAbstraction.logCallback("%s %s", buttonId == BS_BUTTON0_ID ? "Button 0" : "Button 1",
                                  state ? "pressed" : "released");
    }
}

// Task function
static void ProjectZero_taskFxn(UArg a0, UArg a1)
{
    // Initialize application
    Event_Handle evtHandle = Event_create(NULL, NULL);

    // Register to receive connection events
    linkDB_Register(ProjectZero_processConnEvt);

    // Enter main loop
    while (1) {
        uint32_t events = Event_pend(evtHandle, 0, PZ_ALL_EVENTS, BIOS_WAIT_FOREVER);

        // Process periodic events
        if (events & PZ_PERIODIC_EVT) {
            // Handle periodic events (not used in this example)
        }

        // Process ICall messages
        if (events & PZ_ICALL_EVT) {
            ICall_ServiceEnum status;
            ICall_Event *pEvt;

            while ((pEvt = ICall_fetchServiceMsg(&status, &selfEntity, syncEvent)) != NULL) {
                if (status == ICALL_SERVICE_CLASS_BLE) {
                    ProjectZero_processAppMsg(pEvt->event, pEvt->data);
                }
                ICall_freeMsg(pEvt);
            }
        }

        // Process application messages
        if (events & PZ_QUEUE_EVT) {
            while (!Queue_empty(appMsgQueueHandle)) {
                pzMsg_t *pMsg = (pzMsg_t *)Queue_get(appMsgQueueHandle);
                if (pMsg) {
                    ProjectZero_processAppMsg(pMsg->event, pMsg->pData);
                    ICall_free(pMsg);
                }
            }
        }
    }
}

// Process application messages
static void ProjectZero_processAppMsg(uint32_t evt, void *pMsg)
{
    pzCharacteristicData_t *pCharData = (pzCharacteristicData_t *)pMsg;

    switch (evt) {
        case GAP_MSG_EVENT:
            ProjectZero_processGapMessage((gapEventHdr_t *)pMsg);
            break;
        case GATT_MSG_EVENT:
            ProjectZero_processGATTMsg((gattMsgEvent_t *)pMsg);
            break;
        case PZ_READ_RPA_EVT:
            // Handle RPA read event (not implemented in this example)
            break;
        case PZ_SEND_PARAM_UPDATE_EVT:
            // Handle parameter update event (not implemented in this example)
            break;
        case PZ_CONN_EVT:
            // Handle connection event (not implemented in this example)
            break;
        case PZ_SERVICE_WRITE_EVT:
            switch (pCharData->svcUUID) {
                case LED_SERVICE_SERV_UUID:
                    ProjectZero_LedService_ValueChangeHandler(pCharData);
                    break;
                case DATA_SERVICE_SERV_UUID:
                    ProjectZero_DataService_ValueChangeHandler(pCharData);
                    break;
            }
            break;
        case PZ_SERVICE_CFG_EVT:
            switch (pCharData->svcUUID) {
                case BUTTON_SERVICE_SERV_UUID:
                    ProjectZero_ButtonService_CfgChangeHandler(pCharData);
                    break;
                case DATA_SERVICE_SERV_UUID:
                    ProjectZero_DataService_CfgChangeHandler(pCharData);
                    break;
            }
            break;
        default:
            break;
    }

    // Free the message data if it exists
    if (evt == PZ_SERVICE_WRITE_EVT || evt == PZ_SERVICE_CFG_EVT) {
        ICall_free(pMsg);
    }
}

// Process GAP messages
static void ProjectZero_processGapMessage(gapEventHdr_t *pMsg)
{
    switch (pMsg->opcode) {
        case GAP_DEVICE_INIT_DONE_EVENT:
        {
            gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
            if (pPkt->hdr.status == SUCCESS) {
                // Store the system ID
                uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
                systemId[0] = pPkt->devAddr[0];
                systemId[1] = pPkt->devAddr[1];
                systemId[2] = pPkt->devAddr[2];
                systemId[4] = 0x00;
                systemId[3] = 0x00;
                systemId[7] = pPkt->devAddr[5];
                systemId[6] = pPkt->devAddr[4];
                systemId[5] = pPkt->devAddr[3];
                DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);

                if (hwAbstraction.logCallback) {
                    static char addrStr[3 * B_ADDR_LEN + 1];
                    snprintf(addrStr, sizeof(addrStr), "%02X:%02X:%02X:%02X:%02X:%02X",
                             pPkt->devAddr[5], pPkt->devAddr[4], pPkt->devAddr[3],
                             pPkt->devAddr[2], pPkt->devAddr[1], pPkt->devAddr[0]);
                    hwAbstraction.logCallback("GAP is started. Our address: %s", addrStr);
                }
            }
            // Start advertising
            GapAdv_create(NULL, bleConfig.advParams, NULL);
            GapAdv_loadByBuffer(bleConfig.advDataLen, bleConfig.advData);
            GapAdv_loadByBuffer(bleConfig.scanResDataLen, bleConfig.scanResData);
            GapAdv_enable(0, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0);
            break;
        }
        case GAP_LINK_ESTABLISHED_EVENT:
        {
            gapEstLinkReqEvent_t *pEvt = (gapEstLinkReqEvent_t *)pMsg;
            if (pEvt->hdr.status == SUCCESS) {
                ProjectZero_addConn(pEvt->connectionHandle);
                if (hwAbstraction.logCallback) {
                    static char addrStr[3 * B_ADDR_LEN + 1];
                    snprintf(addrStr, sizeof(addrStr), "%02X:%02X:%02X:%02X:%02X:%02X",
                             pEvt->devAddr[5], pEvt->devAddr[4], pEvt->devAddr[3],
                             pEvt->devAddr[2], pEvt->devAddr[1], pEvt->devAddr[0]);
                    hwAbstraction.logCallback("Connected. Peer address: %s", addrStr);
                }
            }
            break;
        }
        case GAP_LINK_TERMINATED_EVENT:
        {
            gapTermLinkEvent_t *pEvt = (gapTermLinkEvent_t *)pMsg;
            ProjectZero_removeConn(pEvt->connectionHandle);
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("Link Terminated: ConnHandle 0x%04X", pEvt->connectionHandle);
            }
            // Restart advertising
            GapAdv_enable(0, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0);
            break;
        }
        default:
            break;
    }
}

// Process GATT messages
static void ProjectZero_processGATTMsg(gattMsgEvent_t *pMsg)
{
    if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT) {
        if (hwAbstraction.logCallback) {
            hwAbstraction.logCallback("FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
        }
    }

    // Forward GATT messages to the services
    GATT_bm_free(&pMsg->msg, pMsg->method);
}

// Process connection events
static void ProjectZero_processConnEvt(uint16_t connHandle, uint8_t event)
{
    if (hwAbstraction.logCallback) {
        hwAbstraction.logCallback("Connection event done for connHandle: 0x%04X", connHandle);
    }
}

// Clear connection list entry
static void ProjectZero_clearConnListEntry(uint16_t connHandle)
{
    for (uint8_t i = 0; i < bleConfig.maxNumBleConns; i++) {
        if (connList[i].connHandle == connHandle || connHandle == LINKDB_CONNHANDLE_ALL) {
            connList[i].connHandle = INVALID_CONNHANDLE;
            memset(&connList[i], 0, sizeof(pzConnRec_t));
        }
    }
}

// Add a device to the connected device list
static uint8_t ProjectZero_addConn(uint16_t connHandle)
{
    pzConnRec_t *rec = ProjectZero_findConnRec(INVALID_CONNHANDLE);
    if (rec) {
        rec->connHandle = connHandle;
        return SUCCESS;
    }
    return bleNoResources;
}

// Remove a device from the connected device list
static uint8_t ProjectZero_removeConn(uint16_t connHandle)
{
    pzConnRec_t *rec = ProjectZero_findConnRec(connHandle);
    if (rec) {
        ProjectZero_clearConnListEntry(connHandle);
        return SUCCESS;
    }
    return bleInvalidRange;
}

// Clock handler
static void ProjectZero_clockHandler(UArg arg)
{
    uint32_t evt = (uint32_t)arg;
    Event_post(Event_handle(NULL), evt);
}

// Find connection record
static pzConnRec_t *ProjectZero_findConnRec(uint16_t connHandle)
{
    for (uint8_t i = 0; i < bleConfig.maxNumBleConns; i++) {
        if (connList[i].connHandle == connHandle) {
            return &connList[i];
        }
    }
    return NULL;
}

// Utility function to enqueue messages to the application task
static status_t ProjectZero_enqueueMsg(uint32_t event, void *pData)
{
    uint8_t success;
    pzMsg_t *pMsg = ICall_malloc(sizeof(pzMsg_t));

    if (pMsg) {
        pMsg->event = event;
        pMsg->pData = pData;

        success = Queue_put(appMsgQueueHandle, (Queue_Elem *)pMsg);
        return (success) ? SUCCESS : FAILURE;
    }

    return bleMemAllocError;
}

// LED Service Value Change Callback
static void ProjectZero_LedService_ValueChangeCB(uint16_t connHandle, uint8_t paramID, uint16_t len, uint8_t *pValue)
{
    if (hwAbstraction.logCallback) {
        hwAbstraction.logCallback("(CB) LED Svc Characteristic value change: paramID(%d). Sending msg to app.", paramID);
    }

    pzCharacteristicData_t *pValChange = ICall_malloc(sizeof(pzCharacteristicData_t) + len);

    if (pValChange != NULL) {
        pValChange->svcUUID = LED_SERVICE_SERV_UUID;
        pValChange->paramID = paramID;
        memcpy(pValChange->data, pValue, len);
        pValChange->dataLen = len;

        if (ProjectZero_enqueueMsg(PZ_SERVICE_WRITE_EVT, pValChange) != SUCCESS) {
            ICall_free(pValChange);
        }
    }
}

// Data Service Value Change Callback
static void ProjectZero_DataService_ValueChangeCB(uint16_t connHandle, uint8_t paramID, uint16_t len, uint8_t *pValue)
{
    if (hwAbstraction.logCallback) {
        hwAbstraction.logCallback("(CB) Data Svc Characteristic value change: paramID(%d). Sending msg to app.", paramID);
    }

    pzCharacteristicData_t *pValChange = ICall_malloc(sizeof(pzCharacteristicData_t) + len);

    if (pValChange != NULL) {
        pValChange->svcUUID = DATA_SERVICE_SERV_UUID;
        pValChange->paramID = paramID;
        memcpy(pValChange->data, pValue, len);
        pValChange->dataLen = len;

        if (ProjectZero_enqueueMsg(PZ_SERVICE_WRITE_EVT, pValChange) != SUCCESS) {
            ICall_free(pValChange);
        }
    }
}

// Button Service CCCD Change Callback
static void ProjectZero_ButtonService_CfgChangeCB(uint16_t connHandle, uint8_t paramID, uint16_t len, uint8_t *pValue)
{
    if (hwAbstraction.logCallback) {
        hwAbstraction.logCallback("(CB) Button Svc Char config change paramID(%d). Sending msg to app.", paramID);
    }

    pzCharacteristicData_t *pValChange = ICall_malloc(sizeof(pzCharacteristicData_t) + len);

    if (pValChange != NULL) {
        pValChange->svcUUID = BUTTON_SERVICE_SERV_UUID;
        pValChange->paramID = paramID;
        memcpy(pValChange->data, pValue, len);
        pValChange->dataLen = len;

        if (ProjectZero_enqueueMsg(PZ_SERVICE_CFG_EVT, pValChange) != SUCCESS) {
            ICall_free(pValChange);
        }
    }
}

// Data Service CCCD Change Callback
static void ProjectZero_DataService_CfgChangeCB(uint16_t connHandle, uint8_t paramID, uint16_t len, uint8_t *pValue)
{
    if (hwAbstraction.logCallback) {
        hwAbstraction.logCallback("(CB) Data Svc Char config change paramID(%d). Sending msg to app.", paramID);
    }

    pzCharacteristicData_t *pValChange = ICall_malloc(sizeof(pzCharacteristicData_t) + len);

    if (pValChange != NULL) {
        pValChange->svcUUID = DATA_SERVICE_SERV_UUID;
        pValChange->paramID = paramID;
        memcpy(pValChange->data, pValue, len);
        pValChange->dataLen = len;

        if (ProjectZero_enqueueMsg(PZ_SERVICE_CFG_EVT, pValChange) != SUCCESS) {
            ICall_free(pValChange);
        }
    }
}

// LED Service Value Change Handler
static void ProjectZero_LedService_ValueChangeHandler(pzCharacteristicData_t *pCharData)
{
    static uint8_t pretty_data_holder[16]; // 5 bytes as hex string "AA:BB:CC:DD:EE"
    snprintf((char *)pretty_data_holder, sizeof(pretty_data_holder), "%02X", pCharData->data[0]);

    switch (pCharData->paramID) {
        case LS_LED0_ID:
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("Value Change msg: LED Service LED0: %s", pretty_data_holder);
            }
            if (hwAbstraction.setLedCallback) {
                hwAbstraction.setLedCallback(0, pCharData->data[0]);
            }
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("Turning LED0 %s", pCharData->data[0] ? "on" : "off");
            }
            break;

        case LS_LED1_ID:
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("Value Change msg: LED Service LED1: %s", pretty_data_holder);
            }
            if (hwAbstraction.setLedCallback) {
                hwAbstraction.setLedCallback(1, pCharData->data[0]);
            }
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("Turning LED1 %s", pCharData->data[0] ? "on" : "off");
            }
            break;

        default:
            return;
    }
}

// Data Service Value Change Handler
static void ProjectZero_DataService_ValueChangeHandler(pzCharacteristicData_t *pCharData)
{
    static uint8_t received_string[DS_STRING_LEN] = {0};

    switch (pCharData->paramID) {
        case DS_STRING_ID:
            memset(received_string, 0, DS_STRING_LEN);
            memcpy(received_string, pCharData->data, MIN(pCharData->dataLen, DS_STRING_LEN - 1));
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("Value Change msg: Data Service String: %s", received_string);
            }
            break;

        case DS_STREAM_ID:
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("Value Change msg: Data Service Stream: %02x:%02x:%02x...",
                                          pCharData->data[0], pCharData->data[1], pCharData->data[2]);
            }
            break;

        default:
            return;
    }
}

// Button Service CCCD Change Handler
static void ProjectZero_ButtonService_CfgChangeHandler(pzCharacteristicData_t *pCharData)
{
    uint16_t configValue = *(uint16_t *)pCharData->data;
    const char *configValString;

    switch (configValue) {
        case GATT_CFG_NO_OPERATION:
            configValString = "Noti/Ind disabled";
            break;
        case GATT_CLIENT_CFG_NOTIFY:
            configValString = "Notifications enabled";
            break;
        case GATT_CLIENT_CFG_INDICATE:
            configValString = "Indications enabled";
            break;
        default:
            configValString = "Unsupported operation";
    }

    switch (pCharData->paramID) {
        case BS_BUTTON0_ID:
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("CCCD Change msg: Button Service BUTTON0: %s", configValString);
            }
            break;

        case BS_BUTTON1_ID:
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("CCCD Change msg: Button Service BUTTON1: %s", configValString);
            }
            break;
    }
}

// Data Service CCCD Change Handler
static void ProjectZero_DataService_CfgChangeHandler(pzCharacteristicData_t *pCharData)
{
    uint16_t configValue = *(uint16_t *)pCharData->data;
    const char *configValString;

    switch (configValue) {
        case GATT_CFG_NO_OPERATION:
            configValString = "Noti/Ind disabled";
            break;
        case GATT_CLIENT_CFG_NOTIFY:
            configValString = "Notifications enabled";
            break;
        case GATT_CLIENT_CFG_INDICATE:
            configValString = "Indications enabled";
            break;
        default:
            configValString = "Unsupported operation";
    }

    switch (pCharData->paramID) {
        case DS_STREAM_ID:
            if (hwAbstraction.logCallback) {
                hwAbstraction.logCallback("CCCD Change msg: Data Service Stream: %s", configValString);
            }
            break;
    }
}






5140.project_zero.hIncluded paths

  • Hi !

    Changing the Project Zero BLE example into a static library sounds like quite task, since it's not possible to switch a project from an executable target to a static library target in CCS. The only way you could create a static library would be to create a new project and try to patch together the files, linker configuration, and compiler configuration. Could you please explain what you did before removing OAD (copying files, changing some project settings, etc ..) so I can try to reproduce your situation and help you better ?

    To answer your questions :
    1. In my project, coexUseCaseConfig_t and cteAntProp_t are defined in the icall_user_config.h file. Is it possible that you may have accidently deleted this file ?
    2. xdc/std.h is located in {your sdk installation path}/kernel/tirtos7/packages/. You can check if this path is correctly included in the File Search Path by going to Project > Proprieties > Build > Arm Linker > File Search Path and checking if ${COM_TI_SIMPLELINK_CC13XX_CC26XX_SDK_INSTALL_DIR}/kernel/tirtos7/packages is there.

    3. I could not find anything regarding best practices for structuring a BLE project as a static library.

    I hope that these answers will help you fix your compilation issues.

    Kind regards,
    Maxence

  • Hi Maxence,

    So I am not trying to change the example because obviously it is an executable but rather I created a static library project and tried to move all the hardware dependent parts to the main code leaving the main code agnostic. since there multiple linked files in different folders of the example project, I removed those that either needed syscfg configuration or some other user configuration  and moved them to the main code using palceholders for them in the library. I have attached the original project zero application file so that it can be compared against the one I sent earlier which is the one from my static library project.

    1. I have not accidentally deleted icall_user_config.h since I linked the files I am using rather than having the copies in the project.

    2. I have not had the problem with xdc/sth before so I am surprised it's coming up because I have xdc already linked in the product settings (image attached)

    3. what I am trying to figure out is if icall_user_config.h is being called in one of my profiles or linked files causing the error.

    4. I have attached my included paths below. I would love for you to take a crack at static library if that is possible.

    Kind regards,

    Augustine 

    included paths:

    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INCLUDE_PATH}
    C:\ti\simplelink_cc13x2_26x2_sdk_5_20_00_52
    C:/ti/simplelink_cc13x2_26x2_sdk_5_20_00_52/kernel/tirtos/packages
    C:/ti/simplelink_cc13x2_26x2_sdk_5_20_00_52/source
    ${PROJECT_ROOT}
    ${CG_TOOL_ROOT}/include
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/common/cc26xx/
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/boards/CC1352R1_LAUNCHXL
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/common/../
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/kernel/tirtos/packages
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/controller/cc26xx/inc
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/inc
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/rom
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/common/cc26xx
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/icall/inc
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/hal/src/target/_common
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/hal/src/target/_common/cc26xx
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/hal/src/inc
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/heapmgr
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/profiles/dev_info
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/icall/src/inc
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/osal/src/inc
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/services/src/saddr
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/ble5stack/services/src/sdata
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/common/nv
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/common/cc26xx
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/devices/cc13x2_cc26x2
    ${COM_TI_SIMPLELINK_CC13X2_26X2_SDK_INSTALL_DIR}/source/ti/posix/ccs

      5415.project_zero.c

  • Hi, 

    Extremely sorry for the one week delay, I wrote down this response a week ago and forgot to press reply Sweat smile

    Could you please send your project by exporting it through CCS so I can have a closer look at the problem ? You can do that by selecting File > Export, then General > Archive file, clicking the checkbox next to your project's name, choosing a file name and clicking finish.

    Kind regards,
    Maxence

  • Hi Maxence,

    Thank you for responding. I have been unsuccessful in tackling this problem up till now. I have attached the archived file here. Hopefully, you can get it to work.

    Project_Zero_Library.zip

  • Hi !

    I managed to get a lot of progress done by simply upgrading your SDK version from v5_20_00_52 to v8_30_01_01 (the latest SDK version).
    Here are the main changes I made :

    - While your include path used the COM_TI_SIMPLELINK_CC13XX_26XX_SDK_INSTALL_DIR symbol, mine use the COM_TI_SIMPLELINK_CC13XX_CC26XX_SDK_INSTALL_DIR symbol. Maybe this changed between the two SDK versions, or maybe you mis-typed the include symbol.
    - I added the CCS compiler include path and the source code path (${PROJECT_LOC}/src, ${PROJECT_LOC}/Profiles and ${CG_TOOL_ROOT}/include)

    The include problems now seem resolved, I have not seen any issue with XDC on my end. The errors are now only related to the source code of the project zero in itself (undefined variables, multiple case label, etc). But this is a work that you will have to do on your own mostly.

    You can find the updated code that I made here : pz_lib.zip

    Kind regards,
    Maxence

  • Hi Maxence,

    I have downloaded the latest SDK and tried it and I am still getting xdc related errors. can you send your project file, let me try with it?

  • Hi

    The project file is in the response I sent :)|

    Kind regards,
    Maxence