1、修改Linux内核设备树
PC $> cd <Linux kernel source directory>
STM32MP157C-DK2
- Edit the arch/arm/boot/dts/stm32mp157a-dk1.dts device tree source file
- (arch/arm/boot/dts/stm32mp157c-ed1.dts,ev1板)
- Add the lines highlighted below
led {
compatible = "gpio-leds";
blue {
label = "heartbeat";
gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
green {
label = "stm32mp:green:user";
gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
default-state = "on";
};
};
PC $> cd <Linux kernel build directory>
PC $> make dtbs
PC $> cp arch/arm/boot/dts/stm32mp157*.dtb install_artifact/boot/
Board $> reboot
2、 修改内置的Linux内核设备驱动程序
- Check that there's no log information when the display driver is probed
Board $> dmesg | grep -i stm_drm_platform_probe
Board $>
- Go to the <Linux kernel source directory>
PC $> cd <Linux kernel source directory>
- Edit the ./drivers/gpu/drm/stm/drv.c source file
- Add a log information in the stm_drm_platform_probe function
static int stm_drm_platform_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct drm_device *ddev;
int ret;
[...]
DRM_INFO("Simple example - %s\n", __func__);
return 0;
[...]
}
- Go to the <Linux kernel build directory>
PC $> cd <Linux kernel build directory>
- Cross-compile the Linux kernel (please check the load address in the README.HOW_TO.txt helper file)
PC $> make uImage LOADADDR=0xC2000040
PC $> cp arch/arm/boot/uImage install_artifact/boot/
- Update the Linux kernel image on board
PC $> scp install_artifact/boot/uImage root@<board ip address>:/boot/
- Reboot the board
Board $> reboot
- Check that there is now log information when the display driver is probed
Board $> dmesg | grep -i stm_drm_platform_probe
[ 2.995125] [drm] Simple example - stm_drm_platform_probe
3、修改/添加外部Linux内核模块
3.1修改外部树内Linux内核模块
- Go to the <Linux kernel source directory>
PC $> cd <Linux kernel source directory>
- Edit the ./drivers/media/platform/vivid/vivid-core.c source file
- Add log information in the vivid_probe and vivid_remove functions
static int vivid_probe(struct platform_device *pdev)
{
const struct font_desc *font = find_font("VGA8x16");
int ret = 0, i;
[...]
/* n_devs will reflect the actual number of allocated devices */
n_devs = i;
pr_info("Simple example - %s\n", __func__);
return ret;
}
static int vivid_remove(struct platform_device *pdev)
{
struct vivid_dev *dev;
unsigned int i, j;
[...]
pr_info("Simple example - %s\n", __func__);
return 0;
}
- Go to the <Linux kernel build directory>
PC $> cd <Linux kernel build directory>
- Cross-compile the Linux kernel modules
PC $> make modules
PC $> make INSTALL_MOD_PATH="./install_artifact" modules_install
- Update the vivid kernel module on the board (please check the kernel version <kernel version>)
PC $> scp install_artifact/lib/modules/<kernel version>/kernel/drivers/media/platform/vivid/vivid.ko root@<board ip address>:/lib/modules/<kernel version>/kernel/drivers/media/platform/vivid/
OR
PC $> scp -r install_artifact/lib/modules/* root@<board ip address>:/lib/modules/
- Update dependency descriptions for loadable kernel modules, and synchronize the data on disk with memory
Board $> /sbin/depmod -a
Board $> sync
- Insert the vivid kernel module into the Linux kernel
Board $> modprobe vivid
[...]
[ 3412.784638] Simple example - vivid_probe
- Remove the vivid kernel module from the Linux kernel
Board $> rmmod vivid
[...]
[ 3423.708517] Simple example - vivid_remove
3.2添加外部树外Linux内核模块
- Prerequisite: the Linux source code is installed, and the Linux kernel has been cross-compiled
- Go to the working directory that contains all the source code (that is, the directory that contains the Linux kernel, U-Boot and TF-A source code directories)
PC $> cd <tag>/sources/arm-<distro>-linux-gnueabi
- Export to KERNEL_SRC_PATH the path to the Linux kernel build directory that contains both the Linux kernel source code and the configuration file (.config)
PC $> export KERNEL_SRC_PATH=$PWD/<Linux kernel build directory>/
Example:
PC $> export KERNEL_SRC_PATH=$PWD/linux-stm32mp-4.19-r0/build
- Create a directory for this kernel module example
PC $> mkdir kernel_module_example
PC $> cd kernel_module_example
- Create the source code file for this kernel module example: kernel_module_example.c
// SPDX-identifier: GPL-2.0
/*
* Copyright (C) STMicroelectronics SA 2018
*
* Authors: Jean-Christophe Trotin <jean-christophe.trotin@st.com>
*
*
#include <linux/module.h> /* for all kernel modules */
#include <linux/kernel.h> /* for KERN_INFO */
#include <linux/init.h> /* for __init and __exit macros */
static int __init kernel_module_example_init(void)
{
printk(KERN_INFO "Kernel module example: hello world from STMicroelectronics\n");
return 0;
}
static void __exit kernel_module_example_exit(void)
{
printk(KERN_INFO "Kernel module example: goodbye from STMicroelectronics\n");
}
module_init(kernel_module_example_init);
module_exit(kernel_module_example_exit);
MODULE_DESCRIPTION("STMicroelectronics simple external out-of-tree Linux kernel module example");
MODULE_AUTHOR("Jean-Christophe Trotin <jean-christophe.trotin@st.com>");
MODULE_LICENSE("GPL v2");
- Create the makefile for this kernel module example: Makefile
| All the indentations in a makefile are tabulations |
# Makefile for simple external out-of-tree Linux kernel module example
# Object file(s) to be built
obj-m := kernel_module_example.o
# Path to the directory that contains the Linux kernel source code
# and the configuration file (.config)
KERNEL_DIR ?= $(KERNEL_SRC_PATH)
# Path to the directory that contains the generated objects
DESTDIR ?= $(KERNEL_DIR)/install_artifact
# Path to the directory that contains the source file(s) to compile
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
install:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) INSTALL_MOD_PATH=$(DESTDIR) modules_install
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
- Cross-compile the kernel module example
PC $> make clean
PC $> make
PC $> make install
- Go to the <Linux kernel build directory>
PC $> cd <Linux kernel build directory>
- The generated kernel module example is in: install_artifact/lib/modules/<kernel version>/extra/kernel_module_example.ko
- Push this kernel module example on board (please check the kernel version <kernel version>)
PC $> ssh root@<board ip address> mkdir -p /lib/modules/<kernel version>/extra
PC $> scp install_artifact/lib/modules/<kernel version>/extra/kernel_module_example.ko root@<board ip address>:/lib/modules/<kernel version>/extra
OR
PC $> scp -r install_artifact/lib/modules/* root@<board ip address>:/lib/modules/
- Update dependency descriptions for loadable kernel modules, and synchronize the data on disk with memory
Board $> /sbin/depmod -a
Board $> sync
- Insert the kernel module example into the Linux kernel
Board $> modprobe kernel_module_example
[18167.821725] Kernel module example: hello world from STMicroelectronics
- Remove the kernel module example from the Linux kernel
Board $> rmmod kernel_module_example
[18180.086722] Kernel module example: goodbye from STMicroelectronics
4、添加“ hello world”用户空间示例
- Go to the working directory that contains all the source codes (i.e. directory that contains the Linux kernel, U-Boot and TF-A source code directories)
PC $> cd <tag>/sources/arm-<distro>-linux-gnueabi
- Create a directory for this user space example
PC $> mkdir hello_world_example
PC $> cd hello_world_example
- Create the source code file for this user space example: hello_world_example.c
// SPDX-identifier: GPL-2.0
/*
* Copyright (C) STMicroelectronics SA 2018
*
* Authors: Jean-Christophe Trotin <jean-christophe.trotin@st.com>
*
*/
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int i =11;
printf("\nUser space example: hello world from STMicroelectronics\n");
setbuf(stdout,NULL);
while (i--) {
printf("%i ", i);
sleep(1);
}
printf("\nUser space example: goodbye from STMicroelectronics\n");
return(0);
}
9.2 Cross-compilation↑
Three ways to use the OpenSTLinux SDK to cross-compile this user space example are proposed below: (1) command line (2) makefile-based project (3) autotools-based project.
9.2.1 Command line↑
This method allows quick cross-compilation of a single-source code file. It applies if the project has only one file.
The cross-development toolchain is associated with the sysroot that contains the header files and libraries needed for generating binaries that run on the target architecture (see SDK for OpenSTLinux distribution#Native and target sysroots).
The sysroot location is specified with the --sysroot option.
The sysroot location must be specified using the --sysroot option. The CC environment variable created by the SDKalready includes the --sysroot option that points to the SDK sysroot location.
PC $> echo $CC
arm-openstlinux_weston-linux-gnueabi-gcc -march=armv7ve -mthumb -mfpu=neon-vfpv4 -mfloat-abi=hard -mcpu=cortex-a7 --sysroot=<SDK installation directory>/SDK/sysroots/cortexa7t2hf-neon-vfpv4-openstlinux_weston-linux-gnueabi
- Create the directory in which the generated binary is to be stored
PC $> mkdir -p install_artifact install_artifact/usr install_artifact/usr/local install_artifact/usr/local/bin
- Cross-compile the single source code file for the user space example
PC $> $CC hello_world_example.c -o ./install_artifact/usr/local/bin/hello_world_example
9.2.2 Makefile-based project↑
For this method, the cross-toolchain environment variables established by running the cross-toolchain environment setup script are subject to general make rules.
For example, see the following environment variables:
PC $> echo $CC
arm-openstlinux_weston-linux-gnueabi-gcc -march=armv7ve -mthumb -mfpu=neon-vfpv4 -mfloat-abi=hard -mcpu=cortex-a7 --sysroot=<SDK installation directory>/SDK/sysroots/cortexa7t2hf-neon-vfpv4-openstlinux_weston-linux-gnueabi
PC $> echo $CFLAGS
-O2 -pipe -g -feliminate-unused-debug-types
PC $> echo $LDFLAGS
PROG = hello_world_example
SRCS = hello_world_example.c
OBJS = $(SRCS:.c=.o)
CLEANFILES = $(PROG)
INSTALL_DIR = ./install_artifact/usr/local/bin
# Add / change option in CFLAGS if needed
# CFLAGS += <new option>
$(PROG): $(OBJS)
$(CC) $(CFLAGS) -o $(PROG) $(OBJS)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
all: $(PROG)
clean:
rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~
install: $(PROG)
mkdir -p $(INSTALL_DIR)
install $(PROG) $(INSTALL_DIR)
- Cross-compile the project
PC $> make
PC $> make install
9.2.3 Autotools-based project↑
This method creates a project based on GNU autotools.
- Create the makefile for this user space example: Makefile.am
bin_PROGRAMS = hello_world_example
hello_world_example_SOURCES = hello_world_example.c
- Create the configuration file for this user space example: configure.ac
AC_INIT(hello_world_example,0.1)
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC
AC_PROG_INSTALL
AC_OUTPUT(Makefile)
- Generate the local aclocal.m4 files and create the configure script
PC $> aclocal
PC $> autoconf
- Generate the files needed by GNU coding standards (for compliance)
PC $> touch NEWS README AUTHORS ChangeLog
- Generate the links towards SDK scripts
PC $> automake -a
- Cross-compile the project
PC $> ./configure ${CONFIGURE_FLAGS}
PC $> make
PC $> make install DESTDIR=./install_artifact
9.3 Deploy and execute on board↑
- Check that the generated binary for this user space example is in: ./install_artifact/usr/local/bin/hello_world_example
- Push this binary onto the board
PC $> scp -r install_artifact/* root@<board ip address>:/
- Execute this user space example
Board $> cd /usr/local/bin
Board $> ./hello_world_example
User space example: hello world from STMicroelectronics
10 9 8 7 6 5 4 3 2 1 0
User space example: goodbye from STMicroelectronics