S32K3XX Progmem dataflash with littlefs support

This commit is contained in:
Peter van der Perk
2022-12-23 14:24:31 +01:00
committed by Xiang Xiao
parent c8cf27e848
commit aac9eb57e8
7 changed files with 596 additions and 0 deletions
+8
View File
@@ -600,6 +600,14 @@ config S32K3XX_FS26
Engineering development purpose only, not for use in production. Engineering development purpose only, not for use in production.
Please refer to the FS26 Datasheet. Please refer to the FS26 Datasheet.
config S32K3XX_PROGMEM
bool "PROGMEM"
default n
select ARCH_HAVE_PROGMEM
---help---
Use the Data Flash data memory as a
Memory-Technology-Device (MTD).
endmenu # S32K3XX Peripheral Selection endmenu # S32K3XX Peripheral Selection
menu "S32K3XX eMIOS PWM Configuration" menu "S32K3XX eMIOS PWM Configuration"
+4
View File
@@ -76,6 +76,10 @@ ifeq ($(CONFIG_S32K3XX_QSPI),y)
CHIP_CSRCS += s32k3xx_qspi.c CHIP_CSRCS += s32k3xx_qspi.c
endif endif
ifeq ($(CONFIG_S32K3XX_PROGMEM),y)
CHIP_CSRCS += s32k3xx_progmem.c
endif
ifeq ($(CONFIG_BUILD_PROTECTED),y) ifeq ($(CONFIG_BUILD_PROTECTED),y)
CHIP_CSRCS += s32k3xx_userspace.c CHIP_CSRCS += s32k3xx_userspace.c
endif endif
@@ -118,6 +118,12 @@
#define S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS1_OFFSET (0x04b8) /* Block 3 Lock Master Super Sector 1 (PFCBLK3_LOCKMASTER_SS1) */ #define S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS1_OFFSET (0x04b8) /* Block 3 Lock Master Super Sector 1 (PFCBLK3_LOCKMASTER_SS1) */
#define S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS2_OFFSET (0x04bc) /* Block 3 Lock Master Super Sector 2 (PFCBLK3_LOCKMASTER_SS2) */ #define S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS2_OFFSET (0x04bc) /* Block 3 Lock Master Super Sector 2 (PFCBLK3_LOCKMASTER_SS2) */
/* Flash Management Unit Register Offsets ***********************************/
#define S32K3XX_FMU_MCR_OFFSET (0x0000) /* Module Configuration (MCR) */
#define S32K3XX_FMU_MCRS_OFFSET (0x0004) /* Module Configuration Status (MCRS) */
#define S32K3XX_FMU_PD_OFFSET (0x0100) /* Program data (PD) */
/* PFLASH Register Addresses ************************************************/ /* PFLASH Register Addresses ************************************************/
#define S32K3XX_PFLASH_PFCR0 (S32K3XX_PFLASH_BASE + S32K3XX_PFLASH_PFCR0_OFFSET) #define S32K3XX_PFLASH_PFCR0 (S32K3XX_PFLASH_BASE + S32K3XX_PFLASH_PFCR0_OFFSET)
@@ -203,6 +209,12 @@
#define S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS1 (S32K3XX_PFLASH_BASE + S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS1_OFFSET) #define S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS1 (S32K3XX_PFLASH_BASE + S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS1_OFFSET)
#define S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS2 (S32K3XX_PFLASH_BASE + S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS2_OFFSET) #define S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS2 (S32K3XX_PFLASH_BASE + S32K3XX_PFLASH_PFCBLK3_LOCKMASTER_SS2_OFFSET)
/* Flash Management Unit Register Addresses *********************************/
#define S32K3XX_FMU_MCR (S32K3XX_FMU_BASE + S32K3XX_FMU_MCR_OFFSET)
#define S32K3XX_FMU_MCRS (S32K3XX_FMU_BASE + S32K3XX_FMU_MCRS_OFFSET)
#define S32K3XX_FMU_PD(n) (S32K3XX_FMU_BASE + S32K3XX_FMU_PD_OFFSET + (n * 4))
/* PFLASH Register Bitfield Definitions *************************************/ /* PFLASH Register Bitfield Definitions *************************************/
/* Platform Flash Memory Configuration Register 0 (PFCR0) */ /* Platform Flash Memory Configuration Register 0 (PFCR0) */
@@ -347,4 +359,33 @@
#define PFLASH_PFCBLK_LOCKMASTER_SS_SHIFT (0) /* Bits 0-31: Block n Lock Master Super Sector m (LOCKMASTER_SS) */ #define PFLASH_PFCBLK_LOCKMASTER_SS_SHIFT (0) /* Bits 0-31: Block n Lock Master Super Sector m (LOCKMASTER_SS) */
#define PFLASH_PFCBLK_LOCKMASTER_SS_MASK (0xffffffff << PFLASH_PFCBLK_LOCKMASTER_SS_SHIFT) #define PFLASH_PFCBLK_LOCKMASTER_SS_MASK (0xffffffff << PFLASH_PFCBLK_LOCKMASTER_SS_SHIFT)
/* Flash Management Unit Bitfield Definitions *******************************/
/* Module Configuration (MCR) */
#define FMU_MCR_EHV_SHIFT (0) /* Bit 0: Enable High Voltage (EHV) */
#define FMU_MCR_EHV_MASK (0x01 << FMU_MCR_EHV_SHIFT)
#define FMU_MCR_ERS_SHIFT (4) /* Bit 4: Erase (ERS) */
#define FMU_MCR_ERS_MASK (0x01 << FMU_MCR_ERS_SHIFT)
#define FMU_MCR_ESS_SHIFT (5) /* Bit 5: Erase Size Select (ESS) */
#define FMU_MCR_ESS_MASK (0x01 << FMU_MCR_ESS_SHIFT)
#define FMU_MCR_PGM_SHIFT (8) /* Bit 8: Program (PGM) */
#define FMU_MCR_PGM_MASK (0x01 << FMU_MCR_PGM_SHIFT)
#define FMU_MCR_WDIE_SHIFT (12) /* Bit 12: Watch Dog Interrupt Enable (WDIE) */
#define FMU_MCR_WDIE_MASK (0x01 << FMU_MCR_WDIE_SHIFT)
#define FMU_MCR_PECIE_SHIFT (15) /* Bit 15: Program/Erase Complete Interrupt Enable (PECIE) */
#define FMU_MCR_PECIE_MASK (0x01 << FMU_MCR_PECIE_SHIFT)
#define FMU_MCR_PEID_SHIFT (16) /* Bit 16-23: Program and Erase Master/Domain ID (PEID) */
#define FMU_MCR_PEID_MASK (0xFF << FMU_MCR_PEID_SHIFT)
#define FMU_MCR_PEID(n) ((n & FMU_MCR_PEID_MASK) >> FMU_MCR_PEID_SHIFT)
#define FMU_MCRS_PEG_SHIFT (14) /* Bit 14: Program/Erase Good (PEG) */
#define FMU_MCRS_PEG_MASK (0x01 << FMU_MCRS_PEG_SHIFT)
#define FMU_MCRS_DONE_SHIFT (15) /* Bit 15: State machine status (DONE) */
#define FMU_MCRS_DONE_MASK (0x01 << FMU_MCRS_DONE_SHIFT)
#define FMU_MCRS_PES_SHIFT (16) /* Bit 16: Program and erase Protection error (PEP) */
#define FMU_MCRS_PES_MASK (0x01 << FMU_MCRS_PES_SHIFT)
#define FMU_MCRS_PEP_SHIFT (17) /* Bit 17: Program and erase sequence error (PES) */
#define FMU_MCRS_PEP_MASK (0x01 << FMU_MCRS_PEP_SHIFT)
#endif /* __ARCH_ARM_SRC_S32K3XX_HARDWARE_S32K3XX_PFLASH_H */ #endif /* __ARCH_ARM_SRC_S32K3XX_HARDWARE_S32K3XX_PFLASH_H */
+423
View File
@@ -0,0 +1,423 @@
/****************************************************************************
* arch/arm/src/s32k3xx/s32k3xx_progmem.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/* Copyright 2022 NXP */
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <errno.h>
#include "hardware/s32k3xx_pflash.h"
#include "hardware/s32k3xx_xrdc.h"
#include "s32k3xx_config.h"
#include "s32k3xx_progmem.h"
#include "arm_internal.h"
#include <arch/board/board.h> /* Include last: has dependencies */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
/****************************************************************************
* Private Functions
****************************************************************************/
uint32_t get_sector(uint32_t address)
{
if ((address >= S32K3XX_PROGMEM_START_ADDR) &&
(address <= S32K3XX_PROGMEM_END_ADDR))
{
/* The address is from the data sectors */
return ((address - (uint32_t)S32K3XX_PROGMEM_START_ADDR) /
S32K3XX_PROGMEM_SECTOR_SIZE);
}
}
void data_sector_lock(uint32_t sector, uint32_t lock)
{
uint32_t regval;
regval = getreg32(S32K3XX_PFLASH_PFCBLK4_SPELOCK);
if (lock)
{
regval |= (1 << sector);
}
else
{
regval &= ~(1 << sector);
}
putreg32(regval, S32K3XX_PFLASH_PFCBLK4_SPELOCK);
}
uint32_t execute_flash_sequence(uint32_t mask)
{
uint32_t regval;
uint32_t status;
/* Set Mask bit */
regval = getreg32(S32K3XX_FMU_MCR);
regval |= mask;
putreg32(regval, S32K3XX_FMU_MCR);
/* Set EHV bit to start program operation */
regval |= FMU_MCR_EHV_MASK;
putreg32(regval, S32K3XX_FMU_MCR);
/* Wait for MCRS Done */
do
{
regval = getreg32(S32K3XX_FMU_MCRS);
}
while ((regval & FMU_MCRS_DONE_MASK) != FMU_MCRS_DONE_MASK);
regval = getreg32(S32K3XX_FMU_MCR);
regval &= ~FMU_MCR_EHV_MASK;
putreg32(regval, S32K3XX_FMU_MCR);
status = getreg32(S32K3XX_FMU_MCRS);
regval &= ~mask;
putreg32(regval, S32K3XX_FMU_MCR);
return status;
}
void execute_init_sequence(uint32_t addr)
{
uint8_t domain_id = getreg8(S32K3XX_XRDC_HWCFG1);
do
{
putreg32(addr, S32K3XX_PFLASH_PFCPGM_PEADR_L);
}
while (FMU_MCR_PEID(getreg32(S32K3XX_FMU_MCR)) != domain_id);
putreg32((FMU_MCRS_PES_SHIFT | FMU_MCRS_PEP_SHIFT), S32K3XX_FMU_MCRS);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_progmem_neraseblocks
*
* Description:
* Return number of erase blocks
*
****************************************************************************/
size_t up_progmem_neraseblocks(void)
{
return S32K3XX_PROGMEM_SECTOR_COUNT;
}
/****************************************************************************
* Name: up_progmem_isuniform
*
* Description:
* Is program memory uniform or page size differs?
*
****************************************************************************/
bool up_progmem_isuniform(void)
{
return true;
}
/****************************************************************************
* Name: up_progmem_pagesize
*
* Description:
* Return read/write page size
*
****************************************************************************/
size_t up_progmem_pagesize(size_t page)
{
return (size_t)S32K3XX_PROGMEM_PAGE_SIZE;
}
/****************************************************************************
* Name: up_progmem_erasesize
*
* Description:
* Return erase block size
*
****************************************************************************/
size_t up_progmem_erasesize(size_t block)
{
return (size_t)S32K3XX_PROGMEM_BLOCK_SECTOR_SIZE;
}
/****************************************************************************
* Name: up_progmem_getpage
*
* Description:
* Address to read/write page conversion
*
* Input Parameters:
* addr - Address with or without flash offset (absolute or aligned to
* page0)
*
* Returned Value:
* Page or negative value on error. The following errors are reported
* (errno is not set!):
*
* -EFAULT: On invalid address
*
****************************************************************************/
ssize_t up_progmem_getpage(size_t addr)
{
if (addr >= S32K3XX_PROGMEM_START_ADDR)
{
addr -= S32K3XX_PROGMEM_START_ADDR;
}
return (size_t)(addr / S32K3XX_PROGMEM_PAGE_SIZE);
}
/****************************************************************************
* Name: up_progmem_getaddress
*
* Description:
* Read/write page to address conversion
*
* Input Parameters:
* page - page index
*
* Returned Value:
* Base address of given page, SIZE_MAX if page index is not valid.
*
****************************************************************************/
size_t up_progmem_getaddress(size_t page)
{
return (size_t)(S32K3XX_PROGMEM_START_ADDR
+ (page * S32K3XX_PROGMEM_PAGE_SIZE));
}
/****************************************************************************
* Name: up_progmem_eraseblock
*
* Description:
* Erase selected block.
*
* Input Parameters:
* block - The erase block index to be erased.
*
* Returned Value:
* block size or negative value on error. The following errors are
* reported (errno is not set!):
*
* -EFAULT: On invalid page
* -EIO: On unsuccessful erase
* -EROFS: On access to write protected area
* -EACCES: Insufficient permissions (read/write protected)
* -EPERM: If operation is not permitted due to some other constraints
* (i.e. some internal block is not running etc.)
*
****************************************************************************/
ssize_t up_progmem_eraseblock(size_t block)
{
uint32_t dest;
dest = (block * S32K3XX_PROGMEM_BLOCK_SECTOR_SIZE +
S32K3XX_PROGMEM_START_ADDR);
data_sector_lock(get_sector(dest), 0);
execute_init_sequence(dest);
putreg32(0x0, S32K3XX_FMU_PD(0));
execute_flash_sequence(FMU_MCR_ERS_MASK);
putreg32(0xffffffff, S32K3XX_FMU_PD(0));
return (ssize_t)S32K3XX_PROGMEM_BLOCK_SECTOR_SIZE;
}
/****************************************************************************
* Name: up_progmem_ispageerased
*
* Description:
* Checks whether page is erased
*
* Input Parameters:
* page - The erase page index to be checked.
*
* Returned Value:
* Returns number of bytes NOT erased or negative value on error. If it
* returns zero then complete page is erased.
*
* The following errors are reported:
* -EFAULT: On invalid page
*
****************************************************************************/
ssize_t up_progmem_ispageerased(size_t page)
{
const uint8_t *p;
int i;
if (page >= S32K3XX_PROGMEM_PAGE_COUNT)
{
return -EFAULT;
}
p = (const uint8_t *)up_progmem_getaddress(page);
for (i = 0; i < S32K3XX_PROGMEM_PAGE_SIZE; i++)
{
if (p[i] != S32K3XX_PROGMEM_ERASEDVAL)
{
break;
}
}
return (ssize_t)(S32K3XX_PROGMEM_PAGE_SIZE - i);
}
/****************************************************************************
* Name: up_progmem_write
*
* Description:
* Program data at given address
*
* Note: this function is not limited to single page and nor it requires
* the address be aligned inside the page boundaries.
*
* Input Parameters:
* addr - Address with or without flash offset
* buf - Pointer to buffer
* count - Number of bytes to write
*
* Returned Value:
* Bytes written or negative value on error. The following errors are
* reported (errno is not set!)
*
* EINVAL: If count is not aligned with the flash boundaries (i.e.
* some MCU's require per half-word or even word access)
* EFAULT: On invalid address
* EIO: On unsuccessful write, do note when this occurs the complete
* flash sector is deemed to be unreadable and a read will most
* likely result in a hard fault.
* EROFS: On access to write protected area
* EACCES: Insufficient permissions (read/write protected)
* EPERM: If operation is not permitted due to some other constraints
* (i.e. some internal block is not running etc.)
*
****************************************************************************/
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
{
uint32_t i;
uint32_t dest;
uint32_t offset;
uint32_t *p_offset;
uint32_t *p_src;
size_t words_to_write;
if (count % S32K3XX_PROGMEM_DFLASH_WRITE_UNIT_SIZE != 0)
{
return -EINVAL;
}
offset = addr % S32K3XX_PROGMEM_WRITE_SIZE;
dest = addr - offset;
words_to_write = ((count + offset) / 4);
if (offset > 0)
{
p_offset = (uint32_t *)(dest);
}
p_src = (uint32_t *)(buf);
data_sector_lock(get_sector(dest), 0);
while (words_to_write > 0)
{
/* Destination address */
execute_init_sequence(dest);
for (i = 0; i < min(32, words_to_write); i++)
{
if (offset > 0)
{
putreg32(*p_offset++, S32K3XX_FMU_PD(i));
offset = offset - 4;
}
else
{
putreg32(*p_src++, S32K3XX_FMU_PD(i));
}
}
words_to_write = words_to_write - i;
execute_flash_sequence(FMU_MCR_PGM_MASK);
}
return count;
}
/****************************************************************************
* Name: up_progmem_erasestate
*
* Description:
* Return value of erase state.
*
****************************************************************************/
uint8_t up_progmem_erasestate(void)
{
return S32K3XX_PROGMEM_ERASEDVAL;
}
void s32k3xx_progmem_init(void)
{
/* Disable D-Flash ECC for back-to-back flash writes */
putreg32(PFLASH_PFCR4_DERR_SUP, S32K3XX_PFLASH_PFCR4);
}
+77
View File
@@ -0,0 +1,77 @@
/****************************************************************************
* arch/arm/src/s32k3xx/s32k3xx_progmem.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/* Copyright 2022 NXP */
#ifndef __ARCH_ARM_SRC_S32K3XX_S32K3XX_PROGMEM_H
#define __ARCH_ARM_SRC_S32K3XX_S32K3XX_PROGMEM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include "arm_internal.h"
#include "s32k3xx_config.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define DFLASH_SIZE 128
/* Base address of the flash segment used for progmem. */
#define S32K3XX_PROGMEM_START_ADDR 0x10000000
#define S32K3XX_PROGMEM_END_ADDR 0x1003FFFF
#define S32K3XX_PROGMEM_BLOCK_COUNT 1
#define S32K3XX_PROGMEM_BLOCK_SIZE DFLASH_SIZE * 1024
#define S32K3XX_PROGMEM_BLOCK_SECTOR_SIZE 8192
#define S32K3XX_PROGMEM_PAGE_SIZE 8
#define S32K3XX_PROGMEM_WRITE_SIZE 128
#define S32K3XX_PROGMEM_SECTOR_SIZE 8192
#define S32K3XX_PROGMEM_SECTOR_COUNT S32K3XX_PROGMEM_BLOCK_SIZE / S32K3XX_PROGMEM_BLOCK_SECTOR_SIZE
#define S32K3XX_PROGMEM_PAGE_COUNT (S32K3XX_PROGMEM_BLOCK_SIZE / S32K3XX_PROGMEM_PAGE_SIZE)
#define S32K3XX_PROGMEM_DFLASH_WRITE_UNIT_SIZE 4
#define S32K3XX_PROGMEM_ERASEDVAL (0xffu)
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
void s32k3xx_progmem_init(void);
#endif /* __ARCH_ARM_SRC_S32K3XX_S32K3XX_PROGMEM_H */
@@ -28,6 +28,7 @@ CONFIG_BOARD_LOOPSPERMSEC=14539
CONFIG_BUILTIN=y CONFIG_BUILTIN=y
CONFIG_CANUTILS_CANDUMP=y CONFIG_CANUTILS_CANDUMP=y
CONFIG_CANUTILS_CANSEND=y CONFIG_CANUTILS_CANSEND=y
CONFIG_ETH0_PHY_TJA1103=y
CONFIG_EXAMPLES_BUTTONS=y CONFIG_EXAMPLES_BUTTONS=y
CONFIG_EXAMPLES_HELLO=y CONFIG_EXAMPLES_HELLO=y
CONFIG_EXAMPLES_TELNETD=y CONFIG_EXAMPLES_TELNETD=y
@@ -55,6 +56,7 @@ CONFIG_LPUART2_SERIAL_CONSOLE=y
CONFIG_MM_REGIONS=2 CONFIG_MM_REGIONS=2
CONFIG_MTD=y CONFIG_MTD=y
CONFIG_MTD_MX25RXX=y CONFIG_MTD_MX25RXX=y
CONFIG_MTD_PROGMEM=y
CONFIG_MX25RXX_LXX=y CONFIG_MX25RXX_LXX=y
CONFIG_NET=y CONFIG_NET=y
CONFIG_NETDEV_IFINDEX=y CONFIG_NETDEV_IFINDEX=y
@@ -100,6 +102,7 @@ CONFIG_S32K3XX_LPUART14=y
CONFIG_S32K3XX_LPUART1=y CONFIG_S32K3XX_LPUART1=y
CONFIG_S32K3XX_LPUART2=y CONFIG_S32K3XX_LPUART2=y
CONFIG_S32K3XX_LPUART9=y CONFIG_S32K3XX_LPUART9=y
CONFIG_S32K3XX_PROGMEM=y
CONFIG_S32K3XX_QSPI=y CONFIG_S32K3XX_QSPI=y
CONFIG_S32K3XX_TJA1153=y CONFIG_S32K3XX_TJA1153=y
CONFIG_SCHED_LPWORK=y CONFIG_SCHED_LPWORK=y
@@ -163,6 +163,46 @@ int s32k3xx_bringup(void)
} }
#endif #endif
#ifdef CONFIG_S32K3XX_PROGMEM
struct mtd_dev_s *mtd;
mtd = progmem_initialize();
if (mtd == NULL)
{
syslog(LOG_ERR, "ERROR: progmem_initialize() failed\n");
}
ret = register_mtddriver("/dev/progmem0", mtd, 0755, NULL);
if (ret != OK)
{
_err("register_mtddriver() failed: %d\n", ret);
}
# ifdef CONFIG_FS_LITTLEFS
else
{
_info("register_mtddriver() succesful\n");
ret = nx_mount("/dev/progmem0", "/mnt/progmem", "littlefs", 0, NULL);
if (ret < 0)
{
ret = nx_mount("/dev/progmem0", "/mnt/progmem", "littlefs", 0,
"forceformat");
if (ret < 0)
{
_err("nx_mount() failed: %d\n", ret);
}
else
{
_info("nx_mount() succesful\n");
}
}
}
# endif
#endif
#ifdef HAVE_MX25L #ifdef HAVE_MX25L
/* Create an instance of the S32K3XX QSPI device driver */ /* Create an instance of the S32K3XX QSPI device driver */