栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

I.MX6U-ALPHA开发板(C语言版本LED驱动实验)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

I.MX6U-ALPHA开发板(C语言版本LED驱动实验)

文章目录
  • 一、C语言运行环境测试
    • 一、设置处理器模式
    • 二、设置sp指针
    • 三、跳转到C语言
  • 二、软件编写
  • 三、链接脚本

一、C语言运行环境测试
.global _start  		

_start:
	
	mrs r0, cpsr
	bic r0, r0, #0x1f 	
	orr r0, r0, #0x13 	
	msr cpsr, r0		

	ldr sp, =0x80200000	
	b 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

#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)


#define SW_MUX_GPIO1_IO03 	*((volatile unsigned int *)0x020E0068)
#define SW_PAD_GPIO1_IO03 	*((volatile unsigned int *)0x020E02F4)


#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;
}


void led_init(void)
{
    SW_PAD_GPIO1_IO03 = 0x5;
    SW_PAD_GPIO1_IO03 = 0x10B0;

    
    GPIO1_GDIR = 0x8;
    GPIO1_DR = 0x0;
}


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闪动

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1000830.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号