0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何使用ESP32C3驅(qū)動SPI NAND flash

深圳市雷龍發(fā)展有限公司 ? 2024-07-08 18:04 ? 次閱讀

最近收到了一片國產(chǎn)工業(yè)級SD NAND,可以替代SD卡,容量大,貼片封裝,非常適合做飛控"黑匣子"。

不用寫驅(qū)動程序自帶壞塊管理的NAND Flash(貼片式TF卡),尺寸小巧,簡單易用,兼容性強,穩(wěn)定可靠,固件可定制,LGA-8封裝,標準SDIO接口,兼容SPI/SD接口,兼容各大MCU平臺,可替代普通TF卡/SD卡,尺寸6x8mm毫米,內(nèi)置SLC晶圓擦寫壽命10萬次,通過1萬次隨機掉電測試耐高低溫,支持工業(yè)級溫度-40°~+85°,機貼手貼都非常方便,速度級別Class10(讀取速度23.5MB/S寫入速度12.3MB/S)標準的SD 2.0協(xié)議使得用戶可以直接移植標準驅(qū)動代碼,省去了驅(qū)動代碼編程環(huán)節(jié)。支持TF卡啟動的SOC都可以用SD NAND,廠商提供了STM32參考例程及原廠技術(shù)支持,主流容量:128MB/512MB/2GB/4GB/8GB,比TF卡穩(wěn)定,比eMMC便宜。

飛控板上ESP32C3的SDIO接口暫時用不了,只能先用SPI接口驅(qū)動。

get?code=NDUyZWIyNTFlMjA2ZDlkZDZkYzg3Zjk4YzYxZWY1YjMsMTcyMDQyODQ2MjcxNg==

評估板做了個micro SD卡的接口,方便直接插到帶卡槽的開發(fā)板上進行調(diào)試。

ESP32C3的SPI接口是硬件SPI,支持DMA,速度應(yīng)該還可以,但是我用杜邦線連接的,肯定會影響信號質(zhì)量,估計時鐘很難跑到50MHz了。

get?code=MGUwYjExZjhkYTY0ZGJhMzZiNjg0OTI3OTAyZDc5N2QsMTcyMDQyODQ2MjcxNg==

接線:

get?code=ZTViMDUxODU5ZDg3OGMyZTBhMzEzNjkzZDExNGE3YjMsMTcyMDQyODQ2MjcxNg==

編寫測試程序:

/* 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

#include

#include

#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_sz = 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);

}

這段代碼是使用SPI(串行外設(shè)接口)與SD卡進行通信。它展示了如何掛載SD卡、寫入文件、讀取文件、重命名文件、格式化SD卡,最后卸載SD卡。

代碼首先包含了必要的頭文件,并定義了一些常量,如最大字符大小、SD卡的掛載點和SPI通信的引腳分配。

然后定義了兩個輔助函數(shù):s_example_write_file和s_example_read_file。s_example_write_file函數(shù)打開一個給定路徑的文件,寫入數(shù)據(jù),然后關(guān)閉文件。如果無法打開文件,它會記錄一個錯誤并返回失敗狀態(tài)。s_example_read_file函數(shù)打開一個給定路徑的文件,從中讀取一行,然后關(guān)閉文件。如果無法打開文件,它會記錄一個錯誤并返回失敗狀態(tài)。

app_main函數(shù)是程序的主入口點。它首先定義了掛載SD卡的配置。然后初始化SPI總線和SD卡插槽。如果初始化失敗,它會記錄一個錯誤并返回。

接下來,它試圖掛載SD卡。如果掛載失敗,它會記錄一個錯誤并返回。如果掛載成功,它會記錄一個成功消息并打印SD卡的屬性。

程序然后在SD卡上寫入一個文件,檢查另一個文件是否存在,如果存在則刪除它,然后將第一個文件重命名為第二個文件。然后從第二個文件中讀取。

程序接著格式化SD卡,并檢查第二個文件是否仍然存在。如果存在,它會記錄一個消息并返回。如果不存在,它會記錄一個成功消息,寫入第三個文件,并從第三個文件中讀取。

最后,卸載SD卡并禁用SPI外設(shè)。

編譯:

get?code=M2FlZWVlYmQ1OWEzOWM5MzQyODNmNzA4ODM4ZWExYzIsMTcyMDQyODQ2MjcxNg==

燒寫到ESP32C3后運行,控制臺輸出:

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()

可以看到輸出了存儲卡信息

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

后面還輸出了讀寫文件相應(yīng)的信息。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • FlaSh
    +關(guān)注

    關(guān)注

    10

    文章

    1634

    瀏覽量

    148006
  • SPI
    SPI
    +關(guān)注

    關(guān)注

    17

    文章

    1706

    瀏覽量

    91563
  • 存儲芯片
    +關(guān)注

    關(guān)注

    11

    文章

    897

    瀏覽量

    43143
  • ESP32
    +關(guān)注

    關(guān)注

    18

    文章

    971

    瀏覽量

    17243
收藏 人收藏

    評論

    相關(guān)推薦

    基于XIAO ESP32C3的智能家居四路控制器設(shè)計

    今天小編給大家?guī)淼氖怯《鹊腗aker Technolab creation的基于ESP32C3的智能家居四路控制器,該控制器可以通過傳統(tǒng)的手動開關(guān)按鈕、紅外遙控器、智能手機進行控制,同時手機上也可以實時顯示溫度和濕度,可以實現(xiàn)無縫銜接的智能家居體驗。
    的頭像 發(fā)表于 01-02 10:53 ?1704次閱讀
    基于XIAO <b class='flag-5'>ESP32C3</b>的智能家居四路控制器設(shè)計

    ESP32C3串口打印數(shù)據(jù)

    、Quad SPI 和 QPI 接口外接多個 flash,滿足各類物聯(lián)網(wǎng)產(chǎn)品功能需求。 串口打印數(shù)據(jù)是嵌入式應(yīng)用中常用的功能,可以用于輸出程序的運行信息。 開發(fā)環(huán)境搭建 樂鑫公司為開發(fā)ESP32C3提供了
    發(fā)表于 01-13 14:49

    esp32c3項目采用wss_server例程,把wifi斷開的話esp32c3會重啟,為什么?

    esp32c3項目采用wss_server 例程,運行后連接WiFi正常,但是如果之后把wifi斷開的話,esp32c3會重啟,監(jiān)視器顯示“assert failed: tlsf_free
    發(fā)表于 06-06 07:29

    idf.py set-target esp32c3無法生效怎么解決?

    idf version: v5.1.2 之前使用的環(huán)境是esp32,然后安裝了esp32c3,現(xiàn)在編譯完下載會出錯,具體操作如下: xin_li@DESKTOP-SH0LJ3
    發(fā)表于 06-06 06:43

    采用esp-hosted的spi連接的方式連接esp32c3與linux主機,esp32c3收到的包的數(shù)據(jù)是錯的,如何避免?

    idf版本:v5.0.3 問題描述:采用esp-hosted的spi連接的方式連接esp32c3與linux主機,在使用iperf3測試軟件發(fā)現(xiàn),e
    發(fā)表于 06-06 08:28

    windowns環(huán)境下esp32c3如何解除flash加密?

    /projects/esp-idf/zh_CN/v4.3.2/esp32c3/security/flash-encryption.html#updating-encrypted-flash-serial 這個方法操作
    發(fā)表于 06-14 06:05

    esp32c3怎樣保護flash中的代碼不被拷貝?

    想知道這個c3怎樣保護flash中的代碼不被拷貝。這個內(nèi)置flash中的代碼有沒有可能被拷貝出來,如果可以拷貝,應(yīng)該怎樣保護。 另一個問題 esp32c3的gpio是否是容忍5v。
    發(fā)表于 06-19 06:32

    如何使用ESP32C3驅(qū)動SPI NAND flash

    TF卡穩(wěn)定,比eMMC便宜。 飛控板上ESP32C3的SDIO接口暫時用不了,只能先用SPI接口驅(qū)動。 []() 評估板做了個micro SD卡的接口,方便直接插到帶卡槽的開發(fā)板上進行調(diào)試
    發(fā)表于 07-08 17:55

    windowns環(huán)境下esp32c3如何解除flash加密?

    硬件環(huán)境:開發(fā)板ESP32-C3-DevkjtM-1IDF環(huán)境:IDF-4.3如題,在使用flash_encryption這個例程時,在第一次已經(jīng)燒寫固件進去,flash加密的情況下,又燒寫了一次
    發(fā)表于 02-13 08:25

    使用ESP32C3,用ESP-IDF編譯bt_hid_mouse_device例程失敗報錯如何解決?

    /CMakeFiles/__idf_spi_flash.dir/esp32c3/spi_flash_rom_patch.c.obj[22/88] Building C object
    發(fā)表于 02-14 08:27

    esp32c3怎樣保護flash中的代碼不被拷貝?

    想知道這個c3怎樣保護flash中的代碼不被拷貝。這個內(nèi)置flash中的代碼有沒有可能被拷貝出來,如果可以拷貝,應(yīng)該怎樣保護。另一個問題 esp32c3的gpio是否是容忍5v。
    發(fā)表于 02-17 08:28

    【開源資料】使用ESP32C3超簡單制作迷你四足機器人

    使用Arduino IDE開發(fā),esp32開發(fā)需要先安裝ESP32 SDK后,開發(fā)板選擇ESP32C3,合宙的ESP32C3開發(fā)板Flash
    發(fā)表于 09-21 11:15

    深入剖析esp32c3的系統(tǒng)底層啟動

    riscv底層的愛好者來說,跳過ESP-IDF框架,直接像使用單片機一樣去使用ESP32C3更加有意思。本文的目的就是理解ESP32C3的裸機開發(fā)流程,像玩單片機一樣去使用這個riscv的mcu。 2.
    的頭像 發(fā)表于 07-06 10:38 ?1.3w次閱讀
    深入剖析<b class='flag-5'>esp32c3</b>的系統(tǒng)底層啟動

    基于nanoESP32-C3開發(fā)板用ESP32-c3下試跑Zephyr

    zephyr main,就拿來試跑一下。 想要在esp32-c3上嘗鮮的同學(xué)請注意,目前esp32-c3剛剛把soc移植進去,對驅(qū)動支援有限,要實際使用可能還有比較長的一段路要走。 Zephyr
    的頭像 發(fā)表于 08-09 09:10 ?9405次閱讀

    【DFRobot Beetle ESP32-C3開發(fā)板試用體驗】刷寫micropython固件

    --port COM3 erase_flash esptool.py --chip esp32c3 --port COM3 --baud 460800 write_
    的頭像 發(fā)表于 11-28 14:02 ?2715次閱讀
    【DFRobot Beetle <b class='flag-5'>ESP32-C3</b>開發(fā)板試用體驗】刷寫micropython固件