Linux kernel transplantation based on tiny4412 (supports device tree) (3)

Publisher:mancozcLatest update time:2023-06-20 Source: elecfansKeywords:tiny4412  Linux Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Platform introduction

Development board: tiny4412ADK + S700 + 4GB Flash

Kernel version to be transplanted: Linux-4.4.0 (supports device tree)

u-boot version: U-Boot 2010.12 that comes with Friendly Arm (some changes have been made to support uImage startup)

busybox version: busybox 1.25

Cross-compilation tool chain: arm-none-linux-gnueabi-gcc

      (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29))


Notice

Continue above.

So far, the board is up and running, and then the driver can be transplanted according to the board's conditions. I’ll do this later. Here’s some knowledge I gained during the tossing process to share.


1. Device tree decompilation

When we execute make dtbs in the kernel directory, some .dtb files will be generated under arch/arm/boot/dts. So what is in this file? We can use the dtc command to decompile these dtb files. The executable program dtc here has been provided in the Linux kernel source code. The specific path is: scripts/dtc/. You can use the following command to compile this tool from the Linux source code:

make CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm scripts

 This will generate the executable program dtc under scripts/dtc.


Of course, if you do not have the Linux source code, you can also use the apt-get command to install this tool. The command is as follows:


sudo apt-get install device-tree-compiler

 The following takes exynos4412-tiny4412.dtb as an example:


Order:


dtc -I dtb -O dts -o tiny4412.dts arch/arm/boot/dts/exynos4412-tiny4412.dtb

Then the decompiled file tiny4412.dts will be generated, part of which is as follows:


/dts-v1/;


/ {

    #address-cells = <;0x1>;

    #size-cells = <;0x1>;

    interrupt-parent = <;0x1>;

    compatible = "friendlyarm,tiny4412", "samsung,exynos4412", "samsung,exynos4";

    model = "FriendlyARM TINY4412 board based on Exynos4412";


    chosen {

        stdout-path = "/serial@13800000";

        bootargs = "root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc earlyprintk";

    };


    aliases {

        spi0 = "/spi@13920000";

        spi1 = "/spi@13930000";

        spi2 = "/spi@13940000";

        i2c0 = "/i2c@13860000";

        i2c1 = "/i2c@13870000";

        i2c2 = "/i2c@13880000";

        i2c3 = "/i2c@13890000";

        i2c4 = "/i2c@138A0000";

        i2c5 = "/i2c@138B0000";

        i2c6 = "/i2c@138C0000";

        i2c7 = "/i2c@138D0000";

        i2c8 = "/i2c@138E0000";

        csis0 = "/camera/csis@11880000";

        csis1 = "/camera/csis@11890000";

        fimc0 = "/camera/fimc@11800000";

        fimc1 = "/camera/fimc@11810000";

        fimc2 = "/camera/fimc@11820000";

        fimc3 = "/camera/fimc@11830000";

        serial0 = "/serial@13800000";

        serial1 = "/serial@13810000";

        serial2 = "/serial@13820000";

        serial3 = "/serial@13830000";

        pinctrl0 = "/pinctrl@11400000";

        pinctrl1 = "/pinctrl@11000000";

        pinctrl2 = "/pinctrl@03860000";

        pinctrl3 = "/pinctrl@106E0000";

        fimc-lite0 = "/camera/fimc-lite@12390000";

        fimc-lite1 = "/camera/fimc-lite@123A0000";

        mshc0 = "/mmc@12550000";

    };


    memory {

        device_type = "memory";

        reg = <0x40000000 0x40000000>;

    };


    clock-controller@03810000 {

        compatible = "samsung,exynos4210-audss-clock";

        reg = <0x3810000 0xc>;

        #clock-cells = <;0x1>;

        linux,phandle = <;0x2>;

        phandle = <;0x2>;

    };

    i2s@03830000 {

This method is very helpful for learning device trees.

2. Print information in u-boot

In many files in u-boot, debug(...) is used to print information. By default, these logs cannot be printed. The definition of this function is in include/common.h:


#ifdef DEBUG

#define debug(fmt,args...)    printf (fmt ,##args)

#define debugX(level,fmt,args...) if (DEBUG>=level) printf(fmt,##args);

#else

#define debug(fmt,args...)

#define debugX(level,fmt,args...)

#endif /* DEBUG */

So you can add #define DEBUG at the top of the C file that calls the debug function. This method is also commonly used in the Linux kernel and Android.


3. Open the early log of Linux kernel startup

Sometimes, after bootm is executed in u-boot, the serial port does not output any information after the start kernel is printed. At this time, you need to open the early kernel log:


make menuconfig


  Kernel hacking  --->


      [*] Kernel low-level debugging functions (read help!)


             Kernel low-level debugging port (Use Samsung S3C UART 0 for low-level debug)


      [*] Early printk


For earlyprintk, you need to add the parameter earlyprintk in bootargs to take effect. With the above configurations, the following macros will take effect:


CONFIG_DEBUG_LL=y


CONFIG_DEBUG_S3C_UART0=y


CONFIG_DEBUG_LL_INCLUDE="debug/exynos.S"


CONFIG_DEBUG_UNCOMPRESS=y

CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"

CONFIG_EARLY_PRINTK=y


The analysis of earlyprintk is in the file arch/arm/kernel/early_printk.c:


   1: extern void printch(int);

   2: 

   3: static void early_write(const char *s, unsigned n)

   4: {

   5:     while (n-- >; 0) {

   6:         if (*s == 'n')

   7:             printch('r');

   8:         printch(*s);

   9:         s++;

  10:     }

  11: }

  12:  

  13: static void early_console_write(struct console *con, const char *s, unsigned n)

  14: {

  15:     early_write(s, n);

  16: }

  17:  

  18: static struct console early_console_dev = {

  19:     .name =        "earlycon",

  20:     .write =    early_console_write,

  21:     .flags =    CON_PRINTBUFFER | CON_BOOT,

  22:     .index =    -1,

  23: };

  24: 

  25: static int __init setup_early_printk(char *buf)

  26: {

  27:     early_console = &;early_console_dev;

  28:     register_console(&;early_console_dev);

  29:     return 0;

  30: }

  31:  

  32: early_param("earlyprintk", setup_early_printk);

Among them, printch is implemented through assembly language.


You can see this in arch/arm/Kconfig.debug:


config DEBUG_LL

    bool "Kernel low-level debugging functions (read help!)"

    depends on DEBUG_KERNEL

    help

      Say Y here to include definitions of printascii, printch, printhex

      in the kernel.  This is helpful if you are debugging code that

      executes before the console is initialized.


 


config DEBUG_S3C_UART0

    depends on PLAT_SAMSUNG

    select DEBUG_EXYNOS_UART if ARCH_EXYNOS

    select DEBUG_S3C24XX_UART if ARCH_S3C24XX

    select DEBUG_S5PV210_UART if ARCH_S5PV210

    bool "Use Samsung S3C UART 0 for low-level debug"

    help

      Say Y here if you want the debug print routines to direct

      their output to UART 0. The port must have been initialised

      by the boot-loader before use.


 


config DEBUG_LL_INCLUDE

    string

    ……

    default "debug/exynos.S" if DEBUG_EXYNOS_UART


 


config EARLY_PRINTK

    bool "Early printk"

    depends on DEBUG_LL

    help

      Say Y here if you want to have an early console using the

      kernel low-level debugging functions. Add earlyprintk to your

      kernel parameters to enable this console.


From the above information we can know:


When the serial port terminal has not been registered, the kernel defines printascii, printch and printhex for debugging;

The early console also uses the function defined above. You need to add the earlyprintk parameter to the parameters passed to the kernel.

The output serial port of the early print function of the Linux kernel must be consistent with that used under u-boot, that is, the kernel is no longer responsible for initialization and lets u-boot do it, so the two must be consistent, otherwise the print functions and earlyprintk will not work. Output information;

You can refer to arch/arm/kernel/debug.S, printascii, printch and printhex are all defined here;

After the kernel enters the C function (start_kernel), you can call early_print to print information. It is defined in arch/arm/kernel/setup.c:

   1: void __init early_print(const char *str, ...)

   2: {

   3:     extern void printascii(const char *);

   4:     char buf[256];

   5: va_list ap;

   6: 

   7:     va_start(ap, str);

   8:     vsnprintf(buf, sizeof(buf), str, ap);

   9: va_end(ap);

  10:  

  11: #ifdef CONFIG_DEBUG_LL

  12:     printascii(buf);

  13: #endif

  14:     printk("%s", buf);

  15: }

As you can see, early_print will also call printascii and printk, which means that the information printed with early_print may appear repeatedly on the terminal (printk will buffer part of it, and when bootconsole is registered, the content in the printk buffer will be output).


The printing function mentioned above can only be used in functions after kernel self-decompression. So can the information during the kernel self-decompression process also be printed? Yes, the files related to kernel self-extraction are under arch/arm/boot/compressed/, which we are familiar with:


Uncompressing Linux... done, booting the kernel.


It is printed by the code in this directory. The specific code is as follows:


arch/arm/boot/compressed/misc.c


   1: void

   2: decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,

   3:         unsigned long free_mem_ptr_end_p,

   4:         int arch_id)

   5: {

   6:     ......

   7:     putstr("Uncompressing Linux...");

   8:     ret = do_decompress(input_data, input_data_end - input_data,

   9:                 output_data, error);

  10:     ......

  11:     putstr(" done, booting the kernel.n");

  12: }

 Among them, putstr is defined as follows:


   1: static void putstr(const char *ptr)

   2: {

   3:     char c;

   4: 

   5:     while ((c = *ptr++) != '') {

   6:         if (c == 'n')

   7:             putc('r');

   8:         putc(c);

   9:     }

  10:  

  11:     flush();

  12: }

 putc is implemented in assembly, arch/arm/boot/compressed/debug.S:


   1: #include CONFIG_DEBUG_LL_INCLUDE

   2:  

   3: ENTRY(putc)

   4:     addruart r1, r2, r3

   5:     waituart r3, r1

   6:     senduart r0, r1

   7: busyuart r3, r1

   8:     mov     pc, lr

   9: ENDPROC(putc)

  10:  

  11:  

The implementation of addruart varies depending on the SOC. For exynos4412, its implementation is (arch/arm/include/debug/exynos.S):


   1: .macro addruart, rp, rv, tmp

   2:     mrc    p15, 0, tmp, c0, c0, 0

   3:     and    tmp, tmp, #0xf0

[1] [2] [3] [4]
Keywords:tiny4412  Linux Reference address:Linux kernel transplantation based on tiny4412 (supports device tree) (3)

Previous article:Linux kernel transplantation based on tiny4412 (supports device tree) (2)
Next article:Linux kernel transplantation based on tiny4412--DM9621NP network card driver transplantation (4)

Recommended ReadingLatest update time:2024-11-16 08:36

mini2440 u-boot linux kernel boot,Mini2440 uboot,kernel,root file system construction
According to the manual of mini2440, I have learned that the construction process of uboot, kernel and root file system is as follows. The specific details are not considered for the time being, only the entire compilation and burning process is considered. First of all, our host machine must have nfs server and tft
[Microcontroller]
ARM platform Linux kernel Notes 1
Linux memory management The paging management of embedded processors is a two-level mapping, with memory space and I/O space addressed uniformly, while the x86 processor uses a three-level mapping, with memory space and I/O space addressed independently. In a 32-bit embedded system, the address range o
[Microcontroller]
ARM platform Linux kernel Notes 1
OK6410A Development Board (VIII) 8 linux-5.11 OK6410A Detailed analysis of the start_kernel runtime stack
include/asm-generic/vmlinux.lds.h  376 #define INIT_TASK_DATA(align)                                                     377     . = ALIGN(align);                                                             378     __start_init_task = .;                                                        379     init_thread_unio
[Microcontroller]
4412 Linux delay and time
basic knowledge • The delay function in Linux is very simple, but often used • The operating system and the MCU handle delays in completely different ways. It is impossible to use The for loop wastes system resources. Instead, there is a dedicated interface function • Commonly used delay functions in Linux system prog
[Microcontroller]
Port linux-3.0 to FL2440 (only basic porting)
First of all, the patch package comes from Lingyun Lab: 1. Apply the patch first: patch -p1 ../linux-3.0-s3c2440.patch 2. Modify the Makefile: ARCH ?= arm CROSS_COMPILE ?= arm-linux- 3. Modify the patch error: in /arch/arm/plat -s3c24xx/devs.c //#ifdef CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X /* UDA1341 add
[Microcontroller]
設置Linux保留物理內存並使用 (1)
平臺 硬件平臺: TQ2440 Linux version: Linux 3.14.45 說明 1.在tq2440上,物理內存的起始地址是0x30000000,一共有64MB的內存,所以物理內存地址範圍是: 0x30000000 - 0x33ffffff 2.可以在uboot傳給kernel的參數bootargs中添加一個"memblock=debug",這樣在Linux啓動的時候,會將設置memblock的信息打印出來 參考博文 Linux kernel---41.arm memory initialization http://bbs.chinaunix.net/thread-4143403-1-1.
[Microcontroller]
Linux ARM (IMX6U) BSP project management experiment
When we write a project, we put all the source code files in the root directory of the project. If there are relatively few project files, this is understandable. However, if the number of source files reaches dozens or even hundreds, putting them all in the root directory will make the project look messy. Therefore,
[Microcontroller]
Linux ARM (IMX6U) BSP project management experiment
Chapter 10, Tiny4412 U-BOOT transplantation 10 DDR working timing and principle 2
The development of DDR is towards higher data transmission frequency and larger memory capacity. DDR2 achieves higher data transmission frequency, and develops from DDR's 2-bit pretetch to 4-bit pretetch. To expand capacity, in addition to increasing the capacity of each L-Bank, the number of L-Banks is also increased
[Microcontroller]
Chapter 10, Tiny4412 U-BOOT transplantation 10 DDR working timing and principle 2
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号