S3C2440 lds链接脚本解析

本文详细解析了嵌入式程序在NandFlash与Sdram中的部署过程,包括小于4K与大于4K程序的不同处理方式,以及如何支持中断等功能。通过具体的链接脚本与汇编指令实例,阐述了重定位地址的设置方法。

1.  SECTIONS到底意味着什么

    在一个裸版程序里面含有*.lds文件,而lds文件意味着如果你的程序烧录在nandflash,那在nandflash的内存将根据lds文件指定偏移来分布,下面从不同场景来解释SECTIONS的内容。


2.  小于4K程序

    若程序小于4K,那程序的整个重定位地址设置为0,可以没有拷贝到sdram的处理。

    uart.lds

SECTIONS {
    . = 0x00000000;
    .text          :   { *(.text) }
    .rodata ALIGN(4) : {*(.rodata)} 
    .data ALIGN(4) : { *(.data) }
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

    head.S

.text
.global _start
_start:
            ldr     r0, =0x53000000     @ WATCHDOG寄存器地址
            mov     r1, #0x0                     
            str   r1, [r0]              @ 写入0,禁止WATCHDOG,否则CPU会不断重启
            
            ldr     sp, =1024*4         @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
                                        @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
            bl      main                @ 调用C程序中的main函数
halt_loop:
            b       halt_loop

    Nandflash其内存结构如下:


    一开始运行之前,默认会从NandFlash拷贝4K大小的程序代码到芯片片内内存上面并且从0开始执行,由于片内内存只有4K,所以链接脚本只适用于程序运行空间小于4K的情况。


3. 大于4K程序

    若要支持程序大于4K,就需要考虑将程序拷贝到sdram中运行,修改head.s文件,添加从片内内存拷贝到Sdram的操作,同时链接脚本设置重定位地址为0x30000000。

   uart.lds

SECTIONS {
    . = 0x30000000;
    .text          :   { *(.text) }
    .rodata ALIGN(4) : {*(.rodata)} 
    .data ALIGN(4) : { *(.data) }
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

    head.S

.extern     main
.text 
.global _start 
_start:
Reset:                  
    ldr sp, =4096          
    bl  disable_watch_dog  
    bl  clock_init         
    bl  memsetup           
    bl  nand_init

    ldr r0, =0x30000000    
    mov r1, #0         
    mov r2, #(1024*10)     
    bl  nand_read          
    ldr pc, =on_sdram
onsdram:
    ldr sp, =0x34000000    
    ldr lr, =halt_loop     
    ldr pc, =main          
halt_loop:
    b   halt_loop

    此时NanFlash和Sdram内存分布如下:


    当重定位0x30000000后,其内存的指令码后会发生什么变化呢?以main函数里面,获取全局变量值为例,

    重定位0x00的时候:

 690:	e59f2224 	ldr	r2, [pc, #548]	; 8bc <main+0x234>
 8bc:	000009d4 	ldrdeq	r0, [r0], -r4
 9d4:	00000000 	andeq	r0, r0, r0

    重定位0x30000000的时候:

30000690:	e59f2224 	ldr	r2, [pc, #548]	; 300008bc <main+0x234>
300008bc:	300009d4 	ldrdcc	r0, [r0], -r4
300009d4:	00000000 	andeq	r0, r0, r0

    三句汇编代码其作用是获取全局变量的值,将其放入寄存器r2中。可以看到第一条汇编指令码和第三条汇编指令码没有变化,重点分析第二条汇编指令码,第二条汇编指令码实际上是第一条汇编寄存器寻址偏移, [pc, #548]的值需要找8bc或300008bc偏移的汇编指令,而其汇编指令又指向0x9d4或0x300009d4偏移,最终获取在其偏移的内容。由此推想若重定位到0x00,当执行到main函数时,会导致执行地址还在片内范围,假设9d4大于4K,则寻址大于片内内存4K,程序就会溢出。所以链接脚本需要设置重定位地址为0x30000000。


5. 大于4K程序并支持中断

    当需要支持中断时,head.S需要加上中断向量表,如下:

@******************************************************************************
@ File锟斤拷head.S
@ 锟斤拷锟杰o拷锟斤拷锟斤拷SDRAM锟斤拷锟斤拷锟斤拷锟斤拷锟狡碉拷SDRAM锟斤拷然锟斤拷锟斤拷锟斤拷SDRAM锟斤拷锟斤拷执锟斤拷
@******************************************************************************       
   
.extern     main
.text 
.global _start 
_start:
@******************************************************************************
@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
@******************************************************************************
 b   Reset

@ 0x04: 未定义指令中止模式的向量地?
HandleUndef:
	b   HandleUndef

@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
	b   HandleSWI

@ 0x0c: 指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
	b   HandlePrefetchAbort

@ 0x10: 数据访问终止导致的异常的向量地址
HandleDataAbort:
	b   HandleDataAbort

@ 0x14: 保留
HandleNotUsed:
	b   HandleNotUsed

@ 0x18: 中断模式的向量地址
	b   HandleIRQ

@ 0x1c: 快中断模式的向量地址
HandleFIQ:
	b   HandleFIQ

Reset:                  
    ldr sp, =4096           @ 锟斤拷锟斤拷栈指锟诫,锟斤拷锟铰讹拷锟斤拷C锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷前锟斤拷要锟斤拷锟秸�
    bl  disable_watch_dog   @ 锟截憋拷WATCHDOG锟斤拷锟斤拷锟斤拷CPU锟结不锟斤拷锟斤拷锟斤拷
    bl  clock_init          @ 锟斤拷锟斤拷MPLL锟斤拷锟侥憋拷FCLK锟斤拷HCLK锟斤拷PCLK
    bl  memsetup            @ 锟斤拷锟矫存储锟斤拷锟斤拷锟斤拷锟斤拷使锟斤拷SDRAM
    bl  nand_init

	ldr r0, =0x30000000     @1. 鐩爣鍦板潃=0x30000000锛岃繖鏄疭DRAM鐨勮捣濮嬪湴鍧�
    mov r1, #4096           	@2. 婧愬湴鍧�   = 4096锛岃繛鎺ョ殑鏃跺�欙紝main.c涓殑浠g爜閮藉瓨鍦∟AND Flash鍦板潃4096寮�濮嬪
    mov r2, #(1024*20)      @3. 澶嶅埗闀垮害= 1024(bytes)锛屽浜庢湰瀹為獙鐨刴ain.c锛岃繖鏄冻澶熶簡
    bl  nand_read           @璋冪敤C鍑芥暟nand_read_ll
    ldr pc, =on_sdram                   @ 跳到SDRAM中继续执行
on_sdram:
    msr cpsr_c, #0xd2    	@ 进入中断模式
    ldr sp, =4096           @ 设置中断模式栈指针
    msr cpsr_c, #0xdf       @ 进入系统模式
    ldr sp, =0x34000000     @ 锟斤拷锟斤拷栈指锟斤拷
    msr cpsr_c, #0x5f       @ 设置I-bit=0,开IRQ中断

    ldr lr, =halt_loop      @ 锟斤拷锟矫凤拷锟截碉拷址
    ldr pc, =main           @ 锟斤拷锟斤拷main锟斤拷锟斤拷
halt_loop:
    b   halt_loop

HandleIRQ:
 	 sub lr, lr, #4                  		@ 计算返回地址
	 stmdb   sp!,    { r0-r12,lr }   	@ 保存使用到的寄存器
	 							@ 注意,此时的sp是中断模式的sp
	 							@ 初始值是上面设置的4096
	 ldr lr, =int_return             		@ 设置调用ISR即EINT_Handle函数后的返回地址
	 ldr pc, =Uart0_Handle 			@ 调用中断服务函数,在interrupt.c中

 int_return:
 	 ldmia   sp!,    { r0-r12,pc }^  	@ 中断返回, ^表示将spsr的值复制到cpsr

  此时需要修改链接脚本,若延续上述写法,如下:

SECTIONS {
    . = 0x30000000;
    .text          :   { *(.text) }
    .rodata ALIGN(4) : {*(.rodata)} 
    .data ALIGN(4) : { *(.data) }
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

   则会有严重的问题,这时看head.S生成的汇编指令

Disassembly of section .text:

30000000 <_start>:
30000000:	ea000006 	b	30000020 <Reset>

    第一条指令码,直接程序跑飞,因为这条指令码ea000006表示跳转到30000020执行,而30000020位于Sdram,还并没有初始化,所以链接脚本应该这样写:

SECTIONS {
    . = 0x00000000;
    .init : AT(0){ head.o init.o nand.o} 
    . = 0x30000000;
    .text ALIGN(4) : AT(4096) { *(.text) } 
    .rodata ALIGN(4) :  {*(.rodata)}
    .data ALIGN(4)   :  { *(.data) }
    __bss_start = .;
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
    __bss_end = .;
}

    可以看到main函数的重定位也以0x30000000为基准。当执行到main函数时,此时能保证在sdram里执行,并且也能保证取数据段的时候,能得到偏移哪怕大于4K也能正确的重定位到,看如下main汇编指令码:

300025a4 <main>:
300025a4:	e92d4080 	push	{r7, lr}
300025a8:	e24dd080 	sub	sp, sp, #128	; 0x80
300025ac:	e3a0207d 	mov	r2, #125	; 0x7d

    此时看nandflash和sdram的内存分布如下:

    

    

    


【前景培训教材】总结4G和5G基本概念:移动通信网络演进:从1G到5G,技术从模拟到数字,再到高速数据网络,每代技术均大幅提升速率、业务类型及传输时延。4G LTE:作为3G到4G的演进技术,LTE提供高达100Mbps的数据下载能力,采用OFDM和MIMO技术。5G NR:5G目标是高数据速率、低延迟、高能效,支持大规模设备连接。5G NR标准逐步演进,包括R15和R16,后者增强uRLLC、V2X支持及毫米波载波聚合。4G和5G网络架构:5G新功能:引入5G区域通知和连接决策功能,确保用户在5G覆盖区域内获得最优连接。网络架构对比:4G和5G在无线接口、系统消息等方面有显著不同,5G采用更先进的架构和技术。4G和5G关键技术:4G关键技术:包括双工方式、多址技术、AMC(自适应调制编码)、HARQ(混合自动重传请求)等,提升数据传输效率和可靠性。5G新增技术:5G在4G基础上增加更多创新技术,如大规模MIMO、毫米波通信等,以实现更高速率和更低延迟。4G和5G帧结构:帧结构定义:4G和5G采用不同的帧结构,以适应不同的网络需求和技术特性。时间同步与资源管理:帧结构的设计涉及时间同步、资源分配等关键方面,对网络性能有重要影响。4G和5G速率计算:速率计算方法:介绍了如何根据网络参数和技术特性计算4G和5G的理论速率。影响因素分析:讨论了影响速率的关键因素,如频谱效率、信道带宽等。4G和5G专用名词:术语定义:提供了4G和5G领域常用的专业术语及其定义,帮助读者理解相关技术概念。4G和5G切换事件:切换机制:详细介绍了4G和5G网络中的切换事件及其触发条件,如A3、A4、B1、B2等事件。优化策略:讨论了如何通过优化切换参数和策略来提升网络性能和用户体验。VOLTE技术和CSFB技术:VOLTE技术:实现了在4G网络上的高清语音和视频通话,提升了通话质量和用户体验。CSFB技术:在4G网络覆盖不足时,通过回落到2G/3G网络来保证通话连续性。4G和5G信令流程:信令流程概述:详细描述了4G和5G网络中的关键信令流程,如附着流程、TAU更新流程、CSFB信令流程等。故障排查与优化:通过分析信令流程,可以帮助定位和解决网络问题,提升网络性能和稳定性。总结:以上总结涵盖了【前景培训教材】中关于4G和5G的基本概念、网络架构、关键技术、帧结构、速率计算、专用名词、切换事件、VOLTE和CSFB技术以及信令流程等方面的内容。这些内容全面而深入地介绍了4G和5G技术的各个方面,为读者提供了丰富的技术知识和实践指导。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值