文章目录
- 1 前言
- 2 接口实现
- 2.1 i2c收发函数实现
- 2.2 页写延时函数
- 2.3 写保护函数
- 2.4 设备注册
- 3 对接RT-Thread设备驱动
- 3.1 标准设备驱动接口
- 3.2 注册到RT-Thread
- 3.3 导出到msh
- 3.4 测试
- 4 相关文章
- 5 代码仓库
1 前言
在此之前编写了一个24系列(i2c接口)EEPROM/FRAM通用驱动库。RT-Thread提供了一个完善的设备管理驱动框架,使得设备可以像访问文件一样访问,甚至支持POSIX标准(open、read、write、close
)。现把EEPROM/FRAM通用驱动库移植到RT-Thread上。
2 接口实现
驱动库做了良好的分层处理,移植到RT-Thread上只需实现_24cxx_dev_t
数据结构中的i2c收发函数i2c_send_thend_recv
和i2c_send_thend_send
即可。
typedef struct
{
int (*i2c_send_thend_recv)(uint8_t slave_addr, const void *send_buff,
uint32_t send_size, void *recv_buff, uint32_t recv_size);
int (*i2c_send_thend_send)(uint8_t slave_addr, const void *send_buff1,
uint32_t send_size1,const void *send_buff2, uint32_t send_size2);
uint8_t slave_addr;
_24_model_t model;
void(*wp)(uint8_t ctrl);
void(*page_write_delay)(void);
}_24cxx_dev_t;
i2c_send_thend_recv
,i2c“发送-接收”函数i2c_send_thend_send
,i2c“发送-发送”函数slave
,器件i2c地址,不包含读写位,如0x50wp
,写包含函数,器件wp引脚控制page_write_delay
,页写延时函数,对于EEPROM使用;FRAM则无需
2.1 i2c收发函数实现
“发送-接收” 函数用于读取i2c器件的寄存器值,对于EEPROM/FRAM则是读取存储地址的数据。
static int hw_i2c_send_then_recv(rt_uint8_t slave_addr, const void *send_buff,
rt_uint32_t send_size, void *recv_buff, rt_uint32_t recv_size)
{
struct rt_i2c_msg ee24_msg[2];
rt_uint8_t ret_size = 0;
ee24_msg[0].addr = slave_addr;
ee24_msg[0].flags = RT_I2C_WR;
ee24_msg[0].buf = (rt_uint8_t*)send_buff;
ee24_msg[0].len = send_size;
ee24_msg[1].addr = slave_addr;
ee24_msg[1].flags = RT_I2C_RD;
ee24_msg[1].buf = (rt_uint8_t*)recv_buff;
ee24_msg[1].len = recv_size;
ret_size = rt_i2c_transfer(rt_at24c_i2c, ee24_msg, 2);
if (ret_size == 2)
{
return _24CXX_OK;
}
else
{
return _24CXX_ERR_I2C_WR;
}
}
“发送-发送” 函数用于向i2c器件的寄存器写入数据,对于EEPROM/FRAM则是向存储地址写入数据。
static int hw_i2c_send_then_send(rt_uint8_t slave_addr, const void *send_buff1,
rt_uint32_t send_size1,const void *send_buff2, rt_uint32_t send_size2)
{
struct rt_i2c_msg ee24_msg[2];
rt_uint8_t ret_size = 0;
ee24_msg[0].buf = (rt_uint8_t*)send_buff1;
ee24_msg[0].addr = slave_addr;
ee24_msg[0].flags = RT_I2C_WR;
ee24_msg[0].len = send_size1;
ee24_msg[1].addr = slave_addr;
ee24_msg[1].flags = RT_I2C_WR | RT_I2C_NO_START;
ee24_msg[1].buf = (rt_uint8_t*)send_buff2;
ee24_msg[1].len = send_size2;
ret_size = rt_i2c_transfer(rt_at24c_i2c, ee24_msg, 2);
if (ret_size == 2)
{
return _24CXX_OK;
}
else
{
return _24CXX_ERR_I2C_WR;
}
}
2.2 页写延时函数
页写延时函数用于EEPROM相邻两页写入的等待时间。对于FRAM则不需要,因为FRAM写入速率快。本次测试的是FRAM,所以该函数为NULL。
void hw_page_write_delay(void)
{
rt_thread_mdelay(1);
}
2.3 写保护函数
写保护,指的是器件的“wp”控制引脚;高电平时禁止写入;低电平允许写入;用于保护数据,防止意外被修改。因此,写保护函数即是一个GPIO控制函数。如果“wp”引脚常接地,该函数为NULL即可。
void hw_wp_ctrl(rt_uint8_t ctrl)
{
rt_pin_write(10, ctrl);
}
2.4 设备注册
const _24cxx_dev_t at24cxx_dev =
{
hw_i2c_send_then_recv,
hw_i2c_send_then_send,
0x50,
_24C04_E,
RT_NULL,
RT_NULL,
};
3 对接RT-Thread设备驱动
3.1 标准设备驱动接口
分别实现RT-Thread设备驱动的open、read、write
函数实体。
static rt_size_t rt_at24cxx_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
_24cxx_dev_t *p = RT_NULL;
rt_int16_t ret = _24CXX_OK;
p = (_24cxx_dev_t*)dev->user_data;
ret = _24cxx_read(p, pos, buffer, size);
if (_24CXX_OK == ret)
{
return size;
}
else
{
return RT_ERROR;
}
}
static rt_size_t rt_at24cxx_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
_24cxx_dev_t *p = RT_NULL;
rt_int16_t ret = _24CXX_OK;
p = (_24cxx_dev_t*)dev->user_data;
ret = _24cxx_write(p, pos, (rt_uint8_t*)buffer, size);
if (_24CXX_OK == ret)
{
return size;
}
else
{
return RT_ERROR;
}
}
- RT-Thread
rt_device_t
提供一个私有数据user_data
,我们用来保存EEPROM/FRAM驱动库设备_24cxx_dev_t
。
3.2 注册到RT-Thread
最后将EEPROM/FRAM设备注册设备到RT-Thread设备管理框架中。
int rt_hw_at24cxx_init(void)
{
rt_at24c_i2c = rt_i2c_bus_device_find(AT24CXX_I2C_BUS);
if (rt_at24c_i2c == RT_NULL)
{
LOG_E("i2c bus device %s not found!\r\n", AT24CXX_I2C_BUS);
return -RT_ERROR;
}
rt_at24c_dev.type = RT_Device_Class_Char;
rt_at24c_dev.init = RT_NULL;
rt_at24c_dev.open = rt_at24cxx_open;
rt_at24c_dev.close = RT_NULL;
rt_at24c_dev.read = rt_at24cxx_read;
rt_at24c_dev.write = rt_at24cxx_write;
rt_at24c_dev.control= RT_NULL;
rt_at24c_dev.user_data = (void*)&at24cxx_dev; ;
rt_device_register(&rt_at24c_dev, AT24CXX_DEVICE_NAME, RT_DEVICE_FLAG_RDWR);
LOG_D("at24cxx init succeed!\r\n");
return 0;
}
INIT_DEVICE_EXPORT(rt_hw_at24cxx_init);
3.3 导出到msh
为了方便测试,我们将读写功能到出到RT-Thread msh中。包括:
详细实现过程,查阅文章末尾源代码。
3.4 测试
msh >list_device
device type ref count
-------- -------------------- ----------
24cxx Character Device 0
i2c1 I2C Bus 0
pin Miscellaneous Device 0
uart2 Character Device 0
uart1 Character Device 2
msh >_24cxx_wr
usage:
_24cxx_wr [eeprom dev] r - read 24cxx
_24cxx_wr [eeprom dev] w - write 24cxx
_24cxx_wr [eeprom dev] e - erase 24cxx
_24cxx_wr 24cxx r
_24cxx_wr 24cxx w
_24cxx_wr 24cxx e
4 相关文章
【1】24系列EEPROM/FRAM通用接口
5 代码仓库
【1】GitHub
【2】码云
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)