Added SMART flash filesystem to RP2040
This commit is contained in:
parent
fb852440af
commit
9ad75fd95d
@ -689,3 +689,29 @@ config RP2040_BOARD_HAS_WS2812
|
|||||||
---help---
|
---help---
|
||||||
See the Board Selection menu to configure the pins used
|
See the Board Selection menu to configure the pins used
|
||||||
by ws2812.
|
by ws2812.
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Flash File System Configuration
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
config RP2040_FLASH_FILE_SYSTEM
|
||||||
|
bool "Configure a read/write filesystem on unused flash memory"
|
||||||
|
default n
|
||||||
|
select MTD
|
||||||
|
select MTD_SMART
|
||||||
|
select FS_SMARTFS
|
||||||
|
---help---
|
||||||
|
See the Board Selection menu to configure the size of the
|
||||||
|
flash chip for a particular board.
|
||||||
|
|
||||||
|
if RP2040_FLASH_FILE_SYSTEM
|
||||||
|
|
||||||
|
config RP2040_FLASH_MOUNT_POINT
|
||||||
|
string "mount point for flash file system"
|
||||||
|
default "/flash"
|
||||||
|
---help---
|
||||||
|
This is the mount point where the flash file system will
|
||||||
|
be mounted. Leave this string empty to prevent automatic
|
||||||
|
mounting of the filesystem.
|
||||||
|
|
||||||
|
endif # RP2040_FLASH_FILE_SYSTEM
|
||||||
|
@ -78,13 +78,17 @@ ifeq ($(CONFIG_ADC),y)
|
|||||||
CHIP_CSRCS += rp2040_adc.c
|
CHIP_CSRCS += rp2040_adc.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_RP2040_FLASH_BOOT),y)
|
|
||||||
ifneq ($(PICO_SDK_PATH),)
|
|
||||||
include chip/boot2/Make.defs
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_IEEE80211_INFINEON_CYW43439),y)
|
ifeq ($(CONFIG_IEEE80211_INFINEON_CYW43439),y)
|
||||||
CHIP_CSRCS += rp2040_cyw43439.c
|
CHIP_CSRCS += rp2040_cyw43439.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_RP2040_FLASH_FILE_SYSTEM),y)
|
||||||
|
CHIP_CSRCS += rp2040_flash_mtd.c
|
||||||
|
CHIP_ASRCS += rp2040_flash_initialize.S
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_RP2040_FLASH_BOOT),y)
|
||||||
|
ifneq ($(PICO_SDK_PATH),)
|
||||||
|
include chip/boot2/Make.defs
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
195
arch/arm/src/rp2040/rp2040_flash_initialize.S
Normal file
195
arch/arm/src/rp2040/rp2040_flash_initialize.S
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/arm/src/rp2040/rp2040_flash_initialize.S
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Description:
|
||||||
|
* The low-level format of the smart filesystem for the rp2040 consists of
|
||||||
|
* a series of 4096-byte blocks each of which contain four 1024 byte
|
||||||
|
* logical sectors. Due to the way flash works the filesystem can only
|
||||||
|
* erase (set to all 1 bits) a whole block. It can however, write smaller
|
||||||
|
* amounts. On the rp2040 the smallest write is 256 bytes. The write can
|
||||||
|
* only flip 1 bits to 0 -- it cannot change a 0 bit to 1.
|
||||||
|
*
|
||||||
|
* Each logical sector starts with a five byte sector header. Most sectors
|
||||||
|
* follow this with a five byte filesystem header. Sector zero does not
|
||||||
|
* follow this rule; it contains the volume label.
|
||||||
|
*
|
||||||
|
* The volume will have root directory located in logical sector three. It
|
||||||
|
* may have additional root directories (indicated by a count in the volume
|
||||||
|
* label). This will be in sequential sectors starting with sector four.
|
||||||
|
*
|
||||||
|
* Actual files and other subdirectories start in logical sector twelve.
|
||||||
|
*
|
||||||
|
* == SECTOR HEADER ==
|
||||||
|
*
|
||||||
|
* Logical sector number: 2 bytes
|
||||||
|
* Sequence number: 2 bytes
|
||||||
|
* Flags: 1 byte
|
||||||
|
*
|
||||||
|
* Flag bits are: C R X S S S V V
|
||||||
|
* C - Set to zero if block committed 0
|
||||||
|
* R - Set to zero if block erased 1
|
||||||
|
* X - CRC status 1
|
||||||
|
* S - Size Code 010
|
||||||
|
* V - Version code 01
|
||||||
|
*
|
||||||
|
* The logical sector number does not have to match the actual position
|
||||||
|
* of a sector. The volume in scanned when mounted and the mapping of
|
||||||
|
* sector number to position in volume is maintained in ram. If a sector
|
||||||
|
* is written to it will be re-written to a new location.
|
||||||
|
*
|
||||||
|
* == VOLUME LABEL ==
|
||||||
|
*
|
||||||
|
* Sector zero is the volume label. It currently consists of the
|
||||||
|
* following fields.
|
||||||
|
*
|
||||||
|
* Smart Volume ID: 4 bytes "SMRT"
|
||||||
|
* Smart version: 1 byte 0x01
|
||||||
|
* Sector size flag: 1 byte 0x10
|
||||||
|
* Extra Root Directories: 1 byte 0x00
|
||||||
|
*
|
||||||
|
* == FILE SYSTEM HEADER ==
|
||||||
|
*
|
||||||
|
* File and directory sectors have a filesystem header directly following
|
||||||
|
* the sector header. This filesystem header consists of:
|
||||||
|
*
|
||||||
|
* Entry type: 1 byte 0x01 = Directory, 0x02 = File.
|
||||||
|
* Next logical sector: 2 bytes 0xff no more sectors
|
||||||
|
* Number of bytes used 2 bytes 0xff empty sector
|
||||||
|
*
|
||||||
|
* == DIRECTORY ENTRIES ==
|
||||||
|
*
|
||||||
|
* Directory Flags: 2 bytes
|
||||||
|
*
|
||||||
|
* == FILE ENTRIES ==
|
||||||
|
*
|
||||||
|
* File data starts following the filesystem header and extends
|
||||||
|
* for a number of bytes as specified in the filesystem header.
|
||||||
|
*
|
||||||
|
* Files with a length of greater that 1019 bytes will span multiple
|
||||||
|
* sectors, linked with the next logical sector flag.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
dir= 1
|
||||||
|
file= 2
|
||||||
|
name_length= 16
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sector
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This macro defines a sector header. It actually sets both the actual
|
||||||
|
* sector header and the filesystem header values.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* num - The logical sector number. Each sector must be unique.
|
||||||
|
* type - The sector type. Should be 'dir' or 'file'
|
||||||
|
* used - The length of the data in this sector.
|
||||||
|
* next - The logical sector number of the next sector in a chain.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.macro sector num, type, used=0xffff, next=0xffff
|
||||||
|
.balign 1024, 0xff
|
||||||
|
.hword \num, 0
|
||||||
|
.byte 0b01101001, \type
|
||||||
|
.hword \next, \used
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: dir_entry
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This macro defines a directory entry.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* perm - Permission bits for this directory entry
|
||||||
|
* addr - Logical sector number of named entry
|
||||||
|
* time - entry creation time stamp
|
||||||
|
* name - name of this entry
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.macro dir_entry perm, addr, time, name
|
||||||
|
.hword \perm | 0x7e00, \addr
|
||||||
|
.word \time
|
||||||
|
0:
|
||||||
|
.ascii "\name"
|
||||||
|
.= 0b + name_length
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_entry
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This macro defines a directory entry.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* perm - Permission bits for this directory entry
|
||||||
|
* addr - Logical sector number of named entry
|
||||||
|
* time - entry creation time stamp
|
||||||
|
* name - name of this entry
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.macro file_entry perm, addr, time, name
|
||||||
|
.hword \perm | 0x5e00, \addr
|
||||||
|
.word \time
|
||||||
|
0:
|
||||||
|
.ascii "\name"
|
||||||
|
.= 0b + name_length
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Global name of the initial filesystem data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.cpu cortex-m0plus
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
.section .flash.init, "ax"
|
||||||
|
.balign 4096
|
||||||
|
.global rp2040_smart_flash_start
|
||||||
|
rp2040_smart_flash_start:
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Volume Label
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.ascii "2040" /* magic tag for flash initialization */
|
||||||
|
.byte 0b01101001
|
||||||
|
.ascii "SMRT"
|
||||||
|
.byte 0x01, 0x10, 0
|
||||||
|
|
||||||
|
.balign 4096, 0xff
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Root directory and initial files in the filesystem
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
sector 3, dir
|
||||||
|
file_entry 0777, 4, 0, "test"
|
||||||
|
|
||||||
|
sector 4, file, used=14
|
||||||
|
.ascii "Hello, world!\n"
|
||||||
|
|
||||||
|
|
||||||
|
.balign 4096, 0xff
|
||||||
|
.global rp2040_smart_flash_end
|
||||||
|
rp2040_smart_flash_end:
|
||||||
|
|
||||||
|
.end
|
569
arch/arm/src/rp2040/rp2040_flash_mtd.c
Normal file
569
arch/arm/src/rp2040/rp2040_flash_mtd.c
Normal file
@ -0,0 +1,569 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/arm/src/rp2040/rp2040_flash_mtd.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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* This code implements a Sector Mapped Allocation for Really Tiny (SMART)
|
||||||
|
* filesystem in the RP2040 flash memory chip. It uses the space not
|
||||||
|
* otherwise used by the NuttX binary and supports both read and write
|
||||||
|
* access.
|
||||||
|
*
|
||||||
|
* There initial contents of this filesystem may be configured when a NuttX
|
||||||
|
* binary is built (using tools/rp2040/make_flash_fs.c), but any changes
|
||||||
|
* subsequently written to the filesystem will persist over re-boots of the
|
||||||
|
* RP2040.
|
||||||
|
*
|
||||||
|
* Note: Although read access to any data stored in this filesystem is very
|
||||||
|
* rapid; because of how the RP2040's flash access routines work with
|
||||||
|
* the normal execute-in-place (XIP) access to that chip, no code can
|
||||||
|
* access flash in the normal manner when this filesystem is erasing
|
||||||
|
* or writing blocks. This means that interrupts must be disabled
|
||||||
|
* during any such access. The main issue with this is that any
|
||||||
|
* application which requires precise timing or rapid response may
|
||||||
|
* be negatively impacted by such operations.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/arch.h>
|
||||||
|
#include <nuttx/irq.h>
|
||||||
|
#include <nuttx/semaphore.h>
|
||||||
|
|
||||||
|
#include "rp2040_flash_mtd.h"
|
||||||
|
#include "rp2040_rom.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define XIP_BASE 0x10000000
|
||||||
|
#define XIP_NOCACHE_NOALLOC_BASE 0x13000000
|
||||||
|
#define FLASH_BLOCK_ERASE_CMD 0x20
|
||||||
|
#define BOOT_2_SIZE 256
|
||||||
|
|
||||||
|
#define FLASH_START_OFFSET (rp2040_smart_flash_start - (uint8_t *) XIP_BASE)
|
||||||
|
#define FLASH_END_OFFSET (rp2040_smart_flash_end - (uint8_t *) XIP_BASE)
|
||||||
|
#define FLASH_START_READ (rp2040_smart_flash_start + 0x03000000)
|
||||||
|
|
||||||
|
/* Note: There is some ambiguity in terminology when it comes to flash.
|
||||||
|
* Some call the chunk that can be erased a sector where others
|
||||||
|
* call that a block.
|
||||||
|
*
|
||||||
|
* Some call the chunk that can be written a sector where others
|
||||||
|
* call that a page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Blocks are the smallest unit that can be erased */
|
||||||
|
|
||||||
|
#define FLASH_BLOCK_SIZE (4 * 1024)
|
||||||
|
#define FLASH_BLOCK_COUNT (CONFIG_RP2040_FLASH_LENGTH - FLASH_START_OFFSET)\
|
||||||
|
/ FLASH_BLOCK_SIZE
|
||||||
|
|
||||||
|
/* Sectors are the smallest unit that can be written */
|
||||||
|
|
||||||
|
#define FLASH_SECTOR_SIZE 256
|
||||||
|
#define FLASH_SECTOR_COUNT (CONFIG_RP2040_FLASH_LENGTH - FLASH_START_OFFSET)\
|
||||||
|
/ FLASH_SECTOR_SIZE
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
# define OTHER_CPU (up_cpu_index() == 0 ? 1 : 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct rp2040_flash_dev_s
|
||||||
|
{
|
||||||
|
struct mtd_dev_s mtd_dev; /* Embedded mdt_dev structure */
|
||||||
|
sem_t sem; /* file access serialization */
|
||||||
|
uint32_t boot_2[BOOT_2_SIZE / 4]; /* RAM copy of boot_2 */
|
||||||
|
} rp2040_flash_dev_t;
|
||||||
|
|
||||||
|
typedef void (*connect_internal_flash_f)(void);
|
||||||
|
typedef void (*flash_exit_xip_f)(void);
|
||||||
|
typedef void (*flash_range_erase_f)(uint32_t, size_t, uint32_t, uint8_t);
|
||||||
|
typedef void (*flash_range_program_f)(uint32_t, const uint8_t *, size_t);
|
||||||
|
typedef void (*flash_flush_cache_f)(void);
|
||||||
|
typedef void (*flash_enable_xip_f)(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int rp2040_flash_erase (struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks);
|
||||||
|
|
||||||
|
static ssize_t rp2040_flash_block_read (struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
|
uint8_t *buffer);
|
||||||
|
|
||||||
|
static ssize_t rp2040_flash_block_write(struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
|
const uint8_t *buffer);
|
||||||
|
|
||||||
|
static ssize_t rp2040_flash_byte_read (struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
|
uint8_t *buffer);
|
||||||
|
|
||||||
|
static int rp2040_flash_ioctl (struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
extern const uint8_t rp2040_smart_flash_start[256];
|
||||||
|
extern const uint8_t rp2040_smart_flash_end[0];
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static struct rp2040_flash_dev_s my_dev =
|
||||||
|
{
|
||||||
|
.mtd_dev =
|
||||||
|
{
|
||||||
|
rp2040_flash_erase,
|
||||||
|
rp2040_flash_block_read,
|
||||||
|
rp2040_flash_block_write,
|
||||||
|
rp2040_flash_byte_read,
|
||||||
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
|
NULL,
|
||||||
|
#endif
|
||||||
|
rp2040_flash_ioctl,
|
||||||
|
"rp_flash"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool initialized = false;
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
connect_internal_flash_f connect_internal_flash;
|
||||||
|
flash_exit_xip_f flash_exit_xip;
|
||||||
|
flash_range_erase_f flash_range_erase;
|
||||||
|
flash_range_program_f flash_range_program;
|
||||||
|
flash_flush_cache_f flash_flush_cache;
|
||||||
|
flash_enable_xip_f flash_enable_xip;
|
||||||
|
} rom_functions;
|
||||||
|
|
||||||
|
void *boot_2_copy = NULL;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: do_erase
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void RAM_CODE(do_erase)(uint32_t addr, size_t count)
|
||||||
|
{
|
||||||
|
/* Note: While we would prefer not to flush the cache, the
|
||||||
|
* flash_flush_cache call is needed to remove CSn IO force.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__asm__ volatile ("" : : : "memory");
|
||||||
|
|
||||||
|
rom_functions.connect_internal_flash();
|
||||||
|
|
||||||
|
rom_functions.flash_exit_xip();
|
||||||
|
|
||||||
|
/* The range erase will try to erase 65536-byte blocks with the 0xd8 flash
|
||||||
|
* command. If it cannot, because either the addr or count are not
|
||||||
|
* multiple of 65536, it will fall back to erasing 4096-byte blocks as
|
||||||
|
* needed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
rom_functions.flash_range_erase(addr, count, 65536, 0xd8);
|
||||||
|
|
||||||
|
rom_functions.flash_flush_cache();
|
||||||
|
|
||||||
|
rom_functions.flash_enable_xip();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: do_write
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void RAM_CODE(do_write)(uint32_t addr, const uint8_t *data, size_t count)
|
||||||
|
{
|
||||||
|
/* Note: While we would prefer not to flush the cache, the
|
||||||
|
* flash_flush_cache call is needed to remove CSn IO force.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__asm__ volatile ("" : : : "memory");
|
||||||
|
|
||||||
|
rom_functions.connect_internal_flash();
|
||||||
|
|
||||||
|
rom_functions.flash_exit_xip();
|
||||||
|
|
||||||
|
rom_functions.flash_range_program(addr, (uint8_t *)data, count);
|
||||||
|
|
||||||
|
rom_functions.flash_flush_cache();
|
||||||
|
|
||||||
|
rom_functions.flash_enable_xip();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rp2040_flash_erase
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int rp2040_flash_erase(struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks)
|
||||||
|
{
|
||||||
|
rp2040_flash_dev_t *rp_dev = (rp2040_flash_dev_t *) dev;
|
||||||
|
irqstate_t flags;
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
finfo("FLASH: erase block: %8u (0x%08x) count:%5u (0x%08X)\n",
|
||||||
|
(unsigned)(startblock),
|
||||||
|
(unsigned)(FLASH_BLOCK_SIZE * startblock + FLASH_START_OFFSET),
|
||||||
|
nblocks,
|
||||||
|
FLASH_BLOCK_SIZE * nblocks);
|
||||||
|
|
||||||
|
usleep(500000);
|
||||||
|
|
||||||
|
ret = nxsem_wait(&(rp_dev->sem));
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
up_cpu_pause(OTHER_CPU);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do_erase(FLASH_BLOCK_SIZE * startblock + FLASH_START_OFFSET,
|
||||||
|
FLASH_BLOCK_SIZE * nblocks);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
up_cpu_resume(OTHER_CPU);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
|
||||||
|
ret = nblocks;
|
||||||
|
|
||||||
|
nxsem_post(&(rp_dev->sem));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rp2040_flash_block_read
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static ssize_t rp2040_flash_block_read(struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
|
uint8_t *buffer)
|
||||||
|
{
|
||||||
|
rp2040_flash_dev_t *rp_dev = (rp2040_flash_dev_t *) dev;
|
||||||
|
int start;
|
||||||
|
int length;
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
ret = nxsem_wait(&(rp_dev->sem));
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
finfo("FLASH: read sector: %8u (0x%08x) count:%5u\n",
|
||||||
|
(unsigned)(startblock),
|
||||||
|
(unsigned)(FLASH_SECTOR_SIZE * startblock + FLASH_START_OFFSET),
|
||||||
|
nblocks);
|
||||||
|
|
||||||
|
start = FLASH_SECTOR_SIZE * startblock;
|
||||||
|
length = FLASH_SECTOR_SIZE * nblocks;
|
||||||
|
|
||||||
|
/* This reads starting at XIP_NOCACHE_NOALLOC_BASE to bypass the
|
||||||
|
* XIP cache. This is done because flash programming does not update
|
||||||
|
* the cache and we don't want to read stale data. Since we expect
|
||||||
|
* access to the flash filesystem to be rather infrequent this isn't
|
||||||
|
* really much of a burden.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memcpy(buffer, FLASH_START_READ + start, length);
|
||||||
|
|
||||||
|
/* Update the file position */
|
||||||
|
|
||||||
|
nxsem_post(&(rp_dev->sem));
|
||||||
|
|
||||||
|
return nblocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rp2040_flash_write
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static ssize_t rp2040_flash_block_write(struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
|
const uint8_t *buffer)
|
||||||
|
{
|
||||||
|
rp2040_flash_dev_t *rp_dev = (rp2040_flash_dev_t *) dev;
|
||||||
|
irqstate_t flags;
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
ret = nxsem_wait(&(rp_dev->sem));
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
up_cpu_pause(OTHER_CPU);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do_write(FLASH_SECTOR_SIZE * startblock + FLASH_START_OFFSET,
|
||||||
|
buffer,
|
||||||
|
FLASH_SECTOR_SIZE * nblocks);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
up_cpu_resume(OTHER_CPU);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
|
||||||
|
finfo("FLASH: write sector: %8u (0x%08x) count:%5u\n",
|
||||||
|
(unsigned)(startblock),
|
||||||
|
(unsigned)(FLASH_SECTOR_SIZE * startblock + FLASH_START_OFFSET),
|
||||||
|
nblocks);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS_INFO
|
||||||
|
for (int i = 0; i < FLASH_SECTOR_SIZE * nblocks; i += 16)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 16; ++j)
|
||||||
|
{
|
||||||
|
printf("%02x, ", buffer[i + j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = nblocks;
|
||||||
|
|
||||||
|
nxsem_post(&(rp_dev->sem));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rp2040_flash_byte_read
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static ssize_t rp2040_flash_byte_read (struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
|
uint8_t *buffer)
|
||||||
|
{
|
||||||
|
rp2040_flash_dev_t *rp_dev = (rp2040_flash_dev_t *) dev;
|
||||||
|
int length;
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
ret = nxsem_wait(&(rp_dev->sem));
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = nbytes;
|
||||||
|
|
||||||
|
finfo("FLASH: read bytes: %8u (0x%08x) count:%5u\n",
|
||||||
|
(unsigned)(offset),
|
||||||
|
(unsigned)(offset + FLASH_START_OFFSET),
|
||||||
|
nbytes);
|
||||||
|
|
||||||
|
/* This reads starting at XIP_NOCACHE_NOALLOC_BASE to bypass the
|
||||||
|
* XIP cache. This is done because flash programming does not update
|
||||||
|
* the cache and we don't want to read stale data. Since we expect
|
||||||
|
* access to the flash filesystem to be rather infrequent this isn't
|
||||||
|
* really much of a burden.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memcpy(buffer, FLASH_START_READ + offset, length);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS_INFO
|
||||||
|
for (int j = 0; j < 16 && j < nbytes; ++j)
|
||||||
|
{
|
||||||
|
printf("%02x, ", buffer[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Update the file position */
|
||||||
|
|
||||||
|
nxsem_post(&(rp_dev->sem));
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rp2040_flash_ioctl
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int rp2040_flash_ioctl(struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
rp2040_flash_dev_t *rp_dev = (rp2040_flash_dev_t *) dev;
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
UNUSED(rp_dev);
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case MTDIOC_GEOMETRY:
|
||||||
|
{
|
||||||
|
struct mtd_geometry_s *geo = (struct mtd_geometry_s *) arg;
|
||||||
|
|
||||||
|
if (geo != NULL)
|
||||||
|
{
|
||||||
|
geo->blocksize = FLASH_SECTOR_SIZE;
|
||||||
|
geo->erasesize = FLASH_BLOCK_SIZE;
|
||||||
|
geo->neraseblocks = FLASH_BLOCK_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MTDIOC_BULKERASE:
|
||||||
|
{
|
||||||
|
/* Erase all the filesystem blocks for the device. Remember that
|
||||||
|
* we share this device with XIP memory so we cannot erase entire
|
||||||
|
* device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = rp2040_flash_erase(dev, 0, FLASH_BLOCK_COUNT);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rp2040_flash_initialize
|
||||||
|
*
|
||||||
|
* Description: Bind a block mode driver that uses the built-in rp2040
|
||||||
|
* flash programming commands for read/write access to unused flash.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct mtd_dev_s *rp2040_flash_mtd_initialize(void)
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
{
|
||||||
|
errno = EBUSY;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
nxsem_init(&(my_dev.sem), 0, 1);
|
||||||
|
|
||||||
|
if (FLASH_BLOCK_COUNT < 4)
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rom_functions.connect_internal_flash = ROM_LOOKUP(ROM_FLASH_CONNECT);
|
||||||
|
rom_functions.flash_exit_xip = ROM_LOOKUP(ROM_FLASH_EXIT_XIP);
|
||||||
|
rom_functions.flash_range_erase = ROM_LOOKUP(ROM_FLASH_ERASE);
|
||||||
|
rom_functions.flash_range_program = ROM_LOOKUP(ROM_FLASH_PROGRAM);
|
||||||
|
rom_functions.flash_flush_cache = ROM_LOOKUP(ROM_FLASH_FLUSH_CACHE);
|
||||||
|
|
||||||
|
/* Instead of using the rom_function for flash_enable_xip, we use the one
|
||||||
|
* from boot stage 2 loaded at the beginning of the XIP rom. We do this
|
||||||
|
* because the boot_rom version can result in slower access to the the
|
||||||
|
* XIP memory.
|
||||||
|
*
|
||||||
|
* We need to make our own copy of this code in ram since we cannot use
|
||||||
|
* the rom until after this call completes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memcpy(my_dev.boot_2, (void *) XIP_BASE, BOOT_2_SIZE);
|
||||||
|
rom_functions.flash_enable_xip = (flash_enable_xip_f)my_dev.boot_2 + 1;
|
||||||
|
|
||||||
|
/* Do we need to initialize the flash? */
|
||||||
|
|
||||||
|
if (memcmp(rp2040_smart_flash_start, "2040", 4) == 0)
|
||||||
|
{
|
||||||
|
uint8_t buffer[FLASH_SECTOR_SIZE];
|
||||||
|
irqstate_t flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* OK, we found the "magic" tag... */
|
||||||
|
|
||||||
|
/* Erase all flash beyond what was loaded from NuttX binary. */
|
||||||
|
|
||||||
|
do_erase(FLASH_END_OFFSET,
|
||||||
|
CONFIG_RP2040_FLASH_LENGTH - FLASH_END_OFFSET);
|
||||||
|
|
||||||
|
/* Erase the "magic" flag, setting the first two bytes to zero. */
|
||||||
|
|
||||||
|
memcpy(buffer, rp2040_smart_flash_start, FLASH_SECTOR_SIZE);
|
||||||
|
|
||||||
|
buffer[0] = 0;
|
||||||
|
buffer[1] = 0;
|
||||||
|
|
||||||
|
do_write(FLASH_START_OFFSET, buffer, FLASH_SECTOR_SIZE);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &(my_dev.mtd_dev);
|
||||||
|
}
|
35
arch/arm/src/rp2040/rp2040_flash_mtd.h
Normal file
35
arch/arm/src/rp2040/rp2040_flash_mtd.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/arm/src/rp2040/rp2040_flash_mtd.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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/mtd/mtd.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rp2040_flash_mtd_initialize
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct mtd_dev_s *rp2040_flash_mtd_initialize(void);
|
63
arch/arm/src/rp2040/rp2040_rom.h
Normal file
63
arch/arm/src/rp2040/rp2040_rom.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/arm/src/rp2040/rp2040_rom.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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define ROM_HWORD_AS_PTR(a) ((void *)(uintptr_t) (*(uint16_t *)(uintptr_t)a))
|
||||||
|
|
||||||
|
#define ROM_CODE(a,b) ((b << 8) | a)
|
||||||
|
|
||||||
|
#define ROM_POPCOUNT32 ROM_CODE('P', '3')
|
||||||
|
#define ROM_REVERSE32 ROM_CODE('R', '3')
|
||||||
|
#define ROM_CLZ32 ROM_CODE('L', '3')
|
||||||
|
#define ROM_CTZ32 ROM_CODE('T', '3')
|
||||||
|
#define ROM_MEMSET ROM_CODE('M', 'S')
|
||||||
|
#define ROM_MEMSET4 ROM_CODE('S', '4')
|
||||||
|
#define ROM_MEMCPY ROM_CODE('M', 'C')
|
||||||
|
#define ROM_MEMCPY44 ROM_CODE('C', '4')
|
||||||
|
#define ROM_RESET_USB_BOOT ROM_CODE('U', 'B')
|
||||||
|
#define ROM_FLASH_CONNECT ROM_CODE('I', 'F')
|
||||||
|
#define ROM_FLASH_EXIT_XIP ROM_CODE('E', 'X')
|
||||||
|
#define ROM_FLASH_ERASE ROM_CODE('R', 'E')
|
||||||
|
#define ROM_FLASH_PROGRAM ROM_CODE('R', 'P')
|
||||||
|
#define ROM_FLASH_FLUSH_CACHE ROM_CODE('F', 'C')
|
||||||
|
#define ROM_FLASH_ENABLE_XIP ROM_CODE('C', 'X')
|
||||||
|
|
||||||
|
#define ROM_LOOKUP(x) \
|
||||||
|
((rom_table_lookup_fn)ROM_HWORD_AS_PTR(0x18)) \
|
||||||
|
(ROM_HWORD_AS_PTR(0x14),x)
|
||||||
|
|
||||||
|
#define STR(s) #s
|
||||||
|
#define RAM_CODE_ATTR(f) __attribute__((noinline, section(".ram_code." f)))
|
||||||
|
#define RAM_CODE(f) RAM_CODE_ATTR(STR(f)) f
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Type Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code);
|
@ -71,6 +71,9 @@ Defconfigs
|
|||||||
- nsh
|
- nsh
|
||||||
Minimum configuration with NuttShell
|
Minimum configuration with NuttShell
|
||||||
|
|
||||||
|
- nsh_flash
|
||||||
|
NuttX shell with SMART flash filesystem.
|
||||||
|
|
||||||
- nshsram
|
- nshsram
|
||||||
Load NuttX binary to SRAM
|
Load NuttX binary to SRAM
|
||||||
|
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||||
|
#
|
||||||
|
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||||
|
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||||
|
# modifications.
|
||||||
|
#
|
||||||
|
# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set
|
||||||
|
# CONFIG_LIBC_LONG_LONG is not set
|
||||||
|
# CONFIG_NSH_ARGCAT is not set
|
||||||
|
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||||
|
# CONFIG_NSH_DISABLE_DATE is not set
|
||||||
|
# CONFIG_STANDARD_SERIAL is not set
|
||||||
|
CONFIG_ARCH="arm"
|
||||||
|
CONFIG_ARCH_BOARD="adafruit-feather-rp2040"
|
||||||
|
CONFIG_ARCH_BOARD_ADAFRUIT_FEATHER_RP2040=y
|
||||||
|
CONFIG_ARCH_CHIP="rp2040"
|
||||||
|
CONFIG_ARCH_CHIP_RP2040=y
|
||||||
|
CONFIG_ARCH_RAMVECTORS=y
|
||||||
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_BOARDCTL_RESET=y
|
||||||
|
CONFIG_BOARD_LOOPSPERMSEC=10450
|
||||||
|
CONFIG_BUILTIN=y
|
||||||
|
CONFIG_DEBUG_FULLOPT=y
|
||||||
|
CONFIG_DEBUG_SYMBOLS=y
|
||||||
|
CONFIG_DISABLE_POSIX_TIMERS=y
|
||||||
|
CONFIG_EXAMPLES_HELLO=y
|
||||||
|
CONFIG_FS_PROCFS=y
|
||||||
|
CONFIG_FS_PROCFS_REGISTER=y
|
||||||
|
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||||
|
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||||
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
|
CONFIG_NSH_READLINE=y
|
||||||
|
CONFIG_RAM_SIZE=270336
|
||||||
|
CONFIG_RAM_START=0x20000000
|
||||||
|
CONFIG_READLINE_CMD_HISTORY=y
|
||||||
|
CONFIG_RP2040_BOARD_HAS_WS2812=y
|
||||||
|
CONFIG_RP2040_FLASH_FILE_SYSTEM=y
|
||||||
|
CONFIG_RP2040_FLASH_LENGTH=8388608
|
||||||
|
CONFIG_RP2040_WS2812_GPIO_PIN=16
|
||||||
|
CONFIG_RR_INTERVAL=200
|
||||||
|
CONFIG_SCHED_WAITPID=y
|
||||||
|
CONFIG_SMARTFS_ALIGNED_ACCESS=y
|
||||||
|
CONFIG_START_DAY=9
|
||||||
|
CONFIG_START_MONTH=2
|
||||||
|
CONFIG_START_YEAR=2021
|
||||||
|
CONFIG_SYSLOG_CONSOLE=y
|
||||||
|
CONFIG_SYSTEM_NSH=y
|
||||||
|
CONFIG_TESTING_GETPRIME=y
|
||||||
|
CONFIG_TESTING_OSTEST=y
|
||||||
|
CONFIG_TESTING_SMART_TEST=y
|
||||||
|
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||||
|
CONFIG_WS2812=y
|
@ -82,11 +82,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram AT > flash
|
} > sram AT > flash
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
flash (rx) : ORIGIN = 0x10000000, LENGTH = 8192K
|
||||||
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +68,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram
|
} > sram
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -70,6 +70,9 @@ Defconfigs
|
|||||||
- nsh
|
- nsh
|
||||||
Minimum configuration with NuttShell
|
Minimum configuration with NuttShell
|
||||||
|
|
||||||
|
- nsh_flash
|
||||||
|
NuttX shell with SMART flash filesystem.
|
||||||
|
|
||||||
- nshsram
|
- nshsram
|
||||||
Load NuttX binary to SRAM
|
Load NuttX binary to SRAM
|
||||||
|
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||||
|
#
|
||||||
|
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||||
|
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||||
|
# modifications.
|
||||||
|
#
|
||||||
|
# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set
|
||||||
|
# CONFIG_LIBC_LONG_LONG is not set
|
||||||
|
# CONFIG_NSH_ARGCAT is not set
|
||||||
|
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||||
|
# CONFIG_NSH_DISABLE_DATE is not set
|
||||||
|
# CONFIG_STANDARD_SERIAL is not set
|
||||||
|
CONFIG_ARCH="arm"
|
||||||
|
CONFIG_ARCH_BOARD="adafruit-kb2040"
|
||||||
|
CONFIG_ARCH_BOARD_ADAFRUIT_KB2040=y
|
||||||
|
CONFIG_ARCH_CHIP="rp2040"
|
||||||
|
CONFIG_ARCH_CHIP_RP2040=y
|
||||||
|
CONFIG_ARCH_RAMVECTORS=y
|
||||||
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_BOARDCTL_RESET=y
|
||||||
|
CONFIG_BOARD_LOOPSPERMSEC=10450
|
||||||
|
CONFIG_BUILTIN=y
|
||||||
|
CONFIG_DEBUG_FULLOPT=y
|
||||||
|
CONFIG_DEBUG_SYMBOLS=y
|
||||||
|
CONFIG_DISABLE_POSIX_TIMERS=y
|
||||||
|
CONFIG_EXAMPLES_HELLO=y
|
||||||
|
CONFIG_FS_PROCFS=y
|
||||||
|
CONFIG_FS_PROCFS_REGISTER=y
|
||||||
|
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||||
|
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||||
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
|
CONFIG_NSH_READLINE=y
|
||||||
|
CONFIG_RAM_SIZE=270336
|
||||||
|
CONFIG_RAM_START=0x20000000
|
||||||
|
CONFIG_READLINE_CMD_HISTORY=y
|
||||||
|
CONFIG_RP2040_BOARD_HAS_WS2812=y
|
||||||
|
CONFIG_RP2040_FLASH_FILE_SYSTEM=y
|
||||||
|
CONFIG_RP2040_FLASH_LENGTH=8388608
|
||||||
|
CONFIG_RP2040_WS2812_GPIO_PIN=17
|
||||||
|
CONFIG_RR_INTERVAL=200
|
||||||
|
CONFIG_SCHED_WAITPID=y
|
||||||
|
CONFIG_SMARTFS_ALIGNED_ACCESS=y
|
||||||
|
CONFIG_START_DAY=9
|
||||||
|
CONFIG_START_MONTH=2
|
||||||
|
CONFIG_START_YEAR=2021
|
||||||
|
CONFIG_SYSLOG_CONSOLE=y
|
||||||
|
CONFIG_SYSTEM_NSH=y
|
||||||
|
CONFIG_TESTING_GETPRIME=y
|
||||||
|
CONFIG_TESTING_OSTEST=y
|
||||||
|
CONFIG_TESTING_SMART_TEST=y
|
||||||
|
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||||
|
CONFIG_WS2812=y
|
@ -82,11 +82,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram AT > flash
|
} > sram AT > flash
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
flash (rx) : ORIGIN = 0x10000000, LENGTH = 8192K
|
||||||
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +68,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram
|
} > sram
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -65,6 +65,9 @@ Defconfigs
|
|||||||
- nsh
|
- nsh
|
||||||
Minimum configuration with NuttShell
|
Minimum configuration with NuttShell
|
||||||
|
|
||||||
|
- nsh_flash
|
||||||
|
NuttX shell with SMART flash filesystem.
|
||||||
|
|
||||||
- nshsram
|
- nshsram
|
||||||
Load NuttX binary to SRAM
|
Load NuttX binary to SRAM
|
||||||
|
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||||
|
#
|
||||||
|
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||||
|
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||||
|
# modifications.
|
||||||
|
#
|
||||||
|
# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set
|
||||||
|
# CONFIG_NSH_ARGCAT is not set
|
||||||
|
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||||
|
# CONFIG_NSH_DISABLE_DATE is not set
|
||||||
|
# CONFIG_RP2040_UART0 is not set
|
||||||
|
# CONFIG_STANDARD_SERIAL is not set
|
||||||
|
CONFIG_ARCH="arm"
|
||||||
|
CONFIG_ARCH_BOARD="adafruit-qt-py-rp2040"
|
||||||
|
CONFIG_ARCH_BOARD_ADAFRUIT_QT_PY_RP2040=y
|
||||||
|
CONFIG_ARCH_CHIP="rp2040"
|
||||||
|
CONFIG_ARCH_CHIP_RP2040=y
|
||||||
|
CONFIG_ARCH_RAMVECTORS=y
|
||||||
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_BOARDCTL_RESET=y
|
||||||
|
CONFIG_BOARD_LOOPSPERMSEC=10450
|
||||||
|
CONFIG_BUILTIN=y
|
||||||
|
CONFIG_DEBUG_FULLOPT=y
|
||||||
|
CONFIG_DEBUG_SYMBOLS=y
|
||||||
|
CONFIG_DISABLE_POSIX_TIMERS=y
|
||||||
|
CONFIG_EXAMPLES_HELLO=y
|
||||||
|
CONFIG_FS_PROCFS=y
|
||||||
|
CONFIG_FS_PROCFS_REGISTER=y
|
||||||
|
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||||
|
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||||
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
|
CONFIG_NSH_READLINE=y
|
||||||
|
CONFIG_RAM_SIZE=270336
|
||||||
|
CONFIG_RAM_START=0x20000000
|
||||||
|
CONFIG_READLINE_CMD_HISTORY=y
|
||||||
|
CONFIG_RP2040_BOARD_HAS_WS2812=y
|
||||||
|
CONFIG_RP2040_FLASH_FILE_SYSTEM=y
|
||||||
|
CONFIG_RP2040_FLASH_LENGTH=8388608
|
||||||
|
CONFIG_RP2040_UART1=y
|
||||||
|
CONFIG_RP2040_UART1_RX_GPIO=5
|
||||||
|
CONFIG_RP2040_WS2812_GPIO_PIN=12
|
||||||
|
CONFIG_RP2040_WS2812_PWR_GPIO=11
|
||||||
|
CONFIG_RR_INTERVAL=200
|
||||||
|
CONFIG_SCHED_WAITPID=y
|
||||||
|
CONFIG_SMARTFS_ALIGNED_ACCESS=y
|
||||||
|
CONFIG_START_DAY=9
|
||||||
|
CONFIG_START_MONTH=2
|
||||||
|
CONFIG_START_YEAR=2021
|
||||||
|
CONFIG_SYSLOG_CONSOLE=y
|
||||||
|
CONFIG_SYSTEM_NSH=y
|
||||||
|
CONFIG_TESTING_GETPRIME=y
|
||||||
|
CONFIG_TESTING_OSTEST=y
|
||||||
|
CONFIG_TESTING_SMART_TEST=y
|
||||||
|
CONFIG_UART1_SERIAL_CONSOLE=y
|
||||||
|
CONFIG_WS2812=y
|
@ -82,11 +82,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram AT > flash
|
} > sram AT > flash
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
flash (rx) : ORIGIN = 0x10000000, LENGTH = 8192K
|
||||||
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +68,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram
|
} > sram
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -475,7 +475,6 @@ if RP2040_I2S
|
|||||||
|
|
||||||
endif # RP2040_I2S
|
endif # RP2040_I2S
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
# WS2812 Configuration
|
# WS2812 Configuration
|
||||||
#####################################################################
|
#####################################################################
|
||||||
@ -501,3 +500,17 @@ if RP2040_BOARD_HAS_WS2812
|
|||||||
such a pin.
|
such a pin.
|
||||||
|
|
||||||
endif # RP2040_BOARD_HAS_WS2812
|
endif # RP2040_BOARD_HAS_WS2812
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# FLASH File System Configuration
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
if RP2040_FLASH_FILE_SYSTEM
|
||||||
|
|
||||||
|
config RP2040_FLASH_LENGTH
|
||||||
|
int "Size of flash memory in bytes."
|
||||||
|
default 2097152
|
||||||
|
---help---
|
||||||
|
This is the overall amount of flash memory on the board.
|
||||||
|
|
||||||
|
endif # RP2040_FLASH_FILE_SYSTEM
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <nuttx/fs/fs.h>
|
#include <nuttx/fs/fs.h>
|
||||||
|
|
||||||
@ -74,6 +76,14 @@
|
|||||||
#include "rp2040_ws2812.h"
|
#include "rp2040_ws2812.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_RP2040_ROMFS_ROMDISK_DEVNAME)
|
||||||
|
# include <rp2040_romfsimg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_RP2040_FLASH_FILE_SYSTEM
|
||||||
|
# include "rp2040_flash_mtd.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_WS2812_HAS_WHITE
|
#ifdef CONFIG_WS2812_HAS_WHITE
|
||||||
#define HAS_WHITE true
|
#define HAS_WHITE true
|
||||||
#else /* CONFIG_WS2812_HAS_WHITE */
|
#else /* CONFIG_WS2812_HAS_WHITE */
|
||||||
@ -92,6 +102,10 @@ int rp2040_common_bringup(void)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_RP2040_FLASH_FILE_SYSTEM
|
||||||
|
struct mtd_dev_s *mtd_dev;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_RP2040_I2C_DRIVER
|
#ifdef CONFIG_RP2040_I2C_DRIVER
|
||||||
#ifdef CONFIG_RP2040_I2C0
|
#ifdef CONFIG_RP2040_I2C0
|
||||||
ret = board_i2cdev_initialize(0);
|
ret = board_i2cdev_initialize(0);
|
||||||
@ -570,5 +584,76 @@ int rp2040_common_bringup(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_RP2040_FLASH_FILE_SYSTEM
|
||||||
|
|
||||||
|
mtd_dev = rp2040_flash_mtd_initialize();
|
||||||
|
|
||||||
|
if (mtd_dev == NULL)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: flash_mtd_initialize failed: %d\n", errno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = smart_initialize(0, mtd_dev, NULL);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: smart_initialize failed: %d\n", -ret);
|
||||||
|
}
|
||||||
|
else if (strlen(CONFIG_RP2040_FLASH_MOUNT_POINT) > 0)
|
||||||
|
{
|
||||||
|
mkdir(CONFIG_RP2040_FLASH_MOUNT_POINT, 0777);
|
||||||
|
|
||||||
|
/* Mount the file system */
|
||||||
|
|
||||||
|
ret = nx_mount("/dev/smart0",
|
||||||
|
CONFIG_RP2040_FLASH_MOUNT_POINT,
|
||||||
|
"smartfs",
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR,
|
||||||
|
"ERROR: nx_mount(\"/dev/smart0\", \"%s\", \"smartfs\","
|
||||||
|
" 0, NULL) failed: %d\n",
|
||||||
|
CONFIG_RP2040_FLASH_MOUNT_POINT,
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_RP2040_ROMFS_ROMDISK_DEVNAME)
|
||||||
|
/* Register the ROM disk */
|
||||||
|
|
||||||
|
ret = romdisk_register(CONFIG_RP2040_ROMFS_ROMDISK_MINOR,
|
||||||
|
rp2040_romfs_img,
|
||||||
|
NSECTORS(rp2040_romfs_img_len),
|
||||||
|
CONFIG_RP2040_ROMFS_ROMDISK_SECTSIZE);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: romdisk_register failed: %d\n", -ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Mount the file system */
|
||||||
|
|
||||||
|
ret = nx_mount(CONFIG_RP2040_ROMFS_ROMDISK_DEVNAME,
|
||||||
|
CONFIG_RP2040_ROMFS_MOUNT_MOUNTPOINT,
|
||||||
|
"romfs",
|
||||||
|
MS_RDONLY,
|
||||||
|
NULL);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR,
|
||||||
|
"ERROR: nx_mount(%s,%s,romfs) failed: %d\n",
|
||||||
|
CONFIG_RP2040_ROMFS_ROMDISK_DEVNAME,
|
||||||
|
CONFIG_RP2040_ROMFS_MOUNT_MOUNTPOINT,
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,9 @@ Defconfigs
|
|||||||
- nsh
|
- nsh
|
||||||
Minimum configuration with NuttShell
|
Minimum configuration with NuttShell
|
||||||
|
|
||||||
|
- nsh_flash
|
||||||
|
NuttX shell with SMART flash filesystem.
|
||||||
|
|
||||||
- nshsram
|
- nshsram
|
||||||
Load NuttX binary to SRAM
|
Load NuttX binary to SRAM
|
||||||
|
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||||
|
#
|
||||||
|
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||||
|
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||||
|
# modifications.
|
||||||
|
#
|
||||||
|
# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set
|
||||||
|
# CONFIG_LIBC_LONG_LONG is not set
|
||||||
|
# CONFIG_NSH_ARGCAT is not set
|
||||||
|
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||||
|
# CONFIG_NSH_DISABLE_DATE is not set
|
||||||
|
# CONFIG_STANDARD_SERIAL is not set
|
||||||
|
CONFIG_ARCH="arm"
|
||||||
|
CONFIG_ARCH_BOARD="pimoroni-tiny2040"
|
||||||
|
CONFIG_ARCH_BOARD_PIMORONI_TINY2040=y
|
||||||
|
CONFIG_ARCH_CHIP="rp2040"
|
||||||
|
CONFIG_ARCH_CHIP_RP2040=y
|
||||||
|
CONFIG_ARCH_COVERAGE=y
|
||||||
|
CONFIG_ARCH_RAMVECTORS=y
|
||||||
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_BOARDCTL_RESET=y
|
||||||
|
CONFIG_BOARD_LOOPSPERMSEC=10450
|
||||||
|
CONFIG_BUILTIN=y
|
||||||
|
CONFIG_DEBUG_FULLOPT=y
|
||||||
|
CONFIG_DEBUG_SYMBOLS=y
|
||||||
|
CONFIG_DISABLE_POSIX_TIMERS=y
|
||||||
|
CONFIG_EXAMPLES_HELLO=y
|
||||||
|
CONFIG_FS_PROCFS=y
|
||||||
|
CONFIG_FS_PROCFS_REGISTER=y
|
||||||
|
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||||
|
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||||
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
|
CONFIG_NSH_READLINE=y
|
||||||
|
CONFIG_RAM_SIZE=270336
|
||||||
|
CONFIG_RAM_START=0x20000000
|
||||||
|
CONFIG_READLINE_CMD_HISTORY=y
|
||||||
|
CONFIG_RP2040_FLASH_FILE_SYSTEM=y
|
||||||
|
CONFIG_RP2040_FLASH_LENGTH=8388608
|
||||||
|
CONFIG_RR_INTERVAL=200
|
||||||
|
CONFIG_SCHED_WAITPID=y
|
||||||
|
CONFIG_SMARTFS_ALIGNED_ACCESS=y
|
||||||
|
CONFIG_START_DAY=11
|
||||||
|
CONFIG_START_MONTH=12
|
||||||
|
CONFIG_START_YEAR=2021
|
||||||
|
CONFIG_SYSLOG_CONSOLE=y
|
||||||
|
CONFIG_SYSTEM_GCOV=y
|
||||||
|
CONFIG_SYSTEM_NSH=y
|
||||||
|
CONFIG_TESTING_GETPRIME=y
|
||||||
|
CONFIG_TESTING_OSTEST=y
|
||||||
|
CONFIG_TESTING_SMART_TEST=y
|
||||||
|
CONFIG_UART0_SERIAL_CONSOLE=y
|
@ -82,11 +82,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram AT > flash
|
} > sram AT > flash
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
flash (rx) : ORIGIN = 0x10000000, LENGTH = 8192K
|
||||||
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +68,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram
|
} > sram
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -72,6 +72,9 @@ Defconfigs
|
|||||||
- nsh
|
- nsh
|
||||||
Minimum configuration with NuttShell
|
Minimum configuration with NuttShell
|
||||||
|
|
||||||
|
- nsh_flash
|
||||||
|
NuttX shell with SMART flash filesystem.
|
||||||
|
|
||||||
- nshsram
|
- nshsram
|
||||||
Load NuttX binary to SRAM
|
Load NuttX binary to SRAM
|
||||||
|
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||||
|
#
|
||||||
|
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||||
|
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||||
|
# modifications.
|
||||||
|
#
|
||||||
|
# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set
|
||||||
|
# CONFIG_LIBC_LONG_LONG is not set
|
||||||
|
# CONFIG_NSH_ARGCAT is not set
|
||||||
|
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||||
|
# CONFIG_NSH_DISABLE_DATE is not set
|
||||||
|
# CONFIG_STANDARD_SERIAL is not set
|
||||||
|
CONFIG_ARCH="arm"
|
||||||
|
CONFIG_ARCH_BOARD="raspberrypi-pico-w"
|
||||||
|
CONFIG_ARCH_BOARD_RASPBERRYPI_PICO_W=y
|
||||||
|
CONFIG_ARCH_CHIP="rp2040"
|
||||||
|
CONFIG_ARCH_CHIP_RP2040=y
|
||||||
|
CONFIG_ARCH_RAMVECTORS=y
|
||||||
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_BOARDCTL_RESET=y
|
||||||
|
CONFIG_BOARD_LOOPSPERMSEC=10450
|
||||||
|
CONFIG_BUILTIN=y
|
||||||
|
CONFIG_DEBUG_FULLOPT=y
|
||||||
|
CONFIG_DEBUG_SYMBOLS=y
|
||||||
|
CONFIG_DISABLE_POSIX_TIMERS=y
|
||||||
|
CONFIG_EXAMPLES_HELLO=y
|
||||||
|
CONFIG_FS_PROCFS=y
|
||||||
|
CONFIG_FS_PROCFS_REGISTER=y
|
||||||
|
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||||
|
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||||
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
|
CONFIG_NSH_READLINE=y
|
||||||
|
CONFIG_RAM_SIZE=270336
|
||||||
|
CONFIG_RAM_START=0x20000000
|
||||||
|
CONFIG_READLINE_CMD_HISTORY=y
|
||||||
|
CONFIG_RP2040_FLASH_FILE_SYSTEM=y
|
||||||
|
CONFIG_RR_INTERVAL=200
|
||||||
|
CONFIG_SCHED_WAITPID=y
|
||||||
|
CONFIG_SMARTFS_ALIGNED_ACCESS=y
|
||||||
|
CONFIG_START_DAY=9
|
||||||
|
CONFIG_START_MONTH=2
|
||||||
|
CONFIG_START_YEAR=2021
|
||||||
|
CONFIG_SYSLOG_CONSOLE=y
|
||||||
|
CONFIG_SYSTEM_NSH=y
|
||||||
|
CONFIG_TESTING_GETPRIME=y
|
||||||
|
CONFIG_TESTING_OSTEST=y
|
||||||
|
CONFIG_TESTING_SMART_TEST=y
|
||||||
|
CONFIG_UART0_SERIAL_CONSOLE=y
|
@ -82,11 +82,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram AT > flash
|
} > sram AT > flash
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
flash (rx) : ORIGIN = 0x10000000, LENGTH = 2048K
|
||||||
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +68,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram
|
} > sram
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -71,6 +71,9 @@ Defconfigs
|
|||||||
- nsh
|
- nsh
|
||||||
Minimum configuration with NuttShell
|
Minimum configuration with NuttShell
|
||||||
|
|
||||||
|
- nsh_flash
|
||||||
|
NuttX shell with SMART flash filesystem.
|
||||||
|
|
||||||
- nshsram
|
- nshsram
|
||||||
Load NuttX binary to SRAM
|
Load NuttX binary to SRAM
|
||||||
|
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||||
|
#
|
||||||
|
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||||
|
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||||
|
# modifications.
|
||||||
|
#
|
||||||
|
# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set
|
||||||
|
# CONFIG_LIBC_LONG_LONG is not set
|
||||||
|
# CONFIG_NSH_ARGCAT is not set
|
||||||
|
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||||
|
# CONFIG_NSH_DISABLE_DATE is not set
|
||||||
|
# CONFIG_STANDARD_SERIAL is not set
|
||||||
|
CONFIG_ARCH="arm"
|
||||||
|
CONFIG_ARCH_BOARD="raspberrypi-pico"
|
||||||
|
CONFIG_ARCH_BOARD_RASPBERRYPI_PICO=y
|
||||||
|
CONFIG_ARCH_CHIP="rp2040"
|
||||||
|
CONFIG_ARCH_CHIP_RP2040=y
|
||||||
|
CONFIG_ARCH_RAMVECTORS=y
|
||||||
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_BOARDCTL_RESET=y
|
||||||
|
CONFIG_BOARD_LOOPSPERMSEC=10450
|
||||||
|
CONFIG_BUILTIN=y
|
||||||
|
CONFIG_DEBUG_FULLOPT=y
|
||||||
|
CONFIG_DEBUG_SYMBOLS=y
|
||||||
|
CONFIG_DISABLE_POSIX_TIMERS=y
|
||||||
|
CONFIG_EXAMPLES_HELLO=y
|
||||||
|
CONFIG_FS_PROCFS=y
|
||||||
|
CONFIG_FS_PROCFS_REGISTER=y
|
||||||
|
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||||
|
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||||
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
|
CONFIG_NSH_READLINE=y
|
||||||
|
CONFIG_RAM_SIZE=270336
|
||||||
|
CONFIG_RAM_START=0x20000000
|
||||||
|
CONFIG_READLINE_CMD_HISTORY=y
|
||||||
|
CONFIG_RP2040_FLASH_FILE_SYSTEM=y
|
||||||
|
CONFIG_RR_INTERVAL=200
|
||||||
|
CONFIG_SCHED_WAITPID=y
|
||||||
|
CONFIG_SMARTFS_ALIGNED_ACCESS=y
|
||||||
|
CONFIG_START_DAY=9
|
||||||
|
CONFIG_START_MONTH=2
|
||||||
|
CONFIG_START_YEAR=2021
|
||||||
|
CONFIG_SYSLOG_CONSOLE=y
|
||||||
|
CONFIG_SYSTEM_NSH=y
|
||||||
|
CONFIG_TESTING_GETPRIME=y
|
||||||
|
CONFIG_TESTING_OSTEST=y
|
||||||
|
CONFIG_TESTING_SMART_TEST=y
|
||||||
|
CONFIG_UART0_SERIAL_CONSOLE=y
|
@ -82,11 +82,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram AT > flash
|
} > sram AT > flash
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
flash (rx) : ORIGIN = 0x10000000, LENGTH = 2048K
|
||||||
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +68,17 @@ SECTIONS
|
|||||||
_sdata = ABSOLUTE(.);
|
_sdata = ABSOLUTE(.);
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu.linkonce.d.*)
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.ram_code.*)
|
||||||
CONSTRUCTORS
|
CONSTRUCTORS
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = ABSOLUTE(.);
|
_edata = ABSOLUTE(.);
|
||||||
} > sram
|
} > sram
|
||||||
|
|
||||||
|
.flash_section : {
|
||||||
|
. = ALIGN(4*1024);
|
||||||
|
*(.flash.*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
_sbss = ABSOLUTE(.);
|
_sbss = ABSOLUTE(.);
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -5751,7 +5751,7 @@ static int smart_fsck_file(FAR struct smart_struct_s *dev,
|
|||||||
|
|
||||||
/* next logical sector */
|
/* next logical sector */
|
||||||
|
|
||||||
logsector = *(uint16_t *)chain->nextsector;
|
logsector = SMARTFS_NEXTSECTOR(chain);
|
||||||
}
|
}
|
||||||
while (logsector != 0xffff);
|
while (logsector != 0xffff);
|
||||||
|
|
||||||
@ -5879,7 +5879,7 @@ static int smart_fsck_directory(FAR struct smart_struct_s *dev,
|
|||||||
|
|
||||||
/* Check next sector recursively */
|
/* Check next sector recursively */
|
||||||
|
|
||||||
nextsector = *(uint16_t *)chain->nextsector;
|
nextsector = SMARTFS_NEXTSECTOR(chain);
|
||||||
|
|
||||||
if (nextsector != 0xffff)
|
if (nextsector != 0xffff)
|
||||||
{
|
{
|
||||||
@ -5893,7 +5893,7 @@ static int smart_fsck_directory(FAR struct smart_struct_s *dev,
|
|||||||
|
|
||||||
ferr("Invalidate next log sector %d\n", nextsector);
|
ferr("Invalidate next log sector %d\n", nextsector);
|
||||||
|
|
||||||
*(uint16_t *)chain->nextsector = 0xffff;
|
SMARTFS_SET_NEXTSECTOR(chain, 0xffff);
|
||||||
|
|
||||||
/* Set flag to relocate later */
|
/* Set flag to relocate later */
|
||||||
|
|
||||||
|
@ -197,8 +197,18 @@
|
|||||||
# define offsetof(type, member) ((size_t) & (((type *)0)->member))
|
# define offsetof(type, member) ((size_t) & (((type *)0)->member))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SMARTFS_NEXTSECTOR(h) (*((uint16_t *)h->nextsector))
|
#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
|
||||||
#define SMARTFS_USED(h) (*((uint16_t *)h->used))
|
# define SMARTFS_NEXTSECTOR(h) (smartfs_rdle16(h->nextsector))
|
||||||
|
# define SMARTFS_SET_NEXTSECTOR(h, v) smartfs_wrle16(h->nextsector, v)
|
||||||
|
# define SMARTFS_USED(h) (smartfs_rdle16(h->used))
|
||||||
|
# define SMARTFS_SET_USED(h, v) smartfs_wrle16(h->used, v)
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define SMARTFS_NEXTSECTOR(h) (*((uint16_t *)h->nextsector))
|
||||||
|
# define SMARTFS_SET_NEXTSECTOR(h, v) ((*((uint16_t *)h->nextsector)) = v)
|
||||||
|
# define SMARTFS_USED(h) (*((uint16_t *)h->used))
|
||||||
|
# define SMARTFS_SET_USED(h, v) ((*((uint16_t *)h->used)) = v)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_SMART_ENABLE_CRC
|
#ifdef CONFIG_MTD_SMART_ENABLE_CRC
|
||||||
#define CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
#define CONFIG_SMARTFS_USE_SECTOR_BUFFER
|
||||||
|
@ -45,6 +45,10 @@
|
|||||||
|
|
||||||
#include "smartfs.h"
|
#include "smartfs.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS_INFO
|
||||||
|
# include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Type
|
* Private Type
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -528,6 +532,8 @@ static ssize_t smartfs_read(FAR struct file *filep, char *buffer,
|
|||||||
|
|
||||||
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
|
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
|
||||||
|
|
||||||
|
finfo("Reading %u bytes\n", (unsigned) buflen);
|
||||||
|
|
||||||
/* Recover our private data from the struct file instance */
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
sf = filep->f_priv;
|
sf = filep->f_priv;
|
||||||
@ -578,7 +584,7 @@ static ssize_t smartfs_read(FAR struct file *filep, char *buffer,
|
|||||||
|
|
||||||
/* Get number of used bytes in this sector */
|
/* Get number of used bytes in this sector */
|
||||||
|
|
||||||
bytesinsector = *((uint16_t *) header->used);
|
bytesinsector = SMARTFS_USED(header);
|
||||||
if (bytesinsector == SMARTFS_ERASEDSTATE_16BIT)
|
if (bytesinsector == SMARTFS_ERASEDSTATE_16BIT)
|
||||||
{
|
{
|
||||||
/* No bytes to read from this sector */
|
/* No bytes to read from this sector */
|
||||||
@ -633,6 +639,18 @@ static ssize_t smartfs_read(FAR struct file *filep, char *buffer,
|
|||||||
|
|
||||||
/* Return the number of bytes we read */
|
/* Return the number of bytes we read */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS_INFO
|
||||||
|
finfo("Read %lu bytes:", bytesread);
|
||||||
|
for (uint32_t i = 0; i < bytesread; ++i)
|
||||||
|
{
|
||||||
|
if ((i & 0x0f) == 0) printf("\n ");
|
||||||
|
|
||||||
|
printf("%02x, ", buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = bytesread;
|
ret = bytesread;
|
||||||
|
|
||||||
errout_with_semaphore:
|
errout_with_semaphore:
|
||||||
@ -657,6 +675,18 @@ static ssize_t smartfs_write(FAR struct file *filep, const char *buffer,
|
|||||||
|
|
||||||
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
|
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS_INFO
|
||||||
|
finfo("Writing %lu bytes:", (uint32_t)buflen);
|
||||||
|
for (uint32_t i = 0; i < buflen; ++i)
|
||||||
|
{
|
||||||
|
if ((i & 0x0f) == 0) printf("\n ");
|
||||||
|
|
||||||
|
printf("%02x, ", buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Recover our private data from the struct file instance */
|
/* Recover our private data from the struct file instance */
|
||||||
|
|
||||||
sf = filep->f_priv;
|
sf = filep->f_priv;
|
||||||
@ -852,7 +882,7 @@ static ssize_t smartfs_write(FAR struct file *filep, const char *buffer,
|
|||||||
/* Copy the new sector to the old one and chain it */
|
/* Copy the new sector to the old one and chain it */
|
||||||
|
|
||||||
header = (struct smartfs_chain_header_s *) sf->buffer;
|
header = (struct smartfs_chain_header_s *) sf->buffer;
|
||||||
*((uint16_t *) header->nextsector) = (uint16_t) ret;
|
SMARTFS_SET_NEXTSECTOR(header, (uint16_t) ret);
|
||||||
|
|
||||||
/* Now sync the file to write this sector out */
|
/* Now sync the file to write this sector out */
|
||||||
|
|
||||||
@ -908,7 +938,7 @@ static ssize_t smartfs_write(FAR struct file *filep, const char *buffer,
|
|||||||
/* Copy the new sector to the old one and chain it */
|
/* Copy the new sector to the old one and chain it */
|
||||||
|
|
||||||
header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
|
header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
|
||||||
*((uint16_t *) header->nextsector) = (uint16_t) ret;
|
SMARTFS_SET_NEXTSECTOR(header, (uint16_t) ret);
|
||||||
readwrite.offset = offsetof(struct smartfs_chain_header_s,
|
readwrite.offset = offsetof(struct smartfs_chain_header_s,
|
||||||
nextsector);
|
nextsector);
|
||||||
readwrite.buffer = (uint8_t *) header->nextsector;
|
readwrite.buffer = (uint8_t *) header->nextsector;
|
||||||
@ -941,6 +971,8 @@ static ssize_t smartfs_write(FAR struct file *filep, const char *buffer,
|
|||||||
|
|
||||||
ret = byteswritten;
|
ret = byteswritten;
|
||||||
|
|
||||||
|
finfo("Wrote %u bytes\n", (unsigned) byteswritten);
|
||||||
|
|
||||||
errout_with_semaphore:
|
errout_with_semaphore:
|
||||||
smartfs_semgive(fs);
|
smartfs_semgive(fs);
|
||||||
return ret;
|
return ret;
|
||||||
@ -1325,6 +1357,7 @@ static int smartfs_readdir(FAR struct inode *mountpt,
|
|||||||
|
|
||||||
entrysize = sizeof(struct smartfs_entry_header_s) +
|
entrysize = sizeof(struct smartfs_entry_header_s) +
|
||||||
fs->fs_llformat.namesize;
|
fs->fs_llformat.namesize;
|
||||||
|
|
||||||
while (sdir->fs_currsector != SMARTFS_ERASEDSTATE_16BIT)
|
while (sdir->fs_currsector != SMARTFS_ERASEDSTATE_16BIT)
|
||||||
{
|
{
|
||||||
/* Read the logical sector */
|
/* Read the logical sector */
|
||||||
@ -1341,7 +1374,11 @@ static int smartfs_readdir(FAR struct inode *mountpt,
|
|||||||
|
|
||||||
/* Now search for entries, starting at curroffset */
|
/* Now search for entries, starting at curroffset */
|
||||||
|
|
||||||
while (sdir->fs_curroffset < ret)
|
/* Note: directories don't use the header's used field
|
||||||
|
* so we search all possilble directory entries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (sdir->fs_curroffset + entrysize < ret)
|
||||||
{
|
{
|
||||||
/* Point to next entry */
|
/* Point to next entry */
|
||||||
|
|
||||||
@ -1350,24 +1387,35 @@ static int smartfs_readdir(FAR struct inode *mountpt,
|
|||||||
|
|
||||||
/* Test if this entry is valid and active */
|
/* Test if this entry is valid and active */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
|
||||||
|
if (((smartfs_rdle16(&entry->flags)
|
||||||
|
& SMARTFS_DIRENT_EMPTY) ==
|
||||||
|
(SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) ||
|
||||||
|
((smartfs_rdle16(&entry->flags)
|
||||||
|
& SMARTFS_DIRENT_ACTIVE) !=
|
||||||
|
(SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
|
||||||
|
#else
|
||||||
if (((entry->flags & SMARTFS_DIRENT_EMPTY) ==
|
if (((entry->flags & SMARTFS_DIRENT_EMPTY) ==
|
||||||
(SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) ||
|
(SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) ||
|
||||||
((entry->flags & SMARTFS_DIRENT_ACTIVE) !=
|
((entry->flags & SMARTFS_DIRENT_ACTIVE) !=
|
||||||
(SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
|
(SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* This entry isn't valid, skip it */
|
/* This entry isn't valid, skip it */
|
||||||
|
|
||||||
sdir->fs_curroffset += entrysize;
|
sdir->fs_curroffset += entrysize;
|
||||||
entry = (struct smartfs_entry_header_s *)
|
|
||||||
&fs->fs_rwbuffer[sdir->fs_curroffset];
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Entry found! Report it */
|
/* Entry found! Report it */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
|
||||||
|
if ((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_TYPE) ==
|
||||||
|
SMARTFS_DIRENT_TYPE_DIR)
|
||||||
|
#else
|
||||||
if ((entry->flags & SMARTFS_DIRENT_TYPE) ==
|
if ((entry->flags & SMARTFS_DIRENT_TYPE) ==
|
||||||
SMARTFS_DIRENT_TYPE_DIR)
|
SMARTFS_DIRENT_TYPE_DIR)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
dentry->d_type = DTYPE_DIRECTORY;
|
dentry->d_type = DTYPE_DIRECTORY;
|
||||||
}
|
}
|
||||||
|
@ -714,11 +714,11 @@ int smartfs_finddirentry(struct smartfs_mountpt_s *fs,
|
|||||||
* to next sector
|
* to next sector
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (*((FAR uint16_t *)header->used) !=
|
if (SMARTFS_USED(header) !=
|
||||||
SMARTFS_ERASEDSTATE_16BIT)
|
SMARTFS_ERASEDSTATE_16BIT)
|
||||||
{
|
{
|
||||||
direntry->datlen +=
|
direntry->datlen +=
|
||||||
*((uint16_t *)header->used);
|
SMARTFS_USED(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
dirsector = SMARTFS_NEXTSECTOR(header);
|
dirsector = SMARTFS_NEXTSECTOR(header);
|
||||||
@ -1293,7 +1293,7 @@ int smartfs_deleteentry(struct smartfs_mountpt_s *fs,
|
|||||||
{
|
{
|
||||||
/* We found ourselves in the chain. Update the chain. */
|
/* We found ourselves in the chain. Update the chain. */
|
||||||
|
|
||||||
SMARTFS_NEXTSECTOR(header) = nextsector;
|
SMARTFS_SET_NEXTSECTOR(header, nextsector);
|
||||||
readwrite.offset = offsetof(struct smartfs_chain_header_s,
|
readwrite.offset = offsetof(struct smartfs_chain_header_s,
|
||||||
nextsector);
|
nextsector);
|
||||||
readwrite.count = sizeof(uint16_t);
|
readwrite.count = sizeof(uint16_t);
|
||||||
@ -1449,13 +1449,15 @@ int smartfs_sync_internal(FAR struct smartfs_mountpt_s *fs,
|
|||||||
/* Update the header with the number of bytes written */
|
/* Update the header with the number of bytes written */
|
||||||
|
|
||||||
header = (struct smartfs_chain_header_s *)sf->buffer;
|
header = (struct smartfs_chain_header_s *)sf->buffer;
|
||||||
if (*((uint16_t *)header->used) == SMARTFS_ERASEDSTATE_16BIT)
|
|
||||||
|
if (SMARTFS_USED(header) == SMARTFS_ERASEDSTATE_16BIT)
|
||||||
{
|
{
|
||||||
*((uint16_t *)header->used) = sf->byteswritten;
|
SMARTFS_SET_USED(header, sf->byteswritten);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*((uint16_t *)header->used) += sf->byteswritten;
|
SMARTFS_SET_USED(header, SMARTFS_USED(header)
|
||||||
|
+ sf->byteswritten);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the entire sector to FLASH */
|
/* Write the entire sector to FLASH */
|
||||||
@ -1504,13 +1506,15 @@ int smartfs_sync_internal(FAR struct smartfs_mountpt_s *fs,
|
|||||||
/* Add new byteswritten to existing value */
|
/* Add new byteswritten to existing value */
|
||||||
|
|
||||||
header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
|
header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
|
||||||
if (*((uint16_t *) header->used) == SMARTFS_ERASEDSTATE_16BIT)
|
|
||||||
|
if (SMARTFS_USED(header) == SMARTFS_ERASEDSTATE_16BIT)
|
||||||
{
|
{
|
||||||
*((uint16_t *) header->used) = sf->byteswritten;
|
SMARTFS_SET_USED(header, sf->byteswritten);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*((uint16_t *) header->used) += sf->byteswritten;
|
SMARTFS_SET_USED(header, SMARTFS_USED(header)
|
||||||
|
+ sf->byteswritten);
|
||||||
}
|
}
|
||||||
|
|
||||||
readwrite.offset = offsetof(struct smartfs_chain_header_s, used);
|
readwrite.offset = offsetof(struct smartfs_chain_header_s, used);
|
||||||
@ -1813,9 +1817,8 @@ int smartfs_shrinkfile(FAR struct smartfs_mountpt_s *fs,
|
|||||||
dest = (FAR uint8_t *)&fs->fs_rwbuffer[offset];
|
dest = (FAR uint8_t *)&fs->fs_rwbuffer[offset];
|
||||||
destsize = fs->fs_llformat.availbytes - offset;
|
destsize = fs->fs_llformat.availbytes - offset;
|
||||||
|
|
||||||
*((uint16_t *)header->used) = remaining;
|
SMARTFS_SET_USED(header, remaining);
|
||||||
*((uint16_t *)header->nextsector) = SMARTFS_ERASEDSTATE_16BIT;
|
SMARTFS_SET_NEXTSECTOR(header, SMARTFS_ERASEDSTATE_16BIT);
|
||||||
|
|
||||||
remaining = 0;
|
remaining = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1879,8 +1882,9 @@ int smartfs_shrinkfile(FAR struct smartfs_mountpt_s *fs,
|
|||||||
destsize = fs->fs_llformat.availbytes - offset;
|
destsize = fs->fs_llformat.availbytes - offset;
|
||||||
|
|
||||||
header = (struct smartfs_chain_header_s *)sf->buffer;
|
header = (struct smartfs_chain_header_s *)sf->buffer;
|
||||||
*((uint16_t *)header->used) = length;
|
|
||||||
*((uint16_t *)header->nextsector) = SMARTFS_ERASEDSTATE_16BIT;
|
SMARTFS_SET_USED(header, length);
|
||||||
|
SMARTFS_SET_NEXTSECTOR(header, SMARTFS_ERASEDSTATE_16BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(dest, CONFIG_SMARTFS_ERASEDSTATE, destsize);
|
memset(dest, CONFIG_SMARTFS_ERASEDSTATE, destsize);
|
||||||
@ -2027,7 +2031,7 @@ int smartfs_extendfile(FAR struct smartfs_mountpt_s *fs,
|
|||||||
/* Copy the new sector to the old one and chain it */
|
/* Copy the new sector to the old one and chain it */
|
||||||
|
|
||||||
header = (struct smartfs_chain_header_s *) sf->buffer;
|
header = (struct smartfs_chain_header_s *) sf->buffer;
|
||||||
*((uint16_t *)header->nextsector) = (uint16_t)ret;
|
SMARTFS_SET_NEXTSECTOR(header, (uint16_t)ret);
|
||||||
|
|
||||||
/* Now sync the file to write this sector out */
|
/* Now sync the file to write this sector out */
|
||||||
|
|
||||||
@ -2083,7 +2087,7 @@ int smartfs_extendfile(FAR struct smartfs_mountpt_s *fs,
|
|||||||
/* Copy the new sector to the old one and chain it */
|
/* Copy the new sector to the old one and chain it */
|
||||||
|
|
||||||
header = (struct smartfs_chain_header_s *)fs->fs_rwbuffer;
|
header = (struct smartfs_chain_header_s *)fs->fs_rwbuffer;
|
||||||
*((FAR uint16_t *)header->nextsector) = (uint16_t)ret;
|
SMARTFS_SET_NEXTSECTOR(header, (uint16_t)ret);
|
||||||
|
|
||||||
readwrite.offset = offsetof(struct smartfs_chain_header_s,
|
readwrite.offset = offsetof(struct smartfs_chain_header_s,
|
||||||
nextsector);
|
nextsector);
|
||||||
|
480
tools/rp2040/make_flash_fs.c
Normal file
480
tools/rp2040/make_flash_fs.c
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* tools/rp2040/make_flash_fs.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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <sys/dir.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define MAX_NAME_LEN 16
|
||||||
|
#define MAX_SECTOR_DATA (1024 - 10)
|
||||||
|
#define MAX_DIR_COUNT (MAX_SECTOR_DATA / 24)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct dir_item_s
|
||||||
|
{
|
||||||
|
struct dir_item_s *prior;
|
||||||
|
bool is_directory;
|
||||||
|
int init_sector;
|
||||||
|
int permissions;
|
||||||
|
char name[0];
|
||||||
|
} dir_item_t;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int max_name_len = MAX_NAME_LEN;
|
||||||
|
int root_sector = 3;
|
||||||
|
char path[4096];
|
||||||
|
uint8_t *buffer;
|
||||||
|
|
||||||
|
const char *preamble =
|
||||||
|
"\n .macro sector num, type, used=0xffff, next=0xffff"
|
||||||
|
"\n .balign 1024, 0xff"
|
||||||
|
"\n .hword \\num, 0"
|
||||||
|
"\n .byte 0b01101001, \\type"
|
||||||
|
"\n 1:"
|
||||||
|
"\n .hword \\next, \\used"
|
||||||
|
"\n .endm"
|
||||||
|
"\n"
|
||||||
|
"\n .macro dir_entry perm, addr, time, name"
|
||||||
|
"\n .hword \\perm | 0x7e00, \\addr"
|
||||||
|
"\n .word \\time"
|
||||||
|
"\n 0:"
|
||||||
|
"\n .ascii \"\\name\""
|
||||||
|
"\n .= 0b + name_length"
|
||||||
|
"\n .endm"
|
||||||
|
"\n"
|
||||||
|
"\n .macro file_entry perm, addr, time, name"
|
||||||
|
"\n .hword \\perm | 0x5e00, \\addr"
|
||||||
|
"\n .word \\time"
|
||||||
|
"\n 0:"
|
||||||
|
"\n .ascii \"\\name\""
|
||||||
|
"\n .= 0b + name_length"
|
||||||
|
"\n .endm"
|
||||||
|
"\n"
|
||||||
|
"\n .cpu cortex-m0plus"
|
||||||
|
"\n .thumb"
|
||||||
|
"\n"
|
||||||
|
"\n .section .flash.init, \"ax\""
|
||||||
|
"\n .balign 4096"
|
||||||
|
"\n .global rp2040_smart_flash_start"
|
||||||
|
"\n rp2040_smart_flash_start:"
|
||||||
|
"\n .ascii \"2040\""
|
||||||
|
"\n .byte 0b01101001"
|
||||||
|
"\n .ascii \"SMRT\""
|
||||||
|
"\n .byte 0x01, 0x10, 0"
|
||||||
|
"\n"
|
||||||
|
"\n .balign 4096, 0xff";
|
||||||
|
|
||||||
|
const char *postamble =
|
||||||
|
"\n"
|
||||||
|
"\n .balign 4096, 0xff"
|
||||||
|
"\n .global rp2040_smart_flash_end"
|
||||||
|
"\n rp2040_smart_flash_end:"
|
||||||
|
"\n"
|
||||||
|
"\n .end";
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void put_name(const char * cp)
|
||||||
|
{
|
||||||
|
putchar('"');
|
||||||
|
|
||||||
|
for (; *cp != 0; ++cp)
|
||||||
|
{
|
||||||
|
switch (*cp)
|
||||||
|
{
|
||||||
|
case '\"': printf("\\\""); break;
|
||||||
|
case '\'': printf("\\\'"); break;
|
||||||
|
case '\\': printf("\\\\"); break;
|
||||||
|
case '\a': printf("\\a"); break;
|
||||||
|
case '\b': printf("\\b"); break;
|
||||||
|
case '\n': printf("\\n"); break;
|
||||||
|
case '\t': printf("\\t"); break;
|
||||||
|
default:
|
||||||
|
if (iscntrl(*cp))
|
||||||
|
{
|
||||||
|
printf("\\%03o", *cp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
putchar(*cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
putchar('"');
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: copy_file
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int copy_file(int in_sector, const char * in_name)
|
||||||
|
{
|
||||||
|
FILE *data_file = fopen(path, "r");
|
||||||
|
struct stat file_stat;
|
||||||
|
int sector_len;
|
||||||
|
uint8_t *bp;
|
||||||
|
|
||||||
|
if (data_file == NULL) return in_sector;
|
||||||
|
|
||||||
|
lstat(path, &file_stat);
|
||||||
|
|
||||||
|
while (file_stat.st_size > 0)
|
||||||
|
{
|
||||||
|
bp = buffer;
|
||||||
|
sector_len = fread(buffer, 1, MAX_SECTOR_DATA, data_file);
|
||||||
|
|
||||||
|
file_stat.st_size -= sector_len;
|
||||||
|
|
||||||
|
if (file_stat.st_size > 0)
|
||||||
|
{
|
||||||
|
printf("\n sector %4d, dir, used=%d, next=%d",
|
||||||
|
in_sector,
|
||||||
|
sector_len,
|
||||||
|
in_sector + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\n sector %4d, file, used=%d",
|
||||||
|
in_sector,
|
||||||
|
sector_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
in_sector += 1;
|
||||||
|
|
||||||
|
for (; sector_len > 0; sector_len -= 8)
|
||||||
|
{
|
||||||
|
printf("\n .byte ");
|
||||||
|
|
||||||
|
for (int i = 0; i < 8 && i < sector_len; ++i)
|
||||||
|
{
|
||||||
|
if (i != 0) printf(", ");
|
||||||
|
|
||||||
|
printf("0x%02x", *bp++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: dir_entry
|
||||||
|
*
|
||||||
|
* On entry:
|
||||||
|
* The global "path" will be path to the prototype directory.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int scan_dir(int in_sector)
|
||||||
|
{
|
||||||
|
dir_item_t *an_item = NULL;
|
||||||
|
dir_item_t *prior_item = NULL;
|
||||||
|
int path_len = strlen(path);
|
||||||
|
int item_count = 0;
|
||||||
|
int sector = in_sector + 1;
|
||||||
|
DIR *input_dir;
|
||||||
|
struct dirent *a_dirent;
|
||||||
|
struct stat stat;
|
||||||
|
int name_len;
|
||||||
|
|
||||||
|
if (name_len > max_name_len)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "directory name to big. skipped. (%s)\n", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_dir = opendir(path);
|
||||||
|
|
||||||
|
if (input_dir == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"could not open directory %s %s\n",
|
||||||
|
path,
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scan directory to create directory entries */
|
||||||
|
|
||||||
|
while ((a_dirent = readdir(input_dir)) != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(a_dirent->d_name, ".") == 0) continue;
|
||||||
|
if (strcmp(a_dirent->d_name, "..") == 0) continue;
|
||||||
|
|
||||||
|
path[path_len] = '/';
|
||||||
|
|
||||||
|
strncpy(&path[path_len + 1], a_dirent->d_name, 4094 - path_len);
|
||||||
|
|
||||||
|
if (a_dirent->d_type == DT_DIR || a_dirent->d_type == DT_REG)
|
||||||
|
{
|
||||||
|
name_len = strlen(a_dirent->d_name);
|
||||||
|
|
||||||
|
if (name_len > max_name_len)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Skipped item. Name too long: %s\n", path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_count += 1;
|
||||||
|
|
||||||
|
an_item = malloc(sizeof(dir_item_t) + name_len + 1);
|
||||||
|
|
||||||
|
an_item->prior = prior_item;
|
||||||
|
prior_item = an_item;
|
||||||
|
|
||||||
|
strncpy(an_item->name, a_dirent->d_name, name_len);
|
||||||
|
|
||||||
|
an_item->init_sector = sector;
|
||||||
|
|
||||||
|
if (a_dirent->d_type == DT_DIR)
|
||||||
|
{
|
||||||
|
an_item->is_directory = true;
|
||||||
|
an_item->permissions = 0777;
|
||||||
|
|
||||||
|
sector = scan_dir(sector);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
an_item->is_directory = false;
|
||||||
|
an_item->permissions = 0666;
|
||||||
|
|
||||||
|
sector = copy_file(sector, an_item->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Skipped unusable item: %s\n", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
path[path_len] = 0;
|
||||||
|
|
||||||
|
closedir(input_dir);
|
||||||
|
|
||||||
|
/* Generate the directory sector for this directory. */
|
||||||
|
|
||||||
|
if (item_count > MAX_DIR_COUNT)
|
||||||
|
{
|
||||||
|
printf("\n sector %4d, dir, next=%d", in_sector, sector);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\n sector %4d, dir", in_sector);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (an_item != NULL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_DIR_COUNT && an_item != NULL; ++i)
|
||||||
|
{
|
||||||
|
if (an_item->is_directory)
|
||||||
|
{
|
||||||
|
printf("\n dir_entry 0%03o, 0x%04x, 0, ",
|
||||||
|
an_item->permissions,
|
||||||
|
an_item->init_sector);
|
||||||
|
|
||||||
|
put_name(an_item->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\n file_entry 0%03o, 0x%04x, 0, ",
|
||||||
|
an_item->permissions,
|
||||||
|
an_item->init_sector);
|
||||||
|
|
||||||
|
put_name(an_item->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
prior_item = an_item->prior;
|
||||||
|
free(an_item);
|
||||||
|
an_item = prior_item;
|
||||||
|
item_count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (an_item != NULL)
|
||||||
|
{
|
||||||
|
printf("\n sector %4d, dir, used=%d",
|
||||||
|
sector,
|
||||||
|
(item_count > MAX_DIR_COUNT) ? (sector + 1) : 0xffff);
|
||||||
|
|
||||||
|
sector += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: print_help
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void print_help(const char * name)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "\nusage: %s [-h][-n name-len] source-path\n\n", name);
|
||||||
|
|
||||||
|
fprintf(stderr, "-h : print this help and exit.\n\n");
|
||||||
|
|
||||||
|
fprintf(stderr, "-n : name length is the length of file names in\n");
|
||||||
|
fprintf(stderr, " the smart filesystem. It must match the\n");
|
||||||
|
fprintf(stderr, " CONFIG_SMARTFS_MAXNAMLEN with which NuttX was\n");
|
||||||
|
fprintf(stderr, " built. The default is %d.\n\n", max_name_len);
|
||||||
|
|
||||||
|
fprintf(stderr, "source-path is the path to a prototype directory tree\n");
|
||||||
|
fprintf(stderr, " that will be used to build the initial smart\n");
|
||||||
|
fprintf(stderr, " filesystem. Any items that are not normal\n");
|
||||||
|
fprintf(stderr, " files or directories will be ignored.\n\n");
|
||||||
|
|
||||||
|
fprintf(stderr, "Output is to stdout.\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
FILE *output_file;
|
||||||
|
const char *input_path = NULL;
|
||||||
|
|
||||||
|
/* parse arguments */
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i)
|
||||||
|
{
|
||||||
|
if (argv[i][0] == '-')
|
||||||
|
{
|
||||||
|
if (argv[i][1] == 'h')
|
||||||
|
{
|
||||||
|
print_help(argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[i][1] == 'n')
|
||||||
|
{
|
||||||
|
if (argv[i][2] == 0 && argc > i + 1)
|
||||||
|
{
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
if (!isdigit(argv[i][0]))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "invalid name length.\n");
|
||||||
|
print_help(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_name_len = atoi(argv[i]);
|
||||||
|
}
|
||||||
|
else if (isdigit(argv[i][2]))
|
||||||
|
{
|
||||||
|
max_name_len = atoi(&(argv[i][2]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "invalid name length.\n");
|
||||||
|
print_help(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unknown argument: %c\n", argv[i][1]);
|
||||||
|
print_help(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input_path == NULL)
|
||||||
|
{
|
||||||
|
input_path = argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_path == NULL)
|
||||||
|
{
|
||||||
|
print_help(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = malloc(MAX_SECTOR_DATA);
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "could not allocate file buffer.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(path, input_path, 4096);
|
||||||
|
|
||||||
|
/* remove any stray trailing slash characters. */
|
||||||
|
|
||||||
|
for (int c = strlen(path) - 1; c >= 0; --c)
|
||||||
|
{
|
||||||
|
if (path[c] != '/') break;
|
||||||
|
path[c] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output the defined constants */
|
||||||
|
|
||||||
|
printf("dir= 1\n"
|
||||||
|
"file= 2\n"
|
||||||
|
"name_length= %d\n",
|
||||||
|
max_name_len);
|
||||||
|
|
||||||
|
/* Output the macro definitions and block zero. */
|
||||||
|
|
||||||
|
puts(preamble);
|
||||||
|
|
||||||
|
/* Scan the prototype directory tree. */
|
||||||
|
|
||||||
|
scan_dir(root_sector);
|
||||||
|
|
||||||
|
/* Wrap things up. */
|
||||||
|
|
||||||
|
puts(postamble);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user