RT-Thread 中用内存模拟flash挂载elf文件

    手上有个stm32开发板,想用内部flash挂载文件系统,查看网上资料,都是创建了一个fal或者littlefs的中间层,不想搞那么复杂了,想着直接挂载elf文件系统。第一步,先用内存模拟flash的读写,跳过flash读写失败的因素。

   第一步,直接注册进IO一个设备,使用一下代码后,在shell中使用list_device可以看到 elf0的设备。

elf_device->parent.type 		= RT_Device_Class_Block;
/* register key device to RT-Thread */
rt_device_register(&(elf_device->parent), "elf0", RT_DEVICE_FLAG_RDWR);

 第二步,添加设备驱动的opt函数。

/*
 * File      : touch.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2010, RT-Thread Develop Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2010-10-01     Yi.Qiu      first version
 */

 /* 
  * Warning, this keypad driver can only work on QEMU emulator 
  */
     
#include <rtthread.h>
#include <rthw.h>

#define ELF_SECTOR_SIZE 64
#define SDCARD_SIM  "sd.bin"
#define SDCARD_SIZE (24*2*512)  //16k

#define SDCARD_DEVICE(device)       (( struct rt_elf_device*)(device))

struct rt_elf_device
{
	struct rt_device parent;
	rt_uint32_t  user_data;
	unsigned char *ptr;
};	
static struct rt_elf_device *elf_device = RT_NULL;


static rt_mutex_t lock;

/* RT-Thread device interface */

static rt_err_t rt_sdcard_init(rt_device_t dev)
{
	rt_kprintf("rt_sdcard_init\n");
	
    return RT_EOK;
}

static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
{
	rt_kprintf("rt_sdcard_open\n");
	
    return RT_EOK;
}

static rt_err_t rt_sdcard_close(rt_device_t dev)
{
	rt_kprintf("rt_sdcard_close\n");
	
    return RT_EOK;
}

/* position: block page address, not bytes address
 * buffer:
 * size  : how many blocks
 */
static rt_size_t rt_sdcard_read(rt_device_t device, rt_off_t position, void *buffer, rt_size_t size)
{
    struct rt_elf_device *sd;
    int result = 0;

    rt_kprintf("sd read: pos %d, size %d\n", position, size);

    rt_mutex_take(lock, RT_WAITING_FOREVER);
    sd = SDCARD_DEVICE(device);
    memcpy(buffer, sd->ptr+position*ELF_SECTOR_SIZE, size*ELF_SECTOR_SIZE);

    rt_mutex_release(lock);
    return size;

_err:
    rt_kprintf("sd read errors!\n");
    rt_mutex_release(lock);
    return 0;
}

/* position: block page address, not bytes address
 * buffer:
 * size  : how many blocks
 */
static rt_size_t rt_sdcard_write(rt_device_t device, rt_off_t position, const void *buffer, rt_size_t size)
{
    struct rt_elf_device *sd;
    int result = 0;

    rt_kprintf("sd write: pos %d, size %d\n", position, size);

    rt_mutex_take(lock, RT_WAITING_FOREVER);
    sd = SDCARD_DEVICE(device);
	memcpy(sd->ptr+position*ELF_SECTOR_SIZE, buffer,size*ELF_SECTOR_SIZE);
    rt_mutex_release(lock);
    return size;

_err:
    rt_kprintf("sd write errors!\n");
    rt_mutex_release(lock);
    return 0;
}

static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
{
    struct rt_elf_device *sd;
    unsigned int size;

    RT_ASSERT(dev != RT_NULL);

    sd = SDCARD_DEVICE(dev);

	

    if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
    {
        struct rt_device_blk_geometry *geometry;

        geometry = (struct rt_device_blk_geometry *)args;
        if (geometry == RT_NULL) return -RT_ERROR;

        geometry->bytes_per_sector = ELF_SECTOR_SIZE;
        geometry->block_size = ELF_SECTOR_SIZE;
        geometry->sector_count = SDCARD_SIZE / ELF_SECTOR_SIZE;

		rt_kprintf("rt_sdcard_control bytes_per_sector = %d, bytes_per_sector = %d, \
			sector_count = %d\n", geometry->bytes_per_sector, geometry->block_size, geometry->sector_count);
    }
    return RT_EOK;
}


rt_err_t rt_hw_sdcard_init(const char *spi_device_name)
{
	//创建锁
    lock = rt_mutex_create("lock", RT_IPC_FLAG_FIFO);
	//申请控件

	elf_device = (struct rt_elf_device*)rt_malloc (sizeof(struct rt_elf_device));
	if (elf_device == RT_NULL) 
	{
		rt_kprintf("rt_elf_device malloc error, no memory!\n");
		return RT_ERROR; /* no memory yet */
	}

    elf_device->ptr = (unsigned char *) rt_malloc(SDCARD_SIZE);
    if (elf_device->ptr == NULL)
    {
        rt_kprintf("malloc error, no memory!\n");
        return RT_ERROR;
    }
	rt_memset((elf_device->ptr), 0, SDCARD_SIZE);
	/* clear device structure */
	rt_memset(&(elf_device->parent), 0, sizeof(struct rt_device));
	

	elf_device->parent.init 		= rt_sdcard_init;
	elf_device->parent.open		= rt_sdcard_open;
	elf_device->parent.close		= rt_sdcard_close;
	elf_device->parent.read 		= rt_sdcard_read;
	elf_device->parent.write 		= rt_sdcard_write;
	elf_device->parent.control 	= rt_sdcard_control;
	elf_device->parent.user_data   = RT_NULL;
	elf_device->parent.type 		= RT_Device_Class_Block;
	/* register key device to RT-Thread */
	rt_device_register(&(elf_device->parent), "elf0", RT_DEVICE_FLAG_RDWR);

    return RT_EOK;
}

INIT_BOARD_EXPORT(rt_hw_sdcard_init);//添加自动调用

 第三步,挂载设备。

#ifdef RT_USING_DFS_ELMFAT
int elffs_mount(void)
{

        /* init the elm chan FatFs filesystam*/
        elm_init();

        /* mount sd card fat partition 1 as root directory */
        if(dfs_mount("elf0", "/", "elm", 0, 0) == 0)
        {
            rt_kprintf("elm File System initialized!\n");
        }
        else
    	{
	    	if(dfs_mkfs("elm", "elf0") == 0)
	        {
	            if (dfs_mount("elf0", "/", "elm", 0, 0) == 0)
	            {
	                rt_kprintf("elm file system initialization done!\n");
	            }
	            else
	            {
	                rt_kprintf("elm file system initialization failed!\n");
	            }
	        }
    	}
}
#endif

INIT_APP_EXPORT(elffs_mount);

第四步,测试,通过msh />echo "hello" my.txt和msh />cat my.txt进行测试,测试结果如下:

 \ | /
- RT -     Thread Operating System
 / | \     3.1.0 build Mar  2 2021
 2006 - 2018 Copyright by rt-thread team
hwtimer0 register success
rt_sdcard_init
rt_sdcard_open
rt_sdcard_control bytes_per_sector = 128, bytes_per_sector = 128,                       sector_count = 192
sd read: pos 0, size 1
rt_sdcard_close
rt_sdcard_open
rt_sdcard_control bytes_per_sector = 128, bytes_per_sector = 128,                       sector_count = 192
rt_sdcard_control bytes_per_sector = 128, bytes_per_sector = 128,                       sector_count = 192
sst write: pos 0, size 1
sst write: pos 1, size 1
sst write: pos 2, size 1
sst write: pos 3, size 1
sst write: pos 4, size 1
sst write: pos 5, size 1
sst write: pos 6, size 1
sst write: pos 7, size 1
sst write: pos 8, size 1
sst write: pos 9, size 1
sst write: pos 10, size 1
sst write: pos 11, size 1
sst write: pos 12, size 1
sst write: pos 13, size 1
sst write: pos 14, size 1
sst write: pos 15, size 1
sst write: pos 16, size 1
sst write: pos 17, size 1
sst write: pos 18, size 1
sst write: pos 19, size 1
sst write: pos 20, size 1
sst write: pos 21, size 1
sst write: pos 22, size 1
sst write: pos 23, size 1
sst write: pos 24, size 1
sst write: pos 25, size 1
sst write: pos 26, size 1
sst write: pos 27, size 1
sst write: pos 28, size 1
sst write: pos 29, size 1
sst write: pos 30, size 1
sst write: pos 31, size 1
sst write: pos 32, size 1
sst write: pos 33, size 1
rt_sdcard_close
rt_sdcard_open
rt_sdcard_control bytes_per_sector = 128, bytes_per_sector = 128,                       sector_count = 192
sd read: pos 0, size 1
elm file system initialization done!
msh />ls
Directory /:
sd read: pos 2, size 1
msh />echo "hello" my.txt
sst write: pos 2, size 1
sd read: pos 1, size 1
sst write: pos 34, size 1
sst write: pos 1, size 1
sd read: pos 2, size 1
sst write: pos 2, size 1
msh />ls
Directory /:
MY.TXT              5                        
msh />cat my.txt
sd read: pos 34, size 1
hellomsh />

遇到的问题:

1、需要在menuconfig中打开RT_USING_DFS_ELMFAT

2、在dfs_mkfs提示fomat error, result=14的错误,看源码发现sector_count过小,必须大于128,修改后正常

3、系统如何知道flash的扇区大小,扇区数量,通过ioctl的cmd RT_DEVICE_CTRL_BLK_GETGEOME,编写程序给geometry结构体赋值
/**
 * block device geometry structure
 */
struct rt_device_blk_geometry
{
    rt_uint32_t sector_count;                           /**< count of sectors */
    rt_uint32_t bytes_per_sector;                       /**< number of bytes per sector */
    rt_uint32_t block_size;                             /**< number of bytes to erase one block */
};

猜你喜欢

转载自blog.csdn.net/tianxin1010/article/details/114320820