STM32F103-Minimum: Add support for SmartFS on Winbond W25 SPI NOR Flash

This commit is contained in:
Alan Carvalho de Assis
2017-08-06 10:38:55 -06:00
committed by Gregory Nutt
parent 9a53a2f64a
commit 0a4650d1ee
7 changed files with 455 additions and 0 deletions
+57
View File
@@ -5,6 +5,63 @@
if ARCH_BOARD_STM32F103_MINIMUM 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 config STM32F103MINIMUM_QETIMER
int "Timer to use with QE encoder" int "Timer to use with QE encoder"
default 4 default 4
+36
View File
@@ -14,6 +14,7 @@ Contents
- Using 128KiB of Flash instead of 64KiB - Using 128KiB of Flash instead of 64KiB
- Quadrature Encoder - Quadrature Encoder
- SDCard support - SDCard support
- SPI NOR Flash
- Nokia 5110 LCD Display support - Nokia 5110 LCD Display support
- USB Console support - USB Console support
- STM32F103 Minimum - specific Configuration Options - STM32F103 Minimum - specific Configuration Options
@@ -279,6 +280,41 @@ Quadrature Encoder:
In this configuration, the QEncoder inputs will be on the TIM4 inputs of In this configuration, the QEncoder inputs will be on the TIM4 inputs of
PB6 and PB7. 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: SDCard support:
=============== ===============
+4
View File
@@ -69,6 +69,10 @@ ifeq ($(CONFIG_MMCSD),y)
CSRCS += stm32_mmcsd.c CSRCS += stm32_mmcsd.c
endif endif
ifeq ($(CONFIG_MTD_W25),y)
CSRCS += stm32_w25.c
endif
ifeq ($(CONFIG_AUDIO_TONE),y) ifeq ($(CONFIG_AUDIO_TONE),y)
CSRCS += stm32_tone.c CSRCS += stm32_tone.c
endif endif
@@ -81,6 +81,30 @@
# include "stm32_rtc.h" # include "stm32_rtc.h"
#endif #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 #ifdef CONFIG_NSH_MMCSDMINOR
# define MMCSD_MINOR CONFIG_NSH_MMCSDMINOR # define MMCSD_MINOR CONFIG_NSH_MMCSDMINOR
#else #else
@@ -130,6 +154,18 @@ int stm32_bringup(void)
} }
#endif #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 #ifdef CONFIG_PWM
/* Initialize PWM and register the PWM device. */ /* Initialize PWM and register the PWM device. */
@@ -74,6 +74,10 @@ void stm32_spidev_initialize(void)
* architecture. * architecture.
*/ */
#ifdef CONFIG_MTD_W25
(void)stm32_configgpio(FLASH_SPI1_CS); /* FLASH chip select */
#endif
#ifdef CONFIG_CAN_MCP2515 #ifdef CONFIG_CAN_MCP2515
(void)stm32_configgpio(GPIO_MCP2515_CS); /* MCP2515 chip select */ (void)stm32_configgpio(GPIO_MCP2515_CS); /* MCP2515 chip select */
#endif #endif
@@ -169,6 +173,10 @@ void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid,
stm32_gpiowrite(GPIO_SDCARD_CS, !selected); stm32_gpiowrite(GPIO_SDCARD_CS, !selected);
} }
#endif #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) uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, uint32_t devid)
+301
View File
@@ -0,0 +1,301 @@
/****************************************************************************
* config/stm32f103-minimum/src/stm32_w25.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sys/mount.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <debug.h>
#ifdef CONFIG_STM32_SPI1
# include <nuttx/spi/spi.h>
# include <nuttx/mtd/mtd.h>
# include <nuttx/fs/smart.h>
# include <nuttx/mtd/configdata.h>
#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;
}
@@ -80,6 +80,9 @@
/* SPI chip selects */ /* 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|\ #define GPIO_CS_MFRC522 (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\
GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4)
@@ -189,6 +192,16 @@ int stm32_gpio_initialize(void);
void stm32_spidev_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 * Name: stm32_qencoder_initialize
* *