tinyriscv/tests/example/lib/flash_n25q.c

149 lines
2.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <stdint.h>
#include "../include/flash_n25q.h"
#include "../include/spi.h"
#include "../include/xprintf.h"
/* N25Q064特点:
* 1.总共64Mb大小即8MB
* 2.总共128个扇区每个扇区大小为64KB
* 3.总共2048个子扇区每个子扇区大小为4KB
* 4.总共37768页每页大小为256B
* 5.擦除的最小单位是子扇区,编程(写)的最小单位是页,读的最小单位是字节
*/
// 写使能
// 擦除或者编程操作之前必须先发送写使能命令
void n25q_write_enable(uint8_t en)
{
spi_set_ss(0);
if (en)
spi_write_byte(WRITE_ENABLE_CMD);
else
spi_write_byte(WRITE_DISABLE_CMD);
spi_set_ss(1);
}
// 读状态寄存器
uint8_t n25q_read_status_reg()
{
uint8_t data;
spi_set_ss(0);
spi_write_byte(READ_STATUS_REG_CMD);
data = spi_read_byte();
spi_set_ss(1);
return data;
}
// 是否正在擦除或者编程
uint8_t n25q_is_busy()
{
return (n25q_read_status_reg() & 0x1);
}
void n25q_init()
{
spi_init();
}
// 读ID号
void n25q_read_id(uint8_t data[], uint8_t len)
{
spi_set_ss(0);
spi_write_byte(READ_ID_CMD);
spi_read_bytes(data, len);
spi_set_ss(1);
}
// 读数据
// addr: 0, 1, 2, ...
void n25q_read_data(uint8_t data[], uint32_t len, uint32_t addr)
{
spi_set_ss(0);
spi_write_byte(READ_CMD);
spi_write_byte((addr >> 16) & 0xff);
spi_write_byte((addr >> 8) & 0xff);
spi_write_byte(addr & 0xff);
spi_read_bytes(data, len);
spi_set_ss(1);
}
// 子扇区擦除
// subsector第几个子扇区: 0 ~ N
void n25q_subsector_erase(uint32_t subsector)
{
n25q_write_enable(1);
spi_set_ss(0);
uint32_t addr = N25Q_SUBSECTOR_TO_ADDR(subsector);
spi_write_byte(SUBSECTOR_ERASE_CMD);
spi_write_byte((addr >> 16) & 0xff);
spi_write_byte((addr >> 8) & 0xff);
spi_write_byte(addr & 0xff);
spi_set_ss(1);
while (n25q_is_busy());
n25q_write_enable(0);
}
// 扇区擦除
// sector第几个扇区: 0 ~ N
void n25q_sector_erase(uint32_t sector)
{
n25q_write_enable(1);
spi_set_ss(0);
uint32_t addr = N25Q_SECTOR_TO_ADDR(sector);
spi_write_byte(SECTOR_ERASE_CMD);
spi_write_byte((addr >> 16) & 0xff);
spi_write_byte((addr >> 8) & 0xff);
spi_write_byte(addr & 0xff);
spi_set_ss(1);
while (n25q_is_busy());
n25q_write_enable(0);
}
// 页编程
// page第几页: 0 ~ N
void n25q_page_program(uint8_t data[], uint32_t len, uint32_t page)
{
n25q_write_enable(1);
spi_set_ss(0);
uint32_t addr = N25Q_PAGE_TO_ADDR(page);
spi_write_byte(PAGE_PROGRAM_CMD);
spi_write_byte((addr >> 16) & 0xff);
spi_write_byte((addr >> 8) & 0xff);
spi_write_byte(addr & 0xff);
spi_write_bytes(data, len);
spi_set_ss(1);
while (n25q_is_busy());
n25q_write_enable(0);
}