最新的v1.3.6版本支持全志F101芯片,单核C907,1.008G主频,内置8M/16M PSRAM,支持丰富的屏幕显示接口。
支持的指令:
1,获取唯一ID
2, 复位芯片
3,初始化JTAG调试口
4,初始化PSRAM
5,支持SPI NOR FLASH烧写
6,支持SPI NAND FLASH烧写
7,支持DUMP 512bits 内部熔丝
8,支持烧写内部512位熔丝
最新的v1.3.6版本支持全志F101芯片,单核C907,1.008G主频,内置8M/16M PSRAM,支持丰富的屏幕显示接口。
支持的指令:
1,获取唯一ID
2, 复位芯片
3,初始化JTAG调试口
4,初始化PSRAM
5,支持SPI NOR FLASH烧写
6,支持SPI NAND FLASH烧写
7,支持DUMP 512bits 内部熔丝
8,支持烧写内部512位熔丝
全志的SOC,只要不是太老旧的芯片,里面都集成了2048bit的EFUSE,但此熔丝位的很多细节,并没有相关描述文档,这导致大家很难在实际项目中应用此功能,而且也缺乏灵活的烧写工具,基于此问题,我花了点时间扩展了下XFEL工具。
现已支持如下芯片的efuse烧写:
1,D1 / D1s / F133
2,T113 / R528
3,V851/ V853
扩展的烧写命令:
usage:
xfel extra efuse dump - Dump all of the efuse information
xfel extra efuse read32 <offset> - Read 32-bits value from efuse
xfel extra efuse write32 <offset> <value> - Write 32-bits value to efuse
xfel extra efuse write <offset> <file> - Write file to efuse
Dump芯片EFUSE
xfel extra efuse dump
chipid:(0x0000 128-bits)
93406000 0c004814 01426250 48671b4b
brom-conf-try:(0x0010 32-bits)
00000000
thermal-sensor:(0x0014 64-bits)
88fbc11a 01e9080f
ft-zone:(0x001c 128-bits)
898f1919 0f760f6c 3108126c 811a0a0e
tvout:(0x002c 32-bits)
0000028f
tvout-gamma:(0x0030 64-bits)
00000000 00000000
oem-program:(0x0038 64-bits)
00000000 00000000
write-protect:(0x0040 32-bits)
00000000
read-protect:(0x0044 32-bits)
00000000
reserved1:(0x0048 64-bits)
00000000 00000000
huk:(0x0050 192-bits)
00000000 00000000 00000000 00000000 00000000 00000000
reserved2:(0x0068 64-bits)
00000000 00000000
rotpk:(0x0070 256-bits)
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
ssk:(0x0090 256-bits)
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
rssk:(0x00b0 128-bits)
00000000 00000000 00000000 00000000
hdcp-hash:(0x00c0 128-bits)
00000000 00000000 00000000 00000000
nv1:(0x00d0 32-bits)
00000000
nv2:(0x00d4 32-bits)
00000000
reserved3:(0x00d8 96-bits)
00000000 00000000 00000000
oem-program-secure:(0x00e4 224-bits)
00000000 00000000 00000000 00000000 00000000 00000000 00000000
完整讨论贴,见坑网
https://whycan.com/t_9947.html
@steward 感谢司徒的研究,发现了一个大BUG,中断号偏移计算错误,现已修复,打补丁如下:
diff --git a/src/arch/arm32/mach-t113s3/romdisk/boot/mangopi.json b/src/arch/arm32/mach-t113s3/romdisk/boot/mangopi.json
index 0f1f34283..4bc02d253 100644
--- a/src/arch/arm32/mach-t113s3/romdisk/boot/mangopi.json
+++ b/src/arch/arm32/mach-t113s3/romdisk/boot/mangopi.json
@@ -386,12 +386,12 @@
"reset-t113@0x02001d0c": { "reset-base": 1184, "reset-count": 32 },
"irq-gic400@0x03020000": { "interrupt-base": 32, "interrupt-count": 224 },
- "irq-t113-gpio@0x02000220": { "interrupt-base": 224, "interrupt-count": 8, "interrupt-parent": 101 },
- "irq-t113-gpio@0x02000240": { "interrupt-base": 256, "interrupt-count": 8, "interrupt-parent": 103 },
- "irq-t113-gpio@0x02000260": { "interrupt-base": 288, "interrupt-count": 23, "interrupt-parent": 105 },
- "irq-t113-gpio@0x02000280": { "interrupt-base": 320, "interrupt-count": 14, "interrupt-parent": 107 },
- "irq-t113-gpio@0x020002a0": { "interrupt-base": 352, "interrupt-count": 7, "interrupt-parent": 109 },
- "irq-t113-gpio@0x020002c0": { "interrupt-base": 384, "interrupt-count": 16, "interrupt-parent": 111 },
+ "irq-t113-gpio@0x02000220": { "interrupt-base": 256, "interrupt-count": 8, "interrupt-parent": 101 },
+ "irq-t113-gpio@0x02000240": { "interrupt-base": 288, "interrupt-count": 8, "interrupt-parent": 103 },
+ "irq-t113-gpio@0x02000260": { "interrupt-base": 320, "interrupt-count": 23, "interrupt-parent": 105 },
+ "irq-t113-gpio@0x02000280": { "interrupt-base": 352, "interrupt-count": 14, "interrupt-parent": 107 },
+ "irq-t113-gpio@0x020002a0": { "interrupt-base": 384, "interrupt-count": 7, "interrupt-parent": 109 },
+ "irq-t113-gpio@0x020002c0": { "interrupt-base": 416, "interrupt-count": 16, "interrupt-parent": 111 },
"gpio-t113@0x02000030": { "gpio-base": 32, "gpio-count": 8, "interrupt-offset": 256 },
"gpio-t113@0x02000060": { "gpio-base": 64, "gpio-count": 8, "interrupt-offset": 288 },
完整补丁见这个链接
https://github.com/xboot/xboot/commit/4e502b7ad6e4f589832d36a4513de00f0cb8de07
R128先跑跑xboot
█████████████████████████████████
██ ▄▄▄▄▄ █ ▀███▀ ▄█▀█ ▄█ ▄▄▄▄▄ ██
██ █ █ █ ▀▄█▄▄▀▄▀█▄▀ █ █ █ ██
██ █▄▄▄█ █▄ ▄▄▀█▄▀█ ▄█ █▄▄▄█ ██
██▄▄▄▄▄▄▄█ █ █▄▀▄█▄▀▄▀▄█▄▄▄▄▄▄▄██
███▄▄█▄█▄▄▀█ ▀ ▀ ▀ ███ ▀▄ ▄▄ ██
██▀ ▄▄ ▄▄█▄▄ ▀ ▄▄▀▄▀▄█ ▀▄▀▄▀▄██
██▄▀▄█▄█▄ ▄▄█▀▄▀ ▀ ███ ██ ██ ██
███ ▄▄▄▄▄▄ ▄▄▀▀▄▄█▀▀▄▀▄▀▄▀▄▀▄▀▄██
██▄▄█▀▄▄▄ ▄ ▀▀▄▄▄▀▄ ███ █ ██ ██
██▄▀▄▄█ ▄▀▀▄▀▄ ▄▀▀▄▀▄▀▄▀▄▀▄▀▄▀▄██
██▄██▄█▄▄█▀▀▀▄█ ███ █ ▄▄▄ ██ ██
██ ▄▄▄▄▄ █▄ ██▀ ▀▀▄▀▄ █▄█ ▀▄▀▄██
██ █ █ █▄▀██▀█▄██ ▀▄ ▄▄ █▀ ██
██ █▄▄▄█ █ ▀▀▄▄██▀▄▀▄█ █▀▄▀▄▀▄██
██▄▄▄▄▄▄▄███▄▄▄▄▄██▄▄█▄█▄█▄▄█▄▄██
█████████████████████████████████
_ _
_ _ | |___ _____ _____ _| |_
\ \/ /| _ | _ | _ |_ _| (C) 2007-2023
) ( | |_| | |_| | |_| | | |____JIANJUN.JIANG__
/_/\_\|_____|_____|_____| |_____________________|
V3.0.0 (May 17 2023 - 23:25:28) - [yuzuki][Yuzuki Based On Allwinner R128 SOC]
[ 0.000020]Probe device 'blk-romdisk.0' with blk-romdisk
[ 0.000800]Probe device 'osc48m' with clk-fixed
[ 0.000810]Probe device 'osc32k' with clk-fixed
[ 0.000820]Probe device 'bus-uart0' with clk-fixed
[ 0.000830]Probe device 'wdg' with clk-fixed
[ 0.000840]Probe device 'uart-16550.0' with uart-16550
[ 0.000850]Probe device 'wdg-r128.0' with wdg-r128
[ 0.000860]Probe device 'console-uart.0' with console-uart
[ 0.000970]mount /private with 'ram' filesystem
Press any key to stop auto boot: 0.330
xboot: /#
xfel工具已支持具体绝大部分全志芯片,现在计划实现对R128芯片的支持。
1,读写SRAM(已完成)
2,执行运行在M33核的payload指令(已完成)
3,读取R128的SID(已完成)
4,初始化M33核心的jtag接口,此接口跟调试串口复用(已开发,未测试)
5,实现reset操作(已完成)
6,初始化LSPRAM以及HSPSRAM(已完成)
7, 支持启动C906核心,加载并执行通过write命令写入到RAM中的C906程序
8, 支持启动DSP核心,加载并执行通过write命令写入到RAM中的DSP程序 (优先级低,估计没手段验证)
9,支持烧写NOR FLASH
@qinchangzu 打这个补丁,可以帮忙测试下,看是否解决问题了
diff --git a/spinor.c b/spinor.c
index 7a30307..8cc6e95 100644
--- a/spinor.c
+++ b/spinor.c
@@ -287,6 +287,85 @@ static inline int spinor_info(struct xfel_ctx_t * ctx, struct spinor_pdata_t * p
return 0;
}
+static inline uint8_t spinor_read_sr3(struct xfel_ctx_t * ctx, struct spinor_pdata_t * pdat)
+{
+ uint8_t tx[1];
+ uint8_t rx[1];
+
+ tx[0] = 0x15;
+ rx[0] = 0x0;
+ fel_spi_xfer(ctx, pdat->swapbuf, pdat->swaplen, pdat->cmdlen, tx, 1, rx, 1);
+ return rx[0];
+}
+
+static inline int spinor_global_unlock(struct xfel_ctx_t * ctx, struct spinor_pdata_t * pdat)
+{
+ uint8_t cbuf[256];
+ uint32_t clen = 0;
+ uint8_t sr3 = spinor_read_sr3(ctx, pdat);
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* write enable */
+ cbuf[clen++] = SPI_CMD_FAST;
+ cbuf[clen++] = 1;
+ cbuf[clen++] = pdat->info.opcode_write_enable;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* global block/sector unlock */
+ cbuf[clen++] = SPI_CMD_FAST;
+ cbuf[clen++] = 1;
+ cbuf[clen++] = 0x98;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* wait busy */
+ cbuf[clen++] = SPI_CMD_SPINOR_WAIT;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* write enable */
+ cbuf[clen++] = SPI_CMD_FAST;
+ cbuf[clen++] = 1;
+ cbuf[clen++] = pdat->info.opcode_write_enable;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* write status 3 and clear wps bit */
+ cbuf[clen++] = SPI_CMD_FAST;
+ cbuf[clen++] = 2;
+ cbuf[clen++] = 0x11;
+ cbuf[clen++] = sr3 & ~(0x1 << 4);
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* wait busy */
+ cbuf[clen++] = SPI_CMD_SPINOR_WAIT;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* end */
+ cbuf[clen++] = SPI_CMD_END;
+ if(clen <= pdat->cmdlen)
+ {
+ fel_chip_spi_run(ctx, cbuf, clen);
+ return 1;
+ }
+ return 0;
+}
+
+
static int spinor_helper_init(struct xfel_ctx_t * ctx, struct spinor_pdata_t * pdat)
{
uint8_t cbuf[256];
@@ -370,6 +449,7 @@ static int spinor_helper_init(struct xfel_ctx_t * ctx, struct spinor_pdata_t * p
if(clen <= pdat->cmdlen)
{
fel_chip_spi_run(ctx, cbuf, clen);
+ spinor_global_unlock(ctx, pdat);
return 1;
}
}
打这个补丁,可以帮忙测试下。
diff --git a/spinor.c b/spinor.c
index 7a30307..8cc6e95 100644
--- a/spinor.c
+++ b/spinor.c
@@ -287,6 +287,85 @@ static inline int spinor_info(struct xfel_ctx_t * ctx, struct spinor_pdata_t * p
return 0;
}
+static inline uint8_t spinor_read_sr3(struct xfel_ctx_t * ctx, struct spinor_pdata_t * pdat)
+{
+ uint8_t tx[1];
+ uint8_t rx[1];
+
+ tx[0] = 0x15;
+ rx[0] = 0x0;
+ fel_spi_xfer(ctx, pdat->swapbuf, pdat->swaplen, pdat->cmdlen, tx, 1, rx, 1);
+ return rx[0];
+}
+
+static inline int spinor_global_unlock(struct xfel_ctx_t * ctx, struct spinor_pdata_t * pdat)
+{
+ uint8_t cbuf[256];
+ uint32_t clen = 0;
+ uint8_t sr3 = spinor_read_sr3(ctx, pdat);
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* write enable */
+ cbuf[clen++] = SPI_CMD_FAST;
+ cbuf[clen++] = 1;
+ cbuf[clen++] = pdat->info.opcode_write_enable;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* global block/sector unlock */
+ cbuf[clen++] = SPI_CMD_FAST;
+ cbuf[clen++] = 1;
+ cbuf[clen++] = 0x98;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* wait busy */
+ cbuf[clen++] = SPI_CMD_SPINOR_WAIT;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* write enable */
+ cbuf[clen++] = SPI_CMD_FAST;
+ cbuf[clen++] = 1;
+ cbuf[clen++] = pdat->info.opcode_write_enable;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* write status 3 and clear wps bit */
+ cbuf[clen++] = SPI_CMD_FAST;
+ cbuf[clen++] = 2;
+ cbuf[clen++] = 0x11;
+ cbuf[clen++] = sr3 & ~(0x1 << 4);
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* spi select */
+ cbuf[clen++] = SPI_CMD_SELECT;
+ /* wait busy */
+ cbuf[clen++] = SPI_CMD_SPINOR_WAIT;
+ /* spi deselect */
+ cbuf[clen++] = SPI_CMD_DESELECT;
+
+ /* end */
+ cbuf[clen++] = SPI_CMD_END;
+ if(clen <= pdat->cmdlen)
+ {
+ fel_chip_spi_run(ctx, cbuf, clen);
+ return 1;
+ }
+ return 0;
+}
+
+
static int spinor_helper_init(struct xfel_ctx_t * ctx, struct spinor_pdata_t * pdat)
{
uint8_t cbuf[256];
@@ -370,6 +449,7 @@ static int spinor_helper_init(struct xfel_ctx_t * ctx, struct spinor_pdata_t * p
if(clen <= pdat->cmdlen)
{
fel_chip_spi_run(ctx, cbuf, clen);
+ spinor_global_unlock(ctx, pdat);
return 1;
}
}
@tripod9 spi nor flash的写保护功能,从各种现象推测得出,保护位应该是持久化的,即使断电,重启,都无法改变状态,只要被锁定了,只有被解锁才能再次写入。这个要求也能解释你为何只能跑一次某些rtos,这个rtos肯定自作主张的锁定了spi nor flash,只要运行一次,就被搞了。我手上没有条件试验这个问题,可以在xfel加解锁代码,彻底解决此类问题。
查看xfel代码,发现在spinor_helper_init时,已经对spi nor flash芯片做了reset处理,难道reset处理也不能unlock spi nor flash吗?可以尝试将unlock指令加在spinor_helper_init里试试
/* spi select */
cbuf[clen++] = SPI_CMD_SELECT;
/* chip reset */
cbuf[clen++] = SPI_CMD_FAST;
cbuf[clen++] = 2;
cbuf[clen++] = 0x66;
cbuf[clen++] = 0x99;
/* spi deselect */
cbuf[clen++] = SPI_CMD_DESELECT;
/* spi select */
cbuf[clen++] = SPI_CMD_SELECT;
/* wait busy */
cbuf[clen++] = SPI_CMD_SPINOR_WAIT;
/* spi deselect */
cbuf[clen++] = SPI_CMD_DESELECT;
/* spi select */
cbuf[clen++] = SPI_CMD_SELECT;
/* write enable */
cbuf[clen++] = SPI_CMD_FAST;
cbuf[clen++] = 1;
cbuf[clen++] = pdat->info.opcode_write_enable;
/* spi deselect */
cbuf[clen++] = SPI_CMD_DESELECT;
/* spi select */
cbuf[clen++] = SPI_CMD_SELECT;
/* write status */
cbuf[clen++] = SPI_CMD_FAST;
cbuf[clen++] = 2;
cbuf[clen++] = OPCODE_WRSR;
cbuf[clen++] = 0;
/* spi deselect */
cbuf[clen++] = SPI_CMD_DESELECT;
/* spi select */
cbuf[clen++] = SPI_CMD_SELECT;
/* wait busy */
cbuf[clen++] = SPI_CMD_SPINOR_WAIT;
/* spi deselect */
cbuf[clen++] = SPI_CMD_DESELECT;
@yuzukitsuru https://bbs.aw-ol.com/topic/3380/d1s-meils烧录导致xfel工具烧写失效/17
估计是这个问题,spi nor flash 被melis代码lock了。unlock下,应该就可以解决问题
@danfeng 有个对比方式,去确认哪里lock spi flash了。
1,先用镊子短接SPI NOR FLASH的数据脚到地,再上电启动,测试xfel烧写,擦除功能(大概率正常)
2,不短接,进入fel模式,比如在加载melis系统后再进入fel模式,这种情况,有可能会出现melis lock spi flash了。
进入fel有多种方式,1,空flash,2,短路flash,3利用系统自带的efex相关指令进入。lock flash仅可能发生在运行部分代码后导致的结果。
@l13819506056 频率是1.008G ,是否方便提供一个简单的可以测试中断的裸机程序。我debug下,现在我实验后发现总是产生swi异常,不知哪里在触发。
@l13819506056 我实验T113中断时,只要一中断,就会产生SWI异常,很神奇,我是裸奔,根本没执行swi相关指令。一直理解不了。
@yuzukitsuru
找到个这个函数,是R528里面的,id_judge_fun,有谁发现什么机关,需要找多个平台的id_judge_fun函数来对比,估计才能看出名堂。
uint id_judge_fun(uint param_1)
{
uint uVar1;
if ((_DAT_01c15004 & 7) == 0) {
uVar1 = disturb_coding(param_1,1);
return uVar1;
}
return 0;
}
uint disturb_coding(uint param_1,int param_2)
{
int iVar1;
iVar1 = crc_16(param_1,param_2);
return param_1 + param_2 | iVar1 << 0x10;
}
void crc_16(uint param_1,int param_2)
{
uint uVar1;
uint uVar2;
short sVar3;
uVar1 = param_1 ^ param_2 << 8;
sVar3 = 8;
do {
uVar2 = uVar1 & 0x8000;
uVar1 = (uVar1 & 0x7fff) << 1;
if (uVar2 != 0) {
uVar1 = (uVar1 ^ 0xffff8005) & 0xffff;
}
sVar3 = sVar3 + -1;
} while (sVar3 != 0);
return;
}
@kirin 在 D1/D1S 的区别是啥? 中说:
wifi/蓝牙可以通过外接无线芯片实现,比如哪吒板子上外接的就是XR829,可以做2.4Gwifi/BT.
预告:明年全志将会推出内置wifi/BT的RISC-V芯片,针对AIoT市场。
这个wifi/BT芯片,是MCU级别还是SOC级别,但愿内存不要太小,否则就跟市面上的没有区别了,可选余地很多。
新版本工具链,在某些老电脑上会出现编译器内部错误,2.0.3版本正常,但这之后的全部异常了。
Compiler executable checksum: 91a728100f71f55a898c866a0b8bf7a7
main.c: In function 'my_strtod':
main.c:37:3: internal compiler error: Illegal instruction
37 | number = number * 10. + (*p - '0');
| ^~~~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://gcc.gnu.org/bugs/> for instructions.
D1s内部含有一个电阻触摸控制器TSADC,可以直接连接标准的电阻触摸,这个控制器基本跟F1C100S的类似,所以编写驱动也就手到擒来,拷贝下,基本就可以了。对于电阻触摸屏,所涉及到的均值滤波,中值滤波,触摸校正参数等,这些xboot里都有成熟的解决方案,就不细说了。
下面是演示视频,感觉还是比较丝滑的。
在没有DE资料的情况下,盲猜型开发,终于搞定了D1s的RGB裸奔显示,顺理成章的就是运行各种风骚APP了,直接贴了,请鉴赏。
最新的SPI NAND FLASH支持列表如下:
/* Winbond */
{ "W25N512GV", SPINAND_ID(0xef, 0xaa, 0x20), 2048, 64, 64, 512, 1, 1 },
{ "W25N01GV", SPINAND_ID(0xef, 0xaa, 0x21), 2048, 64, 64, 1024, 1, 1 },
{ "W25M02GV", SPINAND_ID(0xef, 0xab, 0x21), 2048, 64, 64, 1024, 1, 2 },
{ "W25N02KV", SPINAND_ID(0xef, 0xaa, 0x22), 2048, 128, 64, 2048, 1, 1 },
/* Gigadevice */
{ "GD5F1GQ4UAWxx", SPINAND_ID(0xc8, 0x10), 2048, 64, 64, 1024, 1, 1 },
{ "GD5F1GQ4UExIG", SPINAND_ID(0xc8, 0xd1), 2048, 128, 64, 1024, 1, 1 },
{ "GD5F1GQ4UExxH", SPINAND_ID(0xc8, 0xd9), 2048, 64, 64, 1024, 1, 1 },
{ "GD5F1GQ4xAYIG", SPINAND_ID(0xc8, 0xf1), 2048, 64, 64, 1024, 1, 1 },
{ "GD5F2GQ4UExIG", SPINAND_ID(0xc8, 0xd2), 2048, 128, 64, 2048, 1, 1 },
{ "GD5F2GQ5UExxH", SPINAND_ID(0xc8, 0x32), 2048, 64, 64, 2048, 1, 1 },
{ "GD5F2GQ4xAYIG", SPINAND_ID(0xc8, 0xf2), 2048, 64, 64, 2048, 1, 1 },
{ "GD5F4GQ4UBxIG", SPINAND_ID(0xc8, 0xd4), 4096, 256, 64, 2048, 1, 1 },
{ "GD5F4GQ4xAYIG", SPINAND_ID(0xc8, 0xf4), 2048, 64, 64, 4096, 1, 1 },
{ "GD5F2GQ5UExxG", SPINAND_ID(0xc8, 0x52), 2048, 128, 64, 2048, 1, 1 },
{ "GD5F4GQ4UCxIG", SPINAND_ID(0xc8, 0xb4), 4096, 256, 64, 2048, 1, 1 },
/* Macronix */
{ "MX35LF1GE4AB", SPINAND_ID(0xc2, 0x12), 2048, 64, 64, 1024, 1, 1 },
{ "MX35LF1G24AD", SPINAND_ID(0xc2, 0x14), 2048, 128, 64, 1024, 1, 1 },
{ "MX31LF1GE4BC", SPINAND_ID(0xc2, 0x1e), 2048, 64, 64, 1024, 1, 1 },
{ "MX35LF2GE4AB", SPINAND_ID(0xc2, 0x22), 2048, 64, 64, 2048, 1, 1 },
{ "MX35LF2G24AD", SPINAND_ID(0xc2, 0x24), 2048, 128, 64, 2048, 1, 1 },
{ "MX35LF2GE4AD", SPINAND_ID(0xc2, 0x26), 2048, 128, 64, 2048, 1, 1 },
{ "MX35LF2G14AC", SPINAND_ID(0xc2, 0x20), 2048, 64, 64, 2048, 1, 1 },
{ "MX35LF4G24AD", SPINAND_ID(0xc2, 0x35), 4096, 256, 64, 2048, 1, 1 },
{ "MX35LF4GE4AD", SPINAND_ID(0xc2, 0x37), 4096, 256, 64, 2048, 1, 1 },
/* Micron */
{ "MT29F1G01AAADD", SPINAND_ID(0x2c, 0x12), 2048, 64, 64, 1024, 1, 1 },
{ "MT29F1G01ABAFD", SPINAND_ID(0x2c, 0x14), 2048, 128, 64, 1024, 1, 1 },
{ "MT29F2G01AAAED", SPINAND_ID(0x2c, 0x9f), 2048, 64, 64, 2048, 2, 1 },
{ "MT29F2G01ABAGD", SPINAND_ID(0x2c, 0x24), 2048, 128, 64, 2048, 2, 1 },
{ "MT29F4G01AAADD", SPINAND_ID(0x2c, 0x32), 2048, 64, 64, 4096, 2, 1 },
{ "MT29F4G01ABAFD", SPINAND_ID(0x2c, 0x34), 4096, 256, 64, 2048, 1, 1 },
{ "MT29F4G01ADAGD", SPINAND_ID(0x2c, 0x36), 2048, 128, 64, 2048, 2, 2 },
{ "MT29F8G01ADAFD", SPINAND_ID(0x2c, 0x46), 4096, 256, 64, 2048, 1, 2 },
/* Toshiba */
{ "TC58CVG0S3HRAIG", SPINAND_ID(0x98, 0xc2), 2048, 128, 64, 1024, 1, 1 },
{ "TC58CVG1S3HRAIG", SPINAND_ID(0x98, 0xcb), 2048, 128, 64, 2048, 1, 1 },
{ "TC58CVG2S0HRAIG", SPINAND_ID(0x98, 0xcd), 4096, 256, 64, 2048, 1, 1 },
{ "TC58CVG0S3HRAIJ", SPINAND_ID(0x98, 0xe2), 2048, 128, 64, 1024, 1, 1 },
{ "TC58CVG1S3HRAIJ", SPINAND_ID(0x98, 0xeb), 2048, 128, 64, 2048, 1, 1 },
{ "TC58CVG2S0HRAIJ", SPINAND_ID(0x98, 0xed), 4096, 256, 64, 2048, 1, 1 },
{ "TH58CVG3S0HRAIJ", SPINAND_ID(0x98, 0xe4), 4096, 256, 64, 4096, 1, 1 },
/* Esmt */
{ "F50L512M41A", SPINAND_ID(0xc8, 0x20), 2048, 64, 64, 512, 1, 1 },
{ "F50L1G41A", SPINAND_ID(0xc8, 0x21), 2048, 64, 64, 1024, 1, 1 },
{ "F50L1G41LB", SPINAND_ID(0xc8, 0x01), 2048, 64, 64, 1024, 1, 1 },
{ "F50L2G41LB", SPINAND_ID(0xc8, 0x0a), 2048, 64, 64, 1024, 1, 2 },
/* Fison */
{ "CS11G0T0A0AA", SPINAND_ID(0x6b, 0x00), 2048, 128, 64, 1024, 1, 1 },
{ "CS11G0G0A0AA", SPINAND_ID(0x6b, 0x10), 2048, 128, 64, 1024, 1, 1 },
{ "CS11G0S0A0AA", SPINAND_ID(0x6b, 0x20), 2048, 64, 64, 1024, 1, 1 },
{ "CS11G1T0A0AA", SPINAND_ID(0x6b, 0x01), 2048, 128, 64, 2048, 1, 1 },
{ "CS11G1S0A0AA", SPINAND_ID(0x6b, 0x21), 2048, 64, 64, 2048, 1, 1 },
{ "CS11G2T0A0AA", SPINAND_ID(0x6b, 0x02), 2048, 128, 64, 4096, 1, 1 },
{ "CS11G2S0A0AA", SPINAND_ID(0x6b, 0x22), 2048, 64, 64, 4096, 1, 1 },
/* Etron */
{ "EM73B044VCA", SPINAND_ID(0xd5, 0x01), 2048, 64, 64, 512, 1, 1 },
{ "EM73C044SNB", SPINAND_ID(0xd5, 0x11), 2048, 120, 64, 1024, 1, 1 },
{ "EM73C044SNF", SPINAND_ID(0xd5, 0x09), 2048, 128, 64, 1024, 1, 1 },
{ "EM73C044VCA", SPINAND_ID(0xd5, 0x18), 2048, 64, 64, 1024, 1, 1 },
{ "EM73C044SNA", SPINAND_ID(0xd5, 0x19), 2048, 64, 128, 512, 1, 1 },
{ "EM73C044VCD", SPINAND_ID(0xd5, 0x1c), 2048, 64, 64, 1024, 1, 1 },
{ "EM73C044SND", SPINAND_ID(0xd5, 0x1d), 2048, 64, 64, 1024, 1, 1 },
{ "EM73D044SND", SPINAND_ID(0xd5, 0x1e), 2048, 64, 64, 2048, 1, 1 },
{ "EM73C044VCC", SPINAND_ID(0xd5, 0x22), 2048, 64, 64, 1024, 1, 1 },
{ "EM73C044VCF", SPINAND_ID(0xd5, 0x25), 2048, 64, 64, 1024, 1, 1 },
{ "EM73C044SNC", SPINAND_ID(0xd5, 0x31), 2048, 128, 64, 1024, 1, 1 },
{ "EM73D044SNC", SPINAND_ID(0xd5, 0x0a), 2048, 120, 64, 2048, 1, 1 },
{ "EM73D044SNA", SPINAND_ID(0xd5, 0x12), 2048, 128, 64, 2048, 1, 1 },
{ "EM73D044SNF", SPINAND_ID(0xd5, 0x10), 2048, 128, 64, 2048, 1, 1 },
{ "EM73D044VCA", SPINAND_ID(0xd5, 0x13), 2048, 128, 64, 2048, 1, 1 },
{ "EM73D044VCB", SPINAND_ID(0xd5, 0x14), 2048, 64, 64, 2048, 1, 1 },
{ "EM73D044VCD", SPINAND_ID(0xd5, 0x17), 2048, 128, 64, 2048, 1, 1 },
{ "EM73D044VCH", SPINAND_ID(0xd5, 0x1b), 2048, 64, 64, 2048, 1, 1 },
{ "EM73D044SND", SPINAND_ID(0xd5, 0x1d), 2048, 64, 64, 2048, 1, 1 },
{ "EM73D044VCG", SPINAND_ID(0xd5, 0x1f), 2048, 64, 64, 2048, 1, 1 },
{ "EM73D044VCE", SPINAND_ID(0xd5, 0x20), 2048, 64, 64, 2048, 1, 1 },
{ "EM73D044VCL", SPINAND_ID(0xd5, 0x2e), 2048, 128, 64, 2048, 1, 1 },
{ "EM73D044SNB", SPINAND_ID(0xd5, 0x32), 2048, 128, 64, 2048, 1, 1 },
{ "EM73E044SNA", SPINAND_ID(0xd5, 0x03), 4096, 256, 64, 2048, 1, 1 },
{ "EM73E044SND", SPINAND_ID(0xd5, 0x0b), 4096, 240, 64, 2048, 1, 1 },
{ "EM73E044SNB", SPINAND_ID(0xd5, 0x23), 4096, 256, 64, 2048, 1, 1 },
{ "EM73E044VCA", SPINAND_ID(0xd5, 0x2c), 4096, 256, 64, 2048, 1, 1 },
{ "EM73E044VCB", SPINAND_ID(0xd5, 0x2f), 2048, 128, 64, 4096, 1, 1 },
{ "EM73F044SNA", SPINAND_ID(0xd5, 0x24), 4096, 256, 64, 4096, 1, 1 },
{ "EM73F044VCA", SPINAND_ID(0xd5, 0x2d), 4096, 256, 64, 4096, 1, 1 },
{ "EM73E044SNE", SPINAND_ID(0xd5, 0x0e), 4096, 256, 64, 4096, 1, 1 },
{ "EM73C044SNG", SPINAND_ID(0xd5, 0x0c), 2048, 120, 64, 1024, 1, 1 },
{ "EM73D044VCN", SPINAND_ID(0xd5, 0x0f), 2048, 64, 64, 2048, 1, 1 },
/* Elnec */
{ "FM35Q1GA", SPINAND_ID(0xe5, 0x71), 2048, 64, 64, 1024, 1, 1 },
/* Paragon */
{ "PN26G01A", SPINAND_ID(0xa1, 0xe1), 2048, 128, 64, 1024, 1, 1 },
{ "PN26G02A", SPINAND_ID(0xa1, 0xe2), 2048, 128, 64, 2048, 1, 1 },
/* Ato */
{ "ATO25D1GA", SPINAND_ID(0x9b, 0x12), 2048, 64, 64, 1024, 1, 1 },
/* Heyang */
{ "HYF1GQ4U", SPINAND_ID(0xc9, 0x51), 2048, 128, 64, 1024, 1, 1 },
{ "HYF2GQ4U", SPINAND_ID(0xc9, 0x52), 2048, 128, 64, 2048, 1, 1 },
@mangogeek 已添加Winbond SPI NAND的支持,因为华邦的ID是3个字节,其他的SPI NAND芯片是两个字节的ID,现在代码已做了扩展。
/* Winbond */
{ "W25N512GV", SPINAND_ID(0xef, 0xaa, 0x20), 2048, 64, 64, 512, 1, 1 },
{ "W25N01GV", SPINAND_ID(0xef, 0xaa, 0x21), 2048, 64, 64, 1024, 1, 1 },
{ "W25M02GV", SPINAND_ID(0xef, 0xab, 0x21), 2048, 64, 64, 1024, 1, 2 },
{ "W25N02KV", SPINAND_ID(0xef, 0xaa, 0x22), 2048, 128, 64, 2048, 1, 1 },
LDO有默认电压,而且永远使能,不能软件关闭,具体驱动看这里
https://gitee.com/xboot/xboot/commit/bb13f14a493780d184601125b4f88cecddfbf049
@memory 看来要去绑cpuid了,spi nor flash id还是不太靠谱
@xiaowenge 好奢侈,你那么多板子,我一个也没有,不公平,卖我一个呗.
研究RISCV D1芯片已经一个月有余了,中间为了方便开发,也开发了一个烧写工具xfel,为方便大家研究学习,这里编写了一个简化的裸机程序,供大家参考,实现比较简单,但该有的都有了。(从xboot精简而来,想要研究高阶功能,就去参考xboot源码树)
在DDR中运行d1-baremetal.bin,这种方式比较适合快速开发调试。借助xfel工具就可以实现。
sudo xfel ddr ddr3;sudo xfel write 0x40000000 d1-baremetal.bin;sudo xfel exec 0x40000000;
烧写d1-baremetal.bin到spi nor flash,固化程序到spi nor flash, 然后上电,自动实现初始化ddr,并自拷贝到ddr中运行。
sudo xfel spinor write 0 d1-baremetal.bin
程序正确运行后,会打印如下信息
D1 baremetal
count = 0
count = 1
count = 2
count = 3
count = 4
count = 5
count = 6
count = 7
count = 8
count = 9
count = 10
count = 11
count = 12
count = 13
count = 14
count = 15
count = 16
一些参考链接
https://github.com/xboot/xfel
https://github.com/xboot/xboot
在缺乏工具前,都是利用已有的软件,间接开发,现在有了专用工具,就无需像那么折腾了,仅需在板子上电时,按着fel按键,敲一下如下,指令就可以将xboot运行在DDR中,复杂的开发工作,从此变得简单起来。
sudo xfel ddr ddr3
sudo xfel write 0x40000000 output/xboot.bin
sudo xfel exec 0x40000000
补充下,xboot代码的获取与编译,工具链随便了,你想用玄铁的也行,啥都可以的。
git clone https://github.com/xboot/xboot/ -b test-d1
CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=riscv64-d1 make -j3

借用下晕哥的图,在晕哥的努力下,XFEL现在有了windows版了,方便使用win做开发的同学。
工欲善其事,必先利其器,全志D1沿用传统设计思路,brom里面集成了FEL模式,这个模式是一个很有用的模式,可以烧录,测试,能干的事情很多,本来这种工具也是有成熟的可用,比如:sunxi-fel,基本算裸奔必用的开发工具,但突然来了个RISCV版的FEL,sunxi-fel就无能为力,其深度绑定ARM实现,里面的payload都是arm,根本没有riscv,没有工具,想正向开发,比登天还难。
仔细分析D1的fel,发现其烧写工具跟原先的一致,没有做任何更新,那也就是说,fel标准协议其实是指令集无关的,有了这个信息就好办了,我们完全也可以创建一个指令集无关的fel工具,阅读sunxi-fel,发现其改造困难,基本深度绑定,没有太多开发的意义,还不如重新开发,轻装上阵,遂有了此工程。
此工具理论上全志全系列芯片都可以支持,不管是arm32,arm64,riscv64,重点目标是riscv64的D1支持,设计时避免过多hack,增强适应性,最大的特色借用xfel工具可以直接初始化DDR。有了直接能初始化DDR的fel工具,开发裸机就没有任何难度了,当单片机耍。
xfel(v1.0.1) - https://github.com/xboot/xfel
usage:
xfel help - Print this usage
xfel version - Show brom version
xfel hexdump <address> <length> - Dumps memory region in hex
xfel dump <address> <length> - Binary memory dump to stdout
xfel exec <address> - Call function address
xfel read32 <address> - Read 32-bits value from device memory
xfel write32 <address> <value> - Write 32-bits value to device memory
xfel read <address> <length> <file> - Read memory to file
xfel write <address> <file> - Write file to memory
xfel reset - Reset device using watchdog
xfel sid - Show 128-bits sid information
xfel jtag - Enable jtag debug
xfel ddr [type] - Initial ddr controller with optional type
xfel spinor - Detect spi nor flash
xfel spinor read <address> <length> <file> - Read spi nor flash to file
xfel spinor write <address> <file> - Write file to spi nor flash
xfel spinand - Detect spi nand flash
xfel spinand read <address> <length> <file> - Read spi nand flash to file
xfel spinand write <address> <file> - Write file to spi nand flash