Src Folder in Libraries - 2024.2 English

Porting Guide for embeddedsw Components System Device Tree Based Build Flow (UG1647)

Document ID
UG1647
Release Date
2024-11-27
Version
2024.2 English

Replacing the Makefile

Instead of a Makefile, every library should have a CMakeLists.txt file that looks as shown in the following snippet.

# SPDX-License-Identifier: MIT
cmake_minimum_required(VERSION 3.15)
project(<library name>)
 
find_package(common)
# More details on <library name>.cmake follow in the next sub-section
include(${CMAKE_CURRENT_SOURCE_DIR}/<library name>.cmake NO_POLICY_SCOPE)
collector_create (PROJECT_LIB_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}")
collector_create (PROJECT_LIB_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}")
include_directories(${CMAKE_BINARY_DIR}/include)
# Add subdirectories if there are any within src folder
# Note that the subdirectories ought to have their own CMakeLists.txt to collect the sources and headers
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/<subdir_1>)
collect (PROJECT_LIB_SOURCES <source file>)
collect (PROJECT_LIB_HEADERS <header file>)
collector_list (_sources PROJECT_LIB_SOURCES)
collector_list (_headers PROJECT_LIB_HEADERS)
file(COPY ${_headers} DESTINATION ${CMAKE_BINARY_DIR}/include)
add_library(<library name> STATIC ${_sources})
set_target_properties(<library name> PROPERTIES LINKER_LANGUAGE C)
install(TARGETS <library name> LIBRARY DESTINATION ${CMAKE_SOURCE_DIR}/build ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
get_headers(${_headers})
set_target_properties(<library name> PROPERTIES ADDITIONAL_CLEAN_FILES "${CMAKE_LIBRARY_PATH}/lib<library name>.a;${CMAKE_INCLUDE_PATH}/<rel_headers>;${clean_headers}")
install(TARGETS <library name> LIBRARY DESTINATION ${CMAKE_LIBRARY_PATH} ARCHIVE DESTINATION ${CMAKE_LIBRARY_PATH})
install(DIRECTORY ${CMAKE_BINARY_DIR}/include DESTINATION ${CMAKE_INCLUDE_PATH}/..)

As an example, the XilFPGA library has a file named CMakeLists.txt that has the following contents. For more details CMAKE_MACHINE and CMAKE_SYSTEM_PROCESSOR, see CMAKE_MACHINE and CMAKE_SYSTEM_PROCESSOR.

# SPDX-License-Identifier: MIT
cmake_minimum_required(VERSION 3.3)
project(xilfpga)
include(${CMAKE_CURRENT_SOURCE_DIR}/xilfpga.cmake NO_POLICY_SCOPE)
find_package(common)
collector_create (PROJECT_LIB_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}")
collector_create (PROJECT_LIB_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}")
include_directories(${CMAKE_BINARY_DIR}/include)
if("${CMAKE_MACHINE}" STREQUAL "Versal")
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/interface/versal/)
else()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/interface/zynqmp/)
endif()
collect (PROJECT_LIB_SOURCES xilfpga.c)
collect (PROJECT_LIB_HEADERS xilfpga.h)
collector_list (_sources PROJECT_LIB_SOURCES)
collector_list (_headers PROJECT_LIB_HEADERS)
file(COPY ${_headers} DESTINATION ${CMAKE_BINARY_DIR}/include)
if (${NON_YOCTO})
file(COPY ${CMAKE_BINARY_DIR}/include/xfpga_config.h DESTINATION ${CMAKE_INCLUDE_PATH}/)
endif()
add_library(xilfpga STATIC ${_sources})
set_target_properties(xilfpga PROPERTIES LINKER_LANGUAGE C)
get_headers(${_headers})
set_target_properties(xilfpga PROPERTIES ADDITIONAL_CLEAN_FILES "${CMAKE_LIBRARY_PATH}/libxilfpga.
a;${CMAKE_INCLUDE_PATH}/xfpga_config.h;${clean_headers}")
install(TARGETS xilfpga LIBRARY DESTINATION ${CMAKE_LIBRARY_PATH} ARCHIVE DESTINATION
${CMAKE_LIBRARY_PATH})
install(DIRECTORY ${CMAKE_BINARY_DIR}/include DESTINATION ${CMAKE_INCLUDE_PATH}/..)

Adding New Configuration Files

If the library has software configuration, two new files, <library_name>.cmake and x<library_name>_config.h.in, are added to facilitate this process.

The system device tree based flow makes use of open source CMAKE-based flow and replaces the existing .mld/.tcl based flows to configure the library. <library_name>.cmake and x<library_name>_config.h.in generates the required software configuration header file <library_name>_config.h based on the user configuration.

x<library_name>_config.h.in
The cmakedefine macro in the config.h.in file can be used to generate a series of define statements (macros). This configuration file when processed with <library name>.cmake results into a .h (header) file which contains all the generated #define statements in C syntax. An example xfpga_config_h_in file is shown in the following snippet:
#ifndef _XFPGA_CONFIG_H
#define _XFPGA_CONFIG_H
 
#include <xilfpga.h>
@PCAP_INCLUDE@
@PCAP_COMMON_INCLUDE@
@VERSAL_INCLUDE@
 
#cmakedefine XFPGA_OCM_ADDRESS  @XFPGA_OCM_ADDRESS@U
#cmakedefine XFPGA_BASE_ADDRESS @XFPGA_BASE_ADDRESS@U
#cmakedefine XFPGA_SECURE_MODE  @XFPGA_SECURE_MODE@
#cmakedefine01 XFPGA_DEBUG  @XFPGA_DEBUG@
#cmakedefine XFPGA_SECURE_READBACK_MODE @XFPGA_SECURE_READBACK_MODE@
#cmakedefine XFPGA_SECURE_IPI_MODE_EN @XFPGA_SECURE_IPI_MODE_EN@
 
#endif /* XFPGA_CONFIG_H */

Refer to How To Write Platform Checks for more details on how to use the configuration files with CMAKE.

<library_name>.cmake
Software configuration options can include a variety of data types. For example, they can be Boolean, hex, an entry among a list of possible options, or a number among a large range of numbers. All these software configurations have a default value which can later be changed. These choices can be described using the following CMAKE commands:
  • For configuring parameters that have Boolean properties, use option(<option_variable> "help string describing option" [initial value]). For more information, see option.
  • For configuring parameters whose values could be one in a list of values or a range of values, use set(<variable> <value> [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE]). For more information, see set.

After you have set the CMAKE options and variables, call the configure_file() command. It calls the config.h.in file and generates the <libray name>_config.h. An example xilfpga.cmake is shown in the following snippet:

# SPDX-License-Identifier: MIT
cmake_minimum_required(VERSION 3.15)
 
option(XILFPGA_secure_mode "Enable secure Bitstream loading support" ON)
option(XILFPGA_secure_environment "Which is used to Enable the secure PL configuration" OFF)
option(XILFPGA_secure_readback "Which is used to Enable the secure PL configuration Read-back support" OFF)
option(XILFPGA_debug_mode "Which is used to Enable the Debug messages in the library" OFF)
SET(XILFPGA_ocm_address 0xfffc0000 CACHE STRING "OCM Address which is used for Bitstream Authentication")
SET(XILFPGA_base_address 0x80000 CACHE STRING "Bitstream Image Base Address")
 
set(zynqmp_secure_env 0)
if("${CMAKE_MACHINE}" STREQUAL "Versal")
    set(VERSAL_INCLUDE "#include <xilfpga_versal.h>")
elseif("${CMAKE_MACHINE}" STREQUAL "ZynqMP")
    set(PLATFORM_ZYNQMP " ")
    if((NOT("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "pmu_microblaze")) AND
       ${XILFPGA_secure_environment})
        set(XFPGA_SECURE_IPI_MODE_EN " ")
        set(zynqmp_secure_env 1)
    else()
        set(PCAP_INCLUDE "#include <xilfpga_pcap.h>")
    endif()
    set(PCAP_COMMON_INCLUDE "#include <xilfpga_pcap_common.h>")
endif()
 
set(XFPGA_OCM_ADDRESS ${XILFPGA_ocm_address})
set(XFPGA_BASE_ADDRESS ${XILFPGA_base_address})
if (${XILFPGA_secure_mode})
   set(XFPGA_SECURE_MODE " ")
endif()
if (${XILFPGA_debug_mode})
   set(XFPGA_DEBUG " ")
endif()
if (${XILFPGA_secure_readback})
    set(XFPGA_SECURE_READBACK_MODE " ")
endif()
 
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/xfpga_config.h.in ${CMAKE_BINARY_DIR}/include/xfpga_config.h)

Adding a New Header File

As discussed, a new file named <libray name>_config.h is created by the configure_file() API when the <library_name>.cmake and x<library_name>_config.h.in files are processed together. This separates the library specific configurations into <libray name>_config.h file which, in the existing flow, is located within xparameters.h. This file is auto-generated as mentioned earlier in this document. An example xfpga_config.h is shown in the following snippet:

#ifndef _XFPGA_CONFIG_H
#define _XFPGA_CONFIG_H
 
#include <xilfpga.h>
/* Empty line as the PCAP_INCLUDE couldn't be set in xilfpga.cmake */
/* Empty line as PCAP_COMMON_INCLUDE couldn't be set in xilfpga.cmake */
#include <xilfpga_versal.h>
 
#define XFPGA_OCM_ADDRESS   0xfffc0000U
#define XFPGA_BASE_ADDRESS  0x80000U
#define XFPGA_SECURE_MODE
#define XFPGA_DEBUG  0
/* #undef XFPGA_SECURE_READBACK_MODE */
/* #undef XFPGA_SECURE_IPI_MODE_EN */
 
#endif /* XFPGA_CONFIG_H */

Making Changes in the Existing Source Files (.c and .h)

The following changes are required:

  • All the calls of LookupConfig() API of every driver must be updated to use BaseAddress instead of DeviceId.
  • All the references to the XPAR_<drv_name>_DEVICE_ID macro must be replaced with the macro defined in the x<library_name>_config.h file.
  • The newly generated x<library_name>_config.h must be included in the .c files wherever needed.

Sample changes are shown in the following code:

--- a/lib/sw_services/xilloader/src/common/xloader_auth_enc.c
+++ b/lib/sw_services/xilloader/src/common/xloader_auth_enc.c
@@ -110,6 +110,7 @@
 *       am   06/19/23 Added KAT error code for failure cases
 *       sk   07/06/23 Added Jtag DAP config support for Non-Secure Debug
 *       am   07/03/23 Added authentication optimization support
+*       ng   07/13/23 Added support for system device tree flow
 *
 * </pre>
 *
@@ -135,6 +136,7 @@
 #include "xsecure_init.h"
 #include "xloader_plat_secure.h"
 #include "xloader_plat.h"
+#include "xplmi_config.h"
 
 /************************** Constant Definitions ****************************/
 
@@ -668,7 +670,7 @@ int XLoader_ImgHdrTblAuth(XLoader_SecureParams *SecurePtr)
        SecurePtr->AcPtr = AuthCert;
 
        /** - Get DMA instance */
-       SecurePtr->PmcDmaInstPtr = XPlmi_GetDmaInstance((u32)PMCDMA_0_DEVICE_ID);
+       SecurePtr->PmcDmaInstPtr = XPlmi_GetDmaInstance(PMCDMA_0_DEVICE);
        if (SecurePtr->PmcDmaInstPtr == NULL) {
                Status = XPlmi_UpdateStatus(XLOADER_ERR_IHT_GET_DMA, 0);
                goto END;
@@ -790,7 +792,7 @@ int XLoader_ReadAndVerifySecureHdrs(XLoader_SecureParams *SecurePtr,
        XPlmi_Printf(DEBUG_INFO,
                "Loading secure image headers and partition headers\n\r");
        /* Get DMA instance */
-       SecurePtr->PmcDmaInstPtr = XPlmi_GetDmaInstance((u32)PMCDMA_0_DEVICE_ID);
+       SecurePtr->PmcDmaInstPtr = XPlmi_GetDmaInstance(PMCDMA_0_DEVICE);
        if (SecurePtr->PmcDmaInstPtr == NULL) {
                Status = XPlmi_UpdateStatus(XLOADER_ERR_HDR_GET_DMA, 0);
                goto ERR_END;
@@ -3218,7 +3220,7 @@ static int XLoader_AuthJtag(u32 *TimeOut)
                goto END;
        }
 
-       SecureParams.PmcDmaInstPtr = XPlmi_GetDmaInstance((u32)PMCDMA_0_DEVICE_ID);
+       SecureParams.PmcDmaInstPtr = XPlmi_GetDmaInstance(PMCDMA_0_DEVICE);
        if (SecureParams.PmcDmaInstPtr == NULL) {
                Status = XPlmi_UpdateStatus(XLOADER_ERR_AUTH_JTAG_GET_DMA, 0);
                goto END;