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---
|
||||
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
|
||||
|
@ -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
|
||||
|
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
|
||||
Minimum configuration with NuttShell
|
||||
|
||||
- nsh_flash
|
||||
NuttX shell with SMART flash filesystem.
|
||||
|
||||
- nshsram
|
||||
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(.);
|
||||
*(.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.*)
|
||||
|
@ -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.*)
|
||||
|
@ -70,6 +70,9 @@ Defconfigs
|
||||
- nsh
|
||||
Minimum configuration with NuttShell
|
||||
|
||||
- nsh_flash
|
||||
NuttX shell with SMART flash filesystem.
|
||||
|
||||
- nshsram
|
||||
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(.);
|
||||
*(.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.*)
|
||||
|
@ -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.*)
|
||||
|
@ -65,6 +65,9 @@ Defconfigs
|
||||
- nsh
|
||||
Minimum configuration with NuttShell
|
||||
|
||||
- nsh_flash
|
||||
NuttX shell with SMART flash filesystem.
|
||||
|
||||
- nshsram
|
||||
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(.);
|
||||
*(.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.*)
|
||||
|
@ -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.*)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -69,6 +69,9 @@ Defconfigs
|
||||
- nsh
|
||||
Minimum configuration with NuttShell
|
||||
|
||||
- nsh_flash
|
||||
NuttX shell with SMART flash filesystem.
|
||||
|
||||
- nshsram
|
||||
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(.);
|
||||
*(.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.*)
|
||||
|
@ -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.*)
|
||||
|
@ -72,6 +72,9 @@ Defconfigs
|
||||
- nsh
|
||||
Minimum configuration with NuttShell
|
||||
|
||||
- nsh_flash
|
||||
NuttX shell with SMART flash filesystem.
|
||||
|
||||
- nshsram
|
||||
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(.);
|
||||
*(.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.*)
|
||||
|
@ -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.*)
|
||||
|
@ -71,6 +71,9 @@ Defconfigs
|
||||
- nsh
|
||||
Minimum configuration with NuttShell
|
||||
|
||||
- nsh_flash
|
||||
NuttX shell with SMART flash filesystem.
|
||||
|
||||
- nshsram
|
||||
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(.);
|
||||
*(.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.*)
|
||||
|
@ -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.*)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
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