702 views|1 replies

135

Posts

0

Resources
The OP
 

How to use ESP32C3 to drive SPI NAND flash [Copy link]

I recently received a domestic industrial-grade SD NAND, which can replace SD cards. It has large capacity and surface mount packaging, making it very suitable for flight control "black box".

EEWORLDIMGTK0

NAND Flash (SMD TF card) with built-in bad block management without writing drivers, small size, easy to use, strong compatibility, stable and reliable, customizable firmware, LGA-8 package, standard SDIO interface, compatible with SPI/SD interface, compatible with major MCU platforms, can replace ordinary TF card/SD card, size 6x8mm, built-in SLC wafer erase life 100,000 times, passed 10,000 random power-off tests, high and low temperature resistance, support industrial temperature -40°~+85°, machine and hand paste are very convenient, speed level Class10 (read speed 23.5MB/S write speed 12.3MB/S) standard SD 2.0 protocol allows users to directly transplant standard driver code, eliminating the driver code programming link. SOC that supports TF card startup can use SD NAND, manufacturers provide STM32 reference routines and original technical support, mainstream capacity: 128MB/512MB/2GB/4GB/8GB, more stable than TF card, cheaper than eMMC.

The SDIO interface of ESP32C3 on the flight control board cannot be used temporarily, so it can only be driven by the SPI interface first.

EEWORLDIMGTK1

The evaluation board has a micro SD card interface, which allows it to be directly inserted into a development board with a card slot for debugging.

The SPI interface of ESP32C3 is hardware SPI, which supports DMA and the speed should be OK. However, I used Dupont wire to connect it, which will definitely affect the signal quality. I guess it will be difficult for the clock to reach 50MHz.

EEWORLDIMGTK2

wiring:

EEWORLDIMGTK3

Write a test program:

/* SD card and FAT filesystem example.

This example uses SPI peripheral to communicate with SD card.

This example code is in the Public Domain (or CC0 licensed, at your option.)

Unless required by applicable law or agreed to in writing, this

software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR

CONDITIONS OF ANY KIND, either express or implied.

*/

#include <string.h>

#include <sys/unistd.h>

#include <sys/stat.h>

#include "esp_vfs_fat.h"

#include "sdmmc_cmd.h"

#define EXAMPLE_MAX_CHAR_SIZE 64

static const char *TAG = "example";

#define MOUNT_POINT "/sdcard"

// Pin assignments can be set in menuconfig, see "SD SPI Example Configuration" menu.

// You can also change the pin assignments here by changing the following 4 lines.

#define PIN_NUM_MISO CONFIG_EXAMPLE_PIN_MISO

#define PIN_NUM_MOSI CONFIG_EXAMPLE_PIN_MOSI

#define PIN_NUM_CLK CONFIG_EXAMPLE_PIN_CLK

#define PIN_NUM_CS CONFIG_EXAMPLE_PIN_CS

static esp_err_t s_example_write_file(const char *path, char *data)

{

ESP_LOGI(TAG, "Opening file %s", path);

FILE *f = fopen(path, "w");

if (f == NULL) {

ESP_LOGE(TAG, "Failed to open file for writing");

return ESP_FAIL;

}

fprintf(f, data);

fclose(f);

ESP_LOGI(TAG, "File written");

return ESP_OK;

}

static esp_err_t s_example_read_file(const char *path)

{

ESP_LOGI(TAG, "Reading file %s", path);

FILE *f = fopen(path, "r");

if (f == NULL) {

ESP_LOGE(TAG, "Failed to open file for reading");

return ESP_FAIL;

}

char line[EXAMPLE_MAX_CHAR_SIZE];

fgets(line, sizeof(line), f);

fclose(f);

// strip newline

char *pos = strchr(line, '\n');

if (pos) {

*pos = '\0';

}

ESP_LOGI(TAG, "Read from file: '%s'", line);

return ESP_OK;

}

void app_main(void)

{

esp_err_t ret;

// Options for mounting the filesystem.

// If format_if_mount_failed is set to true, SD card will be partitioned and

// formatted in case when mounting fails.

esp_vfs_fat_sdmmc_mount_config_t mount_config = {

#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED

.format_if_mount_failed = true,

#else

.format_if_mount_failed = false,

#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED

.max_files = 5,

.allocation_unit_size = 16 * 1024

};

sdmmc_card_t *card;

const char mount_point[] = MOUNT_POINT;

ESP_LOGI(TAG, "Initializing SD card");

// Use settings defined above to initialize SD card and mount FAT filesystem.

// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.

// Please check its source code and implement error recovery when developing

// production applications.

ESP_LOGI(TAG, "Using SPI peripheral");

// By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)

// For setting a specific frequency, use host.max_freq_khz (range 400kHz - 20MHz for SDSPI)

// Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;

sdmmc_host_t host = SDSPI_HOST_DEFAULT();

spi_bus_config_t bus_cfg = {

.mosi_io_num = PIN_NUM_MOSI,

.miso_io_num = PIN_NUM_MISO,

.sclk_io_num = PIN_NUM_CLK,

.quadwp_io_num = -1,

.quadhd_io_num = -1,

.max_transfer_number = 4000,

};

ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);

if (ret != ESP_OK) {

ESP_LOGE(TAG, "Failed to initialize bus.");

return;

}

// This initializes the slot without card detect (CD) and write protect (WP) signals.

// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.

sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();

slot_config.gpio_cs = PIN_NUM_CS;

slot_config.host_id = host.slot;

ESP_LOGI(TAG, "Mounting filesystem");

ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);

if (ret != ESP_OK) {

if (ret == ESP_FAIL) {

ESP_LOGE(TAG, "Failed to mount filesystem. "

"If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");

} else {

ESP_LOGE(TAG, "Failed to initialize the card (%s). "

"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));

}

return;

}

ESP_LOGI(TAG, "Filesystem mounted");

// Card has been initialized, print its properties

sdmmc_card_print_info(stdout, card);

// Use POSIX and C standard library functions to work with files.

// First create a file.

const char *file_hello = MOUNT_POINT"/hello.txt";

char data[EXAMPLE_MAX_CHAR_SIZE];

snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Hello", card->cid.name);

ret = s_example_write_file(file_hello, data);

if (ret != ESP_OK) {

return;

}

const char *file_foo = MOUNT_POINT"/foo.txt";

// Check if destination file exists before renaming

struct stat st;

if (stat(file_foo, &st) == 0) {

// Delete it if it exists

unlink(file_foo);

}

// Rename original file

ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo);

if (rename(file_hello, file_foo) != 0) {

ESP_LOGE(TAG, "Rename failed");

return;

}

ret = s_example_read_file(file_foo);

if (ret != ESP_OK) {

return;

}

// Format FATFS

ret = esp_vfs_fat_sdcard_format(mount_point, card);

if (ret != ESP_OK) {

ESP_LOGE(TAG, "Failed to format FATFS (%s)", esp_err_to_name(ret));

return;

}

if (stat(file_foo, &st) == 0) {

ESP_LOGI(TAG, "file still exists");

return;

} else {

ESP_LOGI(TAG, "file doesnt exist, format done");

}

const char *file_nihao = MOUNT_POINT"/nihao.txt";

memset(data, 0, EXAMPLE_MAX_CHAR_SIZE);

snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Nihao", card->cid.name);

ret = s_example_write_file(file_nihao, data);

if (ret != ESP_OK) {

return;

}

//Open file for reading

ret = s_example_read_file(file_nihao);

if (ret != ESP_OK) {

return;

}

// All done, unmount partition and disable SPI peripheral

esp_vfs_fat_sdcard_unmount(mount_point, card);

ESP_LOGI(TAG, "Card unmounted");

//deinitialize the bus after all devices are removed

spi_bus_free(host.slot);

}

This code uses SPI (Serial Peripheral Interface) to communicate with the SD card. It shows how to mount the SD card, write a file, read a file, rename a file, format the SD card, and finally unmount the SD card.

The code starts by including the necessary header files and defining some constants such as the maximum character size, the mount point for the SD card, and the pin assignments for SPI communication.

Then two auxiliary functions are defined: s_example_write_file and s_example_read_file. The s_example_write_file function opens a file with a given path, writes the data, and then closes the file. If the file cannot be opened, it logs an error and returns a failure status. The s_example_read_file function opens a file with a given path, reads a line from it, and then closes the file. If the file cannot be opened, it logs an error and returns a failure status.

The app_main function is the main entry point of the program. It first defines the configuration for mounting the SD card. Then it initializes the SPI bus and the SD card slot. If the initialization fails, it logs an error and returns.

Next, it attempts to mount the SD card. If the mount fails, it logs an error and returns. If the mount succeeds, it logs a success message and prints the properties of the SD card.

The program then writes a file on the SD card, checks if another file exists, deletes it if it does, then renames the first file to the second. It then reads from the second file.

The program then formats the SD card and checks to see if the second file still exists. If so, it logs a message and returns. If not, it logs a success message, writes to the third file, and reads from the third file.

Finally, unmount the SD card and disable the SPI peripheral.

Compile:

EEWORLDIMGTK4

After burning to ESP32C3 and running, the console output is:

I (286) app_start: Starting scheduler on CPU0

I (291) main_task: Started on CPU0

I (291) main_task: Calling app_main()

I (291) example: Initializing SD card

I (301) example: Using SPI peripheral

I (301) example: Mounting filesystem

I (311) gpio: GPIO[1]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0

I (321) sdspi_transaction: cmd=52, R1 response: command not supported

I (361) sdspi_transaction: cmd=5, R1 response: command not supported

I (391) example: Filesystem mounted

Name: CS064

Type: SDHC/SDXC

Speed: 20.00 MHz (limit: 20.00 MHz)

Size: 7382MB

CSD: ver=2, sector_size=512, capacity=15118336 read_bl_len=9

SSR: bus_width=1

I (401) example: Opening file /sdcard/hello.txt

I (411) example: File written

I (411) example: Renaming file /sdcard/hello.txt to /sdcard/foo.txt

I (411) example: Reading file /sdcard/foo.txt

I (421) example: Read from file: 'Hello CS064!'

I (421) vfs_fat_sdmmc: Formatting card, allocation unit size=16384

I (2911) example: file doesnt exist, format done

I (2911) example: Opening file /sdcard/nihao.txt

I (2921) example: File written

I (2921) example: Reading file /sdcard/nihao.txt

I (2921) example: Read from file: 'Nihao CS064!'

I (2921) gpio: GPIO[1]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0

I (2931) example: Card unmounted

I (2931) gpio: GPIO[4]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0

I (2941) gpio: GPIO[6]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0

I (2951) gpio: GPIO[5]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0

I (2961) main_task: Returned from app_main()

You can see the memory card information is output:

Name: CS064

Type: SDHC/SDXC

Speed: 20.00 MHz (limit: 20.00 MHz)

Size: 7382MB

CSD: ver=2, sector_size=512, capacity=15118336 read_bl_len=9

SSR: bus_width=1

The corresponding information of reading and writing files is also output later.

This post is from Test/Measurement

Latest reply

EWORLDIMGTK0 EWORLDIMGTK1 EWORLDIMGTK2 EWORLDIMGTK3 EWORLDIMGTK4 What is it? Did it come out during editing?   Details Published on 2024-7-9 09:30
 
 

6069

Posts

4

Resources
2
 

EWORLDIMGTK0

EWORLDIMGTK1

EWORLDIMGTK2

EWORLDIMGTK3

EWORLDIMGTK4

What is it? Did it come out during editing?

This post is from Test/Measurement
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list