*从xboot抠的启动文件和编译选项,感谢XBOOT大佬贡献的代码
*裸机启动,包括串口0初始化、时钟初始化、内部DRAM初始化并启动到main().
*工程包含了v3s版的sunxi-fel工具
*由于我对ld脚本并不是很熟悉,在这上面花了不少时间找问题:)
*工程源码:(.zip上传失败,放网盘链接)链接: https://pan.baidu.com/s/18E3WTeRR0BuBnaxPEEp1EA 提取码: f3dm
======================================
#编译步骤-在linux平台完成
1、解压源码,修改Makefile中的编译器
2、进入tools/mksunxi目录执行make命令
3、在工程目录执行make编译
4、make write下载,复位运行应该能看到串口输出的信息
======================================
另外还想请教各位大佬一个问题:在sys-dram.c中声明了一个结构体变量,在声明的同时赋值,但是这样cpu就不知道跑哪去了,改成下面这样就好了
但page_size放外面赋值总觉得有点刺挠:),想问问各位大佬有啥解决办法吗。
离线
厉害!赞一个!!!
离线
作为刚注册的小白,好羡慕楼主,折腾的成果。严重支持下。
离线
晕哥掏了血本呀,这个182M,流量费不小哦。
去掉里面的GCC,加个链接好些。
最近编辑记录 staunchheart (2020-07-14 15:53:59)
离线
另外还想请教各位大佬一个问题:在sys-dram.c中声明了一个结构体变量,在声明的同时赋值,但是这样cpu就不知道跑哪去了,改成下面这样就好了
https://whycan.cn/files/members/1924/03.png
但page_size放外面赋值总觉得有点刺挠:),想问问各位大佬有啥解决办法吗。
把几个变量赋值顺序调成和结构体声明里的一样试试?
离线
这个厉害,非常佩服楼主,给力!
最近编辑记录 txl (2020-07-14 16:46:23)
离线
晕哥掏了血本呀,这个182M,流量费不小哦。
去掉里面的GCC,加个链接好些。
你这么一说我才发现里面还藏了个GCC,去掉GCC压缩只有1.6M,是我疏忽了。下次上传前再仔细检查检查。
最近编辑记录 flex-A (2020-07-14 17:25:32)
离线
期待楼主发多几份这些裸机程序,太给力,和STM32的差别大吗?
离线
期待楼主发多几份这些裸机程序,太给力,和STM32的差别大吗?
裸机的话没有stm32那样详尽的库,基本只有一份数据手册和xboot这样的参考。算是一步一个坑。
离线
楼主, 执行这个 make write 命令就下载进去了吗?需要用串口线跟开发板相接吧
离线
楼主, 执行这个 make write 命令就下载进去了吗?需要用串口线跟开发板相接吧
连接荔枝派zero到电脑,荔枝派进到FEL模式,然后make write
离线
这个编译需要使用什么环境呢
离线
厉害,帮顶
离线
感谢分享,顶起
离线
这个编译需要使用什么环境呢
系统:ubuntu,编译:arm-linux-guneabihf-或arm-none-eabi,下载:sunxi-fel
工程里自带v3s版的sunxi-fel工具。有一个arm-gcc,这个属失误,可以把arm-gcc删了,减小体积。
最近编辑记录 flex-A (2020-07-29 20:45:51)
离线
离线
个人觉得程序跑飞 应该是字节对齐问题 你看下你结构体设置没
离线
离线
个人觉得程序跑飞 应该是字节对齐问题 你看下你结构体设置没
不是对齐问题,这种sys-开头的文件,是需要用特别的编程手段的,因为这些程序的链接地址都是在DDR中,而实际运行地址是在SRAM中,需要实现成地址无关的程序,而系统刚启动,什么环境都不具备,C执行环境,更是不完整的,所以只能用特别编程手段。
一般有一下注意点:
1,不要使用已初始化数据段
2,不要使用未初始化数据段
3,不要使用switch case语句,可以用if elseif 代替
4,不要使用全局变量,仅使用局部变量
5,局部变量的初始化,用代码实现,会编译成立即数赋值
6,只能使用栈空间,其他什么都不可以使用
7,不要调用任何外部库,比如工具链里的C库等。
只要按这种要求,编程,编译出来的代码,都是地址无关的,SPL代码是很特殊的,谨记运行地址不是链接地址,就明白为何需要这样处理了。
当然,这种限制,也导致编程要求较高,如果不想挑战自己,就链接两次,做两个程序吧,BL1->BL2,这种,你看某些芯片的引导链,那么长,就是因为这种原因。
独立的一个程序,支持引导,自举,换到DDR空间,要求是很高的。这种编程技巧,算挑战性编程。
最近编辑记录 xboot (2021-06-30 10:04:27)
离线
v3s的裸机是不是只能在DDR里面跑呀,应该不能在SPI_FLASH中跑吧,毕竟解析速度不够?
离线
v3s的裸机是不是只能在DDR里面跑呀,应该不能在SPI_FLASH中跑吧,毕竟解析速度不够?
程序是被搬到DDR里再运行的,V3S没法像STM32那样直接在FLASH里运行
离线
这个是flash的问题啊,NOR flash还是可以执行程序的
离线
这还是需要一个spi flash 来储存东西啊,能不能使用sdcard裸机呢。。。就是说应该要先加载个读mmc的驱动,再将sdcard内的东西搬到sram中运行?
离线
我来填坑啦,填一个三年前的坑嘿嘿。
#问题:在SPL代码的sys-dram.c里,在函数内声明了一个结构体变量,声明的同时赋值会导致SPL代码跑飞,先声明再挨个赋值,SPL就正常执行。
#原因:
1、大家都知道SPL的执行情况很特殊,它在SOC刚复位时被执行,此时DDR尚未初始化,能够使用的仅仅是有限的SRAM空间。所以SPL代码尽量要做到位置无关,汇编代码中对变量的寻址最好是相对寻址或者固化在代码中,如果出现绝对寻址可能会导致代码跳转到尚未初始化的DDR空间。
2、编译器在编译代码时往往会把代码内的元素分段处理,比如大家喜闻乐见的.text .data .bss段。当使用不同的方式赋值一个结构体变量时,它被分到的段会不同,一般情况下这种差异不会有影响,但是在SPL代码这种特殊的条件下,一个变量的存储位置不同就会导致SPL代码执行异常。
3、SPL往往不含.data .rodata段,所有初始化值都以立即数的形式存在.text段中,当一个变量被分到.data段时,SPL去寻找它来初始化外设就会导致程序异常。
#实验:
在一个函数中声明一个结构体变量,声明的同时赋值,这个结构体变量会被分配到.rodata段。
编译命令:
arm-none-eabi-gcc -s code.c -fdata-sections -ffunction-sections
void layout_test()
{
struct dram_para_t para = {
.read_delays = 0x00007979,
.write_delays = 0x6aaa0000,
.dual_rank = 0,
.bus_width = 32,
.row_bits = 15,
.bank_bits = 3,
.page_size = 4096,
};
}
*para这个结构体变量被分配到了.rodata段,并且代码中使用绝对地址来寻址,就是ldr r3, .L2这一句。
.cpu arm7tdmi
.arch armv4t
.fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 6
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "main.c"
.text
.section .rodata
.align 2
.LC0:
.word 31097
.word 1789526016
.short 4096
.byte 32
.byte 0
.byte 15
.byte 3
.space 2
.section .text.layout_test,"ax",%progbits
.align 2
.global layout_test
.syntax unified
.arm
.type layout_test, %function
layout_test:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #20
ldr r3, .L2
sub ip, fp, #20
ldm r3, {r0, r1, r2, r3}
stm ip, {r0, r1, r2, r3}
nop
add sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.L3:
.align 2
.L2:
.word .LC0
.size layout_test, .-layout_test
.ident "GCC: (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)"
在一个函数中声明一个结构体变量,声明后再赋值,这个结构体变量里的值就会以立即数的形式存在.text段中。
void layout_test()
{
struct dram_para_t para = {
.read_delays = 0x00007979,
.write_delays = 0x6aaa0000,
.dual_rank = 0,
.bus_width = 32,
.row_bits = 15,
.bank_bits = 3,
// .page_size = 4096,
};
//声明后赋值
para.page_size=4096;
}
.cpu arm7tdmi
.arch armv4t
.fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 6
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "main.c"
.text
.section .text.layout_test,"ax",%progbits
.align 2
.global layout_test
.syntax unified
.arm
.type layout_test, %function
layout_test:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #20
sub r3, fp, #20
mov r2, #0
str r2, [r3]
str r2, [r3, #4]
str r2, [r3, #8]
str r2, [r3, #12]
ldr r3, .L2
str r3, [fp, #-20]
ldr r3, .L2+4
str r3, [fp, #-16]
mov r3, #32
strb r3, [fp, #-10]
mov r3, #15
strb r3, [fp, #-8]
mov r3, #3
strb r3, [fp, #-7]
mov r3, #4096
strh r3, [fp, #-12] @ movhi
nop
add sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.L3:
.align 2
.L2:
.word 31097
.word 1789526016
.size layout_test, .-layout_test
.ident "GCC: (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)"
离线
懂了,在SPL代码阶段,应该是厂商的bootloader从外部搬一部分代码到内部SRAM中来执行的吧?那么有没有人说下这时搬运的代码是多大?可使用的资源是多少呢?
离线
谢谢楼主分享,最近在跑裸机v3s,给了很大帮助
离线