This is an old revision of the document!


01. Preparation

The Linux kernel is comprised of numerous modules. These can be in-tree (part of the kernel source structure) or out-of-tree (independent modules). While there are some limitations when writing out-of-tree modules, such as restricted access to certain functions, this generally doesn't affect your ability to write drivers.

Task A - The kernel

We are going to write a few out-of-tree kernel modules since this method is more portable. If your code is not architecture-dependent, then you can compile and test your module on your host machine just as easily as on the board. However, if you want to compile it to run on the board, you need a copy of the kernel's source tree that is checked out at the same version as that which is running on the target device. In the following code example we assume that the board is running Linux v6.4.

# check kernel version on the board
[root@board ~]$ uname -r
6.4
 
# see available release tags on your copy of the Linux repo
[student@host ~/linux]$ git tag
 
# check out to the appropriate release version
[student@host ~/linux]$ git checkout v6.4

Although we have the desired kernel version, remember that the FDT needed to be slightly modified. Apply the following diffpatch:

kernel_fdt.patch

kernel_fdt.patch

diff --git a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts
index 89cbec5c41b2..3fe7f3713e4b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts
@@ -19,6 +19,25 @@ chosen {
 		stdout-path = &uart1;
 	};
 
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+
+		led {
+			label = "gpio-led";
+			pintctrl-0 = <&pinctrl_led>;
+			gpios = <&gpio5 5 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
 	pmic_osc: clock-pmic {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
@@ -80,6 +99,7 @@ buck1: BUCK1 {
 				regulator-min-microvolt = <700000>;
 				regulator-max-microvolt = <1300000>;
 				regulator-boot-on;
+				regulator-always-on;
 				regulator-ramp-delay = <1250>;
 				rohm,dvs-run-voltage = <900000>;
 				rohm,dvs-idle-voltage = <850000>;
@@ -91,6 +111,7 @@ buck2: BUCK2 {
 				regulator-min-microvolt = <700000>;
 				regulator-max-microvolt = <1300000>;
 				regulator-boot-on;
+				regulator-always-on;
 				regulator-ramp-delay = <1250>;
 				rohm,dvs-run-voltage = <1000000>;
 				rohm,dvs-idle-voltage = <900000>;
@@ -101,6 +122,7 @@ buck3: BUCK3 {
 				regulator-min-microvolt = <700000>;
 				regulator-max-microvolt = <1300000>;
 				regulator-boot-on;
+				regulator-always-on;
 				rohm,dvs-run-voltage = <1000000>;
 			};
 
@@ -109,6 +131,7 @@ buck4: BUCK4 {
 				regulator-min-microvolt = <700000>;
 				regulator-max-microvolt = <1300000>;
 				regulator-boot-on;
+				regulator-always-on;
 				rohm,dvs-run-voltage = <1000000>;
 			};
 
@@ -117,6 +140,7 @@ buck5: BUCK5 {
 				regulator-min-microvolt = <700000>;
 				regulator-max-microvolt = <1350000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 
 			buck6: BUCK6 {
@@ -124,6 +148,7 @@ buck6: BUCK6 {
 				regulator-min-microvolt = <3000000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 
 			buck7: BUCK7 {
@@ -131,6 +156,7 @@ buck7: BUCK7 {
 				regulator-min-microvolt = <1605000>;
 				regulator-max-microvolt = <1995000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 
 			buck8: BUCK8 {
@@ -138,6 +164,7 @@ buck8: BUCK8 {
 				regulator-min-microvolt = <800000>;
 				regulator-max-microvolt = <1400000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 
 			ldo1: LDO1 {
@@ -161,6 +188,7 @@ ldo3: LDO3 {
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 
 			ldo4: LDO4 {
@@ -168,6 +196,7 @@ ldo4: LDO4 {
 				regulator-min-microvolt = <900000>;
 				regulator-max-microvolt = <1800000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 
 			ldo5: LDO5 {
@@ -175,6 +204,7 @@ ldo5: LDO5 {
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 
 			ldo6: LDO6 {
@@ -182,6 +212,7 @@ ldo6: LDO6 {
 				regulator-min-microvolt = <900000>;
 				regulator-max-microvolt = <1800000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 
 			ldo7: LDO7 {
@@ -189,6 +220,7 @@ ldo7: LDO7 {
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
+				regulator-always-on;
 			};
 		};
 	};
@@ -415,4 +447,10 @@ pinctrl_wdog: wdoggrp {
 			MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
 		>;
 	};
+
+	pinctrl_led: ledggrp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5	0x19
+		>;
+	};
 };


[student@host ~/linux]$ git apply kernel_fdt.patch

Finally, compile the Linux kernel after creating the arm64 defconfig. Also, consider enabling the generation of debug info in Kernel hacking / Compile-time checks and compiler options. If you are compiling the kernel in a VM, make sure to allocate said VM as many CPUs and as much RAM as you can, otherwise it will take a while.

# assuming the cross compiler bin/ is in PATH
[student@host ~/linux]$ make CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=arm64 defconfig
[student@host ~/linux]$ make CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=arm64 Image -j $(nproc)
[student@host ~/linux]$ make CROSS_COMPILE=aarch64-none-linux-gnu- ARCH=arm64 dtbs

During a previous lab, we saw how important it is to have a language server integrated into your text editor. The language server lets you jump to function definitions or see all references of a variable, even outside the current source file. However, the language server needs some hints regarding what code was compiled; normally, it can't know that you've compiled the arm64 version of a architecture-dependent function and not the x86 one. All this information can be provided via a compile_commands.json file that contains the cmdline of all ${CROSS_COMPILE}gcc invocations. Tools like bear can generate it for you without much hassle, but the Linux build system (separate from Kbuild) has a handy script that assembles it for you after compilation:

[student@host ~/linux]$ ./scripts/clang-tools/gen_compile_commands.py

If you don't have a language server configured, you can use elixir as an online alternative.

Task B - The rootfs

For this lab we want to be able to easily transfer files to our boards. We are going to achieve this via SSH, so include BR2_PACKAGE_OPENSSH in your build configuration. Additionally, we want to place a configuration file for the SSH daemon (i.e. sshd) at /etc/ssh/sshd_config. In order to achieve this, we are going to use a rootfs overlay. Essentially, we are going to specify the absolute path to a certain directory

ass/laboratoare/04/tasks/01.1689979334.txt.gz ยท Last modified: 2023/07/22 01:42 by radu.mantu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0