331 lines
8.6 KiB
C
331 lines
8.6 KiB
C
/**
|
||
* @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;
|
||
}
|