一、汇编初始化部分(liubo.S)
1 .equ mem_control_address, 0x48000000 @宏定义,存储控制器起始地址 2 .equ sdram_address, 0x30000000 @宏定义,SDRAM的起始地址 3 4 @********************************** 5 .text @以下语句都属于代码段 6 .global _start @全局声明,表示_start是全局函数 7 8 @********************************** 9 _start: 10 bl close_watchdog @关看门狗,bl和b都是跳转代码段,区别在于bl跳转之后返回,返回地址存到lr中 11 bl set_mem_control @设置控制存储器 12 bl copy_steppingstone4k_to_SDRAM @SDRAM有4K,NARD启动方式,上电,CPU自动将NARD前4K代码完全拷贝到SRAM中,然后此段程序将SRAM中的4K代码拷贝到外接的SDRAM中;如果代码大于4k,则后面部分需要从NARD中拷到SDRAM中 13 ldr pc, =on_sdram @pc也就是寄存器r15程序计数,程序执行前先将起始地址放入计数器,执行后CPU改变PC的值,指向下一条指令的起始位置,mov是寄存器中的值到寄存器或常数到寄存器,mov的移动必需是立即数 14 @如果不确定是不是立即数,就可以用ldr r1, =label label: ;或 ldr r1, = 4096 15 on_sdram: 16 ldr sp, =0x34000000 @sp也就是r13,数据栈指针,设置栈,栈顶指向SDRAM终止地址 17 bl main @调用主函数C函数 18 19 halt_loop: 20 b halt_loop @死循环 21 @********************************** 22 @关看门狗@ 23 @********** 24 close_watchdog: 25 mov r1, #0x53000000 @看门狗地址0x53000000, 加mov r1, #num 加#就是立即数,指把立即数num给r1;mov r1,num 不加#指直接地址,也就是把num地址单元内的值送入到r1 26 mov r2, #0 @寄存器r0-r3用来传递参数,别名a1-a4 27 str r2, [r1] @str r2, [r1] r2的数据放到r1的地址中; str r2, [r1,#n] r2中数据放到r1+n地址中;str r2, [r1],#n r2中数据放到r1中,然后r1+n;str r2 28 @ldr r2, [r1] r1内存单元的数据放到r2中;ldr r2,[r1,#n] r1+n的数据放到r2; ldr r2,[r1], #n r1中的数据放到r2中,并且r1+n 29 mov pc, lr @返回start代码段,执行下一条指令。执行完这段代码之后下一条地址存在lr中,执行下一条代码之前,要将起始地址放到PC 30 @********************************* 31 @设置控制存储器@ 32 @**************** 33 set_mem_control: 34 mov r1, #0x48000000 @控制存储器起始地址放入r1 35 adrl r2, control_list @存储控制器13个寄存器设定值放入r2;感觉效果应该是:比如说每个控制寄存器的设定值control_list:a,b,c,d,e,f ;adrl r2,control_list 处理后,r2地址对应a; r2+n地址对应值b; @r2+2n地址对应值c 36 add r3, r1, #52 @存储控制器的结束地址放入r3,13个寄存器13*4;存储器控制寄存器共13个寄存器,control_1地址0x48000000,control_13地址0x48000030;中间各4位一个寄存器; 37 @所以控制寄存器初始值0x48000000;结束值是0x48000034,也就是初始值+13*4 38 39 1: @此处是一,1-9是属于局部标签,局部标签可以重复使用 40 ldr r4, [r2], #4 @r2寄存器地址单元的数据放入r4,同时r2+4;也就是将第一个控制寄存器需要设定的值放入r4,然后r2+4后即是r2寄存器此时的地址单元对应的数据为第二个控制寄存器的地址 41 str r4, [r1], #4 @将r4的地址内容放入r1中的地址单元,也就是完成了将第一个控制寄存器的设定值放入r1,r1+4之后,也就是之后r1的地址指向下一个寄存器 42 cmp r1, r3 @cmp r1, r3为r1减去r3,但是r1和r3的值不变;此处也就是判断给控制寄存器赋值,是否到了最后一个,也就是第十三个了 43 bne 1b @b和bne都是跳转,区别在于b直接跳转到后面所指,但bne先判断上面是否为0,如果不是0就跳转;bne后面接的1b,1也就是一,即前面的代码段;b是back 44 @对于x属于0-9的局部标签,f表示forward,b表示back,xf:往前跳的意思,就是跳到前面还未执行的程序;xb:往后跳的意思,跳转到前面已经执行过的语句 45 46 .align 4 47 48 control_list: @每个控制寄存器的值设定,根据开发板的使用电路而言,基本已经固定。 49 .long 0x22011110 50 .long 0x00000700 51 .long 0x00000700 52 .long 0x00000700 53 .long 0x00000700 54 .long 0x00000700 55 .long 0x00000700 56 .long 0x00018005 57 .long 0x00018005 58 .long 0x008C07A3 59 .long 0xB1 60 .long 0X30 61 .long 0X30 62 @************************************************** 63 @ 把steppingstone中的4k @ 64 @ 全部复制到sdram中 @ 65 @************************ 66 copy_steppingstone4k_to_SDRAM: 67 mov r1, #0 @ r1=0 68 ldr r2, =0x30000000 @ r2=0x30000000,SDRAM的起始地址0x30000000 69 mov r3, #4*1024 @ 4kb=4*1024b,字节b;r3=4*1024字节 70 1: 71 ldr r4, [r1], #4 @ r1地址单元存储的数据给r4,并且r1+4 72 str r4, [r2], #4 @ r4的值放到r2的存储单元中,并且r2+4 73 cmp r1, r3 @ r1-r3的值,r1和r3的值都不变 74 bne 1b @ 若r1-r3不等于0,则向前跳转到1: 75 mov pc, lr @ 返回 76 77 78 79
二、C语言功能部分(liubo.c)
//************************************************************** // 宏定义部分 //************ #define GPFCON (*(volatile unsigned long *)0x56000050) //三个寄存器相连,每个地址间隔4 #define GPFDAT (*(volatile unsigned long *)0x56000054) #define GPFUP (*(volatile unsigned long *)0x56000018) //因为默认不变,所以,可以不设置 #define ulong unsigned long #define uchar unsigned char //************************************************************** // 延时函数部分 //************** void delayms() { uchar i,j; for(i=0;i<200;i++) for(j=0;j<200;j++); } //*************************************************************** //主函数部分 //*********** int main() { while(1) { uchar j; ulong led_circle[]={0x60,0x50,0x30,0x50}; //依次选择,用于依次点亮三个LED灯 GPFCON=0X1500; //设置3个引脚为输出状态 // GPFUP=0x00; //设置GPFUP寄存器,可以不设置,默认就都是0 for(j=0;j<4;j++) { GPFDAT=led_circle[j]; delayms(); } } return 0; }
三、makefile部分(makefile)
liubo.bin: liubo.S liubo.c # 由liubo.c 和 liubo.S 生成makefile文件 arm-linux-gcc -c -o liubo_S.o liubo.S # 将liubo.S生成.o文件; -c用于生成OBJ目标文件;-o后面的文件是输出;最后面加上输入文件 arm-linux-gcc -c -o liubo_c.o liubo.c # 将liubo.c生成.o文件 arm-linux-ld -Ttext 0x30000000 liubo_S.o liubo_c.o -o liubo_elf # 生成elf文件; arm-linux-ld后接三种:-Ttext 代码段起始地址、-Tdata 数据段起始地址、-Tbss bss段的起始地址;数据在SDRAM中,因此,后面加SDRAM的起 #始地址 arm-linux-objcopy -O binary -S liubo_elf liubo.bin # elf文件生成可执行的二进制bin文件;-S是,不从源文件中复制重定位信息和符号信息到目标文件中去 arm-linux-objdump -D -m arm liubo_elf > liubo.dis # 反汇编生成.dis汇编文件,便于查看调试;-D指,反汇编所有段;-m arm 指反汇编结构为arm汇编 clean: rm -f liubo.dis liubo.bin liubo_elf *.o # 删除上一次make的文件
时间: 2025-01-02 18:15:07