一、C语言运行环境构建:
1.设置处理器模式
设置6ULL处于SVC模式 下。设置CPSR寄存器的bit4-0,也就是M[4:0]为10011=0X13。读写状态寄存器需要用到MRS和MSR指令。MRS将CPSR寄存器数据读出到通用寄存器里面,MSR指令将通用寄存器的值写入到CPSR寄存器里面去。
2.设置sp指针
Sp可以指向内部RAM,也可以指向DDR,我们将其指向DDR。Sp设置到哪里?512MB的范围0x80000000~0x9FFFFFFF。栈大小,0x200000=2MB。处理器栈增长方式,对于A7而言是向下增长的。设置sp指向0x80200000。
3.跳转到C语言
使用b指令,跳转到C语言函数,比如main函数。
二、软件编写:
start.s:
1 .global _start
2 _start:
3 /* 设置处理器进入SVC模式 */
4 mrs r0,cpsr /* 读取cpsr到r0 */
5 bic r0,r0,#0x1f /* 清除cpsr的bit4-0 */
6 orr r0,r0,#0x13 /* 使用SVC模式 */
7 msr cpsr,r0 /* 将r0写入到cpsr */
8 /* 设置sp指针 */
9 ldr sp,=0x80200000
10 b main /* 跳转到C语言main函数*/
main.c:
1 #include "main.h"
2
3 /* 使能外设时钟*/
4 void clk_enable(void)
5 {
6 CCM_CCGR1=0xFFFFFFFF;
7 CCM_CCGR2=0xFFFFFFFF;
8 CCM_CCGR3=0xFFFFFFFF;
9 CCM_CCGR4=0xFFFFFFFF;
10 CCM_CCGR5=0xFFFFFFFF;
11 CCM_CCGR6=0xFFFFFFFF;
12 }
13
14 /* 初始化LED*/
15 void led_init(void)
16 {
17 SW_MUX_GPIO1_IO03=0x5; /* 复用为GPIO1_IO03*/
18 SW_PAD_GPIO1_IO03=0x10B0; /* 设置GPIO1_IO03的电气属性*/
19
20 /* GPIO初始化*/
21 GPIO1_GDIR=0x8; /* 设置GPIO为输出*/
22 GPIO1_DR=0x0; /* 打开LED灯*/
23 }
24
25 /* 打开LED灯*/
26 void led_on(void)
27 {
28 /*
29 * 将GPIO1_DR的bit3清零
30 */
31 GPIO1_DR &= ~(1<<3);
32 }
33
34 /*关闭LED灯*/
35 void led_off(void)
36 {
37 /*
38 * 将GPIO1_DR的bit3置1
39 */
40 GPIO1_DR |= (1<<3);
41 }
42
43 /* 短延时函数*/
44 void delay_short(volatile unsigned int n)
45 {
46 while(n--){}
47 }
48
49 /*延时函数,在396Mhz的主频下延时时间大约为1ms*/
50 void delay(volatile unsigned int n)
51 {
52 while(n--)
53 {
54 delay_short(0x7ff);
55 }
56 }
57
58 int main(void)
59 {
60 clk_enable(); /* 初始化外设时钟*/
61 led_init(); /* 初始化LED*/
62 /* 初始化LED*/
63 while(1)
64 {
65 led_on();
66 delay(500);
67 led_off();
68 delay(500);
69 }
70 /* 设置LED闪烁*/
71 return 0;
72 }
main.h:
1 #ifndef __MAIN_H
2 #define __MAIN_H
3
4 /* 定义要使用的寄存器*/
5 #define CCM_CCGR0 *((volatile unsigned int *)0x020C4068)
6 #define CCM_CCGR1 *((volatile unsigned int *)0X020C406C)
7 #define CCM_CCGR2 *((volatile unsigned int *)0X020C4070)
8 #define CCM_CCGR3 *((volatile unsigned int *)0X020C4074)
9 #define CCM_CCGR4 *((volatile unsigned int *)0X020C4078)
10 #define CCM_CCGR5 *((volatile unsigned int *)0X020C407C)
11 #define CCM_CCGR6 *((volatile unsigned int *)0X020C4080)
12
13 /*
14 * IOMUX相关寄存器地址
15 */
16 #define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068)
17 #define SW_PAD_GPIO1_IO03 *((volatile unsigned int *)0X020E02F4)
18
19 /*
20 * GPIO1相关寄存器地址
21 */
22 #define GPIO1_DR *((volatile unsigned int *)0X0209C000)
23 #define GPIO1_GDIR *((volatile unsigned int *)0X0209C004)
24 #define GPIO1_PSR *((volatile unsigned int *)0X0209C008)
25 #define GPIO1_ICR1 *((volatile unsigned int *)0X0209C00C)
26 #define GPIO1_ICR2 *((volatile unsigned int *)0X0209C010)
27 #define GPIO1_IMR *((volatile unsigned int *)0X0209C014)
28 #define GPIO1_ISR *((volatile unsigned int *)0X0209C018)
29 #define GPIO1_EDGE_SEL *((volatile unsigned int *)0X0209C01C)
30
31 #endif
Makefile:
1 objs = start.o main.o
2
3 ledc.bin:$(objs)
4 arm-linux-gnueabihf-ld -Ttext 87800000 $^ -o ledc.elf
5 arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
6 arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
7
8 %.o:%.c
9 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
10
11 %.o:%.s
12 arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
13
14 clean:
15 rm -rf *.o ledc.bin ledc.elf ledc.dis
有了以上的文件,我们就可以编译烧写到TF卡(烧录方法同汇编LED实验)了,插到板子上就可以验证。但是如果写了以下的链接脚本,只需要把Makefile文件里的arm-linux-gnueabihf-ld -Ttext 87800000 $^ -o ledc.elf改写成arm-linux-gnueabihf-ld -Timx6u.lds $^ -o ledc.elf即可。
三、链接脚本:
链接脚本描述了要连接的文件,以及链接顺序,和链接首地址。
imx6u.lds:
1 SECTIONS{
2 . = 0X87800000;
3 .text :
4 {
5 start.o
6 main.o
7 *(.text)
8 }
9 .rodata ALIGN(4) : {*(.rodata*)}
10 .data ALIGN(4) : { *(.data) }
11 __bss_start = .;
12 .bss ALIGN(4) : { *(.bss) *(COMMON) }
13 __bss_end = .;
14 }
本篇完!!!