driver/epprom/eeprom_m95.c

331 lines
8.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file eeprom_m95.c
* @author xxx
* @date 2023-08-30 08:58:43
* @brief 用于实现M95 EEPROM相关的读写操作
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include "eeprom_m95.h"
#include "spis.h"
#include "delay.h"
#include "storage.h"
#define M95_SPI SPI1
#define EEPROM_M95_1_CS_PORT EE1_CS_GPIO_Port
#define EEPROM_M95_1_CS_PIN EE1_CS_Pin
#define EEPROM_M95_2_CS_PORT EE2_CS_GPIO_Port
#define EEPROM_M95_2_CS_PIN EE2_CS_Pin
// 下面宏定义为2个EEPROM_M95的引脚定义
#define EEPROM_M95_MOSI_PORT SPI_MOSI_GPIO_Port
#define EEPROM_M95_MOSI_PIN SPI_MOSI_Pin
#define EEPROM_M95_MISO_PORT SPI_MISO_GPIO_Port
#define EEPROM_M95_MISO_PIN SPI_MISO_Pin
#define EEPROM_M95_SCK_PORT SPI_CLK_GPIO_Port
#define EEPROM_M95_SCK_PIN SPI_CLK_Pin
#define M95_TEST_PAGE (M95_PAGE_SIZE_256 - 1) ///< 测试页地址
m95_number_t eeprom_m95s[M95_MAX];
/**
* @brief 初始化EEPROM_M95eeprom_m95s
* @param {m95_number_e} num
* @return {*}
* @note 初始化函数对板卡上不同的芯片定义了块大小
*/
void eeprom_m95_init(m95_number_e num)
{
DBG_ASSERT(num < M95_MAX __DBG_LINE);
spi_gpio_group_t gpios;
spi_t *eeprom_m95_spi;
spi_normal_config_t cfg;
osel_memset((uint8_t *)&cfg, 0, sizeof(spi_normal_config_t));
cfg.cmd_rdsr = M95_CMD_RDSR;
cfg.cmd_wrsr = M95_CMD_WRSR;
cfg.cmd_wren = M95_CMD_WREN;
cfg.cmd_wrdi = M95_CMD_WRDI;
cfg.cmd_write = M95_CMD_WRITE;
cfg.cmd_read = M95_CMD_READ;
cfg.dummy_byte = M95_DUMMY_BYTE;
cfg.continuous_write = FALSE;
// 128 byte
if (num == M95_1)
{
// 创建CS引脚
gpios.cs = gpio_create(EEPROM_M95_1_CS_PORT, EEPROM_M95_1_CS_PIN);
cfg.address_bytes = 3;
cfg.page_size = M95_PAGE_SIZE_256;
cfg.total_size = _M95M02_;
}
// 256 byte
else if (num == M95_2)
{
// 创建CS引脚
gpios.cs = gpio_create(EEPROM_M95_2_CS_PORT, EEPROM_M95_2_CS_PIN);
cfg.address_bytes = 3;
cfg.page_size = M95_PAGE_SIZE_256;
cfg.total_size = _M95M02_;
}
else
{
DBG_ASSERT(FALSE __DBG_LINE);
}
gpios.mosi = gpio_create(EEPROM_M95_MOSI_PORT, EEPROM_M95_MOSI_PIN);
gpios.sck = gpio_create(EEPROM_M95_SCK_PORT, EEPROM_M95_SCK_PIN);
gpios.miso = gpio_create(EEPROM_M95_MISO_PORT, EEPROM_M95_MISO_PIN);
gpios.rst = gpio_create(NULL, 0);
gpios.rdy = gpio_create(NULL, 0);
// 创建SPI对象
eeprom_m95_spi = spi_create(SPI_TYPE_NORMAL, gpios, 10);
DBG_ASSERT(eeprom_m95_spi != NULL __DBG_LINE);
osel_memcpy((uint8_t *)&eeprom_m95_spi->cfg, (uint8_t *)&cfg, sizeof(spi_normal_config_t));
// 使能SPI
eeprom_m95_spi->interface.hardware_enable(eeprom_m95_spi, M95_SPI);
eeprom_m95s[num].num = num;
eeprom_m95s[num].spi = eeprom_m95_spi;
// 这里需要设置,否则读出的数据不对
eeprom_m95_spi->interface.u.normal.spi_reset(eeprom_m95_spi);
eeprom_m95_write_protection_close(num); // 关闭写保护
// eeprom_m95_test(num);
}
/**
* @brief 反初始化EEPROM_M95
* @param {m95_number_e} num
* @return {*}
* @note
*/
void eeprom_m95_dinit(m95_number_e num)
{
LL_SPI_Disable(M95_SPI);
GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.mosi->port, eeprom_m95s[num].spi->gpios.mosi->pin);
GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.miso->port, eeprom_m95s[num].spi->gpios.miso->pin);
GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.sck->port, eeprom_m95s[num].spi->gpios.sck->pin);
GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.cs->port, eeprom_m95s[num].spi->gpios.cs->pin);
}
/**
* @brief M95 EEPROM使能
* @return {*}
* @note
*/
void eeprom_m95_enable(void)
{
uint16_t count = 100;
LL_SPI_Enable(M95_SPI);
// 判断SPI是否使能成功
while (LL_SPI_IsEnabled(M95_SPI) != 1)
{
if (count-- == 0)
{
return;
}
else
{
__NOP();
}
}
}
/**
* @brief M95 EEPROM失能
* @return {*}
* @note
*/
void eeprom_m95_disable(void)
{
uint16_t count = 100;
LL_SPI_Disable(M95_SPI);
// 判断SPI是否关闭成功
while (LL_SPI_IsEnabled(M95_SPI) != 0)
{
if (count-- == 0)
{
return;
}
else
{
__NOP();
}
}
}
/**
* @brief 关闭EEPROM M95写保护
*
* 关闭指定M95 EEPROM的写保护功能。
*
* @param num 指定M95 EEPROM的编号
*/
void eeprom_m95_write_protection_close(m95_number_e num)
{
spi_t *handle = eeprom_m95s[num].spi;
DBG_ASSERT(handle != NULL __DBG_LINE);
eeprom_m95_enable();
handle->interface.u.normal.spi_write_reg(handle, handle->cfg.cmd_wrsr, 0);
eeprom_m95_disable();
}
/**
* @brief 获取M95 EEPROM写保护状态(软件)
*
* 根据传入的M95编号获取其写保护状态。
*
* @param num M95编号
* @return 如果M95 EEPROM处于写保护状态则返回FALSE否则返回TRUE。
*/
BOOL eeprom_m95_write_protection_state(m95_number_e num)
{
spi_t *handle = eeprom_m95s[num].spi;
DBG_ASSERT(handle != NULL __DBG_LINE);
eeprom_m95_enable();
eeprom_m95s[num].write_protection.data = handle->interface.u.normal.spi_read_reg(handle, handle->cfg.cmd_rdsr);
eeprom_m95_disable();
if (eeprom_m95s[num].write_protection.bits.bp0 == 1 ||
eeprom_m95s[num].write_protection.bits.bp1 == 1 ||
eeprom_m95s[num].write_protection.bits.srwd == 1)
{
return FALSE;
}
else
{
return TRUE;
}
}
/**
* @brief 读取M95 EEPROM内存数据
* @param num EEPROM模块编号0或1
* @param read_addr 要读取的地址
* @param data 存储读取数据的缓冲区
* @param length 要读取的数据长度
* @return {*}
*/
BOOL eeprom_m95_read(m95_number_e num, uint32_t read_addr, uint8_t *data, uint16_t length)
{
BOOL ret = FALSE;
if (length == 0)
{
return ret;
}
spi_t *eeprom_m95_spi = eeprom_m95s[num].spi; // 获取EEPROM模块的SPI配置
DBG_ASSERT(eeprom_m95_spi != NULL __DBG_LINE);
// 开启和关闭SPI对读写实时性有影响
eeprom_m95_enable();
ret = eeprom_m95_spi->interface.u.normal.spi_read(eeprom_m95_spi, read_addr, data, length);
eeprom_m95_disable();
return ret;
}
/**
* @brief 向M95 EEPROM内存写入数据
* @param num EEPROM模块编号0或1
* @param write_addr 要写入的地址
* @param data 包含要写入数据的缓冲区
* @param length 要写入的数据长度
* @return {*}
*/
BOOL eeprom_m95_write(m95_number_e num, uint32_t write_addr, uint8_t *data, uint16_t length)
{
BOOL ret = FALSE;
if (length == 0)
{
return ret;
}
spi_t *eeprom_m95_spi = eeprom_m95s[num].spi;
DBG_ASSERT(eeprom_m95_spi != NULL __DBG_LINE);
// 开启和关闭SPI对读写实时性有影响
eeprom_m95_enable();
ret = eeprom_m95_spi->interface.u.normal.spi_write(eeprom_m95_spi, write_addr, data, length);
eeprom_m95_disable();
return ret;
}
BOOL eeprom_m95_1_read(uint32_t addr, uint8_t *buf, uint16_t size)
{
return eeprom_m95_read(M95_1, addr, buf, size);
}
BOOL eeprom_m95_1_write(uint32_t addr, uint8_t *buf, uint16_t size)
{
return eeprom_m95_write(M95_1, addr, (uint8_t *)buf, size);
}
BOOL eeprom_m95_2_read(uint32_t addr, uint8_t *buf, uint16_t size)
{
return eeprom_m95_read(M95_2, addr, buf, size);
}
BOOL eeprom_m95_2_write(uint32_t addr, uint8_t *buf, uint16_t size)
{
return eeprom_m95_write(M95_2, addr, (uint8_t *)buf, size);
}
/**
* @brief 用于M95 EEPROM测试
* @param {m95_number_e} num
* @return {*}
* @note
*/
BOOL eeprom_m95_test(m95_number_e num)
{
const uint8_t buf_size = 5;
storage_t *st = storage_init(M95_TEST_PAGE * M95_PAGE_SIZE_256, M95_PAGE_SIZE_256);
DBG_ASSERT(st != NULL __DBG_LINE);
if (num == M95_1)
{
st->ops.read = eeprom_m95_1_read;
st->ops.write = eeprom_m95_1_write;
}
else
{
st->ops.read = eeprom_m95_2_read;
st->ops.write = eeprom_m95_2_write;
}
uint8_t buf[buf_size];
uint8_t rbuf[buf_size];
storage_add_node(st, 0, buf_size);
osel_memset(buf, 0, buf_size);
buf[0] = 0xD5;
buf[1] = 0xC8;
buf[2] = num;
buf[3] = 0xaa;
buf[4] = 0xbb;
storage_write(st, 0, buf);
__NOP();
storage_read(st, 0, rbuf);
storage_destroy(st);
if (osel_memcmp(buf, rbuf, buf_size) == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
/**
* @brief 获取EEPROM M95状态
*
* 获取EEPROM M95设备的工作状态。
*
* @param num EEPROM M95设备编号
*
* @return 如果EEPROM M95设备正常工作返回TRUE否则返回FALSE
*/
BOOL eeprom_m95_status_get(m95_number_e num)
{
return TRUE;
}