当前位置:网站首页>I.MX6U-ALPHA开发板(C语言版本LED驱动实验)
I.MX6U-ALPHA开发板(C语言版本LED驱动实验)
2022-07-04 03:52:00 【*﹏ℳ๓无情*】
一、C语言运行环境测试
.global _start /* 全局标号 */
_start:
/* 进入SVC模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4*/
orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式*/
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中*/
ldr sp, =0X80200000 /* 设置栈指针*/
b main /* 跳转到main函数 */
一、设置处理器模式
设置6ULL处于SVC模式 下。设置CPSR寄存器的bit4-0,也就是M[4:0]为10011=0X13。读写状态寄存器需要用到MRS和MSR指令。MRS将CPSR寄存器数据读出到通用寄存器里面,MSR指令将通用寄存器的值写入到CPSR寄存器里面去。
二、设置sp指针
Sp可以指向内部RAM,也可以指向DDR,我们将其指向DDR。Sp设置到哪里?512MB的范围0x80000000~0x9FFFFFFF。栈大小,0x200000=2MB。处理器栈增长方式,对于A7而言是向下增长的。设置sp指向0x80200000。
三、跳转到C语言
使用b指令,跳转到C语言函数,比如main函数。
二、软件编写
#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)
#define GPIO1_PSR *((volatile unsigned int *)0X0209C008)
#define GPIO1_ICR1 *((volatile unsigned int *)0X0209C00C)
#define GPIO1_ICR2 *((volatile unsigned int *)0X0209C010)
#define GPIO1_IMR *((volatile unsigned int *)0X0209C014)
#define GPIO1_ISR *((volatile unsigned int *)0X0209C018)
#define GPIO1_EDGE_SEL *((volatile unsigned int *)0X0209C01C)
#endif
#include "main.h"
/*使能外设时钟*/
void clk_enable(void)
{
CCM_CCGR1 = 0xFFFFFFFF;
CCM_CCGR2 = 0xFFFFFFFF;
CCM_CCGR3 = 0xFFFFFFFF;
CCM_CCGR4 = 0xFFFFFFFF;
CCM_CCGR5 = 0xFFFFFFFF;
CCM_CCGR6 = 0xFFFFFFFF;
}
/*初始化LED*/
void led_init(void)
{
SW_PAD_GPIO1_IO03 = 0x5;/*复用为GPIO1-IO03*/
SW_PAD_GPIO1_IO03 = 0x10B0;/*设置GPIO1——IO03电气属性*/
/*GPIO初始化*/
GPIO1_GDIR = 0x8;/*设置为输出*/
GPIO1_DR = 0x0;/*打开LED灯*/
}
/*短延时*/
void delay_short(volatile unsigned int n)
{
while(n--){
}
}
void delay(volatile unsigned int n)
{
while(n--)
{
delay_short(0x77f); //1毫秒(396MHZ)
}
}
void led_on(void)
{
GPIO1_DR &= ~(1<<3);
}
void led_off(void)
{
GPIO1_DR |= (1<<3);
}
int main(void)
{
clk_enable();
led_init();
while(1)
{
led_on();
delay(500);
led_off();
delay(500);
}
return 0;
}
三、链接脚本
链接脚本描述了要连接的文件,以及链接顺序,和链接首地址
链接脚本的语法很简单,就是编写一系列的命令,这些命令组成了链接脚本,每个命令是一个带有参数的关键字或者一个对符号的赋值,可以使用分号分隔命令。像文件名之类的字符串可以直接键入,也可以使用通配符“*”。最简单的链接脚本可以只包含一个命令“SECTIONS”,我们可以在这一个“SECTIONS”里面来描述输出文件的内存布局。我们一般编译出来的代码都包含在 text、data、bss 和 rodata 这四个段内,
我们本试验的链接脚本要求如下:
①、链接起始地址为 0X87800000
②、start.o 要被链接到最开始的地方,因为 start.o 里面包含这第一个要执行的命令
根据要求,在 Makefile 同目录下新建一个名为“imx6ul.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 = .;
}
第 1 行我们先写了一个关键字“SECTIONS”,后面跟了一个大括号,这个大括号和第14行的大括号是一对,这是必须的。看起来就跟 C 语言里面的函数一样。
第 2 行对一个特殊符号“.”进行赋值,“.”在链接脚本里面叫做定位计数器,默认的定位计数器为 0。我们要求代码链接到以 0X87800000为起始地址的地方,因此这一行给“.”赋值0X87800000,表示以0X87800000开始,后面的文件或者段都会以0X87800000为起始地址开始链接。
第 3 行的“.text”是段名,后面的冒号是语法要求,冒号后面的大括号里面可以填上要链接到“.text”这个段里面的所有文件,“(.text)”中的“”是通配符,表示所有输入文件的.text段都放到“.text”中。
第5行设置链接到开始位置的文件为start.o,因为 start.o 里面包含着第一个要执行的指令,所以一定要链接到最开始的地方。第 6 行是 main.o这个文件,其实可以不用写出来,因为 main.o 的位置就无所谓了,可以由编译器自行决定链接位置。
第10行定义了一个名为“.data”的段,然后所有文件的“.data”段都放到这里面。ALIGN(4)是用来对“.data”这个段的起
始地址做字节对齐的,ALIGN(4)表示 4 字节对齐。也就是说段“.data”的起始地址要能被 4 整除,一般常见的都是 ALIGN(4)或者 ALIGN(8),也就是 4 字节或者 8 字节对齐。
在第 11、13 行的__bss_start
和__bss_end
是符号,第 11、13 这两行其实就是对这两个符号进行赋值,其值为定位符“.”,这两个符号用来保存.bss 段的起始地址和结束地址。.bss 段是定义了但是没有被初始化的变量,我们需要手动对.bss 段的变量清零的,因此我们需要知道.bss 段的起始和结束地址,这样我们直接对这段内存赋 0 即可完成清零。通过第 11、13 行代码,.bss 段的起始地址和结束地址就保存在了__bss_start
和__bss_end
中,我们就可以直接在汇编或者C 文件里面使用这两个符号。
执行后LED闪动
边栏推荐
- leetcode 121 Best Time to Buy and Sell Stock 买卖股票的最佳时机(简单)
- Ppt tutorial, how to save a presentation as a PDF file in PowerPoint?
- Lnk2038 detected a mismatch of "runtimelibrary": the value "md_dynamicrelease" does not match the value "mdd_dynamicdebug" (in main.obj)
- STM32外接DHT11显示温湿度
- ctf-pikachu-XSS
- 【微服务|openfeign】@FeignClient详解
- Unity 绘制弹球和台球的运动轨迹
- 2021 RSC | Drug–target affinity prediction using graph neural network and contact maps
- vim映射命令
- Unity draws the trajectory of pinball and billiards
猜你喜欢
What does software testing do? Find defects and improve the quality of software
毕业设计:设计秒杀电商系统
Flink learning 8: data consistency
[microservice openfeign] @feignclient detailed explanation
仿《游戏鸟》源码 手游发号评测开服开测合集专区游戏下载网站模板
How to telecommute more efficiently | community essay solicitation
【CSRF-01】跨站请求伪造漏洞基础原理及攻防
leetcode刷题:二叉树08(N叉树的最大深度)
北漂程序员,月薪20K,一年攒15W,正常吗?
dried food! Generation of rare samples based on GaN
随机推荐
北漂程序员,月薪20K,一年攒15W,正常吗?
JS realizes the effect of text scrolling marquee
Idea configuration 360zip open by default -- external tools
01 QEMU starts the compiled image vfs: unable to mount root FS on unknown block (0,0)
leetcode刷题:二叉树07(二叉树的最大深度)
02 specific implementation of LS command
Myslq delete followed by limit
UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0x98 in position 1093: illegal multibyte sequence
软件测试是干什么的 发现缺陷错误,提高软件的质量
[webrtc] M98 Ninja build and compile instructions
How to telecommute more efficiently | community essay solicitation
Global exposure and roller shutter exposure of industrial cameras
Distributed system: what, why, how
Unity 绘制弹球和台球的运动轨迹
思考的小记录
SDP中的SPA
The interactive solution of JS and app in the H5 page embedded in app (parameters can be transferred and callbacks can be made)
干货!基于GAN的稀有样本生成
Idea modify body color
资深开发人员告诉你,怎样编写出优秀的代码?