2020TPC-SW/2020TPCApp0.cydsn/main_cm4.c
2025-02-01 19:52:04 -06:00

812 lines
31 KiB
C

/*******************************************************************************
* File Name: main_cm4.c
*
* Version: 1.30
*
* Description: This file provides the source code for the DFU (App0)
* running on the core CM4 (core1).
* App0 core1 firmware does the following:
* - Downloads App1 firmware image
* - Switches to App1 if App1 image has successfully downloaded
* and is valid
* - Switches to existing App1 if button is pressed
* - Turn on an LED depending on status
* - Hibernates on timeout
*******************************************************************************
* Related Document: CE216767.pdf
*
* Hardware Dependency: CY8CKIT-062-BLE PSoC 6 BLE Pioneer Kit
* CY5677 CySmart USB Dongle
*
******************************************************************************
* Copyright (2019), Cypress Semiconductor Corporation.
******************************************************************************
* This software is owned by Cypress Semiconductor Corporation (Cypress) and is
* protected by and subject to worldwide patent protection (United States and
* foreign), United States copyright laws and international treaty provisions.
* Cypress hereby grants to licensee a personal, non-exclusive, non-transferable
* license to copy, use, modify, create derivative works of, and compile the
* Cypress Source Code and derivative works for the sole purpose of creating
* custom software in support of licensee product to be used only in conjunction
* with a Cypress integrated circuit as specified in the applicable agreement.
* Any reproduction, modification, translation, compilation, or representation of
* this software except as specified above is prohibited without the express
* written permission of Cypress.
*
* Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH
* REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* Cypress reserves the right to make changes without further notice to the
* materials described herein. Cypress does not assume any liability arising out
* of the application or use of any product or circuit described herein. Cypress
* does not authorize its products for use as critical components in life-support
* systems where a malfunction or failure may reasonably be expected to result in
* significant injury to the user. The inclusion of Cypress' product in a life-
* support systems application implies that the manufacturer assumes all risk of
* such use and in doing so indemnifies Cypress against all charges. Use may be
* limited by and subject to the applicable Cypress software license agreement.
*******************************************************************************/
#include <string.h>
#include "project.h"
#include "debug.h"
#include "ias.h"
#include "transport_ble.h"
#if CY_DFU_OPT_CRYPTO_HW != 0
#define MY_CHAN_CRYPTO (uint32_t)(3u) /* IPC data channel for the Crypto */
#define MY_INTR_CRYPTO_SRV (uint32_t)(1u) /* IPC interrupt structure for the Crypto server */
#define MY_INTR_CRYPTO_CLI (uint32_t)(2u) /* IPC interrupt structure for the Crypto client */
#define MY_INTR_CRYPTO_SRV_MUX (IRQn_Type)(2u) /* CM0+ IPC interrupt mux number the Crypto server */
#define MY_INTR_CRYPTO_CLI_MUX (IRQn_Type)(3u) /* CM0+ IPC interrupt mux number the Crypto client */
#define MY_INTR_CRYPTO_ERR_MUX (IRQn_Type)(4u) /* CM0+ ERROR interrupt mux number the Crypto server */
const cy_stc_crypto_config_t cryptoConfig =
{
/* .ipcChannel */ MY_CHAN_CRYPTO,
/* .acquireNotifierChannel */ MY_INTR_CRYPTO_SRV,
/* .releaseNotifierChannel */ MY_INTR_CRYPTO_CLI,
/* .releaseNotifierConfig */ {
#if (CY_CPU_CORTEX_M0P)
/* .intrSrc */ MY_INTR_CRYPTO_CLI_MUX,
/* .cm0pSrc */ cpuss_interrupts_ipc_2_IRQn, /* depends on selected releaseNotifierChannel value */
#else
/* .intrSrc */ cpuss_interrupts_ipc_2_IRQn, /* depends on selected releaseNotifierChannel value */
#endif
/* .intrPriority */ 2u,
},
/* .userCompleteCallback */ NULL,
/* .userGetDataHandler */ NULL,
/* .userErrorHandler */ NULL,
/* .acquireNotifierConfig */ {
#if (CY_CPU_CORTEX_M0P)
/* .intrSrc */ MY_INTR_CRYPTO_SRV_MUX, /* to use with DeepSleep mode should be in DeepSleep capable muxer's range */
/* .cm0pSrc */ cpuss_interrupts_ipc_1_IRQn, /* depends on selected acquireNotifierChannel value */
#else
/* .intrSrc */ cpuss_interrupts_ipc_1_IRQn, /* depends on selected acquireNotifierChannel value */
#endif
/* .intrPriority */ 2u,
},
/* .cryptoErrorIntrConfig */ {
#if (CY_CPU_CORTEX_M0P)
/* .intrSrc */ MY_INTR_CRYPTO_ERR_MUX,
/* .cm0pSrc */ cpuss_interrupt_crypto_IRQn,
#else
/* .intrSrc */ cpuss_interrupt_crypto_IRQn,
#endif
/* .intrPriority */ 2u,
}
};
cy_stc_crypto_context_t cryptoContext;
cy_en_crypto_status_t cryptoStatus;
#endif
/* BLE GAPP Connection Settings */
#define CYBLE_GAPP_CONNECTION_INTERVAL_MIN (0x000Cu) /* 15 ms - (N * 1,25)*/
#define CYBLE_GAPP_CONNECTION_INTERVAL_MAX (0x000Cu) /* 15 ms */
#define CYBLE_GAPP_CONNECTION_SLAVE_LATENCY (0x0000u)
#define CYBLE_GAPP_CONNECTION_TIME_OUT (0x00C8u) /* 2000 ms */
/* BLE Callback function, defined in this file */
void AppCallBack(uint32 event, void* eventParam);
/* Local functions */
static cy_en_dfu_status_t CopyRow(uint32_t dest, uint32_t src, uint32_t rowSize, cy_stc_dfu_params_t * params);
static cy_en_dfu_status_t HandleMetadata(cy_stc_dfu_params_t *params);
static bool IsButtonPressed(uint16_t timeoutInMilis);
static uint32_t counterTimeoutSeconds(uint32_t seconds, uint32_t timeout);
/* This section is used to verify an application signature
For sha256 verification, set the number of elements in the array to 64, and
in bootload_common.ld set __cy_boot_signature_size = 256.
*/
CY_SECTION(".cy_app_signature") __USED static const uint32_t cy_bootload_appSignature[64];
/*******************************************************************************
* Function Name: main
********************************************************************************
*
* Summary:
* Main function of the DFU application (App0).
* 1. If application started from non-software reset it validates App1
* 1.1. If App1 is valid it switches to App1, else goto #2.
* 2. Start DFU communication.
* 3. If updated application has been received it validates this app.
* 4. If App1 is valid it switches to it, else wait for new application.
* 5. If 300 seconds have passed and no new application has been received
* then validate App1, if it is valid then switch to it, else hibernate
* (Happens in the BLE AppCallBack).
*
*******************************************************************************/
int main(void)
{
/* timeout for Cy_DFU_Continue(), in milliseconds */
const uint32_t paramsTimeout = 20u;
/* used to configure DFU */
static cy_stc_dfu_params_t dfuParams;
/* Status codes from DFU SDK API */
cy_en_dfu_status_t status;
/* SW2 released after deciding to stay in App0 */
bool buttonReleased = false;
/*
* DFU state, one of
* - CY_DFU_STATE_NONE
* - CY_DFU_STATE_UPDATING
* - CY_DFU_STATE_FINISHED
* - CY_DFU_STATE_FAILED
*/
uint32_t state = CY_DFU_STATE_NONE;
cy_en_ble_api_result_t apiResult;
cy_stc_ble_stack_lib_version_t stackVersion;
/*
* Used to count seconds, to convert counts to seconds use
* counterTimeoutSeconds(SECONDS, paramsTimeout)
*/
uint32_t count = 0;
uint32_t ledTimer = 0;
#if CY_DFU_OPT_CRYPTO_HW != 0
cy_en_crypto_status_t cryptoStatus;
#endif
/* Buffer to store DFU commands */
CY_ALIGN(4) static uint8_t buffer[CY_DFU_SIZEOF_DATA_BUFFER];
/* Buffer for DFU packets for Transport API */
CY_ALIGN(4) static uint8_t packet[CY_DFU_SIZEOF_CMD_BUFFER];
/* Enable global interrupts */
__enable_irq();
/* Start UART Services */
UART_START();
/* Initializes LEDs */
InitLED();
#if CY_DFU_OPT_CRYPTO_HW != 0
/* Initialize the Crypto Client code */
cryptoStatus = Cy_Crypto_Init(&cryptoConfig, &cryptoContext);
if (cryptoStatus != CY_CRYPTO_SUCCESS)
{
/* Crypto not initialized; debug what is the problem */
Cy_SysLib_Halt(0x00u);
}
cryptoStatus = Cy_Crypto_Enable();
if (cryptoStatus != CY_CRYPTO_SUCCESS)
{
/* Crypto not enabled; debug what is the problem */
Cy_SysLib_Halt(0x00u);
}
#endif /* CY_DFU_OPT_CRYPTO_HW != 0 */
/* Initialize dfuParams structure and DFU SDK state */
dfuParams.timeout = paramsTimeout;
dfuParams.dataBuffer = &buffer[0];
dfuParams.packetBuffer = &packet[0];
status = Cy_DFU_Init(&state, &dfuParams);
/* Ensure DFU Metadata is valid */
status = HandleMetadata(&dfuParams);
if (status != CY_DFU_SUCCESS)
{
Cy_SysLib_Halt(0x00u);
}
/*
* In the case of non-software reset and user does not
* want to stay in App0, check if there is a valid app image.
* If there is - switch to it.
*/
if ((Cy_SysLib_GetResetReason() != CY_SYSLIB_RESET_SOFT) && (IsButtonPressed(2000u) == false))
{
status = Cy_DFU_ValidateApp(1u, &dfuParams);
if (status == CY_DFU_SUCCESS)
{
/*
* Clear reset reason because Cy_DFU_ExecuteApp() performs
* a software reset.
* Without clearing two reset reasons would be present.
*/
do
{
Cy_SysLib_ClearResetReason();
}while(Cy_SysLib_GetResetReason() != 0);
/* Never returns */
Cy_DFU_ExecuteApp(1u);
}
}
/* Initialize DFU communication */
Cy_DFU_TransportStart();
/* Initializes the Immediate Alert Service */
IasInit();
/* Output current stack version to UART */
apiResult = Cy_BLE_GetStackLibraryVersion(&stackVersion);
if(apiResult != CY_BLE_SUCCESS)
{
DBG_PRINTF("CyBle_GetStackLibraryVersion API Error: 0x%2.2x \r\n", apiResult);
}
else
{
DBG_PRINTF("Stack Version: %d.%d.%d.%d \r\n", stackVersion.majorVersion,
stackVersion.minorVersion, stackVersion.patch, stackVersion.buildNumber);
}
for(;;)
{
/* CyBle_ProcessEvents() allows BLE stack to process pending events */
Cy_BLE_ProcessEvents();
/* Process DFU commands */
status = Cy_DFU_Continue(&state, &dfuParams);
++count;
switch(state)
{
case CY_DFU_STATE_FINISHED:
/* Finished downloading the application image */
/* Validate downloaded application, if it is valid then switch to it */
status = Cy_DFU_ValidateApp(1u, &dfuParams);
if (status == CY_DFU_SUCCESS)
{
Cy_DFU_TransportStop();
/*
* Clear reset reason because Cy_DFU_ExecuteApp() performs
* a software reset.
* Without clearing two reset reasons would be present.
*/
do
{
Cy_SysLib_ClearResetReason();
}while(Cy_SysLib_GetResetReason() != 0);
/* Never returns */
Cy_DFU_ExecuteApp(1u);
}
else if (status == CY_DFU_ERROR_VERIFY)
{
/*
* Restarts DFU, alternatives are to Halt MCU here
* or switch to the other app if it is valid.
* Error code may be handled here, i.e. print to debug UART.
*/
status = Cy_DFU_Init(&state, &dfuParams);
/* Reset LED */
ConnectedLED();
ledTimer = 0;
Cy_DFU_TransportReset();
}
break;
case CY_DFU_STATE_FAILED:
/* Handle error here */
DBG_PRINTF("Downloading has failed with error code 0x%x, try again\r\n", status);
/* In this Code Example just restart DFU process */
status = Cy_DFU_Init(&state, &dfuParams);
/* Reset LED */
ConnectedLED();
ledTimer = 0;
Cy_DFU_TransportReset();
break;
case CY_DFU_STATE_UPDATING:
/* Reset timeout counter, if a command was correctly received */
if (status == CY_DFU_SUCCESS)
{
count = 0u;
}
else if (status == CY_DFU_ERROR_TIMEOUT)
{
/*
* if no command has been received during 5 seconds when DFU
* has started then restart DFU.
*/
if (count >= counterTimeoutSeconds(5u, paramsTimeout))
{
count = 0u;
Cy_DFU_Init(&state, &dfuParams);
/* Reset LED */
ConnectedLED();
ledTimer = 0;
Cy_DFU_TransportReset();
}
}
else
{
count = 0u;
/* Delay because Transport still may be sending error response to a host */
Cy_SysLib_Delay(paramsTimeout);
Cy_DFU_Init(&state, &dfuParams);
Cy_DFU_TransportReset();
}
break;
}
/* LED logic, constant values are optimized out. */
/* Reset timer after 2 seconds */
if(ledTimer == (2000u / paramsTimeout)) ledTimer = 0;
/* Every 100 miliseconds */
if(!(ledTimer % (100u / paramsTimeout)))
{
/* Generates two 100 miliseconds pulses, every 2 seconds */
if((state == CY_DFU_STATE_UPDATING) && (ledTimer < (400u / paramsTimeout)))
{
BlinkLED();
}
/* Generates one 100 miliseconds pulse, every 2 seconds */
else if ((Cy_BLE_GetAdvertisementState() == CY_BLE_ADV_STATE_ADVERTISING)
&& (ledTimer < (200u / paramsTimeout)))
{
BlinkLED();
}
else
{
/* Remain OFF */
ConnectedLED();
}
}
++ledTimer;
/* Check if a switch to the other app is requested and perform the switch if it is */
if((buttonReleased == true) && (state == CY_DFU_STATE_NONE))
{
bool switchRequested = false;
if (alertLevel != 0)
{
switchRequested = true;
}
else if(IsButtonPressed(500u) == true)
{
switchRequested = true;
buttonReleased = false;
}
if (switchRequested)
{
/* Validate and switch to App1 */
cy_en_dfu_status_t status = Cy_DFU_ValidateApp(1u, &dfuParams);
if (status == CY_DFU_SUCCESS)
{
Cy_DFU_TransportStop();
/*
* Clear reset reason because Cy_DFU_ExecuteApp() performs
* a software reset.
* Without clearing two reset reasons would be present.
*/
do
{
Cy_SysLib_ClearResetReason();
}while(Cy_SysLib_GetResetReason() != 0);
/* Never returns */
Cy_DFU_ExecuteApp(1u);
}
}
}
else
{
buttonReleased = Cy_GPIO_Read(PIN_SW2_PORT, PIN_SW2_NUM);
}
}
}
/*******************************************************************************
* Function Name: IsButtonPressed
********************************************************************************
* Checks if button is pressed for a 'timeoutInMilis' time.
*
* Params:
* timeout: Amount of time to check if button was pressed. Broken into
* 20 miliseconds steps.
* Returns:
* true if button is pressed for specified amount.
* false otherwise.
*******************************************************************************/
static bool IsButtonPressed(uint16_t timeoutInMilis)
{
uint16_t buttonTime = 0;
bool buttonPressed = false;
timeoutInMilis /= 20;
while(Cy_GPIO_Read(PIN_SW2_PORT, PIN_SW2_NUM) == 0u)
{
Cy_SysLib_Delay(20u);
if(++buttonTime == timeoutInMilis)
{
/* time has passed */
buttonPressed = true;
break;
}
}
return buttonPressed;
}
/*******************************************************************************
* Function Name: counterTimeoutSeconds
********************************************************************************
* Returns number of counts that correspond to number of seconds passed as
* a parameter.
* E.g. comparing counter with 300 seconds is like this.
* ---
* uint32_t counter = 0u;
* for (;;)
* {
* Cy_SysLib_Delay(UART_TIMEOUT);
* ++count;
* if (count >= counterTimeoutSeconds(seconds: 300u, timeout: UART_TIMEOUT))
* {
* count = 0u;
* DoSomething();
* }
* }
* ---
*
* Both parameters are required to be compile time constants,
* so this function gets optimized out to single constant value.
*
* Parameters:
* seconds Number of seconds to pass. Must be less that 4_294_967 seconds.
* timeout Timeout for Cy_DFU_Continue() function, in milliseconds.
* Must be greater than zero.
* It is recommended to be a value that produces no reminder
* for this function to be precise.
* Return:
* See description.
*******************************************************************************/
static uint32_t counterTimeoutSeconds(uint32_t seconds, uint32_t timeout)
{
return (seconds * 1000ul) / timeout;
}
/*******************************************************************************
* Function Name: CopyRow
********************************************************************************
* Copies data from a "src" address to a flash row with the address "dest".
* If "src" data is the same as "dest" data then no copy is needed.
*
* Parameters:
* dest Destination address. Has to be an address of the start of flash row.
* src Source address. Has to be properly aligned.
* rowSize Size of flash row.
*
* Returns:
* CY_DFU_SUCCESS if operation is successful.
* Error code in a case of failure.
*******************************************************************************/
static cy_en_dfu_status_t CopyRow(uint32_t dest, uint32_t src, uint32_t rowSize, cy_stc_dfu_params_t * params)
{
cy_en_dfu_status_t status;
/* Save params->dataBuffer value */
uint8_t *buffer = params->dataBuffer;
/* Compare "dest" and "src" content */
params->dataBuffer = (uint8_t *)src;
status = Cy_DFU_ReadData(dest, rowSize, CY_DFU_IOCTL_COMPARE, params);
/* Restore params->dataBuffer */
params->dataBuffer = buffer;
/* If "dest" differs from "src" then copy "src" to "dest" */
if (status != CY_DFU_SUCCESS)
{
(void) memcpy((void *) params->dataBuffer, (const void*)src, rowSize);
status = Cy_DFU_WriteData(dest, rowSize, CY_DFU_IOCTL_WRITE, params);
}
/* Restore params->dataBuffer */
params->dataBuffer = buffer;
return (status);
}
/*******************************************************************************
* Function Name: HandleMetadata
********************************************************************************
* The goal of this function is to make DFU SDK metadata (MD) valid.
* The following algorithm is used (in C-like pseudocode):
* ---
* if (isValid(MD) == true)
* { if (MDC != MD)
* MDC = MD;
* } else
* { if(isValid(MDC) )
* MD = MDC;
* #if MD Writeable
* else
* MD = INITIAL_VALUE;
* #endif
* }
* ---
* Here MD is metadata flash row, MDC is flash row with metadata copy,
* INITIAL_VALUE is known initial value.
*
* In this code example MDC is placed in the next flash row after the MD, and
* INITIAL_VALUE is MD with only CRC, App0 start and size initialized,
* all the other fields are not touched. This is only done if metadata is
* writeable when downloading.
*
* Parameters:
* params A pointer to a DFU SDK parameters structure.
*
* Returns:
* - CY_DFU_SUCCESS when finished normally.
* - Any other status code on error.
*******************************************************************************/
static cy_en_dfu_status_t HandleMetadata(cy_stc_dfu_params_t *params)
{
const uint32_t MD = (uint32_t)(&__cy_boot_metadata_addr ); /* MD address */
const uint32_t mdSize = (uint32_t)(&__cy_boot_metadata_length ); /* MD size, assumed to be one flash row */
const uint32_t MDC = MD + mdSize; /* MDC address */
cy_en_dfu_status_t status = CY_DFU_SUCCESS;
status = Cy_DFU_ValidateMetadata(MD, params);
if (status == CY_DFU_SUCCESS)
{
/* Checks if MDC equals to DC, if no then copies MD to MDC */
status = CopyRow(MDC, MD, mdSize, params);
}
else
{
status = Cy_DFU_ValidateMetadata(MDC, params);
if (status == CY_DFU_SUCCESS)
{
/* Copy MDC to MD */
status = CopyRow(MD, MDC, mdSize, params);
}
#if CY_DFU_METADATA_WRITABLE != 0
if (status != CY_DFU_SUCCESS)
{
const uint32_t elfStartAddress = 0x10000000;
const uint32_t elfAppSize = 0x40000;
/* Set MD to INITIAL_VALUE */
status = Cy_DFU_SetAppMetadata(0u, elfStartAddress, elfAppSize, params);
}
#endif /* CY_DFU_METADATA_WRITABLE != 0 */
}
return (status);
}
/*******************************************************************************
* Function Name: AppCallBack()
********************************************************************************
*
* Summary:
* This is an event callback function to receive events from the BLE Component.
* Used in Cy_DFU_TransportStart()
*
* event - the event code
* *eventParam - the event parameters
*
*******************************************************************************/
void AppCallBack(uint32 event, void* eventParam)
{
cy_en_ble_api_result_t apiResult;
static cy_stc_ble_gap_sec_key_info_t keyInfo =
{
.localKeysFlag = CY_BLE_GAP_SMP_INIT_ENC_KEY_DIST |
CY_BLE_GAP_SMP_INIT_IRK_KEY_DIST |
CY_BLE_GAP_SMP_INIT_CSRK_KEY_DIST,
.exchangeKeysFlag = CY_BLE_GAP_SMP_INIT_ENC_KEY_DIST |
CY_BLE_GAP_SMP_INIT_IRK_KEY_DIST |
CY_BLE_GAP_SMP_INIT_CSRK_KEY_DIST |
CY_BLE_GAP_SMP_RESP_ENC_KEY_DIST |
CY_BLE_GAP_SMP_RESP_IRK_KEY_DIST |
CY_BLE_GAP_SMP_RESP_CSRK_KEY_DIST,
};
switch (event)
{
/**********************************************************
* General Events
***********************************************************/
/* This event received when BLE communication starts */
case CY_BLE_EVT_STACK_ON:
/* Enter into discoverable mode so that remote can search it. */
apiResult = Cy_BLE_GAPP_StartAdvertisement(CY_BLE_ADVERTISING_FAST, 0u);
if(apiResult != CY_BLE_SUCCESS)
{
}
apiResult = Cy_BLE_GAP_GenerateKeys(&keyInfo);
if(apiResult != CY_BLE_SUCCESS)
{
DBG_PRINTF("CyBle_GapGenerateKeys API Error: %d \r\n", apiResult);
}
break;
/* This event indicates that some internal HW error has occurred. */
case CY_BLE_EVT_HARDWARE_ERROR:
DBG_PRINTF("CYBLE_EVT_HARDWARE_ERROR\r\n");
break;
/**********************************************************
* GAP Events
***********************************************************/
case CY_BLE_EVT_GAP_AUTH_REQ:
DBG_PRINTF("CYBLE_EVT_AUTH_REQ: security=%x, bonding=%x, ekeySize=%x, err=%x \r\n",
(*(cy_stc_ble_gap_auth_info_t *)eventParam).security,
(*(cy_stc_ble_gap_auth_info_t *)eventParam).bonding,
(*(cy_stc_ble_gap_auth_info_t*)eventParam).ekeySize,
(*(cy_stc_ble_gap_auth_info_t *)eventParam).authErr );
if ( cy_ble_configPtr->authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX].security
== (CY_BLE_GAP_SEC_MODE_1 | CY_BLE_GAP_SEC_LEVEL_1) )
{
cy_ble_configPtr->authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX].authErr =
CY_BLE_GAP_AUTH_ERROR_PAIRING_NOT_SUPPORTED;
}
cy_ble_configPtr->authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX].bdHandle =
((cy_stc_ble_gap_auth_info_t *)eventParam)->bdHandle;
apiResult = Cy_BLE_GAPP_AuthReqReply(&cy_ble_configPtr->authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX]);
if(apiResult != CY_BLE_SUCCESS)
{
Cy_BLE_GAP_RemoveOldestDeviceFromBondedList();
apiResult = Cy_BLE_GAPP_AuthReqReply(&cy_ble_configPtr->authInfo[CY_BLE_SECURITY_CONFIGURATION_0_INDEX]);
if(apiResult != CY_BLE_SUCCESS)
{
DBG_PRINTF("CyBle_GappAuthReqReply API Error: %d \r\n", apiResult);
}
}
break;
case CY_BLE_EVT_GAP_PASSKEY_ENTRY_REQUEST:
DBG_PRINTF("CYBLE_EVT_PASSKEY_ENTRY_REQUEST press 'p' to enter passkey \r\n");
break;
case CY_BLE_EVT_GAP_PASSKEY_DISPLAY_REQUEST:
DBG_PRINTF("CYBLE_EVT_PASSKEY_DISPLAY_REQUEST %6.6d \r\n", *(int *)eventParam);
break;
case CY_BLE_EVT_GAP_KEYINFO_EXCHNGE_CMPLT:
DBG_PRINTF("CYBLE_EVT_GAP_KEYINFO_EXCHNGE_CMPLT \r\n");
break;
case CY_BLE_EVT_GAP_AUTH_COMPLETE:
DBG_PRINTF("AUTH_COMPLETE \r\n");
break;
case CY_BLE_EVT_GAP_AUTH_FAILED:
DBG_PRINTF("CYBLE_EVT_AUTH_FAILED: %x \r\n", *(uint8 *)eventParam);
break;
case CY_BLE_EVT_GAP_DEVICE_CONNECTED:
DBG_PRINTF("CYBLE_EVT_GAP_DEVICE_CONNECTED: %d \r\n", appConnHandle.bdHandle);
if ( ((*(cy_stc_ble_gap_connected_param_t *)eventParam).connIntv
< CYBLE_GAPP_CONNECTION_INTERVAL_MIN ) || (
(*(cy_stc_ble_gap_connected_param_t *)eventParam).connIntv
> CYBLE_GAPP_CONNECTION_INTERVAL_MAX ) )
{
cy_stc_ble_gap_conn_update_param_info_t connUpdateParam;
/* If connection settings do not match expected ones - request parameter update */
connUpdateParam.connIntvMin = CYBLE_GAPP_CONNECTION_INTERVAL_MIN;
connUpdateParam.connIntvMax = CYBLE_GAPP_CONNECTION_INTERVAL_MAX;
connUpdateParam.connLatency = CYBLE_GAPP_CONNECTION_SLAVE_LATENCY;
connUpdateParam.supervisionTO = CYBLE_GAPP_CONNECTION_TIME_OUT;
connUpdateParam.bdHandle = appConnHandle.bdHandle;
apiResult = Cy_BLE_L2CAP_LeConnectionParamUpdateRequest(&connUpdateParam);
DBG_PRINTF("Cy_BLE_L2CAP_LeConnectionParamUpdateRequest API: 0x%2.2x \r\n", apiResult);
}
keyInfo.SecKeyParam.bdHandle = (*(cy_stc_ble_gap_connected_param_t *)eventParam).bdHandle;
apiResult = Cy_BLE_GAP_SetSecurityKeys(&keyInfo);
if(apiResult != CY_BLE_SUCCESS)
{
DBG_PRINTF("CyBle_GapSetSecurityKeys API Error: %d \r\n", apiResult);
}
break;
case CY_BLE_EVT_L2CAP_CONN_PARAM_UPDATE_RSP:
DBG_PRINTF("CY_BLE_EVT_L2CAP_CONN_PARAM_UPDATE_RSP, result = %d\r\n",
(*(cy_stc_ble_l2cap_conn_update_rsp_param_t *)eventParam).result);
break;
case CY_BLE_EVT_GAP_KEYS_GEN_COMPLETE:
DBG_PRINTF("CYBLE_EVT_GAP_KEYS_GEN_COMPLETE \r\n");
keyInfo.SecKeyParam = (*(cy_stc_ble_gap_sec_key_param_t *)eventParam);
Cy_BLE_GAP_SetIdAddress(&cy_ble_deviceAddress);
break;
case CY_BLE_EVT_GAP_DEVICE_DISCONNECTED:
DBG_PRINTF("CYBLE_EVT_GAP_DEVICE_DISCONNECTED\r\n");
/* Put the device into discoverable mode so that a remote can search it. */
apiResult = Cy_BLE_GAPP_StartAdvertisement(CY_BLE_ADVERTISING_FAST, CY_BLE_PERIPHERAL_CONFIGURATION_0_INDEX);
if(apiResult != CY_BLE_SUCCESS)
{
DBG_PRINTF("StartAdvertisement API Error: %d \r\n", apiResult);
}
break;
case CY_BLE_EVT_GAP_ENCRYPT_CHANGE:
DBG_PRINTF("CYBLE_EVT_GAP_ENCRYPT_CHANGE: %x \r\n", *(uint8 *)eventParam);
break;
case CY_BLE_EVT_GAP_CONNECTION_UPDATE_COMPLETE:
DBG_PRINTF("CYBLE_EVT_CONNECTION_UPDATE_COMPLETE: %x \r\n", *(uint8 *)eventParam);
break;
case CY_BLE_EVT_GAPP_ADVERTISEMENT_START_STOP:
if(Cy_BLE_GetAdvertisementState() == CY_BLE_ADV_STATE_STOPPED)
{
/* Fast and slow advertising period complete, go to low power
* mode (Hibernate mode) and wait for an external
* user event to wake up the device again */
/* Stop DFU communication */
Cy_DFU_TransportStop();
/* Check if app is valid, if it is then switch to it */
uint32_t status = Cy_DFU_ValidateApp(1u, NULL);
if (status == CY_DFU_SUCCESS)
{
/*
* Clear reset reason because Cy_DFU_ExecuteApp() performs
* a software reset.
* Without clearing two reset reasons would be present.
*/
do
{
Cy_SysLib_ClearResetReason();
}while(Cy_SysLib_GetResetReason() != 0);
/* Never returns */
Cy_DFU_ExecuteApp(1u);
}
/* 300 seconds has passed and App is invalid. Hibernate */
HibernateLED();
Cy_SysPm_Hibernate();
}
break;
/**********************************************************
* GATT Events
***********************************************************/
case CY_BLE_EVT_GATT_CONNECT_IND:
appConnHandle = *(cy_stc_ble_conn_handle_t *)eventParam;
DBG_PRINTF("CYBLE_EVT_GATT_CONNECT_IND: %d \r\n", appConnHandle.bdHandle);
break;
case CY_BLE_EVT_GATT_DISCONNECT_IND:
DBG_PRINTF("CYBLE_EVT_GATT_DISCONNECT_IND: %d \r\n", ((cy_stc_ble_conn_handle_t *)eventParam)->bdHandle);
break;
case CY_BLE_EVT_GATTS_WRITE_CMD_REQ:
DBG_PRINTF("CYBLE_EVT_GATTS_WRITE_CMD_REQ\r\n");
break;
default:
break;
}
}
/* [] END OF FILE */