ESP32开发历程(3)开始踩坑:menuconfig,CMakeLists与component

menuconfig

因为好多资料里都涉及到menuconfig,所以去扒拉扒拉这到底是是个啥

menuconfig是Linux平台用于管理代码工程、模块及功能的实用工具。上至决定某一程序模块是否编译,下到某一行具体的代码是否需要编译以及某个项的值在本次编译时该是什么都可由menuconfig来定义。
menuconfig的使用方式通常是在编译系统之前在系统源代码根目录下执行 make menuconfig 命令从而打开一个图形化配置界面,再通过对各项的值按需配置从而达到影响系统编译结果的目的。
linux下的menuconfig,跟老的ESP-IDF的menuconfig有点像

Vscode中ESP-IDF的menuconfig
个人认为这个玩意就类似于CubeMX……的强化版,能够配置功能之类的

menuconfig 其实只能算是一个“前端”,用于支撑它、决定它拥有什么配置项的“后端”则被称为 Kconfig。

Kconfig

Kconfig 严格来讲是一种编程语言,它拥有自己的语法及结构。正是这些语法和结构组成了menuconfig在用户眼前不同的表现形式。
menuconfig是Linux平台基于Kconfig用于管控代码实用工具。
Kconfig常用的几个知识点有以下五个:
1.config模块
2.menuconfig模块
3.menu模块
4.choice模块
5.if 与 depends on 模块

config模块

一个config就表示一个配置项。

config 配置项名
*配置项类型
*配置项提示语
*其它选项

配置项名表示最终保存在 .config 文件中的键值对项的键名,通常用全大写和单词之间以下划线隔开的形式书写。
配置项类型就是基础类型,可选的类型有:bool、tristate、string、hex、int。
bool 表示布尔型在.config中以 y 和 n 表示。
tristate是三态类型,通常用在内核驱动控制中。在.config中以 y 、n和m表示。y表示将驱动编译进内核镜像,n表示不编译,m表示将驱动编译为ko形式。
string是普通字符串类型,直接将在menuconfig图形界面中用户输入的值原样保存在.config中。
hex是十六进制形式,只能输入0~F的内容。
int是十进制整数形式,只能输入数字。
配置项提示语以prompt开头,后跟一个空格字符,然后就是用双引号包围的文字提示语。作用就是在menuconfig图形界面中作为配置项的提示语。

在 这位大神的博客里有小实验:https://www.cnblogs.com/chorm590/p/13977818.html

menuconfig可以认为是上一节 config 中的升级版。
首先它自己也是一个正常的配置项,通过自己的配置值来决定另外一组配置项是否作为子菜单的形式显示出来并供用户配置。
可以简单地理解为一个小小的菜单树

是一个带了菜单功能的配置项

menu 是一个纯粹的菜单项。menu本身不可配置,只是用来标记其内部可能拥有子配置项。

choice与if与depends on模块

choice是单选模块。
if 与 depends on 模块都属于 config 配置项中的”其它选项“。
它们的作用是等价的,都是根据指定的配置项是否被配置来决定本配置项的显示与否。

感谢

https://www.cnblogs.com/chorm590/p/13977818.html

可以在通过修改 main\Kconfig.projbuild来加入一些有趣的功能

例:实现在 menuconfig 中对 LED的GPIO 进行配置

menu "Example Configuration"
   config BLINK_GPIO
       int "Blink GPIO number"
       range 0 34
       default 5
       help
           GPIO number (IOxx) to blink on and off.
           Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
           GPIOs 35-39 are input-only so cannot be used as outputs.
endmenu

CmakeLists

每个项目都包含一个或多个组件,这些组件可以是 ESP-IDF 的一部分,可以是项目自身组件目录的一部分,也可以从自定义组件目录添加。
组件是 COMPONENT_DIRS 列表中包含 CMakeLists.txt 文件的任何目录。

向ESP-IDF添加自定义组件的时候,要对CMakerLists进行修改

将文件添加到main文件夹中:

set(srcs "gpio_example_main.c"
        "spi_esp32.c"
    )
idf_component_register(SRCS ${srcs})

上述修改是在main中CMakeLists中修改
其中,.c文件直接按照第二行的格式添加即可

使用其它路径时:

标准工程管理:

新建文件夹作为组件,以LED为例,新建文件夹:LED
在LED中新建两个文件夹,分别为includesrc
include文件夹中存放.h文件:led.h
src文件夹中存放.c文件:led.c
在创建C和H文件后,还需要在LED目录下新建个CMAKE文档,如下方

set(led_srcs "src/led.c")
 
idf_component_register(SRCS "${led_srcs}"
                       INCLUDE_DIRS "include")

其中:
第一行意为将字符串"src/led.c"赋值给led_srcs
第二、三行idf_component_register

最小组件 CMakeLists.txt 文件通过使用 idf_component_register 将组件添加到构建系统中。

idf_component_register(SRCS “foo.c” “bar.c”
   INCLUDE_DIRS “include” REQUIRES mbedtls)

SRCS 是源文件列表(.c、.cpp、.cc、.S),里面所有的源文件都将会编译进组件库中。
INCLUDE_DIRS 是目录列表,里面的路径会被添加到所有需要该组件的组件(包括 main 组件)全局 include 搜索路径中。
REQUIRE 实际上并不是必需的,但通常需要它来声明该组件需要使用哪些其它组件,请参考 组件依赖。
上述命令会构建生成与组件同名的库,并最终被链接到应用程序中。
上述目录通常设置为相对于 CMakeLists.txt 文件的相对路径,当然也可以设置为绝对路径。

参数"${led_srcs}"表示led_srcs变量的值

通过这种方法,我们就可以使用自己的组件了

不标准工程文件管理

新建一个文件夹LED,直接将.c.h文件塞进LED文件夹
新建并配置CMakeLists文件如下

set(led_srcs "src/led.c")
idf_component_register(SRCS "${led_srcs}"
                       INCLUDE_DIRS ".")

综述

标准插件管理

1.文件分门别类新建文件夹放好
2.制作CMakeLists
3.主程序调用

main\Kconfig.projbuild功能控住(编译控制)

1.通过模板准备好功能,框架模板见上
2.调用时可以在sdkconfig中找到功能变量(sdkconfig相当于是变量表)

感谢

https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-guides/build-system.html#component-directories
https://blog.csdn.net/weixin_42193239/article/details/121684987
https://www.jianshu.com/p/67175d63c498
https://blog.csdn.net/qq_41431423/article/details/121121510?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-5-121121510-blog-112724707.pc_relevant_multi_platform_whitelistv2&spm=1001.2101.3001.4242.4&utm_relevant_index=7

附实战

led.h

#ifndef __LED_H
#define __LED_H

#include "sdkconfig.h"
#include "driver/gpio.h"

/* Can use project configuration menu (idf.py menuconfig) to choose the GPIO to blink,
   or you can edit the following line and set a number here.
*/
#define BLINK_GPIO CONFIG_BLINK_GPIO

void led_init(void);
void led_on(void);
void led_off(void);

#endif

led.c

#include "led.h"

void led_init(void)
{
    /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
       muxed to GPIO on reset already, but some default to other
       functions and need to be switched to GPIO. Consult the
       Technical Reference for a list of pads and their default
       functions.)
    */
    gpio_pad_select_gpio(BLINK_GPIO);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
}

void led_on(void)
{
    gpio_set_level(BLINK_GPIO, 1);
}

void led_off(void)
{
    gpio_set_level(BLINK_GPIO, 0);
}

CMakeLists

set(led_srcs "src/led.c")

idf_component_register(SRCS "${led_srcs}"
                       INCLUDE_DIRS "include")

main

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "led.h"

void app_main(void)
{
    led_init();
    while(1) {
        /* Blink off (output low) */
	printf("Turning off the LED\n");
        led_off();
        vTaskDelay(200 / portTICK_PERIOD_MS);
        /* Blink on (output high) */
	printf("Turning on the LED\n");
        led_on();
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
}

ljpPd.png

posted @   宋琦琦  阅读(4911)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起