| /***************************************************************************//** |
| * \file cy_flash.c |
| * \version 3.20 |
| * |
| * \brief |
| * Provides the public functions for the API for the PSoC 6 Flash Driver. |
| * |
| ******************************************************************************** |
| * \copyright |
| * Copyright 2016-2018, Cypress Semiconductor Corporation. All rights reserved. |
| * SPDX-License-Identifier: Apache-2.0 |
| |
| |
| |
| *******************************************************************************/ |
| #include "cy_flash.h" |
| #include "cy_sysclk.h" |
| #include "cy_sysint.h" |
| #include "cy_ipc_drv.h" |
| #include "cy_ipc_sema.h" |
| #include "cy_ipc_pipe.h" |
| #include "cy_device.h" |
| |
| |
| /*************************************** |
| * Data Structure definitions |
| ***************************************/ |
| |
| /* Flash driver context */ |
| typedef struct |
| { |
| uint32_t opcode; /**< Specifies the code of flash operation */ |
| uint32_t arg1; /**< Specifies the configuration of flash operation */ |
| uint32_t arg2; /**< Specifies the configuration of flash operation */ |
| uint32_t arg3; /**< Specifies the configuration of flash operation */ |
| } cy_stc_flash_context_t; |
| |
| |
| /*************************************** |
| * Macro definitions |
| ***************************************/ |
| |
| /** \cond INTERNAL */ |
| /** Set SROM API in blocking mode */ |
| #define CY_FLASH_BLOCKING_MODE ((0x01UL) << 8UL) |
| /** Set SROM API in non blocking mode */ |
| #define CY_FLASH_NON_BLOCKING_MODE (0UL) |
| |
| /** SROM API flash region ID shift for flash row information */ |
| #define CY_FLASH_REGION_ID_SHIFT (16U) |
| #define CY_FLASH_REGION_ID_MASK (3U) |
| #define CY_FLASH_ROW_ID_MASK (0xFFFFU) |
| /** SROM API flash region IDs */ |
| #define CY_FLASH_REGION_ID_MAIN (0UL) |
| #define CY_FLASH_REGION_ID_EM_EEPROM (1UL) |
| #define CY_FLASH_REGION_ID_SFLASH (2UL) |
| |
| /** SROM API opcode mask */ |
| #define CY_FLASH_OPCODE_Msk ((0xFFUL) << 24UL) |
| /** SROM API opcode for flash write operation */ |
| #define CY_FLASH_OPCODE_WRITE_ROW ((0x05UL) << 24UL) |
| /** SROM API opcode for flash program operation */ |
| #define CY_FLASH_OPCODE_PROGRAM_ROW ((0x06UL) << 24UL) |
| /** SROM API opcode for row erase operation */ |
| #define CY_FLASH_OPCODE_ERASE_ROW ((0x1CUL) << 24UL) |
| /** SROM API opcode for flash checksum operation */ |
| #define CY_FLASH_OPCODE_CHECKSUM ((0x0BUL) << 24UL) |
| /** SROM API opcode for flash hash operation */ |
| #define CY_FLASH_OPCODE_HASH ((0x0DUL) << 24UL) |
| /** SROM API flash row shift for flash checksum operation */ |
| #define CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT (8UL) |
| /** SROM API flash row shift for flash checksum operation */ |
| #define CY_FLASH_OPCODE_CHECKSUM_REGION_SHIFT (22UL) |
| /** SROM API flash data size parameter for flash write operation */ |
| #define CY_FLASH_CONFIG_DATASIZE (CPUSS_FLASHC_PA_SIZE_LOG2 - 1UL) |
| /** Data to be programmed to flash is located in SRAM memory region */ |
| #define CY_FLASH_DATA_LOC_SRAM (0x100UL) |
| /** SROM API flash verification option for flash write operation */ |
| #define CY_FLASH_CONFIG_VERIFICATION_EN ((0x01UL) << 16u) |
| |
| /** Command completed with no errors */ |
| #define CY_FLASH_ROMCODE_SUCCESS (0xA0000000UL) |
| /** Invalid device protection state */ |
| #define CY_FLASH_ROMCODE_INVALID_PROTECTION (0xF0000001UL) |
| /** Invalid flash page latch address */ |
| #define CY_FLASH_ROMCODE_INVALID_FM_PL (0xF0000003UL) |
| /** Invalid flash address */ |
| #define CY_FLASH_ROMCODE_INVALID_FLASH_ADDR (0xF0000004UL) |
| /** Row is write protected */ |
| #define CY_FLASH_ROMCODE_ROW_PROTECTED (0xF0000005UL) |
| /** Comparison between Page Latches and FM row failed */ |
| #define CY_FLASH_ROMCODE_PL_ROW_COMP_FA (0xF0000022UL) |
| /** Command in progress; no error */ |
| #define CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR (0xA0000009UL) |
| /** Flash operation is successfully initiated */ |
| #define CY_FLASH_IS_OPERATION_STARTED (0x00000010UL) |
| /** Flash is under operation */ |
| #define CY_FLASH_IS_BUSY (0x00000040UL) |
| /** IPC structure is already locked by another process */ |
| #define CY_FLASH_IS_IPC_BUSY (0x00000080UL) |
| /** Input parameters passed to Flash API are not valid */ |
| #define CY_FLASH_IS_INVALID_INPUT_PARAMETERS (0x00000100UL) |
| |
| /** Result mask */ |
| #define CY_FLASH_RESULT_MASK (0x0FFFFFFFUL) |
| /** Error shift */ |
| #define CY_FLASH_ERROR_SHIFT (28UL) |
| /** No error */ |
| #define CY_FLASH_ERROR_NO_ERROR (0xAUL) |
| |
| /** CM4 Flash Proxy address */ |
| #define CY_FLASH_CM4_FLASH_PROXY_ADDR (*(Cy_Flash_Proxy *)(0x00000D1CUL)) |
| typedef cy_en_flashdrv_status_t (*Cy_Flash_Proxy)(cy_stc_flash_context_t *context); |
| |
| /** IPC notify bit for IPC_STRUCT0 (dedicated to flash operation) */ |
| #define CY_FLASH_IPC_NOTIFY_STRUCT0 (0x1UL << CY_IPC_INTR_SYSCALL1) |
| |
| /** Disable delay */ |
| #define CY_FLASH_NO_DELAY (0U) |
| |
| #if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) |
| /** Number of ticks to wait 1 uS */ |
| #define CY_FLASH_TICKS_FOR_1US (8U) |
| /** Slow control register */ |
| #define CY_FLASH_TST_DDFT_SLOW_CTL_REG (*(reg32 *) 0x40260108U) |
| /** Slow control register */ |
| #define CY_FLASH_TST_DDFT_FAST_CTL_REG (*(reg32 *) 0x40260104U) |
| /** Define to set the IMO to perform a delay after the flash operation started */ |
| #define CY_FLASH_TST_DDFT_SLOW_CTL_MASK (0x00001F1EUL) |
| /** Fast control register */ |
| #define CY_FLASH_TST_DDFT_FAST_CTL_MASK (62U) |
| /** Slow output register - output disabled */ |
| #define CY_FLASH_CLK_OUTPUT_DISABLED (0U) |
| |
| /* The default delay time value */ |
| #define CY_FLASH_DEFAULT_DELAY (150UL) |
| /* Calculates the time in microseconds to wait for the number of the CM0P ticks */ |
| #define CY_FLASH_DELAY_CORRECTIVE(ticks) ((((uint32)Cy_SysClk_ClkPeriGetDivider() + 1UL) * \ |
| (Cy_SysClk_ClkSlowGetDivider() + 1UL) * (ticks) * 1000UL)\ |
| / ((uint32_t)cy_Hfclk0FreqHz / 1000UL)) |
| |
| /* Number of the CM0P ticks for StartProgram function delay corrective time */ |
| #define CY_FLASH_START_PROGRAM_DELAY_TICKS (6000UL) |
| /* Delay time for StartProgram function in us */ |
| #define CY_FLASH_START_PROGRAM_DELAY_TIME (900UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_DELAY_TICKS)) |
| /* Number of the CM0P ticks for StartErase function delay corrective time */ |
| #define CY_FLASH_START_ERASE_DELAY_TICKS (9500UL) |
| /* Delay time for StartErase function in us */ |
| #define CY_FLASH_START_ERASE_DELAY_TIME (2200UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_ERASE_DELAY_TICKS)) |
| /* Number of the CM0P ticks for StartWrite function delay corrective time */ |
| #define CY_FLASH_START_WRITE_DELAY_TICKS (19000UL) |
| /* Delay time for StartWrite function in us */ |
| #define CY_FLASH_START_WRITE_DELAY_TIME (9800UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_WRITE_DELAY_TICKS)) |
| |
| /** Delay time for Start Write function in us with corrective time */ |
| #define CY_FLASH_START_WRITE_DELAY (CY_FLASH_START_WRITE_DELAY_TIME) |
| /** Delay time for Start Program function in us with corrective time */ |
| #define CY_FLASH_START_PROGRAM_DELAY (CY_FLASH_START_PROGRAM_DELAY_TIME) |
| /** Delay time for Start Erase function in uS with corrective time */ |
| #define CY_FLASH_START_ERASE_DELAY (CY_FLASH_START_ERASE_DELAY_TIME) |
| |
| #define CY_FLASH_ENTER_WAIT_LOOP (0xFFU) |
| #define CY_FLASH_IPC_CLIENT_ID (2U) |
| |
| /** Semaphore number reserved for flash driver */ |
| #define CY_FLASH_WAIT_SEMA (0UL) |
| /* Semaphore check timeout (in tries) */ |
| #define CY_FLASH_SEMA_WAIT_MAX_TRIES (150000UL) |
| |
| typedef struct |
| { |
| uint8_t clientID; |
| uint8_t pktType; |
| uint16_t intrRelMask; |
| } cy_flash_notify_t; |
| |
| static void Cy_Flash_RAMDelay(uint32_t microseconds); |
| |
| #if (CY_CPU_CORTEX_M0P) |
| #define IS_CY_PIPE_FREE(...) (!Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP1))) |
| #define NOTIFY_PEER_CORE(a) Cy_IPC_Pipe_SendMessage(CY_IPC_EP_CYPIPE_CM4_ADDR, CY_IPC_EP_CYPIPE_CM0_ADDR, (a), NULL) |
| #else |
| #define IS_CY_PIPE_FREE(...) (!Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP0))) |
| #define NOTIFY_PEER_CORE(a) Cy_IPC_Pipe_SendMessage(CY_IPC_EP_CYPIPE_CM0_ADDR, CY_IPC_EP_CYPIPE_CM4_ADDR, (a), NULL) |
| #endif |
| |
| static void Cy_Flash_NotifyHandler(uint32_t * msgPtr); |
| #endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ |
| /** \endcond */ |
| |
| /* Static functions */ |
| static bool Cy_Flash_BoundsCheck(uint32_t flashAddr); |
| static uint32_t Cy_Flash_GetRowNum(uint32_t flashAddr); |
| static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode); |
| static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void); |
| static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds); |
| |
| static volatile cy_stc_flash_context_t flashContext; |
| |
| |
| #if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) |
| /******************************************************************************* |
| * Function Name: Cy_Flash_NotifyHandler |
| ****************************************************************************//** |
| * |
| * This is the interrupt service routine for the pipe notifications. |
| * |
| *******************************************************************************/ |
| typedef struct |
| { |
| uint32_t maxSema; /* Maximum semaphores in system */ |
| uint32_t *arrayPtr; /* Pointer to semaphores array */ |
| } cy_stc_ipc_sema_t; |
| |
| #if defined (__ICCARM__) |
| #pragma diag_suppress=Ta023 |
| __ramfunc |
| #else |
| CY_SECTION(".cy_ramfunc") |
| #endif |
| static void Cy_Flash_NotifyHandler(uint32_t * msgPtr) |
| { |
| uint32_t intr; |
| static uint32_t semaIndex; |
| static uint32_t semaMask; |
| static volatile uint32_t *semaPtr; |
| static cy_stc_ipc_sema_t *semaStruct; |
| |
| cy_flash_notify_t *ipcMsgPtr = (cy_flash_notify_t *)msgPtr; |
| |
| if (CY_FLASH_ENTER_WAIT_LOOP == ipcMsgPtr->pktType) |
| { |
| intr = Cy_SysLib_EnterCriticalSection(); |
| |
| /* Get pointer to structure */ |
| semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SEMA)); |
| |
| /* Get the index into the semaphore array and calculate the mask */ |
| semaIndex = CY_FLASH_WAIT_SEMA / CY_IPC_SEMA_PER_WORD; |
| semaMask = (uint32_t)(1ul << (CY_FLASH_WAIT_SEMA - (semaIndex * CY_IPC_SEMA_PER_WORD) )); |
| semaPtr = &semaStruct->arrayPtr[semaIndex]; |
| |
| /* Notification to the Flash driver to start the current operation */ |
| *semaPtr |= semaMask; |
| |
| /* Check a notification from other core to end of waiting */ |
| while (((*semaPtr) & semaMask) != 0ul) |
| { |
| } |
| |
| Cy_SysLib_ExitCriticalSection(intr); |
| } |
| } |
| #if defined (__ICCARM__) |
| #pragma diag_default=Ta023 |
| #endif |
| #endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_Init |
| ****************************************************************************//** |
| * |
| * Initiates all needed prerequisites to support flash erase/write. |
| * Should be called from each core. |
| * |
| * Requires a call to Cy_IPC_SystemSemaInit() and Cy_IPC_SystemPipeInit() functions |
| * before use. |
| * |
| * This function is called in the SystemInit() function, for proper flash write |
| * and erase operations. If the default startup file is not used, or the function |
| * SystemInit() is not called in your project, call the following three functions |
| * prior to executing any flash or EmEEPROM write or erase operations: |
| * -# Cy_IPC_SystemSemaInit() |
| * -# Cy_IPC_SystemPipeInit() |
| * -# Cy_Flash_Init() |
| * |
| *******************************************************************************/ |
| void Cy_Flash_Init(void) |
| { |
| #if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) |
| if (cy_device->flashRwwSupport) |
| { |
| #if (CY_CPU_CORTEX_M4) |
| cy_stc_sysint_t flashIntConfig = |
| { |
| cpuss_interrupt_fm_IRQn, /* .intrSrc */ |
| 0 /* .intrPriority */ |
| }; |
| |
| (void)Cy_SysInt_Init(&flashIntConfig, &Cy_Flash_ResumeIrqHandler); |
| NVIC_EnableIRQ(flashIntConfig.intrSrc); |
| #endif |
| |
| #if (CY_IPC_CYPIPE_ENABLE) |
| if (cy_device->flashPipeEnable) |
| { |
| (void)Cy_IPC_Pipe_RegisterCallback(CY_IPC_EP_CYPIPE_ADDR, &Cy_Flash_NotifyHandler, |
| (uint32_t)CY_FLASH_IPC_CLIENT_ID); |
| } |
| #endif /* (CY_IPC_CYPIPE_ENABLE) */ |
| } |
| #endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ |
| } |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_SendCmd |
| ****************************************************************************//** |
| * |
| * Sends a command to the SROM via the IPC channel. The function is placed to the |
| * SRAM memory to guarantee successful operation. After an IPC message is sent, |
| * the function waits for a defined time before exiting the function. |
| * |
| * \param mode |
| * Sets the blocking or non-blocking Flash operation. |
| * |
| * \param microseconds |
| * The number of microseconds to wait before exiting the functions |
| * in range 0-65535 us. |
| * |
| * \return Returns the status of the Flash operation, |
| * see \ref cy_en_flashdrv_status_t. |
| * |
| *******************************************************************************/ |
| #if defined (__ICCARM__) |
| #pragma diag_suppress=Ta023 |
| __ramfunc |
| #else |
| CY_SECTION(".cy_ramfunc") |
| #endif |
| static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_IPC_BUSY; |
| IPC_STRUCT_Type *ipcBase = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL); |
| |
| #if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) |
| uint32_t semaTryCount = 0uL; |
| uint32_t intr; |
| |
| CY_ALIGN(4) static cy_flash_notify_t ipcWaitMessage = |
| { |
| /* .clientID */ CY_FLASH_IPC_CLIENT_ID, |
| /* .pktType */ CY_FLASH_ENTER_WAIT_LOOP, |
| /* .intrRelMask */ 0u |
| }; |
| |
| if (cy_device->flashRwwSupport) |
| { |
| /* Check for active core is CM0+, or CM4 on single core device */ |
| #if ((CY_CPU_CORTEX_M0P) || !(__CM0P_PRESENT)) |
| #if (CY_CPU_CORTEX_M0P) |
| bool isPeerCoreEnabled = (CY_SYS_CM4_STATUS_ENABLED == Cy_SysGetCM4Status()); |
| #else |
| bool isPeerCoreEnabled = false; |
| #endif |
| |
| if (!isPeerCoreEnabled) |
| { |
| result = CY_FLASH_DRV_SUCCESS; |
| } |
| else |
| { |
| #endif |
| if (IS_CY_PIPE_FREE()) |
| { |
| if (CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA)) |
| { |
| if (CY_IPC_PIPE_SUCCESS == NOTIFY_PEER_CORE(&ipcWaitMessage)) |
| { |
| /* Wait for SEMA lock by peer core */ |
| while ((CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA)) && ((semaTryCount < CY_FLASH_SEMA_WAIT_MAX_TRIES))) |
| { |
| /* check for timeout (as maximum tries count) */ |
| ++semaTryCount; |
| } |
| |
| if (semaTryCount < CY_FLASH_SEMA_WAIT_MAX_TRIES) |
| { |
| result = CY_FLASH_DRV_SUCCESS; |
| } |
| } |
| } |
| } |
| #if ((CY_CPU_CORTEX_M0P) || !(__CM0P_PRESENT)) |
| } |
| #endif |
| |
| if (CY_FLASH_DRV_SUCCESS == result) |
| { |
| /* Notifier is ready, start of the operation */ |
| intr = Cy_SysLib_EnterCriticalSection(); |
| |
| if (0UL != _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS->CLK_CAL_CNT1)) |
| { |
| /* Tries to acquire the IPC structure and pass the arguments to SROM API */ |
| if (Cy_IPC_Drv_SendMsgPtr(ipcBase, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&flashContext) == CY_IPC_DRV_SUCCESS) |
| { |
| if (cy_device->flashRwwSupport) |
| { |
| Cy_Flash_RAMDelay(microseconds); |
| } |
| |
| if (mode == CY_FLASH_NON_BLOCKING_MODE) |
| { |
| /* The Flash operation is successfully initiated */ |
| result = CY_FLASH_DRV_OPERATION_STARTED; |
| } |
| else |
| { |
| while (0u != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, REG_IPC_STRUCT_LOCK_STATUS(ipcBase))) |
| { |
| /* Polls whether the IPC is released and the Flash operation is performed */ |
| } |
| //Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) |
| |
| result = Cy_Flash_OperationStatus(); |
| } |
| } |
| else |
| { |
| /* The IPC structure is already locked by another process */ |
| result = CY_FLASH_DRV_IPC_BUSY; |
| } |
| } |
| #if ((CY_CPU_CORTEX_M0P) || !(__CM0P_PRESENT)) |
| if (isPeerCoreEnabled) |
| { |
| #endif |
| while (CY_IPC_SEMA_SUCCESS != Cy_IPC_Sema_Clear(CY_FLASH_WAIT_SEMA, true)) |
| { |
| /* Clear SEMA lock */ |
| } |
| #if ((CY_CPU_CORTEX_M0P) || !(__CM0P_PRESENT)) |
| } |
| #endif |
| |
| Cy_SysLib_ExitCriticalSection(intr); |
| /* End of the flash operation */ |
| } |
| } |
| else |
| #endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ |
| { |
| /* Tries to acquire the IPC structure and pass the arguments to SROM API */ |
| if (Cy_IPC_Drv_SendMsgPtr(ipcBase, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&flashContext) == CY_IPC_DRV_SUCCESS) |
| { |
| if (mode == CY_FLASH_NON_BLOCKING_MODE) |
| { |
| /* The Flash operation is successfully initiated */ |
| result = CY_FLASH_DRV_OPERATION_STARTED; |
| } |
| else |
| { |
| while (0u != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, REG_IPC_STRUCT_LOCK_STATUS(ipcBase))) |
| { |
| /* Polls whether the IPC is released and the Flash operation is performed */ |
| } |
| |
| result = Cy_Flash_OperationStatus(); |
| } |
| } |
| else |
| { |
| /* The IPC structure is already locked by another process */ |
| result = CY_FLASH_DRV_IPC_BUSY; |
| } |
| } |
| |
| return (result); |
| } |
| #if defined (__ICCARM__) |
| #pragma diag_default=Ta023 |
| #endif |
| |
| |
| #if !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) |
| /******************************************************************************* |
| * Function Name: Cy_Flash_RAMDelay |
| ****************************************************************************//** |
| * |
| * Wait for a defined time in the SRAM memory region. |
| * |
| * \param microseconds |
| * Delay time in microseconds in range 0-65535 us. |
| * |
| *******************************************************************************/ |
| #if defined (__ICCARM__) |
| #pragma diag_suppress=Ta023 |
| __ramfunc |
| #else |
| CY_SECTION(".cy_ramfunc") |
| #endif |
| static void Cy_Flash_RAMDelay(uint32_t microseconds) |
| { |
| uint32_t ticks = (microseconds & 0xFFFFUL) * CY_FLASH_TICKS_FOR_1US; |
| if (ticks != CY_FLASH_NO_DELAY) |
| { |
| CY_FLASH_TST_DDFT_FAST_CTL_REG = CY_FLASH_TST_DDFT_FAST_CTL_MASK; |
| CY_FLASH_TST_DDFT_SLOW_CTL_REG = CY_FLASH_TST_DDFT_SLOW_CTL_MASK; |
| |
| SRSS->CLK_OUTPUT_SLOW = _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL0, CY_SYSCLK_MEAS_CLK_IMO) | |
| _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL1, CY_FLASH_CLK_OUTPUT_DISABLED); |
| |
| /* Load the down-counter without status bit value */ |
| SRSS->CLK_CAL_CNT1 = _VAL2FLD(SRSS_CLK_CAL_CNT1_CAL_COUNTER1, ticks); |
| |
| /* Make sure that the counter is started */ |
| ticks = _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS->CLK_CAL_CNT1); |
| |
| while (0UL == _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS->CLK_CAL_CNT1)) |
| { |
| /* Wait until the counter stops counting */ |
| } |
| } |
| } |
| #if defined (__ICCARM__) |
| #pragma diag_default=Ta023 |
| #endif |
| |
| #if (CY_CPU_CORTEX_M4) |
| |
| /* Based on bookmark codes of mxs40srompsoc BROS,002-03298 */ |
| #define CY_FLASH_PROGRAM_ROW_BOOKMARK (0x00000001UL) |
| #define CY_FLASH_ERASE_ROW_BOOKMARK (0x00000002UL) |
| #define CY_FLASH_WRITE_ROW_ERASE_BOOKMARK (0x00000003UL) |
| #define CY_FLASH_WRITE_ROW_PROGRAM_BOOKMARK (0x00000004UL) |
| |
| /* Number of the CM0P ticks for function delay corrective time at final stage */ |
| #define CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS (1000UL) |
| #define CY_FLASH_PROGRAM_ROW_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS)) |
| #define CY_FLASH_ERASE_ROW_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS)) |
| #define CY_FLASH_WRITE_ROW_ERASE_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS)) |
| #define CY_FLASH_WRITE_ROW_PROGRAM_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_FINAL_DELAY_TICKS)) |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_ResumeIrqHandler |
| ****************************************************************************//** |
| * |
| * This is the interrupt service routine to make additional processing of the |
| * flash operations resume phase. |
| * |
| *******************************************************************************/ |
| #if defined (__ICCARM__) |
| #pragma diag_suppress=Ta023 |
| __ramfunc |
| #else |
| CY_SECTION(".cy_ramfunc") |
| #endif |
| void Cy_Flash_ResumeIrqHandler(void) |
| { |
| IPC_STRUCT_Type *ipcBase = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP0); |
| |
| uint32_t bookmark; |
| bookmark = FLASHC->FM_CTL.BOOKMARK & 0xffffUL; |
| |
| uint32_t intr = Cy_SysLib_EnterCriticalSection(); |
| |
| uint32_t cm0s = CPUSS->CM0_STATUS; |
| |
| switch (bookmark) |
| { |
| case CY_FLASH_PROGRAM_ROW_BOOKMARK: |
| if ((cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) && ((bool)(CY_IPC_CYPIPE_ENABLE))) |
| { |
| REG_IPC_STRUCT_NOTIFY(ipcBase) = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0)); |
| } |
| Cy_Flash_RAMDelay(CY_FLASH_PROGRAM_ROW_DELAY); |
| break; |
| case CY_FLASH_ERASE_ROW_BOOKMARK: |
| if ((cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) && ((bool)(CY_IPC_CYPIPE_ENABLE))) |
| { |
| REG_IPC_STRUCT_NOTIFY(ipcBase) = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0)); |
| } |
| Cy_Flash_RAMDelay(CY_FLASH_ERASE_ROW_DELAY); /* Delay when erase row is finished */ |
| break; |
| case CY_FLASH_WRITE_ROW_ERASE_BOOKMARK: |
| if ((cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) && ((bool)(CY_IPC_CYPIPE_ENABLE))) |
| { |
| REG_IPC_STRUCT_NOTIFY(ipcBase) = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0)); |
| } |
| Cy_Flash_RAMDelay(CY_FLASH_WRITE_ROW_ERASE_DELAY); /* Delay when erase phase for row is finished */ |
| break; |
| case CY_FLASH_WRITE_ROW_PROGRAM_BOOKMARK: |
| if ((cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) && ((bool)(CY_IPC_CYPIPE_ENABLE))) |
| { |
| REG_IPC_STRUCT_NOTIFY(ipcBase) = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0)); |
| } |
| Cy_Flash_RAMDelay(CY_FLASH_WRITE_ROW_PROGRAM_DELAY); |
| break; |
| default: |
| break; |
| } |
| |
| Cy_SysLib_ExitCriticalSection(intr); |
| } |
| #if defined (__ICCARM__) |
| #pragma diag_default=Ta023 |
| #endif |
| #endif /* (CY_CPU_CORTEX_M4) */ |
| #endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */ |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_EraseRow |
| ****************************************************************************//** |
| * |
| * This function erases a single row of flash. Reports success or |
| * a reason for failure. Does not return until the Write operation is |
| * complete. Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in |
| * the case when another process is writing to flash or erasing the row. |
| * User firmware should not enter the Hibernate or Deep-Sleep mode until flash Erase |
| * is complete. The Flash operation is allowed in Sleep mode. |
| * During the Flash operation, the device should not be reset, including the |
| * XRES pin, a software reset, and watchdog reset sources. Also, low-voltage |
| * detect circuits should be configured to generate an interrupt instead of a |
| * reset. Otherwise, portions of flash may undergo unexpected changes. |
| * |
| * \param rowAddr Address of the flash row number. The number of the flash rows |
| * is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. |
| * The Read-while-Write violation occurs when the flash read operation is |
| * initiated in the same flash sector where the flash write operation is |
| * performing. Refer to the device datasheet for the details. |
| * Address must match row start address. |
| * |
| * \return Returns the status of the Flash operation, |
| * see \ref cy_en_flashdrv_status_t. |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_EraseRow(uint32_t rowAddr) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| |
| /* Prepares arguments to be passed to SROM API */ |
| if (Cy_Flash_BoundsCheck(rowAddr) != false) |
| { |
| SystemCoreClockUpdate(); |
| |
| flashContext.opcode = CY_FLASH_OPCODE_ERASE_ROW | CY_FLASH_BLOCKING_MODE; |
| flashContext.arg1 = rowAddr; |
| flashContext.arg2 = 0UL; |
| flashContext.arg3 = 0UL; |
| |
| if (cy_device->flashEraseDelay) |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY); |
| } |
| else |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY); |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_ProgramRow |
| ****************************************************************************//** |
| * |
| * This function writes an array of data to a single row of flash. Reports |
| * success or a reason for failure. Does not return until the Program operation |
| * is complete. |
| * Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case |
| * when another process is writing to flash. User firmware should not enter the |
| * Hibernate or Deep-sleep mode until flash Write is complete. The Flash operation |
| * is allowed in Sleep mode. During the Flash operation, the device should not be |
| * reset, including the XRES pin, a software reset, and watchdog reset sources. |
| * Also, low-voltage detect circuits should be configured to generate an interrupt |
| * instead of a reset. Otherwise, portions of flash may undergo unexpected |
| * changes.\n |
| * Before calling this function, the target flash region must be erased by |
| * the StartErase/EraseRow function.\n |
| * Data to be programmed must be located in the SRAM memory region. |
| * \note Before reading data from previously programmed/erased flash rows, the |
| * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() |
| * function. |
| * |
| * \param rowAddr Address of the flash row number. The number of the flash rows |
| * is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. |
| * The Read-while-Write violation occurs when the flash read operation is |
| * initiated in the same flash sector where the flash write operation is |
| * performing. Refer to the device datasheet for the details. |
| * Address must match row start address. |
| * |
| * \param data The pointer to the data which has to be written to flash. The size |
| * of the data array must be equal to the flash row size. The flash row size for |
| * the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to |
| * the device datasheet for the details. |
| * |
| * \return Returns the status of the Flash operation, |
| * see \ref cy_en_flashdrv_status_t. |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_ProgramRow(uint32_t rowAddr, const uint32_t* data) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| |
| /* Checks whether the input parameters are valid */ |
| if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data)) |
| { |
| SystemCoreClockUpdate(); |
| |
| /* Prepares arguments to be passed to SROM API */ |
| flashContext.opcode = CY_FLASH_OPCODE_PROGRAM_ROW | CY_FLASH_BLOCKING_MODE; |
| flashContext.arg1 = CY_FLASH_CONFIG_DATASIZE | CY_FLASH_DATA_LOC_SRAM; |
| flashContext.arg2 = rowAddr; |
| flashContext.arg3 = (uint32_t)data; |
| |
| if (cy_device->flashProgramDelay) |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY); |
| } |
| else |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY); |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_WriteRow |
| ****************************************************************************//** |
| * |
| * This function writes an array of data to a single row of flash. This is done |
| * in three steps - pre-program, erase and then program flash row with the input |
| * data. Reports success or a reason for failure. Does not return until the Write |
| * operation is complete. |
| * Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case |
| * when another process is writing to flash. User firmware should not enter the |
| * Hibernate or Deep-sleep mode until flash Write is complete. The Flash operation |
| * is allowed in Sleep mode. During the Flash operation, the |
| * device should not be reset, including the XRES pin, a software |
| * reset, and watchdog reset sources. Also, low-voltage detect |
| * circuits should be configured to generate an interrupt |
| * instead of a reset. Otherwise, portions of flash may undergo |
| * unexpected changes. |
| * |
| * \param rowAddr Address of the flash row number. The number of the flash rows |
| * is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. |
| * The Read-while-Write violation occurs when the flash read operation is |
| * initiated in the same flash sector where the flash write operation is |
| * performing. Refer to the device datasheet for the details. |
| * Address must match row start address. |
| * |
| * \param data The pointer to the data which has to be written to flash. The size |
| * of the data array must be equal to the flash row size. The flash row size for |
| * the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to |
| * the device datasheet for the details. |
| * |
| * \return Returns the status of the Flash operation, |
| * see \ref cy_en_flashdrv_status_t. |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_WriteRow(uint32_t rowAddr, const uint32_t* data) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| |
| /* Checks whether the input parameters are valid */ |
| if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data)) |
| { |
| SystemCoreClockUpdate(); |
| |
| /* Prepares arguments to be passed to SROM API */ |
| flashContext.opcode = CY_FLASH_OPCODE_WRITE_ROW | CY_FLASH_BLOCKING_MODE; |
| flashContext.arg1 = 0UL; |
| flashContext.arg2 = rowAddr; |
| flashContext.arg3 = (uint32_t)data; |
| |
| if (cy_device->flashWriteDelay) |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_WRITE_DELAY); |
| } |
| else |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY); |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_StartWrite |
| ****************************************************************************//** |
| * |
| * Performs pre-program, erase and then starts programming the flash row with |
| * the input data. Returns immediately and reports a successful start |
| * or reason for failure. Reports a \ref CY_FLASH_DRV_IPC_BUSY error |
| * in the case when another process is writing to flash. User |
| * firmware should not enter the Hibernate or Deep-Sleep mode until |
| * flash Write is complete. The Flash operation is allowed in Sleep mode. |
| * During the flash operation, the device should not be reset, including the |
| * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage |
| * detect circuits should be configured to generate an interrupt instead of a reset. |
| * Otherwise, portions of flash may undergo unexpected changes. |
| * \note Before reading data from previously programmed/erased flash rows, the |
| * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() |
| * function. |
| * |
| * \param rowAddr Address of the flash row number. The number of the flash rows |
| * is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. |
| * The Read-while-Write violation occurs when the flash read operation is |
| * initiated in the same flash sector where the flash write operation is |
| * performing. Refer to the device datasheet for the details. |
| * Address must match row start address. |
| * |
| * \param data The pointer to the data to be written to flash. The size |
| * of the data array must be equal to the flash row size. The flash row size for |
| * the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to |
| * the device datasheet for the details. |
| * |
| * \return Returns the status of the Flash operation, |
| * see \ref cy_en_flashdrv_status_t. |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_StartWrite(uint32_t rowAddr, const uint32_t* data) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| |
| /* Checks whether the input parameters are valid */ |
| if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data)) |
| { |
| result = Cy_Flash_StartErase(rowAddr); |
| |
| if (CY_FLASH_DRV_OPERATION_STARTED == result) |
| { |
| /* Polls whether the IPC is released and the Flash operation is performed */ |
| do |
| { |
| result = Cy_Flash_OperationStatus(); |
| } |
| while (result == CY_FLASH_DRV_OPCODE_BUSY); |
| |
| if (CY_FLASH_DRV_SUCCESS == result) |
| { |
| result = Cy_Flash_StartProgram(rowAddr, data); |
| } |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_IsOperationComplete |
| ****************************************************************************//** |
| * |
| * Reports a successful operation result, reason of failure or busy status |
| * ( \ref CY_FLASH_DRV_OPCODE_BUSY ). |
| * |
| * \return Returns the status of the Flash operation (see \ref cy_en_flashdrv_status_t). |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_IsOperationComplete(void) |
| { |
| return (Cy_Flash_OperationStatus()); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_StartErase |
| ****************************************************************************//** |
| * |
| * Starts erasing a single row of flash. Returns immediately |
| * and reports a successful start or reason for failure. |
| * Reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case when IPC structure is locked |
| * by another process. User firmware should not enter the Hibernate or Deep-Sleep mode until |
| * flash Erase is complete. The Flash operation is allowed in Sleep mode. |
| * During the flash operation, the device should not be reset, including the |
| * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage |
| * detect circuits should be configured to generate an interrupt instead of a reset. |
| * Otherwise, portions of flash may undergo unexpected changes. |
| * \note Before reading data from previously programmed/erased flash rows, the |
| * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() |
| * function. |
| * |
| * \param rowAddr Address of the flash row number. The number of the flash rows |
| * is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. |
| * The Read-while-Write violation occurs when the flash read operation is |
| * initiated in the same flash sector where the flash erase operation is |
| * performing. Refer to the device datasheet for the details. |
| * Address must match row start address. |
| * |
| * \return Returns the status of the Flash operation, |
| * see \ref cy_en_flashdrv_status_t. |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_StartErase(uint32_t rowAddr) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| |
| if (Cy_Flash_BoundsCheck(rowAddr) != false) |
| { |
| SystemCoreClockUpdate(); |
| |
| /* Prepares arguments to be passed to SROM API */ |
| flashContext.opcode = CY_FLASH_OPCODE_ERASE_ROW; |
| #if (!(__CM0P_PRESENT)) |
| flashContext.opcode |= CY_FLASH_BLOCKING_MODE; |
| #endif |
| flashContext.arg1 = rowAddr; |
| flashContext.arg2 = 0UL; |
| flashContext.arg3 = 0UL; |
| |
| if (cy_device->flashEraseDelay) |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY); |
| } |
| else |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY); |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_StartProgram |
| ****************************************************************************//** |
| * |
| * Starts writing an array of data to a single row of flash. Returns immediately |
| * and reports a successful start or reason for failure. |
| * Reports a \ref CY_FLASH_DRV_IPC_BUSY error if another process is writing |
| * to flash. The user firmware should not enter Hibernate or Deep-Sleep mode until flash |
| * Program is complete. The Flash operation is allowed in Sleep mode. |
| * During the Flash operation, the device should not be reset, including the |
| * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage |
| * detect circuits should be configured to generate an interrupt instead of a reset. |
| * Otherwise, portions of flash may undergo unexpected changes.\n |
| * Before calling this function, the target flash region must be erased by |
| * the StartErase/EraseRow function.\n |
| * Data to be programmed must be located in the SRAM memory region. |
| * \note Before reading data from previously programmed/erased flash rows, the |
| * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer() |
| * function. |
| * |
| * \param rowAddr The address of the flash row number. The number of the flash rows |
| * is defined by the \ref CY_FLASH_NUMBER_ROWS macro for the selected device. |
| * The Read-while-Write violation occurs when the Flash Write operation is |
| * performing. Refer to the device datasheet for the details. |
| * The address must match the row start address. |
| * |
| * \param data The pointer to the data to be written to flash. The size |
| * of the data array must be equal to the flash row size. The flash row size for |
| * the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to |
| * the device datasheet for the details. |
| * |
| * \return Returns the status of the Flash operation, |
| * see \ref cy_en_flashdrv_status_t. |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_StartProgram(uint32_t rowAddr, const uint32_t* data) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| |
| if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data)) |
| { |
| SystemCoreClockUpdate(); |
| |
| /* Prepares arguments to be passed to SROM API */ |
| flashContext.opcode = CY_FLASH_OPCODE_PROGRAM_ROW; |
| #if (!(__CM0P_PRESENT)) |
| flashContext.opcode |= CY_FLASH_BLOCKING_MODE; |
| #endif |
| flashContext.arg1 = CY_FLASH_CONFIG_DATASIZE | CY_FLASH_DATA_LOC_SRAM; |
| flashContext.arg2 = rowAddr; |
| flashContext.arg3 = (uint32_t)data; |
| |
| if (cy_device->flashProgramDelay) |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY); |
| } |
| else |
| { |
| result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY); |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_RowChecksum |
| ****************************************************************************//** |
| * |
| * Returns a checksum value of the specified flash row. |
| * |
| * \note Now Cy_Flash_RowChecksum() requires the row <b>address</b> (rowAddr) |
| * as a parameter. In previous versions of the driver, this function used |
| * the row <b>number</b> (rowNum) for this parameter. |
| * |
| * \param rowAddr The address of the flash row. |
| * |
| * \param checksumPtr The pointer to the address where checksum is to be stored |
| * |
| * \return Returns the status of the Flash operation. |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_RowChecksum (uint32_t rowAddr, uint32_t* checksumPtr) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| uint32_t resTmp; |
| uint32_t rowID; |
| |
| /* Checks whether the input parameters are valid */ |
| if ((Cy_Flash_BoundsCheck(rowAddr)) && (NULL != checksumPtr)) |
| { |
| rowID = Cy_Flash_GetRowNum(rowAddr); |
| |
| /* Prepares arguments to be passed to SROM API */ |
| flashContext.opcode = CY_FLASH_OPCODE_CHECKSUM | |
| (((rowID >> CY_FLASH_REGION_ID_SHIFT) & CY_FLASH_REGION_ID_MASK) << CY_FLASH_OPCODE_CHECKSUM_REGION_SHIFT) | |
| ((rowID & CY_FLASH_ROW_ID_MASK) << CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT); |
| |
| /* Tries to acquire the IPC structure and pass the arguments to SROM API */ |
| if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0, |
| (void*)&flashContext) == CY_IPC_DRV_SUCCESS) |
| { |
| /* Polls whether IPC is released and the Flash operation is performed */ |
| while (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) != false) |
| { |
| /* Wait till IPC is released */ |
| } |
| |
| resTmp = flashContext.opcode; |
| |
| if ((resTmp >> CY_FLASH_ERROR_SHIFT) == CY_FLASH_ERROR_NO_ERROR) |
| { |
| result = CY_FLASH_DRV_SUCCESS; |
| *checksumPtr = flashContext.opcode & CY_FLASH_RESULT_MASK; |
| } |
| else |
| { |
| result = Cy_Flash_ProcessOpcode(flashContext.opcode); |
| } |
| } |
| else |
| { |
| /* The IPC structure is already locked by another process */ |
| result = CY_FLASH_DRV_IPC_BUSY; |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_CalculateHash |
| ****************************************************************************//** |
| * |
| * Returns a hash value of the specified region of flash. |
| * |
| * \param data Start the data address. |
| * |
| * \param numberOfBytes The hash value is calculated for the number of bytes after the |
| * start data address (0 - 1 byte, 1- 2 bytes etc). |
| * |
| * \param hashPtr The pointer to the address where hash is to be stored |
| * |
| * \return Returns the status of the Flash operation. |
| * |
| *******************************************************************************/ |
| cy_en_flashdrv_status_t Cy_Flash_CalculateHash (const uint32_t* data, uint32_t numberOfBytes, uint32_t* hashPtr) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| volatile uint32_t resTmp; |
| |
| /* Checks whether the input parameters are valid */ |
| if ((data != NULL) && (0ul != numberOfBytes)) |
| { |
| /* Prepares arguments to be passed to SROM API */ |
| flashContext.opcode = CY_FLASH_OPCODE_HASH; |
| flashContext.arg1 = (uint32_t)data; |
| flashContext.arg2 = numberOfBytes; |
| |
| /* Tries to acquire the IPC structure and pass the arguments to SROM API */ |
| if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0, |
| (void*)&flashContext) == CY_IPC_DRV_SUCCESS) |
| { |
| /* Polls whether IPC is released and the Flash operation is performed */ |
| while (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) != false) |
| { |
| /* Wait till IPC is released */ |
| } |
| |
| resTmp = flashContext.opcode; |
| |
| if ((resTmp >> CY_FLASH_ERROR_SHIFT) == CY_FLASH_ERROR_NO_ERROR) |
| { |
| result = CY_FLASH_DRV_SUCCESS; |
| *hashPtr = flashContext.opcode & CY_FLASH_RESULT_MASK; |
| } |
| else |
| { |
| result = Cy_Flash_ProcessOpcode(flashContext.opcode); |
| } |
| } |
| else |
| { |
| /* The IPC structure is already locked by another process */ |
| result = CY_FLASH_DRV_IPC_BUSY; |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_GetRegion |
| ****************************************************************************//** |
| * |
| * Returns false if Flash address is out of boundary, otherwise returns true. |
| * |
| * \param flashAddr Address to be checked |
| * |
| * \return |
| * The valid return value is encoded as follows (or 0xFFFFFFFFUL for invalid address) |
| * <table> |
| * <tr><th>Field <th>Value |
| * <tr><td>Flash row number <td>[15:0] bits |
| * <tr><td>Flash region ID <td>[31:16] bits |
| * </table> |
| * |
| *******************************************************************************/ |
| static uint32_t Cy_Flash_GetRowNum(uint32_t flashAddr) |
| { |
| uint32_t result; |
| |
| if ((flashAddr >= CY_FLASH_BASE) && (flashAddr < (CY_FLASH_BASE + cy_device->flashcSize))) |
| { |
| result = (CY_FLASH_REGION_ID_MAIN << CY_FLASH_REGION_ID_SHIFT) | |
| ((flashAddr - CY_FLASH_BASE) / CY_FLASH_SIZEOF_ROW); |
| } |
| else |
| if ((flashAddr >= CY_EM_EEPROM_BASE) && (flashAddr < (CY_EM_EEPROM_BASE + CY_EM_EEPROM_SIZE))) |
| { |
| result = (CY_FLASH_REGION_ID_EM_EEPROM << CY_FLASH_REGION_ID_SHIFT) | |
| ((flashAddr - CY_EM_EEPROM_BASE) / CY_FLASH_SIZEOF_ROW); |
| } |
| else |
| if ((flashAddr >= SFLASH_BASE) && (flashAddr < (SFLASH_BASE + SFLASH_SECTION_SIZE))) |
| { |
| result = (CY_FLASH_REGION_ID_SFLASH << CY_FLASH_REGION_ID_SHIFT) | |
| ((flashAddr - SFLASH_BASE) / CY_FLASH_SIZEOF_ROW); |
| } |
| else |
| { |
| result = 0xFFFFFFFFUL; |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_BoundsCheck |
| ****************************************************************************//** |
| * |
| * The function checks the following conditions: |
| * - if Flash address is in valid flash rows range |
| * - if Flash address is equal to start address of the row |
| * |
| * \param flashAddr Address to be checked |
| * |
| * \return false - out of bound, true - in flash bounds |
| * |
| *******************************************************************************/ |
| static bool Cy_Flash_BoundsCheck(uint32_t flashAddr) |
| { |
| return ((Cy_Flash_GetRowNum(flashAddr) != 0xFFFFFFFFUL) && ((flashAddr % CY_FLASH_SIZEOF_ROW) == 0UL)); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_ProcessOpcode |
| ****************************************************************************//** |
| * |
| * Converts System Call returns to the Flash driver return defines. |
| * |
| * \param opcode The value returned by the System Call. |
| * |
| * \return Flash driver return. |
| * |
| *******************************************************************************/ |
| static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode) |
| { |
| cy_en_flashdrv_status_t result; |
| |
| switch (opcode) |
| { |
| case 0UL: |
| { |
| result = CY_FLASH_DRV_SUCCESS; |
| break; |
| } |
| case CY_FLASH_ROMCODE_SUCCESS: |
| { |
| result = CY_FLASH_DRV_SUCCESS; |
| break; |
| } |
| case CY_FLASH_ROMCODE_INVALID_PROTECTION: |
| { |
| result = CY_FLASH_DRV_INV_PROT; |
| break; |
| } |
| case CY_FLASH_ROMCODE_INVALID_FM_PL: |
| { |
| result = CY_FLASH_DRV_INVALID_FM_PL; |
| break; |
| } |
| case CY_FLASH_ROMCODE_INVALID_FLASH_ADDR: |
| { |
| result = CY_FLASH_DRV_INVALID_FLASH_ADDR; |
| break; |
| } |
| case CY_FLASH_ROMCODE_ROW_PROTECTED: |
| { |
| result = CY_FLASH_DRV_ROW_PROTECTED; |
| break; |
| } |
| case CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR: |
| { |
| result = CY_FLASH_DRV_PROGRESS_NO_ERROR; |
| break; |
| } |
| case (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS: |
| { |
| result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| break; |
| } |
| case CY_FLASH_IS_OPERATION_STARTED : |
| { |
| result = CY_FLASH_DRV_OPERATION_STARTED; |
| break; |
| } |
| case CY_FLASH_IS_BUSY : |
| { |
| result = CY_FLASH_DRV_OPCODE_BUSY; |
| break; |
| } |
| case CY_FLASH_IS_IPC_BUSY : |
| { |
| result = CY_FLASH_DRV_IPC_BUSY; |
| break; |
| } |
| case CY_FLASH_IS_INVALID_INPUT_PARAMETERS : |
| { |
| result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS; |
| break; |
| } |
| default: |
| { |
| result = CY_FLASH_DRV_ERR_UNC; |
| break; |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_OperationStatus |
| ****************************************************************************//** |
| * |
| * Checks the status of the Flash Operation, and returns it. |
| * |
| * \return Returns the status of the Flash operation |
| * (see \ref cy_en_flashdrv_status_t). |
| * |
| *******************************************************************************/ |
| static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void) |
| { |
| cy_en_flashdrv_status_t result = CY_FLASH_DRV_OPCODE_BUSY; |
| |
| /* Checks if the IPC structure is not locked */ |
| if (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) == false) |
| { |
| /* The result of SROM API calling is returned to the driver context */ |
| result = Cy_Flash_ProcessOpcode(flashContext.opcode); |
| |
| /* Clear pre-fetch cache after flash operation */ |
| FLASHC->FLASH_CMD = FLASHC_FLASH_CMD_INV_Msk; |
| |
| while (FLASHC->FLASH_CMD != 0U) |
| { |
| } |
| } |
| |
| return (result); |
| } |
| |
| |
| /******************************************************************************* |
| * Function Name: Cy_Flash_GetExternalStatus |
| ****************************************************************************//** |
| * |
| * This function handles the case where a module such as security image captures |
| * a system call from this driver and reports its own status or error code, |
| * for example protection violation. In that case, a function from this |
| * driver returns an unknown error (see \ref cy_en_flashdrv_status_t). After receipt |
| * of an unknown error, the user may call this function to get the status |
| * of the capturing module. |
| * |
| * The user is responsible for parsing the content of the returned value |
| * and casting it to the appropriate enumeration. |
| * |
| * \return |
| * The error code that was stored in the opcode variable. |
| * |
| *******************************************************************************/ |
| uint32_t Cy_Flash_GetExternalStatus(void) |
| { |
| return (flashContext.opcode); |
| } |
| |
| |
| /* [] END OF FILE */ |