builduartintel-fpganiosuclinux

Build uClinux for FPGA?


I want to build a Linux for my Altera DE2-115 that connects with the serial port. Now I see kernel panic from the serial port when I try and run it:

 0.000000] Linux version 4.8.0+ (developer@developer-Latitude-E7450) (gcc version 6.2.0 (Sourcery CodeBench Lite 207
[    0.000000] bootconsole [early0] enabled
[    0.000000] early_console initialized at 0xe8001400
[    0.000000] On node 0 totalpages: 32768
[    0.000000] free_area_init_node: node 0, pgdat c05d88f0, node_mem_map c0699740
[    0.000000]   Normal zone: 288 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 32768 pages, LIFO batch:7
[    0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[    0.000000] pcpu-alloc: [0] 0 
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 32480
[    0.000000] Kernel command line: debug console=ttyAL0,115200
[    0.000000] PID hash table entries: 512 (order: -1, 2048 bytes)
[    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Sorting __ex_table...
[    0.000000] allocated 131072 bytes of page_ext
[    0.000000] Memory: 122900K/131072K available (4215K kernel code, 166K rwdata, 1456K rodata, 164K init, 740K bss, 81)
[    0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS:64 nr_irqs:64 0
[    0.000000] Kernel panic - not syncing: 1 timer is found, it needs 2 timers in system
[    0.000000] 
[    0.000000] ---[ end Kernel panic - not syncing: 1 timer is found, it needs 2 timers in system
[    0.000000] 
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15
[    0.000000] Kernel panic - not syncing: Oops
[    0.000000] ---[ end Kernel panic - not syncing: Oops
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] ea = c0003de4, ra = c028ac84, cause = 15

There were many steps and I will try and rebuild with two timers but can you tell me how I should do it? What information more is needed? I changed a lot in make menuconfig but now I proved that it can get started and seen with through the serial port. I used a .sof from a friend who had a very stripped down version of uClinux and it was also old. It only had root access and I try and make one where you can log in. The dts file is as follows.

/*
 * This devicetree is generated by sopc2dts version unknown on Mon Mar 13 18:52:55 CET 2017
 * Sopc2dts is written by Walter Goossens <[email protected]>
 * in cooperation with the nios2 community <[email protected]>
 */
/dts-v1/;

/ {
    model = "ALTR,qsys";
    compatible = "ALTR,qsys";
    #address-cells = <1>;
    #size-cells = <1>;

    cpus {
        #address-cells = <1>;
        #size-cells = <0>;

        cpu: cpu@0x0 {
            device_type = "cpu";
            compatible = "altr,nios2-16.1", "altr,nios2-1.1";
            reg = <0x00000000>;
            interrupt-controller;
            #interrupt-cells = <1>;
            altr,exception-addr = <3221225504>; /* embeddedsw.dts.params.altr,exception-addr type NUMBER */
            altr,fast-tlb-miss-addr = <3355447296>; /* embeddedsw.dts.params.altr,fast-tlb-miss-addr type NUMBER */
            altr,has-initda = <1>;  /* embeddedsw.dts.params.altr,has-initda type NUMBER */
            altr,has-mmu = <1>; /* embeddedsw.dts.params.altr,has-mmu type NUMBER */
            altr,has-mul = <1>; /* embeddedsw.dts.params.altr,has-mul type NUMBER */
            altr,implementation = "fast";   /* embeddedsw.dts.params.altr,implementation type STRING */
            altr,pid-num-bits = <8>;    /* embeddedsw.dts.params.altr,pid-num-bits type NUMBER */
            altr,reset-addr = <3221225472>; /* embeddedsw.dts.params.altr,reset-addr type NUMBER */
            altr,tlb-num-entries = <256>;   /* embeddedsw.dts.params.altr,tlb-num-entries type NUMBER */
            altr,tlb-num-ways = <16>;   /* embeddedsw.dts.params.altr,tlb-num-ways type NUMBER */
            altr,tlb-ptr-sz = <8>;  /* embeddedsw.dts.params.altr,tlb-ptr-sz type NUMBER */
            clock-frequency = <50000000>;   /* embeddedsw.dts.params.clock-frequency type NUMBER */
            dcache-line-size = <32>;    /* embeddedsw.dts.params.dcache-line-size type NUMBER */
            dcache-size = <2048>;   /* embeddedsw.dts.params.dcache-size type NUMBER */
            icache-line-size = <32>;    /* embeddedsw.dts.params.icache-line-size type NUMBER */
            icache-size = <4096>;   /* embeddedsw.dts.params.icache-size type NUMBER */
        }; //end cpu@0x0 (cpu)
    }; //end cpus

    memory {
        device_type = "memory";
        reg = <0x08001000 0x00000400>,
            <0x00000000 0x08000000>;
    }; //end memory

    sopc0: sopc@0 {
        device_type = "soc";
        ranges;
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "ALTR,avalon", "simple-bus";
        bus-frequency = <50000000>;

        jtag: serial@0x8001440 {
            compatible = "altr,juart-16.1", "altr,juart-1.0";
            reg = <0x08001440 0x00000008>;
            interrupt-parent = <&cpu>;
            interrupts = <1>;
        }; //end serial@0x8001440 (jtag)

        timer: timer@0x8001420 {
            compatible = "altr,timer-16.1", "altr,timer-1.0";
            reg = <0x08001420 0x00000020>;
            interrupt-parent = <&cpu>;
            interrupts = <0>;
            clock-frequency = <50000000>;   /* embeddedsw.dts.params.clock-frequency type NUMBER */
        }; //end timer@0x8001420 (timer)

        uart: serial@0x8001400 {
            compatible = "altr,uart-16.1", "altr,uart-1.0";
            reg = <0x08001400 0x00000020>;
            interrupt-parent = <&cpu>;
            interrupts = <2>;
            clock-frequency = <50000000>;   /* embeddedsw.dts.params.clock-frequency type NUMBER */
            current-speed = <115200>;   /* embeddedsw.dts.params.current-speed type NUMBER */
        }; //end serial@0x8001400 (uart)
    }; //end sopc@0 (sopc0)

    chosen {
        bootargs = "debug console=ttyAL0,115200";
    }; //end chosen
}; //end /

Solution

  • You don't run Linux on the "Altera DE2-115" board, you run it on the hardware implemented in the FPGA (as Cyclone IV E chip "EP4CE115" used in the board is not a SoC and have no any "hard cores" of some ARM Cortex-A9 or like). It is impossible to fully answer the question without details of the hardware you have implemented, as FPGAs allow to implement anything (which fits into the FPGA used).

    Your kernel and your nios 2 implementation are not compatible. Can you regenerate FPGA bitstream, do you have quartus / qsys project with the nios 2 and its settings?

    You should check how many timers are implemented in your nios, as your kernel requires two of them, which is visible at first "panic":

     [    0.000000] Kernel panic - not syncing: 1 timer is found, it needs 2 timers in system
    

    This requirement is arch-specific for the nios2, it is from time initializer code: http://lxr.free-electrons.com/source/arch/nios2/kernel/time.c?v=4.8#L341

    341 void __init time_init(void)
    
    343         struct device_node *np;
    344         int count = 0;
    345 
    346         for_each_compatible_node(np, NULL,  ALTR_TIMER_COMPATIBLE)
    347                 count++;
    348 
    349         if (count < 2)
    350                 panic("%d timer is found, it needs 2 timers in system\n", count); 
    

    Rebuilding of the linux kernel 4.8 will not help, as this code is always unconditionally compiled into it: http://lxr.free-electrons.com/source/arch/nios2/kernel/Makefile?v=4.8 20 obj-y += time.o

    And your build of the kernel correct or almost correct, as it boots.

    What you should do - provide needed timers in your soft core by reconfiguring qsys project (add second timer, connect it like the first one, but on different address and new interrupt id; other parameters should be as required by altera's linux). Then rebuild bitstream with quartus (it is long). And also register new timer in the device tree with correct offsets/irq id, then relink kernel with devicetree and reupload both FPGA bitstream and linux image to FPGA / Flash.

    The requirements of two timers for 3.19+ kernels are listed at https://rocketboards.org/foswiki/view/Documentation/NiosIILinuxUserManual (commit http://lkml.iu.edu/hypermail/linux/kernel/1507.0/01501.html?)

    Kernel v3.19 and above Few things need to be noted if using kernel 3.19 and above:

    • Toolchain: Sourcery CondeBench Lite 2014.05-47 and above
    • Hardware: 2 timers in nios2 system
    • DTS: Small letter for altr prefix in dts file, eg: altr,has-mmu; compatible = "altr,juart-1.0";

    Or you can try some kernel older than 3.19, which may work with single timer.