mirror of https://github.com/ARMmbed/mbed-os.git
Update serial-flash to 1.1.0.20805
parent
f489d579b0
commit
623e799d63
|
@ -1,98 +0,0 @@
|
||||||
/***************************************************************************//**
|
|
||||||
* \file cy_serial_flash_prog.c
|
|
||||||
*
|
|
||||||
* \brief
|
|
||||||
* Provides variables necessary to inform programming tools how to program the
|
|
||||||
* attached serial flash memory. The variables used here must be placed at
|
|
||||||
* specific locations in order to be detected and used by programming tools
|
|
||||||
* to know that there is an attached memory and its characteristics. Uses the
|
|
||||||
* configuration provided as part of BSP.
|
|
||||||
*
|
|
||||||
********************************************************************************
|
|
||||||
* \copyright
|
|
||||||
* Copyright 2018-2020 Cypress Semiconductor Corporation
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \addtogroup group_board_libs
|
|
||||||
* \{
|
|
||||||
* In addition to the APIs for reading and writting to memory at runtime, this library also
|
|
||||||
* provides support for informing programming tools about the external memory so it can be
|
|
||||||
* be written at the same time as internal flash. This support can be enabled by defining
|
|
||||||
* CY_ENABLE_XIP_PROGRAM while building the application. With this define in place, code
|
|
||||||
* will be generated in the .cy_sflash_user_data & .cy_toc_part2 sections. These locations
|
|
||||||
* can be read by programming tools (eg: Cypress Programmer, OpenOCD, pyOCD) to know that
|
|
||||||
* there is a memory device attached and how to program it.
|
|
||||||
* \} group_board_libs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CY_ENABLE_XIP_PROGRAM)
|
|
||||||
|
|
||||||
#include "cycfg_qspi_memslot.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const cy_stc_smif_block_config_t * smifCfg; /* Pointer to SMIF top-level configuration */
|
|
||||||
const uint32_t null_t; /* NULL termination */
|
|
||||||
} stc_smif_ipblocks_arr_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This data can be placed anywhere in the internal memory, but it must be at a location that
|
|
||||||
* can be determined and used for the calculation of the CRC16 checksum in the cyToc below. There
|
|
||||||
* are multiple ways this can be accomplished including:
|
|
||||||
* 1) Placing it in a dedicated memory block with a known address. (as done here)
|
|
||||||
* 2) Placing it at an absolute location via a the linker script
|
|
||||||
* 3) Using 'cymcuelftool -S' to recompute the checksum and patch the elf file after linking
|
|
||||||
*/
|
|
||||||
CY_SECTION(".cy_sflash_user_data") __attribute__( (used) )
|
|
||||||
const stc_smif_ipblocks_arr_t smifIpBlocksArr = {&smifBlockConfig, 0x00000000};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This data is used to populate the table of contents part 2. When present, it is used by the boot
|
|
||||||
* process and programming tools to determine key characteristics about the memory usage including
|
|
||||||
* where the boot process should start the application from and what external memories are connected
|
|
||||||
* (if any). This must consume a full row of flash memory row. The last entry is a checksum of the
|
|
||||||
* other values in the ToC which must be updated if any other value changes. This can be done manually
|
|
||||||
* or by running 'cymcuelftool -S' to recompute the checksum.
|
|
||||||
*/
|
|
||||||
CY_SECTION(".cy_toc_part2") __attribute__( (used) )
|
|
||||||
const uint32_t cyToc[128] =
|
|
||||||
{
|
|
||||||
0x200-4, /* Offset=0x0000: Object Size, bytes */
|
|
||||||
0x01211220, /* Offset=0x0004: Magic Number (TOC Part 2, ID) */
|
|
||||||
0, /* Offset=0x0008: Key Storage Address */
|
|
||||||
(int)&smifIpBlocksArr, /* Offset=0x000C: This points to a null terminated array of SMIF structures. */
|
|
||||||
0x10000000u, /* Offset=0x0010: App image start address */
|
|
||||||
/* Offset=0x0014-0x01F7: Reserved */
|
|
||||||
[126] = 0x000002C2, /* Offset=0x01F8: Bits[ 1: 0] CLOCK_CONFIG (0=8MHz, 1=25MHz, 2=50MHz, 3=100MHz)
|
|
||||||
Bits[ 4: 2] LISTEN_WINDOW (0=20ms, 1=10ms, 2=1ms, 3=0ms, 4=100ms)
|
|
||||||
Bits[ 6: 5] SWJ_PINS_CTL (0/1/3=Disable SWJ, 2=Enable SWJ)
|
|
||||||
Bits[ 8: 7] APP_AUTHENTICATION (0/2/3=Enable, 1=Disable)
|
|
||||||
Bits[10: 9] FB_BOOTLOADER_CTL: UNUSED */
|
|
||||||
[127] = 0x3BB30000 /* Offset=0x01FC: CRC16-CCITT (the upper 2 bytes contain the CRC and the lower 2 bytes are 0) */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(CY_ENABLE_XIP_PROGRAM) */
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,234 +0,0 @@
|
||||||
/***************************************************************************//**
|
|
||||||
* \file cy_serial_flash_qspi.c
|
|
||||||
*
|
|
||||||
* \brief
|
|
||||||
* Provides APIs for interacting with an external flash connected to the SPI or
|
|
||||||
* QSPI interface, uses SFDP to auto-discover memory properties if SFDP is
|
|
||||||
* enabled in the configuration.
|
|
||||||
*
|
|
||||||
********************************************************************************
|
|
||||||
* \copyright
|
|
||||||
* Copyright 2018-2020 Cypress Semiconductor Corporation
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "cy_serial_flash_qspi.h"
|
|
||||||
#include "cyhal_qspi.h"
|
|
||||||
#include "cy_utils.h"
|
|
||||||
|
|
||||||
#ifdef CY_IP_MXSMIF
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** \cond INTERNAL */
|
|
||||||
|
|
||||||
/** Timeout to apply while polling the memory for its ready status after quad
|
|
||||||
* enable command has been sent out. Quad enable is a non-volatile write.
|
|
||||||
*/
|
|
||||||
#define CY_SERIAL_FLASH_QUAD_ENABLE_TIMEOUT_US (5000lu) /* in microseconds */
|
|
||||||
|
|
||||||
/* Number of memories supported by the driver */
|
|
||||||
#define SMIF_MEM_DEVICES (1u)
|
|
||||||
|
|
||||||
/* SMIF slot from which the memory configuration is picked up - fixed to 0 as the driver
|
|
||||||
* supports only one device */
|
|
||||||
#define MEM_SLOT (0u)
|
|
||||||
|
|
||||||
/** \endcond */
|
|
||||||
|
|
||||||
static cyhal_qspi_t qspi_obj;
|
|
||||||
|
|
||||||
static cy_stc_smif_mem_config_t * qspi_mem_config[SMIF_MEM_DEVICES];
|
|
||||||
|
|
||||||
static cy_stc_smif_block_config_t qspi_block_config =
|
|
||||||
{
|
|
||||||
/* The number of SMIF memories defined. */
|
|
||||||
.memCount = SMIF_MEM_DEVICES,
|
|
||||||
/* The pointer to the array of memory config structures of size memCount. */
|
|
||||||
.memConfig = (cy_stc_smif_mem_config_t**)qspi_mem_config,
|
|
||||||
/* The version of the SMIF driver. */
|
|
||||||
.majorVersion = CY_SMIF_DRV_VERSION_MAJOR,
|
|
||||||
/* The version of the SMIF driver. */
|
|
||||||
.minorVersion = CY_SMIF_DRV_VERSION_MINOR
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The driver supports only one memory. When multiple memory configurations
|
|
||||||
* are generated by the SMIF configurator tool, provide only the
|
|
||||||
* configuration for memory that need to be supported by the driver.
|
|
||||||
* Memory configuration can be changed by deinit followed by init with new
|
|
||||||
* configuration */
|
|
||||||
cy_rslt_t cy_serial_flash_qspi_init(
|
|
||||||
const cy_stc_smif_mem_config_t* mem_config,
|
|
||||||
cyhal_gpio_t io0,
|
|
||||||
cyhal_gpio_t io1,
|
|
||||||
cyhal_gpio_t io2,
|
|
||||||
cyhal_gpio_t io3,
|
|
||||||
cyhal_gpio_t io4,
|
|
||||||
cyhal_gpio_t io5,
|
|
||||||
cyhal_gpio_t io6,
|
|
||||||
cyhal_gpio_t io7,
|
|
||||||
cyhal_gpio_t sclk,
|
|
||||||
cyhal_gpio_t ssel,
|
|
||||||
uint32_t hz)
|
|
||||||
{
|
|
||||||
cy_en_smif_status_t smifStatus = CY_SMIF_SUCCESS;
|
|
||||||
|
|
||||||
|
|
||||||
cy_rslt_t result = cyhal_qspi_init(&qspi_obj, io0, io1, io2, io3, io4, io5, io6, io7,
|
|
||||||
sclk, ssel, hz, 0);
|
|
||||||
|
|
||||||
qspi_mem_config[MEM_SLOT] = (cy_stc_smif_mem_config_t*) mem_config;
|
|
||||||
|
|
||||||
if(CY_RSLT_SUCCESS == result)
|
|
||||||
{
|
|
||||||
/* Perform SFDP detection and XIP register configuration depending on the
|
|
||||||
* memory configuration.
|
|
||||||
*/
|
|
||||||
smifStatus = Cy_SMIF_MemInit(qspi_obj.base, &qspi_block_config, &qspi_obj.context);
|
|
||||||
if(CY_SMIF_SUCCESS == smifStatus)
|
|
||||||
{
|
|
||||||
/* Enable Quad mode (1-1-4 or 1-4-4 modes) to use all the four I/Os during
|
|
||||||
* communication.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->readCmd->dataWidth == CY_SMIF_WIDTH_QUAD
|
|
||||||
|| qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->programCmd->dataWidth == CY_SMIF_WIDTH_QUAD)
|
|
||||||
{
|
|
||||||
bool isQuadEnabled = false;
|
|
||||||
smifStatus = Cy_SMIF_MemIsQuadEnabled(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], &isQuadEnabled, &qspi_obj.context);
|
|
||||||
if(CY_SMIF_SUCCESS == smifStatus)
|
|
||||||
{
|
|
||||||
if(!isQuadEnabled)
|
|
||||||
{
|
|
||||||
smifStatus = Cy_SMIF_MemEnableQuadMode(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], CY_SERIAL_FLASH_QUAD_ENABLE_TIMEOUT_US, &qspi_obj.context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if((CY_RSLT_SUCCESS != result) || (CY_SMIF_SUCCESS != smifStatus))
|
|
||||||
{
|
|
||||||
cy_serial_flash_qspi_deinit();
|
|
||||||
|
|
||||||
if(CY_SMIF_SUCCESS != smifStatus)
|
|
||||||
{
|
|
||||||
result = (cy_rslt_t)smifStatus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cy_serial_flash_qspi_deinit(void)
|
|
||||||
{
|
|
||||||
if (qspi_obj.base != NULL)
|
|
||||||
{
|
|
||||||
Cy_SMIF_MemDeInit(qspi_obj.base);
|
|
||||||
}
|
|
||||||
|
|
||||||
cyhal_qspi_free(&qspi_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cy_serial_flash_qspi_get_size(void)
|
|
||||||
{
|
|
||||||
return (size_t)qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->memSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* address is ignored for the memory with uniform sector size. Currently,
|
|
||||||
* QSPI Configurator does not support memories with hybrid sectors.
|
|
||||||
*/
|
|
||||||
size_t cy_serial_flash_qspi_get_erase_size(uint32_t addr)
|
|
||||||
{
|
|
||||||
CY_UNUSED_PARAMETER(addr);
|
|
||||||
return (size_t)qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->eraseSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cy_serial_flash_qspi_get_prog_size(uint32_t addr)
|
|
||||||
{
|
|
||||||
CY_UNUSED_PARAMETER(addr);
|
|
||||||
return (size_t)qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->programSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
cy_rslt_t cy_serial_flash_qspi_read(uint32_t addr, size_t length, uint8_t *buf)
|
|
||||||
{
|
|
||||||
/* Cy_SMIF_MemRead() returns error if (addr + length) > total flash size. */
|
|
||||||
return (cy_rslt_t)Cy_SMIF_MemRead(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], addr, buf, length, &qspi_obj.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
cy_rslt_t cy_serial_flash_qspi_write(uint32_t addr, size_t length, const uint8_t *buf)
|
|
||||||
{
|
|
||||||
/* Cy_SMIF_MemWrite() returns error if (addr + length) > total flash size. */
|
|
||||||
return (cy_rslt_t)Cy_SMIF_MemWrite(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], addr, (uint8_t *)buf, length, &qspi_obj.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Does not support hybrid sectors, sector size must be uniform on the entire
|
|
||||||
* chip. Use cy_serial_flash_qspi_get_erase_size(addr) to implement hybrid sector
|
|
||||||
* support when QSPI Configurator and PDL supports memories with hybrid sectors.
|
|
||||||
*/
|
|
||||||
cy_rslt_t cy_serial_flash_qspi_erase(uint32_t addr, size_t length)
|
|
||||||
{
|
|
||||||
cy_en_smif_status_t smifStatus;
|
|
||||||
|
|
||||||
/* If the erase is for the entire chip, use chip erase command */
|
|
||||||
if((addr == 0u) && (length == cy_serial_flash_qspi_get_size()))
|
|
||||||
{
|
|
||||||
smifStatus = Cy_SMIF_MemEraseChip(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], &qspi_obj.context);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Cy_SMIF_MemEraseSector() returns error if (addr + length) > total flash size
|
|
||||||
* or if addr is not aligned to erase sector size or if (addr + length)
|
|
||||||
* is not aligned to erase sector size.
|
|
||||||
*/
|
|
||||||
smifStatus = Cy_SMIF_MemEraseSector(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], addr, length, &qspi_obj.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (cy_rslt_t)smifStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function enables or disables XIP on the MCU, does not send any command
|
|
||||||
// to the serial flash. XIP register configuration is already done as part of
|
|
||||||
// cy_serial_flash_qspi_init() if MMIO mode is enabled in the QSPI
|
|
||||||
// Configurator.
|
|
||||||
cy_rslt_t cy_serial_flash_qspi_enable_xip(bool enable)
|
|
||||||
{
|
|
||||||
if(enable)
|
|
||||||
{
|
|
||||||
Cy_SMIF_SetMode(qspi_obj.base, CY_SMIF_MEMORY);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Cy_SMIF_SetMode(qspi_obj.base, CY_SMIF_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return CY_RSLT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cy_serial_flash_qspi_set_interrupt_priority(uint8_t priority)
|
|
||||||
{
|
|
||||||
NVIC_SetPriority(smif_interrupt_IRQn, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* CY_IP_MXSMIF */
|
|
||||||
|
|
0
targets/TARGET_Cypress/TARGET_PSOC6/common/LICENSE → targets/TARGET_Cypress/TARGET_PSOC6/common/serial-flash/LICENSE
Normal file → Executable file
0
targets/TARGET_Cypress/TARGET_PSOC6/common/LICENSE → targets/TARGET_Cypress/TARGET_PSOC6/common/serial-flash/LICENSE
Normal file → Executable file
|
@ -0,0 +1,97 @@
|
||||||
|
/***********************************************************************************************//**
|
||||||
|
* \file cy_serial_flash_prog.c
|
||||||
|
*
|
||||||
|
* \brief
|
||||||
|
* Provides variables necessary to inform programming tools how to program the
|
||||||
|
* attached serial flash memory. The variables used here must be placed at
|
||||||
|
* specific locations in order to be detected and used by programming tools
|
||||||
|
* to know that there is an attached memory and its characteristics. Uses the
|
||||||
|
* configuration provided as part of BSP.
|
||||||
|
*
|
||||||
|
***************************************************************************************************
|
||||||
|
* \copyright
|
||||||
|
* Copyright 2018-2021 Cypress Semiconductor Corporation
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup group_board_libs
|
||||||
|
* \{
|
||||||
|
* In addition to the APIs for reading and writting to memory at runtime, this library also
|
||||||
|
* provides support for informing programming tools about the external memory so it can be
|
||||||
|
* be written at the same time as internal flash. This support can be enabled by defining
|
||||||
|
* CY_ENABLE_XIP_PROGRAM while building the application. With this define in place, code
|
||||||
|
* will be generated in the .cy_sflash_user_data & .cy_toc_part2 sections. These locations
|
||||||
|
* can be read by programming tools (eg: Cypress Programmer, OpenOCD, pyOCD) to know that
|
||||||
|
* there is a memory device attached and how to program it.
|
||||||
|
* \} group_board_libs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CY_ENABLE_XIP_PROGRAM)
|
||||||
|
|
||||||
|
#include "cycfg_qspi_memslot.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const cy_stc_smif_block_config_t* smifCfg; // Pointer to SMIF top-level configuration
|
||||||
|
const uint32_t null_t; // NULL termination
|
||||||
|
} stc_smif_ipblocks_arr_t;
|
||||||
|
|
||||||
|
// This data can be placed anywhere in the internal memory, but it must be at a location that
|
||||||
|
// can be determined and used for the calculation of the CRC16 checksum in the cyToc below. There
|
||||||
|
// are multiple ways this can be accomplished including:
|
||||||
|
// 1) Placing it in a dedicated memory block with a known address. (as done here)
|
||||||
|
// 2) Placing it at an absolute location via a the linker script
|
||||||
|
// 3) Using 'cymcuelftool -S' to recompute the checksum and patch the elf file after linking
|
||||||
|
CY_SECTION(".cy_sflash_user_data") __attribute__((used))
|
||||||
|
const stc_smif_ipblocks_arr_t smifIpBlocksArr = { &smifBlockConfig, 0x00000000 };
|
||||||
|
|
||||||
|
// This data is used to populate the table of contents part 2. When present, it is used by the boot
|
||||||
|
// process and programming tools to determine key characteristics about the memory usage including
|
||||||
|
// where the boot process should start the application from and what external memories are connected
|
||||||
|
// (if any). This must consume a full row of flash memory row. The last entry is a checksum of the
|
||||||
|
// other values in the ToC which must be updated if any other value changes. This can be done
|
||||||
|
// manually or by running 'cymcuelftool -S' to recompute the checksum.
|
||||||
|
CY_SECTION(".cy_toc_part2") __attribute__((used))
|
||||||
|
const uint32_t cyToc[128] =
|
||||||
|
{
|
||||||
|
0x200-4, // Offset=0x0000: Object Size, bytes
|
||||||
|
0x01211220, // Offset=0x0004: Magic Number (TOC Part 2, ID)
|
||||||
|
0, // Offset=0x0008: Key Storage Address
|
||||||
|
(int)&smifIpBlocksArr, // Offset=0x000C: This points to a null terminated array of SMIF
|
||||||
|
// structures.
|
||||||
|
0x10000000u, // Offset=0x0010: App image start address
|
||||||
|
// Offset=0x0014-0x01F7: Reserved
|
||||||
|
[126] = 0x000002C2, // Offset=0x01
|
||||||
|
// Bits[ 1: 0] CLOCK_CONFIG (0=8MHz, 1=25MHz, 2=50MHz, 3=100MHz)
|
||||||
|
// Bits[ 4: 2] LISTEN_WINDOW (0=20ms, 1=10ms, 2=1ms, 3=0ms, 4=100ms)
|
||||||
|
// Bits[ 6: 5] SWJ_PINS_CTL (0/1/3=Disable SWJ, 2=Enable SWJ)
|
||||||
|
// Bits[ 8: 7] APP_AUTHENTICATION (0/2/3=Enable, 1=Disable)
|
||||||
|
// Bits[10: 9] FB_BOOTLOADER_CTL: UNUSED
|
||||||
|
[127] = 0x3BB30000 // Offset=0x01FC: CRC16-CCITT
|
||||||
|
// (the upper 2 bytes contain the CRC and the lower 2 bytes are 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // defined(CY_ENABLE_XIP_PROGRAM)
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,868 @@
|
||||||
|
/***********************************************************************************************//**
|
||||||
|
* \file cy_serial_flash_qspi.c
|
||||||
|
*
|
||||||
|
* \brief
|
||||||
|
* Provides APIs for interacting with an external flash connected to the SPI or
|
||||||
|
* QSPI interface, uses SFDP to auto-discover memory properties if SFDP is
|
||||||
|
* enabled in the configuration.
|
||||||
|
*
|
||||||
|
***************************************************************************************************
|
||||||
|
* \copyright
|
||||||
|
* Copyright 2018-2021 Cypress Semiconductor Corporation
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "cy_serial_flash_qspi.h"
|
||||||
|
#include "cyhal_qspi.h"
|
||||||
|
#include "cy_trigmux.h"
|
||||||
|
#include "cy_dma.h"
|
||||||
|
#include "cy_utils.h"
|
||||||
|
|
||||||
|
#if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE)
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "cyabs_rtos.h"
|
||||||
|
#endif /* #if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE) */
|
||||||
|
|
||||||
|
#ifdef CY_IP_MXSMIF
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/** \cond INTERNAL */
|
||||||
|
|
||||||
|
/** Timeout to apply while polling the memory for its ready status after quad
|
||||||
|
* enable command has been sent out. Quad enable is a non-volatile write.
|
||||||
|
*/
|
||||||
|
#define CY_SERIAL_FLASH_QUAD_ENABLE_TIMEOUT_US (5000lu) // in microseconds
|
||||||
|
|
||||||
|
/** Number of loops to run while polling the SMIF for its busy status. */
|
||||||
|
#define SMIF_BUSY_CHECK_LOOP_COUNT (10lu)
|
||||||
|
|
||||||
|
/** Timeout to apply per loop while polling the SMIF for its busy status. */
|
||||||
|
#define SMIF_BUSY_CHECK_TIMEOUT_MS (1lu) // in milliseconds
|
||||||
|
|
||||||
|
// Number of memories supported by the driver
|
||||||
|
#define SMIF_MEM_DEVICES (1u)
|
||||||
|
|
||||||
|
// SMIF slot from which the memory configuration is picked up - fixed to 0 as
|
||||||
|
// the driver supports only one device
|
||||||
|
#define MEM_SLOT (0u)
|
||||||
|
|
||||||
|
/* Maximum number of bytes that can be read by SMIF in one transfer */
|
||||||
|
#define SMIF_MAX_RX_COUNT (65536lu)
|
||||||
|
|
||||||
|
#define DMA_YCOUNT_ONE_LOOP (1lu)
|
||||||
|
|
||||||
|
#define MSB_SHIFT_EIGHT (0x08u)
|
||||||
|
#define LSB_MASK (0xFFlu)
|
||||||
|
|
||||||
|
/* Masks used for checking the flag bits */
|
||||||
|
#define FLAG_QSPI_HAL_INIT_DONE (0x01lu << 0)
|
||||||
|
#define FLAG_DMA_INIT_DONE (0x01lu << 1)
|
||||||
|
#define FLAG_READ_IN_PROGRESS (0x01lu << 2)
|
||||||
|
|
||||||
|
#define IS_FLAG_SET(mask) (status_flags & (mask))
|
||||||
|
#define SET_FLAG(mask) (status_flags |= (mask))
|
||||||
|
#define CLEAR_FLAG(mask) (status_flags &= ~(mask))
|
||||||
|
|
||||||
|
#if defined(CY_DEVICE_PSOC6ABLE2)
|
||||||
|
/* You cannot simply change these values. The trigger mux connect code in
|
||||||
|
* _init_dma() needs to be updated correspondingly.
|
||||||
|
*/
|
||||||
|
#define RX_DMA_INSTANCE DW1
|
||||||
|
#define RX_DMA_CHANNEL_NUM (15lu)
|
||||||
|
#define RX_DMA_CH0_IRQn (cpuss_interrupts_dw1_0_IRQn)
|
||||||
|
#elif defined(CY_DEVICE_PSOC6A2M) || defined(CY_DEVICE_PSOC6A512K) || defined(CY_DEVICE_PSOC6256K)
|
||||||
|
/* In these devices, only 1to1 triggers are available between SMIF and a
|
||||||
|
* specific combination of DW instances and channel numbers.
|
||||||
|
* i.e. TX trigger request from SMIF can connect only to DW1 CH22 and
|
||||||
|
* RX trigger request from SMIF can connect only to DW1 CH23.
|
||||||
|
*/
|
||||||
|
#define RX_DMA_INSTANCE DW1
|
||||||
|
#define RX_DMA_CHANNEL_NUM (23lu)
|
||||||
|
#define RX_DMA_CH0_IRQn (cpuss_interrupts_dw1_0_IRQn)
|
||||||
|
|
||||||
|
#define DEVICE_GROUP_1TO1_TRIGGER
|
||||||
|
#else // if defined(CY_DEVICE_PSOC6ABLE2)
|
||||||
|
#define DMA_UNSUPPORTED
|
||||||
|
#endif // if defined(CY_DEVICE_PSOC6ABLE2)
|
||||||
|
|
||||||
|
#define DMA_CHANNEL_PRIORITY (3lu)
|
||||||
|
#define DMA_INTR_PRIORITY (7lu)
|
||||||
|
|
||||||
|
/** \endcond */
|
||||||
|
|
||||||
|
static cyhal_qspi_t qspi_obj;
|
||||||
|
static volatile uint32_t status_flags;
|
||||||
|
static cy_stc_smif_mem_config_t* qspi_mem_config[SMIF_MEM_DEVICES];
|
||||||
|
|
||||||
|
static cy_stc_smif_block_config_t qspi_block_config =
|
||||||
|
{
|
||||||
|
// The number of SMIF memories defined.
|
||||||
|
.memCount = SMIF_MEM_DEVICES,
|
||||||
|
// The pointer to the array of memory config structures of size memCount.
|
||||||
|
.memConfig = (cy_stc_smif_mem_config_t**)qspi_mem_config,
|
||||||
|
// The version of the SMIF driver.
|
||||||
|
.majorVersion = CY_SMIF_DRV_VERSION_MAJOR,
|
||||||
|
// The version of the SMIF driver.
|
||||||
|
.minorVersion = CY_SMIF_DRV_VERSION_MINOR
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE)
|
||||||
|
static cy_mutex_t serial_flash_mutex;
|
||||||
|
#endif /* #if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE) */
|
||||||
|
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t addr;
|
||||||
|
size_t length;
|
||||||
|
uint8_t* buf;
|
||||||
|
cy_serial_flash_qspi_read_complete_callback_t callback;
|
||||||
|
void* callback_arg;
|
||||||
|
} read_txfr_info_t;
|
||||||
|
|
||||||
|
static read_txfr_info_t read_txfr_info;
|
||||||
|
|
||||||
|
/* DMA related variables */
|
||||||
|
static cy_stc_dma_descriptor_t dma_descr;
|
||||||
|
|
||||||
|
/* Default DW descriptor config */
|
||||||
|
static cy_stc_dma_descriptor_config_t dma_descr_config =
|
||||||
|
{
|
||||||
|
.retrigger = CY_DMA_RETRIG_4CYC,
|
||||||
|
.interruptType = CY_DMA_DESCR,
|
||||||
|
.triggerOutType = CY_DMA_DESCR_CHAIN,
|
||||||
|
.channelState = CY_DMA_CHANNEL_ENABLED,
|
||||||
|
.triggerInType = CY_DMA_DESCR,
|
||||||
|
.dataSize = CY_DMA_BYTE,
|
||||||
|
.srcTransferSize = CY_DMA_TRANSFER_SIZE_WORD,
|
||||||
|
.dstTransferSize = CY_DMA_TRANSFER_SIZE_DATA,
|
||||||
|
.descriptorType = CY_DMA_2D_TRANSFER,
|
||||||
|
.srcAddress = 0,
|
||||||
|
.dstAddress = 0,
|
||||||
|
.srcXincrement = 0U,
|
||||||
|
.dstXincrement = 1U,
|
||||||
|
.xCount = 1UL,
|
||||||
|
.srcYincrement = 0U,
|
||||||
|
.dstYincrement = CY_DMA_LOOP_COUNT_MAX,
|
||||||
|
.yCount = 1UL,
|
||||||
|
.nextDescriptor = &dma_descr,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Default DW channel config */
|
||||||
|
static cy_stc_dma_channel_config_t dma_channel_config =
|
||||||
|
{
|
||||||
|
.descriptor = &dma_descr,
|
||||||
|
.preemptable = false,
|
||||||
|
.priority = DMA_CHANNEL_PRIORITY,
|
||||||
|
.enable = false,
|
||||||
|
.bufferable = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const cyhal_resource_inst_t DW_obj =
|
||||||
|
{
|
||||||
|
.type = CYHAL_RSC_DW,
|
||||||
|
.block_num = ((uint32_t)RX_DMA_INSTANCE - DW0_BASE)/sizeof(DW_Type),
|
||||||
|
.channel_num = RX_DMA_CHANNEL_NUM
|
||||||
|
};
|
||||||
|
|
||||||
|
static cy_rslt_t _init_dma(void);
|
||||||
|
static cy_rslt_t _deinit_dma(void);
|
||||||
|
static void _rx_dma_irq_handler(void);
|
||||||
|
static cy_en_smif_status_t _read_next_chunk(void);
|
||||||
|
static void _value_to_byte_array(uint32_t value, uint8_t* byte_array, uint32_t start_pos,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
|
||||||
|
static inline cy_rslt_t _mutex_acquire(void);
|
||||||
|
static inline cy_rslt_t _mutex_release(void);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_init
|
||||||
|
//
|
||||||
|
// The driver supports only one memory. When multiple memory configurations are generated by the
|
||||||
|
// SMIF configurator tool, provide only the configuration for memory that need to be supported by
|
||||||
|
// the driver. Memory configuration can be changed by deinit followed by init with new
|
||||||
|
// configuration
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_init(
|
||||||
|
const cy_stc_smif_mem_config_t* mem_config,
|
||||||
|
cyhal_gpio_t io0,
|
||||||
|
cyhal_gpio_t io1,
|
||||||
|
cyhal_gpio_t io2,
|
||||||
|
cyhal_gpio_t io3,
|
||||||
|
cyhal_gpio_t io4,
|
||||||
|
cyhal_gpio_t io5,
|
||||||
|
cyhal_gpio_t io6,
|
||||||
|
cyhal_gpio_t io7,
|
||||||
|
cyhal_gpio_t sclk,
|
||||||
|
cyhal_gpio_t ssel,
|
||||||
|
uint32_t hz)
|
||||||
|
{
|
||||||
|
cy_en_smif_status_t smif_status = CY_SMIF_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
|
cy_rslt_t result = cyhal_qspi_init(&qspi_obj, io0, io1, io2, io3, io4, io5, io6, io7,
|
||||||
|
sclk, ssel, hz, 0);
|
||||||
|
|
||||||
|
qspi_mem_config[MEM_SLOT] = (cy_stc_smif_mem_config_t*)mem_config;
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
SET_FLAG(FLAG_QSPI_HAL_INIT_DONE);
|
||||||
|
|
||||||
|
// Perform SFDP detection and XIP register configuration depending on the memory
|
||||||
|
// configuration.
|
||||||
|
smif_status = Cy_SMIF_MemInit(qspi_obj.base, &qspi_block_config, &qspi_obj.context);
|
||||||
|
if (CY_SMIF_SUCCESS == smif_status)
|
||||||
|
{
|
||||||
|
// Enable Quad mode (1-1-4 or 1-4-4 modes) to use all the four I/Os during
|
||||||
|
// communication.
|
||||||
|
|
||||||
|
if ((qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->readCmd->dataWidth ==
|
||||||
|
CY_SMIF_WIDTH_QUAD) ||
|
||||||
|
(qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->programCmd->dataWidth ==
|
||||||
|
CY_SMIF_WIDTH_QUAD))
|
||||||
|
{
|
||||||
|
bool isQuadEnabled = false;
|
||||||
|
smif_status =
|
||||||
|
Cy_SMIF_MemIsQuadEnabled(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT],
|
||||||
|
&isQuadEnabled, &qspi_obj.context);
|
||||||
|
if ((CY_SMIF_SUCCESS == smif_status) && !isQuadEnabled)
|
||||||
|
{
|
||||||
|
smif_status =
|
||||||
|
Cy_SMIF_MemEnableQuadMode(qspi_obj.base,
|
||||||
|
qspi_block_config.memConfig[MEM_SLOT],
|
||||||
|
CY_SERIAL_FLASH_QUAD_ENABLE_TIMEOUT_US,
|
||||||
|
&qspi_obj.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CY_SMIF_SUCCESS == smif_status)
|
||||||
|
{
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
result = _init_dma();
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
SET_FLAG(FLAG_DMA_INIT_DONE);
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
|
||||||
|
#if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE)
|
||||||
|
/* Initialize the mutex */
|
||||||
|
result = cy_rtos_init_mutex(&serial_flash_mutex);
|
||||||
|
#endif /* #if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE) */
|
||||||
|
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
}
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((CY_RSLT_SUCCESS != result) || (CY_SMIF_SUCCESS != smif_status))
|
||||||
|
{
|
||||||
|
cy_serial_flash_qspi_deinit();
|
||||||
|
|
||||||
|
if (CY_SMIF_SUCCESS != smif_status)
|
||||||
|
{
|
||||||
|
result = (cy_rslt_t)smif_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_deinit
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void cy_serial_flash_qspi_deinit(void)
|
||||||
|
{
|
||||||
|
cy_rslt_t result;
|
||||||
|
|
||||||
|
if (IS_FLAG_SET(FLAG_QSPI_HAL_INIT_DONE))
|
||||||
|
{
|
||||||
|
if (qspi_obj.base != NULL)
|
||||||
|
{
|
||||||
|
/* There is no harm in calling this even if Cy_SMIF_MemInit() did
|
||||||
|
* not succeed since anyway we own the QSPI object.
|
||||||
|
*/
|
||||||
|
Cy_SMIF_MemDeInit(qspi_obj.base);
|
||||||
|
}
|
||||||
|
|
||||||
|
cyhal_qspi_free(&qspi_obj);
|
||||||
|
CLEAR_FLAG(FLAG_QSPI_HAL_INIT_DONE);
|
||||||
|
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
if (IS_FLAG_SET(FLAG_DMA_INIT_DONE))
|
||||||
|
{
|
||||||
|
result = _deinit_dma();
|
||||||
|
CY_ASSERT(CY_RSLT_SUCCESS == result);
|
||||||
|
|
||||||
|
CLEAR_FLAG(FLAG_DMA_INIT_DONE);
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
|
||||||
|
#if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE)
|
||||||
|
result = cy_rtos_deinit_mutex(&serial_flash_mutex);
|
||||||
|
CY_ASSERT(CY_RSLT_SUCCESS == result);
|
||||||
|
#endif /* #if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE) */
|
||||||
|
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
}
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
CY_UNUSED_PARAMETER(result); /* To avoid compiler warning in Release mode. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_get_size
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
size_t cy_serial_flash_qspi_get_size(void)
|
||||||
|
{
|
||||||
|
return (size_t)qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->memSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_get_erase_size
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
size_t cy_serial_flash_qspi_get_erase_size(uint32_t addr)
|
||||||
|
{
|
||||||
|
size_t erase_sector_size;
|
||||||
|
cy_stc_smif_hybrid_region_info_t* hybrid_info = NULL;
|
||||||
|
|
||||||
|
cy_en_smif_status_t smif_status =
|
||||||
|
Cy_SMIF_MemLocateHybridRegion(qspi_block_config.memConfig[MEM_SLOT], &hybrid_info, addr);
|
||||||
|
|
||||||
|
if (CY_SMIF_SUCCESS != smif_status)
|
||||||
|
{
|
||||||
|
erase_sector_size = (size_t)qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->eraseSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
erase_sector_size = (size_t)hybrid_info->eraseSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return erase_sector_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_get_prog_size
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
size_t cy_serial_flash_qspi_get_prog_size(uint32_t addr)
|
||||||
|
{
|
||||||
|
CY_UNUSED_PARAMETER(addr);
|
||||||
|
return (size_t)qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->programSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_read
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_read(uint32_t addr, size_t length, uint8_t* buf)
|
||||||
|
{
|
||||||
|
cy_rslt_t result_mutex_rel = CY_RSLT_SUCCESS;
|
||||||
|
|
||||||
|
cy_rslt_t result = _mutex_acquire();
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
// Cy_SMIF_MemRead() returns error if (addr + length) > total flash size.
|
||||||
|
result = (cy_rslt_t)Cy_SMIF_MemRead(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT],
|
||||||
|
addr,
|
||||||
|
buf, length, &qspi_obj.context);
|
||||||
|
result_mutex_rel = _mutex_release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give priority to the status of SMIF operation when both SMIF operation
|
||||||
|
* and mutex release fail.
|
||||||
|
*/
|
||||||
|
return ((CY_RSLT_SUCCESS == result) ? result_mutex_rel : result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_abort_read
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_abort_read(void)
|
||||||
|
{
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
cy_rslt_t result;
|
||||||
|
|
||||||
|
/* Wait until SMIF finishes any pending transfer. */
|
||||||
|
for (uint32_t loop = 0; loop < SMIF_BUSY_CHECK_LOOP_COUNT; loop++)
|
||||||
|
{
|
||||||
|
if (!Cy_SMIF_BusyCheck(qspi_obj.base))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cyhal_system_delay_ms(SMIF_BUSY_CHECK_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cy_SMIF_BusyCheck(qspi_obj.base))
|
||||||
|
{
|
||||||
|
SET_FLAG(FLAG_READ_IN_PROGRESS);
|
||||||
|
result = CY_RSLT_SERIAL_FLASH_ERR_QSPI_BUSY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Cy_DMA_Channel_Disable(RX_DMA_INSTANCE, RX_DMA_CHANNEL_NUM);
|
||||||
|
result = CY_RSLT_SUCCESS;
|
||||||
|
CLEAR_FLAG(FLAG_READ_IN_PROGRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
#else // ifndef DMA_UNSUPPORTED
|
||||||
|
return CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED;
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_read_async
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_read_async(uint32_t addr, size_t length, uint8_t* buf,
|
||||||
|
cy_serial_flash_qspi_read_complete_callback_t callback,
|
||||||
|
void* callback_arg)
|
||||||
|
{
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
cy_rslt_t result = CY_RSLT_SERIAL_FLASH_ERR_BAD_PARAM;
|
||||||
|
cy_rslt_t result_mutex_rel = CY_RSLT_SUCCESS;
|
||||||
|
|
||||||
|
CY_ASSERT(NULL != buf);
|
||||||
|
|
||||||
|
if (IS_FLAG_SET(FLAG_READ_IN_PROGRESS))
|
||||||
|
{
|
||||||
|
result = CY_RSLT_SERIAL_FLASH_ERR_READ_BUSY; /* Previous read request is not yet complete.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else if ((addr + length) <= cy_serial_flash_qspi_get_size())
|
||||||
|
{
|
||||||
|
result = _mutex_acquire();
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
read_txfr_info.addr = addr;
|
||||||
|
read_txfr_info.length = length;
|
||||||
|
read_txfr_info.buf = buf;
|
||||||
|
read_txfr_info.callback = callback;
|
||||||
|
read_txfr_info.callback_arg = callback_arg;
|
||||||
|
|
||||||
|
/* Enable the DMA channel */
|
||||||
|
Cy_DMA_Channel_Enable(RX_DMA_INSTANCE, RX_DMA_CHANNEL_NUM);
|
||||||
|
|
||||||
|
SET_FLAG(FLAG_READ_IN_PROGRESS);
|
||||||
|
result = (cy_rslt_t)_read_next_chunk(); /* Start the read transfer */
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS != result)
|
||||||
|
{
|
||||||
|
CLEAR_FLAG(FLAG_READ_IN_PROGRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_mutex_rel = _mutex_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give priority to the status of SMIF operation when both SMIF operation
|
||||||
|
* and mutex release fail.
|
||||||
|
*/
|
||||||
|
return ((CY_RSLT_SUCCESS == result) ? result_mutex_rel : result);
|
||||||
|
#else // ifndef DMA_UNSUPPORTED
|
||||||
|
CY_UNUSED_PARAMETER(addr);
|
||||||
|
CY_UNUSED_PARAMETER(length);
|
||||||
|
CY_UNUSED_PARAMETER(buf);
|
||||||
|
CY_UNUSED_PARAMETER(callback);
|
||||||
|
CY_UNUSED_PARAMETER(callback_arg);
|
||||||
|
|
||||||
|
return CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED;
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_write
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_write(uint32_t addr, size_t length, const uint8_t* buf)
|
||||||
|
{
|
||||||
|
cy_rslt_t result_mutex_rel = CY_RSLT_SUCCESS;
|
||||||
|
|
||||||
|
cy_rslt_t result = _mutex_acquire();
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
// Cy_SMIF_MemWrite() returns error if (addr + length) > total flash size.
|
||||||
|
result = (cy_rslt_t)Cy_SMIF_MemWrite(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT],
|
||||||
|
addr,
|
||||||
|
(uint8_t*)buf, length, &qspi_obj.context);
|
||||||
|
result_mutex_rel = _mutex_release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give priority to the status of SMIF operation when both SMIF operation
|
||||||
|
* and mutex release fail.
|
||||||
|
*/
|
||||||
|
return ((CY_RSLT_SUCCESS == result) ? result_mutex_rel : result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_erase
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_erase(uint32_t addr, size_t length)
|
||||||
|
{
|
||||||
|
cy_rslt_t result_mutex_rel = CY_RSLT_SUCCESS;
|
||||||
|
|
||||||
|
cy_rslt_t result = _mutex_acquire();
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
// If the erase is for the entire chip, use chip erase command
|
||||||
|
if ((addr == 0u) && (length == cy_serial_flash_qspi_get_size()))
|
||||||
|
{
|
||||||
|
result =
|
||||||
|
(cy_rslt_t)Cy_SMIF_MemEraseChip(qspi_obj.base,
|
||||||
|
qspi_block_config.memConfig[MEM_SLOT],
|
||||||
|
&qspi_obj.context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cy_SMIF_MemEraseSector() returns error if (addr + length) > total flash size or if
|
||||||
|
// addr is not aligned to erase sector size or if (addr + length) is not aligned to
|
||||||
|
// erase sector size.
|
||||||
|
result =
|
||||||
|
(cy_rslt_t)Cy_SMIF_MemEraseSector(qspi_obj.base,
|
||||||
|
qspi_block_config.memConfig[MEM_SLOT],
|
||||||
|
addr, length, &qspi_obj.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_mutex_rel = _mutex_release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give priority to the status of SMIF operation when both SMIF operation
|
||||||
|
* and mutex release fail.
|
||||||
|
*/
|
||||||
|
return ((CY_RSLT_SUCCESS == result) ? result_mutex_rel : result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_enable_xip
|
||||||
|
//
|
||||||
|
// This function enables or disables XIP on the MCU, does not send any command
|
||||||
|
// to the serial flash. XIP register configuration is already done as part of
|
||||||
|
// cy_serial_flash_qspi_init() if MMIO mode is enabled in the QSPI
|
||||||
|
// Configurator.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_enable_xip(bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
Cy_SMIF_SetMode(qspi_obj.base, CY_SMIF_MEMORY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Cy_SMIF_SetMode(qspi_obj.base, CY_SMIF_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CY_RSLT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_set_interrupt_priority
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void cy_serial_flash_qspi_set_interrupt_priority(uint8_t priority)
|
||||||
|
{
|
||||||
|
NVIC_SetPriority(smif_interrupt_IRQn, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// cy_serial_flash_qspi_set_interrupt_priority
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void cy_serial_flash_qspi_set_dma_interrupt_priority(uint8_t priority)
|
||||||
|
{
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
NVIC_SetPriority((IRQn_Type)(RX_DMA_CH0_IRQn + RX_DMA_CHANNEL_NUM), priority);
|
||||||
|
#else
|
||||||
|
CY_UNUSED_PARAMETER(priority);
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DMA_UNSUPPORTED
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// _read_next_chunk
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
static cy_en_smif_status_t _read_next_chunk(void)
|
||||||
|
{
|
||||||
|
cy_en_smif_status_t smif_status = CY_SMIF_SUCCESS;
|
||||||
|
uint32_t chunk;
|
||||||
|
uint8_t addr_array[CY_SMIF_FOUR_BYTES_ADDR] = { 0U };
|
||||||
|
|
||||||
|
if (read_txfr_info.length > 0UL)
|
||||||
|
{
|
||||||
|
/* SMIF can read only up to 65536 bytes in one go. Split the larger read into multiple
|
||||||
|
chunks */
|
||||||
|
chunk =
|
||||||
|
(read_txfr_info.length >
|
||||||
|
SMIF_MAX_RX_COUNT) ? (SMIF_MAX_RX_COUNT) : read_txfr_info.length;
|
||||||
|
|
||||||
|
/* In 2D transfer, (X_count x Y_count) should be a multiple of CY_DMA_LOOP_COUNT_MAX (256).
|
||||||
|
*/
|
||||||
|
if (chunk > CY_DMA_LOOP_COUNT_MAX)
|
||||||
|
{
|
||||||
|
/* Make chunk divisible by CY_DMA_LOOP_COUNT_MAX (256) by masking out the LS bits */
|
||||||
|
chunk &= ~(CY_DMA_LOOP_COUNT_MAX - 1);
|
||||||
|
|
||||||
|
dma_descr_config.yCount = chunk/CY_DMA_LOOP_COUNT_MAX;
|
||||||
|
dma_descr_config.xCount = CY_DMA_LOOP_COUNT_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dma_descr_config.yCount = DMA_YCOUNT_ONE_LOOP;
|
||||||
|
dma_descr_config.xCount = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_descr_config.dstAddress = (void*)read_txfr_info.buf;
|
||||||
|
Cy_DMA_Descriptor_Init(&dma_descr, &dma_descr_config);
|
||||||
|
|
||||||
|
/* Pass NULL for buffer (and callback) so that the function does not
|
||||||
|
* set up FIFO interrupt. We don't need FIFO interrupt to be setup
|
||||||
|
* since we will be using DMA.
|
||||||
|
*/
|
||||||
|
_value_to_byte_array(read_txfr_info.addr, &addr_array[0], 0UL,
|
||||||
|
qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->numOfAddrBytes);
|
||||||
|
smif_status = Cy_SMIF_MemCmdRead(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT],
|
||||||
|
addr_array, NULL, chunk, NULL, &qspi_obj.context);
|
||||||
|
|
||||||
|
if (CY_SMIF_SUCCESS == smif_status)
|
||||||
|
{
|
||||||
|
/* Recalculate the next rxBuffer offset */
|
||||||
|
read_txfr_info.length -= chunk;
|
||||||
|
read_txfr_info.addr += chunk;
|
||||||
|
read_txfr_info.buf += chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return smif_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// _init_dma
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
static cy_rslt_t _init_dma(void)
|
||||||
|
{
|
||||||
|
cy_rslt_t result;
|
||||||
|
|
||||||
|
/* Set the source address of the descriptor */
|
||||||
|
dma_descr_config.srcAddress = (void*)&SMIF_RX_DATA_FIFO_RD1(qspi_obj.base);
|
||||||
|
|
||||||
|
/* Configure the RX DMA */
|
||||||
|
result =
|
||||||
|
(cy_rslt_t)Cy_DMA_Channel_Init(RX_DMA_INSTANCE, RX_DMA_CHANNEL_NUM, &dma_channel_config);
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
Cy_DMA_Channel_SetInterruptMask(RX_DMA_INSTANCE, RX_DMA_CHANNEL_NUM, CY_DMA_INTR_MASK);
|
||||||
|
Cy_DMA_Enable(RX_DMA_INSTANCE);
|
||||||
|
|
||||||
|
/* Configure interrupt for RX DMA */
|
||||||
|
cy_stc_sysint_t dma_intr_config =
|
||||||
|
{ .intrSrc = (IRQn_Type)(RX_DMA_CH0_IRQn + RX_DMA_CHANNEL_NUM),
|
||||||
|
.intrPriority = DMA_INTR_PRIORITY };
|
||||||
|
|
||||||
|
result = (cy_rslt_t)Cy_SysInt_Init(&dma_intr_config, _rx_dma_irq_handler);
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
NVIC_EnableIRQ(dma_intr_config.intrSrc);
|
||||||
|
|
||||||
|
/* Configure the trigger mux */
|
||||||
|
#if defined(DEVICE_GROUP_1TO1_TRIGGER)
|
||||||
|
result = (cy_rslt_t)Cy_TrigMux_Select(TRIG_OUT_1TO1_3_SMIF_RX_TO_PDMA1_TR_IN23, false,
|
||||||
|
TRIGGER_TYPE_LEVEL);
|
||||||
|
#else
|
||||||
|
result = (cy_rslt_t)Cy_TrigMux_Connect(TRIG13_IN_SMIF_TR_RX_REQ,
|
||||||
|
TRIG13_OUT_TR_GROUP0_INPUT42, false,
|
||||||
|
TRIGGER_TYPE_LEVEL);
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
result = (cy_rslt_t)Cy_TrigMux_Connect(TRIG1_IN_TR_GROUP13_OUTPUT15,
|
||||||
|
TRIG1_OUT_CPUSS_DW1_TR_IN15, false,
|
||||||
|
TRIGGER_TYPE_LEVEL);
|
||||||
|
}
|
||||||
|
#endif /* #if defined(DEVICE_GROUP_1TO1_TRIGGER) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CY_RSLT_SUCCESS == result)
|
||||||
|
{
|
||||||
|
/* Reserve the DW instance so that HAL will not be able to use it later. */
|
||||||
|
result = cyhal_hwmgr_reserve(&DW_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// _deinit_dma
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
static cy_rslt_t _deinit_dma(void)
|
||||||
|
{
|
||||||
|
cy_rslt_t result = CY_RSLT_SUCCESS;
|
||||||
|
|
||||||
|
NVIC_DisableIRQ((IRQn_Type)(RX_DMA_CH0_IRQn + RX_DMA_CHANNEL_NUM));
|
||||||
|
|
||||||
|
/* Disable only the channel, not the DW instance as it may be used by other
|
||||||
|
* part of the application.
|
||||||
|
*/
|
||||||
|
Cy_DMA_Channel_Disable(RX_DMA_INSTANCE, RX_DMA_CHANNEL_NUM);
|
||||||
|
|
||||||
|
/* Free the DMA resource so that HAL can use it now */
|
||||||
|
cyhal_hwmgr_free(&DW_obj);
|
||||||
|
|
||||||
|
#if defined(DEVICE_GROUP_1TO1_TRIGGER)
|
||||||
|
result = (cy_rslt_t)Cy_TrigMux_Deselect(TRIG_OUT_1TO1_3_SMIF_RX_TO_PDMA1_TR_IN23);
|
||||||
|
#else
|
||||||
|
/* No PDL function is available for handling deinit for non-1to1 trigger muxes. */
|
||||||
|
#endif /* #if defined(DEVICE_GROUP_1TO1_TRIGGER) */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// _rx_dma_irq_handler
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
static void _rx_dma_irq_handler(void)
|
||||||
|
{
|
||||||
|
cy_en_smif_status_t smif_status = CY_SMIF_SUCCESS;
|
||||||
|
bool terminate_read_txfr = true;
|
||||||
|
cy_en_dma_intr_cause_t cause = Cy_DMA_Channel_GetStatus(RX_DMA_INSTANCE, RX_DMA_CHANNEL_NUM);
|
||||||
|
|
||||||
|
Cy_DMA_Channel_ClearInterrupt(RX_DMA_INSTANCE, RX_DMA_CHANNEL_NUM);
|
||||||
|
|
||||||
|
if (CY_DMA_INTR_CAUSE_COMPLETION == cause)
|
||||||
|
{
|
||||||
|
if (read_txfr_info.length > 0UL)
|
||||||
|
{
|
||||||
|
smif_status = _read_next_chunk();
|
||||||
|
|
||||||
|
if (CY_SMIF_SUCCESS == smif_status)
|
||||||
|
{
|
||||||
|
terminate_read_txfr = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
smif_status = (cy_en_smif_status_t)CY_RSLT_SERIAL_FLASH_ERR_DMA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terminate_read_txfr)
|
||||||
|
{
|
||||||
|
Cy_DMA_Channel_Disable(RX_DMA_INSTANCE, RX_DMA_CHANNEL_NUM);
|
||||||
|
CLEAR_FLAG(FLAG_READ_IN_PROGRESS);
|
||||||
|
|
||||||
|
/* Execute the callback */
|
||||||
|
if (NULL != read_txfr_info.callback)
|
||||||
|
{
|
||||||
|
read_txfr_info.callback((cy_rslt_t)smif_status, read_txfr_info.callback_arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Function Name: _value_to_byte_array
|
||||||
|
****************************************************************************//**
|
||||||
|
*
|
||||||
|
* Unpacks the specified number of bytes from a 32-bit value into the given byte
|
||||||
|
* array.
|
||||||
|
*
|
||||||
|
* \param value
|
||||||
|
* The 32-bit (4-byte) value to unpack.
|
||||||
|
*
|
||||||
|
* \param byte_array
|
||||||
|
* The byte array to fill.
|
||||||
|
*
|
||||||
|
* \param start_pos
|
||||||
|
* The start position of the byte array to begin filling from.
|
||||||
|
*
|
||||||
|
* \param size
|
||||||
|
* The number of bytes to unpack.
|
||||||
|
*
|
||||||
|
*******************************************************************************/
|
||||||
|
static void _value_to_byte_array(uint32_t value, uint8_t* byte_array, uint32_t start_pos,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
CY_ASSERT((0lu < size) && (CY_SMIF_FOUR_BYTES_ADDR >= size));
|
||||||
|
CY_ASSERT(NULL != byte_array);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
size--;
|
||||||
|
byte_array[size + start_pos] = (uint8_t)(value & LSB_MASK);
|
||||||
|
value >>= MSB_SHIFT_EIGHT; /* Shift to get the next byte */
|
||||||
|
} while (size > 0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #ifndef DMA_UNSUPPORTED */
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// _mutex_acquire
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
static inline cy_rslt_t _mutex_acquire(void)
|
||||||
|
{
|
||||||
|
#if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE)
|
||||||
|
return cy_rtos_get_mutex(&serial_flash_mutex, CY_RTOS_NEVER_TIMEOUT);
|
||||||
|
#else
|
||||||
|
return CY_RSLT_SUCCESS;
|
||||||
|
#endif /* #if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE) */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
// _mutex_release
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
static inline cy_rslt_t _mutex_release(void)
|
||||||
|
{
|
||||||
|
#if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE)
|
||||||
|
return cy_rtos_set_mutex(&serial_flash_mutex);
|
||||||
|
#else
|
||||||
|
return CY_RSLT_SUCCESS;
|
||||||
|
#endif /* #if defined(CY_SERIAL_FLASH_QSPI_THREAD_SAFE) */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CY_IP_MXSMIF
|
|
@ -1,33 +1,45 @@
|
||||||
/***************************************************************************//**
|
/***********************************************************************************************//**
|
||||||
* \file cy_serial_flash_qspi.h
|
* \file cy_serial_flash_qspi.h
|
||||||
*
|
*
|
||||||
* \brief
|
* \brief
|
||||||
* Provides APIs for interacting with an external flash connected to the SPI or
|
* Provides APIs for interacting with an external flash connected to the SPI or
|
||||||
* QSPI interface. Flash operations read, write, and erase are implemented as
|
* QSPI interface. Read is implemented as both blocking and non-blocking whereas
|
||||||
* blocking functions.
|
* write, and erase are implemented as blocking functions.
|
||||||
*
|
*
|
||||||
********************************************************************************
|
***************************************************************************************************
|
||||||
* \copyright
|
* \copyright
|
||||||
* Copyright 2018-2020 Cypress Semiconductor Corporation
|
* Copyright 2018-2021 Cypress Semiconductor Corporation
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*******************************************************************************/
|
**************************************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \addtogroup group_board_libs Serial Flash
|
* \addtogroup group_board_libs Serial Flash
|
||||||
* \{
|
* \ingroup group_lib
|
||||||
*/
|
* \{
|
||||||
|
*
|
||||||
|
* \section section_resource_usage DMA Resource Usage
|
||||||
|
* This library uses fixed DMA (Datawire or DW) resources and supports DMA only
|
||||||
|
* for the following devices. DMA is not supported for other devices and the
|
||||||
|
* functions \ref cy_serial_flash_qspi_read_async() and
|
||||||
|
* \ref cy_serial_flash_qspi_abort_read() will return
|
||||||
|
* \ref CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED error and
|
||||||
|
* \ref cy_serial_flash_qspi_set_dma_interrupt_priority() will simply return
|
||||||
|
* doing nothing.
|
||||||
|
* * CY8C6xx4, CY8C6xx5, CY8C6xx8, CY8C6xxA, CYB06xx5, CYB06xxA, CYS06xxA: <b>DW1, Channel 23</b>
|
||||||
|
* * CY8C6xx6, CY8C6xx7, CYB06xx7: <b>DW1, Channel 15</b>
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -43,7 +55,37 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** The function or operation is not supported on the target or the memory */
|
/** The function or operation is not supported on the target or the memory */
|
||||||
#define CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 1))
|
#define CY_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED \
|
||||||
|
(CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 1))
|
||||||
|
|
||||||
|
/** Parameters passed to a function are invalid */
|
||||||
|
#define CY_RSLT_SERIAL_FLASH_ERR_BAD_PARAM \
|
||||||
|
(CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 2))
|
||||||
|
|
||||||
|
/** A previously initiated read operation is not yet complete */
|
||||||
|
#define CY_RSLT_SERIAL_FLASH_ERR_READ_BUSY \
|
||||||
|
(CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 3))
|
||||||
|
|
||||||
|
/** A DMA error occurred during read transfer */
|
||||||
|
#define CY_RSLT_SERIAL_FLASH_ERR_DMA \
|
||||||
|
(CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 4))
|
||||||
|
|
||||||
|
/** Read abort failed. QSPI block is busy. */
|
||||||
|
#define CY_RSLT_SERIAL_FLASH_ERR_QSPI_BUSY \
|
||||||
|
(CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_BOARD_LIB_SERIAL_FLASH, 5))
|
||||||
|
|
||||||
|
#ifdef DOXYGEN
|
||||||
|
/** Enables thread-safety for use with multi-threaded RTOS environment. */
|
||||||
|
#define CY_SERIAL_FLASH_QSPI_THREAD_SAFE
|
||||||
|
#endif /* #ifdef DOXYGEN */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback pointer to use with \ref cy_serial_flash_qspi_read_async().
|
||||||
|
* \param peration_status Status of the read operation
|
||||||
|
* \param callback_arg Pointer to be passed back to the callback function
|
||||||
|
*/
|
||||||
|
typedef void (* cy_serial_flash_qspi_read_complete_callback_t)(cy_rslt_t operation_status,
|
||||||
|
void* callback_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initializes the serial flash memory. This function accepts up to 8
|
* \brief Initializes the serial flash memory. This function accepts up to 8
|
||||||
|
@ -84,6 +126,10 @@ cy_rslt_t cy_serial_flash_qspi_init(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief De-initializes the serial flash memory.
|
* \brief De-initializes the serial flash memory.
|
||||||
|
* Before calling this function, ensure that an ongoing asynchronous read
|
||||||
|
* operation is either completed or successfully aborted.
|
||||||
|
* Async read is started by calling \ref cy_serial_flash_qspi_read_async() and
|
||||||
|
* aborted by calling \ref cy_serial_flash_qspi_abort_read().
|
||||||
*/
|
*/
|
||||||
void cy_serial_flash_qspi_deinit(void);
|
void cy_serial_flash_qspi_deinit(void);
|
||||||
|
|
||||||
|
@ -120,6 +166,7 @@ __STATIC_INLINE uint32_t cy_serial_flash_get_sector_start_address(uint32_t addr)
|
||||||
return (addr & ~(cy_serial_flash_qspi_get_erase_size(addr) - 1));
|
return (addr & ~(cy_serial_flash_qspi_get_erase_size(addr) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Reads data from the serial flash memory. This is a blocking
|
* \brief Reads data from the serial flash memory. This is a blocking
|
||||||
* function. Returns error if (addr + length) exceeds the flash size.
|
* function. Returns error if (addr + length) exceeds the flash size.
|
||||||
|
@ -128,7 +175,34 @@ __STATIC_INLINE uint32_t cy_serial_flash_get_sector_start_address(uint32_t addr)
|
||||||
* \param buf Pointer to the buffer to store the data read from the memory
|
* \param buf Pointer to the buffer to store the data read from the memory
|
||||||
* \returns CY_RSLT_SUCCESS if the read was successful, an error code otherwise.
|
* \returns CY_RSLT_SUCCESS if the read was successful, an error code otherwise.
|
||||||
*/
|
*/
|
||||||
cy_rslt_t cy_serial_flash_qspi_read(uint32_t addr, size_t length, uint8_t *buf);
|
cy_rslt_t cy_serial_flash_qspi_read(uint32_t addr, size_t length, uint8_t* buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Reads data from the serial flash memory. This is a non-blocking
|
||||||
|
* function. Returns error if (addr + length) exceeds the flash size.
|
||||||
|
* Uses fixed DMA (DW) instance and channel for transferring the data from
|
||||||
|
* QSPI RX FIFO to the user-provided buffer.
|
||||||
|
* \param addr Starting address to read from
|
||||||
|
* \param length Number of data bytes to read
|
||||||
|
* \param buf Pointer to the buffer to store the data read from the memory
|
||||||
|
* \param callback Pointer to the callback function to be called after the read
|
||||||
|
* operation is complete. Callback is invoked from the DMA ISR.
|
||||||
|
* \param callback_arg Pointer to the argument to be passed to the callback
|
||||||
|
* function
|
||||||
|
* \returns CY_RSLT_SUCCESS if the read was successful, an error code otherwise.
|
||||||
|
*/
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_read_async(uint32_t addr, size_t length, uint8_t* buf,
|
||||||
|
cy_serial_flash_qspi_read_complete_callback_t callback,
|
||||||
|
void* callback_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Aborts an ongoing asynchronous read initiated by calling
|
||||||
|
* \ref cy_serial_flash_qspi_read_async().
|
||||||
|
*
|
||||||
|
* \returns CY_RSLT_SUCCESS if the abort was successful, an error code
|
||||||
|
* if the QSPI block is still busy after a timeout.
|
||||||
|
*/
|
||||||
|
cy_rslt_t cy_serial_flash_qspi_abort_read(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Writes the data to the serial flash memory. The program area
|
* \brief Writes the data to the serial flash memory. The program area
|
||||||
|
@ -141,13 +215,16 @@ cy_rslt_t cy_serial_flash_qspi_read(uint32_t addr, size_t length, uint8_t *buf);
|
||||||
* \returns CY_RSLT_SUCCESS if the write was successful, an error code
|
* \returns CY_RSLT_SUCCESS if the write was successful, an error code
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
cy_rslt_t cy_serial_flash_qspi_write(uint32_t addr, size_t length, const uint8_t *buf);
|
cy_rslt_t cy_serial_flash_qspi_write(uint32_t addr, size_t length, const uint8_t* buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Erases the serial flash memory, uses chip erase command when
|
* \brief Erases the serial flash memory, uses chip erase command when
|
||||||
* addr = 0 and length = flash_size otherwise uses sector erase command. This is
|
* addr = 0 and length = flash_size otherwise uses sector erase command. This is
|
||||||
* a blocking function. Returns error if addr or (addr + length) is not aligned
|
* a blocking function. Returns error if addr or (addr + length) is not aligned
|
||||||
* to the sector size or if (addr + length) exceeds the flash size.
|
* to the sector size or if (addr + length) exceeds the flash size.
|
||||||
|
* For memories with hybrid sectors, returns error if the end address
|
||||||
|
* (=addr + length) is not aligned to the size of the sector in which the end
|
||||||
|
* address is located.
|
||||||
* Call \ref cy_serial_flash_qspi_get_size() to get the flash size and
|
* Call \ref cy_serial_flash_qspi_get_size() to get the flash size and
|
||||||
* call \ref cy_serial_flash_qspi_get_erase_size() to get the size of an erase
|
* call \ref cy_serial_flash_qspi_get_erase_size() to get the size of an erase
|
||||||
* sector.
|
* sector.
|
||||||
|
@ -177,10 +254,17 @@ cy_rslt_t cy_serial_flash_qspi_enable_xip(bool enable);
|
||||||
*/
|
*/
|
||||||
void cy_serial_flash_qspi_set_interrupt_priority(uint8_t priority);
|
void cy_serial_flash_qspi_set_interrupt_priority(uint8_t priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Changes the DMA interrupt priority
|
||||||
|
* \param priority interrupt priority to be set
|
||||||
|
*/
|
||||||
|
void cy_serial_flash_qspi_set_dma_interrupt_priority(uint8_t priority);
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CY_IP_MXSMIF */
|
#endif // CY_IP_MXSMIF
|
||||||
|
|
||||||
/** \} group_board_libs */
|
/** \} group_board_libs */
|
|
@ -0,0 +1 @@
|
||||||
|
<version>1.1.0.20805</version>
|
|
@ -1 +0,0 @@
|
||||||
<version>.19214</version>
|
|
Loading…
Reference in New Issue