首页 > 技术文章 > LED C语言实验

chijiacong 2021-12-03 11:06 原文

一、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 }

 

  本篇完!!!

推荐阅读