正点原子Linux裸机开发学习笔记01C语言版LED开发实验

一,C 语言版 LED 灯简介

                                                         LED 灯驱动
               在实际中很少使用汇编语言去写嵌入式开发,大部分情况下我们都是使用C语言去编写。
而c语言需要用汇编语言来初始化一下c语言环境,比如初始化ddr,设置堆栈指针sp等。

①、汇编文件
汇编文件只是用来完成 C 语言环境搭建。
②、C 语言文件
C 语言文件就是完成我们的业务层代码的,其实就是我们实际例程要完成的功能。

                以 STM32F103 为例,其启动文件 startup_stm32f10x_hd.s 这个汇编文件就是完成 C 语言环境搭建的,当然还有一些其他的处理,比如中断向量表等等。当 startup_stm32f10x_hd.s 把 C 语言环境初始化完成以后就会进入 C 语言环境。
注:
                所谓的 C语言环境就是保证 C 语言能够正常运行。C 语言中的函数调用涉及到出栈入栈,出栈入栈就要对堆栈进行操作,所谓的堆栈其实就是一段内存,这段内存比较特殊,由 SP 指针访问,SP 指针指向栈顶。芯片一上电 SP 指针还没有初始化,所以 C 语言没法运行,对于有些芯片还需要初始化 DDR,因为芯片本身没有 RAM,或者内部 RAM 不开放给用户使用,用户代码需要在DDR 中运行,因此一开始要用汇编来初始化 DDR 控制器

 二,汇编部分实验程序编写

汇编简单介绍:

                GNU 汇编语法适用于所有的架构,并不是 ARM 独享的, GNU 汇编由一系列的语句组成, 每行一条语句,每条语句有三个可选部分,如下:
                label:instruction @ comment
                label 即标号,表示地址位置,有些指令前面可能会有标号,这样就可以通过这个标号得到 指令的地址,标号也可以用来表示数据地址。注意 label 后面的“:”,任何以“:”结尾的标识
符都会被识别为一个标号。
                instruction 即指令,也就是汇编指令或伪指令。
                @符号,表示后面的是注释,就跟 C 语言里面的“ /* ”和“ */ ”一样,其实在 GNU 汇编文
件中我们也可以使用“/* ”和“ */ ”来注释。
                comment 就是注释内容。         

                在 STM32 中,启动文件 startup_stm32f10x_hd.s 就是完成 C 语言环境搭建的,当然还有一 些其他的处理,比如中断向量表等等。
                示例代码 10.3.1.1 STM32 启动文件堆栈初始化代码
1 Stack_Size EQU 0x00000400
2 
3 AREA STACK, NOINIT, READWRITE, ALIGN=3
4 Stack_Mem SPACE Stack_Size
5 __initial_sp
6 
7 ; <h> Heap Configuration
8 ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
9 ; </h>
10
11 Heap_Size EQU 0x00000200
12
13 AREA HEAP, NOINIT, READWRITE, ALIGN=3
14 __heap_base
15 Heap_Mem SPACE Heap_Size
16 __heap_limit
17 *******************省略掉部分代码***********************
18 Reset_Handler PROC
19 EXPORT Reset_Handler [WEAK]
20 IMPORT __main
21 IMPORT SystemInit
22 LDR R0, =SystemInit
23 BLX R0 
24 LDR R0, =__main
25 BX R0
26 ENDP
1 行代码就是设置栈大小,这里是设置为 0X400=1024 字节。
5 行的 __initial_sp 就是初始化 SP 指针。
11 行是设置堆大小。
18 行是复位中断服务函数, STM32 复位完成以后会执行此中断服务函数。
22 行调用 SystemInit() 函数来完成其他初始化工作。
24 行调用 __main __main 是库函数,其会调用 main() 函数。
                I.MX6U 的汇编部分代码和 STM32 的启动文件 startup_stm32f10x_hd.s 基本类似的,只是本 实验我们不考虑中断向量表,只考虑初始化 C 环境即可。
1 .global _start /* 全局标号 */
2 
3 /*
4 * 描述: _start 函数,程序从此函数开始执行,此函数主要功能是设置 C
5 * 运行环境。
6 */
7 _start:
8 
9 /* 进入 SVC 模式 */
10 mrs r0, cpsr
11 bic r0, r0, #0x1f /* 将 r0 的低 5 位清零,也就是 cpsr 的 M0~M4 */
12 orr r0, r0, #0x13 /* r0 或上 0x13,表示使用 SVC 模式 */
13 msr cpsr, r0 /* 将 r0 的数据写入到 cpsr_c 中 */
14
15 ldr sp, =0X80200000 /* 设置栈指针 */
16 b main /* 跳转到 main 函数 */
1 行定义了一个全局标号 _start
7 行就是标号 _start 开始的地方,相当于是一个 _start 函数,这个 _start 就是第一行代码。
10~13 行就是设置处理器进入 SVC 模式。
第 15 行通过 ldr 指令设置 SVC 模式下的 SP 指针=0X80200000。
16 行就是跳转到 main 函数, main 函数就是 C 语言代码了。因为 I.MX6U-ALPHA 开发板上的DDR3地址范围是0X80000000~0XA0000000(512MB) 或 者0X80000000~0X90000000(256MB),不管是 512MB 版本还是 256MB 版本的,其 DDR3 起始地址都是 0X80000000。由于 Cortex-A7 的堆栈是向下增长的,所以将 SP 指针设置为 0X80200000,因此 SVC 模式的栈大0X80200000-0X80000000=0X200000=2MB,2MB 的栈空间已经很大了,如果做裸机开发的话绰绰有余。
SVC模式介绍:
                        除了 User(USR)用户模式以外,其它 8 种运行模式都是特权模式。这几个
运行模式可以通过软件进行任意切换,也可以通过中断或者异常来进行切换。大多数的程序都
运行在用户模式,用户模式下是不能访问系统所有资源的,有些资源是受限的,要想访问这些
受限的资源就必须进行模式切换。但是用户模式是不能直接进行切换的,用户模式下需要借助
异常来完成模式切换,当要切换模式的时候,应用程序可以产生异常,在异常的处理过程中完
成处理器模式切换。
                        当中断或者异常发生以后,处理器就会进入到相应的异常模式种,每一种模式都有一组寄 存器供异常处理程序使用,这样的目的是为了保证在进入异常模式以后,用户模式下的寄存器 不会被破坏。

三,C 语言部分实验程序编写

                在 main.h 里面输入代码:
示例代码 10.3.2.1 main.h 文件代码
#ifndef __MAIN_H
#define __MAIN_H
/******************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : main.h
作者 : 左忠凯
版本 : V1.0
描述 : 时钟 GPIO1_IO03 相关寄存器地址定义。
其他 : 无
 
原子哥在线教学:www.yuanzige.com 论坛:www.openedv.com
347
I.MX6U 嵌入式 Linux 驱动开发指南
日志 : 初版 V1.0 2019/1/3 左忠凯创建
*****************************************************************/
1 /* 
2 * CCM 相关寄存器地址
3 */
4 #define CCM_CCGR0 *((volatile unsigned int *)0X020C4068)
5 #define CCM_CCGR1 *((volatile unsigned int *)0X020C406C)
6 #define CCM_CCGR2 *((volatile unsigned int *)0X020C4070)
7 #define CCM_CCGR3 *((volatile unsigned int *)0X020C4074)
8 #define CCM_CCGR4 *((volatile unsigned int *)0X020C4078)
9 #define CCM_CCGR5 *((volatile unsigned int *)0X020C407C)
10 #define CCM_CCGR6 *((volatile unsigned int *)0X020C4080)
11
12 /* 
13 * IOMUX 相关寄存器地址
14 */
15 #define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068)
16 #define SW_PAD_GPIO1_IO03 *((volatile unsigned int *)0X020E02F4)
17
18 /* 
19 * GPIO1 相关寄存器地址
20 */
21 #define GPIO1_DR *((volatile unsigned int *)0X0209C000)
22 #define GPIO1_GDIR *((volatile unsigned int *)0X0209C004)
23 #define GPIO1_PSR *((volatile unsigned int *)0X0209C008)
24 #define GPIO1_ICR1 *((volatile unsigned int *)0X0209C00C)
25 #define GPIO1_ICR2 *((volatile unsigned int *)0X0209C010)
26 #define GPIO1_IMR *((volatile unsigned int *)0X0209C014)
27 #define GPIO1_ISR *((volatile unsigned int *)0X0209C018)
28 #define GPIO1_EDGE_SEL *((volatile unsigned int *)0X0209C01C)
29
30 #endif
                在 main.h 中我们以宏定义的形式定义了要使用到的所有寄存器,后面的数字就是其地址, 比如 CCM_CCGR0 寄存器的地址就是 0X020C4068 ,这个很简单,很好理解。
                接下看一下 main.c 文件,在 main.c 里面输入如下所示代码:
示例代码 10.3.2.2 main.c 文件代码
/**************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : main.c
作者 : 左忠凯
版本 : V1.0
描述 : I.MX6U 开发板裸机实验 2 C 语言点灯
 
原子哥在线教学:www.yuanzige.com 论坛:www.openedv.com
348
I.MX6U 嵌入式 Linux 驱动开发指南
 使用 C 语言来点亮开发板上的 LED 灯,学习和掌握如何用 C 语言来
 完成对 I.MX6U 处理器的 GPIO 初始化和控制。
其他 : 无
日志 : 初版 V1.0 2019/1/3 左忠凯创建
**************************************************************/
1 #include "main.h"
2 
3 /*
4 * @description : 使能 I.MX6U 所有外设时钟
5 * @param : 无
6 * @return : 无
7 */
8 void clk_enable(void)
9 {
10 CCM_CCGR0 = 0xffffffff;
11 CCM_CCGR1 = 0xffffffff;
12 CCM_CCGR2 = 0xffffffff;
13 CCM_CCGR3 = 0xffffffff;
14 CCM_CCGR4 = 0xffffffff;
15 CCM_CCGR5 = 0xffffffff;
16 CCM_CCGR6 = 0xffffffff;
17 }
18 
19 /*
20 * @description : 初始化 LED 对应的 GPIO
21 * @param : 无
22 * @return : 无
23 */
24 void led_init(void)
25 {
26 /* 1、初始化 IO 复用, 复用为 GPIO1_IO03 */
27 SW_MUX_GPIO1_IO03 = 0x5; 
28 
29 /* 2、配置 GPIO1_IO03 的 IO 属性 
30 *bit 16:0 HYS 关闭
31 *bit [15:14]: 00 默认下拉
32 *bit [13]: 0 kepper 功能
33 *bit [12]: 1 pull/keeper 使能
34 *bit [11]: 0 关闭开路输出
35 *bit [7:6]: 10 速度 100Mhz
36 *bit [5:3]: 110 R0/6 驱动能力
37 *bit [0]: 0 低转换率
38 */
39 SW_PAD_GPIO1_IO03 = 0X10B0; 
40 
41 /* 3、初始化 GPIO, GPIO1_IO03 设置为输出 */
42 GPIO1_GDIR = 0X0000008;
43 
44 /* 4、设置 GPIO1_IO03 输出低电平,打开 LED0 */
45 GPIO1_DR = 0X0;
46 }
47 
48 /*
49 * @description : 打开 LED 灯
50 * @param : 无
51 * @return : 无
52 */
53 void led_on(void)
54 {
55 /* 
56 * 将 GPIO1_DR 的 bit3 清零 
57 */
58 GPIO1_DR &= ~(1<<3);
59 }
60 
61 /*
62 * @description : 关闭 LED 灯
63 * @param : 无
64 * @return : 无
65 */
66 void led_off(void)
67 {
68 /* 
69 * 将 GPIO1_DR 的 bit3 置 1
70 */
71 GPIO1_DR |= (1<<3);
72 }
73 
74 /*
75 * @description : 短时间延时函数
76 * @param - n : 要延时循环次数(空操作循环次数,模式延时)
77 * @return : 无
78 */
79 void delay_short(volatile unsigned int n)
80 {
81 while(n--){}
82 }
83 
84 /*
85 * @description : 延时函数,在 396Mhz 的主频下延时时间大约为 1ms
86 * @param - n : 要延时的 ms 数
87 * @return : 无
88 */
89 void delay(volatile unsigned int n)
90 {
91 while(n--)
92 {
93 delay_short(0x7ff);
94 }
95 }
96 
97 /*
98 * @description : main 函数
99 * @param : 无
100 * @return : 无
101 */
102 int main(void)
103 {
104 clk_enable(); /* 使能所有的时钟 */
105 led_init(); /* 初始化 led */
106
107 while(1) /* 死循环 */
108 { 
109 led_off(); /* 关闭 LED */
110 delay(500); /* 延时大约 500ms */
111
112 led_on(); /* 打开 LED */
113 delay(500); /* 延时大约 500ms */
114 }
115
116 return 0;
117 }

四,编译下载验证

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 正点原子 Linux C 应用编程是一门面向 Linux 系统的 C 语言编程课程,课程内容涵盖 Linux 系统编程、TCP/IP 网络编程、多线程编程、音视频编解码、QT 编程等多个方面,旨在培养学员在 Linux 环境下进行应用开发的能力。 该课程由正点原子教育推出,以实践为主,理论与实践相结合的方式来进行教学。学员们将通过丰富的示例编程、实验和课堂讲解等来深入了解和掌握 Linux C 应用编程。 在 Linux C 应用编程课程中,学员将学习 Linux 系统编程的基础知识和主要的系统调用,使其熟悉 Linux 系统下的文件操作、进程管理、内存映射、信号处理等编程任务。学员还将学习 TCP/IP 网络编程,包括套接字编程、Socket 编程、网络通信等内容。此外,学员还将深入学习多线程编程、音视频编解码和 QT 编程等方面,以便快速实现各种应用程序的开发。 总之,正点原子 Linux C 应用编程课程是一门全方位、全面深入的 Linux 系统下 C 语言编程课程,为学员提供了开展 Linux 应用开发的必备技能和丰富经验。无论是在 Linux 服务器端还是在嵌入式 Linux 系统中,学员都能够通过该课程的学习获得更多的应用编程知识和实战经验。 ### 回答2: 正点原子 Linux C应用编程是一个涉及到嵌入式操作系统和C语言学习课程。通过本课程的学习,可以掌握如何在Linux操作系统下进行C语言应用程序开发,并具备在嵌入式系统上操作 Linux 的能力。Linux是一种广泛应用于服务器和嵌入式系统中的操作系统。具有自由、开放源代码、稳定、安全等特点,Linux越来越受到人们的关注。 本课程的内容分为基础篇和高级篇两部分。基础篇主要讲解Linux系统相关概念,如文件系统、进程、终端等,以及基本的C语言语法和编程技巧,例如变量、运算符、循环、条件语句、函数等。高级篇则介绍Linux下的网络编程、进程间通信、多线程编程、设备驱动程序等内容,更加深入Linux C应用程序开发中的技术细节。 本课程不仅提供了理论知识的讲解,还包括实际应用案例和编程练习,学员可以通过实践,不断提高自己在嵌入式 Linux C应用编程方面的能力。通过学习本课程,可以为嵌入式系统开发和实际项目应用打下坚实的基础。 总之,正点原子 Linux C应用编程是一门非常实用的课程,对于想要深入了解嵌入式Linux系统和C语言应用开发的人来说是必修的课程,能够提升自己在嵌入式领域的技能和竞争力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值