Skip to content

Commit 335f3ad

Browse files
authored
Merge pull request #11355 from kyle-cypress/pr/psoc-serial-flash
Initial support for Serial Flash on PSoC Devices
2 parents c99b150 + d373cab commit 335f3ad

File tree

4 files changed

+426
-0
lines changed

4 files changed

+426
-0
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/***************************************************************************//**
2+
* \file cybsp_serial_flash.c
3+
*
4+
* \brief
5+
* Provides APIs for interacting with an external flash connected to the SPI or
6+
* QSPI interface, uses the configuration generated by the QSPI configurator,
7+
* uses SFDP to auto-discover memory properties if SFDP is enabled in the
8+
* configuration.
9+
*
10+
********************************************************************************
11+
* \copyright
12+
* Copyright 2018-2019 Cypress Semiconductor Corporation
13+
* SPDX-License-Identifier: Apache-2.0
14+
*
15+
* Licensed under the Apache License, Version 2.0 (the "License");
16+
* you may not use this file except in compliance with the License.
17+
* You may obtain a copy of the License at
18+
*
19+
* http://www.apache.org/licenses/LICENSE-2.0
20+
*
21+
* Unless required by applicable law or agreed to in writing, software
22+
* distributed under the License is distributed on an "AS IS" BASIS,
23+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24+
* See the License for the specific language governing permissions and
25+
* limitations under the License.
26+
*******************************************************************************/
27+
28+
#include <stdbool.h>
29+
#include "cybsp_serial_flash.h"
30+
#include "cy_pdl.h"
31+
#include "cyhal_qspi.h"
32+
#include "cy_utils.h"
33+
#include "cybsp.h"
34+
35+
#if defined(__cplusplus)
36+
extern "C" {
37+
#endif
38+
39+
#if defined(CYBSP_QSPI_SCK)
40+
#include "cycfg_qspi_memslot.h"
41+
42+
/** \cond internal */
43+
44+
#define QSPI_BUS_FREQUENCY_HZ (50000000lu)
45+
46+
/** Timeout to apply while polling the memory for its ready status after quad
47+
* enable command has been sent out. Quad enable is a non-volatile write.
48+
*/
49+
#define CYBSP_SERIAL_FLASH_QUAD_ENABLE_TIMEOUT_US (5000lu) /* in microseconds */
50+
51+
/* SMIF slot number to which the memory is connected */
52+
#define MEM_SLOT (0u)
53+
54+
/** \endcond */
55+
56+
static cyhal_qspi_t qspi_obj;
57+
58+
cy_rslt_t cybsp_serial_flash_init(void)
59+
{
60+
cy_en_smif_status_t smifStatus = CY_SMIF_SUCCESS;
61+
62+
cy_rslt_t result = cyhal_qspi_init(&qspi_obj, CYBSP_QSPI_D0, CYBSP_QSPI_D1, CYBSP_QSPI_D2, CYBSP_QSPI_D3, NC, NC, NC, NC,
63+
CYBSP_QSPI_SCK, CYBSP_QSPI_SS, QSPI_BUS_FREQUENCY_HZ, 0);
64+
if(CY_RSLT_SUCCESS == result)
65+
{
66+
/* Perform SFDP detection and XIP register configuration depending on the
67+
* memory configuration.
68+
*/
69+
smifStatus = Cy_SMIF_Memslot_Init(qspi_obj.base, (cy_stc_smif_block_config_t *) &smifBlockConfig, &qspi_obj.context);
70+
if(CY_SMIF_SUCCESS == smifStatus)
71+
{
72+
/* Enable Quad mode (1-1-4 or 1-4-4 modes) to use all the four I/Os during
73+
* communication.
74+
*/
75+
if(smifMemConfigs[MEM_SLOT]->deviceCfg->readCmd->dataWidth == CY_SMIF_WIDTH_QUAD
76+
|| smifMemConfigs[MEM_SLOT]->deviceCfg->programCmd->dataWidth == CY_SMIF_WIDTH_QUAD)
77+
{
78+
bool isQuadEnabled = false;
79+
smifStatus = Cy_SMIF_MemIsQuadEnabled(qspi_obj.base, smifMemConfigs[MEM_SLOT], &isQuadEnabled, &qspi_obj.context);
80+
if(CY_SMIF_SUCCESS == smifStatus)
81+
{
82+
if(!isQuadEnabled)
83+
{
84+
smifStatus = Cy_SMIF_MemEnableQuadMode(qspi_obj.base, smifMemConfigs[MEM_SLOT], CYBSP_SERIAL_FLASH_QUAD_ENABLE_TIMEOUT_US, &qspi_obj.context);
85+
}
86+
}
87+
}
88+
}
89+
}
90+
91+
if((CY_RSLT_SUCCESS == result) && (CY_SMIF_SUCCESS == smifStatus))
92+
{
93+
return CY_RSLT_SUCCESS;
94+
}
95+
else
96+
{
97+
cybsp_serial_flash_deinit();
98+
return (cy_rslt_t)smifStatus;
99+
}
100+
}
101+
102+
void cybsp_serial_flash_deinit(void)
103+
{
104+
cyhal_qspi_free(&qspi_obj);
105+
}
106+
107+
size_t cybsp_serial_flash_get_size(void)
108+
{
109+
return (size_t)smifMemConfigs[MEM_SLOT]->deviceCfg->memSize;
110+
}
111+
112+
/* address is ignored for the memory with uniform sector size. Currently,
113+
* QSPI Configurator does not support memories with hybrid sectors.
114+
*/
115+
size_t cybsp_serial_flash_get_erase_size(uint32_t addr)
116+
{
117+
CY_UNUSED_PARAMETER(addr);
118+
return (size_t)smifMemConfigs[MEM_SLOT]->deviceCfg->eraseSize;
119+
}
120+
121+
cy_rslt_t cybsp_serial_flash_read(uint32_t addr, size_t length, uint8_t *buf)
122+
{
123+
/* Cy_SMIF_MemRead() returns error if (addr + length) > total flash size. */
124+
return (cy_rslt_t)Cy_SMIF_MemRead(qspi_obj.base, smifMemConfigs[MEM_SLOT], addr, buf, length, &qspi_obj.context);
125+
}
126+
127+
cy_rslt_t cybsp_serial_flash_write(uint32_t addr, size_t length, const uint8_t *buf)
128+
{
129+
/* Cy_SMIF_MemWrite() returns error if (addr + length) > total flash size. */
130+
return (cy_rslt_t)Cy_SMIF_MemWrite(qspi_obj.base, smifMemConfigs[MEM_SLOT], addr, (uint8_t *)buf, length, &qspi_obj.context);
131+
}
132+
133+
/* Does not support hybrid sectors, sector size must be uniform on the entire
134+
* chip. Use cybsp_serial_flash_get_erase_size(addr) to implement hybrid sector
135+
* support when QSPI Configurator and PDL supports memories with hybrid sectors.
136+
*/
137+
cy_rslt_t cybsp_serial_flash_erase(uint32_t addr, size_t length)
138+
{
139+
cy_en_smif_status_t smifStatus;
140+
141+
/* If the erase is for the entire chip, use chip erase command */
142+
if((addr == 0u) && (length == cybsp_serial_flash_get_size()))
143+
{
144+
smifStatus = Cy_SMIF_MemEraseChip(qspi_obj.base, smifMemConfigs[MEM_SLOT], &qspi_obj.context);
145+
}
146+
else
147+
{
148+
/* Cy_SMIF_MemEraseSector() returns error if (addr + length) > total flash size
149+
* or if addr is not aligned to erase sector size or if (addr + length)
150+
* is not aligned to erase sector size.
151+
*/
152+
smifStatus = Cy_SMIF_MemEraseSector(qspi_obj.base, smifMemConfigs[MEM_SLOT], addr, length, &qspi_obj.context);
153+
}
154+
155+
return (cy_rslt_t)smifStatus;
156+
}
157+
158+
// This function enables or disables XIP on the MCU, does not send any command
159+
// to the serial flash. XIP register configuration is already done as part of
160+
// cybsp_serial_flash_init() if MMIO mode is enabled in the QSPI
161+
// Configurator.
162+
cy_rslt_t cybsp_serial_flash_enable_xip(bool enable)
163+
{
164+
if(enable)
165+
{
166+
Cy_SMIF_SetMode(qspi_obj.base, CY_SMIF_MEMORY);
167+
}
168+
else
169+
{
170+
Cy_SMIF_SetMode(qspi_obj.base, CY_SMIF_NORMAL);
171+
}
172+
173+
return CY_RSLT_SUCCESS;
174+
}
175+
176+
#endif /* defined(CYBSP_QSPI_SCK) */
177+
178+
#if defined(__cplusplus)
179+
}
180+
#endif
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/***************************************************************************//**
2+
* \file cybsp_serial_flash.h
3+
*
4+
* \brief
5+
* Provides APIs for interacting with an external flash connected to the SPI or
6+
* QSPI interface. Flash operations read, write, and erase are implemented as
7+
* blocking functions.
8+
*
9+
********************************************************************************
10+
* \copyright
11+
* Copyright 2018-2019 Cypress Semiconductor Corporation
12+
* SPDX-License-Identifier: Apache-2.0
13+
*
14+
* Licensed under the Apache License, Version 2.0 (the "License");
15+
* you may not use this file except in compliance with the License.
16+
* You may obtain a copy of the License at
17+
*
18+
* http://www.apache.org/licenses/LICENSE-2.0
19+
*
20+
* Unless required by applicable law or agreed to in writing, software
21+
* distributed under the License is distributed on an "AS IS" BASIS,
22+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23+
* See the License for the specific language governing permissions and
24+
* limitations under the License.
25+
*******************************************************************************/
26+
27+
/**
28+
* \addtogroup group_bsp_serial_flash Serial Flash
29+
* \{
30+
* Driver for interfacing with the serial flash (QSPI NOR flash) on Cypress boards.
31+
*
32+
* \defgroup group_bsp_serial_flash_macros Macros
33+
* \defgroup group_bsp_serial_flash_functions Functions
34+
*/
35+
36+
#pragma once
37+
38+
#include <stddef.h>
39+
#include "cy_result.h"
40+
41+
#if defined(__cplusplus)
42+
extern "C" {
43+
#endif
44+
45+
/**
46+
* \addtogroup group_bsp_serial_flash_macros
47+
* \{
48+
*/
49+
50+
/** The function or operation is not supported on the target or the memory */
51+
#define CYBSP_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_BSP, 6))
52+
53+
/** \} group_bsp_serial_flash_macros */
54+
55+
/**
56+
* \addtogroup group_bsp_serial_flash_functions
57+
* \{
58+
*/
59+
60+
/**
61+
* \brief Initializes the serial flash on the board.
62+
* \returns CY_RSLT_SUCCESS if the initialization was successful, an error code
63+
* otherwise.
64+
*/
65+
cy_rslt_t cybsp_serial_flash_init(void);
66+
67+
/**
68+
* \brief De-initializes the serial flash on the board.
69+
*/
70+
void cybsp_serial_flash_deinit(void);
71+
72+
/**
73+
* \brief Returns the size of the serial flash on the board in bytes.
74+
* \returns Memory size in bytes.
75+
*/
76+
size_t cybsp_serial_flash_get_size(void);
77+
78+
/**
79+
* \brief Returns the size of the erase sector to which the given address
80+
* belongs. Address is used only for a memory with hybrid sector size.
81+
* \param addr Address that belongs to the sector for which size is returned.
82+
* \returns Erase sector size in bytes.
83+
*/
84+
size_t cybsp_serial_flash_get_erase_size(uint32_t addr);
85+
86+
/**
87+
* \brief Reads data from the serial flash on the board. This is a blocking
88+
* function. Returns error if (addr + length) exceeds the flash size.
89+
* \param addr Starting address to read from
90+
* \param length Number of data bytes to read
91+
* \param buf Pointer to the buffer to store the data read from the memory
92+
* \returns CY_RSLT_SUCCESS if the read was successful, an error code otherwise.
93+
*/
94+
cy_rslt_t cybsp_serial_flash_read(uint32_t addr, size_t length, uint8_t *buf);
95+
96+
/**
97+
* \brief Writes the data to the serial flash on the board. The program area
98+
* must have been erased prior to calling this API using
99+
* \ref cybsp_serial_flash_erase() This is a blocking function. Returns error if
100+
* (addr + length) exceeds the flash size.
101+
* \param addr Starting address to write to
102+
* \param length Number of bytes to write
103+
* \param buf Pointer to the buffer storing the data to be written
104+
* \returns CY_RSLT_SUCCESS if the write was successful, an error code
105+
* otherwise.
106+
*/
107+
cy_rslt_t cybsp_serial_flash_write(uint32_t addr, size_t length, const uint8_t *buf);
108+
109+
/**
110+
* \brief Erases the serial flash on the board, uses chip erase command when
111+
* addr = 0 and length = flash_size otherwise uses sector erase command. This is
112+
* a blocking function. Returns error if addr or (addr + length) is not aligned
113+
* to the sector size or if (addr + length) exceeds the flash size.
114+
* Call \ref cybsp_serial_flash_get_size() to get the flash size and
115+
* call \ref cybsp_serial_flash_get_erase_size() to get the size of an erase
116+
* sector.
117+
*
118+
* \param addr Starting address to begin erasing
119+
* \param length Number of bytes to erase
120+
* \returns CY_RSLT_SUCCESS if the erase was successful, an error code
121+
* otherwise.
122+
*/
123+
cy_rslt_t cybsp_serial_flash_erase(uint32_t addr, size_t length);
124+
125+
/**
126+
* \brief Enables Execute-in-Place (memory mapped) mode on the MCU. This
127+
* function does not send any command to the serial flash. This may not be
128+
* supported on all the targets in which case
129+
* CYBSP_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED is returned.
130+
* \param enable true: XIP mode is set, false: normal mode is set
131+
* \returns CY_RSLT_SUCCESS if the operation was successful.
132+
* CYBSP_RSLT_SERIAL_FLASH_ERR_UNSUPPORTED if the target does not
133+
* support XIP.
134+
*/
135+
cy_rslt_t cybsp_serial_flash_enable_xip(bool enable);
136+
137+
/** \} group_bsp_serial_flash_functions */
138+
139+
#if defined(__cplusplus)
140+
}
141+
#endif
142+
143+
/** \} group_bsp_serial_flash */

0 commit comments

Comments
 (0)