为 FPGA 构建 uClinux?

Build uClinux for FPGA?

我想为我的 Altera DE2-115 构建一个 Linux 连接串行端口。现在,当我尝试 运行 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

有很多步骤,我会尝试用两个计时器重建,但你能告诉我应该怎么做吗?还需要什么信息?我在make menuconfig改了很多,现在证明可以通过串口用启动和查看了。我使用了一位朋友的 .sof,他有一个非常精简的 uClinux 版本,而且它也很旧。它只有root权限,我尝试制作一个可以登录的地方。dts文件如下。

/*
 * This devicetree is generated by sopc2dts version unknown on Mon Mar 13 18:52:55 CET 2017
 * Sopc2dts is written by Walter Goossens <waltergoossens@home.nl>
 * in cooperation with the nios2 community <nios2-dev@lists.rocketboards.org>
 */
/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 /

你不 运行 Linux 在 "Altera DE2-115" 板上,你 运行 它在 FPGA 中实现的硬件上(如 Cyclone IV E 芯片 [=板中使用的 37=] 不是 SoC,并且没有任何 "hard cores" 的某些 ARM Cortex-A9 或类似的)。 如果没有您实现的硬件的详细信息,就不可能完全回答这个问题,因为 FPGA 允许实现任何东西(适合所用的 FPGA)。

您的内核和 nios 2 实现不兼容。你能重新生成 FPGA 比特流吗?你有 quartus/qsys 项目和 nios 2 及其设置吗?

你应该检查你的 nios 中实现了多少个定时器,因为你的内核需要两个,一开始是可见的 "panic":

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

这个要求是针对 nios2 的 arch-specific,它来自时间初始化代码: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); 

重建 linux 内核 4.8 无济于事,因为此代码总是无条件地编译到其中:http://lxr.free-electrons.com/source/arch/nios2/kernel/Makefile?v=4.8 20 obj-y += time.o

并且您的内核构建在启动时正确或几乎正确。

你应该做什么 - 通过重新配置 qsys 项目在你的软核中提供所需的定时器(添加第二个定时器,像第一个一样连接它,但是在不同的地址和新的中断 ID 上;其他参数应该按照 altera 的要求linux)。然后用quartus重建比特流(很长)。并在设备树中使用正确的 offsets/irq id 注册新定时器,然后将内核与设备树重新链接并将 FPGA 比特流和 linux 图像重新上传到 FPGA / Flash。

3.19+内核对两个定时器的要求列在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";

或者您可以尝试一些早于 3.19 的内核,它可以使用单个计时器。