Quick Start Guide

group page_ble_quick_start

The PSoC 6 BLE Middleware can be used in various software environments such as ModusToolbox, etc.

Refer to Supported Software and Tools page. The quickest way to get started is using the Code Examples. Cypress Semiconductor continuously extends its portfolio of code examples at the Cypress Semiconductor website and at the Cypress Semiconductor GitHub site.

You must accomplish several tasks to implement a BLE standard profile application:

  • PSoC 6 BLE Middleware configuration in BT Configurator

  • System and PSoC 6 BLE Middleware Initialization

  • Main Loop Implementation

  • Stack Event Handler

  • Service-specific Event Handler

  • Implement Low-power Performance

The snippets below show an implementation of a simple Bluetooth SIG-defined standard profile called Find Me Profile (FMP). BLE midlleware is configured to operate in Complete BLE Protocol Single CPU mode. In this mode,the BLE functionality is entirely on the CM4 CPU core. It uses a software interface for communication between the controller and host. Refer to Configuration Considerations for details on how to configure the BLE middleware for operation in Complete BLE Protocol Dual CPU or Controller-only (HCI over Software API) modes.

PSoC 6 BLE Middleware configuration in BT Configurator

The ModusToolbox BT Configurator Guide describes how to use BT Configurator. The BT Configurator Tool can be launched in ModusToolbox IDE from the BLE personality, as well as in stand-alone mode. Refer to ModusToolbox Software Environment, Quick Start Guide, Documentation, and Videos.

For this Quick Start Guide, the PSoC 6 BLE Middleware is configured as the Find Me Target in the GAP Peripheral role with the settings shown in the figures below:

General Settings

Use the General tab for general configuration of the Bluetooth resource (e.g GAP role, max number of BLE connection, etc).

../../../../_images/bt_config_general_tab.jpg

GATT Settings

Use the GATT Settings tab to configure Profile-specific parameters. For this Quick Start Guide we add only Find Me profile (Find Me Target (GATT Server)).

../../../../_images/bt_config_gatt_tab.jpg

GAP Settings

Use the GAP Settings tab to configure GAP parameters, which define the general connection settings required when connecting Bluetooth devices. It contains various parameters based on the item you select in the tree.

General

In this panel you configure general GAP parameters (e.g. Public device address, Device Name, Appearance, Adv/Scan/Connections TX power level, etc).

../../../../_images/bt_config_gap_tab.jpg

Advertisement Settings

In this panel you configure the general parameters for advertisement configuration (e.g. Discovery mode, Advertising type, Filter policy, Advertising Interval, etc).

../../../../_images/bt_config_advervicement_setting.jpg

Advertisement Packet

In this panel you configure the Advertisement data to be used in device advertisements.

../../../../_images/bt_config_advervicement_packet.jpg

Security Settings

In this panel you configure security settings for the device. The example uses a configuration that does not require authentication, encryption, or authorization for data exchange.

../../../../_images/bt_config_securiti_configuration.jpg

PSoC 6 BLE Middleware configuration is saved in files “cycfg_ble.h” and “cycfg_ble.c”. These files must be attached to the user project.

System and PSoC 6 BLE Middleware Initialization

When PSoC 6 BLE MCU is reset, the application should perform system initialization which includes: setting up the CPU cores for execution, enabling global interrupts, and enabling other components used in the design ( UART, MCWDT, etc). After the CPUs are initialized the application initializes the PSoC 6 BLE Middleware, which sets up a complete BLE subsystem.

As part of the PSoC 6 BLE Middleware initialization, you must:

  • Initialize the BLESS interrupt. See Configure BLESS Interrupt for detailed information. The code below shows how to implement the routine (ISR) handler of the BLESS interrupt service (refer to BlessInterrupt() function). The Cy_BLE_BlessIsrHandler() function is called from BlessInterrupt() to process interrupt events generated by BLESS.

  • Register the generic event handler function to be called by the BLE stack to notify of pending events. Refer to Cy_BLE_RegisterEventCallback() function.

  • Call Cy_BLE_Init() to initialize PSoC 6 BLE Middleware. Pass the address of the configuration structure generated by the BT Configurator, cy_ble_config (exposed in cycfg_ble.c).

  • Call Cy_BLE_Enable() to enable the BLE subsystem.

  • Register service-specific event handlers (the example uses only the IAS event handler to handle Immediate Alert Service related events). Refer to Cy_BLE_IAS_RegisterAttrCallback() function.


#include "cy_syslib.h"
#include "cy_sysint.h"
#include "cycfg.h"
#include "cycfg_ble.h"
 

/*******************************************************************************
* Global variables
*******************************************************************************/
/* The Alert Level value */
static uint8_t                  alertLevel = CY_BLE_NO_ALERT;
 
/* The variables to initialize the BLE stack timer to get a 1-second interval */
static cy_stc_ble_timer_info_t  timerParam = { .timeout = 1u /* second */ };
static uint8_t                  mainTimer = 1u;

/* LED8 and LED9 port definitions */
#define LED8_PORT GPIO_PRT1
#define LED8_PIN 5U

#define LED9_PORT GPIO_PRT13
#define LED9_PIN 7U

/* BLESS interrupt configuration.
 * It is used when BLE middleware operates in BLE Single CM4 Core mode. */
const cy_stc_sysint_t blessIsrCfg =
{
    /* The BLESS interrupt */
    .intrSrc      = bless_interrupt_IRQn,
 
    /* The interrupt priority number */
    .intrPriority = 1u
};


/*******************************************************************************
* Private Function Prototypes
*******************************************************************************/
void AppMainLoop(void);
void AppCallBack(uint32_t event, void *eventParam);
void IasEventHandler(uint32_t event, void *eventParam);
void LowPowerImplementation(void);


/*******************************************************************************
* Function Name: BlessInterrupt
********************************************************************************
* BLESS ISR
* It is used used when BLE middleware operates in BLE single CM4
*
*******************************************************************************/
/* BLESS ISR */
void BlessInterrupt(void)
{
    /* Call interrupt processing */
    Cy_BLE_BlessIsrHandler();
}


/*******************************************************************************
* Function Name: main()
********************************************************************************
* Summary:
*  Main function for the BLE project.
*
*******************************************************************************/
int main(void)
{
    /* Enable interrupts */
    __enable_irq();
     
    /* Initialize all peripherals and system resources */
    init_cycfg_all();

    /* Initialize GPIO */     
    Cy_GPIO_Pin_FastInit(LED9_PORT, LED9_PIN, CY_GPIO_DM_STRONG_IN_OFF, 1u, HSIOM_SEL_GPIO);
    Cy_GPIO_Pin_FastInit(LED8_PORT, LED8_PIN, CY_GPIO_DM_STRONG_IN_OFF, 1u, HSIOM_SEL_GPIO);

    /* Initialize the BLESS interrupt */
    cy_ble_config.hw->blessIsrConfig = &blessIsrCfg;
    Cy_SysInt_Init(cy_ble_config.hw->blessIsrConfig, BlessInterrupt);
     
    /* Register the generic event handler */
    Cy_BLE_RegisterEventCallback(AppCallBack);
     
    /* Initialize the BLE */
    Cy_BLE_Init(&cy_ble_config);
 
    /* Enable BLE Low-power Mode (LPM) */
    Cy_BLE_EnableLowPowerMode();
 
    /* Enable BLE */
    Cy_BLE_Enable();
 
    /* Register the IAS CallBack */
    Cy_BLE_IAS_RegisterAttrCallback(IasEventHandler);
 
    /* Main loop implementation */
    while(1)
    {
        /* Main loop implementation */
        AppMainLoop();
    }    
}

Main Loop Implementation

The main loop in the example has a simply flow:

  • process the BLE stack pending events by a call to Cy_BLE_ProcessEvents()

  • process a received alert level: updates the LEDs based on the alert level

  • restarts the BLE stack timer to get a 1-second interval to blink the LED

  • the application goes into Low-power mode by call to the LowPowerImplementation() function.

void AppMainLoop(void)
{
    /* Cy_BLE_ProcessEvents() allows the BLE stack to process pending events */ 
    Cy_BLE_ProcessEvents();
    
    switch (alertLevel)
    {
    case CY_BLE_NO_ALERT :
        Cy_GPIO_Write(LED9_PORT, LED9_PIN, 1u); /* LED_OFF */
        break ;

    case CY_BLE_MILD_ALERT :
        if(mainTimer)
        {
            /* Toggle the alert LED after a timeout */ 
            Cy_GPIO_Inv(LED9_PORT, LED9_PIN);
        }
        break ;

    case CY_BLE_HIGH_ALERT :
        Cy_GPIO_Write(LED9_PORT, LED9_PIN, 0u); /* LED_ON */
        break ;
    }

    /* Restart the BLE stack timer. Used to get a 1-second interval to
        * blink the LED */
    if(mainTimer)
    {
        mainTimer = 0u;
        Cy_BLE_StartTimer(&timerParam);
    }

    /* Enter deep-sleep to achieve low power in the device */ 
    LowPowerImplementation();
}

Stack Event Handler

The BLE stack within the PSoC 6 BLE Middleware generates events. These events provide status and data to the application firmware through the BLE stack event handler.

The event handler must handle a few basic events from the stack. For the Find Me Target application in this code example, the BLE stack event-handler must process the events described in table below. The actual code recognizes and responds to additional events.

BLE Stack Event Name

Event Description

Event Handler Action

CY_BLE_EVT_STACK_ON

BLE stack initialization is completed successfully

Start advertisement and reflect the advertisement state on the LED

CY_BLE_EVT_GAP_DEVICE_DISCONNECTED

BLE link with the peer device is disconnected

Restart advertisement and reflect the advertisement state on the LED

CY_BLE_EVT_GAP_DEVICE_CONNECTED

BLE link with the peer device is established

Update the BLE link state on the LED

CY_BLE_EVT_GAPP_ADVERTISEMENT_START_STOP

BLE stack advertisement start/stop event

Shutdown the BLE stack

CY_BLE_EVT_STACK_SHUTDOWN_COMPLETE

BLE stack has been shutdown

Put the device into Hibernate mode

CY_BLE_EVT_GAP_AUTH_REQ

BLE authentication request received

Call Cy_BLE_GAPP_AuthReqReply() to reply to the authentication request from Central

The code snippets show examples of how the event handler responds to an identified events. See the actual source code for a complete understanding.

/*******************************************************************************
* Function Name: AppCallBack
********************************************************************************
* Summary: This is an event callback function to receive events from the PSoC 6 BLE Middleware.
*
* Parameters:
*   event      - The event code.
*   eventParam - The event parameters.
*
*******************************************************************************/
void AppCallBack(uint32_t event, void *eventParam)
{
    switch(event)
    {
      /* Generic events (e.g CY_BLE_EVT_STACK_ON, CY_BLE_EVT_STACK_BUSY_STATUS, etc) */
      . . .
    
      /* GAP Events (e.g CY_BLE_EVT_GAP_AUTH_REQ, CY_BLE_EVT_GAP_AUTH_COMPLETE, CY_BLE_EVT_GAP_DEVICE_CONNECTED, etc) */
       . . .
     
      /* GATT Events (e.g CY_BLE_EVT_GATT_CONNECT_IND, CY_BLE_EVT_GATT_DISCONNECT_IND, etc) */
       . . .

      /* Other Events */
       . . .
    }
}

In this snippet, the handler starts advertising in response to the CY_BLE_EVT_STACK_ON event.

        /* This event is received when the BLE stack is initialized and turned ON
         * by invoking the Cy_BLE_StackInit() function */
        case CY_BLE_EVT_STACK_ON:
            /* Enter into discoverable mode so that remote can find it */
            Cy_BLE_GAPP_StartAdvertisement(CY_BLE_ADVERTISING_FAST,
                                           CY_BLE_PERIPHERAL_CONFIGURATION_0_INDEX);
            break;
In this snippet, the handler responds to the “advertisement start/stop” event. The code toggles the LEDs appropriately. If advertising has started, the advertisement LED turns on. The disconnect LED turns off, because the device started advertising and is ready for connection. If advertising stops, the code sets the LEDs appropriately, and sets a flag to enter Hibernate mode.
        /* This event indicates the peripheral device has started/stopped advertising */ 
        case  CY_BLE_EVT_GAPP_ADVERTISEMENT_START_STOP:
            if (Cy_BLE_GetAdvertisementState() == CY_BLE_ADV_STATE_STOPPED)
            {  
                /* The fast and slow advertising period is complete, go to Low-power 
                * mode (Hibernate) and wait for an external user event to wake up 
                * the device again */
                Cy_BLE_Disable();
                
                Cy_GPIO_Write(LED8_PORT, LED8_PIN, 1u); /* LED_OFF */
                Cy_GPIO_Write(LED9_PORT, LED9_PIN, 1u); /* LED_OFF */
            }
            break;  
In this snippet, the handler responds to the “disconnected” event. It starts advertising and sets the LEDs correctly.
        /* This event is generated when disconnected from a remote device or failed 
         * to establish connection */
        case CY_BLE_EVT_GAP_DEVICE_DISCONNECTED:
            /* Start BLE advertising for 30 seconds and update the link status on the LEDs */
            Cy_BLE_GAPP_StartAdvertisement(CY_BLE_ADVERTISING_FAST,
                                           CY_BLE_PERIPHERAL_CONFIGURATION_0_INDEX);
    
            /* Set default value for alert level (CY_BLE_NO_ALERT) */
            alertLevel = CY_BLE_NO_ALERT;
    
            Cy_GPIO_Write(LED8_PORT, LED8_PIN, 0u); /* LED_ON */
            Cy_GPIO_Write(LED9_PORT, LED9_PIN, 1u); /* LED_OFF */
            break;
In this snippet, the handler receives a timeout from BLE stack timer. In this example the BLE stack timer is used to get a 1-second interval to blink the LED.
        /* This event is received when there is a timeout and the application
         * must handle the event */
        case CY_BLE_EVT_TIMEOUT:
            if( (((cy_stc_ble_timeout_param_t *)eventParam)->reasonCode == 
                    CY_BLE_GENERIC_APP_TO) &&
                (((cy_stc_ble_timeout_param_t *)eventParam)->timerHandle == 
                    timerParam.timerHandle) )
            {
                /* Indicate that the timer is raised to the main loop */
                mainTimer++;
                    
                /* Update the LED state */
                if(Cy_BLE_GetAdvertisementState() == CY_BLE_ADV_STATE_ADVERTISING)
                {
                    /* Advertising state */
                    Cy_GPIO_Inv(LED8_PORT, LED8_PIN);
                    Cy_GPIO_Write(LED9_PORT, LED9_PIN, 1u); /* LED_OFF */
                }
                else if(Cy_BLE_GetNumOfActiveConn() == 0u)
                {
                    /* Disconnected state */
                    Cy_GPIO_Write(LED8_PORT, LED8_PIN, 0u); /* LED_ON */
                    Cy_GPIO_Write(LED9_PORT, LED9_PIN, 1u); /* LED_OFF */
                }
                else
                {
                    /* Connected state: update the alert level value LED8 */
                Cy_GPIO_Write(LED8_PORT, LED8_PIN, 1u); /* LED_OFF */
                }  
            }
            break;
In this snippet, the handler puts the device into Hibernate mode in response to the CY_BLE_EVT_STACK_SHUTDOWN_COMPLETE event.
        /* This event is used to inform the application that BLE Stack shutdown
         * is complete */
        case CY_BLE_EVT_STACK_SHUTDOWN_COMPLETE:
            /* Set the device into Hibernate mode */
            Cy_SysPm_SystemEnterHibernate();
            break;
In this snippet, the handler responds to the authentication request from the Central device. The peripheral device must call Cy_BLE_GAPP_AuthReqReply() to reply to the authentication request from the Central.
        /* This event can be received by a device in Peripheral or Central role. 
         * When it is received by a device in a Peripheral role, it must call 
         * Cy_BLE_GAPP_AuthReqReply() to reply to the authentication request from Central */
        case CY_BLE_EVT_GAP_AUTH_REQ:
            if(cy_ble_config.authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX].security ==
                (CY_BLE_GAP_SEC_MODE_1 | CY_BLE_GAP_SEC_LEVEL_1))
            {
                cy_ble_config.authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX].authErr =
                    CY_BLE_GAP_AUTH_ERROR_PAIRING_NOT_SUPPORTED;
            }   
        
            cy_ble_config.authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX].bdHandle =
                ((cy_stc_ble_gap_auth_info_t *)eventParam)->bdHandle;
        
            if (Cy_BLE_GAPP_AuthReqReply(&cy_ble_config.authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX]) !=
                    CY_BLE_SUCCESS)           
            {
                Cy_BLE_GAP_RemoveOldestDeviceFromBondedList();
                Cy_BLE_GAPP_AuthReqReply(&cy_ble_config.authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX]);           
            }
            break;

Service-specific Event Handler

The PSoC 6 BLE Middleware also generates events corresponding to each of the services supported by the design. For the Find Me Target application, the PSoC 6 BLE Middleware generates IAS events that let the application know that the Alert Level characteristic has been updated with a new value. The event handler gets the new value and stores it in the variable alertLevel. The main loop toggles the alert LED based on the current alert level.

The code snippet shows how the firmware accomplishes this task.

void IasEventHandler(uint32_t event, void *eventParam)
{
    /* Alert Level Characteristic write event */
    if(event == CY_BLE_EVT_IASS_WRITE_CHAR_CMD)
    {
        /* Read the updated Alert Level value from the GATT database */
        Cy_BLE_IASS_GetCharacteristicValue(CY_BLE_IAS_ALERT_LEVEL, 
                                           sizeof(alertLevel), 
                                           &alertLevel);
    }
    
    (void) eventParam;
}

Implement Low-power Performance

In the application process, the CPU processes the pending BLE events. If there are no events pending, the CPU enters the deep sleep power mode.

/*******************************************************************************
* Function Name: LowPowerImplementation
********************************************************************************
* Summary: Implements low power in the project.
*
* Theory:
*  The function tries to enter CPU deep sleep as much as possible - whenever the
*  BLE is idle.
*
*******************************************************************************/
void LowPowerImplementation(void)
{
    /* Entering Deep Sleep */
    Cy_SysPm_DeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
}