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