Skip to content

Commit 9d78c65

Browse files
committed
drivers/flash/mcux: fix flash_read() operation on LPC55S36
As other targets in the LPC55xxx series, the LPC55S36 has a Flash controller that raises ECC errors when reading erased pages directly. To avoid this, there is special code for this platform that calls the HAL FLASH_IsFlashAreaReadable() function. However, this in turn calls a function at an hardcoded address in ROM that _always_ causes an instruction fault, making the situation worse. This patch reworks the read operation to use the FLASH_Read() HAL function for this target to gracefully handle error conditions and properly emulate accesses to erased pages. The preprocessor is required since some targets do not define the FLASH_Read() function. Fixes: #80325 Signed-off-by: Luca Burelli <[email protected]>
1 parent 185432c commit 9d78c65

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

drivers/flash/soc_flash_mcux.c

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ LOG_MODULE_REGISTER(flash_mcux);
5555

5656
#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
5757

58-
#if defined(CONFIG_CHECK_BEFORE_READING) && !defined(CONFIG_SOC_LPC55S36)
58+
#if defined(CONFIG_CHECK_BEFORE_READING) && !defined(CONFIG_SOC_LPC55S36)
5959
#define FMC_STATUS_FAIL FLASH_INT_CLR_ENABLE_FAIL_MASK
6060
#define FMC_STATUS_ERR FLASH_INT_CLR_ENABLE_ERR_MASK
6161
#define FMC_STATUS_DONE FLASH_INT_CLR_ENABLE_DONE_MASK
@@ -205,35 +205,53 @@ static int flash_mcux_read(const struct device *dev, off_t offset,
205205
addr = offset + priv->pflash_block_base;
206206

207207
#ifdef CONFIG_CHECK_BEFORE_READING
208+
/*
209+
* Ensure the area is readable, since a direct access may cause faults
210+
* on erased or otherwise unreadable pages. Emulate erased pages,
211+
* return other errors.
212+
*/
208213
#ifdef CONFIG_SOC_LPC55S36
209-
/* Validates the given address range is loaded in the flash hiding region. */
210-
rc = FLASH_IsFlashAreaReadable(&priv->config, addr, len);
211-
if (rc != kStatus_FLASH_Success) {
212-
rc = -EIO;
213-
} else {
214-
/* Check whether the flash is erased ("len" and "addr" must be word-aligned). */
214+
/* On LPC55S36, use a HAL function to safely copy from Flash. */
215+
rc = FLASH_Read(&priv->config, addr, data, len);
216+
switch (rc) {
217+
case kStatus_FLASH_Success:
218+
rc = 0;
219+
break;
220+
case kStatus_FLASH_EccError:
221+
/* Check id the ECC issue is due to the Flash being erased
222+
* ("addr" and "len" must be word-aligned for this call).
223+
*/
215224
rc = FLASH_VerifyErase(&priv->config, ((addr + 0x3) & ~0x3), ((len + 0x3) & ~0x3));
216225
if (rc == kStatus_FLASH_Success) {
217226
rc = -ENODATA;
218227
} else {
219-
rc = 0;
228+
rc = -EIO;
220229
}
230+
break;
231+
default:
232+
rc = -EIO;
233+
break;
221234
}
222-
#else
235+
#else /* CONFIG_SOC_LPC55S36 */
236+
/* On all other targets, check if the Flash area is readable.
237+
* If so, copy data from it directly.
238+
*/
223239
rc = is_area_readable(addr, len);
224-
#endif /* CONFIG_SOC_LPC55S36 */
225-
#endif /* CONFIG_CHECK_BEFORE_READING */
226-
227240
if (!rc) {
228241
memcpy(data, (void *) addr, len);
229242
}
230-
#ifdef CONFIG_CHECK_BEFORE_READING
231-
else if (rc == -ENODATA) {
243+
#endif /* CONFIG_SOC_LPC55S36 */
244+
245+
if (rc == -ENODATA) {
232246
/* Erased area, return dummy data as an erased page. */
233247
memset(data, 0xFF, len);
234248
rc = 0;
235249
}
236-
#endif
250+
#else /* CONFIG_CHECK_BEFORE_READING */
251+
/* No safety checks, directly copy the memory mapped data. */
252+
memcpy(data, (void *) addr, len);
253+
#endif /* CONFIG_CHECK_BEFORE_READING */
254+
237255
return rc;
238256
}
239257

0 commit comments

Comments
 (0)