Skip to content

Commit 09182d1

Browse files
author
Kyle Kearney
committed
Refactor serial flash support
1 parent 7059000 commit 09182d1

File tree

5 files changed

+305
-229
lines changed

5 files changed

+305
-229
lines changed

targets/TARGET_Cypress/TARGET_PSOC6/common/cybsp_serial_flash_prog.c renamed to targets/TARGET_Cypress/TARGET_PSOC6/common/cy_serial_flash_prog.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/***************************************************************************//**
2-
* \file cybsp_serial_flash_prog.c
2+
* \file cy_serial_flash_prog.c
33
*
44
* \brief
55
* Provides variables necessary to inform programming tools how to program the
66
* attached serial flash memory. The variables used here must be placed at
77
* specific locations in order to be detected and used by programming tools
8-
* to know that there is an attached memory and its characteristics.
8+
* to know that there is an attached memory and its characteristics. Uses the
9+
* configuration provided as part of BSP.
910
*
1011
********************************************************************************
1112
* \copyright
@@ -26,22 +27,22 @@
2627
*******************************************************************************/
2728

2829
/**
29-
* \addtogroup group_bsp_serial_flash Serial Flash
30+
* \addtogroup group_serial_flash Serial Flash
3031
* \{
3132
* Variables for informing programming tools that there is an attached memory device and what
3233
* its characteristics are so it can be programmed just like the on-chip memory.
3334
*
34-
* \defgroup group_bsp_serial_flash_variables Variables
35+
* \defgroup group_serial_flash_variables Variables
3536
*/
3637

3738
#include <stdint.h>
38-
#include "cybsp_types.h"
3939

4040
#if defined(__cplusplus)
4141
extern "C" {
4242
#endif
4343

44-
#if defined(CYBSP_QSPI_SCK) && (DEVICE_QSPI)
44+
#if defined(CY_ENABLE_XIP_PROGRAM)
45+
4546
#include "cycfg_qspi_memslot.h"
4647

4748
typedef struct
@@ -51,7 +52,7 @@ typedef struct
5152
} stc_smif_ipblocks_arr_t;
5253

5354
/**
54-
* \addtogroup group_bsp_serial_flash_variables
55+
* \addtogroup group_serial_flash_variables
5556
* \{
5657
*/
5758

@@ -61,7 +62,7 @@ typedef struct
6162
* are multiple ways this can be accomplished including:
6263
* 1) Placing it in a dedicated memory block with a known address. (as done here)
6364
* 2) Placing it at an absolute location via a the linker script
64-
* 3) Using cymcuelftool to recompute the checksum and patch the elf file after linking
65+
* 3) Using 'cymcuelftool -S' to recompute the checksum and patch the elf file after linking
6566
*/
6667
CY_SECTION(".cy_sflash_user_data") __attribute__( (used) )
6768
const stc_smif_ipblocks_arr_t smifIpBlocksArr = {&smifBlockConfig, 0x00000000};
@@ -81,14 +82,21 @@ const uint32_t cyToc[128] =
8182
0, /* Offset=0x0008: Key Storage Address */
8283
(int)&smifIpBlocksArr, /* Offset=0x000C: This points to a null terminated array of SMIF structures. */
8384
0x10000000u, /* Offset=0x0010: App image start address */
84-
[127] = 0x0B1F0000 /* Offset=0x01FC: CRC16-CCITT (the upper 2 bytes contain the CRC and the lower 2 bytes are 0) */
85+
/* Offset=0x0014-0x01F7: Reserved */
86+
[126] = 0x000002C2, /* Offset=0x01F8: Bits[ 1: 0] CLOCK_CONFIG (0=8MHz, 1=25MHz, 2=50MHz, 3=100MHz)
87+
Bits[ 4: 2] LISTEN_WINDOW (0=20ms, 1=10ms, 2=1ms, 3=0ms, 4=100ms)
88+
Bits[ 6: 5] SWJ_PINS_CTL (0/1/3=Disable SWJ, 2=Enable SWJ)
89+
Bits[ 8: 7] APP_AUTHENTICATION (0/2/3=Enable, 1=Disable)
90+
Bits[10: 9] FB_BOOTLOADER_CTL: UNUSED */
91+
[127] = 0x3BB30000 /* Offset=0x01FC: CRC16-CCITT (the upper 2 bytes contain the CRC and the lower 2 bytes are 0) */
8592
};
8693

87-
/** \} group_bsp_serial_flash_variables */
88-
#endif /* defined(CYBSP_QSPI_SCK) && (DEVICE_QSPI) */
94+
/** \} group_serial_flash_variables */
95+
96+
#endif /* defined(CY_ENABLE_XIP_PROGRAM) */
8997

9098
#if defined(__cplusplus)
9199
}
92100
#endif
93101

94-
/** \} group_bsp_serial_flash */
102+
/** \} group_serial_flash */
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/***************************************************************************//**
2+
* \file cy_serial_flash_qspi.c
3+
*
4+
* \brief
5+
* Provides APIs for interacting with an external flash connected to the SPI or
6+
* QSPI interface, uses SFDP to auto-discover memory properties if SFDP is
7+
* enabled in the configuration.
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+
#include <stdbool.h>
28+
#include "cy_serial_flash_qspi.h"
29+
#include "cyhal_qspi.h"
30+
#include "cy_utils.h"
31+
32+
#ifdef CY_IP_MXSMIF
33+
34+
#if defined(__cplusplus)
35+
extern "C" {
36+
#endif
37+
38+
39+
/** \cond internal */
40+
41+
/** Timeout to apply while polling the memory for its ready status after quad
42+
* enable command has been sent out. Quad enable is a non-volatile write.
43+
*/
44+
#define CY_SERIAL_FLASH_QUAD_ENABLE_TIMEOUT_US (5000lu) /* in microseconds */
45+
46+
/* Number of memories supported by the driver */
47+
#define SMIF_MEM_DEVICES (1u)
48+
49+
/* SMIF slot from which the memory configuration is picked up - fixed to 0 as the driver
50+
* supports only one device */
51+
#define MEM_SLOT (0u)
52+
53+
/** \endcond */
54+
55+
static cyhal_qspi_t qspi_obj;
56+
57+
static cy_stc_smif_mem_config_t * qspi_mem_config[SMIF_MEM_DEVICES];
58+
59+
static cy_stc_smif_block_config_t qspi_block_config =
60+
{
61+
/* The number of SMIF memories defined. */
62+
.memCount = SMIF_MEM_DEVICES,
63+
/* The pointer to the array of memory config structures of size memCount. */
64+
.memConfig = (cy_stc_smif_mem_config_t**)qspi_mem_config,
65+
/* The version of the SMIF driver. */
66+
.majorVersion = CY_SMIF_DRV_VERSION_MAJOR,
67+
/* The version of the SMIF driver. */
68+
.minorVersion = CY_SMIF_DRV_VERSION_MINOR
69+
};
70+
71+
/* The driver supports only one memory. When multiple memory configurations
72+
* are generated by the SMIF configurator tool, provide only the
73+
* configuration for memory that need to be supported by the driver.
74+
* Memory configuration can be changed by deinit followed by init with new
75+
* configuration */
76+
cy_rslt_t cy_serial_flash_qspi_init(
77+
const cy_stc_smif_mem_config_t* mem_config,
78+
cyhal_gpio_t io0,
79+
cyhal_gpio_t io1,
80+
cyhal_gpio_t io2,
81+
cyhal_gpio_t io3,
82+
cyhal_gpio_t io4,
83+
cyhal_gpio_t io5,
84+
cyhal_gpio_t io6,
85+
cyhal_gpio_t io7,
86+
cyhal_gpio_t sclk,
87+
cyhal_gpio_t ssel,
88+
uint32_t hz)
89+
{
90+
cy_en_smif_status_t smifStatus = CY_SMIF_SUCCESS;
91+
92+
93+
cy_rslt_t result = cyhal_qspi_init(&qspi_obj, io0, io1, io2, io3, io4, io5, io6, io7,
94+
sclk, ssel, hz, 0);
95+
96+
qspi_mem_config[MEM_SLOT] = (cy_stc_smif_mem_config_t*) mem_config;
97+
98+
if(CY_RSLT_SUCCESS == result)
99+
{
100+
/* Perform SFDP detection and XIP register configuration depending on the
101+
* memory configuration.
102+
*/
103+
smifStatus = Cy_SMIF_MemInit(qspi_obj.base, &qspi_block_config, &qspi_obj.context);
104+
if(CY_SMIF_SUCCESS == smifStatus)
105+
{
106+
/* Enable Quad mode (1-1-4 or 1-4-4 modes) to use all the four I/Os during
107+
* communication.
108+
*/
109+
110+
if(qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->readCmd->dataWidth == CY_SMIF_WIDTH_QUAD
111+
|| qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->programCmd->dataWidth == CY_SMIF_WIDTH_QUAD)
112+
{
113+
bool isQuadEnabled = false;
114+
smifStatus = Cy_SMIF_MemIsQuadEnabled(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], &isQuadEnabled, &qspi_obj.context);
115+
if(CY_SMIF_SUCCESS == smifStatus)
116+
{
117+
if(!isQuadEnabled)
118+
{
119+
smifStatus = Cy_SMIF_MemEnableQuadMode(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], CY_SERIAL_FLASH_QUAD_ENABLE_TIMEOUT_US, &qspi_obj.context);
120+
}
121+
}
122+
}
123+
}
124+
}
125+
126+
if((CY_RSLT_SUCCESS == result) && (CY_SMIF_SUCCESS == smifStatus))
127+
{
128+
return CY_RSLT_SUCCESS;
129+
}
130+
else
131+
{
132+
Cy_SMIF_MemDeInit(qspi_obj.base);
133+
cy_serial_flash_qspi_deinit();
134+
return (cy_rslt_t)smifStatus;
135+
}
136+
}
137+
138+
void cy_serial_flash_qspi_deinit(void)
139+
{
140+
Cy_SMIF_MemDeInit(qspi_obj.base);
141+
cyhal_qspi_free(&qspi_obj);
142+
}
143+
144+
size_t cy_serial_flash_qspi_get_size(void)
145+
{
146+
return (size_t)qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->memSize;
147+
}
148+
149+
/* address is ignored for the memory with uniform sector size. Currently,
150+
* QSPI Configurator does not support memories with hybrid sectors.
151+
*/
152+
size_t cy_serial_flash_qspi_get_erase_size(uint32_t addr)
153+
{
154+
CY_UNUSED_PARAMETER(addr);
155+
return (size_t)qspi_block_config.memConfig[MEM_SLOT]->deviceCfg->eraseSize;
156+
}
157+
158+
cy_rslt_t cy_serial_flash_qspi_read(uint32_t addr, size_t length, uint8_t *buf)
159+
{
160+
/* Cy_SMIF_MemRead() returns error if (addr + length) > total flash size. */
161+
return (cy_rslt_t)Cy_SMIF_MemRead(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], addr, buf, length, &qspi_obj.context);
162+
}
163+
164+
cy_rslt_t cy_serial_flash_qspi_write(uint32_t addr, size_t length, const uint8_t *buf)
165+
{
166+
/* Cy_SMIF_MemWrite() returns error if (addr + length) > total flash size. */
167+
return (cy_rslt_t)Cy_SMIF_MemWrite(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], addr, (uint8_t *)buf, length, &qspi_obj.context);
168+
}
169+
170+
/* Does not support hybrid sectors, sector size must be uniform on the entire
171+
* chip. Use cy_serial_flash_qspi_get_erase_size(addr) to implement hybrid sector
172+
* support when QSPI Configurator and PDL supports memories with hybrid sectors.
173+
*/
174+
cy_rslt_t cy_serial_flash_qspi_erase(uint32_t addr, size_t length)
175+
{
176+
cy_en_smif_status_t smifStatus;
177+
178+
/* If the erase is for the entire chip, use chip erase command */
179+
if((addr == 0u) && (length == cy_serial_flash_qspi_get_size()))
180+
{
181+
smifStatus = Cy_SMIF_MemEraseChip(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], &qspi_obj.context);
182+
}
183+
else
184+
{
185+
/* Cy_SMIF_MemEraseSector() returns error if (addr + length) > total flash size
186+
* or if addr is not aligned to erase sector size or if (addr + length)
187+
* is not aligned to erase sector size.
188+
*/
189+
smifStatus = Cy_SMIF_MemEraseSector(qspi_obj.base, qspi_block_config.memConfig[MEM_SLOT], addr, length, &qspi_obj.context);
190+
}
191+
192+
return (cy_rslt_t)smifStatus;
193+
}
194+
195+
// This function enables or disables XIP on the MCU, does not send any command
196+
// to the serial flash. XIP register configuration is already done as part of
197+
// cy_serial_flash_qspi_init() if MMIO mode is enabled in the QSPI
198+
// Configurator.
199+
cy_rslt_t cy_serial_flash_qspi_enable_xip(bool enable)
200+
{
201+
if(enable)
202+
{
203+
Cy_SMIF_SetMode(qspi_obj.base, CY_SMIF_MEMORY);
204+
}
205+
else
206+
{
207+
Cy_SMIF_SetMode(qspi_obj.base, CY_SMIF_NORMAL);
208+
}
209+
210+
return CY_RSLT_SUCCESS;
211+
}
212+
213+
#if defined(__cplusplus)
214+
}
215+
#endif
216+
217+
#endif /* CY_IP_MXSMIF */
218+

0 commit comments

Comments
 (0)