uint32 CySysFlashWriteRow(uint32 rowNum, const uint8 rowData[])
{
volatile uint32 retValue = CY_SYS_FLASH_SUCCESS;
volatile uint32 clkCnfRetValue = CY_SYS_FLASH_SUCCESS;
volatile uint32 parameters[(CY_FLASH_SIZEOF_ROW + CY_FLASH_SRAM_ROM_DATA) / sizeof(uint32)];
uint8 interruptState;
#if (CY_FLASH_CHECKSUM_WORKAROUND)
uint32 needChecksumWorkaround = 0u;
uint32 savedIndex = 0u;
uint32 savedValue = 0u;
uint32 checksum = 0u;
uint32 bits = 0u;
uint32 i;
#endif /* (CY_FLASH_CHECKSUM_WORKAROUND) */
if ((rowNum < CY_FLASH_NUMBER_ROWS) && (rowData != 0u))
{
/* Copy data to be written into internal variable */
(void)memcpy((void *)¶meters[2u], rowData, CY_FLASH_SIZEOF_ROW);
#if (CY_FLASH_CHECKSUM_WORKAROUND)
for (i = 2u; i < ((CY_FLASH_SIZEOF_ROW / sizeof(uint32)) + 2u); i++)
{
uint32 tmp = parameters[i];
if (tmp != 0u)
{
checksum += tmp;
bits |= tmp;
savedIndex = i;
}
}
needChecksumWorkaround = ((checksum == 0u) && (bits != 0u)) ? 1u : 0u;
if (needChecksumWorkaround != 0u)
{
savedValue = parameters[savedIndex];
parameters[savedIndex] = 0u;
}
#endif /* (CY_FLASH_CHECKSUM_WORKAROUND) */
/* Load Flash Bytes */
parameters[0u] = (uint32) (CY_FLASH_GET_MACRO_FROM_ROW(rowNum) << CY_FLASH_PARAM_MACRO_SEL_OFFSET) |
(uint32) (CY_FLASH_PAGE_LATCH_START_ADDR << CY_FLASH_PARAM_ADDR_OFFSET ) |
(uint32) (CY_FLASH_KEY_TWO(CY_FLASH_API_OPCODE_LOAD) << CY_FLASH_PARAM_KEY_TWO_OFFSET ) |
CY_FLASH_KEY_ONE;
parameters[1u] = CY_FLASH_SIZEOF_ROW - 1u;
CY_FLASH_CPUSS_SYSARG_REG = (uint32) ¶meters[0u];
CY_FLASH_CPUSS_SYSREQ_REG = CY_FLASH_CPUSS_REQ_START | CY_FLASH_API_OPCODE_LOAD;
CY_NOP;
retValue = CY_FLASH_API_RETURN;
if(retValue == CY_SYS_FLASH_SUCCESS)
{
/***************************************************************
* Mask all the exceptions to guarantee that Flash write will
* occur in the atomic way. It will not affect system call
* execution (flash row write) since it is executed in the NMI
* context.
***************************************************************/
interruptState = CyEnterCriticalSection();
clkCnfRetValue = CySysFlashClockBackup();
#if(CY_IP_SPCIF_SYNCHRONOUS)
if(clkCnfRetValue == CY_SYS_FLASH_SUCCESS)
{
retValue = CySysFlashClockConfig();
}
#endif /* (CY_IP_SPCIF_SYNCHRONOUS) */
if(retValue == CY_SYS_FLASH_SUCCESS)
{
/* Write Row */
parameters[0u] = (uint32) (((uint32) CY_FLASH_KEY_TWO(CY_FLASH_API_OPCODE_WRITE_ROW) << CY_FLASH_PARAM_KEY_TWO_OFFSET) | CY_FLASH_KEY_ONE);
parameters[0u] |= (uint32)(rowNum << 16u);
CY_FLASH_CPUSS_SYSARG_REG = (uint32) ¶meters[0u];
CY_FLASH_CPUSS_SYSREQ_REG = CY_FLASH_CPUSS_REQ_START | CY_FLASH_API_OPCODE_WRITE_ROW;
CY_NOP;
retValue = CY_FLASH_API_RETURN;
}
#if (CY_FLASH_CHECKSUM_WORKAROUND)
if ((retValue == CYRET_SUCCESS) && (needChecksumWorkaround != 0u))
{
(void)memset((void *)¶meters[2u], 0, CY_FLASH_SIZEOF_ROW);
parameters[savedIndex] = savedValue;
/* Load Flash Bytes */
parameters[0u] = (uint32) (CY_FLASH_GET_MACRO_FROM_ROW(rowNum) << CY_FLASH_PARAM_MACRO_SEL_OFFSET) |
(uint32) (CY_FLASH_PAGE_LATCH_START_ADDR << CY_FLASH_PARAM_ADDR_OFFSET ) |
(uint32) (CY_FLASH_KEY_TWO(CY_FLASH_API_OPCODE_LOAD) << CY_FLASH_PARAM_KEY_TWO_OFFSET ) |
CY_FLASH_KEY_ONE;
parameters[1u] = CY_FLASH_SIZEOF_ROW - 1u;
CY_FLASH_CPUSS_SYSARG_REG = (uint32) ¶meters[0u];
CY_FLASH_CPUSS_SYSREQ_REG = CY_FLASH_CPUSS_REQ_START | CY_FLASH_API_OPCODE_LOAD;
CY_NOP;
retValue = CY_FLASH_API_RETURN;
if(retValue == CY_SYS_FLASH_SUCCESS)
{
/* Program Row */
parameters[0u] =
(uint32) (((uint32) CY_FLASH_KEY_TWO(CY_FLASH_API_OPCODE_PROGRAM_ROW) <<
CY_FLASH_PARAM_KEY_TWO_OFFSET) | CY_FLASH_KEY_ONE);
parameters[0u] |= (uint32)(rowNum << 16u);
CY_FLASH_CPUSS_SYSARG_REG = (uint32) ¶meters[0u];
CY_FLASH_CPUSS_SYSREQ_REG = CY_FLASH_CPUSS_REQ_START | CY_FLASH_API_OPCODE_PROGRAM_ROW;
CY_NOP;
retValue = CY_FLASH_API_RETURN;
}
}
#endif /* (CY_FLASH_CHECKSUM_WORKAROUND) */
if(clkCnfRetValue == CY_SYS_FLASH_SUCCESS)
{
clkCnfRetValue = CySysFlashClockRestore();
if(clkCnfRetValue != CY_SYS_FLASH_SUCCESS)
{
retValue = clkCnfRetValue;
}
}
CyExitCriticalSection(interruptState);
}
}
else
{
retValue = CY_SYS_FLASH_INVALID_ADDR;
}
return (retValue);
}
|