Help Re. Recommended Linux Distribution for libcamera Development for i.MX8
w.robertson at cairnwater.com
w.robertson at cairnwater.com
Sun Jan 19 21:20:41 CET 2025
Hi Laurent,
Thank you very much!
Would it be a help for me to typeset your explanation into HTML for the
https://libcamera.org/ website so that it could help others? It's much
clearer and much more up-to-date than many of the explanations that are
floating around and an enormous help to someone like me from an
application development background with little embedded experience.
> I've attached my configuration file
> for builroot 2024.11.1 to this e-mail, you can use it as a starting
> point.
Thank you very much. I think the attachment got stripped from the email
- would it be OK to send it again? It might be my email system - sorry
about that.
> While
> many vendors provide their own Linux distributions, BSPs and SDKs and
> market them as easy to use, turnkey options, I adhere to the (old ?)
> school of thoughts that believes understanding what goes behind the
> scenes is important. You can then make a fully informed decision on
> which components to pick and how much manual control and customization
> you need.
Yes - I've often seen technologies which aim to allow developers to work
without understanding what's going on behind the scenes
seem-like-a-good-idea-at-the-time but sneak up to bite their victims on
the backside later on in terms of unforeseen problems or unforeseen
costs.
It's also very important for something like a wildlife camera where what
is and isn't loaded at boot time may have to be carefully controlled.
The most common boot loader for Arm-based embedded Linux systems
> is U-Boot. It's a well established de facto standard in the industry,
> and is what NXP uses for the i.MX8MP. Alternatives exist, but I really
> wouldn't recommend them if you're not already experienced with embedded
> Linux systems.
Thank you very much - that's an enormous help to know that U-Boot is the
de facto standard and used by NXP.
> Arm has standardized the ARMv8 secure boot flow and split it in
> multiple
> stages, named BL1 (the boot ROM in the SoC, the only component that
> can't be updated), BL2 (second stage boot loader, implemented by U-Boot
> and named SPL), BL31 (trusted firmware, a reference implementation made
> by Arm is available at [1]), and BL33 (the last boot loader stage,
> known
> as untrusted boot loader, and implemented by U-Boot proper). There's
> plenty of information online that describes the boot process, for
> instance [2].
>
> The boot loader is responsible for initializing all low-level hardware
> required to load the kernel (system DRAM, permanent storage such as
> eMMC or SD cards, ...). It then loads the kernel, and passes execution
> to it. Parts of the boot loader can remain persistent in system DRAM
> after loading the kernel, and offer runtime services to the kernel
> (control of power domains, secure operations such as access to crypto
> engines, ...).
>
> [1] https://github.com/TrustedFirmware-A/trusted-firmware-a
> [2] https://www.youtube.com/watch?v=GXFw8SV-51g
Thank you very much - that's very good to know how the steps fit
together to finally pass control to the kernel.
> # Device tree
>
> Unlike PCI or USB devices that can be auto-detected at runtime, most
> devices inside the SoC, or connected through non-discoverable buses
> such
> as I2C or SPI, need to be declared to the kernel. The majority of Arm
> systems use Device Tree for that purpose.
>
> The device tree specification ([3]) defines a textual source format and
> a compiled binary format. Device tree bindings then define (as YAML
> schemas) how each particular device is described. The bindings
> maintained as part of the Linux kernel sources ([4]). Finally, as large
> set of device tree sources describing various boards is available in
> the
> kernel source tree as well ([5]). Vendors can also maintain their
> device
> trees outside of the kernel repository.
>
> Device trees are compiled to a binary DTB file and stored in media
> accessible by the boot loader. They are loaded by the boot loader as
> part of the boot process, and passed to the Linux kernel when starting
> it.
>
> [3] https://www.devicetree.org/
> [4]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings
> [5]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/
>
Thank you very much. It's a big help to know that some vendors maintain
their DTs outside of the kernel source - I'd been thinking that if all
possible DTs were included in the kernel repository itself it would
become very large.
It's also a big help to me to understand that DTs have to be available
to the boot loader as well as to the kernel.
> # Linux kernel
>
> The kernel is responsible for controlling the hardware and providing
> services to userspace. While there is only one Linux kernel, SoC and
> board vendor typically fork it to add a set of modifications, from
> changes in the kernel core to additional device drivers. This set can
> be
> as small as a handful of patches or as big as millions of lines,
> depending on the vendor. Vendor kernels are often referred to as BSP
> (Board Support Package) kernels.
>
> After being loaded in system DRAM by the boot loader, the kernel gets
> executed and goes through a fairly long initialization phase. Once the
> initialization is complete, the kernel mounts the root file system,
> loads the init binary, and executes it.
Thank you. Is there usually any easy way to see all the steps that a
vendor has doen to modify the SoC vendor's kernel or the steps the SoC
vendor has doen to modify the original kernel? (Or just do a diff
between a vendor's kernel and the original?)
I get the feeling that a lot of the Debix Linux distributions and Yocto
build are based on the NXP distributions and Yocto and I was interested
in seeing what the differences were.
I guess the more modification there is in a vendor's kernel the more
risk there is that a developer may become tied to their SoM or their SoC
so it's good for a developer to have a feel for this rather than going
into it blindly?
> # Distributions and build frameworks
>
> Linux distributions typically provide all those components in the form
> of an installable image. Depending on the type of distribution, you can
> download a ready-made binary image, or you may need to build one. My
> experience is that ready-made images, provided by distributions
> originating from desktop systems (Debian, Ubuntu, Fedora, ...) may be
> simpler to install, but more difficult to customize. I'm certainly
> biased though, I'm quite sure that someone more familiar with Debian or
> Fedora development would have less trouble compiling a custom kernel
> using the packaging infrastructure provided by those distributions. As
> I'm not such a person, I'll describe alternatives.
>
> In addition to ready-made images, there are build automation frameworks
> that help you build a system image and a corresponding
> cross-compilation
> environment (often referred to as SDK). Two common frameworks are
> buildroot and OpenEmbedded (often referred to as Yocto, although that's
> a misuse of the term). I'm more familiar with buildroot, and that's
> what
> I use with my Debix board, so I will focus on that framework.
>
> Buildroot facilitates the process of building a complete set of
> cross-compilation tools, as well as a root file system, from source. It
> supports thousands of packages and can build the boot loader, Linux
> kernel and root file system image. Building a system image with
> buildroot only requires a few simple steps:
>
> - Cloning the builroot repository
> - Running `make menuconfig` to select configuration options
> - Running `make` to build the image
>
> Deciding which of the thousand packages to select in the configuration
> is difficult if you lack experience. I've attached my configuration
> file
> for builroot 2024.11.1 to this e-mail, you can use it as a starting
> point.
Thank you very much. I think building on an SDK on a more powerful
machine makes a lot more sense than my attempts to do it natively. I
don't have experience of building machines beyond shell scripts to build
Docker containers so I'll start with buildroot.
It's very helpful for me to understand the similarities between
buildroot, OpenEmbedded and Yocto - these terms often get thrown around
without an explanation.
> # Boot flow and system images
>
> Linux is very versatile when it comes to booting a system. Most
> embedded
> boards come with instructions for flashing a system image on an SD
> card,
> and storing all the components (boot loader, device tree, kernel and
> root file system) on the card. Buildroot can create images compatible
> with that boot flow, and that is possibly a good first step to get
> started. However, that's not the boot flow I use.
>
> I find copying files to an SD card every time I make modifications to
> the kernel to be cumbersome and error-prone. Instead, a common kernel
> and userspace development workflow relies on the following boot flow:
>
> - The boot ROM loads the boot loader from storage media (SD card or
> eMMC)
> - The boot loader acquires an IP address through DHCP, and loads the
> device tree and kernel over the network through TFTP
> - The kernel mounts the root file system over the network through NFS
>
> With this workflow, all components but the boot loader are loaded over
> the network. To make modifications to the device tree, kernel, or any
> userspace component (including libcamera), I can cross-compile them on
> my development machine, and copy them to the TFTP root directory (for
> the device tree or kernel) or the NFS root directory (for kernel
> modules
> and any userspace component). New userspace components will be
> immediately available on the target device, and running a new kernel
> only requires a reboot.
>
> My buildroot configuration is tailored for that workflow, and only
> produces a root file system as a tarball, without building a full
> system
> image. It should be possible to use buildroot to build a full system
> image for the Debix Model A board, but I don't believe anyone has
> contributed the default configuration files, so there would be a bit of
> work to do.
I can see that's more efficient for continuous integration than using SD
cards.
> # Picking the right U-Boot version
>
> Vendors often don't upstream support for their boards in U-Boot. I
> believe that the Debix Model A board is well supported in U-Boot
> 2024.10, which is the version used by buildroot 2024.11.1, but I
> haven't
> tested that. I have instead compiled U-Boot manually as I needed to
> make
> changes to its configuration to suit my environment.
I thought I'd found Debix's source for U-Boot:
https://github.com/debix-tech/uboot
but the last commit was 3 years ago so maybe it's somewhere else.
> Recompiling the boot loader manually can be cumbersome. An easy option
> may be to flash the system image provided by Polyhex for the Debix
> Model
> A on an SD card to provide the boot loader, and then replacing the
> kernel and root file system.
That does sound a good way for me to get started - am I right in
thinking that Debix describe that process here?:
https://www.debix.io/Software/blog_info/id/59.html
> That's lots of information, but I'm sure there are still be lots of
> gaps
> you'll have to fill. I'm also pretty sure it would be possible to take
> a
> general purpose Linux distribution such as Fedora or Ubuntu and run it
> on the Debix board, and replace custom components, but I can't help you
> with that as that's not what I do. You will need to experiment and
> gather information, slowly learning how the pieces fit together.
I think I might try to do one very slimmed-down Linux distribution with
the minimum functionality needed to run the MIPI CSI-2 interface, ISP
and SD card which consumes minimal resources, can boot fast, can waken
from sleep state fast and can monitor wildlife but not much else and
another separate much larger and a much more resource intensive general
purpose distribution (including web server, Samba, Wi-Fi connection,
etc.) that's booted when someone wants to interact with the system. I've
never doen this before but hoping the U-Boot might allow the
distribution to be chosen at boot time depending on a simple digital
electronic input - not sure.
It is an enormous jigsaw puzzle...
Thank you very much for all your help!
Will
On 2025-01-19 16:26, Laurent Pinchart wrote:
> Hi Will,
>
> On Sat, Jan 18, 2025 at 12:48:29PM +0000, w.robertson at cairnwater.com
> wrote:
>> Hi all,
>>
>> Any advice you could give on getting started using libcamera on the
>> Debix Model A would be wonderful. With fresh Ubuntu Desktop 24.10 and
>> Raspberry Pi OS images written to an SD card (Using the RPi imager)
>> the
>> Debix Model A won't start to boot and with the Debix Ubuntu
>> distribution
>> it boots but I get an error when I try to install the dependencies
>> needed to rebuild the kernel.
>>
>> My Debix Model A doesn't have the 2 switches to select boot source so
>> I
>> think it boots from SD only and doesn't have on-board eMMC
>>
>> I suspect from the NXP i.MX documentation that with vanilla Ubuntu I'm
>> missing the BSP but I'm not sure.
>>
>> I've been trying to follow libcamera Getting Started but it doesn't
>> say
>> which distribution is used:
>>
>> https://libcamera.org/getting-started.html
>>
>> I'd be enormously grateful for any advice.
>
> OK. Brace yourself, because it will be a bit of a ride, but it's an
> interesting one.
>
> There are multiple options (it would be too easy otherwise), and which
> one is best depends on your use cases and personal preferences. While
> many vendors provide their own Linux distributions, BSPs and SDKs and
> market them as easy to use, turnkey options, I adhere to the (old ?)
> school of thoughts that believes understanding what goes behind the
> scenes is important. You can then make a fully informed decision on
> which components to pick and how much manual control and customization
> you need.
>
> Very roughly speaking, an Arm Linux system needs four major components:
>
> - A boot loader
> - A device tree (for systems that are device-tree based)
> - A kernel
> - A root file system
>
> # Boot loader
>
> The boot loader here is a blanket term that comprises all the software
> components that run from power up to handing control over to the Linux
> kernel. The most common boot loader for Arm-based embedded Linux
> systems
> is U-Boot. It's a well established de facto standard in the industry,
> and is what NXP uses for the i.MX8MP. Alternatives exist, but I really
> wouldn't recommend them if you're not already experienced with embedded
> Linux systems.
>
> Arm has standardized the ARMv8 secure boot flow and split it in
> multiple
> stages, named BL1 (the boot ROM in the SoC, the only component that
> can't be updated), BL2 (second stage boot loader, implemented by U-Boot
> and named SPL), BL31 (trusted firmware, a reference implementation made
> by Arm is available at [1]), and BL33 (the last boot loader stage,
> known
> as untrusted boot loader, and implemented by U-Boot proper). There's
> plenty of information online that describes the boot process, for
> instance [2].
>
> The boot loader is responsible for initializing all low-level hardware
> required to load the kernel (system DRAM, permanent storage such as
> eMMC or SD cards, ...). It then loads the kernel, and passes execution
> to it. Parts of the boot loader can remain persistent in system DRAM
> after loading the kernel, and offer runtime services to the kernel
> (control of power domains, secure operations such as access to crypto
> engines, ...).
>
> [1] https://github.com/TrustedFirmware-A/trusted-firmware-a
> [2] https://www.youtube.com/watch?v=GXFw8SV-51g
>
> # Device tree
>
> Unlike PCI or USB devices that can be auto-detected at runtime, most
> devices inside the SoC, or connected through non-discoverable buses
> such
> as I2C or SPI, need to be declared to the kernel. The majority of Arm
> systems use Device Tree for that purpose.
>
> The device tree specification ([3]) defines a textual source format and
> a compiled binary format. Device tree bindings then define (as YAML
> schemas) how each particular device is described. The bindings
> maintained as part of the Linux kernel sources ([4]). Finally, as large
> set of device tree sources describing various boards is available in
> the
> kernel source tree as well ([5]). Vendors can also maintain their
> device
> trees outside of the kernel repository.
>
> Device trees are compiled to a binary DTB file and stored in media
> accessible by the boot loader. They are loaded by the boot loader as
> part of the boot process, and passed to the Linux kernel when starting
> it.
>
> [3] https://www.devicetree.org/
> [4]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings
> [5]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/
>
> # Linux kernel
>
> The kernel is responsible for controlling the hardware and providing
> services to userspace. While there is only one Linux kernel, SoC and
> board vendor typically fork it to add a set of modifications, from
> changes in the kernel core to additional device drivers. This set can
> be
> as small as a handful of patches or as big as millions of lines,
> depending on the vendor. Vendor kernels are often referred to as BSP
> (Board Support Package) kernels.
>
> After being loaded in system DRAM by the boot loader, the kernel gets
> executed and goes through a fairly long initialization phase. Once the
> initialization is complete, the kernel mounts the root file system,
> loads the init binary, and executes it.
>
> # Root file system
>
> The root file system contains all the userspace components of a Linux
> system. Linux supports a large number of storage media and file system
> types, including SD cards, eMMCs, SATA or NVMe drives, or accessing the
> root file system over the network.
>
> # Distributions and build frameworks
>
> Linux distributions typically provide all those components in the form
> of an installable image. Depending on the type of distribution, you can
> download a ready-made binary image, or you may need to build one. My
> experience is that ready-made images, provided by distributions
> originating from desktop systems (Debian, Ubuntu, Fedora, ...) may be
> simpler to install, but more difficult to customize. I'm certainly
> biased though, I'm quite sure that someone more familiar with Debian or
> Fedora development would have less trouble compiling a custom kernel
> using the packaging infrastructure provided by those distributions. As
> I'm not such a person, I'll describe alternatives.
>
> In addition to ready-made images, there are build automation frameworks
> that help you build a system image and a corresponding
> cross-compilation
> environment (often referred to as SDK). Two common frameworks are
> buildroot and OpenEmbedded (often referred to as Yocto, although that's
> a misuse of the term). I'm more familiar with buildroot, and that's
> what
> I use with my Debix board, so I will focus on that framework.
>
> Buildroot facilitates the process of building a complete set of
> cross-compilation tools, as well as a root file system, from source. It
> supports thousands of packages and can build the boot loader, Linux
> kernel and root file system image. Building a system image with
> buildroot only requires a few simple steps:
>
> - Cloning the builroot repository
> - Running `make menuconfig` to select configuration options
> - Running `make` to build the image
>
> Deciding which of the thousand packages to select in the configuration
> is difficult if you lack experience. I've attached my configuration
> file
> for builroot 2024.11.1 to this e-mail, you can use it as a starting
> point.
>
> # Boot flow and system images
>
> Linux is very versatile when it comes to booting a system. Most
> embedded
> boards come with instructions for flashing a system image on an SD
> card,
> and storing all the components (boot loader, device tree, kernel and
> root file system) on the card. Buildroot can create images compatible
> with that boot flow, and that is possibly a good first step to get
> started. However, that's not the boot flow I use.
>
> I find copying files to an SD card every time I make modifications to
> the kernel to be cumbersome and error-prone. Instead, a common kernel
> and userspace development workflow relies on the following boot flow:
>
> - The boot ROM loads the boot loader from storage media (SD card or
> eMMC)
> - The boot loader acquires an IP address through DHCP, and loads the
> device tree and kernel over the network through TFTP
> - The kernel mounts the root file system over the network through NFS
>
> With this workflow, all components but the boot loader are loaded over
> the network. To make modifications to the device tree, kernel, or any
> userspace component (including libcamera), I can cross-compile them on
> my development machine, and copy them to the TFTP root directory (for
> the device tree or kernel) or the NFS root directory (for kernel
> modules
> and any userspace component). New userspace components will be
> immediately available on the target device, and running a new kernel
> only requires a reboot.
>
> My buildroot configuration is tailored for that workflow, and only
> produces a root file system as a tarball, without building a full
> system
> image. It should be possible to use buildroot to build a full system
> image for the Debix Model A board, but I don't believe anyone has
> contributed the default configuration files, so there would be a bit of
> work to do.
>
> # Picking the right U-Boot version
>
> Vendors often don't upstream support for their boards in U-Boot. I
> believe that the Debix Model A board is well supported in U-Boot
> 2024.10, which is the version used by buildroot 2024.11.1, but I
> haven't
> tested that. I have instead compiled U-Boot manually as I needed to
> make
> changes to its configuration to suit my environment.
>
> Recompiling the boot loader manually can be cumbersome. An easy option
> may be to flash the system image provided by Polyhex for the Debix
> Model
> A on an SD card to provide the boot loader, and then replacing the
> kernel and root file system.
>
>
> That's lots of information, but I'm sure there are still be lots of
> gaps
> you'll have to fill. I'm also pretty sure it would be possible to take
> a
> general purpose Linux distribution such as Fedora or Ubuntu and run it
> on the Debix board, and replace custom components, but I can't help you
> with that as that's not what I do. You will need to experiment and
> gather information, slowly learning how the pieces fit together.
>
>> On 2025-01-17 21:02, w.robertson at cairnwater.com wrote:
>> > Hi
>> >
>> > Which Linux distribution is recommended for libcamera development using
>> > the Debix Model A (NXP i.MX 8M) board?
>> >
>> > I've been trying using the Debix Model A Ubuntu distribution (Ubuntu
>> > 22.04) from https://debix.io/Software/downloadn.html but running into
>> > problems when I try to do a kernel rebuild using the procedure here
>> > https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel and was wondering if
>> > I'd be better using vanilla Ubuntu or Debian?
>> >
>> > Thank you for your help!
More information about the libcamera-devel
mailing list