浅析电商网站建设趋势,wordpress修改文件上传大小,电子书网站怎么做,潮州网站网站建设1. SECTIONS到底意味着什么在一个裸版程序里面含有*.lds文件#xff0c;而lds文件意味着如果你的程序烧录在nandflash#xff0c;那在nandflash的内存将根据lds文件指定偏移来分布#xff0c;下面从不同场景来解释SECTIONS的内容。2. 小于4K程序若程序小于4K#xff0c;那…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只有4Kbl main 调用C程序中的main函数
halt_loop:b halt_loopNandflash其内存结构如下一开始运行之前默认会从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_initldr 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 main0x2348bc: 000009d4 ldrdeq r0, [r0], -r49d4: 00000000 andeq r0, r0, r0重定位0x30000000的时候
30000690: e59f2224 ldr r2, [pc, #548] ; 300008bc main0x234
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锟斤拷锟杰拷锟斤拷锟斤拷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 HandleFIQReset: ldr sp, 4096 锟斤拷锟斤拷栈指锟诫锟斤拷锟铰讹拷锟斤拷C锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷前锟斤拷要锟斤拷锟秸bl disable_watch_dog 锟截憋拷WATCHDOG锟斤拷锟斤拷锟斤拷CPU锟结不锟斤拷锟斤拷锟斤拷bl clock_init 锟斤拷锟斤拷MPLL锟斤拷锟侥憋拷FCLK锟斤拷HCLK锟斤拷PCLKbl memsetup 锟斤拷锟矫存储锟斤拷锟斤拷锟斤拷锟斤拷使锟斤拷SDRAMbl nand_initldr r0, 0x30000000 1. 鐩爣鍦板潃0x30000000锛岃繖鏄疭DRAM鐨勮捣濮嬪湴鍧mov r1, #4096 2. 婧愬湴鍧 4096锛岃繛鎺ョ殑鏃跺欙紝main.c涓殑浠爜閮藉瓨鍦∟AND Flash鍦板潃4096寮濮嬪mov r2, #(1024*20) 3. 澶嶅埗闀垮害 1024(bytes)锛屽浜庢湰瀹為獙鐨刴ain.c锛岃繖鏄冻澶熶簡bl nand_read 璋冪敤C鍑芥暟nand_read_llldr 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-bit0开IRQ中断ldr lr, halt_loop 锟斤拷锟矫凤拷锟截碉拷址ldr pc, main 锟斤拷锟斤拷main锟斤拷锟斤拷
halt_loop:b halt_loopHandleIRQ:sub lr, lr, #4 计算返回地址stmdb sp!, { r0-r12,lr } 保存使用到的寄存器 注意此时的sp是中断模式的sp 初始值是上面设置的4096ldr 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的内存分布如下