You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/06/15 12:29:22 UTC

[incubator-nuttx] branch master updated (845e259ac7 -> 4d4566e9ed)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


    from 845e259ac7 net/tcp: d_appdata should remove the tcp specific option field
     new 5490f8964f stm32wl5: add support for internal FLASH
     new 4d4566e9ed nucleo-wl55jc: add partition table support for progmem FLASH

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 Documentation/platforms/arm/stm32wl5/index.rst     |  10 +
 arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h    | 250 +++++++++--------
 arch/arm/src/stm32wl5/stm32wl5_flash.c             | 166 +++++++-----
 arch/arm/src/stm32wl5/stm32wl5_flash.h             |   8 +-
 boards/arm/stm32wl5/nucleo-wl55jc/Kconfig          | 258 ++++++++++++++++++
 .../stm32wl5/nucleo-wl55jc/configs/demo/defconfig  |  19 ++
 boards/arm/stm32wl5/nucleo-wl55jc/src/Makefile     |   4 +
 .../arm/stm32wl5/nucleo-wl55jc/src/nucleo-wl55jc.h |  10 +
 .../arm/stm32wl5/nucleo-wl55jc/src/stm32_appinit.c |  10 +
 .../arm/stm32wl5/nucleo-wl55jc/src/stm32_flash.c   | 297 +++++++++++++++++++++
 10 files changed, 832 insertions(+), 200 deletions(-)
 create mode 100644 boards/arm/stm32wl5/nucleo-wl55jc/src/stm32_flash.c


[incubator-nuttx] 01/02: stm32wl5: add support for internal FLASH

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 5490f8964f02cb66af9c8afd17c8355c0328f90d
Author: Michał Łyszczek <mi...@bofc.pl>
AuthorDate: Tue Jun 14 00:32:11 2022 +0200

    stm32wl5: add support for internal FLASH
    
    This patch adds corrected implementation of FLASH memory to be used
    with progmem driver for use with mtd filesystems like nxffs or smartfs.
    
    Signed-off-by: Michał Łyszczek <mi...@bofc.pl>
---
 Documentation/platforms/arm/stm32wl5/index.rst  |  10 +
 arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h | 250 ++++++++++++------------
 arch/arm/src/stm32wl5/stm32wl5_flash.c          | 166 +++++++++-------
 arch/arm/src/stm32wl5/stm32wl5_flash.h          |   8 +-
 4 files changed, 234 insertions(+), 200 deletions(-)

diff --git a/Documentation/platforms/arm/stm32wl5/index.rst b/Documentation/platforms/arm/stm32wl5/index.rst
index 3099ebaa8f..798114e211 100644
--- a/Documentation/platforms/arm/stm32wl5/index.rst
+++ b/Documentation/platforms/arm/stm32wl5/index.rst
@@ -40,6 +40,7 @@ RCC         Yes      All registers defined, not all peripherals enabled
 SYSCFG      Yes      All registers defined, GPIO EXTI works, remapping not tested
 USART       Yes
 LPUART      Yes      full speed with HSE works, low power mode with LSE not implemented
+FLASH       Yes      Progmem imlementation - mtd filesystems like smartfs or nxffs work
 DMA         No
 SRAM2       No
 SPI         No
@@ -133,6 +134,15 @@ interrupt first goes through EXTI and is then forwarded to main NVIC.
 
 EXTI for gpio can be enabled via `stm32wl5_gpiosetevent` function.
 
+FLASH
+-----
+
+Place where program code lives. Part of flash can also be used to create
+small filesystems like nxffs or smartfs to hold persistant data between
+reboots without the need of attaching external flash or mmc card. Since
+flash has limited number of erases (writes) it's best to hold there only
+data that is no frequently updated (so, configuration is ok, logs are not).
+
 Supported Boards
 ================
 
diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h
index 757f7e689a..26ca718fe4 100644
--- a/arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h
+++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h
@@ -45,8 +45,6 @@
  * STM32WL5xxx has only single bank flash and page size 2KiB
  */
 
-#define _K(x) ((x)*1024)
-
 #if !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_DEFAULT) && \
     !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_8) && \
     !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_B) && \
@@ -104,7 +102,7 @@
 #  error "unknown flash configuration!"
 #endif
 
-#define STM32WL5_FLASH_SIZE           (STM32WL5_FLASH_NPAGES * STM32WL5_FLASH_PAGESIZE)
+#define STM32WL5_FLASH_SIZE          (STM32WL5_FLASH_NPAGES * STM32WL5_FLASH_PAGESIZE)
 
 /* Register Offsets *********************************************************/
 
@@ -131,114 +129,114 @@
 
 /* Register Addresses *******************************************************/
 
-#define STM32WL5_FLASH_ACR       (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ACR_OFFSET)
-#define STM32WL5_FLASH_ACR2      (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ACR2_OFFSET)
-#define STM32WL5_FLASH_KEYR      (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_KEYR_OFFSET)
-#define STM32WL5_FLASH_OPTKEYR   (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_OPTKEYR_OFFSET)
-#define STM32WL5_FLASH_SR        (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SR_OFFSET)
-#define STM32WL5_FLASH_CR        (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_CR_OFFSET)
-#define STM32WL5_FLASH_ECCR      (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ECCR_OFFSET)
-#define STM32WL5_FLASH_OPTR      (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_OPTR_OFFSET)
-#define STM32WL5_FLASH_PCROP1ASR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1ASR_OFFSET)
-#define STM32WL5_FLASH_PCROP1AER (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1AER_OFFSET)
-#define STM32WL5_FLASH_WRP1AR    (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_WRP1AR_OFFSET)
-#define STM32WL5_FLASH_WRP1BR    (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_WRP1BR_OFFSET)
-#define STM32WL5_FLASH_PCROP1BSR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1BSR_OFFSET)
-#define STM32WL5_FLASH_PCROP1BER (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1BER_OFFSET)
-#define STM32WL5_FLASH_IPCCBR    (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_IPCCBR_OFFSET)
-#define STM32WL5_FLASH_C2ACR     (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2ACR_OFFSET)
-#define STM32WL5_FLASH_C2SR      (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2SR_OFFSET)
-#define STM32WL5_FLASH_C2CR      (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2CR_OFFSET)
-#define STM32WL5_FLASH_SFR       (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SFR_OFFSET)
-#define STM32WL5_FLASH_SRRVR     (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SRRVR_OFFSET)
+#define STM32WL5_FLASH_ACR          (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ACR_OFFSET)
+#define STM32WL5_FLASH_ACR2         (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ACR2_OFFSET)
+#define STM32WL5_FLASH_KEYR         (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_KEYR_OFFSET)
+#define STM32WL5_FLASH_OPTKEYR      (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_OPTKEYR_OFFSET)
+#define STM32WL5_FLASH_SR           (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SR_OFFSET)
+#define STM32WL5_FLASH_CR           (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_CR_OFFSET)
+#define STM32WL5_FLASH_ECCR         (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ECCR_OFFSET)
+#define STM32WL5_FLASH_OPTR         (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_OPTR_OFFSET)
+#define STM32WL5_FLASH_PCROP1ASR    (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1ASR_OFFSET)
+#define STM32WL5_FLASH_PCROP1AER    (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1AER_OFFSET)
+#define STM32WL5_FLASH_WRP1AR       (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_WRP1AR_OFFSET)
+#define STM32WL5_FLASH_WRP1BR       (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_WRP1BR_OFFSET)
+#define STM32WL5_FLASH_PCROP1BSR    (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1BSR_OFFSET)
+#define STM32WL5_FLASH_PCROP1BER    (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1BER_OFFSET)
+#define STM32WL5_FLASH_IPCCBR       (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_IPCCBR_OFFSET)
+#define STM32WL5_FLASH_C2ACR        (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2ACR_OFFSET)
+#define STM32WL5_FLASH_C2SR         (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2SR_OFFSET)
+#define STM32WL5_FLASH_C2CR         (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2CR_OFFSET)
+#define STM32WL5_FLASH_SFR          (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SFR_OFFSET)
+#define STM32WL5_FLASH_SRRVR        (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SRRVR_OFFSET)
 
 /* Register Bitfield Definitions ********************************************/
 
 /* Flash Access Control Register (ACR) */
 
-#define FLASH_ACR_LATENCY_SHIFT     (0)
-#define FLASH_ACR_LATENCY_MASK      (7 << FLASH_ACR_LATENCY_SHIFT)
-#  define FLASH_ACR_LATENCY(n)      ((n) << FLASH_ACR_LATENCY_SHIFT)  /* n wait states, for Vcore range 1 and 2. */
-#  define FLASH_ACR_LATENCY_0       (0 << FLASH_ACR_LATENCY_SHIFT)    /* 000: Zero wait states  */
-#  define FLASH_ACR_LATENCY_1       (1 << FLASH_ACR_LATENCY_SHIFT)    /* 001: One wait state    */
-#  define FLASH_ACR_LATENCY_2       (2 << FLASH_ACR_LATENCY_SHIFT)    /* 010: Two wait states   */
-
-#define FLASH_ACR_PRFTEN            (1 <<  8) /* Bit  8:  Prefetch enable */
-#define FLASH_ACR_ICEN              (1 <<  9) /* Bit  9:  Instruction cache enable */
-#define FLASH_ACR_DCEN              (1 << 10) /* Bit 10: Data cache enable */
-#define FLASH_ACR_ICRST             (1 << 11) /* Bit 11: Instruction cache reset */
-#define FLASH_ACR_DCRST             (1 << 12) /* Bit 12: Data cache reset */
-#define FLASH_ACR_PES               (1 << 15) /* Bit 15: Suspend flash program */
-#define FLASH_ACR_EMPTY             (1 << 16) /* Bit 16: Is user flash empty */
+#define FLASH_ACR_LATENCY_SHIFT    (0)
+#define FLASH_ACR_LATENCY_MASK     (7 << FLASH_ACR_LATENCY_SHIFT)
+#  define FLASH_ACR_LATENCY(n)     ((n) << FLASH_ACR_LATENCY_SHIFT)  /* n wait states, for Vcore range 1 and 2. */
+#  define FLASH_ACR_LATENCY_0      (0 << FLASH_ACR_LATENCY_SHIFT)    /* 000: Zero wait states  */
+#  define FLASH_ACR_LATENCY_1      (1 << FLASH_ACR_LATENCY_SHIFT)    /* 001: One wait state    */
+#  define FLASH_ACR_LATENCY_2      (2 << FLASH_ACR_LATENCY_SHIFT)    /* 010: Two wait states   */
+
+#define FLASH_ACR_PRFTEN           (1 <<  8) /* Bit  8:  Prefetch enable */
+#define FLASH_ACR_ICEN             (1 <<  9) /* Bit  9:  Instruction cache enable */
+#define FLASH_ACR_DCEN             (1 << 10) /* Bit 10: Data cache enable */
+#define FLASH_ACR_ICRST            (1 << 11) /* Bit 11: Instruction cache reset */
+#define FLASH_ACR_DCRST            (1 << 12) /* Bit 12: Data cache reset */
+#define FLASH_ACR_PES              (1 << 15) /* Bit 15: Suspend flash program */
+#define FLASH_ACR_EMPTY            (1 << 16) /* Bit 16: Is user flash empty */
 
 /* Flash Access Control Register 2 (ACR2) */
 
-#define FLASH_ACR2_PRIVMODE         (1 <<  0) /* Bit  0: Enable flash priviliged access mode */
-#define FLASH_ACR2_HDPADIS          (1 <<  1) /* Bit  1: Disable user flash hide protection area access */
-#define FLASH_ACR2_C2SWDBGEN        (1 <<  2) /* Bit  2: Enable cpu2 debug access */
+#define FLASH_ACR2_PRIVMODE        (1 <<  0) /* Bit  0: Enable flash priviliged access mode */
+#define FLASH_ACR2_HDPADIS         (1 <<  1) /* Bit  1: Disable user flash hide protection area access */
+#define FLASH_ACR2_C2SWDBGEN       (1 <<  2) /* Bit  2: Enable cpu2 debug access */
 
 /* Flash Status Register (SR) */
 
-#define FLASH_SR_EOP                (1 <<  0) /* Bit  0: End of operation */
-#define FLASH_SR_OPERR              (1 <<  1) /* Bit  1: Operation error */
-#define FLASH_SR_PROGERR            (1 <<  3) /* Bit  3: Programming error */
-#define FLASH_SR_WRPERR             (1 <<  4) /* Bit  4: Write protection error */
-#define FLASH_SR_PGAERR             (1 <<  5) /* Bit  5: Programming alignment error */
-#define FLASH_SR_SIZERR             (1 <<  6) /* Bit  6: Size error */
-#define FLASH_SR_PGSERR             (1 <<  7) /* Bit  7: Programming sequence error */
-#define FLASH_SR_MISERR             (1 <<  8) /* Bit  8: Fast programming data miss error */
-#define FLASH_SR_FASTERR            (1 <<  9) /* Bit  9: Fast programming error */
-#define FLASH_SR_OPTNV              (1 << 13) /* Bit 13: User option OPTVAL indication */
-#define FLASH_SR_RDERR              (1 << 14) /* Bit 14: PCROP read error */
-#define FLASH_SR_OPTVERR            (1 << 15) /* Bit 15: Option validity error */
-#define FLASH_SR_BSY                (1 << 16) /* Bit 16: Busy */
-#define FLASH_SR_CFGBSY             (1 << 18) /* Bit 18: Program or erase configuration busy */
-#define FLASH_SR_PESD               (1 << 19) /* Bit 19: Program or erase operation suspended */
+#define FLASH_SR_EOP               (1 <<  0) /* Bit  0: End of operation */
+#define FLASH_SR_OPERR             (1 <<  1) /* Bit  1: Operation error */
+#define FLASH_SR_PROGERR           (1 <<  3) /* Bit  3: Programming error */
+#define FLASH_SR_WRPERR            (1 <<  4) /* Bit  4: Write protection error */
+#define FLASH_SR_PGAERR            (1 <<  5) /* Bit  5: Programming alignment error */
+#define FLASH_SR_SIZERR            (1 <<  6) /* Bit  6: Size error */
+#define FLASH_SR_PGSERR            (1 <<  7) /* Bit  7: Programming sequence error */
+#define FLASH_SR_MISERR            (1 <<  8) /* Bit  8: Fast programming data miss error */
+#define FLASH_SR_FASTERR           (1 <<  9) /* Bit  9: Fast programming error */
+#define FLASH_SR_OPTNV             (1 << 13) /* Bit 13: User option OPTVAL indication */
+#define FLASH_SR_RDERR             (1 << 14) /* Bit 14: PCROP read error */
+#define FLASH_SR_OPTVERR           (1 << 15) /* Bit 15: Option validity error */
+#define FLASH_SR_BSY               (1 << 16) /* Bit 16: Busy */
+#define FLASH_SR_CFGBSY            (1 << 18) /* Bit 18: Program or erase configuration busy */
+#define FLASH_SR_PESD              (1 << 19) /* Bit 19: Program or erase operation suspended */
 
 /* Flash Control Register (CR) */
 
-#define FLASH_CR_PG                 (1 << 0)                /* Bit 0 : Program Page */
-#define FLASH_CR_PER                (1 << 1)                /* Bit 1 : Page Erase */
-#define FLASH_CR_MER                (1 << 2)                /* Bit 2 : Mass Erase */
+#define FLASH_CR_PG                (1 << 0)  /* Bit 0 : Program Page */
+#define FLASH_CR_PER               (1 << 1)  /* Bit 1 : Page Erase */
+#define FLASH_CR_MER               (1 << 2)  /* Bit 2 : Mass Erase */
 
-#define FLASH_CR_PNB_SHIFT          (3)                     /* Bits 3-9: Page number */
-#define FLASH_CR_PNB_MASK           (0x7F << FLASH_CR_PNB_SHIFT)
-#define FLASH_CR_PNB(n)             ((n)  << FLASH_CR_PNB_SHIFT) /* Page n, n=0..127 */
+#define FLASH_CR_PNB_SHIFT         (3)       /* Bits 3-9: Page number */
+#define FLASH_CR_PNB_MASK          (0x7F << FLASH_CR_PNB_SHIFT)
+#define FLASH_CR_PNB(n)            ((n)  << FLASH_CR_PNB_SHIFT) /* Page n, n=0..127 */
 
-#define FLASH_CR_START              (1 << 16)               /* Bit 16: Start Erase */
-#define FLASH_CR_OPTSTRT            (1 << 17)               /* Bit 17: Options modification Start */
-#define FLASH_CR_FSTPG              (1 << 23)               /* Bit 23: Fast programming */
-#define FLASH_CR_EOPIE              (1 << 24)               /* Bit 24: End of operation interrupt enable */
-#define FLASH_CR_ERRIE              (1 << 25)               /* Bit 25: Error interrupt enable */
-#define FLASH_CR_RDERRIE            (1 << 26)               /* Bit 26: PCROP read error interrupt enable */
-#define FLASH_CR_OBL_LAUNCH         (1 << 27)               /* Bit 27: Option Byte Loading */
-#define FLASH_CR_OPTLOCK            (1 << 30)               /* Bit 30: Option Lock */
-#define FLASH_CR_LOCK               (1 << 31)               /* Bit 31: Lock */
+#define FLASH_CR_START             (1 << 16) /* Bit 16: Start Erase */
+#define FLASH_CR_OPTSTRT           (1 << 17) /* Bit 17: Options modification Start */
+#define FLASH_CR_FSTPG             (1 << 18) /* Bit 18: Fast programming */
+#define FLASH_CR_EOPIE             (1 << 24) /* Bit 24: End of operation interrupt enable */
+#define FLASH_CR_ERRIE             (1 << 25) /* Bit 25: Error interrupt enable */
+#define FLASH_CR_RDERRIE           (1 << 26) /* Bit 26: PCROP read error interrupt enable */
+#define FLASH_CR_OBL_LAUNCH        (1 << 27) /* Bit 27: Option Byte Loading */
+#define FLASH_CR_OPTLOCK           (1 << 30) /* Bit 30: Option Lock */
+#define FLASH_CR_LOCK              (1 << 31) /* Bit 31: Lock */
 
 /* Flash ECC Register (ECCR) */
 
-#define FLASH_ECCR_ADDR_ECC_SHIFT   (0)                     /* Bits 0-15: Read protect */
-#  define FLASH_ECCR_ADDR_ECC_MASK  (0xffff << FLASH_ECCR_ADDR_ECC_SHIFT)
-#define FLASH_ECCR_SYSF_ECC         (1 << 20)               /* Bit 20: System Flash ECC fail */
-#define FLASH_ECCR_ECCCIE           (1 << 24)               /* Bit 24: ECC correction interrupt enable */
-#define FLASH_ECCR_CPUID_SHIFT      (26)
-#  define FLASH_ECCR_CPUID_MASK     (0x7 << FLASH_ECCR_CPUID_SHIFT)
-#  define FLASH_ECCR_CPUID_CPU1     (0x0 << FLASH_ECCR_CPUID_SHIFT) /* 000: cpu1 access caused ECC failure */
-#  define FLASH_ECCR_CPUID_CPU2     (0x1 << FLASH_ECCR_CPUID_SHIFT) /* 001: cpu2 access caused ECC failure */
+#define FLASH_ECCR_ADDR_ECC_SHIFT  (0)       /* Bits 0-16: ECC fail address */
+#  define FLASH_ECCR_ADDR_ECC_MASK (0x1ffff << FLASH_ECCR_ADDR_ECC_SHIFT)
+#define FLASH_ECCR_SYSF_ECC        (1 << 20) /* Bit 20: System Flash ECC fail */
+#define FLASH_ECCR_ECCCIE          (1 << 24) /* Bit 24: ECC correction interrupt enable */
+#define FLASH_ECCR_CPUID_SHIFT     (26)
+#  define FLASH_ECCR_CPUID_MASK    (0x7 << FLASH_ECCR_CPUID_SHIFT)
+#  define FLASH_ECCR_CPUID_CPU1    (0x0 << FLASH_ECCR_CPUID_SHIFT) /* 000: cpu1 access caused ECC failure */
+#  define FLASH_ECCR_CPUID_CPU2    (0x1 << FLASH_ECCR_CPUID_SHIFT) /* 001: cpu2 access caused ECC failure */
 
-#define FLASH_ECCR_ECCC             (1 << 30)               /* Bit 30: ECC correction */
-#define FLASH_ECCR_ECCD             (1 << 31)               /* Bit 31: ECC detection */
+#define FLASH_ECCR_ECCC            (1 << 30) /* Bit 30: ECC correction */
+#define FLASH_ECCR_ECCD            (1 << 31) /* Bit 31: ECC detection */
 
 /* Flash Option Register (OPTR) */
 
-#define FLASH_OPTR_RDP_SHIFT       (0)                      /* Bits 0-7: Read Protection Level */
+#define FLASH_OPTR_RDP_SHIFT       (0)       /* Bits 0-7: Read Protection Level */
 #define FLASH_OPTR_RDP_MASK        (0xFF << FLASH_OPTR_RDP_SHIFT)
 #define FLASH_OPTR_RDP_NONE        (0xAA << FLASH_OPTR_RDP_SHIFT)
 #define FLASH_OPTR_RDP_CHIP        (0xCC << FLASH_OPTR_RDP_SHIFT) /* WARNING, CANNOT BE REVERSED !! */
 
-#define FLASH_OPTR_ESE             (1 << 8)                 /* Bit 8: System security flag */
+#define FLASH_OPTR_ESE             (1 << 8)  /* Bit 8: System security flag */
 
-#define FLASH_OPTR_BORLEV_SHIFT    (9)                      /* Bits 9-11: BOR reset Level */
+#define FLASH_OPTR_BORLEV_SHIFT    (9)       /* Bits 9-11: BOR reset Level */
 #define FLASH_OPTR_BORLEV_MASK     (7 << FLASH_OPTR_BORLEV_SHIFT)
 #define FLASH_OPTR_VBOR0           (0 << FLASH_OPTR_BORLEV_SHIFT) /* 000: BOR Level 0 (1.7 V) */
 #define FLASH_OPTR_VBOR1           (1 << FLASH_OPTR_BORLEV_SHIFT) /* 001: BOR Level 1 (2.0 V) */
@@ -246,59 +244,59 @@
 #define FLASH_OPTR_VBOR3           (3 << FLASH_OPTR_BORLEV_SHIFT) /* 011: BOR Level 3 (2.5 V) */
 #define FLASH_OPTR_VBOR4           (4 << FLASH_OPTR_BORLEV_SHIFT) /* 100: BOR Level 4 (2.8 V) */
 
-#define FLASH_OPTR_NRST_STOP       (1 << 12)                /* Bit 12: Generate reset when entering the Stop mode */
-#define FLASH_OPTR_NRST_STDBY      (1 << 13)                /* Bit 13: Generate reset when entering the Standby mode */
-#define FLASH_OPTR_NRST_SHDW       (1 << 14)                /* Bit 14: Generate reset when entering the Shutdown mode */
-#define FLASH_OPTR_IWDG_SW         (1 << 16)                /* Bit 16: Independent watchdog selection */
-#define FLASH_OPTR_IWDG_STOP       (1 << 17)                /* Bit 17: Independent watchdog counter freeze in Stop mode */
-#define FLASH_OPTR_IWDG_STDBY      (1 << 18)                /* Bit 18: Independent watchdog counter freeze in Standby mode*/
-#define FLASH_OPTR_WWDG_SW         (1 << 19)                /* Bit 19: Window watchdog selection */
-#define FLASH_OPTR_NBOOT1          (1 << 23)                /* Bit 23: Boot configuration */
-#define FLASH_OPTR_SRAM2_PE        (1 << 24)                /* Bit 24: SRAM2 parity check enable */
-#define FLASH_OPTR_SRAM_RST        (1 << 25)                /* Bit 25: SRAM1/2 Erase when system reset */
-#define FLASH_OPTR_NSWBOOT0        (1 << 26)                /* Bit 26: Software BOOT0 */
-#define FLASH_OPTR_NBOOT0          (1 << 27)                /* Bit 27: nBOOT0 option bit */
-
-#define FLASH_OPTR_C1BOOT_LOCK     (1 << 30)                /* Bit 30: Enable cpu1 boot lock */
-#define FLASH_OPTR_C2BOOT_LOCK     (1 << 31)                /* Bit 31: Enable cpu2 boot lock */
+#define FLASH_OPTR_NRST_STOP       (1 << 12) /* Bit 12: Generate reset when entering the Stop mode */
+#define FLASH_OPTR_NRST_STDBY      (1 << 13) /* Bit 13: Generate reset when entering the Standby mode */
+#define FLASH_OPTR_NRST_SHDW       (1 << 14) /* Bit 14: Generate reset when entering the Shutdown mode */
+#define FLASH_OPTR_IWDG_SW         (1 << 16) /* Bit 16: Independent watchdog selection */
+#define FLASH_OPTR_IWDG_STOP       (1 << 17) /* Bit 17: Independent watchdog counter freeze in Stop mode */
+#define FLASH_OPTR_IWDG_STDBY      (1 << 18) /* Bit 18: Independent watchdog counter freeze in Standby mode*/
+#define FLASH_OPTR_WWDG_SW         (1 << 19) /* Bit 19: Window watchdog selection */
+#define FLASH_OPTR_NBOOT1          (1 << 23) /* Bit 23: Boot configuration */
+#define FLASH_OPTR_SRAM2_PE        (1 << 24) /* Bit 24: SRAM2 parity check enable */
+#define FLASH_OPTR_SRAM_RST        (1 << 25) /* Bit 25: SRAM1/2 Erase when system reset */
+#define FLASH_OPTR_NSWBOOT0        (1 << 26) /* Bit 26: Software BOOT0 */
+#define FLASH_OPTR_NBOOT0          (1 << 27) /* Bit 27: nBOOT0 option bit */
+
+#define FLASH_OPTR_C1BOOT_LOCK     (1 << 30) /* Bit 30: Enable cpu1 boot lock */
+#define FLASH_OPTR_C2BOOT_LOCK     (1 << 31) /* Bit 31: Enable cpu2 boot lock */
 
 /* Flash CPU2 Access Control Register (C2ACR) */
 
-#define FLASH_C2ACR_PRFTEN         (1 <<  8)                /* Bit  8: Enable cpu2 prefetch */
-#define FLASH_C2ACR_ICEN           (1 <<  9)                /* Bit  9: Enable cpu2 instruction cache */
-#define FLASH_C2ACR_ICRST          (1 << 11)                /* Bit 11: Reset cpu2 instruction cache */
-#define FLASH_C2ACR_PES            (1 << 15)                /* Bit 15: Suspend cpu2 flash program/erase */
+#define FLASH_C2ACR_PRFTEN         (1 <<  8) /* Bit  8: Enable cpu2 prefetch */
+#define FLASH_C2ACR_ICEN           (1 <<  9) /* Bit  9: Enable cpu2 instruction cache */
+#define FLASH_C2ACR_ICRST          (1 << 11) /* Bit 11: Reset cpu2 instruction cache */
+#define FLASH_C2ACR_PES            (1 << 15) /* Bit 15: Suspend cpu2 flash program/erase */
 
 /* Flash CPU2 Status Register (C2SR) */
 
-#define FLASH_C2SR_EOP             (1 <<  0)                /* Bit  0: End of operation flag */
-#define FLASH_C2SR_OPERR           (1 <<  1)                /* Bit  1: Operation */
-#define FLASH_C2SR_PROGERR         (1 <<  3)                /* Bit  3: Programming */
-#define FLASH_C2SR_WRPERR          (1 <<  4)                /* Bit  4: Write protection */
-#define FLASH_C2SR_PGAERR          (1 <<  5)                /* Bit  5: Programming alignment */
-#define FLASH_C2SR_SIZERR          (1 <<  6)                /* Bit  6: Size */
-#define FLASH_C2SR_PGSERR          (1 <<  7)                /* Bit  7: Programming sequence */
-#define FLASH_C2SR_MISSERR         (1 <<  8)                /* Bit  8: Fast programming data miss */
-#define FLASH_C2SR_FASTERR         (1 <<  9)                /* Bit  9: Fast programming */
-#define FLASH_C2SR_RDERR           (1 << 14)                /* Bit 14: PCROP read */
-#define FLASH_C2SR_BSY             (1 << 16)                /* Bit 16: Busy flag */
-#define FLASH_C2SR_CFGBSY          (1 << 18)                /* Bit 18: Program or erase configuration busy */
-#define FLASH_C2SR_PESD            (1 << 19)                /* Bit 19: Program/erase operation suspended */
+#define FLASH_C2SR_EOP             (1 <<  0) /* Bit  0: End of operation flag */
+#define FLASH_C2SR_OPERR           (1 <<  1) /* Bit  1: Operation */
+#define FLASH_C2SR_PROGERR         (1 <<  3) /* Bit  3: Programming */
+#define FLASH_C2SR_WRPERR          (1 <<  4) /* Bit  4: Write protection */
+#define FLASH_C2SR_PGAERR          (1 <<  5) /* Bit  5: Programming alignment */
+#define FLASH_C2SR_SIZERR          (1 <<  6) /* Bit  6: Size */
+#define FLASH_C2SR_PGSERR          (1 <<  7) /* Bit  7: Programming sequence */
+#define FLASH_C2SR_MISSERR         (1 <<  8) /* Bit  8: Fast programming data miss */
+#define FLASH_C2SR_FASTERR         (1 <<  9) /* Bit  9: Fast programming */
+#define FLASH_C2SR_RDERR           (1 << 14) /* Bit 14: PCROP read */
+#define FLASH_C2SR_BSY             (1 << 16) /* Bit 16: Busy flag */
+#define FLASH_C2SR_CFGBSY          (1 << 18) /* Bit 18: Program or erase configuration busy */
+#define FLASH_C2SR_PESD            (1 << 19) /* Bit 19: Program/erase operation suspended */
 
 /* Flash CPU2 Control Register (C2CR) */
 
-#define FLASH_C2CR_PG                 (1 << 0)                /* Bit 0 : Program Page */
-#define FLASH_C2CR_PER                (1 << 1)                /* Bit 1 : Page Erase */
-#define FLASH_C2CR_MER                (1 << 2)                /* Bit 2 : Mass Erase */
+#define FLASH_C2CR_PG              (1 << 0)  /* Bit 0 : Program Page */
+#define FLASH_C2CR_PER             (1 << 1)  /* Bit 1 : Page Erase */
+#define FLASH_C2CR_MER             (1 << 2)  /* Bit 2 : Mass Erase */
 
-#define FLASH_C2CR_PNB_SHIFT          (3)                     /* Bits 3-9: Page number */
-#define FLASH_C2CR_PNB_MASK           (0x7F << FLASH_C2CR_PNB_SHIFT)
-#define FLASH_C2CR_PNB(n)             ((n)  << FLASH_C2CR_PNB_SHIFT) /* Page n, n=0..127 */
+#define FLASH_C2CR_PNB_SHIFT       (3)       /* Bits 3-9: Page number */
+#define FLASH_C2CR_PNB_MASK        (0x7F << FLASH_C2CR_PNB_SHIFT)
+#define FLASH_C2CR_PNB(n)          ((n)  << FLASH_C2CR_PNB_SHIFT) /* Page n, n=0..127 */
 
-#define FLASH_C2CR_START              (1 << 16)               /* Bit 16: Start Erase */
-#define FLASH_C2CR_FSTPG              (1 << 18)               /* Bit 23: Fast programming */
-#define FLASH_C2CR_EOPIE              (1 << 24)               /* Bit 24: End of operation interrupt enable */
-#define FLASH_C2CR_ERRIE              (1 << 25)               /* Bit 25: Error interrupt enable */
-#define FLASH_C2CR_RDERRIE            (1 << 26)               /* Bit 26: PCROP read error interrupt enable */
+#define FLASH_C2CR_START           (1 << 16) /* Bit 16: Start Erase */
+#define FLASH_C2CR_FSTPG           (1 << 18) /* Bit 23: Fast programming */
+#define FLASH_C2CR_EOPIE           (1 << 24) /* Bit 24: End of operation interrupt enable */
+#define FLASH_C2CR_ERRIE           (1 << 25) /* Bit 25: Error interrupt enable */
+#define FLASH_C2CR_RDERRIE         (1 << 26) /* Bit 26: PCROP read error interrupt enable */
 
 #endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_FLASH_H */
diff --git a/arch/arm/src/stm32wl5/stm32wl5_flash.c b/arch/arm/src/stm32wl5/stm32wl5_flash.c
index d79a8e3adf..7fff2d309c 100644
--- a/arch/arm/src/stm32wl5/stm32wl5_flash.c
+++ b/arch/arm/src/stm32wl5/stm32wl5_flash.c
@@ -34,17 +34,17 @@
 #include <nuttx/config.h>
 #include <nuttx/arch.h>
 #include <nuttx/progmem.h>
+#include <nuttx/semaphore.h>
 
-#include <semaphore.h>
 #include <assert.h>
 #include <debug.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <string.h>
 
 #include "stm32wl5_rcc.h"
 #include "stm32wl5_waste.h"
 #include "stm32wl5_flash.h"
-
 #include "arm_internal.h"
 
 #if !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_DEFAULT)
@@ -57,6 +57,7 @@
 
 #define FLASH_KEY1         0x45670123
 #define FLASH_KEY2         0xCDEF89AB
+#define FLASH_ERASEDVALUE  0xffu
 
 #define OPTBYTES_KEY1      0x08192A3B
 #define OPTBYTES_KEY2      0x4C5D6E7F
@@ -64,15 +65,7 @@
 #define FLASH_PAGE_SIZE    STM32WL5_FLASH_PAGESIZE
 #define FLASH_PAGE_WORDS   (FLASH_PAGE_SIZE / 4)
 #define FLASH_PAGE_MASK    (FLASH_PAGE_SIZE - 1)
-#if FLASH_PAGE_SIZE == 2048
-#  define FLASH_PAGE_SHIFT   (11)    /* 2**11  = 2048B */
-#elif FLASH_PAGE_SIZE == 4096
-#  define FLASH_PAGE_SHIFT   (12)    /* 2**12  = 4096B */
-#elif FLASH_PAGE_SIZE == 8192
-#  define FLASH_PAGE_SHIFT   (13)    /* 2**13  = 8192B */
-#else
-#  error Unsupported STM32WL5_FLASH_PAGESIZE
-#endif
+#define FLASH_PAGE_SHIFT   (11)    /* 2**11  = 2048B */
 #define FLASH_BYTE2PAGE(o) ((o) >> FLASH_PAGE_SHIFT)
 
 #define FLASH_CR_PAGE_ERASE              FLASH_CR_PER
@@ -99,23 +92,9 @@ static uint32_t g_page_buffer[FLASH_PAGE_WORDS];
  * Private Functions
  ****************************************************************************/
 
-static inline void sem_lock(void)
+static inline int sem_lock(void)
 {
-  int ret;
-
-  do
-    {
-      /* Take the semaphore (perhaps waiting) */
-
-      ret = nxsem_wait(&g_sem);
-
-      /* The only case that an error should occur here is if the wait was
-       * awakened by a signal.
-       */
-
-      DEBUGASSERT(ret == OK || ret == -EINTR);
-    }
-  while (ret == -EINTR);
+  return nxsem_wait_uninterruptible(&g_sem);
 }
 
 static inline void sem_unlock(void)
@@ -168,10 +147,11 @@ static inline void flash_optbytes_lock(void)
 
 static inline void flash_erase(size_t page)
 {
-  finfo("erase page %u\n", page);
+  finfo("erase page %u\n", (unsigned int)page);
 
   modifyreg32(STM32WL5_FLASH_CR, 0, FLASH_CR_PAGE_ERASE);
-  modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PNB_MASK, FLASH_CR_PNB(page));
+  modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PNB_MASK,
+              FLASH_CR_PNB(page & 0xff));
   modifyreg32(STM32WL5_FLASH_CR, 0, FLASH_CR_START);
 
   while (getreg32(STM32WL5_FLASH_SR) & FLASH_SR_BSY)
@@ -186,18 +166,36 @@ static inline void flash_erase(size_t page)
  * Public Functions
  ****************************************************************************/
 
-void stm32wl5_flash_unlock(void)
+int stm32wl5_flash_unlock(void)
 {
-  sem_lock();
+  int ret;
+
+  ret = sem_lock();
+  if (ret < 0)
+    {
+      return ret;
+    }
+
   flash_unlock();
   sem_unlock();
+
+  return ret;
 }
 
-void stm32wl5_flash_lock(void)
+int stm32wl5_flash_lock(void)
 {
-  sem_lock();
+  int ret;
+
+  ret = sem_lock();
+  if (ret < 0)
+    {
+      return ret;
+    }
+
   flash_lock();
   sem_unlock();
+
+  return ret;
 }
 
 /****************************************************************************
@@ -220,6 +218,7 @@ void stm32wl5_flash_lock(void)
 uint32_t stm32wl5_flash_user_optbytes(uint32_t clrbits, uint32_t setbits)
 {
   uint32_t regval;
+  int ret;
 
   /* To avoid accidents, do not allow setting RDP via this function.
    * Remove these asserts if want to enable changing the protection level.
@@ -229,19 +228,24 @@ uint32_t stm32wl5_flash_user_optbytes(uint32_t clrbits, uint32_t setbits)
   DEBUGASSERT((clrbits & FLASH_OPTR_RDP_MASK) == 0);
   DEBUGASSERT((setbits & FLASH_OPTR_RDP_MASK) == 0);
 
-  sem_lock();
+  ret = sem_lock();
+  if (ret < 0)
+    {
+      return 0;
+    }
+
   flash_optbytes_unlock();
 
   /* Modify Option Bytes in register. */
 
   regval = getreg32(STM32WL5_FLASH_OPTR);
 
-  finfo("Flash option bytes before: 0x%x\n", (unsigned)regval);
+  finfo("Flash option bytes before: 0x%" PRIx32 "\n", regval);
 
   regval = (regval & ~clrbits) | setbits;
   putreg32(regval, STM32WL5_FLASH_OPTR);
 
-  finfo("Flash option bytes after:  0x%x\n", (unsigned)regval);
+  finfo("Flash option bytes after:  0x%" PRIx32 "\n", regval);
 
   /* Start Option Bytes programming and wait for completion. */
 
@@ -260,13 +264,11 @@ uint32_t stm32wl5_flash_user_optbytes(uint32_t clrbits, uint32_t setbits)
 
 size_t up_progmem_pagesize(size_t page)
 {
-  (void)page;
   return STM32WL5_FLASH_PAGESIZE;
 }
 
 size_t up_progmem_erasesize(size_t block)
 {
-  (void)block;
   return STM32WL5_FLASH_PAGESIZE;
 }
 
@@ -305,41 +307,23 @@ bool up_progmem_isuniform(void)
   return true;
 }
 
-ssize_t up_progmem_ispageerased(size_t page)
+ssize_t up_progmem_eraseblock(size_t block)
 {
-  size_t addr;
-  size_t count;
-  size_t bwritten = 0;
+  int ret;
 
-  if (page >= STM32WL5_FLASH_NPAGES)
+  if (block >= STM32WL5_FLASH_NPAGES)
     {
       return -EFAULT;
     }
 
-  /* Verify */
-
-  for (addr = up_progmem_getaddress(page), count = up_progmem_pagesize(page);
-       count; count--, addr++)
-    {
-      if (getreg8(addr) != 0xff)
-        {
-          bwritten++;
-        }
-    }
-
-  return bwritten;
-}
+  /* Erase single block */
 
-ssize_t up_progmem_eraseblock(size_t block)
-{
-  if (block >= STM32WL5_FLASH_NPAGES)
+  ret = sem_lock();
+  if (ret < 0)
     {
-      return -EFAULT;
+      return (ssize_t)ret;
     }
 
-  /* Erase single block */
-
-  sem_lock();
   flash_unlock();
 
   flash_erase(block);
@@ -359,6 +343,31 @@ ssize_t up_progmem_eraseblock(size_t block)
     }
 }
 
+ssize_t up_progmem_ispageerased(size_t page)
+{
+  size_t addr;
+  size_t count;
+  size_t bwritten = 0;
+
+  if (page >= STM32WL5_FLASH_NPAGES)
+    {
+      return -EFAULT;
+    }
+
+  /* Verify */
+
+  for (addr = up_progmem_getaddress(page), count = up_progmem_pagesize(page);
+       count; count--, addr++)
+    {
+      if (getreg8(addr) != FLASH_ERASEDVALUE)
+        {
+          bwritten++;
+        }
+    }
+
+  return bwritten;
+}
+
 ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
 {
   uint32_t *dest;
@@ -367,6 +376,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
   size_t xfrsize;
   size_t offset;
   size_t page;
+  bool set_pg_bit = false;
   int i;
   int ret = OK;
 
@@ -393,7 +403,11 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
   dest = (uint32_t *)((uint8_t *)addr - offset);
   written = 0;
 
-  sem_lock();
+  ret = sem_lock();
+  if (ret < 0)
+    {
+      return (ssize_t)ret;
+    }
 
   /* Get flash ready and begin flashing. */
 
@@ -445,6 +459,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
       /* Write the page. Must be with double-words. */
 
       modifyreg32(STM32WL5_FLASH_CR, 0, FLASH_CR_PG);
+      set_pg_bit = true;
 
       for (i = 0; i < FLASH_PAGE_WORDS; i += 2)
         {
@@ -460,7 +475,6 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
 
           if (getreg32(STM32WL5_FLASH_SR) & FLASH_SR_WRITE_PROTECTION_ERROR)
             {
-              modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PG, 0);
               ret = -EROFS;
               goto out;
             }
@@ -468,13 +482,13 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
           if (getreg32(dest - 1) != *(src - 1) ||
               getreg32(dest - 2) != *(src - 2))
             {
-              modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PG, 0);
               ret = -EIO;
               goto out;
             }
         }
 
       modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PG, 0);
+      set_pg_bit = false;
 
       /* Adjust pointers and counts for the next time through the loop */
 
@@ -487,15 +501,20 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
     }
 
 out:
-  /* If there was an error, clear all error flags in status
-   * register (rc_w1 register so do this by writing the
-   * error bits).
+  if (set_pg_bit)
+    {
+      modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PG, 0);
+    }
+
+  /* If there was an error, clear all error flags in status register (rc_w1
+   * register so do this by writing the error bits).
    */
 
   if (ret != OK)
     {
-      ferr("flash write error: %d, status: 0x%x\n", ret,
-           (unsigned)getreg32(STM32WL5_FLASH_SR));
+      ferr("flash write error: %d, status: 0x%" PRIx32 "\n",
+           ret, getreg32(STM32WL5_FLASH_SR));
+
       modifyreg32(STM32WL5_FLASH_SR, 0, FLASH_SR_ALLERRS);
     }
 
@@ -503,3 +522,8 @@ out:
   sem_unlock();
   return (ret == OK) ? written : ret;
 }
+
+uint8_t up_progmem_erasestate(void)
+{
+  return FLASH_ERASEDVALUE;
+}
diff --git a/arch/arm/src/stm32wl5/stm32wl5_flash.h b/arch/arm/src/stm32wl5/stm32wl5_flash.h
index 9978309d59..a4f70df674 100644
--- a/arch/arm/src/stm32wl5/stm32wl5_flash.h
+++ b/arch/arm/src/stm32wl5/stm32wl5_flash.h
@@ -26,14 +26,16 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <stdint.h>
+
 #include "hardware/stm32wl5_flash.h"
 
 /****************************************************************************
- * Public Function Prototypes
+ * Public Functions Prototypes
  ****************************************************************************/
 
-void stm32wl5_flash_lock(void);
-void stm32wl5_flash_unlock(void);
+int stm32wl5_flash_lock(void);
+int stm32wl5_flash_unlock(void);
 
 /****************************************************************************
  * Name: stm32wl5_flash_user_optbytes


[incubator-nuttx] 02/02: nucleo-wl55jc: add partition table support for progmem FLASH

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 4d4566e9ed070e749ad27a5a24d7772b7c340116
Author: Michał Łyszczek <mi...@bofc.pl>
AuthorDate: Tue Jun 14 01:11:33 2022 +0200

    nucleo-wl55jc: add partition table support for progmem FLASH
    
    This patch adds working integration of progmem FLASH. User can partition
    internal FLASH memory to up to 4 partitions and use any combination of
    raw, nxffs, smartfs and mtd_config filesystems (unless there are other
    limitations like nxffs supports only single instance).
    
    Support for dual CPU is added to Kconfig to not overwrite CPU2 program code.
    
    Code guards user to not allocate more memory than there is on FLASH, and
    warns user if not all FLASH memory is used. Errors will be printed when
    user tries to initialize two instances of nxffs or mtd_config filesystems.
    
    Signed-off-by: Michał Łyszczek <mi...@bofc.pl>
---
 boards/arm/stm32wl5/nucleo-wl55jc/Kconfig          | 258 ++++++++++++++++++
 .../stm32wl5/nucleo-wl55jc/configs/demo/defconfig  |  19 ++
 boards/arm/stm32wl5/nucleo-wl55jc/src/Makefile     |   4 +
 .../arm/stm32wl5/nucleo-wl55jc/src/nucleo-wl55jc.h |  10 +
 .../arm/stm32wl5/nucleo-wl55jc/src/stm32_appinit.c |  10 +
 .../arm/stm32wl5/nucleo-wl55jc/src/stm32_flash.c   | 297 +++++++++++++++++++++
 6 files changed, 598 insertions(+)

diff --git a/boards/arm/stm32wl5/nucleo-wl55jc/Kconfig b/boards/arm/stm32wl5/nucleo-wl55jc/Kconfig
index 1d568310d2..a65425890d 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 49e2feacd3..ba1b1efb25 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 9532b20cd4..16a184a937 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 a9585eb37d..e3b7b86338 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 5da9d754c6..4955cf1381 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 0000000000..463f84a9e0
--- /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 <nuttx/config.h>
+#include <nuttx/mtd/mtd.h>
+#include <nuttx/mtd/configdata.h>
+#include <nuttx/fs/nxffs.h>
+#include <nuttx/fs/smart.h>
+#include <nuttx/fs/fs.h>
+
+#include <debug.h>
+#include <stdio.h>
+
+#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;
+}