neuschaefer / wpcm450

Nuvoton WPCM450 tools and documentation
26 stars 4 forks source link

QEMU #10

Open neuschaefer opened 3 years ago

neuschaefer commented 3 years ago

It would be interesting to have WPCM450 system emulation in QEMU. Some of the peripherals of NPCM7xx can probably be reused.

Hurricos commented 3 years ago

Based on this FOSDEM presentation, there isn't any 'nice' way to translate a device tree directly into any of the QEMU device APIs, so a QEMU config would have to be built by hand. Still, I agree, it'd be very nice to verify booting works in QEMU before flashing the build directly e.g. to a motherboard.

peripherals of NPCM7xx can probably be reused.

In what sense? Has a QEMU config already been set up for the NPCM7xx?

neuschaefer commented 3 years ago

QEMU already has peripheral device implementations and SoC/board configs for NPCM750:

$ qemu-system-arm -M ? | grep NPCM
npcm750-evb          Nuvoton NPCM750 Evaluation Board (Cortex A9)

The configurations are probably too specific to the NPCM750(-evb) to reuse, but some of the device emulation code (e.g. I2C) can probably be reused.

I may be misunderstanding what you mean by a "QEMU config". If that's the case, please elaborate.

Hurricos commented 3 years ago

No, you understood me correctly. I actually was not actually really cognizant that the Qemu Object Model actually gets used using C code. Thanks for the links to the SoC and boards.

So would a good way to build the device in QEMU be to loop through the following?:

1) take a minimal default QEMU arm32 SoC + Board, 2) rebuild Linux using select patches from your tree, where applicable 3) migrate an item described in the final device tree into both the compiled-in device tree and into the SoC / board config 4) rebuild qemu 5) Repeat from step 2

neuschaefer commented 3 years ago

Sounds like an approach that should work.

For an absolutely minimal configuration, I think you'll need:

If you have any questions regarding how a peripheral works, please use the wiki and/or raise issues with the "Documentation" tag. I'll be happy to help!

StidOfficial commented 3 years ago

I take versatile board like base board and take some code from npcm7xx board, change base address and irq from your wiki.

Your 2 bare-metal programs (screem and monitor) your for UART0 output with serail0 on qemu but output not work. I just configure UART address, so i think is important to configure interrupt controller and timer correctly for make monitor work correctly.

I continue to work on and publish as soon as possible the modification on github.

Thanks for you work

neuschaefer commented 3 years ago

Hi @StidOfficial, The scream program only accesses the UART. I think it's a good first test case, because it is (almost) the simplest possible test program. The monitor accesses the UART and the timer, but not the interrupt controller, so it should, at this point, not be necessary to hook up the interrupt controller.

StidOfficial commented 3 years ago

The npcm7xx_timer are the same but the mapping for timers and watchdogs are completly diffrent for the npcm7xx.

For the bases addresses : https://github.com/qemu/qemu/blob/52fecb866923890b16202be8e0f360bf247db6a7/hw/arm/npcm7xx.c#L147-L152 With have only 1 address for timers on 0xb8001000 ?

For timers device and sysbuse : https://github.com/qemu/qemu/blob/master/hw/arm/npcm7xx.c#L530-L558 For monitor we the need to do :

SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim);

/* Connect the timer clock. */
qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
            DEVICE(&s->clk), "timer-clock"));

sysbus_realize(sbd, &error_abort);
sysbus_mmio_map(sbd, 0, 0xb8001000);

sysbus_connect_irq(sbd, 1, 12); // Timer 1

/* IRQ for watchdogs */
sysbus_connect_irq(sbd, 5, npcm7xx_irq(s, 1));
/* GPIO that connects clk module with watchdog */
qdev_connect_gpio_out_named(DEVICE(&s->tim),
        NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 0,
        qdev_get_gpio_in_named(DEVICE(&s->clk),
                NPCM7XX_WATCHDOG_RESET_GPIO_IN, i));

The watchdog require npcm7xx clock ? For the timer2/3/4 with need a adustment with npcm7xx-timer ?

It's really complicated because npcm7xx use new method of implementation device (I can't make it work) and the old method with versation (only UART work).

neuschaefer commented 3 years ago

With have only 1 address for timers on 0xb8001000 ?

Yes, I think that's right.

Regarding IRQs: I'm not familiar with QEMU's IRQ infrastructure, but you can see the interrupt numbers in the wiki.

Regarding clocks... I don't know if they're simulated in QEMU. Maybe you can ignore them entirely.

StidOfficial commented 3 years ago

I have create 2 branch :

On NPCM7XX branch (https://github.com/StidOfficial/qemu/tree/wpcm450-npcm7xx-base) :

(qemu) info mtree
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8001000-00000000b800101f (prio 0, i/o): serial
    00000000f03fe000-00000000f03fffff (prio 0, i/o): a9mp-priv-container
      00000000f03fe100-00000000f03fe1ff (prio 0, i/o): gic_cpu
      00000000f03fe200-00000000f03fe21f (prio 0, i/o): a9gtimer shared
      00000000f03fe600-00000000f03fe61f (prio 0, i/o): arm_mptimer_timer
      00000000f03fe620-00000000f03fe63f (prio 0, i/o): arm_mptimer_timer
      00000000f03ff000-00000000f03fffff (prio 0, i/o): gic_dist

address-space: I/O
  0000000000000000-000000000000ffff (prio 0, i/o): io

address-space: cpu-memory-0
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8001000-00000000b800101f (prio 0, i/o): serial
    00000000f03fe000-00000000f03fffff (prio 0, i/o): a9mp-priv-container
      00000000f03fe100-00000000f03fe1ff (prio 0, i/o): gic_cpu
      00000000f03fe200-00000000f03fe21f (prio 0, i/o): a9gtimer shared
      00000000f03fe600-00000000f03fe61f (prio 0, i/o): arm_mptimer_timer
      00000000f03fe620-00000000f03fe63f (prio 0, i/o): arm_mptimer_timer
      00000000f03ff000-00000000f03fffff (prio 0, i/o): gic_dist

(qemu) info roms
addr=0000000000000000 size=0x00001c mem=ram name="bootloader"
addr=0000000000010000 size=0x010000 mem=ram name="../../wpcm450/src/bare-metal/monitor.img"
(qemu) info qom-tree 
/machine (idrac6-bmc-machine)
  /peripheral (container)
  /peripheral-anon (container)
  /soc (nuvoton-wpcm450)
    /a9mpcore (a9mpcore_priv)
      /a9mp-priv-container[0] (memory-region)
      /gic (arm_gic)
        /gic_cpu[0] (memory-region)
        /gic_cpu[1] (memory-region)
        /gic_dist[0] (memory-region)
        /unnamed-gpio-in[0] (irq)
        /unnamed-gpio-in[10] (irq)
        /unnamed-gpio-in[11] (irq)
        /unnamed-gpio-in[12] (irq)
        /unnamed-gpio-in[13] (irq)
        /unnamed-gpio-in[14] (irq)
        /unnamed-gpio-in[15] (irq)
        /unnamed-gpio-in[16] (irq)
        /unnamed-gpio-in[17] (irq)
        /unnamed-gpio-in[18] (irq)
        /unnamed-gpio-in[19] (irq)
        /unnamed-gpio-in[1] (irq)
        /unnamed-gpio-in[20] (irq)
        /unnamed-gpio-in[21] (irq)
        /unnamed-gpio-in[22] (irq)
        /unnamed-gpio-in[23] (irq)
        /unnamed-gpio-in[24] (irq)
        /unnamed-gpio-in[25] (irq)
        /unnamed-gpio-in[26] (irq)
        /unnamed-gpio-in[27] (irq)
        /unnamed-gpio-in[28] (irq)
        /unnamed-gpio-in[29] (irq)
        /unnamed-gpio-in[2] (irq)
        /unnamed-gpio-in[30] (irq)
        /unnamed-gpio-in[31] (irq)
        /unnamed-gpio-in[32] (irq)
        /unnamed-gpio-in[33] (irq)
        /unnamed-gpio-in[34] (irq)
        /unnamed-gpio-in[35] (irq)
        /unnamed-gpio-in[36] (irq)
        /unnamed-gpio-in[37] (irq)
        /unnamed-gpio-in[38] (irq)
        /unnamed-gpio-in[39] (irq)
        /unnamed-gpio-in[3] (irq)
        /unnamed-gpio-in[40] (irq)
        /unnamed-gpio-in[41] (irq)
        /unnamed-gpio-in[42] (irq)
        /unnamed-gpio-in[43] (irq)
        /unnamed-gpio-in[44] (irq)
        /unnamed-gpio-in[45] (irq)
        /unnamed-gpio-in[46] (irq)
        /unnamed-gpio-in[47] (irq)
        /unnamed-gpio-in[48] (irq)
        /unnamed-gpio-in[49] (irq)
        /unnamed-gpio-in[4] (irq)
        /unnamed-gpio-in[50] (irq)
        /unnamed-gpio-in[51] (irq)
        /unnamed-gpio-in[52] (irq)
        /unnamed-gpio-in[53] (irq)
        /unnamed-gpio-in[54] (irq)
        /unnamed-gpio-in[55] (irq)
        /unnamed-gpio-in[56] (irq)
        /unnamed-gpio-in[57] (irq)
        /unnamed-gpio-in[58] (irq)
        /unnamed-gpio-in[59] (irq)
        /unnamed-gpio-in[5] (irq)
        /unnamed-gpio-in[60] (irq)
        /unnamed-gpio-in[61] (irq)
        /unnamed-gpio-in[62] (irq)
        /unnamed-gpio-in[63] (irq)
        /unnamed-gpio-in[6] (irq)
        /unnamed-gpio-in[7] (irq)
        /unnamed-gpio-in[8] (irq)
        /unnamed-gpio-in[9] (irq)
      /gtimer (arm.cortex-a9-global-timer)
        /a9gtimer per cpu[0] (memory-region)
        /a9gtimer shared[0] (memory-region)
      /mptimer (arm_mptimer)
        /arm_mptimer_timer[0] (memory-region)
        /arm_mptimer_timerblock[0] (memory-region)
      /unnamed-gpio-in[0] (irq)
      /unnamed-gpio-in[10] (irq)
      /unnamed-gpio-in[11] (irq)
      /unnamed-gpio-in[12] (irq)
      /unnamed-gpio-in[13] (irq)
      /unnamed-gpio-in[14] (irq)
      /unnamed-gpio-in[15] (irq)
      /unnamed-gpio-in[16] (irq)
      /unnamed-gpio-in[17] (irq)
      /unnamed-gpio-in[18] (irq)
      /unnamed-gpio-in[19] (irq)
      /unnamed-gpio-in[1] (irq)
      /unnamed-gpio-in[20] (irq)
      /unnamed-gpio-in[21] (irq)
      /unnamed-gpio-in[22] (irq)
      /unnamed-gpio-in[23] (irq)
      /unnamed-gpio-in[24] (irq)
      /unnamed-gpio-in[25] (irq)
      /unnamed-gpio-in[26] (irq)
      /unnamed-gpio-in[27] (irq)
      /unnamed-gpio-in[28] (irq)
      /unnamed-gpio-in[29] (irq)
      /unnamed-gpio-in[2] (irq)
      /unnamed-gpio-in[30] (irq)
      /unnamed-gpio-in[31] (irq)
      /unnamed-gpio-in[3] (irq)
      /unnamed-gpio-in[4] (irq)
      /unnamed-gpio-in[5] (irq)
      /unnamed-gpio-in[6] (irq)
      /unnamed-gpio-in[7] (irq)
      /unnamed-gpio-in[8] (irq)
      /unnamed-gpio-in[9] (irq)
      /wdt (arm_mptimer)
        /arm_mptimer_timer[0] (memory-region)
        /arm_mptimer_timerblock[0] (memory-region)
    /cpu[0] (arm926-arm-cpu)
      /unnamed-gpio-in[0] (irq)
      /unnamed-gpio-in[1] (irq)
      /unnamed-gpio-in[2] (irq)
      /unnamed-gpio-in[3] (irq)
  /unattached (container)
    /device[0] (serial-mm)
      /serial (serial)
      /serial[0] (memory-region)
    /device[1] (serial-mm)
      /serial (serial)
      /serial[0] (memory-region)
    /io[0] (memory-region)
    /sysbus (System)
    /system[0] (memory-region)

I can't set maximum irq's to 32 at the moment because GICState can only support 64 and more.

The UART0 doesn't work, but the addresses are correct so i think is a instructor error stop monitor.img execution :

00000000b8000000-00000000b800001f (prio 0, i/o): serial
00000000b8001000-00000000b800101f (prio 0, i/o): serial

I didn't look with gdb.

For versatile branch (https://github.com/StidOfficial/qemu/tree/wpcm450-versatile-base) :

(qemu) info mtree
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-000000000fffffff (prio 0, ram): wpcm450.ram
    0000000010140000-0000000010140fff (prio 0, i/o): pl190
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial

address-space: I/O
  0000000000000000-000000000000ffff (prio 0, i/o): io

address-space: cpu-memory-0
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-000000000fffffff (prio 0, ram): wpcm450.ram
    0000000010140000-0000000010140fff (prio 0, i/o): pl190
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial

(qemu) info roms 
addr=0000000000000000 size=0x00001c mem=ram name="bootloader"
addr=0000000000010000 size=0x010000 mem=ram name="../../wpcm450/src/bare-metal/monitor.img"
(qemu) info qom-tree 
/machine (idrac6-bmc-machine)
  /peripheral (container)
  /peripheral-anon (container)
  /soc (arm926-arm-cpu)
    /unnamed-gpio-in[0] (irq)
    /unnamed-gpio-in[1] (irq)
    /unnamed-gpio-in[2] (irq)
    /unnamed-gpio-in[3] (irq)
  /unattached (container)
    /device[0] (pl190)
      /pl190[0] (memory-region)
      /unnamed-gpio-in[0] (irq)
      /unnamed-gpio-in[10] (irq)
      /unnamed-gpio-in[11] (irq)
      /unnamed-gpio-in[12] (irq)
      /unnamed-gpio-in[13] (irq)
      /unnamed-gpio-in[14] (irq)
      /unnamed-gpio-in[15] (irq)
      /unnamed-gpio-in[16] (irq)
      /unnamed-gpio-in[17] (irq)
      /unnamed-gpio-in[18] (irq)
      /unnamed-gpio-in[19] (irq)
      /unnamed-gpio-in[1] (irq)
      /unnamed-gpio-in[20] (irq)
      /unnamed-gpio-in[21] (irq)
      /unnamed-gpio-in[22] (irq)
      /unnamed-gpio-in[23] (irq)
      /unnamed-gpio-in[24] (irq)
      /unnamed-gpio-in[25] (irq)
      /unnamed-gpio-in[26] (irq)
      /unnamed-gpio-in[27] (irq)
      /unnamed-gpio-in[28] (irq)
      /unnamed-gpio-in[29] (irq)
      /unnamed-gpio-in[2] (irq)
      /unnamed-gpio-in[30] (irq)
      /unnamed-gpio-in[31] (irq)
      /unnamed-gpio-in[3] (irq)
      /unnamed-gpio-in[4] (irq)
      /unnamed-gpio-in[5] (irq)
      /unnamed-gpio-in[6] (irq)
      /unnamed-gpio-in[7] (irq)
      /unnamed-gpio-in[8] (irq)
      /unnamed-gpio-in[9] (irq)
    /device[1] (serial-mm)
      /serial (serial)
      /serial[0] (memory-region)
    /device[2] (serial-mm)
      /serial (serial)
      /serial[0] (memory-region)
    /io[0] (memory-region)
    /sysbus (System)
    /system[0] (memory-region)

The UART0 work, but is difficult to implement the TIMER0 for wait_for_key without create a custom timer device.

If anyone see what is wrong with NPCM7xx branch.

neuschaefer commented 3 years ago

On NPCM7XX branch (https://github.com/StidOfficial/qemu/tree/wpcm450-npcm7xx-base) :


(qemu) info mtree
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8001000-00000000b800101f (prio 0, i/o): serial

The base address of the second UART should be 0xb8000100, not 0xb8001000.

00000000f03fe000-00000000f03fffff (prio 0, i/o): a9mp-priv-container
  00000000f03fe100-00000000f03fe1ff (prio 0, i/o): gic_cpu
  00000000f03fe200-00000000f03fe21f (prio 0, i/o): a9gtimer shared
  00000000f03fe600-00000000f03fe61f (prio 0, i/o): arm_mptimer_timer
  00000000f03fe620-00000000f03fe63f (prio 0, i/o): arm_mptimer_timer
  00000000f03ff000-00000000f03fffff (prio 0, i/o): gic_dist

This stuff looks unnecessary.

It looks like a mapping for RAM is missing. The versatile branch has this line:

     0000000000000000-000000000fffffff (prio 0, ram): wpcm450.ram

(although 00000000-3fffffff should be (more than) enough)

I can't set maximum irq's to 32 at the moment because GICState can only support 64 and more.

Don't worry. In the long term, GIC is the wrong interrupt controller for WPCM450 anyway.

The UART0 doesn't work, but the addresses are correct so i think is a instructor error stop monitor.img execution :

QEMU has some options for instruction tracing, such as -d in_asm. Maybe they'll help in finding the culprit.

For versatile branch (https://github.com/StidOfficial/qemu/tree/wpcm450-versatile-base) :


(qemu) info mtree
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-000000000fffffff (prio 0, ram): wpcm450.ram
    0000000010140000-0000000010140fff (prio 0, i/o): pl190

Again, the wrong interrupt controller

00000000b8000000-00000000b800001f (prio 0, i/o): serial
00000000b8000100-00000000b800011f (prio 0, i/o): serial

But the address of the second UART is right.

StidOfficial commented 3 years ago

The base address of the second UART should be 0xb8000100, not 0xb8001000.

Now is fix

This stuff looks unnecessary.

I regard for NPCM7XX base. But for versatile, i remove the pl190 VIC. Now we have :

(qemu) info mtree
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-000000000fffffff (prio 0, ram): wpcm450.ram
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial

address-space: I/O
  0000000000000000-000000000000ffff (prio 0, i/o): io

address-space: cpu-memory-0
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-000000000fffffff (prio 0, ram): wpcm450.ram
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial

It looks like a mapping for RAM is missing. The versatile branch has this line: 0000000000000000-000000000fffffff (prio 0, ram): wpcm450.ram

Yes i have disable the DRAM, i remove the ifdef and now :

(qemu) info mtree
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-000000000fffffff (prio 0, ram): ram
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial

address-space: I/O
  0000000000000000-000000000000ffff (prio 0, i/o): io

address-space: cpu-memory-0
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-000000000fffffff (prio 0, ram): ram
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial

(although 00000000-3fffffff should be (more than) enough)

On my iDRAC6 i remember (i not sure), i got 264 MiB of RAM, you have 1024 MiB on your iDRAC ?

Now NPCM7XX branch work for UART. You can compile for test and use like this :

./qemu-system-arm -M idrac6-bmc -kernel ../../wpcm450/src/bare-metal/monitor.img

I going to try to implement the npcm7xx_timer and ignore IRQ's interraction. Do you known if we have a standard IC, if we have all necessary information in your wiki ? Do you known if is possible with this state U-boot or not and what is minimal requirement ? And what is the minimum requirement for kernel ? Do you think if is possible to use you bare metal work to implement step by step Watchdor, I2C, IC, ... (I don't known the priority) with QEMU ?

neuschaefer commented 3 years ago

(although 00000000-3fffffff should be (more than) enough)

On my iDRAC6 i remember (i not sure), i got 264 MiB of RAM, you have 1024 MiB on your iDRAC ?

My Supermicro boards have 128 MiB; I haven't checked my Dell board. However, the window in physical address space where RAM can be accessed is larger. The upper bits, that are not used for addressing the RAM, are ignored and the RAM content looks like it repeats in physical address space:

> ww 2000 1 2 3 4 5 6 7 8    # write a test pattern into RAM
> rw 2000 16                 # read it back
00002000: 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008
00002020: 7273752f 6962732f 690a0a6e 205b2066 53502422 5d202231 6874203b 090a6e65
> rw 08002000 16             # same content at 128 MiB
08002000: 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008
08002020: 7273752f 6962732f 690a0a6e 205b2066 53502422 5d202231 6874203b 090a6e65
> rw 0c002000 16             # not at 192 MiB
0c002000: 000220a4 00000005 81020000 00408000 00001800 00000000 08004000 00404001
0c002020: 28000000 50000020 00010002 04800200 00002000 0400000c 82000940 00820000
> rw 10002000 16             # same at 256 MiB
10002000: 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008
10002020: 7273752f 6962732f 690a0a6e 205b2066 53502422 5d202231 6874203b 090a6e65
> rw 20002000 16             # oops, reading here causes a crash
20002000: Press any key to avoid running the default boot script
Loading Linux...

Two things to note here:

I going to try to implement the npcm7xx_timer and ignore IRQ's interraction.

Good. That should be enough to make the timeout logic in monitor.c work.

Do you known if we have a standard IC, if we have all necessary information in your wiki ?

IC meaning interrupt controller? In that case, no, it's not a standard part, it's specific to Winbond/Nuvoton. The wiki page (https://github.com/neuschaefer/wpcm450/wiki/Interrupts) lists the registers and has a few references that can hopefully help you understand the interrupt controller.

If you have questions about any hardware (like the interrupt controller, for example), please ask, ideally in a new github issue for each specific hardware block.

Do you known if is possible with this state U-boot or not and what is minimal requirement ?

Your question is missing a verb. To do what with U-Boot?

And what is the minimul requirement for kernel ?

The kernel port as it was merged in 5.13-rc1 requires the interrupt controller, timer/watchdog, and UART.

Do you think if is possible to use you bare metal work to implement step by step Watchdor, I2C, IC, ... (I don't known the priority) with QEMU ?

My monitor program can probably help a little bit in implementing/testing the various parts, but please note that it doesn't have a lot of drivers in it. The various kernels (ATEN's, AMI's, Dell's, mainline, mine) have more drivers.

StidOfficial commented 3 years ago

My Supermicro boards have 128 MiB; I haven't checked my Dell board. However, the window in physical address space where RAM can be accessed is larger. The upper bits, that are not used for addressing the RAM, are ignored and the RAM content looks like it repeats in physical address space:

That the actual mapping i have made on QEMU :

(qemu) info mtree
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-0000000000001fff (prio 0, ram): ram0
    0000000000002000-0000000008001fff (prio 0, ram): dram0
    0000000008002000-0000000010001fff (prio 0, ram): alias dram1 @dram0 0000000000000000-0000000007ffffff
    0000000010002000-0000000018001fff (prio 0, ram): alias dram2 @dram0 0000000000000000-0000000007ffffff
    0000000018002000-0000000020001fff (prio 0, ram): alias dram3 @dram0 0000000000000000-0000000007ffffff
    00000000b0000200-00000000b00011ff (prio 0, i/o): npcm7xx-clk
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial
    00000000b8001000-00000000b8001fff (prio 0, i/o): npcm7xx-timer
    00000000b8001004-00000000b8002003 (prio 0, i/o): npcm7xx-timer
    00000000b8001020-00000000b800201f (prio 0, i/o): npcm7xx-timer
    00000000b8001024-00000000b8002023 (prio 0, i/o): npcm7xx-timer
    00000000b8001040-00000000b800203f (prio 0, i/o): npcm7xx-timer
    00000000c6000000-00000000c60003ff (prio 0, ram): ram1

address-space: I/O
  0000000000000000-000000000000ffff (prio 0, i/o): io

address-space: cpu-memory-0
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-0000000000001fff (prio 0, ram): ram0
    0000000000002000-0000000008001fff (prio 0, ram): dram0
    0000000008002000-0000000010001fff (prio 0, ram): alias dram1 @dram0 0000000000000000-0000000007ffffff
    0000000010002000-0000000018001fff (prio 0, ram): alias dram2 @dram0 0000000000000000-0000000007ffffff
    0000000018002000-0000000020001fff (prio 0, ram): alias dram3 @dram0 0000000000000000-0000000007ffffff
    00000000b0000200-00000000b00011ff (prio 0, i/o): npcm7xx-clk
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial
    00000000b8001000-00000000b8001fff (prio 0, i/o): npcm7xx-timer
    00000000b8001004-00000000b8002003 (prio 0, i/o): npcm7xx-timer
    00000000b8001020-00000000b800201f (prio 0, i/o): npcm7xx-timer
    00000000b8001024-00000000b8002023 (prio 0, i/o): npcm7xx-timer
    00000000b8001040-00000000b800203f (prio 0, i/o): npcm7xx-timer
    00000000c6000000-00000000c60003ff (prio 0, ram): ram1

memory-region: dram0
  0000000000002000-0000000008001fff (prio 0, ram): dram0

I have create this table, he is similar to info mtree

Physical address End address Size Name Type Description
0x00000000 0x0001ffff 0x2000 (8 KiB) RAM0 Internal RAM0
0x00002000 0x08001fff 0x8000000 (128 MiB) DRAM0 DRAM0
0x08002000 0x10001fff 0x8000000 (128 MiB) DRAM1 DRAM0 alias Symbolic link to 0x00002000 (Is mirrored from 0x00002000 if global memory is equal to 128 MiB)
0x10002000 0x18001fff 0x8000000 (128 MiB) DRAM2 DRAM0 alias Symbolic link to 0x00002000 (Is mirrored from 0x00002000 if global memory is equal to 128 MiB)
0x18002000 0x20001fff 0x8000000 (128 MiB) DRAM3 DRAM0 alias Symbolic link to 0x00002000 (Is mirrored from 0x00002000 if global memory is equal to 128 MiB)
0xc6000000 0xc60003ff 0x400 (1024 B) RAM1 Internal RAM1

Now i can reproduce your commands :

Press any key to avoid running the default boot script
_bootscript
Welcome to lolmon
> ww 2000 1 2 3 4 5 6 7 8 
> rw 2000 16
00002000: 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008
00002020: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> rw 08002000 16
08002000: 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008
08002020: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>  rw 0c002000 16
0c002000: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0c002020: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> rw 10002000 16
10002000: 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008
10002020: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> rw 20002000 16
20002000: 

IC meaning interrupt controller? In that case, no, it's not a standard part, it's specific to Winbond/Nuvoton. The wiki page (https://github.com/neuschaefer/wpcm450/wiki/Interrupts) lists the registers and has a few references that can hopefully help you understand the interrupt controller. If you have questions about any hardware (like the interrupt controller, for example), please ask, ideally in a new github issue for each specific hardware block.

Yes, i mean Iterrupt Controller (excuse me for my weird english). Ok thanks

Your question is missing a verb. To do what with U-Boot?

I want to test u-boot with QEMU and i want to known what is the mimimum requirements (UART, Timer, ...) for compile and test it ?

neuschaefer commented 3 years ago

(qemu) info mtree address-space: memory 0000000000000000-ffffffffffffffff (prio 0, i/o): system 0000000000000000-0000000000001fff (prio 0, ram): ram0 0000000000002000-0000000008001fff (prio 0, ram): dram0 0000000008002000-0000000010001fff (prio 0, ram): alias dram1 @dram0 0000000000000000-0000000007ffffff 0000000010002000-0000000018001fff (prio 0, ram): alias dram2 @dram0 0000000000000000-0000000007ffffff 0000000018002000-0000000020001fff (prio 0, ram): alias dram3 @dram0 0000000000000000-0000000007ffffff

Nice approach.

I'd argue that each DRAM mirror probably starts at a round address (00000000, 08000000, etc.), and that part of the first mirror is simply shadowed by the internal RAM; but the way you modeled it, it does seem to create (mostly) the correct behavior, so it's probably fine.

The part from 20000000 to 20001fff is wrong. Everything from 20000000 onward causes an error.

00000000b0000200-00000000b00011ff (prio 0, i/o): npcm7xx-clk

This overlaps with the memory controller (@ b0001000). Also, I haven't checked how similar and compatible the clock controllers of WPCM450 and NPCM7xx are. They might have incompatible register layouts.

00000000b8000000-00000000b800001f (prio 0, i/o): serial
00000000b8000100-00000000b800011f (prio 0, i/o): serial

Looks good!

00000000b8001000-00000000b8001fff (prio 0, i/o): npcm7xx-timer
00000000b8001004-00000000b8002003 (prio 0, i/o): npcm7xx-timer
00000000b8001020-00000000b800201f (prio 0, i/o): npcm7xx-timer
00000000b8001024-00000000b8002023 (prio 0, i/o): npcm7xx-timer
00000000b8001040-00000000b800203f (prio 0, i/o): npcm7xx-timer

Why does npcm7xx-timer have multiple ranges?

Now i can reproduice your behavior : [...]

rw 08002000 16 08002000: 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008

Great!

I want to test u-boot with QEMU and i want to known what is the mimimum requirements (UART, Timer, ...) for compile and test it ?

First of all, you have to select a version of U-Boot, because the upstream version does not support WPCM450. There are at least two versions provided by firmware vendors:

Both of these probably require a rather old toolchain (GCC, binutils, etc.).

There is currently no modern version of U-Boot for WPCM450.

StidOfficial commented 3 years ago

I'd argue that each DRAM mirror probably starts at a round address (00000000, 08000000, etc.), and that part of the first mirror is simply shadowed by the internal RAM; but the way you modeled it, it does seem to create (mostly) the correct behavior, so it's probably fine. The part from 20000000 to 20001fff is wrong. Everything from 20000000 onward causes an error.

Do you mean like below. It's means the RAM0 is never used, everything use directly DRAM0 ?

address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-0000000007ffffff (prio 0, ram): dram0
    0000000000000000-0000000000001fff (prio 0, ram): ram0
    0000000008000000-000000000fffffff (prio 0, ram): alias dram1 @dram0 0000000000000000-0000000007ffffff
    0000000010000000-0000000017ffffff (prio 0, ram): alias dram2 @dram0 0000000000000000-0000000007ffffff
    0000000018000000-000000001fffffff (prio 0, ram): alias dram3 @dram0 0000000000000000-0000000007ffffff
    00000000b0000200-00000000b00011ff (prio 0, i/o): npcm7xx-clk
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial
    00000000c6000000-00000000c60003ff (prio 0, ram): ram1

This overlaps with the memory controller (@ b0001000). Also, I haven't checked how similar and compatible the clock controllers of WPCM450 and NPCM7xx are. They might have incompatible register layouts.

If i have good understand, if (!wait_for_key(1000000)) {, us argument equal to microsecondes (µs) so he wait 1 seconde for key press. I have test with multiply this by 10 (10 secondes), i have calcule and he wait 10~ (with gnome-clocks). And the rst command work so i think at least for monitor the clock and timer looks good.

That the actual memory mapping :

address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-0000000007ffffff (prio 0, ram): dram0
    0000000000000000-0000000000001fff (prio 0, ram): ram0
    0000000008000000-000000000fffffff (prio 0, ram): alias dram1 @dram0 0000000000000000-0000000007ffffff
    0000000010000000-0000000017ffffff (prio 0, ram): alias dram2 @dram0 0000000000000000-0000000007ffffff
    0000000018000000-000000001fffffff (prio 0, ram): alias dram3 @dram0 0000000000000000-0000000007ffffff
    00000000b0000200-00000000b00011ff (prio 0, i/o): npcm7xx-clk
    00000000b8000000-00000000b800001f (prio 0, i/o): serial
    00000000b8000100-00000000b800011f (prio 0, i/o): serial
    00000000b8001000-00000000b8001fff (prio 0, i/o): npcm7xx-timer
    00000000c6000000-00000000c60003ff (prio 0, ram): ram1

First of all, you have to select a version of U-Boot, because the upstream version does not support WPCM450. There are at least two versions provided by firmware vendors: - AMI (https://github.com/neuschaefer/u-boot/tree/vendor/wpcm450-ami) - Dell (https://github.com/neuschaefer/u-boot/tree/vendor/dell-idrac6-1.70) Both of these probably require a rather old toolchain (GCC, binutils, etc.). There is currently no modern version of U-Boot for WPCM450.

Ok i going to try first with u-boot. I use currently use the cross compile arm-none-eabi- given with fedora. I have also the cross compiler given by dell for irac6 if is needed.

neuschaefer commented 3 years ago

Do you mean like below. It's means the RAM0 is never used, everything for inside DRAM0 ?


address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000000000-0000000007ffffff (prio 0, ram): dram0
    0000000000000000-0000000000001fff (prio 0, ram): ram0
    0000000008000000-000000000fffffff (prio 0, ram): alias dram1 @dram0 0000000000000000-0000000007ffffff
    0000000010000000-0000000017ffffff (prio 0, ram): alias dram2 @dram0 0000000000000000-0000000007ffffff
    0000000018000000-000000001fffffff (prio 0, ram): alias dram3 @dram0 0000000000000000-0000000007ffffff

This looks good, but I'm not sure how QEMU handles the overlap. The desired result is that ram0 is used in the overlapping area. I guess you can influence which memory is preferred by changing the priority ("prio" value).

If i have good understand, if (!wait_for_key(1000000)) { us equal to microsecondes (µs) so he wait 1 seconde for key press.

Yes, the parameter is in microseconds.

I have test with multiply this by 10 (10 secondes), i have calcule and he wait 10~ (with gnome-clocks). And the rst command work so i think at least for monitor the clock and timer looks good.

Very good!

StidOfficial commented 2 years ago

I have disable lot of code (SPI, GPIO and SMC) but we hare close for u-boot.

U-Boot 1.2.0-gbacd4830-dirty (Sep  8 2021 - 18:22:29) Avocent (1.13.7) Whoville

Board: WPCM450_00
DRAM:  128 MB
Flash:  0 kB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   No ethernet found.
Hit any key to stop autoboot:  0 
[uboot_wpcm450]# 
StidOfficial commented 1 year ago

@neuschaefer Do you check https://datasheetspdf.com/pdf-file/1134405/nuvoton/NUC960ADN/1 beacause there are very similar registers, base addresses, ... ?

neuschaefer commented 1 year ago

@StidOfficial thanks for the link! :)