From 05fcdc17b684868a46e2319870cac613929763f1 Mon Sep 17 00:00:00 2001
From: abagu <352211526@qq.com>
Date: Tue, 21 Apr 2020 17:16:13 +0800
Subject: [PATCH] add yaffs support
Signed-off-by: abagu <352211526@qq.com>
---
boot_stage2/.ccsproject | 1 +
boot_stage2/.cproject | 1 +
boot_stage2/src/main.c | 51 ++++++-
boot_stage2/src/types.h | 1 +
boot_stage2/src/yaffs_elf.c | 133 +++++++++++++++++++
writetool/.cproject | 1 +
writetool/src/main.c | 256 ++++++++++++++++++++++++++++++++----
writetool/write.cmd | 36 ++---
8 files changed, 439 insertions(+), 41 deletions(-)
create mode 100644 boot_stage2/src/yaffs_elf.c
diff --git a/boot_stage2/.ccsproject b/boot_stage2/.ccsproject
index d805019..30f1ed7 100644
--- a/boot_stage2/.ccsproject
+++ b/boot_stage2/.ccsproject
@@ -8,4 +8,5 @@
+
diff --git a/boot_stage2/.cproject b/boot_stage2/.cproject
index f362498..9c5fb55 100644
--- a/boot_stage2/.cproject
+++ b/boot_stage2/.cproject
@@ -41,6 +41,7 @@
+
diff --git a/boot_stage2/src/main.c b/boot_stage2/src/main.c
index 9e51c38..513dcc8 100644
--- a/boot_stage2/src/main.c
+++ b/boot_stage2/src/main.c
@@ -10,10 +10,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include "debug.h"
#include "cJSON.h"
@@ -33,6 +35,39 @@
static uint32_t bitmap;
static uint32_t entries[MAX_CORES];
+static nand_flash_t __emif_nand;
+static nand_flash_t __emif_nand;
+static struct nand_partition __data_part = {
+ "nand",
+ 4,
+ 408
+};
+
+unsigned int yaffs_load_elf(const char *file);
+static int yaffs_inited = 0;
+
+static int nand_yaffs_initialize()
+{
+ if (__emif_nand == NULL)
+ return -1;
+ if (yaffs_inited) {
+ return 0;
+ }
+ printf("nand manu id: 0x%x, dev id: %x \r\n", __emif_nand->manu_id, __emif_nand->dev_id);
+ printf("nand size: %d MB (%d block * %d pages * %d Byte) \r\n", \
+ (__emif_nand->block_count * (__emif_nand->page_count_per_block * __emif_nand->data_bytes_per_page / 1024)) / 1024,
+ __emif_nand->block_count, __emif_nand->page_count_per_block, __emif_nand->data_bytes_per_page);
+ if (__data_part.end_block < __data_part.start_block)
+ __data_part.end_block = __emif_nand->block_count - 1;
+
+ if (!vsky_yaffs_setup( __emif_nand, NULL, 1, &__data_part)) {
+ if (yaffs_mount2("/nand", 1) == 0) {
+ yaffs_inited = 1;
+ return 0;
+ }
+ }
+ return -2;
+}
static int is_in_L2(unsigned long addr)
{
@@ -188,6 +223,14 @@ static void load_images(void)
entry = 0;
if (strcmp(type, "spi") == 0) {
entry = spi_load_elf(NOR_FLASH_CS, offset);
+ } else if (strcmp(type, "nand") == 0) {
+ entry = nand_load_elf(__emif_nand, offset);
+ } else if (strcmp(type, "yaffs") == 0) {
+ elem = cJSON_GetObjectItem(item, "file");
+ if (elem) {
+ nand_yaffs_initialize();
+ entry = yaffs_load_elf(cJSON_GetStringValue(elem));
+ }
}
if (is_valid_exec_addr(entry)) {
bitmap |= (1 << id);
@@ -257,19 +300,25 @@ static int wakeup_slave_cores(void)
return 0;
}
+
void main(void)
{
tsc_init();
debug_init();
+ emif16_init_ex((NAND_MODE << EMIF_NAND_CS0) );
bitmap = 0;
memset(entries, 0, sizeof entries);
debug_info("\r\nboot version: %s\r\n", NOR_BOOT_VERSION);
- load_images();
+ __emif_nand = nand_flash_open(EMIF_NAND_CS0, 0);
+ load_images();
+ if (yaffs_inited) {
+ yaffs_unmount("/nand");
+ }
wakeup_slave_cores();
while(1) {
boot();
diff --git a/boot_stage2/src/types.h b/boot_stage2/src/types.h
index 280d936..17dc816 100644
--- a/boot_stage2/src/types.h
+++ b/boot_stage2/src/types.h
@@ -107,4 +107,5 @@ typedef volatile unsigned char VUint8;
/* Types from the ethernet driver */
typedef unsigned int IPN;
+unsigned int yaffs_load_elf(const char *file);
#endif /* types.h */
diff --git a/boot_stage2/src/yaffs_elf.c b/boot_stage2/src/yaffs_elf.c
new file mode 100644
index 0000000..d939b3c
--- /dev/null
+++ b/boot_stage2/src/yaffs_elf.c
@@ -0,0 +1,133 @@
+/* vim: set ts=4 et sw=4:
+ * @file nor.c
+ *
+ * @brief The nor boot driver
+ */
+#include "types.h"
+#include "vsky/libdsp/inc/elfloader.h"
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * @brief The nor master control block which tracks the current nor boot information
+ */
+typedef struct nandmcb_s {
+ uint32 fpos; /**< Current file position. This is an absolute address, not relative to startPos */
+ uint32 startPos; /**< Initial file position */
+ int fd;
+} nandmcb_t;
+
+static nandmcb_t nmcb;
+
+/**
+ * @brief
+ * Set the current file position
+ */
+static Int32 __yaffs_seek (Int32 loc, Int32 from)
+{
+ /* Can't seek from the end of the file, since the end is not known */
+ if (from == 0)
+ nmcb.fpos = nmcb.startPos + loc;
+ else if (from == 1)
+ nmcb.fpos += loc;
+ else
+ return (-1);
+
+ if (nmcb.fpos < nmcb.startPos)
+ nmcb.fpos = nmcb.startPos;
+
+ return (0);
+}
+
+
+/**
+ * @brief
+ * Initialize the control structure. Note that the interface value was
+ * previously verified in the top level nor boot control.
+ */
+static Int32 __yaffs_open (void *ptr_driver, void (*asyncComplete)(void *))
+{
+ const char *name = ptr_driver;
+ nmcb.fd = yaffs_open(name, O_RDONLY, S_IREAD);
+ if (nmcb.fd < 0) {
+ printf("cant open %s to parse\r\n", name);
+ return -1;
+ }
+ nmcb.startPos = 0;
+ nmcb.fpos = 0;
+ return 0;
+}
+
+/**
+ * @brief
+ * Read data from the current address. This function is used
+ * for peek as well as read.
+ */
+static Int32 __yaffs_read (Uint8 *ptr_buf, Uint32 num_bytes)
+{
+ int nr;
+ if (nmcb.fd < 0)
+ return (-1);
+
+ yaffs_lseek(nmcb.fd, nmcb.fpos, SEEK_SET);
+ nr = yaffs_read(nmcb.fd, ptr_buf, num_bytes);
+ nmcb.fpos += nr;
+ return 0;
+}
+
+static Int32 __yaffs_peek(Uint8 *ptr_buf, Uint32 num)
+{
+ Uint32 pos = nmcb.fpos;
+ int r = yaffs_read(nmcb.fd, ptr_buf, num);
+ nmcb.fpos = pos;
+ return (r);
+}
+
+/**
+ * @brief
+ * Return the number of bytes available for current read.
+ * Always return 1k
+ */
+static Int32 __yaffs_query (void)
+{
+ return 0x400;
+}
+
+/**
+ * @brief
+ * Close the nor driver
+ */
+static Int32 __yaffs_close (void)
+{
+ yaffs_close(nmcb.fd);
+ return (0);
+}
+
+/**
+ * @brief
+ * The global nor module function table
+ */
+static BOOT_MODULE_FXN_TABLE __boot_module = {
+ __yaffs_open, /* Open API */
+ __yaffs_close, /* Close API */
+ __yaffs_read, /* Read API */
+ NULL, /* Write API */
+ __yaffs_peek, /* Peek API */
+ __yaffs_seek, /* Seek API */
+ __yaffs_query /* Query API */
+};
+
+unsigned int yaffs_load_elf(const char *file)
+{
+ unsigned int entry = 0;
+
+ if (__boot_module.open((void *)file, NULL)) {
+ return 0;
+ }
+ load_elf(&__boot_module, &entry);
+ __boot_module.close();
+ return entry;
+}
diff --git a/writetool/.cproject b/writetool/.cproject
index d368cd1..82912c7 100644
--- a/writetool/.cproject
+++ b/writetool/.cproject
@@ -41,6 +41,7 @@
+
diff --git a/writetool/src/main.c b/writetool/src/main.c
index 565094c..6c5e91c 100644
--- a/writetool/src/main.c
+++ b/writetool/src/main.c
@@ -2,9 +2,8 @@
* main.c
*
* Created on: 2019-6-26
- * Author: Administrator
+ * Author: shiqiang
*/
-
#include
#include
#include
@@ -12,28 +11,68 @@
#include
#include
+#include
+#include
+#include
#include "cJSON.h"
-#define NOR_API_MODE NOR_FLASH_MODE_SPI
+#define EMIF_NAND_CS0 0
+#define EMIF_NAND_CS1 1
+#define NOR_API_MODE NOR_FLASH_MODE_SPI
-#define CONFIG_FILE "flash.json"
+#define CONFIG_FILE "images.json"
/* NOR writer utility version */
-char version[] = "03.00.00.00";
+char version[] = "04.00.00.00";
/* The input file name is hard coded */
char *input_file = "nor_writer_input.txt";
/* Parameters defined in the input_file */
-#define FILE_NAME "file_name"
-#define START_ADDR "start_addr"
+#define FILE_NAME "file_name"
+#define START_ADDR "start_addr"
/* Memory address to store the write data */
-#define WRITE_DATA_ADDRESS 0x80000000
-
+#define WRITE_DATA_ADDRESS 0x90000000
#define READ_DATA_ADDRESS 0xA0000000
+#define MAX_LINE_LENGTH 128
+
+static nand_flash_t __emif_nand;
+static struct nand_partition __data_part = {
+ "nand",
+ 4,
+ 408
+};
-#define MAX_LINE_LENGTH 128
+static int yaffs_inited = 0;
+
+static int nand_yaffs_initialize()
+{
+ if (__emif_nand == NULL)
+ return -1;
+ if (yaffs_inited) {
+ return 0;
+ }
+ if (__data_part.end_block < __data_part.start_block)
+ __data_part.end_block = __emif_nand->block_count - 1;
+
+ if (!vsky_yaffs_setup( __emif_nand, NULL, 1, &__data_part)) {
+#if 0
+ int nr;
+ nr = yaffs_format("/nand", 0, 0, 0);
+ if (nr < 0) {
+ printf("format failed\r\n");
+ }
+ exit(0);
+#endif
+
+ if (yaffs_mount("/nand") == 0) {
+ yaffs_inited = 1;
+ return 0;
+ }
+ }
+ return -2;
+}
static cJSON *load_config_file(const char *file)
{
@@ -64,7 +103,7 @@ static cJSON *load_config_file(const char *file)
root = cJSON_Parse(buf);
if (root == NULL) {
- printf("%s: file format error.\r\n");
+ printf("%s: file format error.\r\n", file);
}
free(buf);
return (root);
@@ -136,20 +175,100 @@ unsigned int load_file(const char *fn)
}
do {
- len = fread(dest, 1024, 128, fp);
+ len = fread(dest, 1, 4096, fp);
if (len <= 0)
break;
- len *= 1024;
leng += len;
dest += len;
- printf("load file data to mem: %d \n", leng);
+ printf("load to mem: %08x \n", (WRITE_DATA_ADDRESS + leng));
} while(1);
fclose(fp);
return leng;
}
+int yaffs_program(const char *file, unsigned int flen)
+{
+ int fd;
+ char name[256];
+ unsigned char *data = (unsigned char *)WRITE_DATA_ADDRESS;
+
+ if (nand_yaffs_initialize()) {
+ printf("initialize yaffs2 filesystem failed.\r\n");
+ return -1;
+ }
+ sprintf(name, "/%s/%s", __data_part.name, file);
+ fd = yaffs_open(name, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
+ if (fd < 0) {
+ printf("can't open %s to write\r\n", file);
+ return -2;
+ }
+ yaffs_write(fd, data, flen);
+ yaffs_close(fd);
+
+ return 0;
+}
+
+int nand_program(unsigned int offset, unsigned int flen)
+{
+ int nr, block_id, i;
+ unsigned int block_size, pagesize;
+ unsigned char *data = (unsigned char *)WRITE_DATA_ADDRESS;
+ unsigned char *buf = (unsigned char *)READ_DATA_ADDRESS;
+ uint8_t spareData[2048];
+
+ if (__emif_nand == NULL) {
+ printf("nand initialize failed.\r\n");
+ return -1;
+ }
+
+ pagesize = __emif_nand->data_bytes_per_page;
+ block_size = pagesize * __emif_nand->page_count_per_block;
+ if (offset & (block_size - 1)) {
+ printf("offset misalign: offset 0x%x, block_size: 0x%x\r\n", offset, block_size);
+ return -1;
+ }
+
+ int retry;
+ while (flen > 0) {
+ block_id = offset / block_size;
+ retry = 0;
+ spareData[0] = 0x0;
+ nand_flash_read_spare_area(__emif_nand, block_id, 0, spareData);
+ if (spareData[0] != 0xff) {
+ printf("block %d is bad\r\n", block_id);
+ }
+retry_erase:
+ nr = nand_flash_earse_block(__emif_nand, block_id);
+ printf("erase block %d %s\r\n", block_id, nr == 0 ? "success" : "failed");
+ if (nr) {
+ tsc_delay(5000);
+ ++retry;
+ if (retry < 5)
+ goto retry_erase;
+ break;
+ }
+
+ for (i = 0; i < __emif_nand->page_count_per_block && flen > 0; ++i) {
+ nand_flash_write_page(__emif_nand, block_id, i, data);
+ nand_flash_read_page(__emif_nand, block_id, i, buf);
+ /* verify */
+ nr = memcmp(data, buf, pagesize);
+ printf("wrotten block [%d] page [%d] : %s\r\n", block_id, i, nr == 0 ? "success" : "failed");
+ data += pagesize;
+ buf += pagesize;
+ offset += pagesize;
+ if (flen > pagesize) {
+ flen -= pagesize;
+ } else {
+ flen = 0;
+ }
+ }
+ }
+ return 0;
+}
+
int nor_program(unsigned int nor_addr, unsigned int size)
{
nor_flash_t nf;
@@ -229,7 +348,7 @@ static int do_flash_images(cJSON *root)
{
int i, n = 0, x = 0;
cJSON *elem, *node, *img = cJSON_GetObjectItem(root, "images");
- const char *file;
+ const char *file, *mtype;
unsigned int offset, flen;
if (img == NULL) {
@@ -259,10 +378,17 @@ static int do_flash_images(cJSON *root)
if (!elem) {
continue;
}
- if (strcmp(cJSON_GetStringValue(elem), "spi") == 0) {
+ mtype = cJSON_GetStringValue(elem);
+ if (strcmp(mtype, "spi") == 0) {
nor_program(offset, flen);
printf("write %s to 0x%x\r\n", file, offset);
++x;
+ } else if (strcmp(mtype, "yaffs") == 0) {
+ yaffs_program(file, flen);
+ ++x;
+ } else if (strcmp(mtype, "nand") == 0) {
+ nand_program(offset, flen);
+ ++x;
}
}
return (x);
@@ -273,25 +399,111 @@ unsigned int board_input_clock()
return 100000000;
}
-/******************************************************************************
- * Function: main
- ******************************************************************************/
+static cJSON *load_config_from_nand(const char *file)
+{
+ int fd;
+ struct yaffs_stat stbuf;
+ char *buf;
+ cJSON *root;
+
+ fd = yaffs_open(file, O_RDONLY, S_IREAD);
+ if (fd < 0) {
+ printf("[yaffs] can't open configuration file: %s\r\n", file);
+ return NULL;
+ }
+
+ yaffs_fstat(fd, &stbuf) ;
+ printf("[yaffs]: file size %u bytes\r\n", stbuf.st_size);
+
+ buf = malloc(stbuf.st_size + 1);
+ if (buf == NULL) {
+ printf("out of memory: %d bytes\r\n", stbuf.st_size);
+ yaffs_close(fd);
+ return NULL;
+ }
+ yaffs_read(fd, buf, stbuf.st_size);
+ yaffs_close(fd);
+ buf[stbuf.st_size] = 0;
+
+ root = cJSON_Parse(buf);
+ if (root == NULL) {
+ printf("%s: file format error.\r\n", file);
+ }
+ free(buf);
+ return (root);
+}
+
+int write_images_json()
+{
+ unsigned int flen = load_file("images.json");
+ unsigned char *data = (unsigned char *)WRITE_DATA_ADDRESS;
+ int fd;
+
+ fd = yaffs_open("/nand/images.json", O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
+ if (fd < 0) {
+ printf("can't open /nand/images.json to write\r\n");
+ return -1;
+ }
+ yaffs_write(fd, data, flen);
+ yaffs_close(fd);
+ return 0;
+}
+/*
+ * Function: main
+ */
int main(void )
{
- int ret;
- cJSON *root;
+ int nr = 0, ret = 0;
+ cJSON *root = NULL;
+ int is_mounted = 0;
tsc_init();
+ emif16_init_ex((0x1 << EMIF_NAND_CS0) );
+ __emif_nand = nand_flash_open(EMIF_NAND_CS0, 0);
+
+ nr = nand_yaffs_initialize();
+ printf("yaffs initialized: %s\r\n", nr == 0 ? "success" : "failed");
+
+ is_mounted = yaffs_inited;
+
printf("NOR Writer Utility Version %s\n\n", version);
+#if 0
+ if (is_mounted) {
+ struct yaffs_stat stbuf;
+ int fd = yaffs_open("/nand/vs_xc003.bin", O_RDONLY, S_IREAD);
+ if (fd < 0) {
+ printf("can't open vs_xc003\r\n");
+ } else {
+ yaffs_fstat(fd, &stbuf);
+ yaffs_close(fd);
+ printf("file size: %lu\r\n", stbuf.st_size);
+ }
+ yaffs_unmount("/nand");
+ exit(0);
+ }
+#endif
+
+#if 0
+ if (is_mounted) {
+ write_images_json();
+ printf("loading configuration from yaffs.\r\n");
+ root = load_config_from_nand("/nand/images.json");
+ }
+#endif
+ if (root == NULL) {
+ root = load_config_file(CONFIG_FILE);
+ }
- root = load_config_file(CONFIG_FILE);
if (!root) {
return 0;
}
ret = do_flash_images(root);
cJSON_Delete(root);
+ if (is_mounted) {
+ yaffs_unmount("/nand");
+ }
printf("write %d images\r\n", ret);
return 0;
}
diff --git a/writetool/write.cmd b/writetool/write.cmd
index 5025be5..ce7e53d 100644
--- a/writetool/write.cmd
+++ b/writetool/write.cmd
@@ -1,34 +1,34 @@
--c -heap 0x100000 -stack 0x4000
+-c -heap 0x8000000 -stack 0x2000000
/* Memory Map */
MEMORY {
L1PSRAM (RWX) : org = 0x0E00000, len = 0x7FFF
L1DSRAM (RWX) : org = 0x0F00000, len = 0x7FFF
L2SRAM (RWX) : org = 0x0800000, len = 0x080000
- MSMCSRAM (RWX) : org = 0xc000000, len = 0x200000
- DDR3 (RWX) : org = 0x80000000,len = 0x40000000
+ MSMCSRAM (RWX) : org = 0xc000000, len = 0x400000
+ DDR3 (RWX) : org = 0x80000000,len = 0x10000000
}
SECTIONS {
- .sysmem > MSMCSRAM
- .csl_vect > MSMCSRAM
- .text > MSMCSRAM
+ .sysmem > DDR3
+ .csl_vect > DDR3
+ .text > DDR3
GROUP (NEAR_DP)
{
.neardata
.rodata
.bss
- } load > MSMCSRAM
+ } load > DDR3
- .stack > MSMCSRAM
- .cinit > MSMCSRAM
- .cio > MSMCSRAM
- .const > MSMCSRAM
- .data > MSMCSRAM
- .switch > MSMCSRAM
- .far > MSMCSRAM
- .testMem > MSMCSRAM
- .fardata > MSMCSRAM
- .init_array > MSMCSRAM
- .serial_buffer > MSMCSRAM
+ .stack > DDR3
+ .cinit > DDR3
+ .cio > DDR3
+ .const > DDR3
+ .data > DDR3
+ .switch > DDR3
+ .far > DDR3
+ .testMem > DDR3
+ .fardata > DDR3
+ .init_array > DDR3
+ .serial_buffer > DDR3
}