页次: 1
我来填坑啦,填一个三年前的坑嘿嘿。
#问题:在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)"
如题,RP2040的PIO提供了一定的灵活性,可以用来扩展接口。这里用来驱动一个ST7789的8bit并口LCD。
* 目前实现了CPU写数据。
* DMA写数据有问题,一是传的数据会少几个,二是源数据指针设置为自增会导致程序卡死。
如果有大佬熟悉RP2040的DMA,还请指点指点:D
#lcd并口原理图
#代码
pio-tft-lcd.zip
各位大佬好,小弟最近想在全志H616(quad cortex-A53)上构建裸机程序,参考uboot和经大佬指点后,实现如下:
1、H616上电后包括BROM运行在arm32模式,需要手动切换到aarch64位模式运行。
2、切换方式是32位模式下写RMR寄存器触发warm reset,warm reset后切换到64位模式,并且跳转到RVBAR寄存器所指的地址运行。
3、32位模式下提前设置RVBAR,然后写RMR触发warm reset。这些指令提前编译成字节码嵌入到64位程序中。
*切换运行模式的代码如下(抠自uboot):
这个代码在32位模式下会触发warn reset,在64位模式下会跳转到reset标志。
0x00020060是代码加上BROM头在SRAM里地址,即第一条指令的地址。
#define CONFIG_SUN50I_GEN_H6
/*
* Switch into AArch64 if needed.
* Refer to arch/arm/mach-sunxi/rmr_switch.S for the original source.
*/
tst x0, x0 // this is "b #0x84" in ARM (a litle trick here)
b reset
.space 0x7c
.word 0xe28f0058 // add r0, pc, #88
.word 0xe59f1054 // ldr r1, [pc, #84]
.word 0xe0800001 // add r0, r0, r1
.word 0xe580d000 // str sp, [r0]
.word 0xe580e004 // str lr, [r0, #4]
.word 0xe10fe000 // mrs lr, CPSR
.word 0xe580e008 // str lr, [r0, #8]
.word 0xee11ef10 // mrc 15, 0, lr, cr1, cr0, {0}
.word 0xe580e00c // str lr, [r0, #12]
.word 0xee1cef10 // mrc 15, 0, lr, cr12, cr0, {0}
.word 0xe580e010 // str lr, [r0, #16]
.word 0xe59f1024 // ldr r1, [pc, #36] ; 0x170000a0
.word 0xe59f0024 // ldr r0, [pc, #36] ; CONFIG_*_TEXT_BASE
.word 0xe5810000 // str r0, [r1]
.word 0xf57ff04f // dsb sy
.word 0xf57ff06f // isb sy
.word 0xee1c0f50 // mrc 15, 0, r0, cr12, cr0, {2} ; RMR
.word 0xe3800003 // orr r0, r0, #3
.word 0xee0c0f50 // mcr 15, 0, r0, cr12, cr0, {2} ; RMR
.word 0xf57ff06f // isb sy
.word 0xe320f003 // wfi
.word 0xeafffffd // b @wfi
#ifndef CONFIG_SUN50I_GEN_H6
.word 0x017000a0 // writeable RVBAR mapping address
#else
.word 0x09010040 // writeable RVBAR mapping address
#endif
.word 0x00020060 //30: .word 0xffffffff jump to this address when switch to aarch64 sucessfully
#endif
*点灯代码如下(已验证):
.global _start
_start:
//led
reset:
ldr x0,=0x0300B04c
ldr x1,=0x77177777
str x1,[x0]
ldr x0,=0x0300b058
ldr x1,=0x00002000
str x1,[x0]
1:
b 1b
.space 0x7c
很简单的代码,现在的问题是它下进去led点不亮。我这边没啥头绪,还请坛里大佬指点指点:D
slint:原名SixtyFPS,采用slint标记语言构建界面,开发语言绑定了C++、Rust、JavaScript。
提供的开发工具:
*一个.slint语言的编译器。
*vscode插件,提供语法检查和实时预览。
*一个在线编辑器,无需安装任何东西(源代码)即可试用 .slint 语法。
*.slint脚本实时预览的工具。
*一个实验性的Figma 导入器。
开发流程如下图:
关于开发者:
Olivier 和 Simon 在 KDE 项目中开始了他们的开源之旅,KDE 项目是流行的 Linux 开源桌面环境。后来,他们在挪威一家名为 Trolltech 的小公司一起工作时认识了 Qt C++ 工具包。在这里,他们在 API 设计、跨平台软件开发和用户界面组件方面获得了宝贵的经验。Simon 继续在 Qt 公司担任 QtQml 引擎的主要开发人员和维护人员,而 Olivier 则共同创立了软件咨询公司Woboq 。多年后,他们现在位于柏林,开始了一个新项目。借助 Slint,他们的目标是让每个人都可以开发用户界面:从 JavaScript、C++ 或 Rust 开发人员一直到 UI/UX 设计师。
界面展示:
打印机:查看在线交互演示
----------------------------------------------------------------
Dear ImGui:一个立即式GUI,GUI本身不维护控件的状态,由开发者来维护。
“给某人一个状态,他们有一天会遇到错误,但教他们如何在两个必须保持同步的不同位置表示状态,他们将一生都有错误。” -ryg
此库可在免费和许可的许可下使用,但需要财务支持以维持其持续改进。除了维护和稳定性之外,还有许多理想的功能尚未添加。如果您的公司正在使用 Dear ImGui,请考虑联系.)
GUI本身只有cpp文件,支持多个渲染后端:
官方维护的后端/绑定(在存储库中):
渲染器:DirectX9、DirectX10、DirectX11、DirectX12、Metal、OpenGL/ES/ES2、SDL_Renderer、Vulkan、WebGPU。
平台:GLFW、SDL2、Win32、Glut、OSX、Android。
框架:Allegro5、Emscripten。
界面展示:
有扩展组件,Implot是一个绘图用的组件:
如题,stm32使用的stm32f411,DAC使用的wm8978,带一个tpa6138a2耳放。
*带一个LCD,用来显示花里胡哨的频谱。
*Kicad绘制的4层板,白嫖嘉立创
*文件:stm32f411USBAudio_v2.zip
*PCB预览
*演示
*输出部分耳放按数据手册接成了一个多重反馈低通滤波器
如题,可以使用openOCD直接下载程序到stm32h750外接的flash中
--------------------------------------------------
原理:
openOCD原生有针对QSPI的驱动程序stmqspi,能直接操作QSPI,但需要用户先初始化QSPI和flash
-------------------------------------------------
* stm32h750的核心板,外接一片W25Q64
* 内部128KB负责初始化QSPI和W25Q64,只需要能实现正常读写就成,暂时不需要内存映射
* 操作步骤
1、编写QSPI和W25Q64的初始化程序,下载到stm32h750内部128K flash中。
2、修改stm32h7x.cfg文件,只需要在开头source包含语句后添加“set QUADSPI 1”这一句就行
3、启动openocd、tenlet连接它,halt后执行flash list就能看到外部flash驱动已经挂载了
4、执行flash info 1就能看到openocd自动识别出w25q64的型号和容量
5、执行flash write_image erase led.bin 0x90000000将led.bin直接下载到w25q64
*裸机实现framebuffer点亮RGB屏,我这边测试用的是480*272的屏
*感谢xboot贡献的代码
*未开启cache和DMA
*ubuntu平台,下载到flash运行
*编译:make clean && make
下载:make write
*imx6ull裸机开发模板,ubuntu平台,使用NXP官方SDK构建
*通过USB下载到DDR运行,不用频繁烧录SD卡
*该模板仅初始化了UART1,使用arm-gcc库中自带的printf打印信息
*.bin->.imx:Tool目录下的imxmake工具,提供源码
*PC端下载工具:uuu,源码见NXP官方github
*如果修改了.ld文件中的链接地址,务必的修改imxmake.c文件中的ADDR_ENTRY,否则会导致程序加载到错误的地址,无法运行或出玄学:)
*关于设置USB启动,可通过开发板上的跳线设置,或者SD卡启动方式下拔出SD卡,SD卡启动失败会切换到USB启动模式
小弟在.ld文件中使用ENTY命令指定起始地址为Reset_Handler,但是链接出的.elf文件对应地址上的函数却不是Reset_Handler。
各文件详情:
-->.ld文件,文件中指定了ENTRY(Reset_Handler),并且.text段的起始地址设定为0x80002000
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0400;
ISTACK_SIZE = DEFINED(__irq_stack_size__) ? __irq_stack_size__ : 0x0400;
CSTACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
RSTACK_SIZE = DEFINED(__resume_stack_size__) ? __resume_stack_size__ : 0x0400;
/* Specify the memory areas */
*/
MEMORY
{
m_ocram (RWX) : ORIGIN = 0x00900000, LENGTH = 0x00020000
m_interrupts (RX) : ORIGIN = 0x803FFFC0, LENGTH = 0x00000040
m_text (RX) : ORIGIN = 0x80002000, LENGTH = 0x003FDFC0
m_data (RW) : ORIGIN = 0x80400000, LENGTH = 0x00400000
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into DDR RAM */
.interrupts :
{
__VECTOR_TABLE = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} > m_interrupts
/* The program code and other data goes into DDR RAM */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > m_text
--> startup.s,该文件中定义了Reset_Handler函数,并且指定它在.text段
.text
.arm
/* Reset Handler */
.arm
.align 2
.globl Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
cpsid i /* Mask interrupts */
/* Reset SCTlr Settings */
mrc p15, 0, r0, c1, c0, 0 /* Read CP15 System Control register */
bic r0, r0, #(0x1 << 12) /* Clear I bit 12 to disable I Cache */
bic r0, r0, #(0x1 << 2) /* Clear C bit 2 to disable D Cache */
bic r0, r0, #0x2 /* Clear A bit 1 to disable strict alignment */
bic r0, r0, #(0x1 << 11) /* Clear Z bit 11 to disable branch prediction */
bic r0, r0, #0x1 /* Clear M bit 0 to disable MMU */
mcr p15, 0, r0, c1, c0, 0 /* Write value back to CP15 System Control register */
-->最终反编译出的结果
Disassembly of section .text:
80002000 <__do_global_dtors_aux>:
80002000: b510 push {r4, lr}
80002002: f240 046c movw r4, #108 ; 0x6c
80002006: f2c8 0440 movt r4, #32832 ; 0x8040
8000200a: 7823 ldrb r3, [r4, #0]
发现0x80002000地址上的函数却不是Reset_Handler,有熟悉链接脚本的大佬可以指点下小弟吗。
完整工程文件:imx6_template.zip
这是一个imx6ull的裸机工程,目前是使用NXP官方SDK来设置C语言环境,进入main点灯。
小弟实现了个内存管理的库,叫memfox ,用memfox替换系统自带的malloc函数时发生了一个有意思的现象。
测试场景:
*minGW-GCC
*用memfox替换掉malloc的实现
void *malloc(size_t size)
{
if(size<1024)
printf("memfox malloc:%dB\n",size);
else
printf("memfox malloc:%dKB\n",size>>10);
return memfox_malloc(size);
}
void free(void *ptr)
{
uint8_t *p=(uint8_t*)ptr;
printf("memfox free @ 0x%X ",ptr);
if((membuf<=p)&&(p<(membuf+1024*1024)))
memfox_free(ptr);
else
{
printf("[out of range]\n");
ptr=NULL;
}
}
*定义一个大数组membuf并交给memfox管理
uint8_t membuf[1024*1024];
int main(int argc, char *argv[])
{
uint8_t *InputBuffer;
//memfox
printf("->");
memfox_init(membuf,1024*1024);
printf("memfox init @ 0x%X\n",membuf);
//memfox test
InputBuffer=(uint8_t*)malloc(4096);
free(InputBuffer);
return 0;
}
运行结果:
为啥程序会在main调用malloc之前,甚至memfox初始化之前申请了2个4B的空间?
*从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放外面赋值总觉得有点刺挠:),想问问各位大佬有啥解决办法吗。
你好,我是新手,会单片机,想通过F1C100S学习RAM9的裸机开发。我想知道“达克罗德大佬贡献的裸机代码”是在什么环境编译,调试以及下载的。有没有这方面的教程可以推荐一下,十分感谢!
我是在ubuntu下开发的,装了arm-xxx-gcc的编译环境
编译和烧录见这个帖子:https://whycan.cn/t_1393.html
这芯片全志官方公开放出的资料比较少,我是照着RT-Thread和寄存器手册一点一点扣的
SDIO驱动又来了,这次带着Fatfs一起来了!
p:仍然要感谢达克罗德大佬贡献的裸机代码
*描述
1、支持DMA、CPU读写,支持单块,多块读写
2、支持printf
3、支持定时器延时
4、支持SDHC识别,读写,挂载文件系统
5、支持SDSC识别读写,但无法挂载文件系统(坑)
*计划完成
1、SDSC文件系统挂载
2、优化代码结构
*SDHC卡识别,挂载文件系统,读取文件示例
*代码有些地方不是很优美,比如下面这样 =_=
//must delay :)
sd_delay(30);//<<
return err;
*程序还存在一些玄学问题,比如写到卡里的数据会丢失(SDSC),仍有待完善。
*想先放一放SDIO的驱动,玩点其它的,这几天看SD卡协议和输出数据看的头凉 =_=
03sdio.zip
从RT-Thread扣过来的SDIO初始化代码,参考野火的SD卡初始化代码,实现SD卡初始化和单块读写数据
描述:
1、基础工程是达克罗德大神的裸机程序,编译和烧写见此贴: https://whycan.cn/t_1393.html
2、暂时只支持SDHCI。因为我调试的时候用的一张32GB的卡,小容量卡无法正常识别
3、添加了xprintf组件(Fatfs作者写的),方便串口输出调试信息。
4、暂时只支持通过CPU读写。
计划添加:
1、小容量卡的识别和初始化功能
2、通过DMA读写数据
3、完善SD卡操作函数
4、重构部分代码。
*卡信息输出
main->card block size:512
main->card size:30436MB
SD ID:0x00000003
SD name1:0x53433332
SD name2:0x00000047
SD rev:0x00000080
SD SN:0xB006289D
SD type:0x2
*读取数据块
*代码写得不是很好,但希望能起到抛砖引玉的作用:D
sdio.zip
页次: 1