در بخش قبل به معرفی Spi Flash و کاربرد هایش پرداختیم همچنین با راه اندازی و نحوه ارتباط با آن اشنا شدیم همچنین به صورت کوتاه به lfs و مزیت آن نسبت به بقیه fileSystem ها پرداختیم. در این بخش کار با ایسی های حافظه در STM32 با littleFS را آموزش داده و با کانفیگ و راه اندازی آن آشنا میشویم.
کتابخانه LittleFS
ابتدا کتابخانه littleFS را دانلود کنید، سورس فایلها و هدر آن را به پروژه اضافه کنید.
#include “lfs.h”
LFS_YES_TRACE
فعال کردن TRACE برای دیباگ کردنLFS_NO_MALLOC
غیر فعال کردن استفاده از حافظه پویا
استراکچرها و بافرهای littleFS
lfs_t lfs; lfs_file_t file; static uint8_t lfs_read_cache_buf[256]; static uint8_t lfs_prog_cache_buf[256]; static uint8_t lfs_lookahead_buf[16]; // 128/8=16
آرایهها برای نوشتن و خواندن در فایلها
char WriteBuf[def_num_lfs_ram] = {"Hi,Budy! if you get this Message......Congratulations!You have succeeded!!"}; char ReadBuf[def_num_lfs_ram];
ایجاد ارتباط بین توابع spi flash و littleFS
به کمک کد زیر توابعی که برای w25q نوشتیم را به lfs معرفی میکنیم.
اگر به جای w25q قصد داشتید از Fhash داخلی میکرو (یا spiFlash دیگری) استفاده کنید، کافی است توابع erase, read, write مربوطه را قرار دهید.
static int user_provided_block_device_read(const struct lfs_config *lfsc, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) { W25Q_ReadPage((uint8_t *)buffer,(block * lfsc->block_size + off),size); return LFS_ERR_OK; } static int user_provided_block_device_prog( const struct lfs_config *lfsc, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) { W25Q_WritePage((uint8_t*)buffer,(block * lfsc->block_size + off),size); return LFS_ERR_OK; } static int user_provided_block_device_erase(const struct lfs_config *lfsc, lfs_block_t block) { W25Q_EraseSector4KB(block); return LFS_ERR_OK; } static int user_provided_block_device_sync(const struct lfs_config *lfsc) { return LFS_ERR_OK; }
کانفیگ کردن lfs
- read_size (سایز صفحات ایسی) = 256
- prog_size (سایز صفحات ایسی) = 256
- block_size (سایز سکتور ایسی(تعداد بایت)) = 4096
- block_ count تعداد سکتور موجود در ایسی مثلا w25q16 تعداد بلاکها 512 میباشد
- cache_size برابر است با read_size
- lookahead_size حاصل block_ count /8
const struct lfs_config cfg = { .context = NULL, .read = user_provided_block_device_read, .prog = user_provided_block_device_prog, .erase = user_provided_block_device_erase, .sync = user_provided_block_device_sync, .read_size = 256, .prog_size = 256, .block_size = 4096, .block_count = 512, .cache_size = 256, .block_cycles = 200, .lookahead_size = 64, .read_buffer = lfs_read_cache_buf, .prog_buffer = lfs_prog_cache_buf, .lookahead_buffer = lfs_lookahead_buf, };
دیباگ در littleFS
جهت استفاده از قابلیت دیباگ lfs باید تابع printf را به uart میکروکنترلر ریدایرکت کنیم زیرا trace ها در lfs از printf استفاده میکنند.
برای اینکار ابتدا uart سخت افزاری را کانفیگ میکنیم.
void USART_ini(){ CLEAR_BIT(USART1->CR1,USART_CR1_UE ); SET_BIT(RCC->APB2ENR,RCC_APB2ENR_USART1EN ); CLEAR_BIT(USART1->CR1,USART_CR1_OVER8 ); SET_BIT(USART1->CR1,USART_CR1_TE ); SET_BIT(USART1->CR1,USART_CR1_RE ); USART1->BRR = 0XD0; SET_BIT(USART1->CR1,USART_CR1_UE ); SET_BIT(USART1->CR1,USART_CR1_TCIE ); SET_BIT(USART1->CR1,USART_CR1_RXNEIE ); }
برای ارسال یک بایت دیتا از ریجستر tdr استفاده میکنیم
نحوه ریدایرکت کردن printf در keil
در پنجره اصلی برنامه Keil، گزینه Project را انتخاب میکنیم و از بخش Manage زیر منو Run-Time Environment را کلیک میکنیم. در پنجره باز شده از زیرمنوی Compiler پارامتر STDOUT را تغییر میدهیم:
سپس یک عدد template جدید ایجاد میکنیم:
کد زیر را در آن قرار میدهیم
int stdout_putchar (int ch) { USART1->TDR = (uint8_t)ch; while( !READ_BIT(USART1->ISR,USART_ISR_TC) ){} SET_BIT(USART1->ICR,USART_ICR_TCCF ); return (ch); }
اکنون توانسیم ریجستر trd را به printf اتصال دهیم و از قابلیتهای آن استفاده کنیم.
کد تست littleFS
کد زیر را در داخل فایل main قرار دهید، و برنامه را کامپایل کنید.
int err = lfs_mount(&lfs, &cfg); if (err) { lfs_format(&lfs, &cfg); lfs_mount(&lfs, &cfg); } lfs_file_open(&lfs, &file, "my_file", LFS_O_RDWR | LFS_O_CREAT); lfs_file_read(&lfs, &file, &ReadBuf, sizeof(ReadBuf)); lfs_file_close(&lfs, &file); lfs_unmount(&lfs); ReadBuf[0]='*'; printf("%s",ReadBuf);
اکنون در صورتی که تمام کانفیگها درست باشند، Little پیغام زیر را میدهد.
نمونه کد برای خواندن فایلی که ایجاد کردیم:
lfs_file_open(&lfs, &file, "my_file", LFS_O_RDWR | LFS_O_CREAT); lfs_file_read(&lfs, &file, &ReadBuf, sizeof(ReadBuf)); lfs_file_close(&lfs, &file); lfs_unmount(&lfs); printf("****************your DATA///////////////////-\n"); printf("*\n");printf("*\n");printf("*\n");printf("*\n");printf("*\n"); ReadBuf[0]='*'; printf("%s",ReadBuf); printf("*\n");printf("*\n");printf("*\n");printf("*\n");printf("*\n");
به این صورت کار با ایسی های حافظه در STM32 با littleFS را یاد گرفتیم.
منبع: سیسوگ