sdk:examples: add flash_ctrl
Signed-off-by: liangkangnan <liangkangnan@163.com>pull/4/head
parent
e097662c62
commit
8f4c2cb7fe
|
@ -29,6 +29,7 @@ C_SRCS += $(BSP_DIR)/lib/i2c.c
|
||||||
C_SRCS += $(BSP_DIR)/lib/spi.c
|
C_SRCS += $(BSP_DIR)/lib/spi.c
|
||||||
C_SRCS += $(BSP_DIR)/lib/pinmux.c
|
C_SRCS += $(BSP_DIR)/lib/pinmux.c
|
||||||
C_SRCS += $(BSP_DIR)/lib/flash_n25q.c
|
C_SRCS += $(BSP_DIR)/lib/flash_n25q.c
|
||||||
|
C_SRCS += $(BSP_DIR)/lib/flash_ctrl.c
|
||||||
|
|
||||||
LINKER_SCRIPT := $(BSP_DIR)/link.lds
|
LINKER_SCRIPT := $(BSP_DIR)/link.lds
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Generated register defines for flash_ctrl
|
||||||
|
|
||||||
|
// Copyright information found in source file:
|
||||||
|
// Copyright lowRISC contributors.
|
||||||
|
|
||||||
|
// Licensing information found in source file:
|
||||||
|
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
#ifndef _FLASH_CTRL_REG_DEFS_
|
||||||
|
#define _FLASH_CTRL_REG_DEFS_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
// Register width
|
||||||
|
#define FLASH_CTRL_PARAM_REG_WIDTH 32
|
||||||
|
|
||||||
|
#define FLASH_CTRL_BASE_ADDR (0x0E000000)
|
||||||
|
#define FLASH_CTRL_REG(offset) (*((volatile uint32_t *)(FLASH_CTRL_BASE_ADDR + offset)))
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FLASH_OP_READ = 0,
|
||||||
|
FLASH_OP_PROGRAM,
|
||||||
|
FLASH_OP_ERASE,
|
||||||
|
FLASH_OP_INIT
|
||||||
|
} flash_op_mode_e;
|
||||||
|
|
||||||
|
void flash_ctrl_init();
|
||||||
|
void flash_ctrl_deinit();
|
||||||
|
void flash_ctrl_qspi_init();
|
||||||
|
void flash_ctrl_read(uint32_t start_addr, uint32_t *data, uint32_t len);
|
||||||
|
uint8_t flash_ctrl_page_program(uint32_t page_addr, uint32_t *data, uint32_t len);
|
||||||
|
uint8_t flash_ctrl_sector_erase(uint32_t sector_addr);
|
||||||
|
|
||||||
|
// flash_ctrl control register
|
||||||
|
#define FLASH_CTRL_CTRL_REG_OFFSET 0x0
|
||||||
|
#define FLASH_CTRL_CTRL_REG_RESVAL 0x0
|
||||||
|
#define FLASH_CTRL_CTRL_START_BIT 0
|
||||||
|
#define FLASH_CTRL_CTRL_OP_MODE_MASK 0x3
|
||||||
|
#define FLASH_CTRL_CTRL_OP_MODE_OFFSET 1
|
||||||
|
#define FLASH_CTRL_CTRL_OP_MODE_FIELD \
|
||||||
|
((bitfield_field32_t) { .mask = FLASH_CTRL_CTRL_OP_MODE_MASK, .index = FLASH_CTRL_CTRL_OP_MODE_OFFSET })
|
||||||
|
#define FLASH_CTRL_CTRL_SW_CTRL_BIT 3
|
||||||
|
#define FLASH_CTRL_CTRL_PROGRAM_INIT_BIT 4
|
||||||
|
#define FLASH_CTRL_CTRL_WRITE_ERROR_BIT 5
|
||||||
|
#define FLASH_CTRL_CTRL_RESERVED_MASK 0x3ffffff
|
||||||
|
#define FLASH_CTRL_CTRL_RESERVED_OFFSET 6
|
||||||
|
#define FLASH_CTRL_CTRL_RESERVED_FIELD \
|
||||||
|
((bitfield_field32_t) { .mask = FLASH_CTRL_CTRL_RESERVED_MASK, .index = FLASH_CTRL_CTRL_RESERVED_OFFSET })
|
||||||
|
|
||||||
|
// flash_ctrl address register
|
||||||
|
#define FLASH_CTRL_ADDR_REG_OFFSET 0x4
|
||||||
|
#define FLASH_CTRL_ADDR_REG_RESVAL 0x0
|
||||||
|
#define FLASH_CTRL_ADDR_RW_ADDRESS_MASK 0x7fffff
|
||||||
|
#define FLASH_CTRL_ADDR_RW_ADDRESS_OFFSET 0
|
||||||
|
#define FLASH_CTRL_ADDR_RW_ADDRESS_FIELD \
|
||||||
|
((bitfield_field32_t) { .mask = FLASH_CTRL_ADDR_RW_ADDRESS_MASK, .index = FLASH_CTRL_ADDR_RW_ADDRESS_OFFSET })
|
||||||
|
#define FLASH_CTRL_ADDR_RESERVED_MASK 0x1ff
|
||||||
|
#define FLASH_CTRL_ADDR_RESERVED_OFFSET 23
|
||||||
|
#define FLASH_CTRL_ADDR_RESERVED_FIELD \
|
||||||
|
((bitfield_field32_t) { .mask = FLASH_CTRL_ADDR_RESERVED_MASK, .index = FLASH_CTRL_ADDR_RESERVED_OFFSET })
|
||||||
|
|
||||||
|
// flash_ctrl data register
|
||||||
|
#define FLASH_CTRL_DATA_REG_OFFSET 0x8
|
||||||
|
#define FLASH_CTRL_DATA_REG_RESVAL 0x0
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
#endif // _FLASH_CTRL_REG_DEFS_
|
||||||
|
// End generated register defines for flash_ctrl
|
|
@ -0,0 +1,122 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../../bsp/include/flash_ctrl.h"
|
||||||
|
#include "../../bsp/include/utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
void flash_ctrl_init()
|
||||||
|
{
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= 1 << FLASH_CTRL_CTRL_SW_CTRL_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_ctrl_deinit()
|
||||||
|
{
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) &= ~(1 << FLASH_CTRL_CTRL_SW_CTRL_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化flash为QSPI模式
|
||||||
|
void flash_ctrl_qspi_init()
|
||||||
|
{
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) &= ~(FLASH_CTRL_CTRL_OP_MODE_MASK << FLASH_CTRL_CTRL_OP_MODE_OFFSET);
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= (FLASH_OP_INIT << FLASH_CTRL_CTRL_OP_MODE_OFFSET);
|
||||||
|
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= 1 << FLASH_CTRL_CTRL_START_BIT;
|
||||||
|
while (FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) & (1 << FLASH_CTRL_CTRL_START_BIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flash_ctrl_program_init()
|
||||||
|
{
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= 1 << FLASH_CTRL_CTRL_PROGRAM_INIT_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flash_ctrl_program_deinit()
|
||||||
|
{
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) &= ~(1 << FLASH_CTRL_CTRL_PROGRAM_INIT_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读数据
|
||||||
|
void flash_ctrl_read(uint32_t start_addr, uint32_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t addr, i;
|
||||||
|
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) &= ~(FLASH_CTRL_CTRL_OP_MODE_MASK << FLASH_CTRL_CTRL_OP_MODE_OFFSET);
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= (FLASH_OP_READ << FLASH_CTRL_CTRL_OP_MODE_OFFSET);
|
||||||
|
|
||||||
|
addr = start_addr;
|
||||||
|
len = len >> 2;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_ADDR_REG_OFFSET) = addr & FLASH_CTRL_ADDR_RW_ADDRESS_MASK;
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= 1 << FLASH_CTRL_CTRL_START_BIT;
|
||||||
|
while (FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) & (1 << FLASH_CTRL_CTRL_START_BIT));
|
||||||
|
data[i] = FLASH_CTRL_REG(FLASH_CTRL_DATA_REG_OFFSET);
|
||||||
|
addr += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 以word为单位进行烧写,一次最多烧一个page(256个字节)
|
||||||
|
// 返回值,1:成功,0:失败
|
||||||
|
uint8_t flash_ctrl_page_program(uint32_t page_addr, uint32_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t i, index;
|
||||||
|
uint32_t prog_len, remain_len;
|
||||||
|
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) &= ~(FLASH_CTRL_CTRL_OP_MODE_MASK << FLASH_CTRL_CTRL_OP_MODE_OFFSET);
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= (FLASH_OP_PROGRAM << FLASH_CTRL_CTRL_OP_MODE_OFFSET);
|
||||||
|
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_ADDR_REG_OFFSET) = page_addr & FLASH_CTRL_ADDR_RW_ADDRESS_MASK;
|
||||||
|
|
||||||
|
if (len > 4)
|
||||||
|
flash_ctrl_program_init();
|
||||||
|
|
||||||
|
remain_len = len;
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
while (remain_len > 0) {
|
||||||
|
// 一次最多烧32个byte
|
||||||
|
if (remain_len > 32)
|
||||||
|
prog_len = 32;
|
||||||
|
else
|
||||||
|
prog_len = remain_len;
|
||||||
|
|
||||||
|
remain_len -= prog_len;
|
||||||
|
// word的个数
|
||||||
|
prog_len = prog_len >> 2;
|
||||||
|
|
||||||
|
// 每次烧写一个word
|
||||||
|
for (i = 0; i < prog_len; i++) {
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_DATA_REG_OFFSET) = data[index];
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= 1 << FLASH_CTRL_CTRL_START_BIT;
|
||||||
|
while (FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) & (1 << FLASH_CTRL_CTRL_START_BIT));
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 4) {
|
||||||
|
flash_ctrl_program_deinit();
|
||||||
|
while (FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) & (1 << FLASH_CTRL_CTRL_START_BIT));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) & (1 << FLASH_CTRL_CTRL_WRITE_ERROR_BIT))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扇区擦除
|
||||||
|
// 返回值,1:成功,0:失败
|
||||||
|
uint8_t flash_ctrl_sector_erase(uint32_t sector_addr)
|
||||||
|
{
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) &= ~(FLASH_CTRL_CTRL_OP_MODE_MASK << FLASH_CTRL_CTRL_OP_MODE_OFFSET);
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= (FLASH_OP_ERASE << FLASH_CTRL_CTRL_OP_MODE_OFFSET);
|
||||||
|
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_ADDR_REG_OFFSET) = sector_addr & FLASH_CTRL_ADDR_RW_ADDRESS_MASK;
|
||||||
|
|
||||||
|
FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) |= 1 << FLASH_CTRL_CTRL_START_BIT;
|
||||||
|
while (FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) & (1 << FLASH_CTRL_CTRL_START_BIT));
|
||||||
|
|
||||||
|
if (FLASH_CTRL_REG(FLASH_CTRL_CTRL_REG_OFFSET) & (1 << FLASH_CTRL_CTRL_WRITE_ERROR_BIT))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.bin
|
||||||
|
*.dump
|
||||||
|
*.mem
|
||||||
|
flash_ctrl
|
|
@ -0,0 +1,20 @@
|
||||||
|
RISCV_ARCH := rv32im
|
||||||
|
RISCV_ABI := ilp32
|
||||||
|
RISCV_MCMODEL := medlow
|
||||||
|
|
||||||
|
|
||||||
|
TARGET = flash_ctrl
|
||||||
|
|
||||||
|
|
||||||
|
#CFLAGS += -DSIMULATION
|
||||||
|
#CFLAGS += -O2
|
||||||
|
#ASM_SRCS +=
|
||||||
|
#LDFLAGS +=
|
||||||
|
#INCLUDES += -I.
|
||||||
|
|
||||||
|
C_SRCS := \
|
||||||
|
main.c \
|
||||||
|
|
||||||
|
|
||||||
|
BSP_DIR = ../../bsp
|
||||||
|
include ../../bsp/bsp.mk
|
|
@ -0,0 +1 @@
|
||||||
|
flash读、擦除、编程例程。
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../../bsp/include/uart.h"
|
||||||
|
#include "../../bsp/include/xprintf.h"
|
||||||
|
#include "../../bsp/include/pinmux.h"
|
||||||
|
#include "../../bsp/include/flash_ctrl.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DATA_BUF_LEN (32)
|
||||||
|
|
||||||
|
// bytes = DATA_BUF_LEN * 4
|
||||||
|
#define DATA_BYTES (DATA_BUF_LEN << 2)
|
||||||
|
|
||||||
|
static uint32_t write_data_buf[DATA_BUF_LEN];
|
||||||
|
static uint32_t read_data_buf[DATA_BUF_LEN];
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
// UART引脚配置
|
||||||
|
pinmux_set_io0_func(IO0_UART0_TX);
|
||||||
|
pinmux_set_io3_func(IO3_UART0_RX);
|
||||||
|
// UART初始化
|
||||||
|
uart_init(UART0, uart0_putc);
|
||||||
|
|
||||||
|
flash_ctrl_init();
|
||||||
|
|
||||||
|
// 擦除0子扇区
|
||||||
|
if (!flash_ctrl_sector_erase(0))
|
||||||
|
xprintf("erase failed...\n");
|
||||||
|
|
||||||
|
// 构造编程数据
|
||||||
|
for (i = 0; i < DATA_BUF_LEN; i++)
|
||||||
|
write_data_buf[i] = i;
|
||||||
|
|
||||||
|
// 编程第0页
|
||||||
|
if (!flash_ctrl_page_program(0, write_data_buf, DATA_BYTES))
|
||||||
|
xprintf("program failed...\n");
|
||||||
|
|
||||||
|
// 读0x0地址开始的数据
|
||||||
|
flash_ctrl_read(0, read_data_buf, DATA_BYTES);
|
||||||
|
|
||||||
|
flash_ctrl_deinit();
|
||||||
|
|
||||||
|
// 打印读到的数据
|
||||||
|
for (i = 0; i < DATA_BUF_LEN; i++)
|
||||||
|
xprintf("0x%x\n", read_data_buf[i]);
|
||||||
|
|
||||||
|
/************************** QSPI测试 **************************/
|
||||||
|
|
||||||
|
flash_ctrl_init();
|
||||||
|
|
||||||
|
// QSPI初始化
|
||||||
|
flash_ctrl_qspi_init();
|
||||||
|
|
||||||
|
// 读0x0地址开始的数据
|
||||||
|
flash_ctrl_read(0, read_data_buf, DATA_BYTES);
|
||||||
|
|
||||||
|
flash_ctrl_deinit();
|
||||||
|
|
||||||
|
xprintf("\nquad spi test, read data:\n");
|
||||||
|
// 打印读到的数据
|
||||||
|
for (i = 0; i < DATA_BUF_LEN; i++)
|
||||||
|
xprintf("0x%x\n", read_data_buf[i]);
|
||||||
|
|
||||||
|
while (1);
|
||||||
|
}
|
Loading…
Reference in New Issue