嵌入式Linux学习历程 — NXP官方SDK使用实验

NXP官方SDK使用实验

NXP官方为I.MX6ULL编写了SDK包(I.MX6UL也可使用),其中有NXP已经编写好的寄存器定义文件。

I.MX6ULL的SDK包在NXP官网下载
在这里插入图片描述
在安装好的文件中,我们只需要fsl_common.h、fsl_iomuxc.h、MCIMX6Y2.h这三个文件。

同时需要一个新头文件,用于存放一些SDK库文件需要使用到的数据类型
cc.h

#ifndef __CC_H
#define __CC_H

#define __I     volatile
#define __O     volatile
#define __IO    volatile

typedef signed   char          int8_t;
typedef signed   short         int16_t;
typedef signed   int           int32_t;
typedef unsigned char          uint8_t;
typedef unsigned short         uint16_t;
typedef unsigned int           uint32_t;
typedef unsigned long long     uint64_t;

typedef signed   char          s8;
typedef signed   short         s16;
typedef signed   int           s32;
typedef signed   long long     s64;
typedef unsigned char          u8;
typedef unsigned short         u16;
typedef unsigned int           u32;
typedef unsigned long long     u64;



#endif 

汇编文件
start.S

.global _start      /* 全局标量 */

.global _bss_start
_bss_start:
    .word __bss_start

.global _bss_end
_bss_end:
    .word __bss_end

/*
    描述: _start函数,程序从此函数开始执行,此函数主要功能是设置C运行环境

 */
_start:

    /* 进入SVC模式 */
    mrs r0, cpsr       // 读取cpsr的数据到r0
    bic r0, r0, #0X1F  // 将r0的低五位清零,即cpsr的M0-M4
    orr r0, r0, #0X13  // r0或上0x13,表示使用SVC模式
    msr cpsr, r0       // 将r0的数据写入到cpsr_c中

    /* 清除BSS段 */
    ldr r0, _bss_start
    ldr r1, _bss_end
    mov r2, #0

bss_loop:
    stmia r0!, {r2}
    cmp r0, r1             //比较r0和r1里面的数值
    ble bss_loop           //如果r0地址小于等于r1,继续清除bss段

    ldr sp, = 0X80200000  // 设置栈指针
    b main                // 跳转到C语言main函数


驱动文件:
main.c

#include "fsl_common.h"
#include "fsl_iomuxc.h"
#include "MCIMX6Y2.h"

/**********************************
* 函数名称: void clk_enable(void)
* 函数功能: 使能外设时钟
* 输入   : 无
* 输出   : 无
***********************************/
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;
}

/**********************************
* 函数名称: void LED_Init(void)
* 函数功能: 初始化LED
* 输入   : 无
* 输出   : 无
***********************************/
void LED_Init(void)
{
    /* 初始化IO复用,复用为GPIO1_IO03 */
    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0);

    /* 设置GPIO1——IO3 电气属性 */
    /***************************
     *bit 16:0 HYS关闭
	 *bit [15:14]: 00 默认下拉
     *bit [13]: 0 kepper功能
     *bit [12]: 1 pull/keeper使能
     *bit [11]: 0 关闭开路输出
     *bit [7:6]: 10 速度100Mhz
     *bit [5:3]: 110 R0/6驱动能力
     *bit [0]: 0 低转换率
    ****************************/
    IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0X10B0);

    /* 初始化GPIO,GPIO1_IO3设置为输出 */
    GPIO1 -> GDIR = 0X00000008;

    /* 设置GPIO1_IO3输出低电平,打开LED灯 */
    GPIO1 -> DR = 0X0;
    
}

/**********************************
* 函数名称: void delay_short(volatile unsigned int n)
* 函数功能: 短延时
* 输入   : volatile unsigned int n
* 输出   : 无
***********************************/
void delay_short(volatile unsigned int n)
{
    while(n--);
}

/**********************************
* 函数名称: void delay(volatile unsigned int n)
* 函数功能: 延时,在396Mhz主频下约1ms
* 输入   : volatile unsigned int n
* 输出   : 无
***********************************/
void delay(volatile unsigned int n)
{
    while(n--)
        delay_short(0X7FF);
}

/**********************************
* 函数名称: void LED_On(void)
* 函数功能: 打开LED灯
* 输入   : 无
* 输出   : 无
***********************************/
void LED_On(void)
{
    GPIO1 -> DR &= ~(1 << 3);  /* bit3清零 */
    /* 1 << 3: 
     *      1左移3位 0000 0001 --> 0000 1000
     * ~(1 << 3):
     *      ~(0000 1000) --> 1111 0111
     * GPIO1_DR &= ~(1 << 3) 即 将bit3清零
     */
}

/**********************************
* 函数名称: void LED_Off(void)
* 函数功能: 关闭LED灯
* 输入   : 无
* 输出   : 无
***********************************/
void LED_Off(void)
{
    GPIO1 -> DR |= (1 << 3);  /* bit3置1 */
}

int main(void)
{
    clk_enable();    /* 使能外设时钟 */
    LED_Init();      /* 初始化LED */

    while(1) 
    {
        LED_On();
        delay(500);
    
        LED_Off();
        delay(500);
    }

    return 0;
}


Makefile:

CROSS_COMPILE ?= arm-linux-gnueabihf-
NAME		  ?= ledc

CC 		:= $(CROSS_COMPILE)gcc
LD		:= $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump

OBJS 	:= start.o main.o

$(NAME).bin : $(OBJS)
	$(LD) -Timx6ull.lds -o $(NAME).elf $^
	$(OBJCOPY) -O binary -S $(NAME).elf $@
	$(OBJDUMP) -D -m arm $(NAME).elf > $(NAME).dis
	
%.o:%.S
	$(CC) -Wall -nostdlib -c -O2 -o $@ $<
	
%.o:%.c
	$(CC) -Wall -nostdlib -c -O2 -o $@ $<
	
clean:
	rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis
	

链接脚本:
imx6ull.lds

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

fsl_iomuxc.h中有两个用于设置IO的函数

IOMUXC_SetPinMux(uint32_t muxRegister,		    	//0x020E0068U
                 uint32_t muxMode,			    	//0x5U  用于设定MUX_MODE
                 uint32_t inputRegister,			//0x00000000U
                 uint32_t inputDaisy,				//0x0U
                 uint32_t configRegister,			//0x020E02F4U
                 //前五个用了一个宏(如IOMUXC_GPIO1_IO03_GPIO1_IO03)代替
                 //即 #define IOMUXC_GPIO1_IO03_GPIO1_IO03 0x020E0068U,0x5U,0x00000000U,0x0U,0x020E02F4U
                 uint32_t inputOnfield)		    	//0

IOMUXC_SetPinConfig(uint32_t muxRegister,		    //0x020E0068U
                 	uint32_t muxMode,			    //0x5U
                 	uint32_t inputRegister,			//0x00000000U
                 	uint32_t inputDaisy,			//0x0U
                 	uint32_t configRegister,		//0x020E02F4U
                 	//前五个用了一个宏(如IOMUXC_GPIO1_IO03_GPIO1_IO03)代替
                 	//即 #define IOMUXC_GPIO1_IO03_GPIO1_IO03 0x020E0068U,0x5U,0x00000000U,0x0U,0x020E02F4U
                    uint32_t configValue)    		//0x10B0  用于设置电气属性
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值