qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Teensy 4.1 Implementation


From: Shiny Saana
Subject: Re: Teensy 4.1 Implementation
Date: Tue, 23 Aug 2022 16:00:17 +0200

Thank you again for your time!

I didn't know at all about the generic loader!! It feels to me that it will definitely be very useful in loading the Teensy image.

(To give more background: the Teensy-Arduinon toolchain first compiles an .elf and then convert that to an Intex hex file. We can retrieve that .elf in /tmp after compilation, but if all you have is an ihex (which is the case for my use-case), then you're out of luck.)

To answer your question:

> Do you know what the hardware sets the initial vector 
> base address to? (that is, where the ROM itself puts its
> reset/interrupt vector table). I couldn't find anything in
> the datasheet that said that.

From experimentation and dissasembly on the ROM, (located in 0x0020_0000), the very first int (converted to BE) is "0x2020_1000" , which is located to "OCRAM2", also referred as "ROM RAM" by the documentation, and the next int is "0x0020_2091", which both points inside the ROM itself , and which when forcibly disassembled in Ghidra does look like a function.
So I'm pretty confident the initial vector base address is 0x0020_0000.

Regarding the "kernel loading" issue, I believe that I was initially mistaken. From other examples online, I believed that it was the way to load the Teensy image. But thinking and discussing it with another ARM dev, wouldn't the ROM itself actually be considered the kernel? 

The teensy ihex image (converted to raw binary) could then be loaded via the generic loader (and then, document that behavior in QEMU, and for user convenience, in my own program using QEMU, I could merely provide a script that handles the arguments for them).

Knowing that, if the call to  armv7m_load_kernel() is mandatory, maybe it would make sense to load the ROM in C code via this function, with the compiled ROM addresses from 0x0000_0000 to 0x001F_FFFF being padded with 0.
I'm *absolutely not sure* if this is a good idea, but that's the one I got from the understanding that I have. 

As always, thank you again for the help (and for using some of your time to go through the documentation yourself, I genuinely appreciate the help a great lot.)

Saana

Le mar. 23 août 2022 à 15:09, Peter Maydell <peter.maydell@linaro.org> a écrit :
On Sun, 21 Aug 2022 at 01:05, Shiny Saana <shinysaana@gmail.com> wrote:
> I've been able to write an initial Teensy 4.1 machine, for now with
> only the few important memory regions initialized, and successfully
> ran some hand-written ARM code on it.

Great, that's good progress!

> The documentation ( https://www.pjrc.com/teensy/IMXRT1060RM_rev3.pdf ),
> in section 9.7.1, gives some informations on how, in the actual
> Teensy board, the ROM, executed at boot, initialize the board
> peripherals, and also reads from a data structure included in the
> Flash memory (the user-provided program) where the CPU should jump
> to after the ROM has done its work (somewhere in that same Flash memory,
> usually).
>
> I was able to successfully dump the ROM of the real board and
> confirm this behavior. Given that the current plan is not to
> emulate every peripherals, I am of the opinion that writing a very
> simple ROM that merely reads this Flash provided data structure and
> jumps to the provided address sounds like a good starting point, so
> that I can keep iterating on writing more and more complex code
> through the provided Teensy toolchain, and implementing needed
> peripherals.
>
> As such, I have several questions:
>
> 1/ To replicate this behaviour, is this considered the correct
> approach by the current QEMU maintainers?

Yes, I think this is probably a reasonable way to go.

> 2/ If so, I have not been able to find any function that would be
> able to load data into a memory region "statically". Does one
> exist? Is there an alternative to this process?

Depends exactly what you want to do. If you want "let the user
load data to an arbitrary address", then the "generic loader"
is usually helpful:
https://www.qemu.org/docs/master/system/generic-loader.html

If you mean "C code within QEMU loads data to a specific place",
rom_add_blob_fixed_as() is probably what you want. This is how
hw/arm/boot.c loads both user-provided data files and the
hand-coded mini-bootloader into the guest.

> 3/ Regarding loading the "kernel" of the board, as part of the
> init process, I am calling the usual "armv7m_load_kernel" function
> with its usual parameters. However, it seems to load it as the
> very start of the address space, which is not where the flash
> memory is, and so is not where the kernel should be loaded. I
> wasn't able to find a workaround. Is there something I'm missing?

The behaviour of armv7m_load_kernel() depends on what kind
of file you pass to -kernel. If you pass -kernel an ELF file,
then it will get loaded to the addresses as specified by
the ELF file, so you can use that to put data anywhere you like.
If you pass it a raw binary file then, yeah, at the moment
that gets loaded to address 0. There's no real reason for this
limitation -- it's mainly because when that code was written
we supported very few M-profile boards, and all of them booted
from address 0. (That is, the board doesn't set either the
init-svtor or init-nsvtor properties on the armv7m object to
anything other than 0.) We could change how this works, but
the difficulty is that the desire for "Just Do What I Mean"
behaviour for a specific board tends to conflict with the
desire for all boards to behave in a consistent manner.
In particular, at the moment passing a binary file to -kernel
means "I want this to be loaded so that it has the
CPU vector table in it and execution starts from reset as
the architecture says it should"; it can't both mean that
consistently across M-profile boards and also mean "on the
teeny board, be an image file intended to boot via the ROM
loader".

Loading the teeny images via the generic loader rather than
via -kernel would be one way to sidestep this issue...



(By the way, calling armv7m_load_kernel() is mandatory even if
you don't care about loading an image, because it's the function
that arranges that the CPU gets reset correctly.)

thanks
-- PMM

reply via email to

[Prev in Thread] Current Thread [Next in Thread]