Linux system porting: porting the original Kernel to the development board

Linux system porting: porting the original Kernel to the development board

1. Get the original kernel and compile it

I directly compile the source code provided by the atom, and compile the instructions

#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16

After compiling, get the image file:

20220323222600

Device tree file:

20220323214430

Second, the kernel boot test

Start the compiled linux kernel from the board through the network, and see the phenomenon. If you want to ping each other through the network, you must be under the LAN!

Set the bootargs parameter of the board uboot to console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw

setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw

Then copy the generated image file and device tree to the FTP root directory for booting from the network:

cp arch/arm/boot/dts/imx6ull-14x14-evk.dtb ~/linux/tftp/
cp arch/arm/boot/zImage ~/linux/tftp/

input on the development board

tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-evk.dtb
bootz 80800000 - 83000000

Start the network, the system starts successfully, you can enter the command:

20220323225238

The root file system we just started is guided by the bootargs environment variable of uboot, where root=/dev/mmcblk1p2 is the guide for the parameters of the root file system to be stored in partition 2 of EMMC. If there is no file system, the startup will fail. Kernel panic caused by missing root filesystem

3. Add your own board file

Add a configuration file for the Punctual Atomic Alpha board

3.1 Board configuration file

Copy the imx_v7_mfg_defconfig configuration file under arch/arm/configs, name it imx_my_emmc_defconfig, the name of our own configuration file, and then modify and configure our own kernel in it

cp arch/arm/configs/imx_v7_mfg_defconfig arch/arm/configs/imx_my_emmc_defconfig

Then you can use

make imx_my_emmc_defconfig

Configure the Linux kernel

20220324091622

3.2 Board Device Tree

Copy a copy of imx6ull-14x14-evk.dts from the directory arch/arm/boot/dts, rename it to imx6ull-my-emmc.dts as the device tree of our own board, and modify it in it later

cp arch/arm/boot/dts/imx6ull-14x14-evk.dts arch/arm/boot/dts/imx6ull-my-emmc.dts

Then in arch/arm/boot/dts/Makefile, find the "dtb-$(CONFIG_SOC_IMX6ULL)" configuration item, add "imx6ull-my-emmc.dtb" to this configuration item and append our device tree, dts will compile generate dtb

3.3 Compile

Modify the previous compilation script

#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_my_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16

Give the script execution permission, and then execute, the compilation is completed as follows, the compilation is successful The above kernel configuration is no problem

20220324093809

Copy the zImage and device tree .dtb files to the tftp directory, boot from the network, and load our own device tree:

tftp 80800000 zImage
tftp 83000000 imx6ull-my-emmc.dtb
bootz 80800000 - 83000000

Started successfully:

20220324101201

Four, important configuration modification

4.1 Modification of main frequency

Print the CPU frequency on the boot system, and the operating frequency information is stored in /sys/bus/cpu/devices/cpu0/cpufreq

20220324102644

The meaning of the file is as follows:

  • cpuinfo_cur_freq : the current cpu operating frequency, the operating frequency read from the CPU register
  • cpuinfo_max_freq : The highest operating frequency that the processor can run (unit: KHz)
  • cpuinfo_min_freq : The minimum operating frequency that the processor can run (unit: KHz)
  • cpuinfo_transition_latency : The time it takes for the processor to switch the frequency (unit: ns)
  • scaling_available_frequencies : List of main frequencies supported by the processor (unit: KHz)
  • scaling_available_governors : All governor types supported in the current kernel
  • scaling_cur_freq : saves the current CPU frequency cached by the cpufreq module, and does not check the CPU hardware registers
  • scaling_driver : This file saves the frequency modulation driver used by the current CPU
  • scaling_governor : governor (frequency regulation) strategy, there are 5 frequency regulation strategies in the Linux kernel
  1. Performance, the highest performance, directly use the highest frequency, regardless of power consumption
  2. Interactive, use the highest frequency directly at the beginning, and then slowly reduce it according to the CPU load
  3. Powersave, power saving mode, usually runs at the lowest frequency, system performance will be affected, generally do not use this
  4. Userspace, you can manually adjust the frequency in user space
  5. Ondemand, check the load regularly, and then adjust the frequency according to the load. Reduce CPU frequency when load is low
  • scaling_max_freq : the highest frequency that governor (frequency modulation) can adjust
  • cpuinfo_min_freq : The lowest frequency that governor (frequency modulation) can adjust

Print the current frequency: 792M

20220324103045

There are 4 switching frequencies that the CPU can support:

20220324103140

We modify the working frequency and change the default working mode to Powersave mode in the configuration file

sudo vim arch/arm/configs/imx_my_emmc_defconfig

Add default code

20220324104627

Recompile after modification, start the system kernel from the network, and then check the operating frequency of the system, it becomes 198M

20220324105859

In addition to modifying the defconfig file, the method of modifying the working frequency can also be configured graphically, using

make menuconfig

After the graphical configuration, the configuration file is generated, and then compiled. The results of the two methods are the same.

Generally, ondemand mode is used, one can save power, and the other can reduce heat

In addition to the above working frequencies, we can also run the programs we want, and we won't say much about the specific modifications. Generally, we can use the ones provided by the original factory.

4.2 EMMC driver modification

The EMMC in the Linux kernel driver is in 4-wire mode by default, and it is not as fast as 8-wire mode, so we changed the EMMC driver to 8-wire

20220324110308

Modify the EMMC wiring and directly modify the device tree, open the file imx6ull-alientek-emmc.dts, and put the following configuration file

20220324110557

change into

20220324110740

Then compile dts to dtb separately:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs

reboot the system

4.3 Network driver modification

The network of the atomic development board is different from the official network hardware of NXP. The network PHY chip is changed from KSZ8081 to LAN8720A. The network driver that comes with the Linux kernel cannot be driven and needs to be modified.

4.3.1 Modify chip reset pin

Open the device tree file imx6ull-my-emmc.dts and find the following code to delete the redundant IO port configuration

20220324153156

After modification:

20220324153357

Delete the following code, let GPIO5_IO07 and GPIO5_IO08 be the reset pins of ENET1 and ENET2 respectively

20220324153715

Then find iomuxc_snvs, configure the two pins just deleted as reset pins, the code is as follows:

20220324154439

4.3.2 Network Clock Pin Configuration

In imx6ull-my-emmc.dts, will be the following two codes

20220324154640

The following parameters are modified to 0x4001b009 (the electrical property values ​​of the two pins)

4.3.3 Modify the pinctrl-0 attribute of a node

Modify the location as follows

20220324154953

Modify these two node attributes to the following figure, and pass in the reset function we wrote above:

20220324155519

4.3.4 Modify network port node and add reset

In the device tree file, the node of fec2 has the address information of the write network port

20220324155707

Modify the value of reg, corresponding to 0 and 1, because the number after ethernet-phy@ is the PHY address, and the PHY address of ENET1 is 0,
so the @ is followed by 0, and the same is true for ENET2:

20220324160418

Add a reset pin in the two fec nodes and set the duration to 200ms for subsequent software reset use

20220324160319

Add driver information to the node to guide the kernel to find the corresponding driver

20220324161045

After the configuration is complete, recompile the device tree

4.3.5 Modify the network driver

Open the drivers/net/ethernet/freescale/fec_main.c file and add the following code to the function fec_probe:

20220324163235

Used to reset the two chips to ensure normal operation, enter the following code to open the graphical interface

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-  menuconfig

Enable the network port driver on the interface, the path is as follows

-> Device Drivers
    -> Network device support
        -> PHY Device support and infrastructure
        	-> Drivers for SMSC PHYs

20220324163623

If checked, the LAN8720 driver will be compiled

4.3.6 Modify smsc.c file and add soft reset

In Linux, a soft reset of LAN8720A is required to ensure normal operation. The driver file of LAN8720A is drivers/net/phy/smsc.c, you can modify this file and find the smsc_phy_reset reset function inside.

Modified to the following code

	//初始化变量
	int err, phy_reset;
	int msec = 1;
	struct device_node *np;
	int timeout = 50000;
	//获取 FEC1 网卡对应的设备节点
	if(phydev->addr == 0) /* FEC1 */ 
	{
    
    
		np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
		if(np == NULL)
		{
    
    
			return -EINVAL;
		}
	}
	//获取 FEC2 网卡对应的设备节点
	if(phydev->addr == 1) /* FEC2 */ 
	{
    
    
		np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
		if(np == NULL)
		{
    
    
			return -EINVAL;
		}
	}
	//从设备树中获取“phy-reset-duration”属性信息,也就是复位时间
	err = of_property_read_u32(np, "phy-reset-duration", &msec);
	/* A sane reset duration should not be longer than 1s */
	if (!err && msec > 1000)
		msec = 1;
	//从设备树中获取“phy-reset-gpios”属性信息,也就是复位 IO
	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
	if (!gpio_is_valid(phy_reset))
		return;
	//复位 LAN8720A
	gpio_direction_output(phy_reset, 0);
	gpio_set_value(phy_reset, 0);
	msleep(msec);
	gpio_set_value(phy_reset, 1);
	//处于 Powerdown 模式的时候才会软复位 LAN8720
	int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
	if (rc < 0)
		return rc;
	if ((rc & MII_LAN83C185_MODE_MASK) ==MII_LAN83C185_MODE_POWERDOWN) 
	{
    
    
		/* set "all capable" mode and reset the phy */
		rc |= MII_LAN83C185_MODE_ALL;
		phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
	}
	phy_write(phydev, MII_BMCR, BMCR_RESET);
	/* wait end of reset (max 500 ms) */
	do {
    
    
		udelay(10);
		if (timeout-- == 0)
		return -1;
		rc = phy_read(phydev, MII_BMCR);
	} while (rc & BMCR_RESET);
	return 0;

After modifying the device tree and the Linux kernel, recompile it, start the Linux kernel, and use the ifconfig command to view the network card

20220324172841

Ping the host, success

20220324173007

4.4 Save the modified configuration file

When modifying the network driver, we enabled the LAN8720A driver through the graphical interface. After enabling, the following code will exist in .config

CONFIG_SMSC_PHY=y

When CONFIG_SMSC_PHY=y, the driver file smsc.c will be compiled. When we execute make clean to clean up the project, the .config file will be deleted, so save the file

  • non-graphical

In non-graphical mode, directly rename the generated .config file to the imx_my_emmc_defconfig configuration file and save it to arch/arm/configs

  • Graphical

Rename the generated .config file to the imx_my_emmc_defconfig configuration file in the graphical interface and save it to arch/arm/configs

V. Summary of Transplantation

  • Get the original kernel source code
  • Copy the configuration file, device tree file, compile and download to test whether linux can start
  • Modify the configuration file
  • Modify the device tree file (important device tree and driver files such as network port, EMMC, serial port, etc., adapt to your own board)
  • Compile and generate zImage and device tree files for the development board
  • port rootfs
  • finish the flower

Guess you like

Origin blog.csdn.net/qq_45396672/article/details/123717176