add n25q norflash driver
Signed-off-by: liangkangnan <liangkangnan@163.com>pull/1/head
parent
27da406793
commit
86392aa607
|
@ -0,0 +1,36 @@
|
|||
#ifndef _FLASH_N25Q_H_
|
||||
#define _FLASH_N25Q_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define N25Q_PAGE_SIZE 256
|
||||
|
||||
#define N25Q_PAGE_TO_ADDR(page) (page << 8)
|
||||
#define N25Q_SUBSECTOR_TO_ADDR(subsector) (subsector << 12)
|
||||
#define N25Q_SECTOR_TO_ADDR(sector) (sector << 16)
|
||||
|
||||
#define WRITE_STATUS_REG_CMD 0x01
|
||||
#define PAGE_PROGRAM_CMD 0x02
|
||||
#define READ_CMD 0x03
|
||||
#define WRITE_DISABLE_CMD 0x04
|
||||
#define READ_STATUS_REG_CMD 0x05
|
||||
#define WRITE_ENABLE_CMD 0x06
|
||||
#define SUBSECTOR_ERASE_CMD 0x20
|
||||
#define CLEAR_FLAG_STATUS_REG_CMD 0x50
|
||||
#define READ_FLAG_STATUS_REG_CMD 0x70
|
||||
#define BULK_ERASE_CMD 0xC7
|
||||
#define SECTOR_ERASE_CMD 0xD8
|
||||
#define WRITE_LOCK_REG_CMD 0xE5
|
||||
#define READ_LOCK_REG_CMD 0xE8
|
||||
#define READ_ID_CMD 0x9F
|
||||
|
||||
|
||||
void n25q_init();
|
||||
void n25q_read_id(uint8_t data[], uint8_t len);
|
||||
void n25q_read_data(uint8_t data[], uint32_t len, uint32_t addr);
|
||||
void n25q_subsector_erase(uint32_t subsector);
|
||||
void n25q_sector_erase(uint32_t sector);
|
||||
void n25q_page_program(uint8_t data[], uint32_t len, uint32_t page);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,148 @@
|
|||
#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);
|
||||
}
|
Loading…
Reference in New Issue