I have an project which has several different PCB revisions, each with different peripheral ICs that the ESP32 communicates with. Each revision has a variety of changes like for example using a different sensor IC, and so I need different functions to communicate with the specific sensor. The application code otherwise remains identical. Until now there were just two PCB revisions, and so I used pre-processor directives to conditionally compile with relevant blocks code.
We are now approaching a third hardware version, and so I want to create a sort of hardware abstraction layer that includes only code relating to that specific PCB revision. That way the code can remain clear, and it will be simple in the future to add changes for new hardware revisions. What I am envisioning is that when I build the project, I could specify the PCB revision I am building for, and the relevant component would be included. When changes are made to the application code, automated CI processes could build for each of the revisions.
For example there could be a component for each PCB revision. Then there would be a header file with interface definitions, for example "uint32_t read_sensor_api()". Each board component would then have the actual implementation for their specific sensor.
What is the best practice with the ESP-IDF build system to accomplish this? Would I need to write CMake instructions? Any help on the direction to go with this would be greatly appreciated.
Dealing with an ESP-IDF project that needs to support many PCB revisions?
-
- Posts: 11
- Joined: Tue Jan 11, 2022 9:26 pm
Re: Dealing with an ESP-IDF project that needs to support many PCB revisions?
Hi squirtle321,
One way to add such "board revision" choice in an IDF based project would be by adding a Kconfig option.
You can get the idea from Kconfig.projbuild and CMakeLists.txt files in this example: https://github.com/espressif/esp-idf/tr ... onfig/main
Hope that helps.
One way to add such "board revision" choice in an IDF based project would be by adding a Kconfig option.
You can get the idea from Kconfig.projbuild and CMakeLists.txt files in this example: https://github.com/espressif/esp-idf/tr ... onfig/main
Hope that helps.
Re: Dealing with an ESP-IDF project that needs to support many PCB revisions?
You can check this example to see how I had done it. In my case using same project with ESP32 & ESP32-S3
https://github.com/sukesh-ak/ESP32-LVGL8x-SDSPI
Main issue is that sdconfig file gets overwritten in the project root when you run menuconfig.
This means when you rebuild, it goes through full compile.
I have modified the CMakeList.txt to store the sdconfig inside the build folder. Check readme for details.
https://github.com/sukesh-ak/ESP32-LVGL ... sts.txt#L8
https://github.com/sukesh-ak/ESP32-LVGL8x-SDSPI
Main issue is that sdconfig file gets overwritten in the project root when you run menuconfig.
This means when you rebuild, it goes through full compile.
I have modified the CMakeList.txt to store the sdconfig inside the build folder. Check readme for details.
https://github.com/sukesh-ak/ESP32-LVGL ... sts.txt#L8
-
- Posts: 11
- Joined: Tue Jan 11, 2022 9:26 pm
Re: Dealing with an ESP-IDF project that needs to support many PCB revisions?
ESP_igrr wrote: ↑Thu Sep 15, 2022 6:26 amHi squirtle321,
One way to add such "board revision" choice in an IDF based project would be by adding a Kconfig option.
You can get the idea from Kconfig.projbuild and CMakeLists.txt files in this example: https://github.com/espressif/esp-idf/tr ... onfig/main
Hope that helps.
Hi ESP_igrr,
Thank you for the tip, it's been very helpful. I've been working through adapting your linked example and I'm wondering if you have any feedback about my attempt to achieve this board revision choice feature?
This is my project structure:
Code: Select all
application:
CMakeLists.txt
sdkconfig
main:
CMakeLists.txt
kconfig.projbuild
main.c
components:
hardware_interface:
CMakeLists.txt
foo_interface.h
bar_interface.h
version_1:
foo_implementation.c
bar_implementation.c
version_2:
foo_implementation.c
bar_implementation.c
application_code:
CMakeLists.txt
func.h
func.c
The component application_code has "REQUIRES hardware_interface" in its CMakeLists.txt, and the header file func.h has:
Code: Select all
#include "foo_interface.h"
#include "bar_interface.h"
Code: Select all
menu "Example Product Configuration"
choice EXAMPLE_FUNC_IMPL
prompt "Choose the implementation of interfaces defined in the hardware_interface component"
help
This setting is used in component CMakeLists.txt.
config BUILD_VERSION_1
bool "Hardware version 1"
config BUILD_VERSION_2
bool "Hardware version 2"
endchoice
endmenu
And finally in the CMakeLists.txt in the hardware_interface component, I want to conditionally include the source code in either version_1 or version_2 subdirectories.
Code: Select all
if (BUILD_VERSION_1)
set(srcs "./version_1/foo_implementation.c" "./version_1/bar_implementation.c")
elseif(BUILD_VERSION_2)
set(srcs "./version_2/foo_implementation.c" "./version_2/bar_implementation.c")
endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "."
)
I am a beginner at working with CMake and ESP-IDF and am wondering if there is a better way to be conditionally compiling with different source code? It feels a little verbose to specify the relative path and name of each file. Any help or a point in the right direction is appreciated.
Thank you!
Re: Dealing with an ESP-IDF project that needs to support many PCB revisions?
The project structure you have posted does make sense to me!
Regarding verbosity in CMake, one way to handle it could be to introduce another variable for version name. This will work if every hardware version has the same set of source files. For example:
If you are using CMake 3.15 or later, you can simplify the CMake part this even further, using list(TRANSFORM ... PREPEND) command:
Regarding verbosity in CMake, one way to handle it could be to introduce another variable for version name. This will work if every hardware version has the same set of source files. For example:
Code: Select all
menu "Example Product Configuration"
choice BUILD_VERSION
prompt "Choose the implementation of interfaces defined in the hardware_interface component"
help
This setting is used in component CMakeLists.txt.
config BUILD_VERSION_1
bool "Hardware version 1"
config BUILD_VERSION_2
bool "Hardware version 2"
endchoice
# Hidden Kconfig option which gets set to the name of the hardware version
config BUILD_VERSION
string
default "version_1" if BUILD_VERSION_1
default "version_2" if BUILD_VERSION_2
endmenu
Code: Select all
set(srcs ${CONFIG_BUILD_VERSION}/foo_implementation.c
${CONFIG_BUILD_VERSION}/bar_implementation.c)
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS "."
)
Code: Select all
set(srcs foo_implementation.c bar_implementation.c)
list(TRANSFORM srcs PREPEND "${CONFIG_BUILD_VERSION}/")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS "."
)
-
- Posts: 11
- Joined: Tue Jan 11, 2022 9:26 pm
Re: Dealing with an ESP-IDF project that needs to support many PCB revisions?
Thank you, ESP_igrr! My project structure is a lot cleaner now and those CMake tips also saved a lot of characters and lines.ESP_igrr wrote: ↑Mon Sep 26, 2022 7:39 pmThe project structure you have posted does make sense to me!
Regarding verbosity in CMake, one way to handle it could be to introduce another variable for version name. This will work if every hardware version has the same set of source files. For example:
Code: Select all
menu "Example Product Configuration" choice BUILD_VERSION prompt "Choose the implementation of interfaces defined in the hardware_interface component" help This setting is used in component CMakeLists.txt. config BUILD_VERSION_1 bool "Hardware version 1" config BUILD_VERSION_2 bool "Hardware version 2" endchoice # Hidden Kconfig option which gets set to the name of the hardware version config BUILD_VERSION string default "version_1" if BUILD_VERSION_1 default "version_2" if BUILD_VERSION_2 endmenu
If you are using CMake 3.15 or later, you can simplify the CMake part this even further, using list(TRANSFORM ... PREPEND) command:Code: Select all
set(srcs ${CONFIG_BUILD_VERSION}/foo_implementation.c ${CONFIG_BUILD_VERSION}/bar_implementation.c) idf_component_register(SRCS ${srcs} INCLUDE_DIRS "." )
Code: Select all
set(srcs foo_implementation.c bar_implementation.c) list(TRANSFORM srcs PREPEND "${CONFIG_BUILD_VERSION}/") idf_component_register(SRCS ${srcs} INCLUDE_DIRS "." )
Appreciate it!
Who is online
Users browsing this forum: Google [Bot] and 69 guests