/*******************************************************************************
* File Name: main_cm0p.c
*
* Version: 1.30
*
* Description: This file provides the source code for the DFU (App0)
*              running on the core CM0+ (core0).
*              App0 core0 firmware does the following:
*              - Switches to the App1 on reset if it was scheduled.
*              - Else starts App0 core1 firmware.
*
* Related Document: Code example 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 "dfu/cy_dfu.h"
#include "project.h"
#include "cy_si_config.h"

/*
* Set this define to any value different than 0, to use a standard TOC2, 
* erase the public key, and enable the device to run code generated by other projects.
*/
#define UNLOCK_SYSTEM   (1u)

#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_server_context_t  cryptoServerContext;
    cy_en_crypto_status_t           cryptoStatus;
#endif

#if UNLOCK_SYSTEM == (0u)
/* Flashboot parameters */
#define CY_SI_FLASHBOOT_FLAGS ((CY_SI_FLASHBOOT_VALIDATE_YES << CY_SI_TOC_FLAGS_APP_VERIFY_POS) \
                                | (CY_SI_FLASHBOOT_WAIT_20MS << CY_SI_TOC_FLAGS_DELAY_POS) \
                                | (CY_SI_FLASHBOOT_CLK_25MHZ << CY_SI_TOC_FLAGS_CLOCKS_POS))

/* TOC Part 2 Definition */
CY_SECTION(".cy_toc_part2") __USED
const cy_stc_si_toc_t cy_toc2 =
{
    .objSize        = sizeof(cy_stc_si_toc_t) - sizeof(uint32_t),   /**< Object Size (Bytes) excluding CRC */
    .magicNum       = CY_SI_TOC2_MAGICNUMBER,                       /**< TOC2 ID (magic number) */
    .userKeyAddr    = (uint32_t) &CySecureKeyStorage,               /**< User key storage address */
    .smifCfgAddr    = 0UL,                                          /**< SMIF config list pointer */
    .appAddr1       = CY_DFU_APP0_VERIFY_START,                     /**< App0 start address */
    .appFormat1     = CY_DFU_CYPRESS_APP,                           /**< App0 Format */
    .shashObj       = 1UL,                                          /**< Include public key in the SECURE HASH */
    .sigKeyAddr     = (uint32_t)&SFLASH->PUBLIC_KEY,                /**< Address of signature verification key */
    .tocFlags       = CY_SI_FLASHBOOT_FLAGS,                        /**< Flashboot flags stored in TOC2 */
    .crc            = 0UL,                                          /**< CRC populated by cymcuelftool */
};

/* Assuming App0 is located at start of flash, change define if different */
#define APP0_START_ADDRESS  CY_FLASH_BASE

/* Cypress Standard Application Format Header */
CY_SECTION(".cy_app_header") __USED
const cy_stc_user_appheader_t applicationHeader =
{
    .objSize        = CY_DFU_APP0_VERIFY_LENGTH,        /* Application Size (Bytes) excluding hash */
    .appId          = CY_SI_APP_VERSION,                /* App ID */
    .appAttributes  = 0UL,                              /* Reserved */
    .numCores       = 2UL,                              /* CM0+ and CM4 */
    .core0Vt        = (uint32_t)(&__Vectors[0]) - APP0_START_ADDRESS - offsetof(cy_stc_user_appheader_t, core0Vt),               /* Offset to CM0+ Vector Table in flash */
    .core1Vt        = (uint32_t)(&__cy_app_core1_start_addr) - APP0_START_ADDRESS - offsetof(cy_stc_user_appheader_t, core1Vt),  /* Offset to CM4 Vector Table in flash */
    .core0Id        = CY_ARM_CM0P_CPUID,                /* ARM CM0+ CPU ID */
    .core1Id        = CY_ARM_CM4_CPUID,                 /* ARM CM4 CPU ID */
};
#endif /* UNLOCK_SYSTEM == (0u) */

#if UNLOCK_SYSTEM != (0u)
/* Flashboot parameters */
#define CY_SI_FLASHBOOT_FLAGS ((CY_SI_FLASHBOOT_VALIDATE_NO << CY_SI_TOC_FLAGS_APP_VERIFY_POS) \
                                | (CY_SI_FLASHBOOT_WAIT_20MS << CY_SI_TOC_FLAGS_DELAY_POS) \
                                | (CY_SI_FLASHBOOT_CLK_25MHZ << CY_SI_TOC_FLAGS_CLOCKS_POS))

/* Standard TOC Part 2 Definition */
CY_SECTION(".cy_toc_part2") __USED
const cy_stc_si_toc_t cy_toc2 =
{
    .objSize        = sizeof(cy_stc_si_toc_t) - sizeof(uint32_t),   /**< Object Size (Bytes) excluding CRC */
    .magicNum       = CY_SI_TOC2_MAGICNUMBER,                       /**< TOC2 ID (magic number) */
    .userKeyAddr    = 0UL,							                /**< User key storage address */
    .smifCfgAddr    = 0UL,                                          /**< SMIF config list pointer */
    .appAddr1       = CY_FLASH_BASE,                				/**< Main Flash base address */
    .appFormat1     = CY_DFU_BASIC_APP,                          	/**< Basic format */
    .shashObj       = 0UL,                                          
    .sigKeyAddr     = 0UL,                							/**< Address of signature verification key */
    .tocFlags       = CY_SI_FLASHBOOT_FLAGS,                        /**< Flashboot flags stored in TOC2 */
    .crc            = 0UL,                                          /**< CRC populated by cymcuelftool */
};
#endif /* UNLOCK_SYSTEM != 0UL */

/*******************************************************************************
* Function Name: main
********************************************************************************
*
* Summary:
*  Main function of App0 core0. Unfreezes IO and sets up the user button (SW2)
*  as the hibernate wakeup source. Afterwards initializes core1 (CM4) and goes 
*  into deep sleep.
*
* Parameters:
*  None
* 
* Return:
*  None
*
*******************************************************************************/
int main(void)
{
    /* Unfreeze IO after Hibernate */
    if(Cy_SysPm_GetIoFreezeStatus())
    {
        Cy_SysPm_IoUnfreeze();
    }
    /* Set SW2 as hibernate wakeup pin */
    Cy_SysPm_SetHibWakeupSource(CY_SYSPM_HIBPIN1_LOW);
    
    /* enable global interrupts */
    __enable_irq();
    
#if CY_DFU_OPT_CRYPTO_HW != 0
    /* Start the Crypto Server */
    Cy_Crypto_Server_Start(&cryptoConfig, &cryptoServerContext);
#endif

    /* Enable CM4 with the CM4 start address defined in the
       DFU SDK linker script */
    Cy_SysEnableCM4( (uint32_t)(&__cy_app_core1_start_addr) );

    for (;;)
    {
        /* Process crypto server requests */
        Cy_Crypto_Server_Process();
        //Go into Deep Sleep
        Cy_SysPm_DeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
    }
}

/*******************************************************************************
* Function Name: Cy_OnResetUser
********************************************************************************
*
* Summary:
*  This function is called at the start of Reset_Handler(). It is a weak function
*  that may be redefined by user code.
*  DFU SDK requires it to call Cy_DFU_OnResetApp0().
*  Checks if an App switch has been scheduled and transfers control to it.
*
* Parameters:
*  None
*
* Return:
*  None
*
*******************************************************************************/
void Cy_OnResetUser(void)
{
    Cy_DFU_OnResetApp0();
}

/* [] END OF FILE */
