RT-Thread 直接使用spi flash设备

文章目录

如果我们不想使用文件系统,要直接读写spi flash,直接调用read和write就行了,但是read和write是读写一个扇区的,不能随机地址读写,如果要随机读写一个地址,需要对其进行封装一下。

这里直接上代码了,代码也比较简单,就不注释了。

#include "spi_flash.h"
#include <rtthread.h>


#define SPI_FLASH_SECTOR_MAX_SIZE   4096

static struct rt_mutex spi_flash_mutex;
static unsigned char flash_buf[SPI_FLASH_SECTOR_MAX_SIZE];

static rt_device_t spi_flash_dev; 
static struct rt_device_blk_geometry spi_flash_geometry;

rt_err_t spi_flash_init(const char *flash_name)
{
    rt_err_t res = RT_ERROR;
    rt_mutex_init(&spi_flash_mutex, "flash_mtx", RT_IPC_FLAG_FIFO);
    

	
	spi_flash_dev = rt_device_find(flash_name);
    if (!spi_flash_dev) {
        rt_kprintf("find %s failed!\n", flash_name);
        return res;
    }
	
	res = rt_device_open(spi_flash_dev, RT_DEVICE_OFLAG_RDWR);
	if (res != RT_EOK) {
        rt_kprintf("open spi_flash_dev failed!\n");
        return res;
    }
	rt_kprintf("initialize spiFlash success!\n");
	res = rt_device_control(spi_flash_dev, RT_DEVICE_CTRL_BLK_GETGEOME, &spi_flash_geometry);
	rt_kprintf("block_size : %d, bytes_per_sector : %d, sector_count : %d\n", 
			   spi_flash_geometry.block_size, spi_flash_geometry.bytes_per_sector, spi_flash_geometry.sector_count);
    return res;
}


rt_err_t spi_flash_read(rt_uint8_t flash_id, rt_uint32_t addr, rt_uint8_t *buffer, rt_uint32_t buffer_len)
{
	rt_device_t flash_dev;
	struct rt_device_blk_geometry *geometry;
	rt_uint32_t sector = 0;
	rt_uint32_t offset = 0;
	rt_uint32_t remain = 0;
	
	rt_mutex_take(&spi_flash_mutex, RT_WAITING_FOREVER);

    flash_dev = spi_flash_dev;
    geometry = &spi_flash_geometry;
	if (flash_dev == RT_NULL) {
		rt_mutex_release(&spi_flash_mutex);
		return -RT_ERROR;
	}
    
	sector = addr/geometry->bytes_per_sector;
	offset = addr%geometry->bytes_per_sector;
	remain = geometry->bytes_per_sector - offset;
	if (remain >= buffer_len)
		remain = buffer_len;
	if (sector >= geometry->sector_count || buffer_len > geometry->bytes_per_sector) {
		rt_kprintf("spi_flash_read failed. sector : %d >= %d, buffer_len : %d > %d\n",
				   sector, geometry->sector_count, buffer_len, geometry->bytes_per_sector);
		rt_mutex_release(&spi_flash_mutex);
		return -RT_ERROR;
	}
	while (1) {
		rt_device_read(flash_dev, sector, flash_buf, 1);
		rt_memcpy(buffer, &flash_buf[offset], remain);
		
		if (remain == buffer_len) {
			break;
		} else {
			buffer += remain;
			buffer_len -= remain;
			offset = 0;
			++sector;
			if (buffer_len > geometry->bytes_per_sector)
				remain = geometry->bytes_per_sector;
			else
				remain = buffer_len;
		}
	}
	
	rt_mutex_release(&spi_flash_mutex);
	return RT_EOK;
}

rt_err_t spi_flash_write(rt_uint8_t flash_id, rt_uint32_t addr, rt_uint8_t *buffer, rt_uint32_t buffer_len)
{
	rt_err_t res = -RT_ERROR;
	
	rt_device_t flash_dev;
	struct rt_device_blk_geometry *geometry;
	rt_uint32_t sector = 0, offset = 0, remain = 0;
	
	rt_mutex_take(&spi_flash_mutex, RT_WAITING_FOREVER);
	
    flash_dev = spi_flash_dev;
    geometry = &spi_flash_geometry;
	if (flash_dev == RT_NULL) {
		rt_mutex_release(&spi_flash_mutex);
		return -RT_ERROR;
	}
	
	sector = addr/geometry->bytes_per_sector;
	offset = addr%geometry->bytes_per_sector;
	remain = geometry->bytes_per_sector - offset;
	
	if (remain >= buffer_len)
		remain = buffer_len;
	while (1) {
		if (sector >= geometry->sector_count) {
			rt_kprintf("bsk_flash_write failed. sector : %d >= %d\n", sector, geometry->sector_count);
			return -RT_ERROR;
		}
		rt_device_read(flash_dev, sector, flash_buf, 1);
		rt_memcpy(&flash_buf[offset], buffer, remain);
		rt_device_write(flash_dev, sector, flash_buf, 1);
		if (remain == buffer_len) {
			break;
		} else {
			buffer += remain;
			buffer_len -= remain;
			offset = 0;
			++sector;
			if (buffer_len > geometry->bytes_per_sector)
				remain = geometry->bytes_per_sector;
			else
				remain = buffer_len;
		}
	}
	res = RT_EOK;
ERR:
	rt_mutex_release(&spi_flash_mutex);
	return res;
}

rt_err_t spi_flash_erase(rt_uint8_t flash_id, rt_uint32_t sector)
{
	rt_device_t flash_dev;
	
    flash_dev = spi_flash_dev;

	if (flash_dev == RT_NULL) {
		return -RT_ERROR;
	}
	
	return rt_device_control(flash_dev, RT_DEVICE_CTRL_BLK_ERASE, &sector);
}
FINSH_FUNCTION_EXPORT_ALIAS(spi_flash_erase, flash_erase, spi_flash_erase)

void flash_rd_test(int flash_id, int sector)
{
	rt_uint32_t i;
	rt_device_t flash_dev;
	struct rt_device_blk_geometry *geometry;
	

		flash_dev = spi_flash_dev;
		geometry = &spi_flash_geometry;
	if (flash_dev == RT_NULL) {
		return ;
	}
	
	rt_device_read(flash_dev, sector, flash_buf, 1);
	rt_kprintf("read sector : %d\n", sector);
	for (i = 0; i < geometry->bytes_per_sector; ++i) {
		
		if (i%64 == 0) {
			rt_kprintf("\n");
		}
		rt_kprintf("%x ", flash_buf[i]);
	}
	rt_kprintf("\n");
}
FINSH_FUNCTION_EXPORT(flash_rd_test, flash_rd_test(flash_id,sector))

void flash_wr_test(int flash_id, int sector, rt_uint8_t value)
{
	unsigned char buf[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
	rt_device_t flash_dev;
	struct rt_device_blk_geometry *geometry;
	
		flash_dev = spi_flash_dev;
		geometry = &spi_flash_geometry;

	if (flash_dev == RT_NULL) {
		return ;
	}
	spi_flash_write(flash_id, sector*geometry->bytes_per_sector, buf, 10);
}
FINSH_FUNCTION_EXPORT(flash_wr_test, flash_wr_test(id, sector, value))


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值