/** * @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 "entity.h" #include "board.h" #include "diagnosis.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 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; }