Initial public release.
This commit is contained in:
parent
7b169e8116
commit
dac4af8d25
255 changed files with 68595 additions and 2 deletions
812
2020TPCApp0.cydsn/main_cm4.c
Normal file
812
2020TPCApp0.cydsn/main_cm4.c
Normal file
|
@ -0,0 +1,812 @@
|
|||
/*******************************************************************************
|
||||
* 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 */
|
Loading…
Add table
Add a link
Reference in a new issue