yocto meta-st-stm32mp conf文件夹分析

meta-st-stm32mp conf文件夹分析

machine conf分析

本节主要分析conf/machine下面的文件
yocto meta-st-stm32mp conf文件夹分析_第1张图片

stm32mp1.conf

  1. 包含inc文件
include conf/machine/include/st-machine-common-stm32mp.inc
include conf/machine/include/st-machine-providers-stm32mp.inc

st-machine-providers-stm32mp.inc 主要是确定provider,包括kernel uboot atf optee-os等
st-machine-common-stm32mp.inc 主要的处理逻辑都在这里面
2. 指定特定的machine家族

MACHINEOVERRIDES .= ":stm32mp1common"
  1. 确定Chip architecture
DEFAULTTUNE = "cortexa7thf-neon-vfpv4"
include conf/machine/include/tune-cortexa7.inc
  1. 确定boot 方案
BOOTSCHEME_LABELS += "trusted"
BOOTSCHEME_LABELS += "optee"

支持trust 启动和optee安全启动
5. 设置boot设备

BOOTDEVICE_LABELS += "emmc"
BOOTDEVICE_LABELS += "nand-4-256"
BOOTDEVICE_LABELS += "nor-sdcard"
BOOTDEVICE_LABELS += "sdcard"

支持emmc sdcard nand nor启动
6. 设置machine的设备树

STM32MP_DT_FILES_DK += "stm32mp157c-dk2 stm32mp157f-dk2"
  1. 配置machine feature
MACHINE_FEATURES += "splashscreen"
MACHINE_FEATURES += "watchdog"
MACHINE_FEATURES += "bluetooth"
MACHINE_FEATURES += "wifi"
MACHINE_FEATURES += "${@'gpu' if d.getVar('ACCEPT_EULA_'+d.getVar('MACHINE')) == '1' else ''}"
MACHINE_FEATURES += "m4copro"

BLUETOOTH_LIST += "linux-firmware-bluetooth-bcm4343"
WIFI_LIST += "linux-firmware-bcm43430"
  1. kernel相关配置
KERNEL_MODULE_AUTOLOAD = "goodix"

# Define the devicetree for Linux A7 examples
LINUX_A7_EXAMPLES_DT += "stm32mp157c-dk2-a7-examples"

指定自动加载的module 和kernel的dt文件
9. 指定M4核心的相关配置

CUBE_M4_EXAMPLES_DT += "stm32mp157c-dk2-m4-examples"

stm32mp1-xxx.conf
上面stm32mp1.conf列出了很多mp1系列支持的启动方式、启动设备、dt文件等多样化配置,stm32mp1-xxx.conf是具体的官方评估板的配置文件,里面的配置是stm32mp1.conf的子集。例如启动设备只支持sdcard,支持trusted启动,MACHINE_FEATURES有删减等。不做具体介绍,一看便知。

include文件夹

上面stm32mp1.conf 里面引用了几个inc文件,下面主要看一下include里面的这几个文件

yocto meta-st-stm32mp conf文件夹分析_第2张图片

st-machine-providers-stm32mp.inc

这个文件比较简单,主要就是通过PREFERRED_PROVIDER_指定具体的包,主要包括kernel uboot tfa optee-os

PREFERRED_PROVIDER_virtual/kernel = "linux-stm32mp"
PREFERRED_PROVIDER_virtual/bootloader = "u-boot-stm32mp"
PREFERRED_PROVIDER_u-boot = "u-boot-stm32mp"
PREFERRED_PROVIDER_virtual/trusted-firmware-a = "tf-a-stm32mp"
PREFERRED_PROVIDER_virtual/trusted-firmware-a-serialboot = "tf-a-stm32mp-serialboot"

TF_A_CONFIG_append_pn-tf-a-stm32mp-serialboot = " serialboot "
TF_A_CONFIG_append_pn-tf-a-stm32mp = " ${@bb.utils.contains('BOOTSCHEME_LABELS', 'trusted', 'trusted', '', d)} "
TF_A_CONFIG_append_pn-tf-a-stm32mp = " ${@bb.utils.contains('BOOTSCHEME_LABELS', 'optee', 'optee', '', d)} "

PREFERRED_PROVIDER_virtual/optee-os = "optee-os-stm32mp"

st-machine-storage-device-stm32mp.inc

DEVICE_STORAGE ?= "EMMC:mmc1, NAND:nand0, NOR:nor0, SDCARD:mmc0"

DEVICE_STORAGE_NAMES += "EMMC"
DEVICE_STORAGE_NAMES += "NAND"
DEVICE_STORAGE_NAMES += "NOR"
DEVICE_STORAGE_NAMES += "SDCARD"

DEVICE_STORAGE_TYPES += "mmc0"
DEVICE_STORAGE_TYPES += "mmc1"
DEVICE_STORAGE_TYPES += "mmc2"
DEVICE_STORAGE_TYPES += "nand0"
DEVICE_STORAGE_TYPES += "nor0"

python () {
    """
    This function configure dynamically the needed alias between generic storage
    device name and device type.
    Output for this function is the initialization of:
        DEVICE_ = ''
        DEVICE_ = ''
    """
    device_storage_config = d.getVar('DEVICE_STORAGE') or ''
    if not device_storage_config:
        return
    if not device_storage_config.strip():
        return
    if len(device_storage_config.split(',')) > 0:
        # Init supported device storage configuration
        supported_device_names = (d.getVar('DEVICE_STORAGE_NAMES') or '').split()
        supported_device_types = (d.getVar('DEVICE_STORAGE_TYPES') or '').split()
        # Loop for all storage device configurations
        for device_storage in device_storage_config.split(','):
            device_name = device_storage.split(':')[0].strip()
            device_type = device_storage.split(':')[1].strip()
            # Check for configuration consistency
            if device_name and device_type:
                # Make sure configuration is correctly done
                if device_name not in supported_device_names:
                    bb.fatal('Wrong DEVICE_STORAGE configuration: "%s" is not part of supported device name (%s)' % (device_name, supported_device_names))
                if device_type not in supported_device_types:
                    bb.fatal('Wrong DEVICE_STORAGE configuration: "%s" is not part of supported device type (%s)' % (device_type, supported_device_types))
                # Configure alias
                d.setVar('DEVICE_%s' % device_name, device_type)
                d.setVar('DEVICE_%s' % device_type, device_name)
            else:
                bb.fatal('Wrong DEVICE_STORAGE configuration: expecting DEVICE_STORAGE = ":,:"')
}

# -----------------------------------------------------------------------------
# EMMC
# Extra space is required to store 'Protective MBR' and 'Primary GPT Header'
# Currently the required size is 17kBytes (i.e. 0x4400)
# We need to align this size to get the first offset to use
DEVICE_START_OFFSET_EMMC    ?= "0x00080000"
DEVICE_ALIGNMENT_SIZE_EMMC  ?= "0x00080000"

# Specific to EMMC, there are two boot partitions using specific offset to access
DEVICE_START_OFFSET_BOOT0_EMMC ?= "boot1"
DEVICE_START_OFFSET_BOOT1_EMMC ?= "boot2"

# Configure the rootfs partition uid used in gpt partition table for EMMC
DEVICE_PARTUUID_ROOTFS_EMMC ?= "${@d.getVar(d.expand('DEVICE_PARTUUID_ROOTFS_${DEVICE_EMMC}')) or ''}"

# Configure the list of boards that enable EMMC
DEVICE_BOARD_ENABLE_EMMC += "${@bb.utils.contains('BOOTDEVICE_LABELS', 'emmc', '${STM32MP_DT_FILES_ED}', '', d)}"
DEVICE_BOARD_ENABLE_EMMC += "${@bb.utils.contains('BOOTDEVICE_LABELS', 'emmc', '${STM32MP_DT_FILES_EV}', '', d)}"

# -----------------------------------------------------------------------------
# NAND
DEVICE_START_OFFSET_NAND   ?= "0x00000000"
DEVICE_ALIGNMENT_SIZE_NAND ?= "0x00040000"

# Configure the list of boards that enable EMMC
DEVICE_BOARD_ENABLE_NAND   += "${@bb.utils.contains('BOOTDEVICE_LABELS', 'nand-4-256', '${STM32MP_DT_FILES_ED}', '', d)}"
DEVICE_BOARD_ENABLE_NAND   += "${@bb.utils.contains('BOOTDEVICE_LABELS', 'nand-4-256', '${STM32MP_DT_FILES_EV}', '', d)}"

# -----------------------------------------------------------------------------
# NOR
DEVICE_START_OFFSET_NOR    ?= "0x00000000"
DEVICE_ALIGNMENT_SIZE_NOR  ?= "0x00010000"

# Configure the list of boards that enable EMMC
DEVICE_BOARD_ENABLE_NOR    += "${@bb.utils.contains('BOOTDEVICE_LABELS', 'nor-sdcard' , '${STM32MP_DT_FILES_EV}', '', d)}"

# -----------------------------------------------------------------------------
# SDCARD
# Extra space is required to store 'Protective MBR' and 'Primary GPT Header'
# Currently the required size is 17kBytes (i.e. 0x4400)
# We need to align this size to get the first offset to use
DEVICE_START_OFFSET_SDCARD    ?= "0x00004400"
DEVICE_ALIGNMENT_SIZE_SDCARD  ?= "0x00000200"

# Configure the rootfs partition uid used in gpt partition table for SDCARD
DEVICE_PARTUUID_ROOTFS_SDCARD ?= "${@d.getVar(d.expand('DEVICE_PARTUUID_ROOTFS_${DEVICE_SDCARD}')) or ''}"

# Configure the list of boards that enable SDCARD
DEVICE_BOARD_ENABLE_SDCARD    += "${@bb.utils.contains('BOOTDEVICE_LABELS', 'sdcard', '${STM32MP_DT_FILES_DK}', '', d)}"
DEVICE_BOARD_ENABLE_SDCARD    += "${@bb.utils.contains_any('BOOTDEVICE_LABELS', [ 'sdcard', 'nor-sdcard' ], '${STM32MP_DT_FILES_ED}', '', d)}"
DEVICE_BOARD_ENABLE_SDCARD    += "${@bb.utils.contains_any('BOOTDEVICE_LABELS', [ 'sdcard', 'nor-sdcard' ], '${STM32MP_DT_FILES_EV}', '', d)}"

# -----------------------------------------------------------------------------
# Fixed configuration from U-Boot source code
# -----------------------------------------------------------------------------
DEVICE_PARTUUID_ROOTFS_mmc0 ?= "e91c4e10-16e6-4c0e-bd0e-77becf4a3582"
DEVICE_PARTUUID_ROOTFS_mmc1 ?= "491f6117-415d-4f53-88c9-6e0de54deac6"
DEVICE_PARTUUID_ROOTFS_mmc2 ?= "fd58f1c7-be0d-4338-8ee9-ad8f050aeb18"

st-machine-storage-device-stm32mp中上来定义了三个变量
DEVICE_STORAGE:可配置的启动存储组合
DEVICE_STORAGE_NAMES:默认支持的启动存储名字。eg:EMMC SDCARD
DEVICE_STORAGE_TYPES:默认支持的启动存储类型。eg:mmc0 mmc1
python函数做的关键工作其实就2行赋值:
d.setVar(‘DEVICE_%s’ % device_name, device_type)
d.setVar(‘DEVICE_%s’ % device_type, device_name)
最终效果就是DEVICE_EMMC=mmc0 DEVICE_mmc0=EMMC

然后就是针对每一种可启动设备的变量配置,这里只关注EMMC 和SDCARD,NOR 和NAND暂不关注。
关键变量整理以后赋值如下(以fsmp1开发板获取结果显示):

在这里插入图片描述DEVICE_START_OFFSET_EMMC ?= “0x00080000”
DEVICE_ALIGNMENT_SIZE_EMMC ?= “0x00080000”

DEVICE_START_OFFSET_BOOT0_EMMC ?= “boot1”
DEVICE_START_OFFSET_BOOT1_EMMC ?= “boot2”

DEVICE_PARTUUID_ROOTFS_EMMC =“491f6117-415d-4f53-88c9-6e0de54deac6”
DEVICE_BOARD_ENABLE_EMMC = " stm32mp157a-fsmp1a "
总结:主要就是给不同的启动设备设置分区的UUID和板子配套的dts文件,在extlinux中会用到。

st-machine-features-stm32mp.inc

GPU_IMAGE_INSTALL = "${@bb.utils.contains('MACHINE_FEATURES', 'gpu', '${GPU_LIST}', '', d)} "
ALSA_IMAGE_INSTALL = "${@bb.utils.contains('COMBINED_FEATURES', 'alsa', '${ALSA_LIST}', '', d)} "
BLUETOOTH_IMAGE_INSTALL = "${@bb.utils.contains('MACHINE_FEATURES', 'bluetooth', '${BLUETOOTH_LIST}', '', d)}"
M4COPRO_IMAGE_INSTALL = "${@bb.utils.contains('MACHINE_FEATURES', 'm4copro', '${M4COPRO_LIST}', '', d)}"
OPTEE_IMAGE_INSTALL = "${@bb.utils.contains('COMBINED_FEATURES', 'optee', '${OPTEE_LIST}', '', d)} "
WIFI_IMAGE_INSTALL = "${@bb.utils.contains('MACHINE_FEATURES', 'wifi', '${WIFI_LIST}', '', d)} "

EXTRA_IMAGEDEPENDS_append = " \
    ${OPTEE_BINARY_INSTALL} \"

MACHINE_EXTRA_RRECOMMENDS_append = " \
    ${GPU_IMAGE_INSTALL}        \
    ${ALSA_IMAGE_INSTALL}       \
    ${BLUETOOTH_IMAGE_INSTALL}  \
    ${M4COPRO_IMAGE_INSTALL}    \
    ${OPTEE_IMAGE_INSTALL}      \
    ${WIFI_IMAGE_INSTALL}       \"

这个文件指定了一系列的FEATURE_IMAGE_INSTALL变量,然后通过判断MACHINE_FEATURES变量中是否指定该FEATURE决定是否将这些包 包含到根文件系统。
EXTRA_IMAGEDEPENDS:镜像构建所需要的机器特定包列表。这些包对于机器启动来说是必要的。
MACHINE_EXTRA_RRECOMMENDS:镜像构建所需要的机器特定包列表。这些包对于机器启动来说不是必要的。

gpu_vivante.inc



GPU_USERLAND_LIBRARIES_WAYLAND ?= "gcnano-userland-multi-binary-stm32mp"
GPU_USERLAND_LIBRARIES_EGLFS   ?= "gcnano-userland-multi-binary-stm32mp"
GPU_USERLAND_LIBRARIES_X11     ?= "mesa"

def get_gpu_vivante_handler(d):
    """  Overloading the default EGL/GLES/mesa implementation."""
    machine_features = d.getVar('MACHINE_FEATURES').split()
    distro_features = d.getVar('DISTRO_FEATURES').split()

    gpu_lib_wayland = d.getVar('GPU_USERLAND_LIBRARIES_WAYLAND').split()
    gpu_lib_eglfs = d.getVar('GPU_USERLAND_LIBRARIES_EGLFS').split()
    gpu_lib_x11 = d.getVar('GPU_USERLAND_LIBRARIES_X11').split()

    if 'gpu' in machine_features:
        if 'wayland' in distro_features:
            provider = gpu_lib_wayland[0]
        else:
            if 'x11' in distro_features:
                provider = gpu_lib_x11[0]
            else:
                '''no wayland, no X11 -> choose DRM/FB for eglfs'''
                provider = gpu_lib_eglfs[0]
    else:
        provider = "mesa"

    return provider;

GPU_USERLAND_LIBRARIES_INSTALL = "${@get_gpu_vivante_handler(d)}"

PREFERRED_PROVIDER_virtual/egl = "${@get_gpu_vivante_handler(d)}"
PREFERRED_PROVIDER_virtual/libgles1 = "${@get_gpu_vivante_handler(d)}"
PREFERRED_PROVIDER_virtual/libgles2 = "${@get_gpu_vivante_handler(d)}"
PREFERRED_PROVIDER_virtual/libgbm = "${@get_gpu_vivante_handler(d)}"
PREFERRED_PROVIDER_virtual/mesa = "${@bb.utils.contains('PREFERRED_PROVIDER_virtual/egl','mesa','mesa','mesa-gl',d)}"
PREFERRED_PROVIDER_virtual/libgl = "${@bb.utils.contains('PREFERRED_PROVIDER_virtual/egl','mesa','mesa','mesa-gl',d)}"

主要通过 MACHINE_FEATURES DISTRO_FEATURES两个变量配合来确定一些包的provider.
比如MACHINE_FEATURES 包含gpu、DISTRO_FEATURES 没有指定wayland或者x11,则 egl libgles1 libgles2 libgbm 系列包的provider都是 gcnano-userland-multi-binary-stm32mp 。 mesa libgl 系列包的provider 是 mesa-gl。

st-machine-extlinux-config-stm32mp.inc

st-machine-extlinux-config-stm32mp.inc关键变量整理以后赋值如下(以fsmp1开发板获取结果显示、去除nand nor相关内容):

#@DESCRIPTION: STM32MP machine extlinux file configuration

# Define extlinux console for stm32mp machine
UBOOT_EXTLINUX_CONSOLE = "console=ttySTM0,115200"
# Define default FDTDIR for all configs
UBOOT_EXTLINUX_FDTDIR = "/"
# Define default MENU DESCRIPTION for all configs
UBOOT_EXTLINUX_MENU_DESCRIPTION = "OpenSTLinux"
# Define default boot config for all config
UBOOT_EXTLINUX_DEFAULT_LABEL ?= "OpenSTLinux"
# Define default INITRD for all configs
INITRD_SHORTNAME ??= ""
UBOOT_EXTLINUX_INITRD ?= "/uInitrd"

# -----------------------------------------------------------------------------
# Configurations
# -----------------------------------------------------------------------------
# Define additional targets to use
UBOOT_EXTLINUX_TARGETS += "${@bb.utils.contains_any('BOOTDEVICE_LABELS', [ 'sdcard', 'nor-sdcard' ], 'target-sdcard', '', d)}"
UBOOT_EXTLINUX_TARGETS += "${@bb.utils.contains('BOOTDEVICE_LABELS', 'emmc', 'target-emmc', '', d)}"

# Define labels for each target
# (mandatory to allow specific var override if needed)
UBOOT_EXTLINUX_LABELS_target-sdcard += "rootfs"
UBOOT_EXTLINUX_LABELS_target-emmc += "rootfs"

# Define specific bootprefix for each target
UBOOT_EXTLINUX_BOOTPREFIXES_target-sdcard = "${DEVICE_SDCARD}_"
UBOOT_EXTLINUX_BOOTPREFIXES_target-emmc = "${DEVICE_EMMC}_"

# Define ROOT overrides for each target
UBOOT_EXTLINUX_ROOT_target-sdcard = "root=PARTUUID=${DEVICE_PARTUUID_ROOTFS_SDCARD}"
UBOOT_EXTLINUX_ROOT_target-emmc = "root=PARTUUID=${DEVICE_PARTUUID_ROOTFS_EMMC}"
# -----------------------------------------------------------------------------
# Append specific examples configs
# -----------------------------------------------------------------------------
# Enable UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG var that allows to configure
# additional target:
#   UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG = "extra-target"
# Then define new label(s) to append to the label list from current target
#   UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[extra-target] = "newlabel1 newlabel2"
# This will create new 'extlinux.conf' file with name 'extra-target_extlinux.conf'
# that will use UBOOT_EXTLINUX_LABELS label list defined for current target plus
# the 'newlabel1' and 'newlabel2' labels.
# -----------------------------------------------------------------------------
# Define additional extra targets to consider
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG_target-sdcard += "${STM32MP_DT_FILES_DK}"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG_target-sdcard += "${STM32MP_DT_FILES_ED}"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG_target-sdcard += "${STM32MP_DT_FILES_EV}"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG_target-emmc += "${STM32MP_DT_FILES_ED}"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG_target-emmc += "${STM32MP_DT_FILES_EV}"
# Define extra label configuration
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[stm32mp157c-dk2] += "stm32mp157c-dk2-a7"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[stm32mp157c-dk2] += "stm32mp157c-dk2-m4"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[stm32mp157c-ev1] += "stm32mp157c-ev1-a7"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[stm32mp157c-ev1] += "stm32mp157c-ev1-m4"

UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[stm32mp157f-dk2] += "stm32mp157f-dk2-a7"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[stm32mp157f-dk2] += "stm32mp157f-dk2-m4"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[stm32mp157f-ev1] += "stm32mp157f-ev1-a7"
UBOOT_EXTLINUX_TARGETS_EXTRA_CONFIG[stm32mp157f-ev1] += "stm32mp157f-ev1-m4"

# -----------------------------------------------------------------------------
# Configure A7 examples labels
# -----------------------------------------------------------------------------
# Define MENU DESCRIPTION overrides for new A7 labels
UBOOT_EXTLINUX_MENU_DESCRIPTION_stm32mp157c-dk2-a7 = "stm32mp157c-dk2-a7-examples"
UBOOT_EXTLINUX_MENU_DESCRIPTION_stm32mp157c-ev1-a7 = "stm32mp157c-ev1-a7-examples"
UBOOT_EXTLINUX_MENU_DESCRIPTION_stm32mp157f-dk2-a7 = "stm32mp157f-dk2-a7-examples"
UBOOT_EXTLINUX_MENU_DESCRIPTION_stm32mp157f-ev1-a7 = "stm32mp157f-ev1-a7-examples"
# Define FDT overrides for new A7 labels
UBOOT_EXTLINUX_FDT_stm32mp157c-dk2-a7 = "/stm32mp157c-dk2-a7-examples.dtb"
UBOOT_EXTLINUX_FDT_stm32mp157c-ev1-a7 = "/stm32mp157c-ev1-a7-examples.dtb"
UBOOT_EXTLINUX_FDT_stm32mp157f-dk2-a7 = "/stm32mp157f-dk2-a7-examples.dtb"
UBOOT_EXTLINUX_FDT_stm32mp157f-ev1-a7 = "/stm32mp157f-ev1-a7-examples.dtb"

# -----------------------------------------------------------------------------
# Configure M4 examples labels
# -----------------------------------------------------------------------------
# Define MENU DESCRIPTION overrides for new A7 labels
UBOOT_EXTLINUX_MENU_DESCRIPTION_stm32mp157c-dk2-m4 = "stm32mp157c-dk2-m4-examples"
UBOOT_EXTLINUX_MENU_DESCRIPTION_stm32mp157c-ev1-m4 = "stm32mp157c-ev1-m4-examples"
UBOOT_EXTLINUX_MENU_DESCRIPTION_stm32mp157f-dk2-m4 = "stm32mp157f-dk2-m4-examples"
UBOOT_EXTLINUX_MENU_DESCRIPTION_stm32mp157f-ev1-m4 = "stm32mp157f-ev1-m4-examples"
# Define FDT overrides for new M4 labels
UBOOT_EXTLINUX_FDT_stm32mp157c-dk2-m4 = "/stm32mp157c-dk2-m4-examples.dtb"
UBOOT_EXTLINUX_FDT_stm32mp157c-ev1-m4 = "/stm32mp157c-ev1-m4-examples.dtb"
UBOOT_EXTLINUX_FDT_stm32mp157f-dk2-m4 = "/stm32mp157f-dk2-m4-examples.dtb"
UBOOT_EXTLINUX_FDT_stm32mp157f-ev1-m4 = "/stm32mp157f-ev1-m4-examples.dtb"

通过bitbake 查看环境变量如下:
在这里插入图片描述extlinux可以提供一个选择菜单选择使用什么dtb文件(是么?)

st-machine-flashlayout-stm32mp.inc

st-machine-common-stm32mp.inc

上面的inc最后大部分都会在st-machine-common-stm32mp.inc中被调用或者被配置。这里面涉及到很多class的内容。这部分暂时先不分析,等下一片文章分析完machine class里面的所有内容再回来分析整体的conf文件的内容
TODO…

你可能感兴趣的:(stm32,单片机,嵌入式硬件)