From 0a4650d1eee137a815170ff2ae4815389714b12e Mon Sep 17 00:00:00 2001 From: Alan Carvalho de Assis Date: Sun, 6 Aug 2017 10:38:55 -0600 Subject: [PATCH] STM32F103-Minimum: Add support for SmartFS on Winbond W25 SPI NOR Flash --- configs/stm32f103-minimum/Kconfig | 57 ++++ configs/stm32f103-minimum/README.txt | 36 +++ configs/stm32f103-minimum/src/Makefile | 4 + configs/stm32f103-minimum/src/stm32_bringup.c | 36 +++ configs/stm32f103-minimum/src/stm32_spi.c | 8 + configs/stm32f103-minimum/src/stm32_w25.c | 301 ++++++++++++++++++ .../stm32f103-minimum/src/stm32f103_minimum.h | 13 + 7 files changed, 455 insertions(+) create mode 100644 configs/stm32f103-minimum/src/stm32_w25.c diff --git a/configs/stm32f103-minimum/Kconfig b/configs/stm32f103-minimum/Kconfig index 3479da27251..15f1bc0f1cd 100644 --- a/configs/stm32f103-minimum/Kconfig +++ b/configs/stm32f103-minimum/Kconfig @@ -5,6 +5,63 @@ if ARCH_BOARD_STM32F103_MINIMUM +config STM32F103MINIMUM_FLASH + bool "MTD driver for external 4Mbyte W25Q32FV FLASH on SPI1" + default n + select MTD + select MTD_W25 + select MTD_SMART + select FS_SMARTFS + select STM32_SPI1 + select MTD_BYTE_WRITE + ---help--- + Configures an MTD device for use with the onboard flash + +config STM32F103MINIMUM_FLASH_MINOR + int "Minor number for the FLASH /dev/smart entry" + default 0 + depends on STM32F103MINIMUM_FLASH + ---help--- + Sets the minor number for the FLASH MTD /dev entry + +config STM32F103MINIMUM_FLASH_PART + bool "Enable partition support on FLASH" + default y + depends on STM32F103MINIMUM_FLASH + ---help--- + Enables creation of partitions on the FLASH + +config STM32F103MINIMUM_FLASH_CONFIG_PART + bool "Create application config data partition on FLASH" + default n + depends on STM32F103MINIMUM_FLASH_PART + depends on PLATFORM_CONFIGDATA + ---help--- + Enables creation of a /dev/config partition on the FLASH + +config STM32F103MINIMUM_FLASH_CONFIG_PART_NUMBER + int "Index number of config partition (in list below)" + default 0 + depends on STM32F103MINIMUM_FLASH_CONFIG_PART + ---help--- + Specifies the index number of the config data partition + from the partition list. + +config STM32F103MINIMUM_FLASH_PART_LIST + string "Flash partition size list" + default "1024,1024,1024,1024" + depends on STM32F103MINIMUM_FLASH_PART + ---help--- + Comma separated list of partition sizes in KB. + +config STM32F103MINIMUM_FLASH_PART_NAMES + string "Flash partition name list" + default "first,second,third,forth" + depends on STM32F103MINIMUM_FLASH_PART + depends on MTD_PARTITION_NAMES + ---help--- + Comma separated list of partition names. + config STM32F103MINIMUM_QETIMER int "Timer to use with QE encoder" default 4 diff --git a/configs/stm32f103-minimum/README.txt b/configs/stm32f103-minimum/README.txt index 23bb4d357d6..d85ac86df22 100644 --- a/configs/stm32f103-minimum/README.txt +++ b/configs/stm32f103-minimum/README.txt @@ -14,6 +14,7 @@ Contents - Using 128KiB of Flash instead of 64KiB - Quadrature Encoder - SDCard support + - SPI NOR Flash - Nokia 5110 LCD Display support - USB Console support - STM32F103 Minimum - specific Configuration Options @@ -279,6 +280,41 @@ Quadrature Encoder: In this configuration, the QEncoder inputs will be on the TIM4 inputs of PB6 and PB7. +SPI NOR Flash support: +====================== + + We can use an extern SPI NOR Flash with STM32F103-Minimum board. In this case + we tested the Winboard W25Q32FV (32Mbit = 4MiB). + + You can connect the W25Q32FV module in the STM32F103 Minimum board this way: + connect PA5 (SPI1 CLK) to CLK; PA7 (SPI1 MOSI) to DI; PA6 (SPI MISO) to DO; + PA4 to /CS; Also connect 3.3V to VCC and GND to GND. + + You can start with default "stm32f103-minimum/nsh" configuration option and + enable these options using "make menuconfig" : + + System Type ---> + STM32 Peripheral Support ---> + [*] SPI1 + + Board Selection ---> + [*] MTD driver for external 4Mbyte W25Q32FV FLASH on SPI1 + (0) Minor number for the FLASH /dev/smart entry + [*] Enable partition support on FLASH + (1024,1024,1024,1024) Flash partition size list + + Device Drivers ---> + -*- Memory Technology Device (MTD) Support ---> + [*] Support MTD partitions + -*- SPI-based W25 FLASH + (0) W25 SPI Mode + (20000000) W25 SPI Frequency + + File Systems ---> + -*- SMART file system + (0xff) FLASH erased state + (16) Maximum file name length + SDCard support: =============== diff --git a/configs/stm32f103-minimum/src/Makefile b/configs/stm32f103-minimum/src/Makefile index b8f5c1f3d86..c399b10fbf3 100644 --- a/configs/stm32f103-minimum/src/Makefile +++ b/configs/stm32f103-minimum/src/Makefile @@ -69,6 +69,10 @@ ifeq ($(CONFIG_MMCSD),y) CSRCS += stm32_mmcsd.c endif +ifeq ($(CONFIG_MTD_W25),y) +CSRCS += stm32_w25.c +endif + ifeq ($(CONFIG_AUDIO_TONE),y) CSRCS += stm32_tone.c endif diff --git a/configs/stm32f103-minimum/src/stm32_bringup.c b/configs/stm32f103-minimum/src/stm32_bringup.c index 1d2542f0a4f..95c5cc4654a 100644 --- a/configs/stm32f103-minimum/src/stm32_bringup.c +++ b/configs/stm32f103-minimum/src/stm32_bringup.c @@ -81,6 +81,30 @@ # include "stm32_rtc.h" #endif +/* Checking needed by W25 Flash */ + +#define HAVE_W25 1 + +/* Can't support the W25 device if it SPI1 or W25 support is not enabled */ + +#if !defined(CONFIG_STM32_SPI1) || !defined(CONFIG_MTD_W25) +# undef HAVE_W25 +#endif + +/* Can't support W25 features if mountpoints are disabled */ + +#ifdef CONFIG_DISABLE_MOUNTPOINT +# undef HAVE_W25 +#endif + +/* Default W25 minor number */ + +#if defined(HAVE_W25) && !defined(CONFIG_NSH_W25MINOR) +# define CONFIG_NSH_W25MINOR 0 +#endif + +/* Checking needed by MMC/SDCard */ + #ifdef CONFIG_NSH_MMCSDMINOR # define MMCSD_MINOR CONFIG_NSH_MMCSDMINOR #else @@ -130,6 +154,18 @@ int stm32_bringup(void) } #endif +#ifdef HAVE_W25 + /* Initialize and register the W25 FLASH file system. */ + + ret = stm32_w25initialize(CONFIG_NSH_W25MINOR); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize W25 minor %d: %d\n", + CONFIG_NSH_W25MINOR, ret); + return ret; + } +#endif + #ifdef CONFIG_PWM /* Initialize PWM and register the PWM device. */ diff --git a/configs/stm32f103-minimum/src/stm32_spi.c b/configs/stm32f103-minimum/src/stm32_spi.c index b638281f214..b678e706335 100644 --- a/configs/stm32f103-minimum/src/stm32_spi.c +++ b/configs/stm32f103-minimum/src/stm32_spi.c @@ -74,6 +74,10 @@ void stm32_spidev_initialize(void) * architecture. */ +#ifdef CONFIG_MTD_W25 + (void)stm32_configgpio(FLASH_SPI1_CS); /* FLASH chip select */ +#endif + #ifdef CONFIG_CAN_MCP2515 (void)stm32_configgpio(GPIO_MCP2515_CS); /* MCP2515 chip select */ #endif @@ -169,6 +173,10 @@ void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid, stm32_gpiowrite(GPIO_SDCARD_CS, !selected); } #endif + +#ifdef CONFIG_MTD_W25 + stm32_gpiowrite(FLASH_SPI1_CS, !selected); +#endif } uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, uint32_t devid) diff --git a/configs/stm32f103-minimum/src/stm32_w25.c b/configs/stm32f103-minimum/src/stm32_w25.c new file mode 100644 index 00000000000..554fd29fa30 --- /dev/null +++ b/configs/stm32f103-minimum/src/stm32_w25.c @@ -0,0 +1,301 @@ +/**************************************************************************** + * config/stm32f103-minimum/src/stm32_w25.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_STM32_SPI1 +# include +# include +# include +# include +#endif + +#include "stm32_spi.h" + +#include "stm32f103_minimum.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Debug ********************************************************************/ +/* Non-standard debug that may be enabled just for testing the watchdog + * timer + */ + +#define W25_SPI_PORT 1 + +/* Configuration ************************************************************/ +/* Can't support the W25 device if it SPI1 or W25 support is not enabled */ + +#define HAVE_W25 1 +#if !defined(CONFIG_STM32_SPI1) || !defined(CONFIG_MTD_W25) +# undef HAVE_W25 +#endif + +/* Can't support W25 features if mountpoints are disabled */ + +#if defined(CONFIG_DISABLE_MOUNTPOINT) +# undef HAVE_W25 +#endif + +/* Can't support both FAT and SMARTFS */ + +#if defined(CONFIG_FS_FAT) && defined(CONFIG_FS_SMARTFS) +# warning "Can't support both FAT and SMARTFS -- using FAT" +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_w25initialize + * + * Description: + * Initialize and register the W25 FLASH file system. + * + ****************************************************************************/ + +int stm32_w25initialize(int minor) +{ + int ret; +#ifdef HAVE_W25 + FAR struct spi_dev_s *spi; + FAR struct mtd_dev_s *mtd; + FAR struct mtd_geometry_s geo; +#if defined(CONFIG_MTD_PARTITION_NAMES) + FAR const char *partname = CONFIG_STM32F103MINIMUM_FLASH_PART_NAMES; +#endif + + /* Get the SPI port */ + + spi = stm32_spibus_initialize(W25_SPI_PORT); + if (!spi) + { + syslog(LOG_ERR, "ERROR: Failed to initialize SPI port %d\n", + W25_SPI_PORT); + return -ENODEV; + } + + /* Now bind the SPI interface to the W25 SPI FLASH driver */ + + mtd = w25_initialize(spi); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: Failed to bind SPI port %d to the Winbond" + "W25 FLASH driver\n", W25_SPI_PORT); + return -ENODEV; + } + +#ifndef CONFIG_FS_SMARTFS + /* And finally, use the FTL layer to wrap the MTD driver as a block driver */ + + ret = ftl_initialize(minor, mtd); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Initialize the FTL layer\n"); + return ret; + } +#else + /* Initialize to provide SMARTFS on the MTD interface */ + + /* Get the geometry of the FLASH device */ + + ret = mtd->ioctl(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo)); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: mtd->ioctl failed: %d\n", ret); + return ret; + } + +#ifdef CONFIG_STM32F103MINIMUM_FLASH_PART + { + int partno; + int partsize; + int partoffset; + int partszbytes; + int erasesize; + const char *partstring = CONFIG_STM32F103MINIMUM_FLASH_PART_LIST; + const char *ptr; + FAR struct mtd_dev_s *mtd_part; + char partref[4]; + + /* Now create a partition on the FLASH device */ + + partno = 0; + ptr = partstring; + partoffset = 0; + + /* Get the Flash erase size */ + + erasesize = geo.erasesize; + + while (*ptr != '\0') + { + /* Get the partition size */ + + partsize = atoi(ptr); + partszbytes = (partsize << 10); /* partsize is defined in KB */ + + /* Check if partition size is bigger then erase block */ + + if (partszbytes < erasesize) + { + syslog(LOG_ERR, "ERROR: Partition size is lesser than erasesize!\n"); + return -1; + } + + /* Check if partition size is multiple of erase block */ + + if ( (partszbytes % erasesize) != 0 ) + { + syslog(LOG_ERR, "ERROR: Partition size is not multiple of erasesize!\n"); + return -1; + } + + mtd_part = mtd_partition(mtd, partoffset, partszbytes/ erasesize); + partoffset += partszbytes / erasesize; + +#ifdef CONFIG_STM32F103MINIMUM_FLASH_CONFIG_PART + /* Test if this is the config partition */ + + if (CONFIG_STM32F103MINIMUM_FLASH_CONFIG_PART_NUMBER == partno) + { + /* Register the partition as the config device */ + + mtdconfig_register(mtd_part); + } + else +#endif + { + /* Now initialize a SMART Flash block device and bind it + * to the MTD device. + */ + +#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS) + sprintf(partref, "p%d", partno); + smart_initialize(CONFIG_STM32F103MINIMUM_FLASH_MINOR, mtd_part, partref); +#endif + } + + /* Set the partition name */ + +#if defined(CONFIG_MTD_PARTITION_NAMES) + if (!mtd_part) + { + syslog(LOG_ERR, "Error: failed to create partition %s\n", partname); + return -1; + } + + mtd_setpartitionname(mtd_part, partname); + + /* Now skip to next name. We don't need to split the string here + * because the MTD partition logic will only display names up to + * the comma, thus allowing us to use a single static name + * in the code. + */ + + while (*partname != ',' && *partname != '\0') + { + /* Skip to next ',' */ + + partname++; + } + + if (*partname == ',') + { + partname++; + } +#endif + + /* Update the pointer to point to the next size in the list */ + + while ((*ptr >= '0') && (*ptr <= '9')) + { + ptr++; + } + + if (*ptr == ',') + { + ptr++; + } + + /* Increment the part number */ + + partno++; + } + } +#else /* CONFIG_STM32F103MINIMUM_FLASH_PART */ + + /* Configure the device with no partition support */ + + smart_initialize(CONFIG_STM32F103MINIMUM_FLASH_MINOR, mtd, NULL); + +#endif /* CONFIG_STM32F103MINIMUM_FLASH_PART */ +#endif /* CONFIG_FS_SMARTFS */ +#endif /* HAVE_W25 */ + + /* Create a RAM MTD device if configured */ + +#if defined(CONFIG_RAMMTD) && defined(CONFIG_STM32F103MINIMUM_RAMMTD) + { + uint8_t *start = (uint8_t *)kmm_malloc(CONFIG_STM32F103MINIMUM_RAMMTD_SIZE * 1024); + mtd = rammtd_initialize(start, CONFIG_STM32F103MINIMUM_RAMMTD_SIZE * 1024); + mtd->ioctl(mtd, MTDIOC_BULKERASE, 0); + +#if defined(CONFIG_MTD_SMART) && defined(CONFIG_FS_SMARTFS) + /* Now initialize a SMART Flash block device and bind it to the MTD device */ + + smart_initialize(CONFIG_STM32F103MINIMUM_RAMMTD_MINOR, mtd, NULL); +#endif + } + +#endif /* CONFIG_RAMMTD && CONFIG_STM32F103MINIMUM_RAMMTD */ + + return OK; +} diff --git a/configs/stm32f103-minimum/src/stm32f103_minimum.h b/configs/stm32f103-minimum/src/stm32f103_minimum.h index 17c2e4c5e01..b2cea452260 100644 --- a/configs/stm32f103-minimum/src/stm32f103_minimum.h +++ b/configs/stm32f103-minimum/src/stm32f103_minimum.h @@ -80,6 +80,9 @@ /* SPI chip selects */ +#define FLASH_SPI1_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) + #define GPIO_CS_MFRC522 (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) @@ -189,6 +192,16 @@ int stm32_gpio_initialize(void); void stm32_spidev_initialize(void); +/************************************************************************************ + * Name: stm32_w25initialize + * + * Description: + * Called to initialize Winbond W25 memory + * + ************************************************************************************/ + +int stm32_w25initialize(int minor); + /**************************************************************************** * Name: stm32_qencoder_initialize *