LV01-01-AliOSThings-09-源码与编译-02-kconfig基础

本文主要是源码与编译——kconfig基础知识的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows版本 windows11
Ubuntu版本 Ubuntu22.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
点击查看本文参考资料
分类 网址 说明
官方网站 阿里云 阿里云官网主页
阿里生活物联平台 生活物联网平台(飞燕平台)主页
AliGenie 天猫精灵开放平台AliGenie主页
阿里物联网平台 阿里物联网平台主页
Bluetooth 技术网站 蓝牙协议规范什么的可以来这里找
Telink Telink | Chips for a Smarter IoT (telink-semi.com)
Telink中文官网
开发手册 AliOS Things开发指南 AliOS Things开发指南,这里是最新版本,可以直接从官网找到
AliOS Things开发指南 AliOS Things应用开发指南,这里应该是3.3版本的完整开发文档
AliOS Things开发指南(3.0) AliOS Things应用开发指南,这里应该是3.0版本的完整开发文档
生活物联网平台开发文档 生活物联网平台(飞燕平台)开发文档
《设备端开发指南》
Wi-Fi IoT品类定义与功能开发 天猫精灵IoT开放平台——Wi-Fi IoT品类定义与功能开发
硬件平台 mk3080 WiFi开发板 WiFi开发板使用指南-阿里云开发者社区
esp8266开发板 一个教程:ESP8266-NodeMCU开发板详解-太极创客 (taichi-maker.com)
TLSR8258 Datasheet Datasheet for Telink BLE + IEEE802.15.4 MultiStandard Wireless SoC TLSR8258
参考资料 AliOS Things 3.0 应用开发指南 这个只是一篇参考文章,里面是一些环境搭建相关的,可以参考
IP知识百科 - 华为 (huawei.com) IP的一些相关知识点
点击查看相关文件下载
分类 网址 说明
蓝牙规范相关文档 Core Specification 5.2 核心规格 5.2,该规范定义了创建可互操作的Bluetooth 设备所需的技术。
《Core_v5.2.pdf》
Mesh Model(v1.1) 本Bluetooth 规范定义了模型(以及它们所需的状态和消息),这些模型用于在mesh 网络中的节点上执行基本功能,超出了Bluetooth Mesh 配置文件 规范中定义的基础模型。
本规范包括定义跨设备类型标准功能的通用模型,以及支持关键mesh 场景的模型,如照明控制、传感器、时间和场景。
《MshMDL_v1.1.pdf》
Mesh Profile(v1.0.1) 该Bluetooth 规范定义了基本要求,以实现可互操作的mesh 网络解决方案,用于Bluetooth 低能量无线技术。
《MshPRFv1.0.1.pdf》
Mesh Device Properties 本规范包含Bluetooth Mesh 配置文件 和Bluetooth Mesh 模型规范所要求的设备属性的定义。
但是跟之前的有些区别,我主要看的之前的版本:《MMeshDeviceProperties_v1.2.pdf》
GATT Specification Supplement GATT Specification Supplement | Bluetooth® Technology Website。
好像可以在线看:《GATT Specification Supplement》
Assigned Numbers GATT的一些类型定义可以在这里找。
AliOS Things alios-things/AliOS-Things Gitee上的AliOSThings SDK源码仓库
alibaba/AliOS-Things GitHub上的AliOSThings SDK源码仓库
天猫精灵蓝牙Mesh协议栈 alibaba-archive/genie-bt-mesh-stack GitHub上的天猫精灵蓝牙Mesh协议栈源码仓库。
之前是在alibaba/genie-bt-mesh-stack这个仓库。
写笔记的时候最新提交为faf523618a6a2560090fc423222b9db80984bb7a
蓝牙Mesh设备开发指南 阿里云生活服务平台开发手册——蓝牙设备开发一节中的内容

这个其实在前面学习linux的时候就学习过,这里再简单介绍一下吧。

一、menuconfig

1. 打开图形配置界面

自AliOS Things 2.1开始,引入了基于Menuconfig的图形配置系统,组件配置文件(Config.in)是配置系统工作的基础。

1.1 SDK源码目录

我们在AliOS-Things源码目录敲aos make menuconfig文件就可以打开图形配置界面啦:

image-20231124190100105

1.2 工程目录

其实我们在工程目录下敲也可以打开一个图形配置界面,我们可以在 helloworld_mk3080 目录下打开图形配置文件看一下:

image-20231124190422228

可以看到这里的配置选项会比源码目录中少很多。

2. 配置操作

2.1 预定义配置

其实前面我们知道,我们在图形配置界面进行配置的时候,其实他原本是有一个默认的配置文件的,这个配置就是预定义配置。预定义配置是由系统预设、或者用户创建的配置内容,可以在工程中复用并作为工程配置的起点。系统使用统一的SDK目录 AOS_SDK_PATHbuild/configs目录存放预定义配置文件。用户可以加载已有配置,也可以将自定义配置保存至该目录,当我们自己创建配置文件的时候需要遵循以下规则:

  • 默认的配置文件名以 _defconfig结尾,例如profile-linkkit-mk3060_defconfig

  • 文件名里面不可以包含@,若是需要表达app@Board这样的含义,可以使用其他字符代替,例如app-board_defconfig

2.2 加载预定义配置

1
2
3
# SDK源码目录下 ~/AliOS-Things-SDK
aos make list-defconfig # 检查有效配置列表
aos make <profile-name_defconfig> # 加载预定义配置

我们现在来加载一个默认配置文件,我们先看一下图形配置界面中的BSP配置项:

image-20231124192614594

接下来我们来加载一个profile-linkkitapp_esp8266_defconfig配置文件,然后再来看一下:

1
2
3
4
5
6
7
8
9
10
11
12
hk@vm:~/AliOS-Things-SDK$ aos make profile-linkkitapp_esp8266_defconfig
aos-cube version: 0.5.11
platform/board/stm32f103rb-nucleo/Config.in:3:warning: defaults for choice values not supported
platform/board/esp8266/Config.in:3:warning: defaults for choice values not supported
platform/board/mk3072/Config.in:3:warning: defaults for choice values not supported
application/example/example_legacy/uai_demo/uai_kws_demo/Config.in:15:warning: defaults for choice values not supported
application/example/example_legacy/uai_demo/uai_cifar10_demo/Config.in:15:warning: defaults for choice values not supported
warning: (ENABLE_OTA) selects ENABLE_AOS_OTA which has unmet direct dependencies (<choice> && AOS_APP_LINKKIT_DEMO)
warning: (ENABLE_OTA) selects ENABLE_AOS_OTA which has unmet direct dependencies (<choice> && AOS_APP_LINKKIT_DEMO)
#
# configuration written to .config
#

然后我们再打打开配置界面看一下:

image-20231124192902898

可以看到这里已经变成了ESP8266,他还有一些其他的配置项会改变,这里就不再细说了。

2.2 保存预定义配置

我们平时使用图形配置界面配置好后,我们可以将配置文件保存为默认配置文件到对应的目录,这样后边我们更换开发板或者修改配置文件后就很容易切换回原来的配置啦:

1
2
3
4
5
6
7
# 情形一:保存所有配置选项,包括未配置选项
# <AOS_SDK_PATH>为AliOS-Things源码目录
cp .config <AOS_SDK_PATH>/build/configs/<config-name>_defconfig

# 情形二:保存最少配置项,不包括默认选项
aos make savedefconfig
cp .defconfig <AOS_SDK_PATH>/build/configs/<config-name>_defconfig
image-20231124193715749

显然可以看到.config文件配置项很多,而.defconfig文件配置项就很少,但是一般还是建议保存全部配置文件,毕竟更安全一些。

3. 图形界面修改配置

这里我们要看meunconfig图形界面配置后影响了哪些文件,所以这里我们可以先将源码目录进行git管理,注意可以使用下面的.gitignore文件:

点击查看 .gitignore文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
trace_test
activate
out
*.out
*.db
.gdbinit
.gdbinitkernel
.gdbinitframework
.gdbinitapp
.openocd_cfg
copy_bootloader_output_for_eclipse
copy_output_for_eclipse
*.sw*
build/compiler
build/OpenOCD
si
.cproject
.project
*.pyc
aos_partition_*.bin
OSX
example/flash/flash.mk
example/flash/main.c
example/flash/README.md
settings.json
build/cmd/win32/Python27/Lib/encodings/*.pyc
*.d
build/scripts/config_mk.py
build/scripts/*.pyc
$Recycle.Bin
.sconsign.dblite
cb2201*.map
projects/autogen/*
# source sight project files
*.IAB
*.IAD
*.IMB
*.IMD
*.PFI
*.PO
*.PR
*.PRI
*.PS
*.SearchResults
*.WK3
.DS_Store

3.1 修改保存配置项

这个很简单,这里就不写了。当我们修改保存后,会将这些配置文件写入一个.config文件:

image-20231124195513688

这个.config配置文件的路径我们是可以自定义的,默认的话是在Alios-Things源码目录下。那个我们选择OK的时候,构建系统就会自动把.config文件配置信息同步到aos_config.h中。为什么有这么个文件?我们知道.config文件是给图形配置界面用的,我们在图形配置界面进行的配置最终肯定是要影响代码的,那怎么通过这些配置项来影响代码?我们打开这个.h文件一看就会看到这里面全是宏,这下我们很容易就明白了:

image-20231124195958154

要注意的是这个头文件分为两个部分:用户自定义宏和组件的配置所对应的宏。初始情况下,用户自定义的宏区域不包含任何宏,由用户自行添加,这里我们添加自己的宏定义的话,不会被覆盖掉。组件配置对应的宏是和.config里面的配置一一对应的,两者是由编译系统自动实现同步。

3.2 影响了哪些文件?

那我们进行图形界面配置后,影响了哪些文件?我们修改一个配置项看一下,我们修改一下应用版本,我们修改为下面的版本(原来为app-1.0.0-20200214.140831):

image-20231124194835479

然后我们退出并保存配置项,然后敲一下git status命令:

image-20231124195044046

会看到由有上面3个文件被修改了,我们只需要关注.config和aos_config.h文件即可,那个带有.config.old的文件应该是个备份文件之类的吧,我们不需要关注,我么看一下都产生了哪些变化,我们敲一下git diff命令:

image-20231124195422245

可以看到这两个文件中都有版本号的配置发生了改变。

4. 相关配置文件

这一部分我们在自己创建的工程目录中操作,其实上面在SDK源码目录中的文件情况对工程目录也是一样的,另外还会有一些文件我们接下来一工程目录分析一下这些文件。我们用相同的方式看一下会有哪些文件发生变化(我这里直接创建工程,没有编译,直接提交所有文件到版本库,然后修改一个配置项就会有如下文件发生改变):

image-20231124201500548

会发现修改的文件更多了,但是实际我们需要关注的只有下面几个:

  • 配置参数文件
1
2
3
# 配置参数文件
修改: .config
修改: aos_config.h
image-20231124202621010

.config 和 aos_config.h两个文件是同步的,不管更改任何一个,只要我们敲下aos命令,这两个文件都会同步更新,由于menuconfig菜单界面使用的是.config文件,所以menuconfig菜单界面也会同时改变,这三者无论修改哪一个,另外两个都会进行更新。注意,SDK源码目录和工程源码目录下都会有.config和aos_config.h文件,我们在工程源码中编译的话,就主要看工程源码的就可以,要是配置SDK源码的话,就关注SDK里面的文件就可以了。

  • 配置后参与编译的文件
1
2
3
# 配置后参与编译的文件
修改: out/config/auto.conf
修改: out/config/autoconf.h
image-20231124202418185

这两个文件中的内容都是配置选项, auto.conf 是给Makefile文件用的,用于实际编译使用,autoconf.h是我们工程源码使用的,这两个文件是实际参与编译的文件,为什么这么麻烦?当然也可以是直接使用编译配置文件,但是AliOS-Things为了开发者的便利,才这样的来设计。

二、Kconfig语法

Kconfig是有语法的,它在SDK中有一个文档:

1
AliOS-Things-SDK/build/kconfig/Linux64/kconfig-language.txt

这个文档就是Kconfig文件的所有语法。

1. 菜单选项

大多数的选项都定义了一个配置选项,其它选项则有助于对它们进行组织。一个配置选项定义可以是下面的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13


config MODVERSIONS

bool "Set version information on all module symbols"

depends MODULES

help

Usually, modules have to be recompiled whenever you switch to a new

kernel. ...

每行都是以config关键字开始,并可以接多个参数。”config” 为定义了一新的配置选项。下面的几行定义了该配置选项的属性。属性可以是该配置选项的类型、输入提示(input prompt)、依赖关系、帮助信息和默认值。配置选项可以用相同的名字定义多次,但每个定义只能有一个输入提示并且类型还不能冲突。

2. 菜单属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
菜单选项可以有多个属性。并不要求这些属性可以用在任何地方(见语法)。

类型定义:"bool"/"tristate"/"string"/"hex"/"int"

每个配置选项都必须指定类型。有两个基本类型:tristate 和 string,其他类型都是基于这两个基本类型。类型定义可以用输入提示,所以下面的两个例子是等价的:

bool "Networking support"



bool

prompt "Networking support"



输入提示: "prompt " <prompt> ["if" <expr>]

每个菜单选项最多只能有一个显示给用户的输入提示。可以用 "if" 来表示该提示的依赖关系,当然这是可选的。

默认值:"default" <expr> ["if" <expr>]

一个配置选项可以有任意多个默认值。如果有多个默认值,那么只有第一个被定义的值是可用的。默认值并不是只限于应用在定义他们的菜单选项。这就意味着默认值可以定义在任何地方或被更早的定义覆盖。如果用户没有设置(通过上面的输入提示),配置选项的值就是默认值。如果可以显示输入提示的话,就会把默认值显示给用户,并可以让用户进行修改。默认值的依赖关系可以用 "if" 添加。(可选项)

依赖关系:"depends on"/"requires" <expr>

为一菜单选项定义依赖关系。如果定义了多个依赖关系,它们之间用 '&&' 间隔。依赖关系也可以应用到该菜单中所有的其它选项(同样接受一if表达式),所以下面的两个例子是等价的:

bool "foo" if BAR

default y if BAR

and

depends on BAR

bool "foo"

default y


反向依赖关系:"select" <symbol> ["if" <expr>]

尽管普通的依赖关系可以降低选项的上限,反向依赖能将这一限制降的更低。当前菜单选项的值是symbol的最小值。如果symbol被选择了多次,上限就是其中的最大值。反向依赖只能用在 boolean 或 tristate 选项上。


数据范围:"range" <symbol> <symbol> ["if" <expr>]

int和hex类型的选项设置可以接受输入值范围。用户只能输入大于等于第一个symbol,小于等于第二个symbol的值。



帮助信息: "help" or "---help---"

定义一帮助信息。帮助信息的结束就由缩进的水平决定的,这也就意味着信息是在第一个比帮助信息开始行的缩进小的行结束。"---help---""help" 在实现的作用上没有区别,"---help---" 有助于将文件中的配置逻辑与给开发人员的提示分开。

3. 菜单依赖关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
依赖关系决定了菜单选项是否可见,也可以减少tristate的输入范围。tristate逻辑比boolean逻辑在表达式中用更多的状态(state)来表示模块的状态。依赖关系表达式的语法如下:

<expr> ::= <symbol> (1)

<symbol> '=' <symbol> (2)

<symbol> '!=' <symbol> (3)

'(' <expr> ')' (4)

'!' <expr> (5)

<expr> '&&' <expr> (6)

<expr> '||' <expr> (7)

表达式是以优先级的降序列出的。

(1) 将symbol赋给表达式。boolean和tristate类型的symbol直接赋给表达式。所有其它类型的symbol都赋 'n'

(2) 如果两个symbol相等,返回'y',否则为'n'

(3) 如果两个symbol相等,返回'n',否则为'y'

(4) 返回表达式的值。用于改变优先级。

(5) 返回 !(/expr/) 的结果。

(6) 返回 min(/expr/,/expr/) 的结果。

(7) 返回 max(/expr/,/expr/) 的结果。

一个表达式的值可以是'n''m''y'(或者是计算的结果 0,1,2)。当表达式的值为'm''y'的时候,菜单项才是可见的。

symbol有两种类型:不可变的和可变的。不可变的symbol是最普通的,由'config'语句定义,完全由数字、字母和下划线组成。不可变的symbol只是表达式的一部分。经常用单引号或双引号括起来。在引号中,可以使用任何字符,使用引号要用转义字符'/'

4. 菜单结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
菜单在树中的位置可由两种方法决定。第一种可以是这样:

menu "Network device support"

depends NET

config NETDEVICES

...

endmenu

所有的在"menu" ... "endmenu" 之间都是"Network device support"的子菜单。所有的子菜单选项都继承了父菜单的依赖关系,比如,"NET"的依赖关系就被加到了配置选项NETDEVICES的依赖列表中。

还有就是通过分析依赖关系生成菜单的结构。如果菜单选项在一定程度上依赖于前面的选项,它就能成为该选项的子菜单。首先,前面的(父)选项必须是依赖列表中的一部分并且它们中必须有满足下面两个条件的选项:

如果父选项为'n',子选项必须不可见。

如果父选项可见,子选项才能可见。

config MODULES

bool "Enable loadable module support"

config MODVERSIONS

bool "Set version information on all module symbols"

depends MODULES

comment "module support disabled"

depends !MODULES

MODVERSIONS 直接依赖 MODULES,这就意味着如果MODULES不为'n',该选项才可见。换句话说,当MODULES可见时,选项才可见(MODULES的(空)依赖关系也是选项依赖关系的一部分)。

5. kconfig关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
配置文件描述了菜单选项,每行都是以一关键字开头(除了帮助信息)。下面的关键字:

- config

- menuconfig

- choice/endchoice

- comment

- menu/endmenu

- if/endif

- source

5个同样可以用在菜单选项定义的开始。

5.1 config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
   "config" <symbol>

<config options>

config是关键字,表示一个配置选项的开始;紧跟着的<symbol>是配置选项的名称,省略了前缀"CONFIG_"

例如:

config TMPFS_POSIX_ACL

bool "Tmpfs POSIX Access Control Lists"

depends on TMPFS

select GENERIC_ACL

help

POSIX Access Control Lists (ACLs) support permissions for users and

groups beyond the owner/group/world scheme.

To learn more about Access Control Lists, visit the POSIX ACLs for

Linux website <http://acl.bestbits.at/>.

If you don't know what Access Control Lists are, say N.

解析:config是关键字,表示一个配置选项的开始;紧跟着的TMPFS_POSIX_ACL是配置选项的名称,省略了前缀"CONFIG_"

bool表示变量类型,即"CONFIG_ TMPFS_POSIX_ACL "的类型,有5种类型:bool、tristate、string、hex和int,其中tristate和string是基本的类型

bool变量的值: y和n

tristate变量的值: y、n和m

string变量的值: 字符串

bool之后的字符串“Tmpfs POSIX Access Control Lists”是提示信息,在配置界面中上下移动光标选中它时,就可以通过按空格或回车键来设置CONFIG_ TMPFS_POSIX_ACL的值。

depends on:表示依赖于XXX,“depends on TMPFS”表示只有当TMPFS配置选项被选中时,当前配置选项的提示信息才会出现,才能设置当前配置选项。

5.2 menuconfig

1
2
3
4
5
 "menuconfig" <symbol>

<config options>

此关键字和前面的关键字很相似,但它在前面的基础上要求所有的子选项作为独立的行显示。

5.3 choices

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  "choice"

<choice options>

<choice block>

"endchoice"

该关键字定义了一组选择项,并且选项可以是前面描述的任何属性。尽管boolean只允许选择一个配置选项,tristate可以抒多个配置选项设为'm',但选项只能是boolean或tristate类型。这可以在一个硬件有多个驱动的情况下使用,最终只有一个驱动被编译进/加载到内核,但所有的驱动都可以编译成模块。选项可以接受的另一个选项是"optional",这样选项就被设置为'n',没有被选中的。

例如:

choice条目将多个类似的配置选项组合在一起,供用户单选或多选

choice

prompt "ARM system type"

default ARCH_VERSATILE

config ARCH_AAEC2000

.........

config ARCH_REALVIEW

.........

endchoice

prompt "ARM system type"给出提示信息“ARM system type”,光标选中后回车进入就可以看到多个config条目定义的配置选项。choice条目中定义的变量只有bool和tristate。

5.4 comment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   "comment" <prompt>

<comment options>

这里定义了在配置过程中显示给用户的注释,该注释还将写进输出文件中。唯一可用的可选项是依赖关系。

例如:

comment条目用于定义一些帮助信息,出现在界面的第一行,如在arch/arm/Kconifg中有如下代码:

menu "Floating point emulation"

comment "At least one emulation must be selected"

config FPE_NWFPE

.........

config FPE_NWFPE_XP

在界面中如下所示:

762927-20161016221850702-879475685

5.5 menu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   "menu" <prompt>

<menu options>

<menu block>

"endmenu"

这里定义了一个菜单,详细信息请看前面的"菜单结构"。唯一可用的可选项是依赖关系。

例如:

menu条目用于生成菜单,其格式如下:

menu "Floating poing emulation"

config FPE_NWFPE

..............

config FPE_NWFPE_XP

.............

endmenu

menu之后的Floating poing emulation是菜单名,menu和endmenu间有很多config条目,在配置界面中如下所示:

Floating poing emulation--->

[] FPE_NWFPE

[] FPE_NWFPE_XP

5.6 if

1
2
3
4
5
6
7
   "if" <expr>

<if block>

"endif"

这里定义了if结构。依赖关系<expr>被加到所有在if ... endif 中的菜单选项中。

5.7 source

1
2
3
source条目用于读取另一个Config.in文件,如:

source "net/Kconifg"