Jetson Nano - Editing DTB file to interface with hardware

I am trying to connect a CAN shield with the jetson nano but I am having trouble finding instructions online to access + edit the DTB file to be able to interface with the hardware.

From what I have come across online, the way to go seems to be to completely rebuild the kernel and modify the DTB file that way

As I’m a beginner with this, I have some basic questions about the process of rebuilding kernel. Is this done on another computer then flashed to the jetson, or is there a way to access + modify the DTB file on the jetson nano itself?

It would also be really helpful if someone can post the step-by-step instructions to either modify the DTB file or rebuild the kernel (the links instructions I have found online don’t seem to work)

Shika

Some information you might find useful…

The device tree can be built with the kernel source, but doing so is not building a kernel at all. The device tree is essentially a set of arguments you can pass to various drivers as they load (arguments to the function call). Technically, the device tree is not part of the kernel. The reason you can build this from the kernel is that arguments to different drivers only apply if that driver is used, and when you configure a kernel, then it makes sense to use that configuration to build a device tree. Consider building a device tree with the kernel source to simply be sharing of the Kconfig mechanism to pick possible arguments which apply only to selected drivers. The actual kernel is not built.

Aside from building a device tree via kernel source there are many other ways to work with this. The tool “dtc” (device tree compiler) can take a source (".dts") tree and convert back and forth with an object file (".dtb" files). This tool can also use a directory tree to create a source or binary file.

As an example, the kernel will show a reflection of the device tree it sees at the time of loading using pseudo files (they aren’t really on the hard drive, they are in RAM, and pretending to be files). To create a human readable (and editable) source file from the running system:
dtc -I fs -O dts -o extracted.dts /proc/device-tree
(if you don’t have “dtc”, then “sudo apt-get install device-tree-compiler”…the kernel comes with this in its own source as well)

In the above the “input” type is “filesystem”, or “fs”, the output is type device tree source ("-O dts"), the name of the file output is “extracted.dts”, and the data which creates this extracted.dts is “/proc/device-tree”. You might want to even cd to “/proc/device-tree” and see what is in it and how it compares to a tree.

To convert an existing binary to source:
dtc -I dtb -O dts -o reverse_compiled.dts /boot/some_tree.dtb

You could then edit reverse_compiled.dts, and turn it into a new custom .dtb (try to not overwrite a new file onto an old file…it is better to leave the old one in place and edit extlinux.conf to point at the new tree):
dtc -I dts -O dtb -o edited_new_tree.dtb reverse_compiled.dts

Just for trivia’s sake, note that kernel builds use a “device tree include file”, or “.dtsi”. These are not complete source, but are a subset of tree used with a particular driver when Kconfig says to build that driver. Many .dtsi files are combined, which becomes a master source “.dts” file. Then this is built with dtc like in the above examples. The files chosen for this creation probably depend (at least in the case of a Jetson) on the carrier board model, the module model on the carrier board, and the configured drivers.

FYI, “plug-n-play” devices don’t need a device tree, they self-report and the kernel can figure them out. Device tree is used when hardware needs to be found somewhere and given arguments which the device itself cannot self-report. An example would be a serial UART. If you run this command you’ll see the specification of some serial UARTs, along with their physical address in memory:
find /proc/device-tree/ -name 'serial@*'
(you could then cd to that location and examine files which would correspond to the section of the “.dtb” file loaded if the file is reverse compiled…the number in the “serial@number” is the hex base address)

When trying the dtc -I fs -O dts -o extracted.dts /proc/device-tree command, I’m getting an error : FATAL ERROR: Couldn’t open output file extracted.dts: Permission denied.

How do I give myself permission to access the directory?

There isn’t any special permission required for the command to run, but to create “extracted.dts” you need to be in a directory your user has permission to write in. If you are in “/proc”, then basically nobody has permissions there (with exceptions). If you first “cd /some/where/you/can/write/to”, and then run the dtc command, it should work.

I was able to extract the device tree and edit it in the form of dts but when trying to create the new .dtb file, I got the following error:

Error: extracted.dts:8666.28-29 syntax error
FATAL ERROR: Unable to parse input tree

I think the syntax error occured when extracting the dtb file to dts.Is there a step in between (like a command to run) to make sure the extraction doesn’t have errors?

Was there any sort of error when creating the first “.dts” extracted file?

If you recompile the uneditedextracted.dts”, is it able to create a “.dtb” file? Is it only after edits when the recompile fails?

Also, can you provide a full error log? For example, if you have used cd to go to a directory your user can write to:
dtc -I dts -O dtb edited.dtb extracted_and_edited.dts 2>&1 | tee log_dtc.txt