Skip to content

Commit 3d21b82

Browse files
committed
MXRT1050: Add support for Flash driver
Signed-off-by: Mahesh Mahadevan <[email protected]>
1 parent e46e482 commit 3d21b82

File tree

5 files changed

+562
-5
lines changed

5 files changed

+562
-5
lines changed
Lines changed: 364 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2019 ARM Limited
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "flash_api.h"
19+
#include "mbed_toolchain.h"
20+
#include "mbed_critical.h"
21+
22+
#if DEVICE_FLASH
23+
24+
#include "fsl_flexspi.h"
25+
#include "fsl_cache.h"
26+
#include "flash_defines.h"
27+
28+
AT_QUICKACCESS_SECTION_CODE(void flexspi_update_lut_ram(void));
29+
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_write_enable_ram(uint32_t baseAddr));
30+
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_wait_bus_busy_ram(void));
31+
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_flash_erase_sector_ram(uint32_t address));
32+
AT_QUICKACCESS_SECTION_CODE(static void flexspi_lower_clock_ram(void));
33+
AT_QUICKACCESS_SECTION_CODE(static void flexspi_clock_update_ram(void));
34+
AT_QUICKACCESS_SECTION_CODE(status_t flexspi_nor_flash_page_program_ram(uint32_t address,
35+
const uint32_t *src,
36+
uint32_t size));
37+
AT_QUICKACCESS_SECTION_CODE(void flexspi_nor_flash_read_data_ram(uint32_t addr,
38+
uint32_t *buffer,
39+
uint32_t size));
40+
41+
void flexspi_update_lut_ram(void)
42+
{
43+
flexspi_config_t config;
44+
45+
memset(&config, 0, sizeof(config));
46+
47+
/*Get FLEXSPI default settings and configure the flexspi. */
48+
FLEXSPI_GetDefaultConfig(&config);
49+
50+
/*Set AHB buffer size for reading data through AHB bus. */
51+
config.ahbConfig.enableAHBPrefetch = true;
52+
/*Allow AHB read start address do not follow the alignment requirement. */
53+
config.ahbConfig.enableReadAddressOpt = true;
54+
config.ahbConfig.enableAHBBufferable = true;
55+
config.ahbConfig.enableAHBCachable = true;
56+
/* enable diff clock and DQS */
57+
config.enableSckBDiffOpt = true;
58+
config.rxSampleClock = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad;
59+
config.enableCombination = true;
60+
FLEXSPI_Init(FLEXSPI, &config);
61+
62+
/* Configure flash settings according to serial flash feature. */
63+
FLEXSPI_SetFlashConfig(FLEXSPI, &deviceconfig, kFLEXSPI_PortA1);
64+
65+
/* Update LUT table. */
66+
FLEXSPI_UpdateLUT(FLEXSPI, 0, customLUT, CUSTOM_LUT_LENGTH);
67+
68+
FLEXSPI_SoftwareReset(FLEXSPI);
69+
70+
/* Wait for bus idle. */
71+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
72+
}
73+
}
74+
75+
status_t flexspi_nor_write_enable_ram(uint32_t baseAddr)
76+
{
77+
flexspi_transfer_t flashXfer;
78+
status_t status = kStatus_Success;
79+
80+
memset(&flashXfer, 0, sizeof(flashXfer));
81+
82+
/* Write enable */
83+
flashXfer.deviceAddress = baseAddr;
84+
flashXfer.port = kFLEXSPI_PortA1;
85+
flashXfer.cmdType = kFLEXSPI_Command;
86+
flashXfer.SeqNumber = 2;
87+
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE;
88+
89+
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
90+
91+
return status;
92+
}
93+
94+
status_t flexspi_nor_wait_bus_busy_ram(void)
95+
{
96+
/* Wait status ready. */
97+
bool isBusy = false;
98+
uint32_t readValue = 0;
99+
status_t status = kStatus_Success;
100+
flexspi_transfer_t flashXfer;
101+
102+
memset(&flashXfer, 0, sizeof(flashXfer));
103+
104+
flashXfer.deviceAddress = 0;
105+
flashXfer.port = kFLEXSPI_PortA1;
106+
flashXfer.cmdType = kFLEXSPI_Read;
107+
flashXfer.SeqNumber = 2;
108+
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS;
109+
flashXfer.data = &readValue;
110+
flashXfer.dataSize = 2;
111+
112+
do {
113+
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
114+
115+
if (status != kStatus_Success) {
116+
return status;
117+
}
118+
119+
if (readValue & 0x8000) {
120+
isBusy = false;
121+
} else {
122+
isBusy = true;
123+
}
124+
125+
if (readValue & 0x3200) {
126+
status = kStatus_Fail;
127+
break;
128+
}
129+
130+
} while (isBusy);
131+
132+
return status;
133+
134+
}
135+
136+
status_t flexspi_nor_flash_erase_sector_ram(uint32_t address)
137+
{
138+
status_t status = kStatus_Success;
139+
flexspi_transfer_t flashXfer;
140+
141+
memset(&flashXfer, 0, sizeof(flashXfer));
142+
143+
/* Write enable */
144+
status = flexspi_nor_write_enable_ram(address);
145+
if (status != kStatus_Success) {
146+
return status;
147+
}
148+
149+
flashXfer.deviceAddress = address;
150+
flashXfer.port = kFLEXSPI_PortA1;
151+
flashXfer.cmdType = kFLEXSPI_Command;
152+
flashXfer.SeqNumber = 4;
153+
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR;
154+
155+
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
156+
if (status != kStatus_Success) {
157+
return status;
158+
}
159+
160+
status = flexspi_nor_wait_bus_busy_ram();
161+
162+
/* Do software reset. */
163+
FLEXSPI_SoftwareReset(FLEXSPI);
164+
165+
return status;
166+
}
167+
168+
static void flexspi_lower_clock_ram(void)
169+
{
170+
unsigned int reg = 0;
171+
172+
/* Wait for bus idle. */
173+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
174+
}
175+
176+
FLEXSPI_Enable(FLEXSPI, false);
177+
178+
/* Disable FlexSPI clock */
179+
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;
180+
181+
/* flexspi clock 66M, DDR mode, internal clock 33M. */
182+
reg = CCM->CSCMR1;
183+
reg &= ~CCM_CSCMR1_FLEXSPI_PODF_MASK;
184+
reg |= CCM_CSCMR1_FLEXSPI_PODF(3);
185+
CCM->CSCMR1 = reg;
186+
187+
/* Enable FlexSPI clock */
188+
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
189+
190+
FLEXSPI_Enable(FLEXSPI, true);
191+
192+
/* Do software reset. */
193+
FLEXSPI_SoftwareReset(FLEXSPI);
194+
195+
/* Wait for bus idle. */
196+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
197+
}
198+
}
199+
200+
static void flexspi_clock_update_ram(void)
201+
{
202+
/* Program finished, speed the clock to 133M. */
203+
/* Wait for bus idle before change flash configuration. */
204+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
205+
}
206+
FLEXSPI_Enable(FLEXSPI, false);
207+
/* Disable FlexSPI clock */
208+
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;
209+
210+
/* flexspi clock 260M, DDR mode, internal clock 130M. */
211+
CCM->CSCMR1 &= ~CCM_CSCMR1_FLEXSPI_PODF_MASK;
212+
213+
/* Enable FlexSPI clock */
214+
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
215+
216+
FLEXSPI_Enable(FLEXSPI, true);
217+
218+
/* Do software reset. */
219+
FLEXSPI_SoftwareReset(FLEXSPI);
220+
221+
/* Wait for bus idle. */
222+
while (!FLEXSPI_GetBusIdleStatus(FLEXSPI)) {
223+
}
224+
}
225+
226+
status_t flexspi_nor_flash_page_program_ram(uint32_t address, const uint32_t *src, uint32_t size)
227+
{
228+
status_t status = kStatus_Success;
229+
flexspi_transfer_t flashXfer;
230+
231+
memset(&flashXfer, 0, sizeof(flashXfer));
232+
233+
flexspi_lower_clock_ram();
234+
235+
/* Write enable */
236+
status = flexspi_nor_write_enable_ram(address);
237+
238+
if (status != kStatus_Success) {
239+
return status;
240+
}
241+
242+
/* Prepare page program command */
243+
flashXfer.deviceAddress = address;
244+
flashXfer.port = kFLEXSPI_PortA1;
245+
flashXfer.cmdType = kFLEXSPI_Write;
246+
flashXfer.SeqNumber = 2;
247+
flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM;
248+
flashXfer.data = (uint32_t *)src;
249+
flashXfer.dataSize = size;
250+
251+
status = FLEXSPI_TransferBlocking(FLEXSPI, &flashXfer);
252+
253+
if (status != kStatus_Success) {
254+
return status;
255+
}
256+
257+
status = flexspi_nor_wait_bus_busy_ram();
258+
259+
flexspi_clock_update_ram();
260+
261+
return status;
262+
}
263+
264+
void flexspi_nor_flash_read_data_ram(uint32_t addr, uint32_t *buffer, uint32_t size)
265+
{
266+
memcpy(buffer, (void *)addr, size);
267+
}
268+
269+
int32_t flash_init(flash_t *obj)
270+
{
271+
flexspi_update_lut_ram();
272+
273+
return 0;
274+
}
275+
276+
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
277+
{
278+
status_t status = kStatus_Success;
279+
int32_t ret = 0;
280+
281+
core_util_critical_section_enter();
282+
283+
status = flexspi_nor_flash_erase_sector_ram(address - FlexSPI_AMBA_BASE);
284+
285+
if (status != kStatus_Success) {
286+
ret = -1;
287+
} else {
288+
DCACHE_InvalidateByRange(address, BOARD_FLASH_SECTOR_SIZE);
289+
}
290+
291+
core_util_critical_section_exit();
292+
293+
return ret;
294+
}
295+
296+
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
297+
{
298+
status_t status = kStatus_Success;
299+
int32_t ret = 0;
300+
301+
core_util_critical_section_enter();
302+
303+
status = flexspi_nor_flash_page_program_ram(address - FlexSPI_AMBA_BASE, (uint32_t *)data, size);
304+
305+
if (status != kStatus_Success) {
306+
ret = -1;
307+
} else {
308+
DCACHE_InvalidateByRange(address, size);
309+
}
310+
311+
core_util_critical_section_exit();
312+
313+
return ret;
314+
}
315+
316+
int32_t flash_read(flash_t *obj, uint32_t address, uint8_t *data, uint32_t size)
317+
{
318+
flexspi_nor_flash_read_data_ram(address, (uint32_t *)data, size);
319+
320+
return 0;
321+
}
322+
323+
int32_t flash_free(flash_t *obj)
324+
{
325+
return 0;
326+
}
327+
328+
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
329+
{
330+
uint32_t sectorsize = MBED_FLASH_INVALID_SIZE;
331+
uint32_t devicesize = BOARD_FLASH_SIZE;
332+
uint32_t startaddr = BOARD_FLASH_START_ADDR;
333+
334+
if ((address >= startaddr) && (address < (startaddr + devicesize))) {
335+
sectorsize = BOARD_FLASH_SECTOR_SIZE;
336+
}
337+
338+
return sectorsize;
339+
}
340+
341+
uint32_t flash_get_page_size(const flash_t *obj)
342+
{
343+
return BOARD_FLASH_PAGE_SIZE;
344+
}
345+
346+
uint32_t flash_get_start_address(const flash_t *obj)
347+
{
348+
return BOARD_FLASH_START_ADDR;
349+
}
350+
351+
uint32_t flash_get_size(const flash_t *obj)
352+
{
353+
return BOARD_FLASH_SIZE;
354+
}
355+
356+
uint8_t flash_get_erase_value(const flash_t *obj)
357+
{
358+
(void)obj;
359+
360+
return 0xFF;
361+
}
362+
363+
#endif //DEVICE_FLASH
364+

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/objects.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ struct trng_s {
6666
uint8_t dummy;
6767
};
6868

69+
#if DEVICE_FLASH
70+
struct flash_s {
71+
uint8_t dummy;
72+
};
73+
#endif
74+
6975
#include "gpio_object.h"
7076

7177
#ifdef __cplusplus

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/device.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919
#define MBED_DEVICE_H
2020

2121
#define DEVICE_ID_LENGTH 24
22-
#define BOARD_FLASH_SIZE (0x4000000U)
22+
/* 4MB reserved for mbed-os */
23+
#define BOARD_FLASH_SIZE (0x3C00000U)
24+
#define BOARD_FLASH_START_ADDR (0x60400000U)
25+
26+
#define BOARD_FLASH_PAGE_SIZE (512)
27+
#define BOARD_FLASH_SECTOR_SIZE (262144)
28+
2329
#define BOARD_ENET_PHY_ADDR (2)
2430

2531
#include "objects.h"

0 commit comments

Comments
 (0)