Beaglebone Black: Interaction between Device Tree and Kernel Module - linux-kernel

I am currently developing a SPI Kernel Module for my Beaglebone Black (Debian Wheezy 2015-11-12, Kernel version 3.8.13-bone79). My kernel module can access (request_mem_region() => ioremap()) registers from the AM3358 processor (read/write) to manipulate the registers, to change the settings of the SPI0.
On the other side is my device tree, which can manipulate the pins of the SPI0.
Unfortunately, I´ve got Problems:
If I load my Device Tree first, and then my Kernel Module I get an message that I haven´t got permission to load my kernel module.
If I load my Module first and then my Device tree, all pinmuxes are allright, but the CLK of SPI0 is killed. Furthermore if I remove my module and free my allocated Memory (Registers, iounmap() => release_mem_region()) I get a 'Trying to free nonexistent resource' message.
You see, I am struggeling to understand the interaction between Device Tree and Kernel Module...
I would be extremely grateful, if someone could "push" me in the right direction... ;)
All the best
Flo

Related

Flashing ESP32's memory without installing the whole IDF?

Problem
I'm looking for a way to flash an ESP32 module's memory without installing the whole IDF software suite.
Why
Because I want to integrate ESP32 onto a custom board along with a low-performance ARM-powered CPU which runs a tiny Linux distro (based on Debian), and I want to flash ESP32 from this tiny Linux distro.
I know I could use the bootloader, but who will upload the initial bootloader? I don't want to do extra steps, so my idea is to embed the ESP32 module onto my custom board, and let the Linux to flash it from factory-state (when it's flash is empty, ie. no preloaded bootloader). Or is the serial bootloader always preinstalled on all ESP32 modules (like on ESP-WROOM-32)?
Why I don't want to use IDF? Because I don't want to build or debug anything, I just want to flash myprogram.bin onto ESP32. Also, as the board is low-performance, it would take ages to download everything for running IDF.
Current state
The ESP32 module is now visible via UART (RX,TX,GND), and if I held low the GPIO0, it runs the bootloader (my current module is embedded onto a NodeMCU - but there is no USB connected, this is raw UART!):
rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2))
waiting for download
Could I expect the same behavior (controlling GPIO0 for running the bootloader) for all ESP32 modules, or this works just because guys at NodeMCU preprogrammed already some bootloader onto it?
I'm looking for a way to flash this ESP32 preferrably without any python script.
The ESP32 has a first-stage bootloader in ROM capable of writing to Flash - that's what's printing your output. You can talk to it if you know the protocol - this is implemented by the Python scripts in ESP IDF. If you don't want to use the official implementation because it's too heavy, you'll have to write your own implementation of this protocol which scratches your specific itch. Fortunately it's more or less documented and you can likely reverse engineer any missing knowledge from official Python scripts.
Actually Espressif also provides a nice and small binary for flashing ESPs:
https://github.com/espressif/esp-serial-flasher
Serial flasher component provides portable library for flashing Espressif SoCs (ESP32, ESP32-S2, ESP8266) from other host microcontroller. Espressif SoCs are normally programmed via serial interface (UART). Port layer for given host microcontroller has to be implemented, if not available.
One more (but very important) addition:
You have to modify this repo to make it work correctly, and also you might have to upload not just your binary, but also bootloader and partition_table.

External xilinx PCie driver with Yocto

I compiled the xilinx pcie driver using this as a starting point.
https://www.yoctoproject.org/docs/current/kernel-dev/kernel-dev.html#incorporating-out-of-tree-modules
and then instead of using this to the prebuilt image:
MACHINE_EXTRA_RRECOMMENDS += "kernel-module-mymodule"
I copy kernel file .ko directly to the image as:
fs#fs:/opt/PHYTEC_BSPs/yocto_imx7/build/tmp/work/cortexa7hf-neon-poky-linux-gnueabi/met/0.1-r0$ scp xpcie.ko root#172.17.100.101:/lib/modules
then when I insert this kernel module with hardware connected:
root#imx7d-phyboard-zeta-001:/lib/modules# insmod /lib/modules/xpcie.ko
Base hw val 0
Base hw len 0
BAR0 of 0K
BAR0 of 0M
xpcie: Init: Could not remap memory.
insmod: ERROR: could not insert module /lib/modules/xpcie.ko: Operation
not permitted
root#imx7d-phyboard-zeta-001:/lib/modules#
What is the reason?
Is it not allowed to copy kernel directly on already built image like this?
Futhermore when I add it to the image as in local.conf file:
MACHINE_EXTRA_RRECOMMENDS += "kernel-module-mymodule"
again built and load the image, it is not available in /lib/modules/ directory. Where i can find it? or using other 3 methods will be better?
Using insmod to install the driver is the right thing to do. It does not seem to be the cause of the problem you are seeing.
When you build the driver, the .ko file will usually be in the source directory where you built it, unless you make modules_install.
Getting back to the actual problem:
Looking at the driver source, the message "Could not remap memory" indicates that the driver could not map the PCIE memory region into the kernel address space.
Looks like the base address registers were not configured. On all the machines I use, the BIOS has to configure the base address registers before Linux can use the device.
We program the FPGA, reboot the machine, and then load the driver and use the FPGA. Did you try this? Does your FPGA show up with lspci?
Once the FPGA is programmed, if the PCIE configuration does not change you can tell the kernel to rescan and it will write the base address registers with the same values.

Embedded Linux Newbie Questions

So I am on the quest of learning embedded Linux and have a few questions that I cannot seem to find an answer for.
1) Does the kernel depend on the dtb/dts files when compiling? I thought that the kernel only needs to know the chip architecture (i.e. arm) and the dtb file is loaded by the boot loader (uBoot) so therefore the kernel only needs to load its drivers which are configured by the dtb file.
2) Mixing and matching: I'm under the impression that I can mix and match any combination of boot loader, dtb, kernel, rootfs, and modules given the following
kernel: must know which chip it is compiled for
dtb: must know the board details and chip, i.e. how much ram, configure a GPIO for SPI
boot loader: must know the chip and uEnv.txt must have params for the kernel and dtb location
rootfs: completely independent
modules: must be compiled with the specific version of kernel
3) Drivers: If I want to load a SPI driver do I need anything specific or will the kernel know how to operate this because the dtb file setup the required registers?
4) Modules: Are these just dependent on the kernel or do they need to know something about the chip and board (when I say chip what I mean is do they have to know more than a simple arm or x86 architecture)?
Thank you in advance, I know these are some basic questions but any help is appreciated.
1) Does the kernel depend on the dtb/dts files when compiling? I thought that the kernel only needs to know the chip architecture (i.e. arm) and the dtb file is loaded by the boot loader (uBoot [sic]) so therefore the kernel only needs to load its drivers which are configured by the dtb file.
The Linux kernel is compiled without any dependency on the Device Tree.
The compilation of the kernel does depend on the chip architecture, but which code modules that are compiled depends on the board configuration(s) and feature selection.
BTW it's U-Boot for Universal Boot, not microBoot.
2) Mixing and matching: I'm under the impression that I can mix and match any combination of boot loader, dtb, kernel, rootfs, and modules given the following
kernel: must know which chip it is compiled for
dtb: must know the board details and chip, i.e. how much ram, configure a GPIO for SPI
boot loader: must know the chip and uEnv.txt must have params for the kernel and dtb location
rootfs: completely independent
modules: must be compiled with the specific version of kernel
Essentially correct, but typically one doesn't go overboard in trying to "mix-n-match". There are often optimal or preferred (or at least appropriate) choices.
By "rootfs" I'm assuming you mean type of filesystem for the rootfs, rather some image of a rootfs. (See Addendum below.)
3) Drivers: If I want to load a SPI driver do I need anything specific or
There are two types of "SPI driver", the master and protocol.
The SPI master driver is for the SPI controller chip that serves as the one interface master. This is usually a platform driver and not have a device node in /dev.
For each SPI slave device there must be a protocol driver. This driver will typically have a device node in /dev.
will the kernel know how to operate this because the dtb file setup the required registers?
The Device Tree must specify which driver is for which device and any/all resources allocated/assigned to each device.
The dtb file does not "setup" anything. It's only configuration data; there is no executable code. A device driver, typically during its probe or initialization phase, is responsible for acquiring/allocating its resources.
4) Modules: Are these just dependent on the kernel or do they need to know something about the chip and board?
Your use of "modules" is ambiguous. Source code files are sometimes referred to as "modules". Presumably you really mean loadable kernel modules.
Although most people associate kernel modules (only) with device drivers, other kernel services such as filesystems and network protocol handlers can also be built as modules.
The primary rationale for a kernel module versus static linkage (i.e. built in the kernel) is for runtime configurability (which in turn improves memory efficiency). Optional features, services and drivers can be left out of the kernel that is booted, but can still be loaded later when needed.
Loadable modules are "dependent" on the kernel simply because of linking requirements for proper execution. The degree of "chip and board knowledge" obviously depends on the functionality of the module, just like any other piece of kernel code.
Addendum
when I say rootfs I am referring to a prebuilt rootfs
A kernel image and (prebuilt) rootfs image are not "completely independent".
The executable binaries and the shared libraries in the rootfs image must be compatible with the kernel features. More significantly, since kernel loadable modules are installed in the rootfs and not with the kernel image, and these modules can be strictly tied to a specific build of a kernel version, it makes sense to pair a kernel image with a rootfs image.

Linux kernel modules

I've not clear what is the difference between drivers that can be "embedded" inside a monolithic kernel and drivers available only as external modules.
What kind of effort is requested to "port" some driver (provided as "external module" only) to a monolithic kernel?
I would like to be able to run Vmware Tools disabling loadable modules support and getting rid of the initrd bazaar.
Though the driver more or less remains the same(in both cases),there are definitely benefits for using "drivers" embedded in monolithic kernel.
I'll try to explain the "effort in porting" the driver part which you've asked.
Depending on the kind of driver you've, essentially you've to figure out how it will fit in the current kernel source tree, its compilation(include your .ko in the uImage) and loading of it while kernel booting. Let's illustrate each step a bit:
a.) Locate the folder (in the kernel source tree) where you think it is best suited to keep your driver code.
b.) Work on to make sure your driver code is getting compiled.[i.e ultimately it will be part of monolithic kernel image(uImage or whatever you call it)]. In this context, You've to work on your Makefile for your driver. You might have to introduce some CONFIG flags to compile your driver code. There are tons of Makefiles' and driver code lying in the source tree. Roam around and you will get a good reference of how it is being done.
c.) Make sure that your driver code is independent of any other
loadable kernel module(i.e such modules which are not part of the
"monolithic" kernel image). Because if you invoke your driver
code(which is monolithic now and is in memory) which depends on
loadable module code then it may cause some kernel
panic/segmentation fault kind of error.
d.) Make sure that your driver is registered with a higher level of
subsystem which will be initializing all the registered drivers
during boot-up time.(for example: an i2c driver once registered
with i2c driver framework will be loaded automatically when i2c subsystem is initialized during system startup). This step might not be really required if you can figure out another way of invoking your driver's __init and __exit functions.
e.) Now, Your Driver _init and (_exit sections) "should" be called
if it is getting loaded by any device driver framework or directly(i.e. while
kernel is booting up ).
f.) In case of h/w drivers, we have .probe implementation in driver
which will be invoked once the kernel finds a corresponding device.
In case of s/w drivers, I guess __init and __exit is all you have.
g.) Once it is loaded, you can use it like you were using it earlier as a loadable kernel module
h.) I'll recommend reading source code of similar device drivers in the linux kernel tree and see how they are operating.
Hope this helps.

View linux kernel drivers built into the kernel, and how do they get binded/mounted/started

I'm having a bit of a hard time fully understanding how the kernel starts in linux. I'm a wince developer and our company decided to run with linux instead now.
We outsourced all of the board bringup and the package I recieved is quit a bit different for the prototype board we have compared to the nitrogen6x we have been using.
Before i start listing the differences for the distro we created, the kernels are identical. The distro we have been using is a busybox system. The one we recieved from the vendor is sysvinit. I removed mdev from busybox and we are only using udev.
when I use the kernel on our busybox build the touch screen drivers breaks, or doesn' run, or does something totally magical. I'm not quit sure... there is a /dev/input/event0 device which when run on the sysvinit side is a touch device.. Is the kernel not the mechanism that binds the built-in drivers to a device node? I thought udev was for more dynamic events in the system.
On the other hand I can't really tell whats been loaded on my device. Is there a way to list running drivers that were built into the kernel? my touch pad is up? This is a fairly simple process of looking at the registry on wince to see which devices were loaded.
I guess what I'm really trying to discover, isn't so much how to add a driver to the kernel, its how the whole thing gets is plumbed together. I've found plenty of documents on createing kernel modules, but i haven't found a good resource on how to pull everything together from scratch so you can actually use said modules. Going back to the example of the touchscreen driver, its built into the kernel, how does that get plugged into /dev/input/event0??
I'm kind of having a difficult time finding good resources mostly because searching google for varations of linux/drivers/device nodes/ piles in tons of random crap from everywhere.
What you probably want to use now is evtest. It will allow you to know what are the input devices that are present and ready to use on your system.
To get more information on the input subsystem and more generic information on how the kernel is working, I can direct you to our training materials. The materials are free to download, use and redistribute.
The general answer is, there is no single, easy place to look to discover what drivers have been loaded by the kernel if they are compiled in. Of course, lsmod will display any drivers that were dynamically loaded after kernel boot.
The kernel does not create device nodes. That is, to quote your question, the kernel does not "bind" the driver to the device node. The association between kernel driver and device node is contained in the major and minor numbers registered when the driver is initialized. You can have a device node on your file system for which there is no corresponding driver (common especially in older devices where device nodes were statically created on the file system) and you can also have a driver installed for which there is no device node.
Modern Linux distros have dynamically created device nodes created on a mount point called /dev and this is usually a tmpfs file system, meaning it is volatile - it gets destroyed on every boot and recreated dynamically on each new boot.
udev is the magic that creates most device nodes based on events that it receives from the kernel when a new device is discovered (this can be after boot on device plugin, like a USB disk) or on startup when udev reads the queued events and acts on them. As you noted, busybox has a limited udev implementation called mdev.
Study udev and you will get a much better understanding of the process. Hope this helps a little.

Resources