二、点亮LED(GPIO控制)

二、点亮LED(GPIO控制)

文件状态:
[ ] 草稿
[ ] 正在修改
[ √ ] 正式发布
文件标识:
当前版本:V1.1
作 者:Skymixos
完成日期:2022年10月02日

版 本 历 史

版本/状态作者参与者起止日期备注
V1.0Skymixos2022年1月4日创建文件
V1.1Skymixos2022年1月22日修改文件格式,细化实验过程,完成定稿
V1.2Skymixos2022年02月22日修改编码实现部分的思维导图
V1.3Skymixos2022年02月23日修改文档结构

每日一句:千里之行,始于足下

1. 目的

  • 熟悉嵌入式开发的基本流程
  • 基本了解I.MX6ULL SoC
  • 熟悉I.MX6ULL的GPIO使用方法

2. 目标

  • 掌握ARM裸机程序开发流程(编写,编译,下载,调试)
  • 通过GPIO控制LED的亮灭

3. 嵌入式软件的执行流程

嵌入式设备开机上电后执行流程与PC对比:
在这里插入图片描述

设备上电后首先执行Bootloader(比如:BIOS,U-boot),Bootloader加载操作系统(比如:Windows,Linux,uCos等)到内存中执行。而应用程序往往在操作系统起来后被加载执行。目前写的裸机程序(点亮LED)在上述流程图中属于操作系统部分
在这里插入图片描述
Bootloader往往支持从FLASH,SD卡,USB,网卡等介质将Kernel加载到DDR中运行,为了调试方便

我们的目标程序(microx.bin)将由U-boot加载到DDR中执行(可以省去底层的初始化以及频繁的FLASH擦写)。

U-boot支持网络下载功能,我们只需要在服务器上开启tffp服务,就可以轻松的将程序下载到开发板上执行。

4. I.MX6ULL GPIO操作的理论基础

4.1 硬件连接

4.1.1 正点原子I.MX6U-MINI LED部分原理图

在这里插入图片描述

在这里插入图片描述

4.1.2 100ASK_IMX6ULL Pro LED部分原理图

在这里插入图片描述

4.1.3 100ASK_IMX6ULL Pro vs I.MX6U-MINI

开发板控制LED的GPIOGPIO组控制状态
I.MX6U-MINIGPIO1_IO03GPIO1* gpio输出低电平,点亮LED
* gpio输出高电平,熄灭LED
100ASK_IMX6ULL ProGPIO5_IO03GPIO5* gpio输出低电平,点亮LED
* gpio输出高电平,熄灭LED

4.2 GPIO理论基础

LED控制需要的理论基础知识涉及:复用引脚,时钟,GPIO操作。

详细分析见:i.MX6U/LL SoC

5. 软件设计

从aliyun服务器上克隆原始的项目工程并切换到dev_1.0分支:

$ git clone git@code.aliyun.com:luopinjing/microx.git
$ git checkout dev_1.0

在这里插入图片描述

5.1 目录结构

目录/文件名用途/含义备注
3rd_party存放一些第三方的开源库目前该目录只存放了一个内容为空的SConscript文件
bsp存放板级支持代码(这些代码一般参考官方实现)目前该目录只存放了一个内容为空的SConscript文件
driver存放microx系统的设备驱动代码目前该目录只存放了一个内容为空的SConscript文件
fs存放microx系统文件系统相关代码目前该目录只存放了一个内容为空的SConscript文件
include集中存放头文件
init存放初始化代码目前该目录只存放了一个内容为空的SConscript文件
kernel存放microx系统内核核心代码目前该目录只存放了一个内容为空的SConscript文件
lib存放microx系统使用库目前该目录只存放了一个内容为空的SConscript文件
prebuilt存放编译工具,kconfig工具等* gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf.tbz2
* Kconfiglib-master.zip
script存放编译脚本及配置* build_log.sh:shell脚本,实现log打印功能
* config.py:编译参数配置,被SConstruct使用
* gen_autoconf_header.py:python脚本,实现将.config转换为autoconf.h的功能
* imx6ull_defconfig:默认的编译配置
* Kconfiglib-master:开源工具,实现图形化配置功能
* build.sh:顶层build.sh的实现,控制整个项目的编译
* gen_autoconf.py:python脚本,实现将.config转换为autoconf.py的功能
* Kconfig
* microx.lds:链接脚本
shell存放microx系统mini shell代码目前该目录只存放了一个内容为空的SConscript文件
build.sh链接文件指向script下的build.sh
SConstruct顶层构建文件类似顶层Makefile功能
README项目说明及使用介绍
.git项目版本管理仓库
.gitignore用于记录无需版本管理的内容文件用来忽略被指定的文件或文件夹的改动,被记录在.gitignore文件里的文件或文件夹,是无法被git跟踪到的,即被忽略的文件是不会被放入到远程仓库里的

5.2 软件构件系统

在这里插入图片描述

5.2.1 Shell脚本

编译系统中含有两个Linux shell脚本文件:build.shbuild_log.sh

  • build_log.sh:实现编译菜单及脚本的日志打印功能
  • build.sh:控制整个项目的编译(包括:编译环境配置,编译,清除等)

Linux shell脚本编程的基础知识见:Linux Shell

5.2.1.1 build_log.sh
#!/bin/bash

################################ Log Related ################################
LOG_PRO_OFF="\033[0m"    # close all property
LOG_PRO_FONT_BLACK="\033[1;30m"
LOG_PRO_FONT_RED="\033[1;31m"
LOG_PRO_FONT_GREEN="\033[1;32m"
LOG_PRO_FONT_YELLOW="\033[1;33m"
LOG_PRO_FONT_BLUE="\033[1;34m"
LOG_PRO_FONT_PURPLE="\033[1;35m"
LOG_PRO_FONT_DARKGREEN="\033[1;36m"
LOG_PRO_FONT_WHITE="\033[1;37m"

#
# log <log_level> [log]
# example:
# log INFO "hello, this is a test"
#
function log()
{
    if [ $# -lt 2 ]
    then
        build_help;
    else
        loglvel=$1
        case $loglvel in
            ver)
                echo -e $LOG_PRO_FONT_GREEN"$2"$LOG_PRO_OFF
                ;;
            dbg)
                echo -e $LOG_PRO_FONT_BLUE"$2"$LOG_PRO_OFF
                ;;
            info)
                echo -e $LOG_PRO_FONT_DARKGREEN"$2"$LOG_PRO_OFF
                ;;
            warn)
                echo -e $LOG_PRO_FONT_PURPLE"$2"$LOG_PRO_OFF
                ;;
            err)
                echo -e $LOG_PRO_FONT_RED"$2"$LOG_PRO_OFF
                ;;
            *)
                echo -e $LOG_PRO_FONT_WHITE"$2"$LOG_PRO_OFF
                ;;
        esac
    fi
}

function build_help()
{
    log info "------------------- microX OS Build Menu ----------------------------"
    log info "usage: script/build.sh [option]"
    log info "-s:   setup build enviorment"
    log info "-m:   menuconfig"
    log info "-b:   build OS(microX), show less log."
    log info "-bv:  build OS(microX), show more log."
    log info "-c:   clean OS(microX)"
    log info "----------------------------------------------------------------------"
}
5.2.1.2 build.sh
#!/bin/bash

export ENV_BUILD_TOP=`pwd`
export ENV_BUILD_TARGET=microx

export ENV_BUILD_TEXTBASE=0x8000
export ENV_BUILD_TFTPBOOT=/home/book/tftpboot
export ENV_BUILD_CROSS_TOOL=gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf
export ENV_BUILD_TYPE=debug

export ENV_BUILD_OUT=$ENV_BUILD_TOP/out
export ENV_BUILD_SCRIPT_DIR=$ENV_BUILD_TOP/script
export ENV_BUILD_KCONFIGLIB_DIR=$ENV_BUILD_TOP/script/Kconfiglib-master
export ENV_BUILD_3RDPARTY=$ENV_BUILD_TOP/3rd_party
export ENV_BUILD_PYTHON=python3
export ENV_BUILD_CONFIG=$ENV_BUILD_TOP/.config

export ENV_BUILD_LDS=${ENV_BUILD_SCRIPT_DIR}/${ENV_BUILD_TARGET}.lds
export ENV_BUILD_TARGET_ELF=${ENV_BUILD_OUT}/${ENV_BUILD_TARGET}.elf
ENV_BUILD_TARGET_BIN=${ENV_BUILD_OUT}/${ENV_BUILD_TARGET}.bin

. $ENV_BUILD_SCRIPT_DIR/build_log.sh

function gen_autoconf_py()
{
    log dbg "generate autoconf python script"
    $ENV_BUILD_PYTHON $ENV_BUILD_SCRIPT_DIR/gen_autoconf.py > $ENV_BUILD_OUT/autogen.py

    $ENV_BUILD_PYTHON $ENV_BUILD_SCRIPT_DIR/gen_autoconf_header.py > $ENV_BUILD_OUT/autogen.h
}

function menuconfig()
{
    if [ ! -f ${ENV_BUILD_TOP}/.config ]; then
        cp $ENV_BUILD_SCRIPT_DIR/imx6ull_defconfig  ${ENV_BUILD_TOP}/.config
    fi
    $ENV_BUILD_PYTHON $ENV_BUILD_KCONFIGLIB_DIR/menuconfig.py $ENV_BUILD_SCRIPT_DIR/Kconfig
    gen_autoconf_py
}

do_build_system()
{
    if test $1 == "build"; then
        log info "[ Build ] ---- microX ----"
        if [ ! -d  ${ENV_BUILD_TOP}/prebuilt/${ENV_BUILD_CROSS_TOOL} ]; then
            log err "should exec: ./build.sh -s first"
        else
            export ENV_BUILD_VERBOSE=1
            scons -Q -j8
        fi
    elif test $1 == "build_detail"; then
        log info "[ Build ] ---- microX detail ----"
        if [ ! -d  ${ENV_BUILD_TOP}/prebuilt/${ENV_BUILD_CROSS_TOOL} ]; then
            log err "should exec: ./build.sh -s first"
        else
            export ENV_BUILD_VERBOSE=0
            scons -Q -j8
        fi
    elif test $1 == "setup"; then
        log info "[ Setup ] ---- Enviorment ----"

        if [ ! -d ${ENV_BUILD_OUT} ]; then
            mkdir -p ${ENV_BUILD_OUT}
        fi

        if [ ! -d ${ENV_BUILD_TOP}/prebuilt/Kconfiglib-master ]; then
            unzip -o ${ENV_BUILD_TOP}/prebuilt/Kconfiglib-master.zip -d $ENV_BUILD_SCRIPT_DIR
        fi

        if [ -f ${ENV_BUILD_TOP}/prebuilt/${ENV_BUILD_CROSS_TOOL}.tbz2 ]; then
            tar jxf ${ENV_BUILD_TOP}/prebuilt/${ENV_BUILD_CROSS_TOOL}.tbz2 -C $ENV_BUILD_TOP/prebuilt/
        else
            log warn "${ENV_BUILD_TOP}/prebuilt/${ENV_BUILD_CROSS_TOOL}.tbz2 not exist, please check!!!"
        fi
    elif test $1 == "clean"; then
        log info "[ Clean ] ---- microX ----"

        if [ -f ${ENV_BUILD_TOP}/config.pyc ]; then
            rm ${ENV_BUILD_TOP}/config.pyc -f
        fi

        if [ -f ${ENV_BUILD_TOP}/script/config.pyc ]; then
            echo "${ENV_BUILD_TOP}/script/config.pyc exist"
            rm ${ENV_BUILD_TOP}/script/config.pyc -f
        else
            echo "${ENV_BUILD_TOP}/script/config.pyc not exist"
        fi

        scons -c
    else
        log warn "do_build_system: unsupport action"
    fi
}

do_export_env()
{
    # 交叉编译工具链里的工具: CC,AS, CXX, STRIP, OBJCOPY, OBJDUMP
    ENV_BUILD_TOOCHAIN_PREFIX=${ENV_BUILD_TOP}/prebuilt/${ENV_BUILD_CROSS_TOOL}/bin/arm-linux-gnueabihf-
    export CC=${ENV_BUILD_TOOCHAIN_PREFIX}gcc
    export AS=${ENV_BUILD_TOOCHAIN_PREFIX}gcc
    export AR=${ENV_BUILD_TOOCHAIN_PREFIX}ar
    export CXX=${ENV_BUILD_TOOCHAIN_PREFIX}g++
    export LD=${ENV_BUILD_TOOCHAIN_PREFIX}ld
    export STRIP=${ENV_BUILD_TOOCHAIN_PREFIX}strip
    export OBJCOPY=${ENV_BUILD_TOOCHAIN_PREFIX}objcopy
    export OBJDUMP=${ENV_BUILD_TOOCHAIN_PREFIX}objdump
}

if [ -f $ENV_BUILD_OUT/.config ]; then
    . $ENV_BUILD_OUT/.config
fi 

if [ $# -lt 1 ]; then
    build_help;
else
    do_export_env;
    build_action=$1
    case $build_action in 
        -s) # setup enviorment
            do_build_system setup;
            ;;
        -m) # menuconfig 
            menuconfig
            ;;
        -b) # build system
            do_build_system build;
            ;;
        -bv) # build detail
            do_build_system build_detail;
            ;;
        -c) # clean system
            do_build_system clean;
            ;;
        *)
            help;
            ;;
        esac
fi

5.3 核心代码实现

5.3.1 head.S

.text   // .text申明以下为代码段
.global  _start // 定义一个全局符号 _start, 链接脚本microx.lds中会使用该符号
_start:                 
    ldr sp, =0x80200000    // 设置栈
    bl clean_bss    // 清除BSS段
    bl start_kernel // 跳转到 C函数入口: start_kernel执行,该函数在 main.c中实现

halt:
    b  halt     // 如果执行到此处, 将在这里无限循环

clean_bss:
    /* 清除BSS段, __bss_start/__bss_end符号在链接脚本microx.lds中定义 */
    ldr r1, =__bss_start
    ldr r2, =__bss_end
    mov r3, #0
clean:
    str r3, [r1]
    add r1, r1, #4
    cmp r1, r2
    bne clean

    mov pc, lr

主要功能:

  • 设置栈
  • 初始化BSS段
  • 跳转到start_kernel处执行

5.3.2 led.h/led.c

led.h:

/*************************************************************************************************
** Copyright © microX OS 2020 - 2030. All rights reserved.
** 
** 文件名 : led.h
** 作者 : skymixos.Luo
** 版本 : V1.0
** 描述 : LED驱动头文件
**
**
** 修改记录:
**  日期                 版本                修改人                      备注
** ---------------------------------------------------------------------------------------------
** 2022年10月16日         V1.0               skymixos.Luo                创建文件并添加注释
**
***************************************************************************************************/
#ifndef _MX_HW_LED_H_
#define _MX_HW_LED_H_

#include "sys/types.h"

typedef enum {
    LED_DEVICE_ID1,
    LED_DEVICE_IDMAX
} LED_DEVICE_ID;

typedef enum {
    LED_CTRL_CMD_ON,
    LED_CTRL_CMD_OFF,
} LED_CTRL_CMD;

typedef struct led_device {
    void* base;         // GPIO控制器基地址
    mx_bool_t is_init;  // 是否完成设备初始化

    // 设备初始化,反初始化,控制
    void (*pfn_init)(struct led_device* hndl);
    void (*pfn_deinit)(struct led_device* hndl);
    void (*pfn_ctl)(struct led_device* hndl, LED_DEVICE_ID id, LED_CTRL_CMD cmd);    
} led_device_t, *led_device_hndl;

led_device_hndl get_led_instance(void);

#endif // !_MX_HW_LED_H_

led.c:

/*************************************************************************************************
** Copyright © microX OS 2020 - 2030. All rights reserved.
** 
** 文件名 : led.c
** 作者 : skymixos.Luo
** 版本 : V1.0
** 描述 : LED驱动实现
**
**
** 修改记录:
**  日期                 版本                修改人                      备注
** ---------------------------------------------------------------------------------------------
** 2022年9月10日         V1.0               skymixos.Luo                创建文件并添加注释
**
***************************************************************************************************/
#include "sys/io.h"
#include "drv/led.h"
#include "autogen.h"
#include "bsp/imx6ull_soc.h"

static led_device_t g_led_device = {0};

MX_UNUSED static const mx_int8_t* get_led_id_string(LED_DEVICE_ID id) 
{
    switch (id) {
        CONVNUMTOSTR(LED_DEVICE_ID1);
        CONVNUMTOSTR(LED_DEVICE_IDMAX);
        default: return "unknown led id";
    }
}

MX_UNUSED static const char* get_led_cmd_string(LED_CTRL_CMD cmd) 
{
    switch (cmd) {
        CONVNUMTOSTR(LED_CTRL_CMD_ON);
        CONVNUMTOSTR(LED_CTRL_CMD_OFF);
        default: return "unknown led cmd";
    }
}

/*
 * 对于 100ASK_IMX6ULL Pro开发板: GPIO5_3
 * 对于 ATK-DL6Y2CM 开发板: GPIO1_4
 */
static void led_init(struct led_device* hndl)
{
    mx_uint32_t reg_val = 0;

    /* 1.使能GPIO部分的时钟
     * set CCM to enable GPIO1/5
     * GPIO5 bit[31:30] = 0b11
     * GPIO1 bit[27:26] = 0b11
     */
    reg_val = readl(SOC_CCM_BASE + CCM_CCGR1);
#ifdef CONFIG_PLATFORM_ATKDL6Y2CM_IMX6ULL
    reg_val |= (3 << 26);
#else
    reg_val |= (3 << 30);
#endif
    writel(reg_val, SOC_CCM_BASE + CCM_CCGR1);

    /*
     * 2.复用引脚配置
     * 100ASK_IMX6ULL Pro: IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3  229_0014h
     * ATK-DL6Y2CM: IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO04    20E_006Ch
     */
#ifdef CONFIG_PLATFORM_ATKDL6Y2CM_IMX6ULL
    reg_val = readl(SOC_IOMUXC_BASE + 0x6c);
    reg_val &= ~(0xf);
    reg_val |= 5;
    writel(reg_val, SOC_IOMUXC_BASE + 0x6c);
#else
    reg_val = readl(SOC_IOMUXC_SNVS_BASE + 0x14);
    reg_val &= ~(0xf);
    reg_val |= 5;
    writel(reg_val, SOC_IOMUXC_SNVS_BASE + 0x14);
#endif

    /*
     * 3.将GPIO配置为输出,默认输出高电平,熄灭LED
     */
    reg_val = readl(hndl->base + GPIO_GDIR);
    reg_val |= (1 << 3);
    writel(reg_val, hndl->base + GPIO_GDIR);

    // 将GPIO输出高电平,熄灭LED
    reg_val = readl(hndl->base + GPIO_DR);
    reg_val |= (1 << 3);
    writel(reg_val, hndl->base + GPIO_DR);
}

static void led_deinit(struct led_device* hndl)
{
    // nothing
}

static void led_ctl(struct led_device* hndl, LED_DEVICE_ID id, LED_CTRL_CMD cmd)
{
    mx_uint32_t led_bit = 0;
    mx_uint32_t led_val = readl(hndl->base + GPIO_DR);

    if (id == LED_DEVICE_ID1) {
        led_bit = 3;
    } else {
        return;
    }

    if (cmd == LED_CTRL_CMD_ON) {
        led_val &= ~(1 << led_bit);
    } else if (cmd == LED_CTRL_CMD_OFF) {
        led_val |= (1 << led_bit);
    } else {
        return;
    }

    writel(led_val, hndl->base + GPIO_GR_OFFSET);    
}

led_device_hndl get_led_instance(void)
{
    if (g_led_device.is_init == false) {
#ifdef CONFIG_PLATFORM_100ASK_IMX6ULL
        g_led_device.base         = (void*)SOC_GPIO5_BASE;
#else
        g_led_device.base         = (void*)SOC_GPIO1_BASE;
#endif
        g_led_device.pfn_init     = led_init;
        g_led_device.pfn_deinit   = led_deinit;
        g_led_device.pfn_ctl      = led_ctl;

        g_led_device.pfn_init(&g_led_device);
        g_led_device.is_init = true;
    }
    return &g_led_device;
}

主要功能:

  • 实现LED的控制(点亮,熄灭)

5.3.3 main.c

#include "led.h"

static void delay(volatile mx_uint32_t d)
{
    while (d--);
}

mx_int32_t start_kernel(void)
{
    led_device_hndl led = get_led_instance();

    while (1) {
        led->pfn_ctl(led, LED_DEVICE_ID1, LED_CTRL_CMD_OFF);
        delay(10000000);
        led->pfn_ctl(led, LED_DEVICE_ID1, LED_CTRL_CMD_ON);
        delay(10000000);
    }

    return 0;
}

主要功能:

  • 调用led驱动的控制接口,循环的点亮熄灭LED

5.5 编译测试

5.5.1 云服务器的代码仓库中下载测试代码(code.ayliyun.com)

5.5.1.1 配置git并将SSH公钥添加到aliyun服务器
  • git配置用户名和email
$ git config --global user.name "your_name"
$ git config --global user.email "your_email"

注:将"your_name"和"your_email"替换成自己的用户名和邮箱

比如:

$ git config --global user.name “microx”

$ git config --global user.email “microx@163.com”

  • 生成公钥:
$ ssh-keygen -t rsa -C "your_email"

执行该命令并一路回车之后,会在用户的根目录生成:id_rsa.pub文件,如:
在这里插入图片描述

  • 将id_rsa.pub的内容添加到aliyun服务器

在这里插入图片描述

  • 下载代码:git clone git@code.aliyun.com:luopinjing/microx.git

在这里插入图片描述

下载完成后,切换到dev_1.0分支并:git checkout dev_1.0
在这里插入图片描述

检出代码:git checkout v0.0.1

5.5.2 配置(根据自己的开发板选择对应配置)

  • 执行 ./build.sh 会出现编译菜单:
    在这里插入图片描述

  • 首次下载代码,需先执行:./build.sh -s 来设置编译环境
    在这里插入图片描述

  • 执行 ./build.sh -m 来选择自己所使用的开发板
    在这里插入图片描述

菜单使用:回车键(进入子菜单);上下方向键(选择菜单项);左右方向键(用于进入和返回);Esc键(退出菜单);字母Y:保存设置;字母N:不保存设置

5.5.3 编译

  • 执行 ./build.sh -b 命令完成目标程序编译,并将编译产生的microx.bin拷贝到 /home/book/tftpboot/目录下。
    在这里插入图片描述

  • 执行 ./build.sh -bv 命令会显示详细的编译信息
    在这里插入图片描述

编译产生的结果存放在 out 目录下:
在这里插入图片描述

  • autogen.h:使用配置./build.sh -m 生成的配置最终会转换成autogen.h,里面包含定义的一系列宏,代码中使用这些宏达到条件编译的目的。
  • autogen.py:使用配置./build.sh -m 生成的配置最终会转换成autogen.py,该文件被编译系统使用,达到选择需要编译哪些文件的目标。
  • microx.elf:编译产生的elf文件。
  • microx.bin:最终烧写到目标板上运行的文件,是由microx.elf转换生成的。
  • microx.dis:反汇编文件,用于调试(当程序崩溃时)

5.5.4 下载程序运行测试

5.5.4.1 开发板和Windows的网络连接配置

开发板和Windows开发主机有两种网络连接方式

  • 方式一:开发板和Windows开发主机连接到同一个路由器上(前提是你得有一个路由器)
  • 方式二:开发板和Windosw开发主机通过一根网线直连(如果你的电脑没有网口,可以购买一个USB转网口的转接器)

在这里插入图片描述

  • 采用方式一时,路由器会给Windows动态分配IP地址,需要手动给开发板设置一个与Windows在同一网段的地址。
  • 采用方式二时,需要给Windows对应的网卡设置一个与开发板同一网段的IP地址(开发板默认的IP地址为192.168.1.X)。
5.5.4.2 Windows下开启tftp服务

在这里插入图片描述

使用tftp服务的时候需要关闭Windows的防火墙,否则开发板不能ping通Windows!!!

在这里插入图片描述

在这里插入图片描述

  • 开发板设置tftp服务器的ip为Windows的ip:setenv serverip xx.xx.xx.xx

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oHEZm1KF-1666972676643)(images/DFIEkCh4kll3W4Q4t7h9H0tmYU6YU4m_kYLrsQlJNU8.png)]

注:这个ip地址以自己机器的ip地址为准

  • 保持参数配置:saveenv
    在这里插入图片描述
5.5.4.2 下载程序运行

开发板上电后,按下“回车”键进入u-boot的下载模式。通过tftp下载microx.bin到内存地址0x80008000处执行。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

6. 小结

3.1 使用到汇编指令及伪指令

  • MOV指令
  • B指令
  • LDR指令
  • LDR伪指令

3.2 C语言知识点

  • 基本的数据类型
  • 结构体: struct
  • 枚举类型:enum
  • 指针,函数指针
  • typedef的使用
  • 位操作:按位与(&),按位或(|),按位取反(~)
  • 关键字:static,volatile

7. 参考资料

https://blog.csdn.net/hes_c/article/details/71600471

https://www.cnblogs.com/deepworm/p/10452908.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天整点嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值