您尚未登录。

楼主 # 2021-06-19 18:50:12

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

研究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






点击下载: d1-baremetal.7z

https://github.com/xboot/xfel
https://github.com/xboot/xboot

离线

#1 2021-06-19 19:03:55

cube
会员
注册时间: 2021-03-11
已发帖子: 190
积分: 114.5

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

请问楼主怎么实现同一个固件,既能在ddr跑,又能在flash跑的?

离线

楼主 #2 2021-06-19 19:54:19

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

	la t0, _start
	la t1, _image_start
	LREG t1, (t1)
	beq t0, t1, _avoid

	/* Initial system jtag, uart and clock */
	call sys_jtag_init
	call sys_uart_init
	call sys_clock_init

	/* Copy ddr bin to 0x00030000 */
	la t1, _ddr_bin_start
	LREG t1, (t1)
	la t2, _ddr_bin_end
	LREG t2, (t2)
	sub a2, t2, t1
	la t1, _image_start
	LREG t1, (t1)
	la t2, _ddr_bin_start
	LREG t2, (t2)
	sub t0, t2, t1
	la a1, _start
	add a1, a1, t0
	li a0, 0x00030000
	call memcpy

	/* Initial ddr controller */
	call sys_dram_init
_avoid:
	nop
	/* Copyself to link address */
	la t0, _start
	la t1, _image_start
	LREG t1, (t1)
	beq t0, t1, 1f
	call sys_copyself
1:	nop

核心就这个地方,判断当前运行地址是否是链接地址,nor flash启动的话,肯定不是链接地址,那么就会多做很多事,初始化时钟,DDR,自拷贝等,如果是链接地址,那么就跳过这些动作,直接在DDR中运行。

离线

#3 2021-06-19 21:03:10

cube
会员
注册时间: 2021-03-11
已发帖子: 190
积分: 114.5

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

原来如此,感谢大佬解惑。

离线

#4 2021-06-20 19:04:08

微凉VeiLiang
会员
所在地: 深圳
注册时间: 2018-10-28
已发帖子: 562
积分: 501
个人网站

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

好东西,感谢xboot大佬分享裸机工程

离线

#5 2021-06-21 13:16:55

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

请问楼主,按照您的步骤,利用xfel工具直接在DDR中运行d1-baremetal.bin,串口输出运行信息,但是烧录到spi nor flash后,上电运行,串口并未输出信息,这是怎么回事呢?_20210621-1316.png

离线

#6 2021-06-21 13:27:03

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

利用spinor read 读出spi nor中的内容 发现没有并没有将.bin写进去

离线

#7 2021-06-21 13:52:39

哇酷小二
管理员
注册时间: 2020-04-22
已发帖子: 2,813
积分: 1902

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

是d1吗,你的flash型号是什么,焊好了吗?

xfel spinor 这个命令检测出是什么型号?

离线

#8 2021-06-21 13:58:49

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

是d1,应该是焊接好了,spi nor flash的信息如下:
111_20210621-1358.png
用xfel spinor这个命令输出的信息如下_20210621-1357.png

离线

#9 2021-06-21 14:02:09

哇酷小二
管理员
注册时间: 2020-04-22
已发帖子: 2,813
积分: 1902

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

March 说:

是d1,应该是焊接好了,spi nor flash的信息如下:
https://whycan.com/files/members/6619/111_20210621-1358.png
用xfel spinor这个命令输出的信息如下https://whycan.com/files/members/6619/捕获_20210621-1357.png

怪不得了,有两个选择

① 换用xfel代码里面支持的flash
② 修改 xfel代码兼容你的flash

离线

#10 2021-06-21 14:07:03

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

请问xfel支持的spi nor flash是什么型号的呢

离线

#11 2021-06-21 14:14:04

哇酷小二
管理员
注册时间: 2020-04-22
已发帖子: 2,813
积分: 1902

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

static const struct spinor_info_t spinor_infos[] = {
	{ "w25x40", 0xef3013, 512 * 1024, 4096, 1, 256, 3, OPCODE_READ, OPCODE_PROG, OPCODE_WREN, OPCODE_E4K, 0, OPCODE_E64K, 0 },
};

https://github.com/xboot/xfel/blob/master/spinor.c

看代码, 应该目前只支持 w25x40

离线

楼主 #12 2021-06-21 14:39:02

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

目前支持所有sfdp协议 nor flash,不支持sfdp协议的,就需要自己填入flash信息,w25x40是不支持sfdp的

离线

楼主 #13 2021-06-21 14:40:48

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

你这边既然能正确获取flash容量,应该是支持sfdp协议的,但还是烧不进去,有点奇怪,但可以做个测试,重新上电后,仅写入64KB,然后再读出来,看是否一致。不应该出现这种现象的。

离线

楼主 #14 2021-06-21 14:43:23

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

你在虚拟机里跑,有没有可能是虚拟机相关问题了,可以真机或者windows烧录实验下。

离线

#15 2021-06-21 14:53:14

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

我再测试测试

离线

#16 2021-06-22 11:13:27

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

请问楼主可以分享一下D1的mksunxi工具的源码吗?

离线

#17 2021-06-22 12:04:02

tigger
会员
注册时间: 2021-06-18
已发帖子: 146
积分: 85

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

March 说:

请问楼主可以分享一下D1的mksunxi工具的源码吗?

mksunxi.c

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>

#if 0
static inline uint32_t __swab32(uint32_t x)
{
	return ( (x<<24) | (x>>24) | \
		((x & (uint32_t)0x0000ff00UL)<<8) | \
		((x & (uint32_t)0x00ff0000UL)>>8) );
}
#define cpu_to_le32(x)	(__swab32((uint32_t)(x)))
#define le32_to_cpu(x)	(__swab32((uint32_t)(x)))
#else
#define cpu_to_le32(x)	(x)
#define le32_to_cpu(x)	(x)
#endif

struct boot_head_t {
	uint32_t instruction;
	uint8_t magic[8];
	uint32_t checksum;
	uint32_t length;
	uint8_t spl_signature[4];
	uint32_t fel_script_address;
	uint32_t fel_uenv_length;
	uint32_t dt_name_offset;
	uint32_t reserved1;
	uint32_t boot_media;
	uint32_t string_pool[13];
};

int main (int argc, char *argv[])
{
	struct boot_head_t * h;
	FILE * fp;
	char * buffer;
	int buflen, filelen;
	uint32_t * p;
	uint32_t sum;
	int i, l, loop;
	
	if(argc != 2)
	{
		printf("Usage: mksunxi <bootloader>\n");
		return -1;
	}

	fp = fopen(argv[1], "r+b");
	if(fp == NULL)
	{
		printf("Open bootloader error\n");
		return -1;
	}
	fseek(fp, 0L, SEEK_END);
	filelen = ftell(fp);
	fseek(fp, 0L, SEEK_SET);
	
	if(filelen <= sizeof(struct boot_head_t))
	{
		fclose(fp);
		printf("The size of bootloader too small\n");
		return -1;
	}

	buflen = (filelen + 0x2000) & ~(0x2000 - 1);
	buffer = malloc(buflen);
	memset(buffer, 0, buflen);
	if(fread(buffer, 1, filelen, fp) != filelen)
	{
		printf("Can't read bootloader\n");
		free(buffer);
		fclose(fp);
		return -1;
	}

	h = (struct boot_head_t *)buffer;
	p = (uint32_t *)h;
	l = le32_to_cpu(h->length);
	h->checksum = cpu_to_le32(0x5F0A6C39);
	loop = l >> 2;
	for(i = 0, sum = 0; i < loop; i++)
		sum += le32_to_cpu(p[i]);
	h->checksum = cpu_to_le32(sum);
	
	fseek(fp, 0L, SEEK_SET);
	if(fwrite(buffer, 1, buflen, fp) != buflen)
	{
		printf("Write bootloader error\n");
		free(buffer);
		fclose(fp);
		return -1;
	}

	fclose(fp);
	printf("The bootloader head has been fixed\n");
	return 0;
}

离线

#18 2021-06-26 20:43:09

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

请问楼主,关于中断向量表这部分的汇编代码,有点不太懂,主要是vectors:csrw mscratch, sp    addi sp, sp, -(37 * REGSZ)     SREG x1, 1 * REGSZ(x2)...这部分。

离线

#19 2021-06-27 10:12:13

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

楼主,还有这个问题: https://whycan.com/t_6706.html ,有时候DDR信息能输出完整,有时候输出又不完整,很奇怪。

离线

楼主 #20 2021-06-27 10:45:14

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

March 说:

请问楼主,关于中断向量表这部分的汇编代码,有点不太懂,主要是vectors:csrw mscratch, sp    addi sp, sp, -(37 * REGSZ)     SREG x1, 1 * REGSZ(x2)...这部分。

就是中断现场保护,没什么特别的。

离线

楼主 #21 2021-06-27 10:51:03

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

March 说:

楼主,还有这个问题: https://whycan.com/t_6706.html ,有时候DDR信息能输出完整,有时候输出又不完整,很奇怪。

这个估计你哪里异常了,DDR不要初始化两次,还有要注意cache类问题,需要你自己仔细对比自己的操作。

离线

#22 2021-06-28 10:49:27

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

xboot 说:
March 说:

请问楼主,关于中断向量表这部分的汇编代码,有点不太懂,主要是vectors:csrw mscratch, sp    addi sp, sp, -(37 * REGSZ)     SREG x1, 1 * REGSZ(x2)...这部分。

就是中断现场保护,没什么特别的。

好的,谢谢楼主,请问可以提供一份关于中断的裸机程序吗(如GPIO中断),中断这部分不知道该怎么处理。谢谢。

离线

楼主 #23 2021-06-28 11:01:10

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

看xboot代码里面都有的

离线

#24 2021-06-29 22:59:27

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

参考xboot的代码,加了GPIO中断的相关代码,但是触发不了中断,不知道是哪里出了问题,求帮助。d1-baremetal.rar

离线

#25 2021-06-30 09:08:38

liao0418
会员
注册时间: 2021-06-25
已发帖子: 0
积分: 0

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

该评论内容与本帖子无关,鼓励各位坑友积极发言讨论与帖子有关的内容!

离线

  • 不通过:与技术无关

楼主 #26 2021-06-30 15:01:15

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

你这是在搞笑吗?中断控制器都没有初始化,还想触发中断

离线

#27 2021-06-30 15:16:15

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

中断控制器是PLIC吧,我初始化了啊,_20210630-1515.png 望指点

离线

楼主 #28 2021-06-30 15:25:18

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

先尝试用定时器做中断源吧,至少这个xboot是验证通过的,而且gpio中断,属于子中断,需要先开启父中断的

最近编辑记录 xboot (2021-06-30 15:26:17)

离线

#29 2021-07-02 11:27:47

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

xboot 说:

先尝试用定时器做中断源吧,至少这个xboot是验证通过的,而且gpio中断,属于子中断,需要先开启父中断的

定时器确实可以产生中断,我写的gpio中断的流程如下:_20210702-1121.png
timer的处理是类似的,您看我的gpio中断流程哪里有问题啊,不知道您说的父中断指的什么呢?

离线

楼主 #30 2021-07-02 12:53:38

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

父中段就是一个中断被多个子中段共享,gpio一般是一组对应一个父中断

离线

#31 2021-07-02 14:24:19

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

在数据手册上没有找到开启gpio父中断的相关寄存器啊

离线

#32 2021-07-02 16:16:34

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

xboot 说:

父中段就是一个中断被多个子中段共享,gpio一般是一组对应一个父中断

根据您的意思,6T$Q)F7I[)`279S`)4WCJ6S.png,这个寄存器应该控制着是gpio的子中断_20210702-1614.png,那PLIC_MIE_ REGn是控制着gpio的父中断吗?

离线

楼主 #33 2021-07-02 16:43:19

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

这是中断编号,手册里有的

#define D1_IRQ_GPIOB_NS			(85)
#define D1_IRQ_GPIOC_NS			(87)
#define D1_IRQ_GPIOD_NS			(89)
#define D1_IRQ_GPIOE_NS			(91)
#define D1_IRQ_GPIOF_NS			(93)
#define D1_IRQ_GPIOG_NS			(95)

离线

#34 2021-07-06 10:11:23

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

在D1裸机程序中的sys_spinor_init函数中:
_20210706095934.png
在用户手册上并未找到SPI_CCR寄存器的相关说明啊,望指点。

离线

#35 2021-07-06 10:20:42

哇酷小二
管理员
注册时间: 2020-04-22
已发帖子: 2,813
积分: 1902

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

March 说:

在D1裸机程序中的sys_spinor_init函数中:
https://whycan.com/files/members/6619/微信图片_20210706095934.png
在用户手册上并未找到SPI_CCR寄存器的相关说明啊,望指点。

本站精华帖汇总, 各种手册在线下载,各种开源pcb工程下载
https://whycan.com/t_3019.html#p25005


d1手册确实没有 spi ccr,你找下arm系列手册,偏移应该是0x24。

离线

#36 2021-07-11 19:30:59

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

关于D1裸机的系统软件复位,在用户手册有如下寄存器描述:
_20210711-1556.png
WDOG_SOFT_RST_REG[31:16]:要想改变WDOG_SOFT_RST_REG[0]的值,需将WDOG_SOFT_RST_REG[31:16]设置为0x16AA,
WDOG_SOFT_RST_REG[0]:写1清零,那我怎么才能将WDOG_SOFT_RST_REG[0]变为1使得复位整个系统呢?
是直接将将WDOG_SOFT_RST_REG[31:16]设置为0x16AA就能使得WDOG_SOFT_RST_REG[0]变为1吗?

离线

#37 2021-07-11 19:34:06

March
会员
注册时间: 2021-05-28
已发帖子: 59
积分: 26

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

找到问题在哪了,因为该寄存器的有些位是只写的,所以要一次性赋值,如下:
111_20210711-1933.png

离线

#38 2021-11-30 17:22:42

ccl
会员
注册时间: 2020-09-16
已发帖子: 10
积分: 5

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

[ERROR DEBUG] auto scan dram rank&width fail !
DRAM only have internal ZQ!!
get_pmu_exist() = 4294967295
ddr_efuse_type: 0xa
ZQ calibration error,check external 240 ohm resistor.
[ERROR DEBUG] auto scan dram rank&width fail !

烧写进F133-A SPI-NOR DDR初始化失败!

最近编辑记录 ccl (2021-11-30 17:23:27)

离线

#39 2021-12-08 11:52:13

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

请问我用xfel工具直接在DDR中运行d1-baremetal.bin,可以正常运行,但是烧录到d1自带spinand的0地址后,重启只有ddr初始化成功的打印,没有main的count循环打印,这个正常吗?我测过从spinand读出来24k确认已经烧录成功了。

离线

#40 2021-12-08 11:59:50

cube
会员
注册时间: 2021-03-11
已发帖子: 190
积分: 114.5

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

woolen 说:

请问我用xfel工具直接在DDR中运行d1-baremetal.bin,可以正常运行,但是烧录到d1自带spinand的0地址后,重启只有ddr初始化成功的打印,没有main的count循环打印,这个正常吗?我测过从spinand读出来24k确认已经烧录成功了。

估计是这个bin没有magic和crc,
可能brom不识别吧?

离线

#41 2021-12-08 12:35:12

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

@cube
从代码里面直接编译出来的bin,有执行mksunxi的,而且ddr初始化的部分有打印的,应该是已经被加载到了sram然后执行了一部分?

离线

#42 2021-12-08 13:04:35

cube
会员
注册时间: 2021-03-11
已发帖子: 190
积分: 114.5

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

woolen 说:

@cube
从代码里面直接编译出来的bin,有执行mksunxi的,而且ddr初始化的部分有打印的,应该是已经被加载到了sram然后执行了一部分?

日志贴出来看看

离线

#43 2021-12-08 13:55:42

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

cube 说:

日志贴出来看看

编译和烧录:

woolen@ubuntu:/disk4/allwinner_d1/d1-baremetal$ make CROSS=riscv64-unknown-elf-
[AS] source/start.S
[AS] source/memcpy.S
[AS] source/memset.S
[CC] source/sys-clock.c
[CC] source/sys-dram.c
[CC] source/sys-uart.c
[CC] source/sys-spinor.c
[CC] source/main.c
[CC] source/sys-jtag.c
[CC] source/sys-copyself.c
[LD] Linking output/d1-baremetal.elf
[OC] Objcopying output/d1-baremetal.bin
copy from `output/d1-baremetal.elf' [elf64-littleriscv] to `output/d1-baremetal.bin' [binary]
Make header information for brom booting
The bootloader head has been fixed, spl size is 24576 bytes.

woolen@ubuntu:/disk4/allwinner_d1/d1-baremetal$ xfel version
AWUSBFEX soc=0x00185900(D1/F133) 0x00000001 ver=0x0001 0x44 0x08 scratchpad=0x00045000
woolen@ubuntu:/disk4/allwinner_d1/d1-baremetal$ xfel spinand write 0x0 output/d1-baremetal.bin
100% [================================================] 24.000 KB, 246.427 KB/s

重新上电后串口打印,只有ddr的部分。

DRAM only have internal ZQ!!
get_pmu_exist() = 4294967295
ddr_efuse_type: 0x0
[AUTO DEBUG] two rank and full DQ!
ddr_efuse_type: 0x0
[AUTO DEBUG] rank 0 row = 15
[AUTO DEBUG] rank 0 bank = 8
[AUTO DEBUG] rank 0 page size = 2 KB
[AUTO DEBUG] rank 1 row = 15
[AUTO DEBUG] rank 1 bank = 8
[AUTO DEBUG] rank 1 page size = 2 KB
rank1 config same as rank0
DRAM BOOT DRIVE INFO: %s
DRAM CLK = 792 MHz
DRAM Type = 3 (2:DDR2,3:DDR3)
DRAMC ZQ value: 0x7b7bfb
DRAM ODT value: 0x42.
ddr_efuse_type: 0x0
DRAM SIZE =1024 M
DRAM simple test OK.

离线

楼主 #44 2021-12-08 14:48:56

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

@woolen
这个测试demo仅支持spi nor flash引导,如果要支持spi nand引导,需要做两个工作,一个是实现spi nand自拷贝,另一个是,一个page只能使用前2k,后面的需要空着。

spi nand flash 引导是有点特殊的。但只要满足这两个要求,就可以实现spi nand 自举了。

离线

#45 2021-12-08 14:52:19

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

知道了,nand拷贝到mem的部分还没写,我自己改一下...

	if(d == BOOT_DEVICE_SPINOR)
	{
		mem = (void *)__image_start;
		size = __image_end - __image_start;

		sys_spinor_init();
		sys_spinor_read(0, mem, size);
		sys_spinor_exit();
	}
	else if(d == BOOT_DEVICE_SPINAND)
	{
	}

离线

#46 2021-12-08 15:16:49

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

xboot 说:

@woolen
这个测试demo仅支持spi nor flash引导,如果要支持spi nand引导,需要做两个工作,一个是实现spi nand自拷贝,另一个是,一个page只能使用前2k,后面的需要空着。

spi nand flash 引导是有点特殊的。但只要满足这两个要求,就可以实现spi nand 自举了。

谢谢回复。
“一个page只能使用前2k,后面的需要空着” 这个我不太理解,能详细说一下吗?

离线

楼主 #47 2021-12-08 16:59:27

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

看这个帖子吧。
https://whycan.com/t_5527.html

离线

#48 2021-12-08 20:17:09

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

xboot 说:

看这个帖子吧。
https://whycan.com/t_5527.html

我看了之后还有点疑问,现在的裸机程序是24k,我用xfel烧到spinand,xfel会写1k跳1k吗?如果不会的话,既然代码已经起来了,是不是说明d1的brom可以连续读取nand flash了?

最近编辑记录 woolen (2021-12-08 20:17:31)

离线

楼主 #49 2021-12-09 10:24:08

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

spl的大小不一定就是24k,大小由链接脚本中自动计算的__spl_size来决定,但mksunxi工具会将spl按8k的整数倍来填充,这是为了兼容各种引导介质。
xfel现在是没有做任何写1k跳1k的,后面会增加一个命令行参数来做这件事。

同样跟你有一样的疑惑,现在没有按1k跳为何能有ddr打印信息,checksum肯定是不正确的,理论上应该是禁止运行的才对。除非,对于nand 引导,checksum根本就不起作用,要确认这个问题,就需要去逆向brom了。

假设checksum不起作用,或者歪打正着,碰对了,那么后面的现象就是可解释的。
同样关注这个问题,争取有个明确的结论。

这里提供一个之前做的工作,用于判断启动的引导介质,已验证。

enum {
	BOOT_DEVICE_SPINOR,
	BOOT_DEVICE_SPINAND,
	BOOT_DEVICE_SDCARD,
};

static int get_boot_device(void)
{
	uint8_t s = *((volatile uint8_t *)(0x00020000 + 0x28));

	if(s == 0x3)
		return BOOT_DEVICE_SPINOR;
	else if(s == 0x4)
		return BOOT_DEVICE_SPINAND;
	else if(s == 0x0)
		return BOOT_DEVICE_SDCARD;
	return BOOT_DEVICE_SPINOR;
}

离线

#50 2021-12-09 12:04:54

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

@xboot
我的板子只有spinand,加上了get_boot_device,处理一下返回值输出到串口,也确认是BOOT_DEVICE_SPINAND。flash型号是出厂的那个MX35LF2GE4AD,看了下page是2k。

然后做了点实验,对d1-baremetal.bin做了修改:crc替换一个字节、magic替换一个字节、bin末尾替换一个字节,这样分别生成了3个bin并用xfel烧录到spinand的0地址,发现启动都没有被brom加载。不过brom加载了64k偏移位置的另一个spl,怀疑是之前我用PhoneixSuit烧录的固件在nand的64k位置备份了一个spl,把这段再换掉就起不来了。(之前很疑惑起的spl打印不是我编的,在另外帖子看到下面的话然后去dump了一下flash内容发现64k位置还有一个spl)

Some SoCs can also boot from SPI NAND flash. Here the BROM tries to read a valid first stage bootloader starting from page number 0, 32, 64, 96, 128, 160, 192 and 224. It only reads the first 1024 bytes from every page.

所以我得出的结论是brom对spinand的magic和crc都是有校验的,并且看起来不是每个页只读1K,这个跟上面这段话有点矛盾~

离线

#51 2021-12-09 12:09:48

caoke
会员
注册时间: 2019-12-24
已发帖子: 6
积分: 1

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

感谢大佬解惑。

离线

#52 2021-12-09 13:24:59

吴助建
会员
注册时间: 2021-12-08
已发帖子: 12
积分: 5

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

该评论内容与本帖子无关,鼓励各位坑友积极发言讨论与帖子有关的内容!

离线

  • 不通过:其他

楼主 #53 2021-12-09 13:46:42

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

@woolen
那很有可能brom spi nand flash 引导时的地址不是0,而是64KB,还有一个可能的地方,就是每个page使用的是2k,而不是1k。

两个方向查找原因:
1,spi nand flash引导地址
2,每page采用2k还是1k,checksum运算应该是必须的。

离线

楼主 #54 2021-12-09 13:53:00

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

猜测,brom里面自动搜索spi nand flash 有效spl,这个是合理的,而且也很有可能就是这样,但很有可能,D1 的brom是每个page读取2k,这样对于2k page的spi nand flash就无需留空了。

离线

#55 2021-12-09 15:23:09

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

xboot 说:

猜测,brom里面自动搜索spi nand flash 有效spl,这个是合理的,而且也很有可能就是这样,但很有可能,D1 的brom是每个page读取2k,这样对于2k page的spi nand flash就无需留空了。

我重新用PhoenixSuit烧录了一个tina的固件(spl是64k),从spinand读一下内容发现spl在每个block上(0x0、0x20000、0x40000、0x60000...)都有一份,应该是为了防止坏块做的多备份,brom会从前往后找到可用的spl来加载。(不知道为什么我之前的spl备份是在0x10000上而且后面没有,暂时先不纠结了)

把d1-baremetal.bin再烧录spinand的0x0位置上,启动的就是d1-baremetal.bin。D1的brom每个page读取2k这个我感觉很有可能。

离线

楼主 #56 2021-12-09 16:06:27

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

那就写一个sys-spinand.c,测试下,是否能完成引导,既然是多个引导地址,那就从0开始写了。

关于spinand自拷贝,可以参考xfel里面的代码,当然,全志的boot0也可以参考。

离线

楼主 #57 2021-12-09 20:39:44

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

已实现spinand引导,确认每个page使用2k,自拷贝函数实现。

/*
 * sys-spinand.c
 *
 * Copyright(c) 2007-2021 Jianjun Jiang <8192542@qq.com>
 * Official site: http://xboot.org
 * Mobile phone: +86-18665388956
 * QQ: 8192542
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <xboot.h>

/*
 * Default spi nand page size: 2048(11), 4096(12)
 */
#define SPINAND_PAGE_BITS	(11)
#define SPINAND_PAGE_MASK	((1 << SPINAND_PAGE_BITS) - 1)
#define SPINAND_PAGE_SIZE	(1 << SPINAND_PAGE_BITS)

enum {
	SPI_GCR	= 0x04,
	SPI_TCR	= 0x08,
	SPI_IER	= 0x10,
	SPI_ISR	= 0x14,
	SPI_FCR	= 0x18,
	SPI_FSR	= 0x1c,
	SPI_WCR	= 0x20,
	SPI_CCR	= 0x24,
	SPI_MBC	= 0x30,
	SPI_MTC	= 0x34,
	SPI_BCC	= 0x38,
	SPI_TXD	= 0x200,
	SPI_RXD	= 0x300,
};

void sys_spinand_init(void)
{
	virtual_addr_t addr;
	u32_t val;

	/* Config GPIOC2, GPIOC3, GPIOC4 and GPIOC5 */
	addr = 0x02000060 + 0x00;
	val = read32(addr);
	val &= ~(0xf << ((2 & 0x7) << 2));
	val |= ((0x2 & 0xf) << ((2 & 0x7) << 2));
	write32(addr, val);

	val = read32(addr);
	val &= ~(0xf << ((3 & 0x7) << 2));
	val |= ((0x2 & 0xf) << ((3 & 0x7) << 2));
	write32(addr, val);

	val = read32(addr);
	val &= ~(0xf << ((4 & 0x7) << 2));
	val |= ((0x2 & 0xf) << ((4 & 0x7) << 2));
	write32(addr, val);

	val = read32(addr);
	val &= ~(0xf << ((5 & 0x7) << 2));
	val |= ((0x2 & 0xf) << ((5 & 0x7) << 2));
	write32(addr, val);

	/* Deassert spi0 reset */
	addr = 0x0200196c;
	val = read32(addr);
	val |= (1 << 16);
	write32(addr, val);

	/* Open the spi0 gate */
	addr = 0x02001940;
	val = read32(addr);
	val |= (1 << 31);
	write32(addr, val);

	/* Open the spi0 bus gate */
	addr = 0x0200196c;
	val = read32(addr);
	val |= (1 << 0);
	write32(addr, val);

	/* Select pll-periph0 for spi0 clk */
	addr = 0x02001940;
	val = read32(addr);
	val &= ~(0x3 << 24);
	val |= 0x1 << 24;
	write32(addr, val);

	/* Set clock pre divide ratio, divided by 1 */
	addr = 0x02001940;
	val = read32(addr);
	val &= ~(0x3 << 8);
	val |= 0x0 << 8;
	write32(addr, val);

	/* Set clock divide ratio, divided by 6 */
	addr = 0x02001940;
	val = read32(addr);
	val &= ~(0xf << 0);
	val |= (6 - 1) << 0;
	write32(addr, val);

	/* Set spi clock rate control register, divided by 2 */
	addr = 0x04025000;
	write32(addr + SPI_CCR, 0x1000);

	/* Enable spi0 and do a soft reset */
	addr = 0x04025000;
	val = read32(addr + SPI_GCR);
	val |= (1 << 31) | (1 << 7) | (1 << 1) | (1 << 0);
	write32(addr + SPI_GCR, val);
	while(read32(addr + SPI_GCR) & (1 << 31));

	val = read32(addr + SPI_TCR);
	val &= ~(0x3 << 0);
	val |= (1 << 6) | (1 << 2);
	write32(addr + SPI_TCR, val);

	val = read32(addr + SPI_FCR);
	val |= (1 << 31) | (1 << 15);
	write32(addr + SPI_FCR, val);
}

void sys_spinand_exit(void)
{
	virtual_addr_t addr = 0x04025000;
	u32_t val;

	/* Disable the spi0 controller */
	val = read32(addr + SPI_GCR);
	val &= ~((1 << 1) | (1 << 0));
	write32(addr + SPI_GCR, val);
}

static void sys_spi_select(void)
{
	virtual_addr_t addr = 0x04025000;
	u32_t val;

	val = read32(addr + SPI_TCR);
	val &= ~((0x3 << 4) | (0x1 << 7));
	val |= ((0 & 0x3) << 4) | (0x0 << 7);
	write32(addr + SPI_TCR, val);
}

static void sys_spi_deselect(void)
{
	virtual_addr_t addr = 0x04025000;
	u32_t val;

	val = read32(addr + SPI_TCR);
	val &= ~((0x3 << 4) | (0x1 << 7));
	val |= ((0 & 0x3) << 4) | (0x1 << 7);
	write32(addr + SPI_TCR, val);
}

static void sys_spi_write_txbuf(u8_t * buf, int len)
{
	virtual_addr_t addr = 0x04025000;
	int i;

	write32(addr + SPI_MTC, len & 0xffffff);
	write32(addr + SPI_BCC, len & 0xffffff);
	if(buf)
	{
		for(i = 0; i < len; i++)
			write8(addr + SPI_TXD, *buf++);
	}
	else
	{
		for(i = 0; i < len; i++)
			write8(addr + SPI_TXD, 0xff);
	}
}

static int sys_spi_transfer(void * txbuf, void * rxbuf, int len)
{
	virtual_addr_t addr = 0x04025000;
	int count = len;
	u8_t * tx = txbuf;
	u8_t * rx = rxbuf;
	u8_t val;
	int n, i;

	while(count > 0)
	{
		n = (count <= 64) ? count : 64;
		write32(addr + SPI_MBC, n);
		sys_spi_write_txbuf(tx, n);
		write32(addr + SPI_TCR, read32(addr + SPI_TCR) | (1 << 31));

		while((read32(addr + SPI_FSR) & 0xff) < n);
		for(i = 0; i < n; i++)
		{
			val = read8(addr + SPI_RXD);
			if(rx)
				*rx++ = val;
		}

		if(tx)
			tx += n;
		count -= n;
	}
	return len;
}

static int sys_spi_write_then_read(void * txbuf, int txlen, void * rxbuf, int rxlen)
{
	if(sys_spi_transfer(txbuf, NULL, txlen) != txlen)
		return -1;
	if(sys_spi_transfer(NULL, rxbuf, rxlen) != rxlen)
		return -1;
	return 0;
}

static void sys_spinand_wait(void)
{
	u8_t tx[2];
	u8_t rx[1];

	tx[0] = 0x0f;
	tx[1] = 0xc0;
	do {
		sys_spi_select();
		sys_spi_write_then_read(tx, 2, rx, 1);
		sys_spi_deselect();
	} while((rx[0] & 0x1) == 0x1);
}

void sys_spinand_read(int addr, void * buf, int count)
{
	u8_t tx[4];
	u32_t pa, ca;
	int n;

	while(count > 0)
	{
		pa = addr >> SPINAND_PAGE_BITS;
		ca = addr & SPINAND_PAGE_MASK;
		n = count > (SPINAND_PAGE_SIZE - ca) ? (SPINAND_PAGE_SIZE - ca) : count;
		tx[0] = 0x13;
		tx[1] = (u8_t)(pa >> 16);
		tx[2] = (u8_t)(pa >> 8);
		tx[3] = (u8_t)(pa >> 0);
		sys_spi_select();
		sys_spi_write_then_read(tx, 4, 0, 0);
		sys_spi_deselect();
		sys_spinand_wait();
		tx[0] = 0x03;
		tx[1] = (u8_t)(ca >> 8);
		tx[2] = (u8_t)(ca >> 0);
		tx[3] = 0x0;
		sys_spi_select();
		sys_spi_write_then_read(tx, 4, buf, n);
		sys_spi_deselect();
		sys_spinand_wait();
		addr += n;
		buf += n;
		count -= n;
	}
}

其中,因spl代码需要实现成位置无关,就不支持芯片型号检测了,一般的spi nand flash page 为2k,4k,这些通过宏定义来设置了,不动态识别。

/*
 * Default spi nand page size: 2048(11), 4096(12)
 */
#define SPINAND_PAGE_BITS	(11)
#define SPINAND_PAGE_MASK	((1 << SPINAND_PAGE_BITS) - 1)
#define SPINAND_PAGE_SIZE	(1 << SPINAND_PAGE_BITS)

这个自拷贝函数,为连续拷贝,不做任何间隔拷贝,间隔拷贝函数仅BROM中的才是如此,xboot中,spl代码实现成位置无关的,且为一个独立的镜像。其镜像最前面就是spl代码。

所以烧录时,将xboot的前64k,烧录到0地址,这个烧录过程需要做间隔处理,再将完整xboot烧录到256k的位置,这个位置无需做任何间隔处理,由上面的函数来实现自拷贝。

2k page大小的flash时,spl代码烧写无需特殊处理。

离线

楼主 #58 2021-12-09 23:27:41

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

离线

楼主 #59 2021-12-09 23:29:41

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

离线

楼主 #60 2021-12-09 23:44:37

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

结合搜索的各种资料,大概明白了,spl的整个过程,brom引导时会从block0开始依次检测合法spl代码,spl会存在多个备份,直到找到合法的为止,各个备份spl按block来对齐,如果 SPL 超过 1 个 block, 单个备份起始 block 地址为偶数。最大可以有8个备份,一个page是2kb有效,但这个现在不敢肯定,手上没有4kpage的nand来测试,估计大概率是还是2k有效。

离线

#61 2021-12-10 14:22:18

woolen
会员
注册时间: 2021-12-08
已发帖子: 11
积分: 11

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

@xboot
感谢,我今天想试一下,发现大佬已经写好了,这边d1-baremetal用spinand已经测试OK。

离线

楼主 #62 2021-12-10 18:25:31

xboot
会员
注册时间: 2019-10-15
已发帖子: 485
积分: 310

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

将spl保留区域调整为1MB,并扩展了xfel,支持烧录spl镜像到spi nand flash,可以烧录普通镜像,以及压缩镜像,并能正常引导启动。

烧写普通镜像到SPI Nand Flash

sudo xfel spinand splwrite 2048 1048576 xboot.bin

烧写压缩镜像到SPI Nand Flash

sudo xfel spinand splwrite 2048 1048576 xboot.bin.z

xfel 1.2.2版本支持的命令

xfel(v1.2.2) - https://github.com/xboot/xfel
usage:
    xfel version                                             - Show chip 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 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
    xfel spinand splwrite <valid-page-size> <address> <file> - Write file to spi nand flash with spl mode

离线

#63 2021-12-15 10:18:21

lsgandwty
会员
注册时间: 2021-12-14
已发帖子: 3
积分: 3

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

该评论内容与本帖子无关,鼓励各位坑友积极发言讨论与帖子有关的内容!

离线

  • 不通过:其他

#64 2021-12-26 21:19:53

wenunit
会员
注册时间: 2020-04-22
已发帖子: 30
积分: 5

Re: 为方便大家研究全志RISCV D1芯片,花了点时间编写了一个精简版的裸机程序,方便大家学习参考。

该评论内容与本帖子无关,鼓励各位坑友积极发言讨论与帖子有关的内容!

离线

  • 不通过:其他

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn