1.新增Kconfig部署教程。
24
README.md
@@ -36,7 +36,7 @@
|
||||
|
||||
----------
|
||||
|
||||

|
||||

|
||||
|
||||
----------
|
||||
|
||||
@@ -80,9 +80,9 @@
|
||||
|
||||
`Kconfig` 会根据配置文件自动生成配置选项界面。开发者可以通过简单的操作来选择需要启用的功能组件和设置相关参数。
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
通过修改参数,快速裁剪所需功能。配置完成后通过 `Python` 脚本自动生成配置文件。
|
||||
|
||||
@@ -128,16 +128,16 @@
|
||||
1. 从 `Gitee` 或 `Github` 仓库下载最新版本源码到本地。
|
||||
2. 将源码导入到您工程所在的目录。以STM32工程为例:
|
||||
|
||||

|
||||

|
||||
|
||||
3. 如使用的芯片已经做了 `BSP` 适配请参考芯片对应 `BSP` 中的配置教程,完成 `BSP` 配置。
|
||||
4. 移除不需要的文件 `bsp`、`document`、`module` 目录(如不需要`GIT`也可以移除`.git`文件删除)。完成后,目录结构如下所示:
|
||||
|
||||

|
||||

|
||||
|
||||
5. 将文件加入到IDE中(大部分IDE都能自动识别工程路径下的文件,无需进行此步骤)。以 `keil` 为例:
|
||||
|
||||

|
||||

|
||||
|
||||
添加 `source`、`device`、`driver` 目录下的所有文件。
|
||||
|
||||
@@ -145,13 +145,13 @@
|
||||
|
||||
1. 在 `mr-library` 目录下打开命令行工具,运行 `menuconfig` 进行菜单配置。
|
||||
|
||||

|
||||

|
||||
|
||||
注:当添加对应芯片驱动的后,将显示 `Device configure` 和 `Driver configure`。对应 `Driver configure` 请参考 `BSP` 下教程。
|
||||
|
||||
2. 选中 `Device configure` 回车进入菜单,按照需要配置功能。
|
||||
|
||||

|
||||

|
||||
|
||||
3. 配置完成后,按 `Q` 退出菜单配置界面,按`Y` 保存配置。
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
1. 在编译器中添加 `mr-library` 的包含路径,以 `keil` 为例:
|
||||
|
||||

|
||||

|
||||
|
||||
2. 配置自动初始化(GCC环境),查找您工程下以 `.ld` 为后缀的连接脚本文件(通常为 `link.ld`),在脚本文件中添加代码:
|
||||
注:如果您的是在 `keil` 等,能够自动生成链接脚本的环境下,请跳过此步骤。
|
||||
@@ -178,11 +178,11 @@
|
||||
|
||||
示例:
|
||||
|
||||

|
||||

|
||||
|
||||
3. 配置GNU语法。如果您使用的是非 `GCC` 编译器,请使能GNU语法。以 `keil` 为例:
|
||||
|
||||

|
||||

|
||||
|
||||
4. 在您的工程中引入 `#include "include/mr_lib.h"`。
|
||||
5. 在 `main` 函数中添加 `mr_auto_init();` 自动初始化函数。
|
||||
@@ -243,7 +243,7 @@ int main(void)
|
||||
|
||||
# 现在您已经完成了入门教程,开始使用MR库吧
|
||||
|
||||
1. 参考更多教程:目录 `document`。
|
||||
1. [参考更多教程](document)。
|
||||
2. 尝试基于某款芯片开发驱动,练习设备驱动编程。
|
||||
3. 尝试编写更多设备模板和开发更多功能。
|
||||
4. 欢迎您提出意见和建议。如果您对开发有兴趣,诚邀您参与到 `MR` 项目的开发中来,项目交流群:199915649(QQ)。
|
||||
|
||||
24
README_EN.md
@@ -42,7 +42,7 @@ drivers. This greatly improves the reusability of software and its extensibility
|
||||
|
||||
----------
|
||||
|
||||

|
||||

|
||||
|
||||
----------
|
||||
|
||||
@@ -89,9 +89,9 @@ code.
|
||||
`Kconfig` will automatically generate the configuration options interface based on the configuration file. Developers
|
||||
can select the functional components that need to be enabled and set relevant parameters through simple operations.
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
By modifying parameters, you can quickly tailor the required functions. After the configuration is complete,
|
||||
the `Python` script automatically generates the configuration file.
|
||||
@@ -139,19 +139,19 @@ tutorials are based on applying Kconfig).
|
||||
1. Download the latest version source code from the Gitee or Github repository to the local.
|
||||
2. Import the source code into the directory where your project is located. Taking an STM32 project as an example:
|
||||
|
||||

|
||||

|
||||
|
||||
3. If the used chip has BSP adaptation, please refer to the chip's corresponding BSP configuration tutorial to complete
|
||||
the BSP configuration.
|
||||
4. Remove unnecessary files such as `bsp`、`document`、`module` directories (you can also remove the `.git` file to delete
|
||||
GIT if not needed). The directory structure is shown below after completion:
|
||||
|
||||

|
||||

|
||||
|
||||
5. Add the files to the IDE (most ides automatically recognize the files in the project path, eliminating the need for
|
||||
this step). Take `keil` for example:
|
||||
|
||||

|
||||

|
||||
|
||||
Add all files in the `source`, `device`, `driver` directories.
|
||||
|
||||
@@ -159,7 +159,7 @@ tutorials are based on applying Kconfig).
|
||||
|
||||
1. Open the command line tool in the `mr-library` directory and run `menuconfig` to configure the menu.
|
||||
|
||||

|
||||

|
||||
|
||||
Note: When the corresponding chip driver is added, `Device configure` and `Driver configure` will be displayed.
|
||||
Please refer to the tutorial under `BSP` for `Driver configure`.
|
||||
@@ -167,7 +167,7 @@ tutorials are based on applying Kconfig).
|
||||
2. Enter the menu by pressing the Enter key on `Device configure`, and configure the desired functions according to
|
||||
needs.
|
||||
|
||||

|
||||

|
||||
|
||||
3. After configuration is complete, press `Q` to exit the menu configuration interface, press `Y` to save the
|
||||
configuration.
|
||||
@@ -181,7 +181,7 @@ tutorials are based on applying Kconfig).
|
||||
|
||||
1. Add the include paths of `mr-library` in the compiler, taking `keil` as an example:
|
||||
|
||||

|
||||

|
||||
|
||||
2. Configure automatic initialization (GCC environment), find the link script file with suffix `.ld` in your project
|
||||
directory (usually `link.ld`), and add the following code to the script file:
|
||||
@@ -196,11 +196,11 @@ tutorials are based on applying Kconfig).
|
||||
|
||||
Example:
|
||||
|
||||

|
||||

|
||||
|
||||
3. Configure the GNU syntax. If you are using a non-gcc compiler, enable GNU syntax. Take `keil` for example:
|
||||
|
||||

|
||||

|
||||
|
||||
4. Include `#include "include/mr_lib.h"` in your project.
|
||||
5. Add the automatic initialization function `mr_auto_init();` in the main function.
|
||||
@@ -261,7 +261,7 @@ int main(void)
|
||||
|
||||
# Now that you have completed the introductory tutorial, start using the MR Library.
|
||||
|
||||
1. See more tutorials: directory `document`.
|
||||
1. [See more tutorials](document).
|
||||
2. Try developing drivers based on certain chips to practice device driver programming.
|
||||
3. Try writing more device templates and developing more features.
|
||||
4. Welcome to provide your opinions and suggestions. If you are interested in development, you are welcome to
|
||||
|
||||
206
document/Kconfig.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# 如何为项目引入Kconfig配置系统
|
||||
|
||||
<!-- TOC -->
|
||||
* [如何为项目引入Kconfig配置系统](#如何为项目引入kconfig配置系统)
|
||||
* [环境搭建](#环境搭建)
|
||||
* [验证 python 环境](#验证-python-环境)
|
||||
* [安装Kconfig](#安装kconfig)
|
||||
* [C语言头文件生成脚本](#c语言头文件生成脚本)
|
||||
* [应用](#应用)
|
||||
* [创建Kconfig](#创建kconfig)
|
||||
<!-- TOC -->
|
||||
|
||||
项目中经常会有通过宏配置或选择参数:
|
||||
|
||||
```c
|
||||
#ifdef CFG_ENABLE
|
||||
#define CFG_ARGS "test"
|
||||
void printf_args(void)
|
||||
{
|
||||
printf("args: %s\n", CFG_ARGS);
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
当项目规模较小,配置项和依赖关系相对简单时,我们可以通过手动修改源代码来实现配置功能。但是,随着项目规模的增长和配置复杂度的增加,这种方式也会出现一些问题。
|
||||
|
||||
随着代码体量和调用关系的增多,对配置者来说`很难完全熟悉`
|
||||
代码结构及各模块之间的依赖关系。同时,如果配置项设置较为`随意且缺乏约束`,也很可能导致`错误配置`。这对项目质量和维护都带来一定难度。
|
||||
|
||||
对于规模较大的项目来说,需要一套专业的配置管理系统来解决这些问题。Kconfig正是为了应对这种需求而产生的。它通过配置脚本定义各配置选项及其依赖关系,并提供`图形化界面`
|
||||
供配置者操作。同时还会检查配置`合理性`,帮助我们实现定制化构建的同时`防止错误配置`。
|
||||
|
||||
如果有接触过Linux内核或者嵌入式操作系统RTTHREAD等,相信对Kconfig系统都不陌生。Kconfig是Linux内核和许多其他系统广泛使用的一款配置管理工具。它可以让开发人员在编译时选择性地包含或排除某些功能模块。
|
||||
|
||||
Kconfig
|
||||
使用配置脚本定义各种配置选项及其依赖关系。通过图形或字符型用户界面,开发者可以查看并设置各种配置。然后Kconfig会生成 `.config`
|
||||
文件保存选择结果。在编译的时候,会根据 `.config` 文件里设置的符号自动包含或排除对应的源代码。
|
||||
|
||||

|
||||
|
||||
# 环境搭建
|
||||
|
||||
## 验证 python 环境
|
||||
|
||||
Kconfig依赖于 ` python` ,如果没有 ` python` 环境请自行安装。
|
||||
|
||||
在命令行中使用所示命令验证:
|
||||
|
||||
```cmd
|
||||
python --version
|
||||
```
|
||||
|
||||
显示(正确显示版本即可):
|
||||
|
||||
```cmd
|
||||
Python 3.11.4
|
||||
```
|
||||
|
||||
## 安装Kconfig
|
||||
|
||||
```cmd
|
||||
python -m pip install windows-curses
|
||||
python -m pip install kconfiglib
|
||||
```
|
||||
|
||||
在命令行中使用所示命令验证:
|
||||
|
||||
```cmd
|
||||
menuconfig -h
|
||||
```
|
||||
|
||||
显示信息即安装成功。
|
||||
|
||||
## C语言头文件生成脚本
|
||||
|
||||
Kconfiglib 生成的是 `.config` 文件,并非C语言文件,需要使用脚本生成,`将以下代码复制到文件中并命名为kconfig.py`。
|
||||
|
||||
```python
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
from kconfiglib import Kconfig, split_expr, expr_value, expr_str, BOOL,
|
||||
TRISTATE, TRI_TO_STR, AND, OR
|
||||
|
||||
|
||||
def generate_config(kconfig_file, config_in, config_out, header_out):
|
||||
print("Parsing " + kconfig_file)
|
||||
kconf = Kconfig(kconfig_file, warn_to_stderr=False,
|
||||
suppress_traceback=True)
|
||||
|
||||
# Load config files
|
||||
print(kconf.load_config(config_in))
|
||||
|
||||
# Write merged config
|
||||
print(kconf.write_config(config_out))
|
||||
|
||||
# Write headers
|
||||
print(kconf.write_autoconf(header_out))
|
||||
|
||||
with open(header_out, 'r+') as header_file:
|
||||
content = header_file.read()
|
||||
header_file.truncate(0)
|
||||
header_file.seek(0)
|
||||
|
||||
# Remove CONFIG_ and MR_USING_XXX following number
|
||||
content = content.replace("#define CONFIG_", "#define ")
|
||||
|
||||
# Add the micro
|
||||
header_file.write("#ifndef _CONFIG_H_\n")
|
||||
header_file.write("#define _CONFIG_H_\n\n")
|
||||
|
||||
header_file.write("#ifdef __cplusplus\n")
|
||||
header_file.write("extern \"C\" {\n")
|
||||
header_file.write("#endif /* __cplusplus */\n\n")
|
||||
|
||||
# Write back the original data
|
||||
header_file.write(content)
|
||||
|
||||
# Add the micro
|
||||
header_file.write("\n#ifdef __cplusplus\n")
|
||||
header_file.write("}\n")
|
||||
header_file.write("#endif /* __cplusplus */\n\n")
|
||||
header_file.write("#endif /* _CONFIG_H_*/\n")
|
||||
|
||||
|
||||
def main():
|
||||
kconfig_file = 'Kconfig'
|
||||
config_in = '.config'
|
||||
config_out = '.config'
|
||||
header_out = 'config.h'
|
||||
generate_config(kconfig_file, config_in, config_out, header_out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
修改`main`函数中`header_out `可修改生成的函数文件名。
|
||||
|
||||
此脚本去除了Kconfig默认添加的`CONFIG_`前缀,并为其加上了`_CONFIG_H_`
|
||||
和`C`声明。
|
||||
|
||||
# 应用
|
||||
|
||||
## 创建Kconfig
|
||||
|
||||
新建一个名字为 `Kconfig` 的文件(注意没有后缀名),和上一步中中创建的 `kconfig.py` 的文件放在一起。
|
||||
|
||||
```Kconfig
|
||||
mainmenu "Demo"
|
||||
|
||||
menu "Args configure"
|
||||
config CFG_ARG1
|
||||
bool "Enable arg1"
|
||||
default n
|
||||
|
||||
config CFG_ARG2
|
||||
int "Arg2 number"
|
||||
default 8
|
||||
range 0 64
|
||||
|
||||
endmenu
|
||||
```
|
||||
|
||||
在当前目录下调用命令行,输入:
|
||||
|
||||
```cmd
|
||||
menuconfig
|
||||
```
|
||||
|
||||
就可以看到我们刚刚写的Demo界面
|
||||
|
||||

|
||||
|
||||
回车后就可以看到配置的2个参数:
|
||||
|
||||

|
||||
|
||||
设置的范围也在输入时生效了:
|
||||
|
||||

|
||||
|
||||
配置完成后按`Q`退出,`Y`保存配置。
|
||||
|
||||
在当前目录下调用命令行,输入:
|
||||
|
||||
```cmd
|
||||
python kconfig.py
|
||||
```
|
||||
|
||||
运行 `python` 脚本生成`.h`文件。
|
||||
|
||||
运行结果:
|
||||
|
||||
```cmd
|
||||
Parsing Kconfig
|
||||
Loaded configuration '.config'
|
||||
Configuration saved to '.config'
|
||||
Kconfig header saved to 'config.h'
|
||||
```
|
||||
|
||||
显示生成`config.h`成功。打开这个文件:
|
||||
|
||||

|
||||
BIN
document/picture/Kconfig/Kconfig.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
document/picture/Kconfig/Kconfig1.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
document/picture/Kconfig/Kconfig2.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
document/picture/Kconfig/Kconfig3.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
document/picture/Kconfig/Kconfig4.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |