Added SMART flash filesystem to RP2040

This commit is contained in:
curuvar 2022-09-04 19:02:24 -04:00 committed by Alan Carvalho de Assis
parent fb852440af
commit 9ad75fd95d
37 changed files with 1980 additions and 34 deletions

View File

@ -689,3 +689,29 @@ config RP2040_BOARD_HAS_WS2812
---help---
See the Board Selection menu to configure the pins used
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

View File

@ -78,13 +78,17 @@ ifeq ($(CONFIG_ADC),y)
CHIP_CSRCS += rp2040_adc.c
endif
ifeq ($(CONFIG_RP2040_FLASH_BOOT),y)
ifneq ($(PICO_SDK_PATH),)
include chip/boot2/Make.defs
endif
ifeq ($(CONFIG_IEEE80211_INFINEON_CYW43439),y)
CHIP_CSRCS += rp2040_cyw43439.c
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

View 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

View 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);
}

View 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);

View 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);

View File

@ -71,6 +71,9 @@ Defconfigs
- nsh
Minimum configuration with NuttShell
- nsh_flash
NuttX shell with SMART flash filesystem.
- nshsram
Load NuttX binary to SRAM

View File

@ -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

View File

@ -82,11 +82,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram AT > flash
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -20,6 +20,7 @@
MEMORY
{
flash (rx) : ORIGIN = 0x10000000, LENGTH = 8192K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
}
@ -67,11 +68,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -70,6 +70,9 @@ Defconfigs
- nsh
Minimum configuration with NuttShell
- nsh_flash
NuttX shell with SMART flash filesystem.
- nshsram
Load NuttX binary to SRAM

View File

@ -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

View File

@ -82,11 +82,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram AT > flash
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -20,6 +20,7 @@
MEMORY
{
flash (rx) : ORIGIN = 0x10000000, LENGTH = 8192K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
}
@ -67,11 +68,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -65,6 +65,9 @@ Defconfigs
- nsh
Minimum configuration with NuttShell
- nsh_flash
NuttX shell with SMART flash filesystem.
- nshsram
Load NuttX binary to SRAM

View File

@ -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

View File

@ -82,11 +82,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram AT > flash
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -20,6 +20,7 @@
MEMORY
{
flash (rx) : ORIGIN = 0x10000000, LENGTH = 8192K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
}
@ -67,11 +68,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -475,7 +475,6 @@ if RP2040_I2S
endif # RP2040_I2S
#####################################################################
# WS2812 Configuration
#####################################################################
@ -501,3 +500,17 @@ if RP2040_BOARD_HAS_WS2812
such a pin.
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

View File

@ -27,6 +27,8 @@
#include <debug.h>
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <sys/stat.h>
#include <nuttx/fs/fs.h>
@ -74,6 +76,14 @@
#include "rp2040_ws2812.h"
#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
#define HAS_WHITE true
#else /* CONFIG_WS2812_HAS_WHITE */
@ -92,6 +102,10 @@ int rp2040_common_bringup(void)
{
int ret = 0;
#ifdef CONFIG_RP2040_FLASH_FILE_SYSTEM
struct mtd_dev_s *mtd_dev;
#endif
#ifdef CONFIG_RP2040_I2C_DRIVER
#ifdef CONFIG_RP2040_I2C0
ret = board_i2cdev_initialize(0);
@ -570,5 +584,76 @@ int rp2040_common_bringup(void)
}
#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;
}

View File

@ -69,6 +69,9 @@ Defconfigs
- nsh
Minimum configuration with NuttShell
- nsh_flash
NuttX shell with SMART flash filesystem.
- nshsram
Load NuttX binary to SRAM

View File

@ -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

View File

@ -82,11 +82,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram AT > flash
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -20,6 +20,7 @@
MEMORY
{
flash (rx) : ORIGIN = 0x10000000, LENGTH = 8192K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
}
@ -67,11 +68,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -72,6 +72,9 @@ Defconfigs
- nsh
Minimum configuration with NuttShell
- nsh_flash
NuttX shell with SMART flash filesystem.
- nshsram
Load NuttX binary to SRAM

View File

@ -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

View File

@ -82,11 +82,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram AT > flash
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -20,6 +20,7 @@
MEMORY
{
flash (rx) : ORIGIN = 0x10000000, LENGTH = 2048K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
}
@ -67,11 +68,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -71,6 +71,9 @@ Defconfigs
- nsh
Minimum configuration with NuttShell
- nsh_flash
NuttX shell with SMART flash filesystem.
- nshsram
Load NuttX binary to SRAM

View File

@ -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

View File

@ -82,11 +82,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram AT > flash
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -20,6 +20,7 @@
MEMORY
{
flash (rx) : ORIGIN = 0x10000000, LENGTH = 2048K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 264K
}
@ -67,11 +68,17 @@ SECTIONS
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.gnu.linkonce.d.*)
*(.ram_code.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > sram
.flash_section : {
. = ALIGN(4*1024);
*(.flash.*)
} > flash
.bss : {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)

View File

@ -5751,7 +5751,7 @@ static int smart_fsck_file(FAR struct smart_struct_s *dev,
/* next logical sector */
logsector = *(uint16_t *)chain->nextsector;
logsector = SMARTFS_NEXTSECTOR(chain);
}
while (logsector != 0xffff);
@ -5879,7 +5879,7 @@ static int smart_fsck_directory(FAR struct smart_struct_s *dev,
/* Check next sector recursively */
nextsector = *(uint16_t *)chain->nextsector;
nextsector = SMARTFS_NEXTSECTOR(chain);
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);
*(uint16_t *)chain->nextsector = 0xffff;
SMARTFS_SET_NEXTSECTOR(chain, 0xffff);
/* Set flag to relocate later */

View File

@ -197,8 +197,18 @@
# define offsetof(type, member) ((size_t) & (((type *)0)->member))
#endif
#define SMARTFS_NEXTSECTOR(h) (*((uint16_t *)h->nextsector))
#define SMARTFS_USED(h) (*((uint16_t *)h->used))
#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
# 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
#define CONFIG_SMARTFS_USE_SECTOR_BUFFER

View File

@ -45,6 +45,10 @@
#include "smartfs.h"
#ifdef CONFIG_DEBUG_FS_INFO
# include <stdio.h>
#endif
/****************************************************************************
* 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);
finfo("Reading %u bytes\n", (unsigned) buflen);
/* Recover our private data from the struct file instance */
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 */
bytesinsector = *((uint16_t *) header->used);
bytesinsector = SMARTFS_USED(header);
if (bytesinsector == SMARTFS_ERASEDSTATE_16BIT)
{
/* 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 */
#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;
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);
#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 */
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 */
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 */
@ -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 */
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,
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;
finfo("Wrote %u bytes\n", (unsigned) byteswritten);
errout_with_semaphore:
smartfs_semgive(fs);
return ret;
@ -1325,6 +1357,7 @@ static int smartfs_readdir(FAR struct inode *mountpt,
entrysize = sizeof(struct smartfs_entry_header_s) +
fs->fs_llformat.namesize;
while (sdir->fs_currsector != SMARTFS_ERASEDSTATE_16BIT)
{
/* Read the logical sector */
@ -1341,7 +1374,11 @@ static int smartfs_readdir(FAR struct inode *mountpt,
/* 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 */
@ -1350,24 +1387,35 @@ static int smartfs_readdir(FAR struct inode *mountpt,
/* 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) ==
(SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) ||
((entry->flags & SMARTFS_DIRENT_ACTIVE) !=
(SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
#endif
{
/* This entry isn't valid, skip it */
sdir->fs_curroffset += entrysize;
entry = (struct smartfs_entry_header_s *)
&fs->fs_rwbuffer[sdir->fs_curroffset];
continue;
}
/* 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) ==
SMARTFS_DIRENT_TYPE_DIR)
#endif
{
dentry->d_type = DTYPE_DIRECTORY;
}

View File

@ -714,11 +714,11 @@ int smartfs_finddirentry(struct smartfs_mountpt_s *fs,
* to next sector
*/
if (*((FAR uint16_t *)header->used) !=
if (SMARTFS_USED(header) !=
SMARTFS_ERASEDSTATE_16BIT)
{
direntry->datlen +=
*((uint16_t *)header->used);
SMARTFS_USED(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. */
SMARTFS_NEXTSECTOR(header) = nextsector;
SMARTFS_SET_NEXTSECTOR(header, nextsector);
readwrite.offset = offsetof(struct smartfs_chain_header_s,
nextsector);
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 */
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
{
*((uint16_t *)header->used) += sf->byteswritten;
SMARTFS_SET_USED(header, SMARTFS_USED(header)
+ sf->byteswritten);
}
/* 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 */
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
{
*((uint16_t *) header->used) += sf->byteswritten;
SMARTFS_SET_USED(header, SMARTFS_USED(header)
+ sf->byteswritten);
}
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];
destsize = fs->fs_llformat.availbytes - offset;
*((uint16_t *)header->used) = remaining;
*((uint16_t *)header->nextsector) = SMARTFS_ERASEDSTATE_16BIT;
SMARTFS_SET_USED(header, remaining);
SMARTFS_SET_NEXTSECTOR(header, SMARTFS_ERASEDSTATE_16BIT);
remaining = 0;
}
@ -1879,8 +1882,9 @@ int smartfs_shrinkfile(FAR struct smartfs_mountpt_s *fs,
destsize = fs->fs_llformat.availbytes - offset;
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);
@ -2027,7 +2031,7 @@ int smartfs_extendfile(FAR struct smartfs_mountpt_s *fs,
/* Copy the new sector to the old one and chain it */
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 */
@ -2083,7 +2087,7 @@ int smartfs_extendfile(FAR struct smartfs_mountpt_s *fs,
/* Copy the new sector to the old one and chain it */
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,
nextsector);

View 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;
}