| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- #include "hard_flash_at45db.h"
- #include "board.h"
- #include "hpm_spi_drv.h"
- #include "hpm_clock_drv.h"
- #include "hpm_gpio_drv.h"
- // 后续具体的IO宏都放到board头文件里
- #ifndef GD25Q16_FLASH
- /* 使用 SPI2 作为示例,你可以根据需要修改 */
- #define AT45DB_SPI_BASE HPM_SPI2
- #define AT45DB_CS_GPIO_PTR HPM_GPIO0 /* GPIO 控制器基地址 */
- #define AT45DB_CS_PORT 1 /* GPIOB = 1 */
- #define AT45DB_CS_PIN 12 /* PIN12 */
- /******************SPI时钟频率*******************/
- #define AT45DB_CLK_FRE 21000000
- /* CS 控制宏 */
- #define AT45DB_CS_SELECT() gpio_write_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN, 0)
- #define AT45DB_CS_DESELECT() gpio_write_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN, 1)
- /* 静态变量 */
- static uint32_t spi_clk_freq;
- /**
- * @brief SPI 读写一个字节
- */
- static uint8_t spi_readwrite_byte(uint8_t byte)
- {
- uint8_t rx_byte = 0;
- spi_control_config_t control_config;
-
- /* 配置传输控制 */
- spi_master_get_default_control_config(&control_config);
- control_config.common_config.trans_mode = spi_trans_write_read_together;
- control_config.master_config.cmd_enable = false;
- control_config.master_config.addr_enable = false;
-
- /* 执行传输 */
- spi_transfer(AT45DB_SPI_BASE,
- &control_config,
- NULL, NULL,
- &byte, 1,
- &rx_byte, 1);
-
- return rx_byte;
- }
- /**
- * @brief 初始化 AT45DB 的 SPI 接口
- */
- void at45db_init(void)
- {
- spi_timing_config_t timing_config = {0};
- spi_format_config_t format_config = {0};
-
- /* 初始化 SPI 时钟和引脚 */
- spi_clk_freq = board_init_spi_clock(AT45DB_SPI_BASE);
- board_init_spi_pins(AT45DB_SPI_BASE);
-
- /* 配置 CS 引脚 */
- AT45DB_CS_DESELECT(); /* CS 默认高电平 */
-
- /* 3. 配置 SPI 时序(主模式)*/
- spi_master_get_default_timing_config(&timing_config);
- timing_config.master_config.clk_src_freq_in_hz = spi_clk_freq;
- timing_config.master_config.sclk_freq_in_hz = AT45DB_CLK_FRE;
- spi_master_timing_init(AT45DB_SPI_BASE, &timing_config);
-
- /* 4. 配置 SPI 格式 */
- spi_master_get_default_format_config(&format_config);
- format_config.common_config.data_len_in_bits = 8; /* 8位数据 */
- format_config.common_config.mode = spi_master_mode; /* 主机模式 */
- format_config.common_config.cpol = spi_sclk_low_idle; /* CPOL=0:空闲时低电平 */
- format_config.common_config.cpha = spi_sclk_sampling_odd_clk_edges; /* CPHA=0:第一个边沿采样 */
- spi_format_init(AT45DB_SPI_BASE, &format_config);
-
- }
- /**
- * @brief 查询 AT45DB 是否准备好
- * @return 1: 准备好, 0: 忙
- */
- uint8_t at45db_is_busy(void)
- {
- uint8_t status_reg;
-
- AT45DB_CS_SELECT();
- spi_readwrite_byte(AT45DB_READ_STATE_REGISTER);
- status_reg = spi_readwrite_byte(0x00);
- AT45DB_CS_DESELECT();
-
- return (status_reg & 0x80) ? 1 : 0;
- }
- /**
- * @brief 检查 AT45DB 是否存在
- * @return 1: 存在, 0: 不存在
- */
- uint8_t at45db_check(void)
- {
- uint8_t buf[3];
-
- AT45DB_CS_SELECT();
- spi_readwrite_byte(0x9F); /* 读ID命令 */
- buf[0] = spi_readwrite_byte(0);
- buf[1] = spi_readwrite_byte(0);
- buf[2] = spi_readwrite_byte(0);
- AT45DB_CS_DESELECT();
-
- /* AT45DB161 的 ID 是 0x1F, 0x26, 0x00 */
- if ((buf[0] == 0x1F) && (buf[1] == 0x26) && (buf[2] == 0x00)) {
- return 1;
- }
- return 0;
- }
- /**
- * @brief 读一页数据
- * @param page 页地址 (0-4096)
- * @param pdata 数据缓冲区
- */
- void at45db_read_page(uint16_t page, uint8_t *pdata)
- {
- int i;
-
- if (page > 4096) return;
-
- /* 等待芯片就绪 */
- while (at45db_is_busy() == 0);
-
- AT45DB_CS_SELECT();
- spi_readwrite_byte(AT45DB_MM_PAGE_READ);
- spi_readwrite_byte((int8_t)(page >> 6)); /* A20 - A9 */
- spi_readwrite_byte((int8_t)(page << 2));
- spi_readwrite_byte(0x00); /* 3字节地址 */
-
- /* 4个 dummy 字节 */
- spi_readwrite_byte(0x00);
- spi_readwrite_byte(0x00);
- spi_readwrite_byte(0x00);
- spi_readwrite_byte(0x00);
-
- /* 读取数据 */
- for (i = 0; i < 512; i++) {
- *pdata++ = spi_readwrite_byte(0x00);
- }
- AT45DB_CS_DESELECT();
- }
- /**
- * @brief 写一页数据
- * @param page 页地址 (0-4095)
- * @param data 要写入的数据
- */
- void at45db_write_page(uint16_t page, uint8_t *data)
- {
- uint16_t i;
-
- if (page > 4095) return;
-
- /* 等待芯片就绪 */
- while (at45db_is_busy() == 0);
-
- /* 步骤1:将数据写入 buffer2 */
- AT45DB_CS_SELECT();
- spi_readwrite_byte(AT45DB_BUFFER_2_WRITE);
- spi_readwrite_byte(0x00);
- spi_readwrite_byte(0x00);
- spi_readwrite_byte(0x00);
-
- for (i = 0; i < 512; i++) {
- spi_readwrite_byte(data[i]);
- }
- AT45DB_CS_DESELECT();
-
- /* 等待写入完成 */
- while (at45db_is_busy() == 0);
-
- /* 步骤2:将 buffer2 的内容编程到主存储器 */
- AT45DB_CS_SELECT();
- spi_readwrite_byte(AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE);
- spi_readwrite_byte((uint8_t)(page >> 6));
- spi_readwrite_byte((uint8_t)(page << 2));
- spi_readwrite_byte(0x00);
- AT45DB_CS_DESELECT();
- }
- /**
- * @brief 在一页内写入部分数据
- * @param page 页地址
- * @param data 数据
- * @param len 长度
- */
- void at45db_write_bytes_on_one_page(uint16_t page, uint8_t *data, uint16_t len)
- {
- uint16_t i;
-
- if (page > 4095 || len > 512) return;
-
- /* 等待芯片就绪 */
- while (at45db_is_busy() == 0);
-
- /* 将数据写入 buffer2 */
- AT45DB_CS_SELECT();
- spi_readwrite_byte(AT45DB_BUFFER_2_WRITE);
- spi_readwrite_byte(0x00);
- spi_readwrite_byte(0x00);
- spi_readwrite_byte(0x00);
-
- for (i = 0; i < len; i++) {
- spi_readwrite_byte(data[i]);
- }
- AT45DB_CS_DESELECT();
-
- /* 等待写入完成 */
- while (at45db_is_busy() == 0);
-
- /* 编程到主存储器 */
- AT45DB_CS_SELECT();
- spi_readwrite_byte(AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE);
- spi_readwrite_byte((uint8_t)(page >> 6));
- spi_readwrite_byte((uint8_t)(page << 2));
- spi_readwrite_byte(0x00);
- AT45DB_CS_DESELECT();
- }
- /**
- * @brief 从任意地址读取多个字节
- * @param addr 起始地址 (0-4096*512)
- * @param pdata 数据缓冲区
- * @param len 要读取的字节数
- */
- void at45db_read_bytes(uint32_t addr, uint8_t *pdata, uint16_t len)
- {
- int i, j, k;
- uint8_t temp[512];
- uint16_t page, offset;
-
- if (addr > 4096 * 512) return;
-
- page = addr / 512;
- offset = addr % 512;
-
- at45db_read_page(page++, temp);
- for (i = offset; (len != 0) && (i < 512); len--, i++) {
- *pdata++ = temp[i];
- }
-
- if ((i == 512) && (len != 0)) {
- if (len > 512) {
- for (k = 0; k < len / 512; k++) {
- at45db_read_page(page++, temp);
- for (j = 0; j < 512; j++) {
- *pdata++ = temp[j];
- }
- }
- len -= 512 * k;
- }
- if (len != 0) {
- at45db_read_page(page, temp);
- for (j = 0; j < len; j++) {
- *pdata++ = temp[j];
- }
- }
- }
- }
- /**
- * @brief 从任意地址写入多个字节
- * @param addr 起始地址 (0-4096*512)
- * @param pdata 要写入的数据
- * @param len 要写入的字节数
- */
- void at45db_write_bytes(uint32_t addr, uint8_t *pdata, uint16_t len)
- {
- uint8_t temp[512];
- uint16_t page, offset;
- uint16_t i, j, k;
-
- if (addr > 4096 * 512) return;
-
- page = addr / 512;
- offset = addr % 512;
-
- at45db_read_page(page, temp);
- for (i = offset; (len != 0) && (i < 512); len--, i++) {
- temp[i] = *pdata++;
- }
- at45db_write_page(page++, temp);
-
- if ((i == 512) && (len != 0)) {
- if (len > 512) {
- for (k = 0; k < len / 512; k++) {
- for (j = 0; j < 512; j++) {
- temp[j] = *pdata++;
- }
- at45db_write_page(page++, temp);
- }
- len -= 512 * k;
- }
-
- if (len != 0) {
- at45db_read_page(page, temp);
- for (j = 0; j < len; j++) {
- temp[j] = *pdata++;
- }
- at45db_write_page(page, temp);
- }
- }
- }
- /**
- * @brief 写入浮点数
- */
- void at45db_write_float(uint32_t addr, float value)
- {
- f_bytes data;
- data.value = value;
- at45db_write_bytes(addr, &data.byte[0], 4);
- }
- /**
- * @brief 读取浮点数
- */
- float at45db_read_float(uint32_t addr)
- {
- f_bytes data;
- data.value = 0;
- at45db_read_bytes(addr, &data.byte[0], 4);
- return data.value;
- }
- /**
- * @brief 写入16位整数
- */
- void at45db_write_int16(uint32_t addr, int16_t value)
- {
- i_bytes data;
- data.value = value;
- at45db_write_bytes(addr, &data.byte[0], 2);
- }
- /**
- * @brief 读取16位整数
- */
- int16_t at45db_read_int16(uint32_t addr)
- {
- i_bytes data;
- data.value = 0;
- at45db_read_bytes(addr, &data.byte[0], 2);
- return data.value;
- }
- #endif
|