/***************************************************************************//**
* \file cy_flash_v2.c
* \version 3.110
*
* \brief
* Provides the public functions for the API for the Flash Driver.
*
********************************************************************************
* \copyright
* Copyright 2021, Cypress Semiconductor Corporation. All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/
#include "cy_device.h"
#if defined(CY_IP_MXFLASHC_VERSION_ECT)
#include "cy_flash.h"
#include "cy_sysint.h"
#include "cy_ipc_drv.h"
#include "cy_syslib.h"
/** SROM API flash region ID shift for flash row information */
#define CY_FLASH_REGION_ID_SHIFT (16U)
#define CY_FLASH_ROW_ID_MASK (0xFFFFU)
/** SROM API flash region IDs */
#define CY_FLASH_REGION_ID_MAIN (0UL)
#define CY_FLASH_REGION_ID_WFLASH (1UL)
#define ADDRESS_LENGTH_32_BIT (4U)
#define ADDRESS_LENGTH_256_BIT (32U)
#define DATA_LENGTH_32_BIT (1U)
#define DATA_LENGTH_256_BIT (8U)
#define CY_FLASH_CODE_ECC_INJECT_POS (0x03UL) /** CODE ECC injection position shift */
#define CY_FLASH_WORK_ECC_INJECT_POS (0x02UL) /** WORK ECC injection position shift */
#define CY_FLASH_CACHE_ECC_INJECT_POS (0x02UL) /** CACHE ECC injection position shift */
static cy_en_flashdrv_status_t Cy_Flash_GetRowDetails(uint32_t rowAddr, uint8_t *rowID, cy_en_flash_checksum_bank_t *bank, cy_en_flash_checksum_region_t *region);
static cy_en_flashdrv_status_t Cy_Flash_CalculateHash_Ext(const cy_stc_flash_computehash_config_t *config, uint32_t* hashPtr);
static cy_en_flashdrv_status_t Cy_Flash_EraseSector_Ext(const cy_stc_flash_erasesector_config_t *config, cy_en_flash_driver_blocking_t block);
static en_flash_bounds_t Cy_Flash_WorkBoundsCheck(uint32_t address);
static en_flash_bounds_t Cy_Flash_MainBoundsCheck(uint32_t address);
static en_flash_bounds_t Cy_Flash_BoundsCheck(uint32_t flashAddr);
static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode);
static uint8_t g_non_block_context = 0;
/*******************************************************************************
* Function Name: Cy_Flash_CallSromApiForFlashWrite
****************************************************************************//**
*
* This function call SROM API driver for flash writing (e.g. program row,
* erase sector). Then, processes response message of the
* driver API and response message of SROM API if required.
*
* apiArgs pointer to SROM API arguments.
*
* block driver blocking mode cy_en_flash_driver_blocking_t
*
* Returns the status of the Flash operation.
*
*******************************************************************************/
static cy_en_flashdrv_status_t Cy_Flash_CallSromApiForFlashWrite(const un_srom_api_args_t* apiArgs, cy_en_flash_driver_blocking_t block)
{
if(block == CY_FLASH_DRIVER_BLOCKING)
{
un_srom_api_resps_t apiResp = {{ 0UL }};
/* Call SROM API with blocking mode */
cy_en_srom_driver_status_t sromDrvStatus;
sromDrvStatus = Cy_Srom_CallApi(apiArgs, &apiResp);
if(sromDrvStatus == CY_SROM_DR_IPC_BUSY)
{
return CY_FLASH_DRV_IPC_BUSY;
}
else if(sromDrvStatus == CY_SROM_DR_TIMEOUT)
{
return CY_FLASH_DRV_SROM_API_TIMEOUT;
}
else if(sromDrvStatus == CY_SROM_DR_API_UNKNOWN)
{
return CY_FLASH_DRV_ERR_UNC;
}
else
{
cy_en_flashdrv_status_t result;
result = Cy_Flash_ProcessOpcode(apiResp.resp[0]);
if(result != CY_FLASH_DRV_SUCCESS)
{
return result;
}
/* Invalidates the flash cache and buffer */
FLASHC_FLASH_CMD = _VAL2FLD(FLASHC_FLASH_CMD_INV, 1U);
// Wait for completion (HW will clear bit)
while (_FLD2VAL(FLASHC_FLASH_CMD_INV, FLASHC_FLASH_CMD) != 0U)
{
}
return CY_FLASH_DRV_SUCCESS;
}
}
else
{
/* Call SROM API with non-blocking mode */
cy_en_srom_driver_status_t status = Cy_Srom_CallApi_NonBlock(apiArgs);
if ( status != CY_SROM_DR_SUCCEEDED)
{
/* The IPC structure is already locked by another process */
return CY_FLASH_DRV_IPC_BUSY;
}
return CY_FLASH_DRV_SUCCESS;
}
}
/*******************************************************************************
* Function Name: Cy_Flash_Program_WorkFlash
****************************************************************************//**
*
* This function writes an array of data to work flash. Reports success or
* or a reason for failure.
* Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in the case when another
* process is operating flash. User firmware should not enter the hibernate
* mode until flash Write is complete. The Flash operation is allowed in Sleep and
* Deep-sleep modes. 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.
*
* config configuration of this function.
* This parameter is defined by the cy_stc_flash_programrow_config_t
* in group_flash_srom_config_structure macro.
*
* Returns the status of the Flash operation (see cy_en_flashdrv_status_t).
*
* Note: row or page is same and of the size 512 bytes
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_Program_WorkFlash(const cy_stc_flash_programrow_config_t* config)
{
cy_en_flashdrv_status_t status = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
/* Checks if input pointers are not NULL */
if(config == NULL)
{
return status;
}
/* Checks if input address are valid */
if((Cy_Flash_WorkBoundsCheck((uint32_t)config->destAddr) == CY_FLASH_OUT_OF_BOUNDS) || (config->dataAddr == NULL))
{
return status;
}
/* Prepares arguments to be passed to SROM API */
un_srom_api_args_t apiArgs = {{ 0UL }};
apiArgs.ProgramRow.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_PROGRAM_WFLASH;
apiArgs.ProgramRow.arg0.blocking = (uint32_t)CY_FLASH_PROGRAMROW_BLOCKING;
apiArgs.ProgramRow.arg0.skipBlankCheck = (uint32_t)config->skipBC;
apiArgs.ProgramRow.arg1.dataLoc = (uint32_t)config->dataLoc;
apiArgs.ProgramRow.arg1.dataSize = (uint32_t)config->dataSize;
apiArgs.ProgramRow.arg1.interruptMask = (uint32_t)config->intrMask;
apiArgs.ProgramRow.arg2.dstAddr = (uint32_t)config->destAddr;
apiArgs.ProgramRow.arg3.srcAddr = (uint32_t)config->dataAddr;
/* Call SROM API driver and process response */
status = Cy_Flash_CallSromApiForFlashWrite(&apiArgs, CY_FLASH_DRIVER_BLOCKING);
return status;
}
/*******************************************************************************
* Function Name: Cy_Flash_Program
****************************************************************************//**
*
* This function writes an array of data to a single row of flash. Reports success or
* or a reason for failure.
* Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in the case when another
* process is operating flash. User firmware should not enter the hibernate
* mode until flash Write is complete. The Flash operation is allowed in Sleep and
* Deep-sleep modes. 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.
*
* config configuration of this function.
* This parameter is defined by the cy_stc_flash_programrow_config_t
* in group_flash_srom_config_structure macro.
*
* Returns the status of the Flash operation (see cy_en_flashdrv_status_t).
*
* Note: row or page is same and of the size 512 bytes
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_Program(const cy_stc_flash_programrow_config_t* config, cy_en_flash_driver_blocking_t block)
{
cy_en_flashdrv_status_t status;
/* Checks if input pointers are not NULL */
if(config == NULL)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Checks if input address are valid */
if((Cy_Flash_BoundsCheck((uint32_t)config->destAddr) == CY_FLASH_OUT_OF_BOUNDS) || (config->dataAddr == NULL))
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Prepares arguments to be passed to SROM API */
un_srom_api_args_t apiArgs = {{ 0UL }};
apiArgs.ProgramRow.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_PROGRAM_ROW;
apiArgs.ProgramRow.arg0.blocking = (uint32_t)config->blocking;
apiArgs.ProgramRow.arg0.skipBlankCheck = (uint32_t)config->skipBC;
apiArgs.ProgramRow.arg1.dataLoc = (uint32_t)config->dataLoc;
apiArgs.ProgramRow.arg1.dataSize = (uint32_t)config->dataSize;
apiArgs.ProgramRow.arg1.interruptMask = (uint32_t)config->intrMask;
apiArgs.ProgramRow.arg2.dstAddr = (uint32_t)config->destAddr;
apiArgs.ProgramRow.arg3.srcAddr = (uint32_t)config->dataAddr;
/* Call SROM API driver and process response */
status = Cy_Flash_CallSromApiForFlashWrite(&apiArgs, block);
if(status == CY_FLASH_DRV_SUCCESS && block == CY_FLASH_DRIVER_NON_BLOCKING)
{
g_non_block_context = (uint8_t)(FLASHC_FM_CTL_ECT_STATUS_PGM_WORK_Msk | FLASHC_FM_CTL_ECT_STATUS_PGM_CODE_Msk);
status = CY_FLASH_DRV_OPERATION_STARTED;
}
return status;
}
/*******************************************************************************
* Function Name: Cy_Flash_Checksum
****************************************************************************//**
*
* Returns a checksum value of the specified flash row. supports only blocking
* mode for now.
* rowNum The Checksum is calculated to the flash row.
*
* checksumPtr The pointer to the address where checksum is to be stored
*
* Returns the status of the Flash operation.
*
* Note:row or page is same and of the size 512 bytes
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_Checksum(const cy_stc_flash_checksum_config_t *config, uint32_t* checksumPtr)
{
/* Checks whether the input parameters are valid */
if (config->rowId >= CY_FLASH_NUMBER_ROWS)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Prepares arguments to be passed to SROM API */
un_srom_api_args_t apiArgs = {{ 0UL }};
CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 14.3', 1, \
'Checked manually. Intentional expression will always be true for CAT1C devices.')
if(CPUSS_FLASH_SIZE >= 4096u)
{
apiArgs.CheckSum.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_CHECKSUM;
apiArgs.CheckSum.arg0.region = (uint32_t)config->region;
apiArgs.CheckSum.arg0.whole = (uint32_t)config->whole;
apiArgs.CheckSum.arg0.row_id = (uint32_t)config->rowId;
apiArgs.CheckSum.arg0.bank = (uint32_t)config->bank;
}
else
{
apiArgs.CheckSumLessThan4M.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_CHECKSUM;
apiArgs.CheckSumLessThan4M.arg0.region = (uint32_t)config->region;
apiArgs.CheckSumLessThan4M.arg0.whole = (uint32_t)config->whole;
apiArgs.CheckSumLessThan4M.arg0.row_id = (uint32_t)config->rowId;
apiArgs.CheckSumLessThan4M.arg0.bank = (uint32_t)config->bank;
}
CY_MISRA_BLOCK_END('MISRA C-2012 Rule 14.3')
/* Call SROM API with blocking mode */
un_srom_api_resps_t apiResp = {{ 0UL }};
cy_en_srom_driver_status_t sromDrvStatus;
sromDrvStatus = Cy_Srom_CallApi(&apiArgs, &apiResp);
if(sromDrvStatus == CY_SROM_DR_IPC_BUSY)
{
return CY_FLASH_DRV_IPC_BUSY;
}
else if(sromDrvStatus == CY_SROM_DR_TIMEOUT)
{
return CY_FLASH_DRV_SROM_API_TIMEOUT;
}
else if(sromDrvStatus == CY_SROM_DR_API_UNKNOWN)
{
return CY_FLASH_DRV_ERR_UNC;
}
else
{
/* non-empty terminating "else" statement. */
}
/* Process response message from API */
cy_en_flashdrv_status_t result;
result = Cy_Flash_ProcessOpcode(apiResp.resp[0]);
if(result == CY_FLASH_DRV_SUCCESS)
{
// checksum is in data1 not data0. the the pointer returned is to data0.
uint32_t data[2];
// CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.1','Checked manually. Intentional Non boolean type is interpreted as boolean.');
Cy_IPC_Drv_ReadDDataValue(Cy_IPC_Drv_GetIpcBaseAddress((uint32_t)CY_IPC_CHAN_SYSCALL), data );
*checksumPtr = data[1];
}
return result;
}
/*******************************************************************************
* Function Name: Cy_Flash_CalculateHash_Ext
****************************************************************************//**
*
* Returns a hash value of the specified region of flash. supports only blocking
* mode for now.
* data Start the data address.
*
* numberOfBytes The hash value is calculated for the number of bytes after the
* start data address (0 - 1 byte, 1- 2 bytes etc).
*
* hashPtr The pointer to the address where hash is to be stored
*
* Returns the status of the Flash operation.
*
*******************************************************************************/
static cy_en_flashdrv_status_t Cy_Flash_CalculateHash_Ext(const cy_stc_flash_computehash_config_t *config, uint32_t* hashPtr)
{
/* Checks whether the input parameters are valid */
if ((config->startAddr == NULL) || (config->numOfByte == 0UL) || (hashPtr == NULL))
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Prepares arguments to be passed to SROM API */
un_srom_api_args_t apiArgs = {{ 0UL }};
apiArgs.ComputeHash.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_HASH;
apiArgs.ComputeHash.arg0.type = (uint32_t)config->type;
apiArgs.ComputeHash.arg1.start_addr = (uint32_t)config->startAddr;
apiArgs.ComputeHash.arg2.number_byte = (config->numOfByte - 1UL);
/* Call SROM API with blocking mode */
un_srom_api_resps_t apiResp = {{ 0UL }};
cy_en_srom_driver_status_t sromDrvStatus;
sromDrvStatus = Cy_Srom_CallApi(&apiArgs, &apiResp);
if(sromDrvStatus == CY_SROM_DR_IPC_BUSY)
{
return CY_FLASH_DRV_IPC_BUSY;
}
else if(sromDrvStatus == CY_SROM_DR_TIMEOUT)
{
return CY_FLASH_DRV_SROM_API_TIMEOUT;
}
else if(sromDrvStatus == CY_SROM_DR_API_UNKNOWN)
{
return CY_FLASH_DRV_ERR_UNC;
}
else
{
/* non-empty terminating "else" statement. */
}
/* Process response message from API */
cy_en_flashdrv_status_t result;
result = Cy_Flash_ProcessOpcode(apiResp.resp[0]);
if(result == CY_FLASH_DRV_SUCCESS)
{
*hashPtr = apiResp.ComputeHash.resp0.hash_crc;
}
return result;
}
/*******************************************************************************
* Function Name: Cy_Flash_WorkBoundsCheck
****************************************************************************//**
*
* Checks if Flash address is out of work region.
*
* address Address to be checked
*
* en_flash_bounds_t
*
*******************************************************************************/
static en_flash_bounds_t Cy_Flash_WorkBoundsCheck(uint32_t address)
{
cy_en_bankmode_t bankmode = Cy_Flashc_GetWorkBankMode();
if(bankmode == CY_FLASH_SINGLE_BANK_MODE)
{
if(( CY_WFLASH_LG_SBM_TOP <= address) && (address < CY_WFLASH_LG_SBM_END))
{
return(CY_FLASH_IN_BOUNDS);
}
if((CY_WFLASH_SM_SBM_TOP <= address) && (address < CY_WFLASH_SM_SBM_END))
{
return(CY_FLASH_IN_BOUNDS);
}
}
else
{
if(( CY_WFLASH_LG_DBM0_TOP <= address) && (address < CY_WFLASH_LG_DBM0_END))
{
return(CY_FLASH_IN_BOUNDS);
}
if(( CY_WFLASH_SM_DBM0_TOP <= address) && (address < CY_WFLASH_SM_DBM0_END))
{
return(CY_FLASH_IN_BOUNDS);
}
if(( CY_WFLASH_LG_DBM1_TOP <= address) && (address < CY_WFLASH_LG_DBM1_END))
{
return(CY_FLASH_IN_BOUNDS);
}
if(( CY_WFLASH_SM_DBM1_TOP <= address) && (address < CY_WFLASH_SM_DBM1_END))
{
return(CY_FLASH_IN_BOUNDS);
}
}
return(CY_FLASH_OUT_OF_BOUNDS);
}
/*******************************************************************************
* Function Name: Cy_Flash_MainBoundsCheck
****************************************************************************//**
*
* Returns 1 if Flash address is out of main region, otherwise returns 0.
*
* address Address to be checked
*
* 1 - out of bound, 0 - in flash bounds
*
*******************************************************************************/
static en_flash_bounds_t Cy_Flash_MainBoundsCheck(uint32_t address)
{
cy_en_bankmode_t bankmode = Cy_Flashc_GetMainBankMode();
if(bankmode == CY_FLASH_SINGLE_BANK_MODE)
{
if(( CY_FLASH_LG_SBM_TOP <= address) && (address < CY_FLASH_LG_SBM_END))
{
return(CY_FLASH_IN_BOUNDS);
}
if(( CY_FLASH_SM_SBM_TOP <= address) && (address < CY_FLASH_SM_SBM_END))
{
return(CY_FLASH_IN_BOUNDS);
}
}
else
{
if(( CY_FLASH_LG_DBM0_TOP <= address) && (address < CY_FLASH_LG_DBM0_END))
{
return(CY_FLASH_IN_BOUNDS);
}
if(( CY_FLASH_SM_DBM0_TOP <= address) && (address < CY_FLASH_SM_DBM0_END))
{
return(CY_FLASH_IN_BOUNDS);
}
if(( CY_FLASH_LG_DBM1_TOP <= address) && (address < CY_FLASH_LG_DBM1_END))
{
return(CY_FLASH_IN_BOUNDS);
}
if(( CY_FLASH_SM_DBM1_TOP <= address) && (address < CY_FLASH_SM_DBM1_END))
{
return(CY_FLASH_IN_BOUNDS);
}
}
return(CY_FLASH_OUT_OF_BOUNDS);
}
/*******************************************************************************
* Function Name: Cy_Flash_BoundsCheck
****************************************************************************//**
*
* Returns 1 if Flash address is out of boundary, otherwise returns 0.
*
* flashAddr Address to be checked
*
* 1 - out of bound, 0 - in flash bounds
*
*******************************************************************************/
static en_flash_bounds_t Cy_Flash_BoundsCheck(uint32_t flashAddr)
{
if(Cy_Flash_WorkBoundsCheck(flashAddr) == CY_FLASH_IN_BOUNDS)
{
return(CY_FLASH_IN_BOUNDS);
}
if(Cy_Flash_MainBoundsCheck(flashAddr) == CY_FLASH_IN_BOUNDS)
{
return(CY_FLASH_IN_BOUNDS);
}
return (CY_FLASH_OUT_OF_BOUNDS);
}
/*******************************************************************************
* Function Name: Cy_Flash_ProcessOpcode
****************************************************************************//**
*
* Converts System Call returns to the Flash driver return defines.
*
* opcode The value returned by the System Call.
*
* Flash driver return. cy_en_flashdrv_status_t only support a
* part of SROM response. please use Cy_Srom_GetApiResponse to
* get complete status of SROM API.
*
*******************************************************************************/
static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode)
{
cy_en_flashdrv_status_t retVal;
cy_en_srom_api_status_t apiStatus;
apiStatus = Cy_Srom_ConvertRespToStatus(opcode);
// Process error code
switch (apiStatus)
{
case CY_SROM_STATUS_SUCCESS:
retVal = CY_FLASH_DRV_SUCCESS;
break;
case CY_SROM_STATUS_INVALID:
retVal = CY_FLASH_DRV_ERR_UNC;
break;
case CY_SROM_STATUS_INVALID_PROTECTION:
retVal = CY_FLASH_DRV_INV_PROT;
break;
case CY_SROM_STATUS_INVALID_FM_PL:
retVal = CY_FLASH_DRV_INVALID_FM_PL;
break;
case CY_SROM_STATUS_INVALID_FLASH_ADDR:
retVal = CY_FLASH_DRV_INVALID_FLASH_ADDR;
break;
case CY_SROM_STATUS_NVM_PROTECTED:
retVal = CY_FLASH_DRV_ROW_PROTECTED;
break;
case CY_SROM_STATUS_INVALID_IPC_STRUCT:
retVal = CY_FLASH_DRV_IPC_BUSY;
break;
case CY_SROM_STAUTS_CHECKSUM_NON_ZERO:
retVal = CY_FLASH_DRV_CHECKSUM_NON_ZERO;
break;
case CY_SROM_STATUS_SECTOR_SUSPEND:
retVal = CY_FLASH_DRV_SECTOR_SUSPEND;
break;
case CY_SROM_STATUS_NO_ERASE_SUSPEND:
retVal = CY_FLASH_DRV_NO_ERASE_SUSPEND;
break;
case CY_SROM_STATUS_FLASH_NOT_ERASED:
retVal = CY_FLASH_DRV_FLASH_NOT_ERASED;
break;
case CY_SROM_STATUS_NO_ERASE_ONGOING:
retVal = CY_FLASH_DRV_NO_ERASE_ONGOING;
break;
case CY_SROM_STATUS_ACTIVE_ERASE:
retVal = CY_FLASH_DRV_ACTIVE_ERASE;
break;
case CY_SROM_STAUTS_INVALID_DATA_WIDTH:
retVal = CY_FLASH_DRV_INVALID_DATA_WIDTH;
break;
case CY_SROM_STATUS_FLASH_SAFTEY_ENABLED:
retVal = CY_FLASH_DRV_FLASH_SAFTEY_ENABLED;
break;
case CY_SROM_STATUS_INVALID_SFLASH_ADDR:
retVal = CY_FLASH_DRV_INVALID_SFLASH_ADDR;
break;
case CY_SROM_STATUS_SFLASH_BACKUP_ERASED:
retVal = CY_FLASH_DRV_SFLASH_BACKUP_ERASED;
break;
default:
retVal = CY_FLASH_DRV_ERR_UNC;
break;
}
return (retVal);
}
/*******************************************************************************
* Function Name: Cy_Flash_EraseSector_Ext
****************************************************************************//**
*
* This function Starts the sector erase operation on the specified sector.
* This function cannot be called on SFLASH. Reports success
* or a reason for failure.
* Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in the case when another
* process is operating flash. User firmware should not enter the hibernate
* mode until flash Erase is complete. The Flash operation is allowed in Sleep and
* Deep-sleep modes. 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.
*
* config configuration of this function.
* This parameter is defined by the cy_stc_flash_erasesector_config_t
* in group_flash_srom_config_structure macro.
*
* Returns the status of the Flash operation (see cy_en_flashdrv_status_t).
*
*******************************************************************************/
static cy_en_flashdrv_status_t Cy_Flash_EraseSector_Ext(const cy_stc_flash_erasesector_config_t *config, cy_en_flash_driver_blocking_t block)
{
cy_en_flashdrv_status_t status;
/* Checks if input pointers are not NULL */
if (config == NULL)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Checks if input address is in work/main region */
if(Cy_Flash_BoundsCheck((uint32_t)(config->sectorAddr)) == CY_FLASH_OUT_OF_BOUNDS)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Checks if input address is word aligned */
if(((uint32_t)(config->sectorAddr) % sizeof(uint32_t)) != 0UL)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Prepares arguments to be passed to SROM API */
un_srom_api_args_t apiArgs = {{ 0UL }};
apiArgs.EraseSector.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_ERASE_SECTOR;
apiArgs.EraseSector.arg0.blocking = (uint32_t)config->blocking;
apiArgs.EraseSector.arg0.interruptMask = (uint32_t)config->intrMask;
apiArgs.EraseSector.arg1.address = (uint32_t)config->sectorAddr;
/* Call SROM API driver and process response */
status = Cy_Flash_CallSromApiForFlashWrite(&apiArgs, block);
return status;
}
/*******************************************************************************
* Function Name: Cy_Flash_EraseSuspend
****************************************************************************//**
*
* This function suspends an ongoing erase operation. User should not read from a
* sector which is suspended from an erase operation. Cy_Flash_ProgramRow function
* will return error if invoked on suspended sector.
* This function cannot be called on SFLASH. Reports success
* or a reason for failure. Does not return until the Erase operation is complete.
* Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in the case when another
* process is operating flash.
* This function supports only blocking mode for now.
*
* Returns the status of the Flash operation (see cy_en_flashdrv_status_t).
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_EraseSuspend(void)
{
/* Prepares arguments to be passed to SROM API */
un_srom_api_args_t apiArgs = {{ 0UL }};
apiArgs.EraseSuspend.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_ERASE_SUSPEND;
/* Call SROM API with blocking mode */
un_srom_api_resps_t apiResp = {{ 0UL }};
cy_en_srom_driver_status_t sromDrvStatus;
sromDrvStatus = Cy_Srom_CallApi(&apiArgs, &apiResp);
if(sromDrvStatus == CY_SROM_DR_IPC_BUSY)
{
return CY_FLASH_DRV_IPC_BUSY;
}
else if(sromDrvStatus == CY_SROM_DR_TIMEOUT)
{
return CY_FLASH_DRV_SROM_API_TIMEOUT;
}
else if(sromDrvStatus == CY_SROM_DR_API_UNKNOWN)
{
return CY_FLASH_DRV_ERR_UNC;
}
else
{
/* non-empty terminating "else" statement. */
}
/* Process response message from API */
cy_en_flashdrv_status_t result;
result = Cy_Flash_ProcessOpcode(apiResp.resp[0]);
if(result == CY_FLASH_DRV_SUCCESS)
{
/* Invalidates the flash cache and buffer */
FLASHC_FLASH_CMD = _VAL2FLD(FLASHC_FLASH_CMD_INV, 1U);
// Wait for completion (HW will clear bit)
while (_FLD2VAL(FLASHC_FLASH_CMD_INV, FLASHC_FLASH_CMD) != 0U)
{
}
}
return result;
}
/*******************************************************************************
* Function Name: Cy_Flash_EraseResume
****************************************************************************//**
*
* This function calls to resume a suspended erase operation.
* Reports success or a reason for failure.
* Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in the case when another
* process is operating flash.
*
* config configuration of this function.
* This parameter is defined by the cy_stc_flash_eraseresume_config_t
* in group_flash_srom_config_structure macro.
*
* Returns the status of the Flash operation (see cy_en_flashdrv_status_t).
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_EraseResume(const cy_stc_flash_eraseresume_config_t *config)
{
/* Checks if input pointers are not NULL */
if (config == NULL)
{
return (cy_en_flashdrv_status_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Prepares arguments to be passed to SROM API */
un_srom_api_args_t apiArgs = {{ 0UL }};
apiArgs.EraseResume.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_ERASE_RESUME;
apiArgs.EraseResume.arg0.blocking = (uint32_t)config->intrMask;
apiArgs.EraseResume.arg0.intrmask = (uint32_t)config->blocking;
/* Call SROM API with blocking mode */
un_srom_api_resps_t apiResp = {{ 0UL }};
cy_en_srom_driver_status_t sromDrvStatus;
sromDrvStatus = Cy_Srom_CallApi(&apiArgs, &apiResp);
if(sromDrvStatus == CY_SROM_DR_IPC_BUSY)
{
return CY_FLASH_DRV_IPC_BUSY;
}
else if(sromDrvStatus == CY_SROM_DR_TIMEOUT)
{
return CY_FLASH_DRV_SROM_API_TIMEOUT;
}
else if(sromDrvStatus == CY_SROM_DR_API_UNKNOWN)
{
return CY_FLASH_DRV_ERR_UNC;
}
else
{
/* Process response message from API */
cy_en_flashdrv_status_t result;
result = Cy_Flash_ProcessOpcode(apiResp.resp[0]);
return result;
}
}
/*******************************************************************************
* Function Name: Cy_Flash_BlankCheck
****************************************************************************//**
*
* This function performs blank check on the addressed work FLASH.
* Reports success or a reason for failure.
* Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in the case when another
* process is operating flash.
*
* config configuration of this function.
* This parameter is defined by the cy_stc_flash_blankcheck_config_t
* in group_flash_srom_config_structure macro.
*
* Returns the status of the Flash operation (see cy_en_flashdrv_status_t).
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_BlankCheck(const cy_stc_flash_blankcheck_config_t *config, cy_en_flash_driver_blocking_t block)
{
/* Checks if input pointers are not NULL */
if (config == NULL)
{
return (cy_en_flashdrv_status_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
if(config->numOfWordsToBeChecked == 0UL)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Checks if input address are valid */
if ((Cy_Flash_WorkBoundsCheck((uint32_t)config->addrToBeChecked) == CY_FLASH_OUT_OF_BOUNDS) ||
(Cy_Flash_WorkBoundsCheck((uint32_t)config->addrToBeChecked + config->numOfWordsToBeChecked*4UL - 1UL) == CY_FLASH_OUT_OF_BOUNDS))
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
/* Prepares arguments to be passed to SROM API */
un_srom_api_args_t apiArgs = {{ 0UL }};
apiArgs.BlankCheck.arg0.opcode = (uint32_t)CY_SROM_OP_FLASH_BLANK_CHECK;
apiArgs.BlankCheck.arg1.addrToBeChecked = (uint32_t)config->addrToBeChecked;
apiArgs.BlankCheck.arg2.numOfWordsToBeChecked = (config->numOfWordsToBeChecked - 1UL);
/* Tries to acquire the IPC structure and pass the arguments to SROM API */
if(block == CY_FLASH_DRIVER_BLOCKING)
{
/* Call SROM API with blocking mode */
un_srom_api_resps_t apiResp = {{ 0UL }};
cy_en_srom_driver_status_t sromDrvStatus;
sromDrvStatus = Cy_Srom_CallApi(&apiArgs, &apiResp);
if(sromDrvStatus == CY_SROM_DR_IPC_BUSY)
{
return CY_FLASH_DRV_IPC_BUSY;
}
else if(sromDrvStatus == CY_SROM_DR_TIMEOUT)
{
return CY_FLASH_DRV_SROM_API_TIMEOUT;
}
else if(sromDrvStatus == CY_SROM_DR_API_UNKNOWN)
{
return CY_FLASH_DRV_ERR_UNC;
}
else
{
/* Process response message from API */
cy_en_flashdrv_status_t result;
result = Cy_Flash_ProcessOpcode(apiResp.resp[0]);
return result;
}
}
else
{
g_non_block_context = (uint8_t)FLASHC_FM_CTL_ECT_STATUS_BLANK_CHECK_WORK_Msk;
/* Send message by IPC */
cy_en_srom_driver_status_t status = Cy_Srom_CallApi_NonBlock(&apiArgs);
if (status != CY_SROM_DR_SUCCEEDED)
{
/* The IPC structure is already locked by another process */
return CY_FLASH_DRV_IPC_BUSY;
}
return CY_FLASH_DRV_SUCCESS;
}
}
/*******************************************************************************
* Function Name: Cy_Flashc_InjectECC
****************************************************************************//**
*
* This function enables ECC injection and sets the address where a parity will be injected
* and the parity value.
* Reports success or a reason for failure.
*
* region An indicator which region (Code/Work/Cache) ECC parity will be injected to.
* This parameter is defined by the cy_en_region_t
* in group_flash_macro macro.
*
* address The address where ECC parity will be injected.
*
* parity The parity value which will be injected.
*
* Returns the status of the Flash operation (see cy_en_flashdrv_status_t).
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flashc_InjectECC(cy_en_region_t region, uint32_t address, uint8_t parity)
{
cy_en_flashdrv_status_t result =CY_FLASH_DRV_SUCCESS;
switch(region)
{
case CY_FLASH_MAIN_REGION:
if (Cy_Flash_MainBoundsCheck(address) == CY_FLASH_OUT_OF_BOUNDS)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
FLASHC_FLASH_CTL |= _VAL2FLD(FLASHC_FLASH_CTL_MAIN_ECC_INJ_EN, 1U);
FLASHC_ECC_CTL = (_VAL2FLD(FLASHC_ECC_CTL_WORD_ADDR, (address >> CY_FLASH_CODE_ECC_INJECT_POS)) |
_VAL2FLD(FLASHC_ECC_CTL_PARITY, parity ));
break;
case CY_FLASH_WORK_REGION:
if (Cy_Flash_WorkBoundsCheck(address) == CY_FLASH_OUT_OF_BOUNDS)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
FLASHC_FLASH_CTL |= _VAL2FLD(FLASHC_FLASH_CTL_WORK_ECC_INJ_EN, 1U);
FLASHC_ECC_CTL = (_VAL2FLD(FLASHC_ECC_CTL_WORD_ADDR, (address >> CY_FLASH_WORK_ECC_INJECT_POS)) |
_VAL2FLD(FLASHC_ECC_CTL_PARITY, parity ));
break;
case CY_FLASH_CA_CM0P_REGION:
if (Cy_Flash_MainBoundsCheck(address) == CY_FLASH_OUT_OF_BOUNDS)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
FLASHC_FLASH_CTL |= _VAL2FLD(FLASHC_CM0_CA_CTL0_RAM_ECC_INJ_EN, 1U);
FLASHC_ECC_CTL = (_VAL2FLD(FLASHC_ECC_CTL_WORD_ADDR, (address >> CY_FLASH_CACHE_ECC_INJECT_POS)) |
_VAL2FLD(FLASHC_ECC_CTL_PARITY, parity ));
break;
default:
// Default case. Nothing to do.
break;
}
return result;
}
/*******************************************************************************
* Function Name: Cy_Flashc_InjectECC_Disable
****************************************************************************//**
*
* This function disables ECC injection for the region specified.
*
* \note This function is applicable for CAT1C devices.
*
*******************************************************************************/
void Cy_Flashc_InjectECC_Disable(cy_en_region_t region)
{
switch(region)
{
case CY_FLASH_MAIN_REGION:
FLASHC_FLASH_CTL &= ~FLASHC_FLASH_CTL_MAIN_ECC_INJ_EN_Msk;
break;
case CY_FLASH_WORK_REGION:
FLASHC_FLASH_CTL &= ~FLASHC_FLASH_CTL_WORK_ECC_INJ_EN_Msk;
break;
case CY_FLASH_CA_CM0P_REGION:
FLASHC_FLASH_CTL &= ~FLASHC_CM0_CA_CTL0_RAM_ECC_INJ_EN_Msk;
break;
default:
// Default case. Nothing to do.
break;
}
}
/*******************************************************************************
* Function Name: Cy_Flash_OperationStatus
****************************************************************************//**
*
* Checks the status of the Flash Operation, and returns it.
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void)
{
un_srom_api_resps_t resp = {{ 0UL }};
if(0UL != (FLASHC_FM_CTL_ECT_FLASH_STATUS & g_non_block_context))
{
return CY_FLASH_DRV_OPERATION_STARTED;
}
else
{
g_non_block_context = 0;
cy_en_srom_api_status_t status = Cy_Srom_GetApiResponse(&resp);
if(CY_SROM_STATUS_SUCCESS == status)
{
return Cy_Flash_ProcessOpcode(resp.resp[0]);
}
else
{
return CY_FLASH_DRV_ERR_UNC;
}
}
}
/*******************************************************************************
* Function Name: Cy_Flash_StartWrite
****************************************************************************//**
*
* 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.
*
* rowAddr Address of the flash row number.
* 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.
*
* 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.
*
* 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;
uint32_t prog_length = (uint32_t)ADDRESS_LENGTH_32_BIT;
uint32_t data_length = (uint32_t)DATA_LENGTH_32_BIT;
if (data == NULL)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
else
{
cy_stc_flash_programrow_config_t flash_programrow_config =
{
.destAddr = (const uint32_t *)rowAddr,
.dataAddr = (const uint32_t *)data,
.blocking = CY_FLASH_PROGRAMROW_NON_BLOCKING,
.skipBC = CY_FLASH_PROGRAMROW_SKIP_BLANK_CHECK,
.dataSize = CY_FLASH_PROGRAMROW_DATA_SIZE_32BIT,
.dataLoc = CY_FLASH_PROGRAMROW_DATA_LOCATION_SRAM,
.intrMask = CY_FLASH_PROGRAMROW_SET_INTR_MASK,
};
/* Checks whether the input parameters are valid */
if(Cy_Flash_WorkBoundsCheck(rowAddr) == CY_FLASH_IN_BOUNDS)
{
flash_programrow_config.dataSize = CY_FLASH_PROGRAMROW_DATA_SIZE_32BIT;
}
else if(Cy_Flash_MainBoundsCheck(rowAddr) == CY_FLASH_IN_BOUNDS)
{
prog_length = ADDRESS_LENGTH_256_BIT;
data_length = DATA_LENGTH_256_BIT;
flash_programrow_config.dataSize = CY_FLASH_PROGRAMROW_DATA_SIZE_256BIT;
}
else
{
/* non-empty terminating "else" statement */
}
for(uint32_t i_addr = rowAddr; i_addr < rowAddr + CY_FLASH_SIZEOF_ROW; i_addr+=prog_length)
{
flash_programrow_config.destAddr = (const uint32_t *)i_addr;
flash_programrow_config.dataAddr = (const uint32_t *)(data);
g_non_block_context = (uint8_t)(FLASHC_FM_CTL_ECT_STATUS_PGM_WORK_Msk | FLASHC_FM_CTL_ECT_STATUS_PGM_CODE_Msk);
result = Cy_Flash_Program(&flash_programrow_config,CY_FLASH_DRIVER_NON_BLOCKING);
if(result == CY_FLASH_DRV_OPERATION_STARTED)
{
while((Cy_Flash_IsOperationComplete() != CY_FLASH_DRV_SUCCESS))
{
}
data+=data_length;
}
else
{
return result;
}
}
}
return CY_FLASH_DRV_OPERATION_STARTED;
}
/*******************************************************************************
* Function Name: Cy_Flash_StartEraseSector
****************************************************************************//**
*
* Starts erasing a sector of flash. Returns immediately
* and reports a successful start or reason for failure.
* Reports a 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.
* Before reading data from previously programmed/erased flash rows, the
* user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
* function.
*
*
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_StartEraseSector(uint32_t sectorAddr)
{
cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
/* Checks whether the input parameters are valid */
if(Cy_Flash_BoundsCheck((uint32_t)(sectorAddr)) == CY_FLASH_OUT_OF_BOUNDS)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
cy_stc_flash_erasesector_config_t flash_erasesector_config =
{
.sectorAddr = (const uint32_t *)sectorAddr,
.blocking = CY_FLASH_ERASESECTOR_NON_BLOCKING,
.intrMask = CY_FLASH_ERASESECTOR_SET_INTR_MASK,
};
g_non_block_context = (uint8_t)(FLASHC_FM_CTL_ECT_STATUS_ERASE_CODE_Msk | FLASHC_FM_CTL_ECT_STATUS_ERASE_WORK_Msk);
result = Cy_Flash_EraseSector_Ext(&flash_erasesector_config, CY_FLASH_DRIVER_NON_BLOCKING);
if(result != CY_FLASH_DRV_SUCCESS)
{
return result;
}
return CY_FLASH_DRV_OPERATION_STARTED;
}
/*******************************************************************************
* 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.
*
*******************************************************************************/
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;
uint32_t prog_length = (uint32_t)ADDRESS_LENGTH_32_BIT;
uint32_t data_length = (uint32_t)DATA_LENGTH_32_BIT;
if (data == NULL)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
cy_stc_flash_programrow_config_t flash_programrow_config =
{
.destAddr = (const uint32_t *)rowAddr,
.dataAddr = (const uint32_t *)data,
.blocking = CY_FLASH_PROGRAMROW_BLOCKING,
.skipBC = CY_FLASH_PROGRAMROW_SKIP_BLANK_CHECK,
.dataSize = CY_FLASH_PROGRAMROW_DATA_SIZE_32BIT,
.dataLoc = CY_FLASH_PROGRAMROW_DATA_LOCATION_SRAM,
.intrMask = CY_FLASH_PROGRAMROW_NOT_SET_INTR_MASK,
};
/* Checks whether the input parameters are valid */
if(Cy_Flash_WorkBoundsCheck(rowAddr) == CY_FLASH_IN_BOUNDS)
{
flash_programrow_config.dataSize = CY_FLASH_PROGRAMROW_DATA_SIZE_32BIT;
}
else if(Cy_Flash_MainBoundsCheck(rowAddr) == CY_FLASH_IN_BOUNDS)
{
prog_length = ADDRESS_LENGTH_256_BIT;
data_length = DATA_LENGTH_256_BIT;
flash_programrow_config.dataSize = CY_FLASH_PROGRAMROW_DATA_SIZE_256BIT;
}
else
{
/* empty else statement. */
}
for(uint32_t i_addr = rowAddr; i_addr < rowAddr + CY_FLASH_SIZEOF_ROW; i_addr+=prog_length)
{
flash_programrow_config.destAddr = (const uint32_t *)i_addr;
flash_programrow_config.dataAddr = (const uint32_t *)(data);
result = Cy_Flash_Program(&flash_programrow_config, CY_FLASH_DRIVER_BLOCKING);
if(result != CY_FLASH_DRV_SUCCESS)
{
break;
}
data+=data_length;
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_EraseSector
****************************************************************************//**
*
* This function erases a sector of flash. Reports success or
* a reason for failure. Does not return until the Erase 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 sectorAddr Address of the flash row number.
* 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_EraseSector(uint32_t sectorAddr)
{
cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
/* Checks whether the input parameters are valid */
if(Cy_Flash_BoundsCheck((uint32_t)(sectorAddr)) == CY_FLASH_OUT_OF_BOUNDS)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
cy_stc_flash_erasesector_config_t flash_erasesector_config =
{
.sectorAddr = (const uint32_t *)sectorAddr,
.blocking = CY_FLASH_ERASESECTOR_BLOCKING,
.intrMask = CY_FLASH_ERASESECTOR_NOT_SET_INTR_MASK,
};
result = Cy_Flash_EraseSector_Ext(&flash_erasesector_config, CY_FLASH_DRIVER_BLOCKING);
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_CalculateHash
****************************************************************************//**
*
* Returns a hash value of the specified region of flash.
*
*******************************************************************************/
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;
/* Checks whether the input parameters are valid */
if ((data == NULL) || (numberOfBytes == 0UL) || (hashPtr == NULL))
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
cy_stc_flash_computehash_config_t flash_computehash_config =
{
.startAddr = (const uint32_t *)data,
.numOfByte = numberOfBytes,
.type = CY_FLASH_COMPUTEHASH_BASIC,
};
result = Cy_Flash_CalculateHash_Ext(&flash_computehash_config, hashPtr);
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_RowChecksum
****************************************************************************//**
*
* Returns a checksum value of the specified flash row.
*
* \note Now Cy_Flash_RowChecksum() requires the row address (rowAddr)
* as a parameter. In previous versions of the driver, this function used
* the row number (rowNum) for this parameter.
*
* rowAddr The address of the flash row.
*
* checksumPtr The pointer to the address where checksum is to be stored
*
* 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;
uint8_t rowID = 0;
cy_en_flash_checksum_bank_t bank = CY_FLASH_CHECKSUM_BANK0;
cy_en_flash_checksum_region_t region = CY_FLASH_CHECKSUM_MAIN;
/* Checks whether the input parameters are valid */
if ((Cy_Flash_BoundsCheck(rowAddr)== CY_FLASH_OUT_OF_BOUNDS) || (checksumPtr == NULL))
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
if (CY_FLASH_DRV_SUCCESS == Cy_Flash_GetRowDetails(rowAddr,&rowID, &bank, ®ion))
{
cy_stc_flash_checksum_config_t flash_computechecksum_config =
{
.rowId = rowID,
.bank = bank,
.whole = CY_FLASH_CHECKSUM_PAGE,
.region = region,
};
result = Cy_Flash_Checksum(&flash_computechecksum_config, checksumPtr);
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_GetRowDetails
****************************************************************************//**
*
* Returns flash region ID, Bank and row number of the Flash address.
*******************************************************************************/
static cy_en_flashdrv_status_t Cy_Flash_GetRowDetails(uint32_t rowAddr, uint8_t *rowID, cy_en_flash_checksum_bank_t *bank, cy_en_flash_checksum_region_t *region)
{
cy_en_flashdrv_status_t result = CY_FLASH_DRV_SUCCESS;
if (Cy_Flash_WorkBoundsCheck(rowAddr) == CY_FLASH_OUT_OF_BOUNDS)
{
return CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
}
cy_en_bankmode_t bankmode = Cy_Flashc_GetMainBankMode();
if(bankmode == CY_FLASH_SINGLE_BANK_MODE)
{
if ((rowAddr >= CY_WFLASH_LG_SBM_TOP) && (rowAddr < CY_WFLASH_SM_SBM_END))
{
*rowID = (uint8_t)((CY_FLASH_REGION_ID_WFLASH << CY_FLASH_REGION_ID_SHIFT) |
((rowAddr - CY_WFLASH_LG_SBM_TOP) / CY_FLASH_SIZEOF_ROW));
*bank = CY_FLASH_CHECKSUM_BANK0;
*region = CY_FLASH_CHECKSUM_WORK;
}
else if ((rowAddr >= CY_FLASH_LG_SBM_TOP) && (rowAddr < CY_FLASH_SM_SBM_END))
{
*rowID = (uint8_t)((CY_FLASH_REGION_ID_WFLASH << CY_FLASH_REGION_ID_SHIFT) |
((rowAddr - CY_WFLASH_LG_SBM_TOP) / CY_FLASH_SIZEOF_ROW));
*bank = CY_FLASH_CHECKSUM_BANK0;
*region = CY_FLASH_CHECKSUM_MAIN;
}
else
{
/* rowAddr oout of bounds. */
}
}
else
{
if ((rowAddr >= CY_WFLASH_LG_DBM0_TOP) && (rowAddr < CY_WFLASH_SM_DBM0_END))
{
*rowID = (uint8_t)((CY_FLASH_REGION_ID_WFLASH << CY_FLASH_REGION_ID_SHIFT) |
((rowAddr - CY_WFLASH_LG_DBM0_TOP) / CY_FLASH_SIZEOF_ROW));
*bank = CY_FLASH_CHECKSUM_BANK0;
*region = CY_FLASH_CHECKSUM_WORK;
}
else if ((rowAddr >= CY_WFLASH_LG_DBM1_TOP) && (rowAddr < CY_WFLASH_SM_DBM1_END))
{
*rowID = (uint8_t)((CY_FLASH_REGION_ID_WFLASH << CY_FLASH_REGION_ID_SHIFT) |
((rowAddr - CY_WFLASH_LG_SBM_TOP) / CY_FLASH_SIZEOF_ROW));
*bank = CY_FLASH_CHECKSUM_BANK1;
*region = CY_FLASH_CHECKSUM_WORK;
}
else if ((rowAddr >= CY_FLASH_LG_DBM0_TOP) && (rowAddr < CY_FLASH_SM_DBM0_END))
{
*rowID = (uint8_t)((CY_FLASH_REGION_ID_MAIN << CY_FLASH_REGION_ID_SHIFT) |
((rowAddr - CY_FLASH_LG_DBM0_TOP) / CY_FLASH_SIZEOF_ROW));
*bank = CY_FLASH_CHECKSUM_BANK0;
*region = CY_FLASH_CHECKSUM_MAIN;
}
else if ((rowAddr >= CY_FLASH_LG_DBM1_TOP) && (rowAddr < CY_FLASH_SM_DBM1_END))
{
*rowID = (uint8_t)((CY_FLASH_REGION_ID_MAIN << CY_FLASH_REGION_ID_SHIFT) |
((rowAddr - CY_FLASH_LG_DBM1_TOP) / CY_FLASH_SIZEOF_ROW));
*bank = CY_FLASH_CHECKSUM_BANK1;
*region = CY_FLASH_CHECKSUM_MAIN;
}
else
{
/* rowAddr oout of bounds. */
}
}
return (result);
}
/*******************************************************************************
* Function Name: Cy_Flash_Init
****************************************************************************//**
*
* Initiates all needed prerequisites to support flash erase/write.
* Should be called from each core.
*
* 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, ensure to perform the following steps
* before any flash or EmEEPROM write/erase operations:
*
*******************************************************************************/
void Cy_Flash_Init(void)
{
/* In Blocking mode the calling function get's the response and sends it to the user.
* In Non blocking mode user will call operation status and gets the response in return.
* There is no need for the driver to handle error in the interrupt handler.
* Error needs to be passed to the user.
*/
Cy_Srom_SetResponseHandler(NULL);
}
/*******************************************************************************
* Function Name: Cy_Flash_IsOperationComplete
****************************************************************************//**
*
* Reports a successful operation result, reason of failure or busy status
* ( CY_FLASH_DRV_OPCODE_BUSY ).
*******************************************************************************/
cy_en_flashdrv_status_t Cy_Flash_IsOperationComplete(void)
{
return (Cy_Flash_OperationStatus());
}
/*******************************************************************************
* Function Name: Cy_Flashc_MainWriteEnable
****************************************************************************//**
*
* Enable writing main flash
*
*******************************************************************************/
void Cy_Flashc_MainWriteEnable(void)
{
FLASHC_FM_CTL_ECT_MAIN_FLASH_SAFETY |= FLASHC_FM_CTL_ECT_MAIN_FLASH_SAFETY_MAINFLASHWRITEENABLE_Msk;
}
/*******************************************************************************
* Function Name: Cy_Flashc_MainWriteDisable
****************************************************************************//**
*
* Disable writing main flash
*
*******************************************************************************/
void Cy_Flashc_MainWriteDisable(void)
{
FLASHC_FM_CTL_ECT_MAIN_FLASH_SAFETY &= (uint32_t) ~FLASHC_FM_CTL_ECT_MAIN_FLASH_SAFETY_MAINFLASHWRITEENABLE_Msk;
}
/*******************************************************************************
* Function Name: Cy_Flashc_WorkWriteEnable
****************************************************************************//**
*
* Enable writing work flash
*
*******************************************************************************/
void Cy_Flashc_WorkWriteEnable(void)
{
FLASHC_FM_CTL_ECT_WORK_FLASH_SAFETY |= FLASHC_FM_CTL_ECT_WORK_FLASH_SAFETY_WORKFLASHWRITEENABLE_Msk;
}
/*******************************************************************************
* Function Name: Cy_Flashc_WorkWriteDisable
****************************************************************************//**
*
* Disable writing work flash
*
*******************************************************************************/
void Cy_Flashc_WorkWriteDisable(void)
{
FLASHC_FM_CTL_ECT_WORK_FLASH_SAFETY &= (uint32_t) ~FLASHC_FM_CTL_ECT_WORK_FLASH_SAFETY_WORKFLASHWRITEENABLE_Msk;
}
/*******************************************************************************
* Function Name: Cy_Flashc_WorkECCEnable
****************************************************************************//**
*
* Enables ECC for work flash
*
*******************************************************************************/
void Cy_Flashc_WorkECCEnable(void)
{
FLASHC_FLASH_CTL |= FLASHC_FLASH_CTL_WORK_ECC_EN_Msk;
}
/*******************************************************************************
* Function Name: Cy_Flashc_WorkECCDisable
****************************************************************************//**
*
* Disables ECC for work flash
*
*******************************************************************************/
void Cy_Flashc_WorkECCDisable(void)
{
FLASHC_FLASH_CTL &= (uint32_t) ~FLASHC_FLASH_CTL_WORK_ECC_EN_Msk;
}
/*******************************************************************************
* Function Name: Cy_Flashc_MainECCEnable
****************************************************************************//**
*
* Enables ECC for main flash
*
*******************************************************************************/
void Cy_Flashc_MainECCEnable(void)
{
FLASHC_FLASH_CTL |= FLASHC_FLASH_CTL_MAIN_ECC_EN_Msk;
}
/*******************************************************************************
* Function Name: Cy_Flashc_MainECCDisable
****************************************************************************//**
*
* Disables ECC for main flash
*
*******************************************************************************/
void Cy_Flashc_MainECCDisable(void)
{
FLASHC_FLASH_CTL &= (uint32_t) ~FLASHC_FLASH_CTL_MAIN_ECC_EN_Msk;
}
/*******************************************************************************
* Function Name: Cy_Flashc_SetWorkBankMode
****************************************************************************//**
*
* Sets bank mode for work flash
*
* mode bank mode to be set
*
*******************************************************************************/
void Cy_Flashc_SetWorkBankMode(cy_en_bankmode_t mode)
{
if(CY_FLASH_DUAL_BANK_MODE == mode)
{
FLASHC_FLASH_CTL |= FLASHC_FLASH_CTL_WORK_BANK_MODE_Msk;
}
else
{
FLASHC_FLASH_CTL &= (uint32_t) ~FLASHC_FLASH_CTL_WORK_BANK_MODE_Msk;
}
}
/*******************************************************************************
* Function Name: Cy_Flashc_GetWorkBankMode
****************************************************************************//**
*
* Gets current bank mode for work flash
*
*******************************************************************************/
cy_en_bankmode_t Cy_Flashc_GetWorkBankMode(void)
{
uint32_t bank_mode = _FLD2VAL(FLASHC_FLASH_CTL_WORK_BANK_MODE, FLASHC_FLASH_CTL);
if(bank_mode == 0UL)
{
return CY_FLASH_SINGLE_BANK_MODE;
}
else
{
return CY_FLASH_DUAL_BANK_MODE;
}
}
/*******************************************************************************
* Function Name: Cy_Flashc_SetMainBankMode
****************************************************************************//**
*
* Sets bank mode for main flash
*
* mode bank mode to be set
*
*******************************************************************************/
void Cy_Flashc_SetMainBankMode(cy_en_bankmode_t mode)
{
if(CY_FLASH_DUAL_BANK_MODE == mode)
{
FLASHC_FLASH_CTL |= FLASHC_FLASH_CTL_MAIN_BANK_MODE_Msk;
}
else
{
FLASHC_FLASH_CTL &= (uint32_t) ~FLASHC_FLASH_CTL_MAIN_BANK_MODE_Msk;
}
}
/*******************************************************************************
* Function Name: Cy_Flashc_GetMainBankMode
****************************************************************************//**
*
* Gets current bank mode for main flash
*
*******************************************************************************/
cy_en_bankmode_t Cy_Flashc_GetMainBankMode(void)
{
uint32_t bank_mode = _FLD2VAL(FLASHC_FLASH_CTL_MAIN_BANK_MODE, FLASHC_FLASH_CTL);
if(bank_mode == 0UL)
{
return CY_FLASH_SINGLE_BANK_MODE;
}
else
{
return CY_FLASH_DUAL_BANK_MODE;
}
}
/*******************************************************************************
* Function Name: Cy_Flashc_SetMain_Flash_Mapping
****************************************************************************//**
*
* \brief Sets mapping for main flash region. Applicable only in Dual Bank mode of Main flash region
*
* \param mapping mapping to be set
*
* \return none
*******************************************************************************/
void Cy_Flashc_SetMain_Flash_Mapping(cy_en_maptype_t mapping)
{
FLASHC_FLASH_CTL &= ~FLASHC_FLASH_CTL_MAIN_MAP_Msk;
FLASHC_FLASH_CTL |= _VAL2FLD(FLASHC_FLASH_CTL_MAIN_MAP, mapping);
}
/*******************************************************************************
* Function Name: Cy_Flashc_SetWork_Flash_Mapping
****************************************************************************//**
*
* \brief Sets mapping for work flash region. Applicable only in Dual Bank mode of Work flash region
*
* \param mapping mapping to be set
*
* \return none
*******************************************************************************/
void Cy_Flashc_SetWork_Flash_Mapping(cy_en_maptype_t mapping)
{
FLASHC_FLASH_CTL &= ~FLASHC_FLASH_CTL_WORK_MAP_Msk;
FLASHC_FLASH_CTL |= _VAL2FLD(FLASHC_FLASH_CTL_WORK_MAP, mapping);
}
#endif // defined(CY_IP_MXFLASHC_VERSION_ECT)
/* [] END OF FILE */