韦东山嵌入式Linux学习笔记之——代码重定位002_链接脚本的引入

本文探讨了嵌入式系统中NorFlash启动时遇到的问题及解决方案,特别是全局变量的重定位方法,并通过链接脚本和start.S文件实现了代码和数据段的有效重定位。

近期将之前学习嵌入式的笔记进行了整理,内容涉及到基础知识以及嵌入式开发过程中比较重要的模块开发知识,文章中有我在学习过程中的标注,非常详细,可以让入门学习事半功倍。

获取链接    提取码:qk7t 

 

【正文】

① NOR启动:

② nand 启动:

上次讲到的g_char不能按照程序正确输出的原因是nor启动的时候g_char在nor flash中,其不可写的特性决定了输出结果。

现在能否修改Makefile让nor启动时讲代码拷贝到SDRAM中,这样就可以实现全局变量的可读可写了。

现在想在nor flash启动的时候将其中的代码段拷贝至SDRAM中0地址起始的空间,将全局变量g_char拷贝至0x30000000起始的空间。

编译之后发现.bin文件变成了800M,805306369-->0x30000001,符合程序中的g_char所占1字节的设置。

但是nor flash一共才2M,不可实现。

解决方法有两种:

第1种: 只是重定位了全局变量

① 在,bin文件中让g_char和代码段靠在一起

② 烧写至nor flash中

③ 运行时让前面的代码段将g_char复制到SDRAM起始的0x30000000地址空间中,即重定位

第2种:重定位了整个代码+全局变量

让代码段和g_char之间没有那么大的空洞。

我们怎么将位于0x30000000的数据data段跟位于0地址的代码段拼在一起呢?

因为这些复杂的操作通过简单的参数设置已经无法实现,因此需要引入链接脚本来完成相应的操作。

链接脚本:

通过链接脚本的方式实现:

SECTIONS {
	.test 0 : { *(.test) }
	.rodata : { *(.rodata) }
	.data 0x30000000 :  AT(0X800) { *(.data) }
	.bss : { *(.bss) *(.COMMON)}
}

编译

烧写至开发板的nor flash之后发现输出是乱码,烧写至nand flash之后依然是乱码。

在链接脚本中,我们将data段定位到了0x800(2048)的位置上,但是在main函数中访问g_char时的地址是0x30000000。

下面查看main函数的反汇编码:

从反汇编码可以看出,寄存器r3确实在0x30000000地址中得到了其中的值,但是我们在程序中并没有将g_char的值放到0x3000000的地址空间去,因此缺少了重定位的一个步骤。

修改代码:现在需要将g_char的值从0x800的地方复制到0x30000000的地址空间去。

在start.S文件中加入重定位的代码即可:

	/* 重定位data段 */
	mov r1, #0x800
	mov r0, [r1]
	mov r1, #0x30000000
	str r0, [r1]

之后编译代码下载至开发板,发现还是乱码。。。“RP值低预警”。。。

查找问题后发现,原因竟然是。。。在start.S中没有初始化SDRAM!!

之后再次编译代码下载至开发板(注意设置开发板启动模式为nor启动):

成功!!

接下来的问题是,刚刚的重定位代码并不通用。在重定位的时候我们是在知道原地址和重定位地址的情况下从0x800仅仅复制了一个字节到0x30000000地址中去的,如果我们要复制多个字节又该怎么做呢?

首先修改链接脚本:

SECTIONS {
	.text 0 : { *(.text) }
	.rodata : { *(.rodata) }
	.data 0x30000000 : AT(0X800) 
	{ 
		data_load_addr = LOADADDR(.data);
		data_start = . ;
		*(.data) 
		data_end = . ;
	}
	.bss : { *(.bss) *(.COMMON)}
}

注意:链接脚本中的“.”代表当前地址,这里的当前地址指的是前面各种段地址的顺延。

然后修改start.S文件:

	/* 重定位data段 */
	ldr r1, =data_load_addr  /* data段在bin文件中的地址,加载地址 */、
	ldr r2, =data_start     /* data段的重定位(从nor或者nand flash中定位至SDRAM中)开始地址,运行时的地址 */
	ldr r3, =data_end       /* data段重定位的结束地址 */

/* 接下来将r1所指地址中的值拷贝至r2所指的地址空间 */
cpy:
	ldrb r4, [r1]   //从r1地址处拷贝一个字节到r4
	strb r4, [r2]
	add r1, r1, #1
	add r2, r2, #1
	cmp r2, r3
	bne cpy

在main函数中加入一个全局变量:

char g_char = 'A';
char g_char3 = 'a';

const char g_char2 = 'B';
int g_A = 0;
int g_B;

int main(void)
{
	uart0_init();

	while(1)
	{
		putchar(g_char);   
		g_char++;      /* nor启动时,此代码无效 */
		
		putchar(g_char3);   
		g_char3++;      /* nor启动时,此代码无效 */
		delay(100000);
	}

编译烧写:

成功。

 

 

 

 

内容概要:本文系统研究了构网型变流器的正负序阻抗解耦特性及其在弱电网环境下的稳定性表现,重点依托Matlab/Simulink仿真平台,构建了详细的阻抗数学模型,设计了解耦控制策略,并采用小信号扫频法进行频域辨识与稳定性验证。研究深入探讨了构网型变流器与传统跟网型逆变器在正负序阻抗特性上的本质差异,结合虚拟同步发电机(VSG)等先进控制技术,分析其在抑制宽频带振荡、削弱锁相环动态耦合等方面的优越性。文中不仅提供了完整的仿真模型与MATLAB代码实现,还整合了光伏、风电、储能、微电网等多类新能源系统的阻抗建模与稳定性分析资源,形成了一套面向新型电力系统稳定性的综合性技术资料体系,具有较强的科研复现与工程参考价值。; 适合人群:面向具备电力电子、电力系统自动化、新能源并网等专业背景的研究生、高校教师及工程技术人员,特别适用于从事阻抗建模、小干扰稳定性分析、宽频振荡机理研究以及撰写高水平学术论文的科研工作者。; 使用场景及目标:①掌握构网型变流器正负序阻抗建模与扫频辨识的仿真方法;②深入理解VSG等构网型控制在弱电网中提升稳定性的内在机理;③复现顶刊论文中的阻抗分析流程与稳定性判据应用;④利用提供的成熟模型与代码加速科研进程,支撑课题研究与学术成果产出。; 阅读建议:建议结合文中提供的Simulink模型与MATLAB代码,按照“理论建模—仿真搭建—扫频激励—频响提取—Nyquist判据分析”的完整流程进行实践操作,重点关注扫频信号的注入方式、频率范围设置及阻抗曲线的物理意义解读,并参考博士论文复现案例深化对复杂动态耦合问题的理解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值