【ARM 裸机】C 语言 led 驱动

前面刚学习了汇编 led 驱动的编写和验证,现在开始就要进入 C 语言 led 驱动编写与验证了 !

1、C 语言运行环境构建

1.1、设置处理器模式

使 6ULL 处于 SVC 模式下,之前已经提到了处理器的九种模式,参考:【ARM 裸机】汇编 led 驱动之基本语法,如何设置成 SVC 模式,需要用到 CPSR 寄存器,CPSR 寄存器一共是 32 位,关注它的第 0~4 位,也就是设置为 M[4:0] 为 10011 = 0x13;
在这里插入图片描述
在这里插入图片描述
读写状态寄存器需要用到 MRS 和 MSR 指令,不能使用 LDR 和 STR 指令来对状态寄存器读写了;
在这里插入图片描述

1.2、设置 sp 指针

sp 指针可以指向内部 RAM,也可以指向 DDR,这里设置成指向 DDR,sp 设置到哪里?以正点原子开发板为例,512 MB 的范围是 0x80000000~0x9FFFFFFF,假定设置的栈的大小是 2 MB(0x20000),A7 的栈增长方式为向下增长,所以要设置成 sp 指针指向 0x80200000;

1.3、汇编跳转到 C 语言

使用 b 指令跳转到 C 语言的函数,比如 main 函数;

2、驱动编写

在 /home/zsw/linux/IMX6ULL/board_drivers 目录下新建一个 2_ledc 的目录,打开 VScode,在 VScode 中打开文件夹 2_ledc,然后将工作区另存为 ledc,然后新建文件 start.s、main.c、main.h、Makefile 这四个文件;
在这里插入图片描述
start.s

.global _start_start:// 设置处理器为 SVC 模式mrs r0, cpsr        // 读取 cpsr 到 r0bic r0, r0, #0x1f   // r0 & ~0x1f 清除 cpsr 的 bit4~0    bic  位清除指令orr r0, r0, #0x13   // r0 | 0x13 设置成 SVC 模式      orr 按位或msr cpsr, r0        // 把 r0 写入 cpsr// 设置 sp 指针ldr sp, =0x80200000// 跳转到 c 语言b main  

main.c

#include "main.h"// 使能外设时钟
void clk_enable(void)
{CCM_CCGR0 = 0xffffffff;CCM_CCGR1 = 0xffffffff;CCM_CCGR2 = 0xffffffff;CCM_CCGR3 = 0xffffffff;CCM_CCGR4 = 0xffffffff;CCM_CCGR5 = 0xffffffff;CCM_CCGR6 = 0xffffffff;
}
// 初始化 led
void led_init(void)
{SW_MUX_GPIO1_IO03 = 0x5;   // 复用为 GPIO1_IO03SW_PAD_GPIO1_IO03 = 0x10b0;   // 配置电气属性// GPIO 初始化GPIO1_GDIR = 0x8;   // 设置为输出GPIO1_DR = 0x0;   // 打开 led
}
// 短延时
void delay_short(volatile unsigned int n)
{while(n--){}
}
// 长延时,在 396MHz 下一次循环大概 1 ms
void delay_ms(volatile unsigned int n)
{while(n--){delay_short(0x7ff);}
}   
// 打开 led
void led_on(void)
{GPIO1_DR &= ~(1<<3);   // bit3 清零
}
// 关闭 led
void led_off(void)
{GPIO1_DR |= (1<<3);   // bit3 置1
}
int main(void)
{clk_enable();led_init();// led 闪烁while (1){led_on();delay_ms(500);led_off();delay_ms(500);}return 0; 
}

main.h

#ifndef __MAIN_H
#define __MAIN_H// 定义要使用的寄存器// CCM相关寄存器地址
#define CCM_CCGR0           *((volatile unsigned int *)0x020c4068)
#define CCM_CCGR1           *((volatile unsigned int *)0x020c406c)
#define CCM_CCGR2           *((volatile unsigned int *)0x020c4070)
#define CCM_CCGR3  			*((volatile unsigned int *)0x020c4074)
#define CCM_CCGR4 			*((volatile unsigned int *)0x020c4078)
#define CCM_CCGR5 			*((volatile unsigned int *)0x020c407c)
#define CCM_CCGR6 			*((volatile unsigned int *)0x020c4080)// IOMUX相关寄存器地址 
#define SW_MUX_GPIO1_IO03 	*((volatile unsigned int *)0x020e0068)
#define SW_PAD_GPIO1_IO03 	*((volatile unsigned int *)0x020e02f4)// GPIO1相关寄存器地址 
#define GPIO1_DR 			*((volatile unsigned int *)0x0209c000)
#define GPIO1_GDIR 			*((volatile unsigned int *)0x0209c004)#endif

Makefile

objs = main.o start.oledc.bin: $(objs)arm-linux-gnueabihf-ld -Ttext 0x87800000 start.o main.o -o ledc.elfarm-linux-gnueabihf-objcopy -O binary -S ledc.elf ledc.binarm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis%.o: %.carm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<%.o: %.sarm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<clean:rm -rf *.o ledc.bin ledc.elf ledc.dis

3、烧写验证

在这里插入图片描述

I.MX6ULL_MINI_ledc


演示视频中可以看到 led 每隔 500 ms 闪烁,到这里也就基本结束了本节的内容,但是还要补充一点: 链接脚本,在 Makefile 中,我们使用了下面这行代码,

	arm-linux-gnueabihf-ld -Ttext 0x87800000 start.o main.o -o ledc.elf

上面的语句中我们是通过“-Ttext”来指定链接地址是 0X87800000 的,这样的话所有的文件都会链接到以 0X87800000 为起始地址的区域,看名字就知道链接脚本主要用于链接的,用于描述文件应该如何被链接在一起形成最终的可执行文件,其主要目的是描述输入文件中的段如何被映射到输出文件中,并且控制输出文件中的内存排布,最简单的链接脚本可以只包含一个命“SECTIONS”,我们可以在这一个“SECTIONS”里面来描述输出文件的内存布局。我们一般编译出来的代码都包含在 text、data、bss 和 rodata 这四个段内;
下新建一个名为“imx6u.lds”的文件,然后在此文件里面输入如下所示代码,

SECTIONS{. = 0X87800000;.text :{start.o main.o *(.text)}.rodata ALIGN(4) : {*(.rodata*)} .data ALIGN(4) : { *(.data) } __bss_start = .; .bss ALIGN(4) : { *(.bss) *(COMMON) } __bss_end = .;
}

第 2 行设置定位计数器为 0X87800000,因为我们的链接地址就是0X87800000;第5行设置链接到开始位置的文件为start.o,因为 start.o 里面包含着第一个要执行的指令,所以一定要链接到最开始的地方;第 6 行是 main.o 这个文件,其实可以不用写出来,因为 main.o 的位置就无所谓了,可以由编译器自行决定链接位置;在第 11、13 行有“__bss_start”和“__bss_end”这两个东西?这个是什么呢?“__bss_start”和“__bss_end”是符号,第 11、13 这两行其实就是对这两个符号进行赋值,其值为定位符“.”,这两个符号用来保存.bss 段的起始地址和结束地址。前面说了.bss 段是定义了但是没有被初始化的变量,我们需要手动对.bss 段的变量清零的,因此我们需要知道.bss 段的起始和结束地址,这样我们直接对这段内存赋 0 即可完成清零。通过第 11、13 行代码,.bss 段的起始地址和结束地址就保存在了“__bss_start”和“__bss_end”中,我们就可以直接在汇编或者 C 文件里面使用这两个符号,修改 Makefile 中的这一行,

	arm-linux-gnueabihf-ld -Timx6u.lds -o ledc.elf

在这里插入图片描述
我们可以查看反汇编文件中的信息,链接脚本没啥问题;
在这里插入图片描述
现在重新编译工程,烧写验证结果是正确的,总结一下,本节从设置处理器模式开始,然后设置 sp 指针,跳转到 C 语言的 main,在 Makefile 中使用了变量,模式规则,自动化变量,最后还引入了链接脚本,东西比较多,需要时间去理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/641403.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

虚拟机中安装的CentOS7的桌面右上角没有网络图标解决方案

问题描述 今天在打开CentOS7后&#xff0c;发现右上角的网络图标不见了&#xff0c;然后命令行访问百度也不通。然后上网查了一些解决方法。 原因分析及解决方案&#xff1a; 上网查了许多解决方法&#xff0c;其中一种成功解决了我的问题&#xff1b;我的是配置文件的问题。…

大模型Agent几种常见的架构设计模式

▼最近直播超级多&#xff0c;预约保你有收获 架构设计模式已成为程序员的重要技能。在大模型 Agent 智能体应用领域&#xff0c; 同样需要架构设计模式来支撑大模型应用在企业中规模的落地。 根据多年的架构设计经验&#xff0c;我在这里整理总结了一些针对大模型应用的设计方…

AI大模型探索之路-认知篇3:大语言模型微调基础认知

文章目录 前言一、微调技术概述二、微调的必要性三、大模型的微调方法四、微调过程中的技术细节五、微调后的模型评估与应用总结 前言 在人工智能的广阔研究领域内&#xff0c;大型预训练语言模型&#xff08;Large Language Models, LLMs&#xff09;已经成为推动技术革新的关…

如何训练一个大语言模型(LLMs)

目录 前言大语言模型 Vs机器学习模型训练过程步骤1&#xff1a;数据策划&#xff08;Data Curation)步骤2&#xff1a;格式化与预处理步骤3&#xff1a;训练模型步骤4&#xff1a;模型评估 LLM Leaderboard[LLM Leaderboard 2024](https://www.vellum.ai/llm-leaderboard)[Open…

crmeb的分销推广如何用

CRMBE分销推广说明 1、CRMEB分销模式 分销模式&#xff1a; 指定分销、人人分销、满额分销 指定分销&#xff1a; 用户默认无分销权限&#xff0c;需要后台开通分销权限后&#xff0c;才可以通过推广下级获得返佣&#xff1b; 人人分销&#xff1a; 用户在商城注册后自动获得分…

javaScript中的执行栈和执行上下文

执行上下文 执行上下文&#xff0c;英文全称为 Execution Context&#xff0c;一句话概括就是“代码&#xff08;全局代码、函数代码&#xff09;执行前进行的准备工作”&#xff0c;也称之为“执行上下文环境”。 运行JavaScript代码&#xff0c;当代码执行进入一个环境时&a…

COZY: Stylized Weather 3

远离枯燥的现实主义,一个精美手工制作的程式化天气系统。 从一天中的不同时间到一年中的不同季节,从蓬松的云朵到狂风暴雨,从晴朗的日子到浓雾弥漫,COZY都能轻松做到! ✅ 3.0中的新功能 HDRP支持 物理上精确的月球系统 8K 星形纹理 新的豪华云风格融合了纹理,创造出高性…

Facebook的区块链应用深度分析

去中心化身份验证的意义 在当今数字化社会中&#xff0c;身份验证的重要性不言而喻。对于Facebook这样的大型社交媒体平台来说&#xff0c;确保用户的身份真实性和数据的安全性是至关重要的。传统的中心化身份验证方式存在一定的安全风险和可信性问题&#xff0c;而去中心化身…

5款小伙伴们私信推荐免费软件

​ 最近后台收到好多小伙伴的私信&#xff0c;今天继续推荐五款小工具&#xff0c;都是免费使用的&#xff0c;大家可以去试试看。 1. 数据恢复工具——EaseUS Data ​ EaseUS Data是一款高效的数据恢复软件&#xff0c;能够恢复因各种原因丢失的文件&#xff0c;如误删除、格…

Redis入门到通关之数据结构解析-ZipList

文章目录 ☃️概述☃️ZipListEntry☃️Encoding编码☃️ZipList的连锁更新问题☃️总结 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间与…

街子智勇传媒,盼你知错即改

今天本“人民体验官”推荐人民日报官方微博文化产品《请相信&#xff1a;读书是通向世界最好的路》。 图&#xff1a;来源“人民体验官”推广平台 “不读书&#xff0c;天地辽阔内心犹在井底。”这话说得入木三分&#xff01; 这话让笔者立即联想到自己最近发表的戏作打油诗《…

RF高频腔设计(6)

为了在最小功率损耗的情况下得到最大的加速电压&#xff0c;我们需要最大化分路阻抗&#xff08;shunt impedance&#xff09;。 由公式 R ( R Q ) Q R\left(\frac{R}{Q}\right)Q R(QR​)Q 可知道&#xff0c;如果增加分路阻抗的大小&#xff0c;可以通过提高Q&#xff0c;或…