mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
S32K3XX Progmem dataflash with littlefs support
This commit is contained in:
committed by
Xiang Xiao
parent
c8cf27e848
commit
aac9eb57e8
@@ -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"
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user