diff --git a/boards/arm/stm32wl5/nucleo-wl55jc/Kconfig b/boards/arm/stm32wl5/nucleo-wl55jc/Kconfig index 1d568310d2b..a65425890de 100644 --- a/boards/arm/stm32wl5/nucleo-wl55jc/Kconfig +++ b/boards/arm/stm32wl5/nucleo-wl55jc/Kconfig @@ -17,4 +17,262 @@ config ARCH_BOARD_NUCLEO_WL55JC_DEMO_LED_IRQ comment "[demo] LED on button interrupt requires NSH_ARCHINIT" depends on !NSH_ARCHINIT || !ARCH_BUTTONS +menuconfig ARCH_BOARD_FLASH_MOUNT + bool "Enable FLASH partitioning and mounting" + depends on !DISABLE_MOUNTPOINT + select MTD + select MTD_PROGMEM + select MTD_PARTITION + select MTD_PARTITION_NAMES + select FS_PROCFS + default n + ---help--- + When enabled, you will be able to configure partition table + for onboard FLASH memory to create and mount flash filesystems. + All partition sizes are specified in PAGE_SIZE size. On + STM32WL5 page size is always 2048. + + On STM32WL55JC there are 128 pages of flash memory. Size of + all configured partitions shall not exceed 128. In fact, it + should be equal to 128 or else you will simply have unused + space on flash. Even if you want some raw flash access you + should specify this partition in table and select fs_raw. + + By default there are only 4 partitions defined, if you need + more, you can define more in Kconfig and stm32_flash.c files. + +comment "FLASH partitioning and mounting requires !DISABLE_MOUNTPOINT" + depends on DISABLE_MOUNTPOINT + +if ARCH_BOARD_FLASH_MOUNT + +config ARCH_BOARD_FLASH_CPU1_PROG_SIZE + int "Size reserved for CPU1 program code" + default 127 + ---help--- + How much memory to reserve for CPU1 program code. This should + specified as other partitions will be created at offset to + this partition. + +config ARCH_BOARD_FLASH_CPU2_PROG_SIZE + int "Size reserved for CPU2 program code" + default 0 + ---help--- + How much memory to reserve for CPU2 program code. If you use + dual CPU you should specify how much memory you want to + reserve for code for second CPU. User partition will be + created at this offset. If you don't use CPU2, set this to 0. + +config ARCH_BOARD_FLASH_PART1_SIZE + int "Size of user partition 1" + default 1 + ---help--- + Size of partition specified in PAGE_SIZE. Page size on + stm32wl5xxx is always 2048. + +config ARCH_BOARD_FLASH_PART1_NAME + string "Name of user partition 1" + default "part1" + ---help--- + MTD partition name, this can be later read by MTD API, + or it can also be read from /proc/partitions to easily + identify partitions. + +config ARCH_BOARD_FLASH_PART1_MNT + string "Mount point for user partition 1" + default "/mnt/part1" + ---help--- + Directory where filesystem should be mounted. + + Note: not all filesystems can be mounted. rawfs and + mtdconfig for example cannot be mounted. In that case + this config will be ignored. + +config ARCH_BOARD_FLASH_PART1_FS + string + default "rawfs" if ARCH_BOARD_FLASH_PART1_FS_RAWFS + default "nxffs" if ARCH_BOARD_FLASH_PART1_FS_NXFFS + default "smartfs" if ARCH_BOARD_FLASH_PART1_FS_SMARTFS + default "mtdconfig" if ARCH_BOARD_FLASH_PART1_FS_MTDCONFIG + +choice + prompt "Filesystem of user partition 1" + default ARCH_BOARD_FLASH_PART1_FS_RAW + +config ARCH_BOARD_FLASH_PART1_FS_RAWFS + bool "rawfs" + ---help--- + Raw block device /dev/mtdblockN will be available to use + with standard open(2)/fopen(3) functions. + +config ARCH_BOARD_FLASH_PART1_FS_NXFFS + select FS_NXFFS + bool "nxffs" + ---help--- + Partition will be used as nxffs. Only one nxffs partition + can be enabled at one given time! + +config ARCH_BOARD_FLASH_PART1_FS_SMARTFS + select FS_SMARTFS + select MTD_SMART + bool "smartfs" + ---help--- + Partition will be used as smartfs. After first flash, you + will have to format partition with "mksmartfs /dev/smartN" + command. This has to be done only once unless you change + partition table that would affect offsets and/or sizes. + Programmers (like openocd) should not touch this memory + when flashing new software, unless you exceeded reserved + memory for program code. + + Smartfs uses quite substential ammount of FLASH data to + get to workable state and mount. Looks like 8 page sizes + is absolute minimum (so a 16KiB!). + +config ARCH_BOARD_FLASH_PART1_FS_MTDCONFIG + select MTD_CONFIG + bool "mtdconfig" + ---help--- + Purpose build filesystem to hold application's configuration. + It's not a filesystem per se, as it cannot be mounted and + setting and retrieving configuration is done via ioctl(2) + calls. + +endchoice # Filesystem of user partition 1 + +config ARCH_BOARD_FLASH_PART2_SIZE + int "Size of user partition 2" + default 0 + +if ARCH_BOARD_FLASH_PART2_SIZE > 0 + +config ARCH_BOARD_FLASH_PART2_NAME + string "Name of user partition 2" + default "part2" + +config ARCH_BOARD_FLASH_PART2_MNT + string "Mount point for user partition 2" + default "/mnt/part2" + +config ARCH_BOARD_FLASH_PART2_FS + string + default "rawfs" if ARCH_BOARD_FLASH_PART2_FS_RAWFS + default "nxffs" if ARCH_BOARD_FLASH_PART2_FS_NXFFS + default "smartfs" if ARCH_BOARD_FLASH_PART2_FS_SMARTFS + default "mtdconfig" if ARCH_BOARD_FLASH_PART2_FS_MTDCONFIG + +choice + prompt "Filesystem of user partition 2" + default ARCH_BOARD_FLASH_PART2_FS_RAW + +config ARCH_BOARD_FLASH_PART2_FS_RAWFS + bool "rawfs" + +config ARCH_BOARD_FLASH_PART2_FS_NXFFS + select FS_NXFFS + bool "nxffs" + +config ARCH_BOARD_FLASH_PART2_FS_SMARTFS + select FS_SMARTFS + select MTD_SMART + bool "smartfs" + +config ARCH_BOARD_FLASH_PART2_FS_MTDCONFIG + select MTD_CONFIG + bool "mtdconfig" + +endchoice # Filesystem of user partition 2 + +config ARCH_BOARD_FLASH_PART3_SIZE + int "Size of user partition 3" + default 0 + +if ARCH_BOARD_FLASH_PART3_SIZE > 0 + +config ARCH_BOARD_FLASH_PART3_NAME + string "Name of user partition 3" + default "part3" + +config ARCH_BOARD_FLASH_PART3_MNT + string "Mount point for user partition 3" + default "/mnt/part3" + +config ARCH_BOARD_FLASH_PART3_FS + string + default "rawfs" if ARCH_BOARD_FLASH_PART3_FS_RAWFS + default "nxffs" if ARCH_BOARD_FLASH_PART3_FS_NXFFS + default "smartfs" if ARCH_BOARD_FLASH_PART3_FS_SMARTFS + default "mtdconfig" if ARCH_BOARD_FLASH_PART3_FS_MTDCONFIG + +choice + prompt "Filesystem of user partition 3" + default ARCH_BOARD_FLASH_PART3_FS_RAW + +config ARCH_BOARD_FLASH_PART3_FS_RAWFS + bool "rawfs" + +config ARCH_BOARD_FLASH_PART3_FS_NXFFS + select FS_NXFFS + bool "nxffs" + +config ARCH_BOARD_FLASH_PART3_FS_SMARTFS + select FS_SMARTFS + select MTD_SMART + bool "smartfs" + +config ARCH_BOARD_FLASH_PART3_FS_MTDCONFIG + select MTD_CONFIG + bool "mtdconfig" + +endchoice # Filesystem of user partition 3 + +config ARCH_BOARD_FLASH_PART4_SIZE + int "Size of user partition 4" + default 0 + +if ARCH_BOARD_FLASH_PART4_SIZE > 0 + +config ARCH_BOARD_FLASH_PART4_NAME + string "Name of user partition 4" + default "part4" + +config ARCH_BOARD_FLASH_PART4_MNT + string "Mount point for user partition 4" + default "/mnt/part4" + +config ARCH_BOARD_FLASH_PART4_FS + string + default "rawfs" if ARCH_BOARD_FLASH_PART4_FS_RAWFS + default "nxffs" if ARCH_BOARD_FLASH_PART4_FS_NXFFS + default "smartfs" if ARCH_BOARD_FLASH_PART4_FS_SMARTFS + default "mtdconfig" if ARCH_BOARD_FLASH_PART4_FS_MTDCONFIG + +choice + prompt "Filesystem of user partition 4" + default ARCH_BOARD_FLASH_PART4_FS_RAW + +config ARCH_BOARD_FLASH_PART4_FS_RAWFS + bool "rawfs" + +config ARCH_BOARD_FLASH_PART4_FS_NXFFS + select FS_NXFFS + bool "nxffs" + +config ARCH_BOARD_FLASH_PART4_FS_SMARTFS + select FS_SMARTFS + select MTD_SMART + bool "smartfs" + +config ARCH_BOARD_FLASH_PART4_FS_MTDCONFIG + select MTD_CONFIG + bool "mtdconfig" + +endchoice # Filesystem of user partition 4 + +endif # ARCH_BOARD_FLASH_PART2_SIZE > 0 +endif # ARCH_BOARD_FLASH_PART3_SIZE > 0 +endif # ARCH_BOARD_FLASH_PART4_SIZE > 0 + +endif # ARCH_BOARD_FLASH_MOUNT + endif # ARCH_BOARD_NUCLEO_WL55JC diff --git a/boards/arm/stm32wl5/nucleo-wl55jc/configs/demo/defconfig b/boards/arm/stm32wl5/nucleo-wl55jc/configs/demo/defconfig index 49e2feacd3b..ba1b1efb255 100644 --- a/boards/arm/stm32wl5/nucleo-wl55jc/configs/demo/defconfig +++ b/boards/arm/stm32wl5/nucleo-wl55jc/configs/demo/defconfig @@ -8,6 +8,22 @@ # CONFIG_STANDARD_SERIAL is not set CONFIG_ARCH="arm" CONFIG_ARCH_BOARD="nucleo-wl55jc" +CONFIG_ARCH_BOARD_FLASH_CPU1_PROG_SIZE=116 +CONFIG_ARCH_BOARD_FLASH_MOUNT=y +CONFIG_ARCH_BOARD_FLASH_PART1_MNT="" +CONFIG_ARCH_BOARD_FLASH_PART1_NAME="raw" +CONFIG_ARCH_BOARD_FLASH_PART2_FS_SMARTFS=y +CONFIG_ARCH_BOARD_FLASH_PART2_MNT="/mnt/smart" +CONFIG_ARCH_BOARD_FLASH_PART2_NAME="smartie" +CONFIG_ARCH_BOARD_FLASH_PART2_SIZE=8 +CONFIG_ARCH_BOARD_FLASH_PART3_FS_NXFFS=y +CONFIG_ARCH_BOARD_FLASH_PART3_MNT="/mnt/nx" +CONFIG_ARCH_BOARD_FLASH_PART3_NAME="nxf" +CONFIG_ARCH_BOARD_FLASH_PART3_SIZE=2 +CONFIG_ARCH_BOARD_FLASH_PART4_FS_MTDCONFIG=y +CONFIG_ARCH_BOARD_FLASH_PART4_MNT="" +CONFIG_ARCH_BOARD_FLASH_PART4_NAME="config" +CONFIG_ARCH_BOARD_FLASH_PART4_SIZE=1 CONFIG_ARCH_BOARD_NUCLEO_WL55JC=y CONFIG_ARCH_BOARD_NUCLEO_WL55JC_DEMO_LED_IRQ=y CONFIG_ARCH_BUTTONS=y @@ -24,12 +40,15 @@ CONFIG_INPUT=y CONFIG_INPUT_BUTTONS=y CONFIG_INPUT_BUTTONS_LOWER=y CONFIG_LPUART1_SERIAL_CONSOLE=y +CONFIG_MTD_CONFIG_NAMED=y +CONFIG_MTD_SMART_SECTOR_SIZE=2048 CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y CONFIG_RAM_SIZE=32768 CONFIG_RAM_START=0x20000000 CONFIG_RAW_BINARY=y CONFIG_STM32WL5_LPUART1=y +CONFIG_SYSTEM_CFGDATA=y CONFIG_SYSTEM_NSH=y CONFIG_USERLED=y CONFIG_USERLED_LOWER=y diff --git a/boards/arm/stm32wl5/nucleo-wl55jc/src/Makefile b/boards/arm/stm32wl5/nucleo-wl55jc/src/Makefile index 9532b20cd41..16a184a9378 100644 --- a/boards/arm/stm32wl5/nucleo-wl55jc/src/Makefile +++ b/boards/arm/stm32wl5/nucleo-wl55jc/src/Makefile @@ -30,4 +30,8 @@ ifeq ($(CONFIG_ARCH_BUTTONS),y) CSRCS += stm32_buttons.c endif +ifeq ($(CONFIG_ARCH_BOARD_FLASH_MOUNT),y) +CSRCS += stm32_flash.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/stm32wl5/nucleo-wl55jc/src/nucleo-wl55jc.h b/boards/arm/stm32wl5/nucleo-wl55jc/src/nucleo-wl55jc.h index a9585eb37d8..e3b7b863380 100644 --- a/boards/arm/stm32wl5/nucleo-wl55jc/src/nucleo-wl55jc.h +++ b/boards/arm/stm32wl5/nucleo-wl55jc/src/nucleo-wl55jc.h @@ -74,4 +74,14 @@ void board_leds_initialize(void); +/**************************************************************************** + * Name: stm32wl5_flash_init + * + * Description: + * Initialize on-board FLASH partition table + * + ****************************************************************************/ + +int stm32wl5_flash_init(void); + #endif /* __BOARDS_ARM_STM32WL5_NUCLEO_WL55JC_SRC_NUCLEO_WL55JC_H */ diff --git a/boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_appinit.c b/boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_appinit.c index 5da9d754c68..4955cf1381e 100644 --- a/boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_appinit.c +++ b/boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_appinit.c @@ -116,6 +116,16 @@ int board_app_initialize(uintptr_t arg) } #endif +#if defined(CONFIG_ARCH_BOARD_ENABLE_FLASH_MOUNT) + /* Register partition table for on-board FLASH memory */ + + ret = stm32wl5_flash_init(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32wl5_flash_init() failed: %d\n", ret); + } +#endif + return ret; } diff --git a/boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_flash.c b/boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_flash.c new file mode 100644 index 00000000000..463f84a9e01 --- /dev/null +++ b/boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_flash.c @@ -0,0 +1,297 @@ +/**************************************************************************** + * boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_flash.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 +#include +#include +#include +#include +#include + +#include +#include + +#include "nucleo-wl55jc.h" +#include "hardware/stm32wl5_flash.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#if (CONFIG_ARCH_BOARD_FLASH_CPU1_PROG_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_CPU2_PROG_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_PART1_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_PART2_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_PART3_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_PART4_SIZE) > 128 +# error "Sum of all flash pertitions cannot be bigger than 128" +#endif + +#if (CONFIG_ARCH_BOARD_FLASH_CPU1_PROG_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_CPU2_PROG_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_PART1_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_PART2_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_PART3_SIZE + \ + CONFIG_ARCH_BOARD_FLASH_PART4_SIZE) < 128 +# warning "There is unused space on flash" +#endif + +#define FLASH_PAGE_SIZE STM32WL5_FLASH_PAGESIZE + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +struct part_table +{ + int size; /* partition size in pages */ + const char *name; /* name of the partition */ + const char *mnt; /* mount point for the partition */ + const char *fs; /* fs type (smart, raw, nxffs) */ +}; + +/* partition table, first entry *must always* be program flash memory */ + +static const struct part_table part_table[] = +{ + { + .size = CONFIG_ARCH_BOARD_FLASH_CPU1_PROG_SIZE, + .name = "cpu1-progmem", + .mnt = NULL, + .fs = "rawfs" + }, + +#if CONFIG_ARCH_BOARD_FLASH_CPU2_PROG_SIZE > 0 + .size = CONFIG_ARCH_BOARD_FLASH_CPU2_PROG_SIZE, + .name = "cpu2-progmem", + .mnt = NULL, + .fs = "rawfs" +#endif + + { + .size = CONFIG_ARCH_BOARD_FLASH_PART1_SIZE, + .name = CONFIG_ARCH_BOARD_FLASH_PART1_NAME, + .mnt = CONFIG_ARCH_BOARD_FLASH_PART1_MNT, + .fs = CONFIG_ARCH_BOARD_FLASH_PART1_FS + }, + +#if CONFIG_ARCH_BOARD_FLASH_PART2_SIZE > 0 + { + .size = CONFIG_ARCH_BOARD_FLASH_PART2_SIZE, + .name = CONFIG_ARCH_BOARD_FLASH_PART2_NAME, + .mnt = CONFIG_ARCH_BOARD_FLASH_PART2_MNT, + .fs = CONFIG_ARCH_BOARD_FLASH_PART2_FS + }, +#endif /* CONFIG_ARCH_BOARD_FLASH_PART2_SIZE */ + +#if CONFIG_ARCH_BOARD_FLASH_PART3_SIZE > 0 + { + .size = CONFIG_ARCH_BOARD_FLASH_PART3_SIZE, + .name = CONFIG_ARCH_BOARD_FLASH_PART3_NAME, + .mnt = CONFIG_ARCH_BOARD_FLASH_PART3_MNT, + .fs = CONFIG_ARCH_BOARD_FLASH_PART3_FS + }, +#endif /* CONFIG_ARCH_BOARD_FLASH_PART3_SIZE */ + +#if CONFIG_ARCH_BOARD_FLASH_PART4_SIZE > 0 + { + .size = CONFIG_ARCH_BOARD_FLASH_PART4_SIZE, + .name = CONFIG_ARCH_BOARD_FLASH_PART4_NAME, + .mnt = CONFIG_ARCH_BOARD_FLASH_PART4_MNT, + .fs = CONFIG_ARCH_BOARD_FLASH_PART4_FS + }, +#endif /* CONFIG_ARCH_BOARD_FLASH_PART4_SIZE */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int stm32wl5_flash_init(void) +{ + FAR struct mtd_dev_s *mtd; + FAR struct mtd_dev_s *mtd_part; + int offset; + int mtdconfig_minor; + int mtdblk_minor; + int smart_minor; + int nxf_minor; + int ret; + int i; + + /* create an instance of the stm32 flash program memory device driver */ + + if ((mtd = progmem_initialize()) == NULL) + { + ferr("ERROR: progmem_initialize failed %d\n", errno); + return -1; + } + + /* create partitions, this does not actually write anything + * to flash memory, we only create partition table in ram + */ + + mtdconfig_minor = 0; + mtdblk_minor = 0; + smart_minor = 0; + nxf_minor = 0; + offset = 0; + + for (i = 0; i != sizeof(part_table) / sizeof(struct part_table); i++) + { + int size; + const char *name; + const char *mnt; + const char *fs; + + size = part_table[i].size; + name = part_table[i].name; + mnt = part_table[i].mnt; + fs = part_table[i].fs; + + finfo("[%s] creating partition, size: %d, fs: %s, offset: %d\n", + name, size, fs, offset); + + /* create mtd parition */ + + mtd_part = mtd_partition(mtd, offset, size); + + /* calculate offset for next partition */ + + offset += size; + + if (mtd_part == NULL) + { + ferr("[%s]ERROR: mtd_partition() failed %d\n", name, errno); + continue; + } + + if (mtd_setpartitionname(mtd_part, name)) + { + ferr("[%s]ERROR: mtd_setpartitionname() failed %d\n", name, errno); + continue; + } + + /* initialize filesystems */ + + if (strcmp(fs, "rawfs") == 0) + { + /* for raw fs just create mtdblock using ftl */ + + if ((ret = ftl_initialize(mtdblk_minor, mtd_part))) + { + ferr("[%s]ERROR: ftl_initialize failed %d\n", name, ret); + continue; + } + + mtdblk_minor++; + } + +#if defined(CONFIG_FS_NXFFS) + else if (strcmp(fs, "nxffs") == 0) + { + if (nxf_minor) + { + ferr("[%s]ERROR: only 1 nxffs is allowed, ignoring\n", name); + continue; + } + + /* attach mtd to nxffs */ + + if ((ret = nxffs_initialize(mtd_part))) + { + ferr("[%s]ERROR: nxffs_initialize failed %d\n", name, ret); + continue; + } + + /* mount nxffs */ + + if ((ret = nx_mount(NULL, mnt, "nxffs", 0, NULL))) + { + ferr("[%s]ERROR: nx_mount failed: %d", name, ret); + continue; + } + + nxf_minor++; + } +#endif + +#if defined(CONFIG_FS_SMARTFS) + else if (strcmp(fs, "smartfs") == 0) + { + /* attach mtd to smartfs */ + + char src[32]; + snprintf(src, sizeof(src), "/dev/smart%d", smart_minor); + + if ((ret = smart_initialize(smart_minor, mtd_part, NULL))) + { + ferr("[%s]ERROR: smart_initialize() failed %d\n", name, ret); + continue; + } + + /* mount smartfs */ + + if ((ret = nx_mount(src, mnt, "smartfs", 0, NULL))) + { + ferr("[%s]ERROR: nx_mount failed: %d\n", name, ret); + if (ret == ENODEV) + { + syslog(LOG_INFO, "[%s] mtd, smartfs seems unformated. " + "Did you run 'mksmartfs %s'?\n", name, src); + } + + continue; + } + + smart_minor++; + } +#endif + +#if defined(CONFIG_MTD_CONFIG) + else if (strcmp(fs, "mtdconfig") == 0) + { + if (mtdconfig_minor) + { + ferr("[%s]ERROR: only 1 mtdconfig is allowed, ignoring\n", + name); + continue; + } + + /* attach mtd to mtdconfig driver */ + + if (mtdconfig_register(mtd_part) != 0) + { + ferr("[%s]ERROR: mtdconfig_register() failed %d\n", + name, errno); + continue; + } + + mtdconfig_minor++; + } +#endif + } + + return 0; +}