IMX6ull裸机bsp_led小实验

imx6ull Led_bsp

1. 开发环境及工具

linux环境下vscode + 交叉编译工具(主要生成目标环境下可运行的文件)+ cmake

2.需求

  • 闪烁

3.原理

在这里插入图片描述

​ 可以看出,LED0 接到了 GPIO_3 上,GPIO_3 就是 GPIO1_IO03,当 GPIO1_IO03输出低电平(0)的时候发光二极管 LED0 就会导通点亮,当 GPIO1_IO03 输出高电平(1)的时候发光二极管 LED0 不会导通,因此 LED0 也就不会点亮。所以 LED0 的亮灭取决于 GPIO1_IO03的输出电平,输出 0 就亮,输出 1 就灭。

打开imx6ull芯片参考手册的第28章详细描述了GPIO的功能,原文如下

28.4.1 GPIO Function
A GPIO signal can operate as a general-purpose input/output when the IOMUX is set to
GPIO mode. Each GPIO signal may be independently configured as either an input or an
output using the GPIO direction register (GPIO_GDIR).
When configured as an output (GPIO_GDIR bit = 1), the value in the data bit in the
GPIO data register (GPIO_DR) is driven on the corresponding GPIO line. When a signal
is configured as an input (GPIO_GDIR bit = 0), the state of the input can be read from
the corresponding GPIO_PSR bit.
当IOMUX设置为GPIO模式时,GPIO信号可以作为通用输入/输出。使用GPIO方向寄存器(GPIO_GDIR),每个GPIO信号可
以独立地配置为输入或输出。当配置为输出(GPIO_GDIR位= 1)时,GPIO数据寄存器(GPIO_DR)中数据位的值在对应的
GPIO线路上驱动。当一个信号被配置为输入时(GPIO_GDIR位= 0),输入的状态可以从对应的GPIO_PSR位读取。

​ 在GPIO Programming章节描述了如何配置GPIO功能,我们只需要输出模式功能,原文如下

28.4.3.2 GPIO Write Mode
The programming sequence for driving output signals should be as follows:
1. Configure IOMUX to select GPIO mode (Via IOMUXC), also enable SION if need
to read loopback pad value through PSR
2. Configure GPIO direction register to output (GPIO_GDIR[GDIR] set to 1b).
3. Write value to data register (GPIO_DR).
28.4.3.2 GPIO写模式驱动输出信号的编程顺序如下。
- 配置IOMUX选择GPIO模式(通过IOMUXC),如果需要通过PSR读取环回pad值,也可以启用SION。

- 配置GPIO方向寄存器为输出(GPIO_GDIR[GDIR]设置为1b)。

- 将值写入数据寄存器(GPIO_DR)。

​ 从手册描述的步骤来看需要配置对应的寄存器实现输出功能。

  • 第一步通过IOMUX(io复用)对应的寄存器将GPIO1_IO03引脚配置为GPIO功能。
    在这里插入图片描述
    ​ 在手册上找到IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 字段描述。可以看到只需将该寄存器的0到3bit的值写为5就可以配置为GPIO模式其它的保持默认值即可。
    在这里插入图片描述

    可以从内存映射表中找到对应寄存器的地址为(0x020E0068)。

    • 第二步配置GPIO方向寄存器为输出(GPIO_GDIR[GDIR]设置为1b)。
      在这里插入图片描述
      将GPIO1的GDIR寄存器的值写为1即是输出模式。
      在这里插入图片描述
      可以从内存映射表中找到对应寄存器的地址为(0x0209C004)。

    • 第三步将值写入数据寄存器(GPIO_DR)。
      在这里插入图片描述
      向DR寄存器的第3bit写0或者1就可以实现灯的亮灭了。

    注意:必须将I/O多路复用器配置为GPIO模式,GPIO_DR值才能与信号连接。在禁用输入路径的情况下读取数据寄存器总是
    返回一个零值。
    

    可以从内存映射表中找到对应寄存器的地址为(0x0209C000)。

4.代码编写

本来还有时钟初始化,但imx6ull内部boot程序已经默认初始化了。

创建bsp_led_reg.h用来设置对应寄存器的定义。

#ifndef _BSP_LED_REG_H
#define _BSP_LED_REG_H

/*GPIO相关寄存器*/

/*第一种写法*/
#define  GPIO1_Base                                   0x0209C000
#define  GPIO1_DR         *((volatile unsigned int *) (GPIO1_Base+0) )
#define  GPIO1_DIR        *((volatile unsigned int *) (GPIO1_Base+4) )

/*第二种写法*/
typedef struct bsp_led_reg
{
    /* data */
   volatile unsigned int  DR;
   volatile unsigned int  DIR;
}GPIO_Type;
#define  GPIO1              ((GPIO_Type *)GPIO1_Base)

/*GPIO复用相关寄存器*/
#define  IOMUXC_GPIO1_IO03    *((volatile unsigned int *) (0x020E0068))

#endif

创建bsp_led.h用来设置对应接口函数的定义。

#ifndef __BSP_LED_H
#define __BSP_LED_H

#include"bsp_led_reg.h"
#include"bsp_delay.h"
void led_init(void);
void led_on(void);
void led_off(void);
void led_blink(volatile unsigned int sec); //闪烁

#endif // !__BSP_LED_H

创建bsp_led.c用来设置对应接口函数的实现。

#include "bsp_led.h"
/*
 * @description	: 初始化LED对应的GPIO
 * @param 		: 无
 * @return 		: 无
 */
void led_init(void)
{
	/* 1、初始化IO复用 */
	IOMUXC_GPIO1_IO03 |= (5<<0);		/* 复用为GPIO1_IO03 */

	/* 2、初始化GPIO,设置GPIO1_IO03设置为输出  */
	GPIO1_DIR |= (1 << 3);	
	
	/* 3、设置GPIO1_IO03输出低电平,打开LED0 */
	GPIO1_DR &= ~(1 << 3);			
}

/*
 * @description	: 打开LED灯
 * @param 		: 无
 * @return 		: 无
 */
void led_on(void)
{
	/* 将GPIO1_DR的bit3清零 	*/
	GPIO1->DR &= ~(1<<3); 
}

/*
 * @description	: 关闭LED灯
 * @param 		: 无
 * @return 		: 无
 */
void led_off(void)
{
	/* 将GPIO1_DR的bit3置1 */
	GPIO1->DR |= (1<<3); 
}
void led_blink(volatile unsigned int sec)
{
	led_off();		/* 关闭LED 	*/
	Delay(sec);		/* 延时ms 	*/
	led_on();		/* 打开LED 	*/
	Delay(sec);		/* 延时ms 	*/
}

start.S文件

.global _Main  		/* 全局标号 */
/*
 * 描述:	_start函数,程序从此函数开始执行,此函数主要功能是设置C
 *		 运行环境。
 */
    .syntax unified
    .arch armv7-a
    .section ._Main, "start"
_Main:
	/* 进入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中 					*/

    /*
    清除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    /* 设置栈指针在ddr范围内(不和其他段重复)即可			 */
	b main				  /* 跳转到main函数 		 */

imx6ull.ld文件

ENTRY(_Main)
SECTIONS{
    /*代码段*/
    . = 0x80002000;
    .text : 
    {
      KEEP(*(._Main)) /*程序运行入口0x80002000*/
      *(.text)
    } 
    .rodata ALIGN(4) : {*(.rodata*)}
    .data ALIGN(4) : {*(.data)}
    /*未初始化段*/
    .bss :
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(COMMON)
        . = ALIGN(4);
        __bss_end__ = .;
    } 
}

​ armgcc.camke文件

INCLUDE(CMakeForceCompiler)

# EXECUTABLE EXTENSION
SET (CMAKE_EXECUTABLE_SUFFIX ".elf")

# TOOLCHAIN_DIR AND NANO LIBRARY
SET(TOOLCHAIN_DIR $ENV{ARMGCC_DIR})
STRING(REGEX REPLACE "\\\\" "/" TOOLCHAIcdN_DIR "${TOOLCHAIN_DIR}")

IF(NOT TOOLCHAIN_DIR)
    MESSAGE(FATAL_ERROR "***Please set ARMGCC_DIR in envionment variables***")
ENDIF()

MESSAGE(STATUS "TOOLCHAIN_DIR: " ${TOOLCHAIN_DIR})

# TARGET_TRIPLET
SET(TARGET_TRIPLET "arm-none-eabi")

SET(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_DIR}/bin)
SET(TOOLCHAIN_INC_DIR ${TOOLCHAIN_DIR}/${TARGET_TRIPLET}/include)
SET(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_DIR}/${TARGET_TRIPLET}/lib)

SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_PROCESSOR arm)

CMAKE_FORCE_C_COMPILER(${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-gcc${TOOLCHAIN_EXT} GNU)
CMAKE_FORCE_CXX_COMPILER(${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-g++${TOOLCHAIN_EXT} GNU)
SET(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-gcc${TOOLCHAIN_EXT})

SET(CMAKE_OBJCOPY ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-objcopy CACHE INTERNAL "objcopy tool")
SET(CMAKE_OBJDUMP ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-objdump CACHE INTERNAL "objdump tool")

SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g" CACHE INTERNAL "c compiler flags debug")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g" CACHE INTERNAL "cxx compiler flags debug")
SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -g" CACHE INTERNAL "asm compiler flags debug")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE INTERNAL "linker flags debug")


SET(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR}/${TARGET_TRIPLET} ${EXTRA_FIND_PATH})
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

​ CMakeLists.txt文件

INCLUDE(CMakeForceCompiler)
# CROSS COMPILER SETTING
SET(CMAKE_SYSTEM_NAME Generic)
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
# ENABLE ASM
ENABLE_LANGUAGE(ASM)

# CURRENT DIRECTORY
SET(ProjDirPath "/home/user/testlinux/board_dirves/cmake_led")

SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -Wall")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -Wall")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} --specs=nosys.specs")

include_directories(${ProjDirPath}/bsp/delay)

include_directories(${ProjDirPath}/bsp/led)

include_directories(${ProjDirPath}/imx6u)

add_executable(ledc.elf 
"${ProjDirPath}/project/start.S"
"${ProjDirPath}/project/main.c"
"${ProjDirPath}/bsp/delay/bsp_delay.h"
"${ProjDirPath}/bsp/delay/bsp_delay.c"
"${ProjDirPath}/bsp/led/bsp_led_reg.h"
"${ProjDirPath}/bsp/led/bsp_led.h"
"${ProjDirPath}/bsp/led/bsp_led.c"
)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -T${ProjDirPath}/imx6ull.ld -static")
message(WARNING   "this is : ${CMAKE_EXE_LINKER_FLAGS_DEBUG}")

ADD_CUSTOM_COMMAND(TARGET ledc.elf POST_BUILD COMMAND ${CMAKE_OBJCOPY}
-Obinary ${EXECUTABLE_OUTPUT_PATH}/ledc.elf ${EXECUTABLE_OUTPUT_PATH}/ledc.bin)

4.1工程结构

在这里插入图片描述

5.效果

ledc

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值