NUCLEO-F411RE RT-Thread 体验 (10) - GCC环境 AT24CXX的使用
1、AT24CXX的移植
在reconfigure.h添加at24cxx的定义
Makefile里添加编译
这里我放在了User目录下,里面所有的.c文件都会被编译进去。
2、测试
封装一个结构体,将结构体填充后,写到eeprom中,然后从eeprom读出来,看数据是否一致。
结构体大小为120K,最小的at24c01 128K字节,也能读写。
at24C02测试如下:
at24C256测试如下:
3、修改后的代码
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-13 XiaojieFan the first version
* 2019-12-04 RenMing ADD PAGE WRITE and input address can be selected
* 2022-10-11 GuangweiRen Delay 2ms after writing one byte
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <string.h>
#include <stdlib.h>
#define DBG_ENABLE
#define DBG_SECTION_NAME "at24xx"
#define DBG_LEVEL DBG_LOG
#define DBG_COLOR
#include <rtdbg.h>
#include "at24cxx.h"
#ifdef PKG_USING_AT24CXX
#define AT24CXX_ADDR (0xA0 >> 1) //A0 A1 A2 connect GND
#if (EE_TYPE == AT24C01)
#define AT24CXX_PAGE_BYTE 8
#define AT24CXX_MAX_MEM_ADDRESS 128
#elif (EE_TYPE == AT24C02)
#define AT24CXX_PAGE_BYTE 8
#define AT24CXX_MAX_MEM_ADDRESS 256
#elif (EE_TYPE == AT24C04)
#define AT24CXX_PAGE_BYTE 16
#define AT24CXX_MAX_MEM_ADDRESS 512
#elif (EE_TYPE == AT24C08)
#define AT24CXX_PAGE_BYTE 16
#define AT24CXX_MAX_MEM_ADDRESS 1024
#elif (EE_TYPE == AT24C16)
#define AT24CXX_PAGE_BYTE 16
#define AT24CXX_MAX_MEM_ADDRESS 2048
#elif (EE_TYPE == AT24C32)
#define AT24CXX_PAGE_BYTE 32
#define AT24CXX_MAX_MEM_ADDRESS 4096
#elif (EE_TYPE == AT24C64)
#define AT24CXX_PAGE_BYTE 32
#define AT24CXX_MAX_MEM_ADDRESS 8192
#elif (EE_TYPE == AT24C128)
#define AT24CXX_PAGE_BYTE 64
#define AT24CXX_MAX_MEM_ADDRESS 16384
#elif (EE_TYPE == AT24C256)
#define AT24CXX_PAGE_BYTE 64
#define AT24CXX_MAX_MEM_ADDRESS 32768
#elif (EE_TYPE == AT24C512)
#define AT24CXX_PAGE_BYTE 128
#define AT24CXX_MAX_MEM_ADDRESS 65536
#endif
static rt_err_t read_regs(at24cxx_device_t dev, rt_uint8_t len, rt_uint8_t *buf)
{
struct rt_i2c_msg msgs;
msgs.addr = AT24CXX_ADDR;
msgs.flags = RT_I2C_RD;
msgs.buf = buf;
msgs.len = len;
if (rt_i2c_transfer(dev->i2c, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
uint8_t at24cxx_read_one_byte(at24cxx_device_t dev, uint16_t readAddr)
{
rt_uint8_t buf[2];
rt_uint8_t temp;
#if (EE_TYPE > AT24C16)
buf[0] = (uint8_t)(readAddr>>8);
buf[1] = (uint8_t)readAddr;
if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 0, buf, 2) == 0)
#else
buf[0] = readAddr;
if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 0, buf, 1) == 0)
#endif
{
return RT_ERROR;
}
read_regs(dev, 1, &temp);
return temp;
}
rt_err_t at24cxx_write_one_byte(at24cxx_device_t dev, uint16_t writeAddr, uint8_t dataToWrite)
{
rt_uint8_t buf[3];
#if (EE_TYPE > AT24C16)
buf[0] = (uint8_t)(writeAddr>>8);
buf[1] = (uint8_t)writeAddr;
buf[2] = dataToWrite;
if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 0, buf, 3) == 3)
#else
buf[0] = writeAddr; //cmd
buf[1] = dataToWrite;
//buf[2] = data[1];
if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 0, buf, 2) == 2)
#endif
return RT_EOK;
else
return -RT_ERROR;
}
rt_err_t at24cxx_read_page(at24cxx_device_t dev, uint32_t readAddr, uint8_t *pBuffer, uint16_t numToRead)
{
struct rt_i2c_msg msgs[2];
uint8_t AddrBuf[2];
msgs[0].addr = AT24CXX_ADDR;
msgs[0].flags = RT_I2C_WR ;
#if (EE_TYPE > AT24C16)
AddrBuf[0] = readAddr >> 8;
AddrBuf[1] = readAddr;
msgs[0].buf = AddrBuf;
msgs[0].len = 2;
#else
AddrBuf[0] = readAddr;
msgs[0].buf = AddrBuf;
msgs[0].len = 1;
#endif
msgs[1].addr = AT24CXX_ADDR ;
msgs[1].flags = RT_I2C_RD;
msgs[1].buf = pBuffer;
msgs[1].len = numToRead;
if(rt_i2c_transfer(dev->i2c, msgs, 2) == 0)
{
return RT_ERROR;
}
return RT_EOK;
}
rt_err_t at24cxx_write_page(at24cxx_device_t dev, uint32_t wirteAddr, uint8_t *pBuffer, uint16_t numToWrite)
{
struct rt_i2c_msg msgs[2];
uint8_t AddrBuf[2];
msgs[0].addr = AT24CXX_ADDR ;
msgs[0].flags = RT_I2C_WR ;
#if (EE_TYPE > AT24C16)
AddrBuf[0] = wirteAddr >> 8;
AddrBuf[1] = wirteAddr;
msgs[0].buf = AddrBuf;
msgs[0].len = 2;
#else
AddrBuf[0] = wirteAddr;
msgs[0].buf = AddrBuf;
msgs[0].len = 1;
#endif
msgs[1].addr = AT24CXX_ADDR;
msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;
msgs[1].buf = pBuffer;
msgs[1].len = numToWrite;
if(rt_i2c_transfer(dev->i2c, msgs, 2) <= 0)
{
return RT_ERROR;
}
return RT_EOK;
}
rt_err_t at24cxx_check(at24cxx_device_t dev)
{
uint8_t temp;
RT_ASSERT(dev);
temp = at24cxx_read_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1);
if (temp == 0x55) return RT_EOK;
else
{
at24cxx_write_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1, 0x55);
rt_thread_mdelay(EE_TWR); // wait 5ms befor next operation
temp = at24cxx_read_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1);
if (temp == 0x55) return RT_EOK;
}
return RT_ERROR;
}
/**
* This function read the specific numbers of data to the specific position
*
* @param bus the name of at24cxx device
* @param ReadAddr the start position to read
* @param pBuffer the read data store position
* @param NumToRead
* @return RT_EOK write ok.
*/
rt_err_t at24cxx_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)
{
rt_err_t result;
RT_ASSERT(dev);
if(ReadAddr + NumToRead > AT24CXX_MAX_MEM_ADDRESS)
{
return RT_ERROR;
}
result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
if (result == RT_EOK)
{
while (NumToRead)
{
*pBuffer++ = at24cxx_read_one_byte(dev, ReadAddr++);
NumToRead--;
}
}
else
{
LOG_E("The at24cxx could not respond at this time. Please try again");
}
rt_mutex_release(dev->lock);
return RT_EOK;
}
/**
* This function read the specific numbers of data to the specific position
*
* @param bus the name of at24cxx device
* @param ReadAddr the start position to read
* @param pBuffer the read data store position
* @param NumToRead
* @return RT_EOK write ok.
*/
rt_err_t at24cxx_page_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)
{
rt_err_t result = RT_EOK;
uint16_t pageReadSize = AT24CXX_PAGE_BYTE - ReadAddr % AT24CXX_PAGE_BYTE;
RT_ASSERT(dev);
if(ReadAddr + NumToRead > AT24CXX_MAX_MEM_ADDRESS)
{
return RT_ERROR;
}
result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
if(result == RT_EOK)
{
while (NumToRead)
{
if(NumToRead > pageReadSize)
{
if(at24cxx_read_page(dev, ReadAddr, pBuffer, pageReadSize))
{
result = RT_ERROR;
}
ReadAddr += pageReadSize;
pBuffer += pageReadSize;
NumToRead -= pageReadSize;
pageReadSize = AT24CXX_PAGE_BYTE;
}
else
{
if(at24cxx_read_page(dev, ReadAddr, pBuffer, NumToRead))
{
result = RT_ERROR;
}
NumToRead = 0;
}
}
}
else
{
LOG_E("The at24cxx could not respond at this time. Please try again");
}
rt_mutex_release(dev->lock);
return result;
}
/**
* This function write the specific numbers of data to the specific position
*
* @param bus the name of at24cxx device
* @param WriteAddr the start position to write
* @param pBuffer the data need to write
* @param NumToWrite
* @return RT_EOK write ok.at24cxx_device_t dev
*/
rt_err_t at24cxx_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite)
{
uint16_t i = 0;
rt_err_t result;
RT_ASSERT(dev);
if(WriteAddr + NumToWrite > AT24CXX_MAX_MEM_ADDRESS)
{
return RT_ERROR;
}
result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
if (result == RT_EOK)
{
while (1) //NumToWrite--
{
if (at24cxx_write_one_byte(dev, WriteAddr, pBuffer[i]) == RT_EOK)
{
rt_thread_mdelay(2);
WriteAddr++;
}
if (++i == NumToWrite)
{
break;
}
rt_thread_mdelay(EE_TWR);
}
}
else
{
LOG_E("The at24cxx could not respond at this time. Please try again");
}
rt_mutex_release(dev->lock);
return RT_EOK;
}
/**
* This function write the specific numbers of data to the specific position
*
* @param bus the name of at24cxx device
* @param WriteAddr the start position to write
* @param pBuffer the data need to write
* @param NumToWrite
* @return RT_EOK write ok.at24cxx_device_t dev
*/
rt_err_t at24cxx_page_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite)
{
rt_err_t result = RT_EOK;
uint16_t pageWriteSize = AT24CXX_PAGE_BYTE - WriteAddr % AT24CXX_PAGE_BYTE;
RT_ASSERT(dev);
if(WriteAddr + NumToWrite > AT24CXX_MAX_MEM_ADDRESS)
{
return RT_ERROR;
}
result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
if(result == RT_EOK)
{
while (NumToWrite)
{
if(NumToWrite > pageWriteSize)
{
if(at24cxx_write_page(dev, WriteAddr, pBuffer, pageWriteSize))
{
result = RT_ERROR;
}
rt_thread_mdelay(EE_TWR); // wait 5ms befor next operation
WriteAddr += pageWriteSize;
pBuffer += pageWriteSize;
NumToWrite -= pageWriteSize;
pageWriteSize = AT24CXX_PAGE_BYTE;
}
else
{
if(at24cxx_write_page(dev, WriteAddr, pBuffer, NumToWrite))
{
result = RT_ERROR;
}
rt_thread_mdelay(EE_TWR); // wait 5ms befor next operation
NumToWrite = 0;
}
}
}
else
{
LOG_E("The at24cxx could not respond at this time. Please try again");
}
rt_mutex_release(dev->lock);
return result;
}
/**
* This function initializes at24cxx registered device driver
*
* @param dev the name of at24cxx device
*
* @return the at24cxx device.
*/
at24cxx_device_t at24cxx_init(const char *i2c_bus_name)
{
at24cxx_device_t dev;
RT_ASSERT(i2c_bus_name);
dev = rt_calloc(1, sizeof(struct at24cxx_device));
if (dev == RT_NULL)
{
LOG_E("Can't allocate memory for at24cxx device on '%s' ", i2c_bus_name);
return RT_NULL;
}
dev->i2c = rt_i2c_bus_device_find(i2c_bus_name);
if (dev->i2c == RT_NULL)
{
LOG_E("Can't find at24cxx device on '%s' ", i2c_bus_name);
rt_free(dev);
return RT_NULL;
}
dev->lock = rt_mutex_create("mutex_at24cxx", RT_IPC_FLAG_FIFO);
if (dev->lock == RT_NULL)
{
LOG_E("Can't create mutex for at24cxx device on '%s' ", i2c_bus_name);
rt_free(dev);
return RT_NULL;
}
return dev;
}
/**
* This function releases memory and deletes mutex lock
*
* @param dev the pointer of device driver structure
*/
void at24cxx_deinit(at24cxx_device_t dev)
{
RT_ASSERT(dev);
rt_mutex_delete(dev->lock);
rt_free(dev);
}
const char *eep_type[] =
{
"AT24C01",
"AT24C02",
"AT24C04",
"AT24C08",
"AT24C16",
"AT24C32",
"AT24C64",
"AT24C128",
"AT24C256",
"AT24C512",
};
system_info at_system_info = {0};
void system_info_init(void)
{
rt_sprintf(at_system_info.version,"%s %s",__DATE__,__TIME__);
at_system_info.sysclk = HAL_RCC_GetSysClockFreq();
at_system_info.hclk = HAL_RCC_GetHCLKFreq();
at_system_info.apb1_clk = HAL_RCC_GetPCLK1Freq();
at_system_info.apb2_clk = HAL_RCC_GetPCLK2Freq();
rt_memcpy(at_system_info.eep_type,eep_type[EE_TYPE],rt_strlen(eep_type[EE_TYPE]));
rt_sprintf(at_system_info.rt_thread_version, "%d.%d.%d build %s %s",RT_VERSION,
RT_SUBVERSION, RT_REVISION, __DATE__, __TIME__);
at_system_info.romsize = 512;
at_system_info.ramsize = 128;
}
void system_info_show(system_info *p_system_info)
{
rt_kprintf(" System Info Get EepRom: \n");
rt_kprintf(" System Version : %s\n",p_system_info->version);
rt_kprintf(" Eeprom Type : %s\n",p_system_info->eep_type);
rt_kprintf(" System Clock : %ld\r\n",p_system_info->sysclk);
rt_kprintf(" AHB Clock : %ld\r\n",p_system_info->hclk);
rt_kprintf(" APB1 Clock : %ld\r\n",p_system_info->apb1_clk);
rt_kprintf(" APB2 Clock : %ld\r\n",p_system_info->apb2_clk);
rt_kprintf(" RT-Thread Version : %s\n",p_system_info->rt_thread_version);
rt_kprintf(" System Info Size : %ld K\n",sizeof(system_info));
}
int at24(int argc ,char *argv[])
{
at24cxx_device_t dev = RT_NULL;
system_info at_r_info = {0};
if (argc != 1)
{
rt_kprintf("error, usage: at24\n");
return -1;
}
system_info_init();
dev = at24cxx_init("i2c1");
at24cxx_write(dev, 0, (uint8_t *)&at_system_info, sizeof(system_info));
rt_kprintf("write system info ok\n");
at24cxx_read(dev,0,(uint8_t *)&at_r_info,sizeof(system_info));
system_info_show(&at_r_info);
at24cxx_deinit(dev);
return 0;
}
MSH_CMD_EXPORT(at24, at24cxx eeprom test);
#endif
.h文件
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-13 XiaojieFan the first version
* 2019-12-04 RenMing Use PAGE WRITE instead of BYTE WRITE and input address can be selected
*/
#ifndef __AT24CXX_H__
#define __AT24CXX_H__
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#define AT24C01 0
#define AT24C02 1
#define AT24C04 2
#define AT24C08 3
#define AT24C16 4
#define AT24C32 5
#define AT24C64 6
#define AT24C128 7
#define AT24C256 8
#define AT24C512 9
#define AT24CTYPE 10 // Number of supported types
#define EE_TWR 5
#ifndef EE_TYPE
#define EE_TYPE AT24C02
#endif
struct at24cxx_device
{
struct rt_i2c_bus_device *i2c;
rt_mutex_t lock;
};
typedef struct
{
char version[24];
uint32_t sysclk;
uint32_t hclk;
uint32_t apb1_clk;
uint32_t apb2_clk;
uint32_t ramsize;
uint32_t romsize;
char eep_type[24];
char rt_thread_version[48];
}system_info;
typedef struct at24cxx_device *at24cxx_device_t;
extern at24cxx_device_t at24cxx_init(const char *i2c_bus_name);
extern rt_err_t at24cxx_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead);
extern rt_err_t at24cxx_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite);
extern rt_err_t at24cxx_page_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead);
extern rt_err_t at24cxx_page_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite);
#endif