<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>my tech blog &#187; Zynq</title>
	<atom:link href="http://billauer.se/blog/category/zynq/feed/" rel="self" type="application/rss+xml" />
	<link>https://billauer.se/blog</link>
	<description>Anything I found worthy to write down.</description>
	<lastBuildDate>Thu, 12 Mar 2026 11:36:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Download a 3D-printable spacer / leg for Z-Turn Lite + IO Cape</title>
		<link>https://billauer.se/blog/2018/10/z-turn-lite-io-cape-plastic-leg-spacer/</link>
		<comments>https://billauer.se/blog/2018/10/z-turn-lite-io-cape-plastic-leg-spacer/#comments</comments>
		<pubDate>Sat, 27 Oct 2018 18:54:51 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[Blender and 3D]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=5561</guid>
		<description><![CDATA[(click to enlarge) Even though I find Myir&#8217;s Z-Turn Lite + its IO Cape combination of cards useful and well designed, there&#8217;s a small and annoying detail about them: The spacers that arrive with the boards don&#8217;t allow setting them up steadily on a flat surface, because the Z-Turn board is elevated over the IO [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="https://billauer.se/blog/wp-content/uploads/2018/10/the-whole-thing.jpg"><img class="aligncenter size-medium wp-image-5562" title="Z-Turn Lite + IO Cape with 3D-printed spacer" src="https://billauer.se/blog/wp-content/uploads/2018/10/the-whole-thing-300x95.jpg" alt="Z-Turn Lite + IO Cape with 3D-printed spacer" width="300" height="95" /></a><em>(click to enlarge)</em></p>
<p>Even though I find Myir&#8217;s <a href="http://xillybus.com/doc/xillinux-and-z-turn-lite" target="_blank">Z-Turn Lite + its IO Cape</a> combination of cards useful and well designed, there&#8217;s a small and annoying detail about them: The spacers that arrive with the boards don&#8217;t allow setting them up steadily on a flat surface, because the Z-Turn board is elevated over the IO Cape board. As a result, the former board&#8217;s far edge has no support, which makes the two boards wiggle. And a little careless movement is all it takes to have these boards disconnected from each other.</p>
<p>So I made a simple 3D design of a plastic leg (or spacer, if you like) for supporting the Z-Turn Lite board. See the small white thing holding the board to the left of the picture above? Or the one in the picture below? That&#8217;s the one.</p>
<p><a href="https://billauer.se/blog/wp-content/uploads/2018/10/one-spacer-in-action.jpg"><img class="aligncenter size-medium wp-image-5563" title="3D-printed spacer attached to Z-Turn Lite board" src="https://billauer.se/blog/wp-content/uploads/2018/10/one-spacer-in-action-300x195.jpg" alt="3D-printed spacer attached to Z-Turn Lite board" width="300" height="195" /></a></p>
<p>If you&#8217;d like to print your own, just <a href="/download/zturnspacer.zip" target="_blank">click here to download</a> a zip file containing the Blender v2.76 model  file as well as a ready-to-print STL file. It&#8217;s hereby released to the public domain under <a href="https://creativecommons.org/share-your-work/public-domain/cc0/" target="_blank">Creative Common&#8217;s CC0 license</a>.</p>
<p><a href="https://billauer.se/blog/wp-content/uploads/2018/10/zturn-spacer-model.jpg"><img class="aligncenter size-medium wp-image-5564" title="The 3D model of the spacer, in Blender" src="https://billauer.se/blog/wp-content/uploads/2018/10/zturn-spacer-model-300x206.jpg" alt="The 3D model of the spacer, in Blender" width="300" height="206" /></a></p>
<p>The units of this model is millimeters. You&#8217;ll need this little part of info.</p>
<p>I printed mine at <a href="https://www.hubs.com/" target="_blank">Hubs</a> (they were 3D Hubs at the time). Because I bundled this with another, more bulky piece of work, the technique used was FDM at 200 μm, with standard ABS as material. If you&#8217;re into 3D printing, you surely just read &#8220;cheapest&#8221;. And indeed, printing four of these should cost no more than one USD. But then there&#8217;s the set-up cost and shipping, which will most likely be much more than the printing itself. So print a bunch of them, even though only two are needed. It&#8217;s going to be a few dollars anyhow.</p>
<p>Even though these spacers aren&#8217;t very pretty, and with zero mechanical sophistication, they do the job. At least those I got require just a little bit of force to get into the holes, and they stay there (thanks to the pin diameter of 3.2 mm, which matches the holes&#8217; exactly). And because it&#8217;s such a dirt simple design, this model should be printable with any technique and rigid material.</p>
<p>Wrapping up, here&#8217;s a picture of three printed spacers + two of the spacers that arrived with the boards. Just for comparison.</p>
<p><a href="https://billauer.se/blog/wp-content/uploads/2018/10/spacers.jpg"><img class="aligncenter size-medium wp-image-5565" title="3D-printed spacers compared with Myir's spacers" src="https://billauer.se/blog/wp-content/uploads/2018/10/spacers-300x91.jpg" alt="3D-printed spacers compared with Myir's spacers" width="300" height="91" /></a></p>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2018/10/z-turn-lite-io-cape-plastic-leg-spacer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Controlling GPIO on the Z-Turn Lite board with Xillinux</title>
		<link>https://billauer.se/blog/2018/09/xillinux-z-turn-lite-gpio-bash/</link>
		<comments>https://billauer.se/blog/2018/09/xillinux-z-turn-lite-gpio-bash/#comments</comments>
		<pubDate>Sun, 23 Sep 2018 18:16:49 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=5541</guid>
		<description><![CDATA[Introduction This post shows how to access some GPIO functionalities from Xillinux running on a Z-Turn Lite board (with an Z-turn Lite IO Cape board attached), directly from the command line. Watchdog When the &#8220;WD&#8221; jumper at J26 on the board is placed, it&#8217;s possible to utilize the board&#8217;s watchdog chip, which resets the processor [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>This post shows how to access some GPIO functionalities from <a href="http://xillybus.com/xillinux" target="_blank">Xillinux</a> running on a <a href="http://xillybus.com/doc/xillinux-and-z-turn-lite" target="_blank">Z-Turn Lite</a> board (with an Z-turn Lite IO Cape board attached), directly from the command line.</p>
<h3>Watchdog</h3>
<p>When the &#8220;WD&#8221; jumper at J26 on the board is placed, it&#8217;s possible to utilize the board&#8217;s watchdog chip, which resets the processor if its watchdog-clear pin isn&#8217;t toggled for 1.2 seconds. If that pin is in high-Z, the watchdog is inactive, and doesn&#8217;t reset the processor even if no toggling has taken place. This can be achieved either by removing the &#8220;WD&#8221; jumper, which floats the pin, or making the pin high-Z by setting the relevant GPIO to an input (Xillinux ensures the latter, so booting it with the &#8220;WD&#8221; jumper is safe).</p>
<p>When the pin is high-Z, a small sawtooth-like pulse, which is a few microseconds wide,  is visible with an oscilloscope every 1.2 sec, and it&#8217;s  the watchdog driving the pin to verify that the wire is in high-Z.</p>
<p>The watchdog&#8217;s clear pin is wired to the Zynq&#8217;s PS-only pin MIO0, which is configured as GPIO 0.</p>
<p>To take control of this pin from the command line:</p>
<pre># echo 0 &gt; /sys/class/gpio/export
# echo out &gt; /sys/class/gpio/gpio0/direction</pre>
<p>These commands turn the GPIO into an output, and hence it&#8217;s not a high-Z anymore. The pin must start toggling every 1.2 seconds from this moment, or the processor is reset.</p>
<p>To prevent this reset, the following command can be used:</p>
<pre># while [ 1 ] ; do echo 1 &gt; /sys/class/gpio/gpio0/value ; echo 0 &gt; /sys/class/gpio/gpio0/value ; sleep 0.5 ; done</pre>
<p>This works on MYiR&#8217;s OOB Linux as well (not just Xillinux).</p>
<h3>Sensing the IO Cape board&#8217;s pushbutton</h3>
<p>Not to be confused with the button on the Z-Turn Lite board itself, this is how to fetch the value of the button on the IO Cape Board:</p>
<pre># echo 88 &gt; /sys/class/gpio/export
# cat /sys/class/gpio/gpio88/direction
in
# cat /sys/class/gpio/gpio88/value</pre>
<p>This prints out 0 or 1, depending on the button&#8217;s state.</p>
<h3>Controlling the IO Cape board&#8217;s J8 pins</h3>
<p>Out of the box, Xillinux routes 34 GPIO I/Os to the IO Cape board&#8217;s J8 connector. This can be modified easily by editing the top-level module of Xillinux&#8217; logic design, but this is beyond this post&#8217;s scope.</p>
<p>The 34 pins are wired to the connector&#8217;s pins 3 to 36. In Linux, to access pin N on the J8, request GPIO number N+51.</p>
<p>For example, in order to toggle pin J8/3, the GPIO to request is 3 + 51 = 54, so the following commands at shell prompt cause some fast toggling:</p>
<pre># echo 54 &gt; /sys/class/gpio/export
# echo out &gt; /sys/class/gpio/gpio54/direction
# while [ 1 ] ; do echo 1 &gt; /sys/class/gpio/gpio54/value ; echo 0 &gt; /sys/class/gpio/gpio54/value ; done</pre>
<p>The GPIO pins can also be used as inputs, by following the standard Linux API for GPIO. Note however that pins J8/31 and J8/34 are pulled up with resistors on the IO Cape board.</p>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2018/09/xillinux-z-turn-lite-gpio-bash/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Xilinx&#8217; Zynq Z007s: Is it really single core?</title>
		<link>https://billauer.se/blog/2018/09/xilinx-zynq-smp-or-single-core/</link>
		<comments>https://billauer.se/blog/2018/09/xilinx-zynq-smp-or-single-core/#comments</comments>
		<pubDate>Fri, 14 Sep 2018 15:02:14 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Linux kernel]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=5528</guid>
		<description><![CDATA[Introduction Xilinx&#8217; documentation says that XC7Z007S, among other &#8220;S&#8221; devices, is a single-core device, as opposed to, for example, its older brother XC7Z010, which is dual-core. So I compared several aspects of the PS part of a Z007S vs. Z010, and to my astonishment, I found that Z007S is exactly the same: Two CPUs are [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Xilinx&#8217; documentation says that XC7Z007S, among other &#8220;S&#8221; devices, is a single-core device, as opposed to, for example, its older brother XC7Z010, which is dual-core. So I compared several aspects of the PS part of a Z007S vs. Z010, and to my astonishment, I found that Z007S is exactly the same: Two CPUs are reported by the hardware itself, SMP is kicked off on both, and a simple performance test I made showed that Z007S runs two processes in parallel as fast as Z010.</p>
<p>So the question is: In what sense is XC7Z007S single-core? For now, I have no answer to that. I&#8217;ll update this post as soon as someone manages to explain this to me. In the meanwhile, I&#8217;ve tried to get this <a href="https://forums.xilinx.com/t5/Embedded-Processor-System-Design/Is-the-Z007S-really-single-core/td-p/890243" target="_blank">figured out in Xilinx&#8217; forum</a>.</p>
<p>The rest of this post outlines the various similarities between the Z007S vs. Z010 I tested. The PL bitfiles of different Zynq devices are incompatible, so there&#8217;s no chance I mistook which devices I worked with.</p>
<p>The tests below were made with <a href="http://xillybus.com/xillinux" target="_blank">Xillinux-2.0</a> (kernel v4.4) on two Z-turn Lite boards, one carrying Z007S, and one Z010.</p>
<h3>Found 2 CPUs?</h3>
<p>I started wondering when the kernel&#8217;s dmesg log indicated that it had found 2 CPUs on a Z007S:</p>
<pre>[    0.132523] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
[    0.132586] Setting up static identity map for 0x82c0 - 0x82f4
[    0.310962] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
[    0.311065] <span style="color: #ff0000;"><strong>Brought up 2 CPUs</strong></span>
[    0.311102] <span style="color: #ff0000;"><strong>SMP: Total of 2 processors activated</strong></span> (2664.03 BogoMIPS).
[    0.311121] CPU: All CPU(s) started in SVC mode.</pre>
<p>Also, /proc/cpuinfo consistently listed two CPUs. One could think that it&#8217;s because two CPUs are declared in the device tree, but removing one of them makes no difference.</p>
<p>On Z010, the exact same log and appears in this matter, and /proc/cpuinfo says the same.</p>
<h3>CPU&#8217;s hardware register reporting two CPUs</h3>
<p>According to the Zynq-7000 AP SoC Technical Reference Manual (UG585), the processor&#8217;s SCU_CONFIGURATION_REGISTER indicates the number of CPUs present in the Cortex-A9  MPCore processor in bits 1:0. Binary &#8217;01&#8242; means two Cortex-A9 processors, CPU0 and CPU1. Binary &#8217;00&#8242; means one Cortex-A9 processor, CPU0.</p>
<p>Using Xillinux-2.0&#8242;s poke kernel utility to read the processor&#8217;s SCU_CONFIGURATION_REGISTER register, I got exactly the same result on  Z007S and Z010:</p>
<pre>poke read addr=f8f00004: value=00000511</pre>
<p>In other words, both devices report two processors.</p>
<p>I&#8217;m under the impression that the kernel uses this register to tell the number of CPUs by virtue of the scu_get_core_count() (defined in arch/arm/kernel/smp_scu.c) function, called by zynq_smp_init_cpus() in arch/arm/mach-zynq/platsmp.c.</p>
<p>The latter function sets the kernel&#8217;s &#8220;CPU possible&#8221; bits, so it&#8217;s how the Zynq-specific kernel setup code tells the kernel framework which CPUs indexes are good for use.</p>
<p>Also, the <a href="https://github.com/xillybus/xillinux-u-boot/releases/tag/xillinux-z-turn-lite" target="_blank">U-Boot code</a> used by Xillinux for Z-Turn Lite prints out the processor count, based upon SCU_CONFIGURATION_REGISTER, as well as other info. For Z007S it gave:</p>
<pre>U-Boot 2013.07 (Sep 17 2018 - 11:51:45)              

Detected device ID code 0x3 (XC7Z007S) with <span style="color: #ff0000;"><strong>2 CPU(s)</strong></span>, PS_VERSION = 3
Strapped boot mode: 5 (SD Card)</pre>
<p>and for Z010:</p>
<pre>U-Boot 2013.07 (Sep 17 2018 - 11:51:45)              

Detected device ID code 0x2 (XC7Z010) with <strong><span style="color: #ff0000;">2 CPU(s)</span></strong>, PS_VERSION = 3
Strapped boot mode: 5 (SD Card)</pre>
<h3>A simple benchmark test</h3>
<p>The proof is in the pudding. I wrote a simple program, which forks into two processes, each running a certain amount of plain CPU-intensive operations, and then quits. The output of this program is of no interest, but it&#8217;s printed out to avoid the compiler from optimizing away the crunching. Its listing is given at the end of this post for reference.</p>
<p>Using the &#8220;time&#8221; utility to measure the execution times, I ran the program on Z007S and Z010, and consistently got the same results, except for slight fluctuations:</p>
<pre># time ./work 400
Parent process done with LSR at e89c4641
Child process quitting with LSR at e89c4641
Parent process quitting

real	0m3.604s
user	0m7.030s
sys	0m0.010s</pre>
<p>The 3.6 seconds given as &#8220;real&#8221; is the wall clock time. The 7 seconds of &#8220;user&#8221; time is the amount of consumed CPU. And as one would expect from a program that runs on two processes on a dual core machine, the consumed CPU time is approximately double the wall clock time. This is the result I expected from Z010, but not from Z007S.</p>
<p>Just to be sure I wasn&#8217;t being silly, I booted  the kernel with &#8220;nosmp&#8221; in the kernel command line, which forced a single-CPU bringup. Indeed, the kernel reported finding one CPU in its logs, and /proc/cpuinfo reflected that as well.</p>
<p>And the pudding?</p>
<pre># time ./work 400
Parent process done with LSR at e89c4641
Child process quitting with LSR at e89c4641
Parent process quitting

real	0m6.998s
user	0m6.970s
sys	0m0.010s</pre>
<p>Exactly as expected: With one processor, forking into two processes has no advantage. The CPU time is the wall clock time. I waited twice as long for it to finish.</p>
<p>At some point I suspected that the specific Linux version I used had a specific scheduler issue, which allowed a single-core CPU to perform as well as a dual-core. However the dual-core results were repeated on a Zybo board with three completely different kernels (except Xillinux-2.0) and yielded the same results (or slightly worse, with older kernels).</p>
<h3>Conclusion</h3>
<p>Given the results above, it&#8217;s not clear why Z007S is labeled as a single-core device. It&#8217;s not a matter of how it quacks or walks, but in the end, the device performs twice as fast when the work is split into two processes.</p>
<p>Or I missed something here. Kindly comment below if you found my mistake.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<h3>Appendix: The benchmark program&#8217;s listing</h3>
<pre>#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;time.h&gt;
#include &lt;signal.h&gt;
#include &lt;errno.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/wait.h&gt;

static unsigned int lsr_state;

int main(int argc, char *argv[]) {

  int count, i, j, bit;
  pid_t pid;

  if (argc != 2) {
    fprintf(stderr, "Usage: %s count\n", argv[0]);
    exit(1);
  }

  count = atoi(argv[1]);

  lsr_state = 1;

  pid = fork();

  if (pid &lt; 0) {
    perror("Failed to fork");
    exit(1);
  }

  for (i=0; i&lt;count; i++)
    for (j=0; j&lt;(1&lt;&lt;20); j++) {
      bit = ((lsr_state &gt;&gt; 19) ^ (lsr_state &gt;&gt; 2)) &amp; 0x01;

      lsr_state = (lsr_state &lt;&lt; 1) | bit;

      if (lsr_state == 0) {
	fprintf(stderr, "Huh? The LSR state is zero!\n");
	exit(1);
      }
    }

  if (pid == 0) {
    fprintf(stderr, "Child process quitting with LSR at %x\n", lsr_state);
    return 0;
  }

  fprintf(stderr, "Parent process done with LSR at %x\n", lsr_state);

  pid = wait(&amp;i);

  fprintf(stderr, "Parent process quitting\n");

  return 0;
}</pre>
<p>saved as work.c, compiled with</p>
<pre># gcc -O3 -Wall work.c -o work</pre>
<p>directly on the Zynq board itself (Xillinux comes with a native gcc compiler). But cross compilation should make no difference.</p>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2018/09/xilinx-zynq-smp-or-single-core/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Soft Linux kernel hacking for dumping ULPI commands to USB PHY</title>
		<link>https://billauer.se/blog/2018/09/linux-dump-ulpi-registers/</link>
		<comments>https://billauer.se/blog/2018/09/linux-dump-ulpi-registers/#comments</comments>
		<pubDate>Tue, 11 Sep 2018 18:37:52 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[Linux kernel]]></category>
		<category><![CDATA[USB]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=5523</guid>
		<description><![CDATA[Ever wanted to see how the a Linux USB host talks with its PHY with ULPI commands? Probably not. But if you do, here&#8217;s how I did it on a Zynq device, connected to an USB3320 USB 2.0 PHY chip. Note that: The relevant sources must be compiled into the kernel. Modules are loaded too [...]]]></description>
			<content:encoded><![CDATA[<p>Ever wanted to see how the a Linux USB host talks with its PHY with ULPI commands? Probably not. But if you do, here&#8217;s how I did it on a Zynq device, connected to an USB3320 USB 2.0 PHY chip. Note that:</p>
<ul>
<li>The relevant sources must be compiled into the kernel. Modules are loaded too late. The choice of PHY frontend is made when the USB driver is initialized, and if the relevant driver isn&#8217;t handy, a generic PHY is picked instead&#8230;</li>
<li>&#8230; which is most likely as good. In retrospect, there&#8217;s is very little reason to load the actual driver.</li>
<li>In particular, my system works great without the dedicated USB PHY driver.</li>
</ul>
<p>So it&#8217;s about adding a plain pr_info() into the kernel&#8217;s drivers/usb/phy/phy-ulpi-viewport.c, so it prints every ULPI register write command to the kernel log. Added code marked in red:</p>
<pre>static int ulpi_viewport_write(struct usb_phy *otg, u32 val, u32 reg)
{
	int ret;
	void __iomem *view = otg-&gt;io_priv;

<span style="color: #ff0000;"><strong>	pr_info("ulpi_viewport_write: reg 0x%04x = 0x%02x\n",
		reg, val);
</strong></span>
	writel(ULPI_VIEW_WAKEUP | ULPI_VIEW_WRITE, view);
	ret = ulpi_viewport_wait(view, ULPI_VIEW_WAKEUP);
	if (ret)
		return ret;

	writel(ULPI_VIEW_RUN | ULPI_VIEW_WRITE | ULPI_VIEW_DATA_WRITE(val) |
						 ULPI_VIEW_ADDR(reg), view);

	return ulpi_viewport_wait(view, ULPI_VIEW_RUN);
}</pre>
<p>And that&#8217;s it. One can also cover the ulpi_viewport_read() method in the same way, but it wasn&#8217;t important to me (I wanted to the powering on of Vbus).</p>
<p>The relevant part in my device tree read:</p>
<pre>	usb_phy0: phy0 {
		compatible = "ulpi-phy";
		#phy-cells = &lt;0&gt;;
		reg = &lt;0xe0002000 0x1000&gt;;
		view-port = &lt;0x0170&gt;;
		drv-vbus;
	};

	usb0: usb@e0002000 {
		compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
		clocks = &lt;&amp;clkc 28&gt;;
		interrupt-parent = &lt;&amp;ps7_scugic_0&gt;;
		interrupts = &lt;0 21 4&gt;;
		reg = &lt;0xe0002000 0x1000&gt;;
		phy_type = "ulpi";
		dr_mode = "host";
		usb-phy = &lt;&amp;usb_phy0&gt;;
	};</pre>
<p>And this is what I got in the dmesg log:</p>
<pre><span style="color: #008000;">[    1.396317] ulpi_phy_probe() invoked
[    1.399968] ulpi_phy_probe() returns successfully
</span>[    1.405148] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    1.418505] ehci-pci: EHCI PCI platform driver
[    1.429765] ehci-platform: EHCI generic platform driver
[    1.441924] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    1.454951] ohci-pci: OHCI PCI platform driver
[    1.466237] ohci-platform: OHCI generic platform driver
[    1.478504] uhci_hcd: USB Universal Host Controller Interface driver
[    1.492047] usbcore: registered new interface driver usb-storage
[    1.505250] chipidea-usb2 e0002000.usb: ci_hdrc_usb2_probe invoked
[    1.518410] e0002000.usb supply vbus not found, using dummy regulator
[    1.532049] ci_hdrc ci_hdrc.0: ChipIdea HDRC found, revision: 22, lpm: 0; cap: e0d0a100 op: e0d0a140
<span style="color: #008000;">[    1.532062] ulpi_init() invoked
</span>[    1.542033] ULPI transceiver vendor/product ID 0x0424/0x0007
[    1.554611] Found SMSC USB3320 ULPI transceiver.
<strong><span style="color: #ff0000;">[    1.566118] ulpi_viewport_write: reg 0x0016 = 0x55
[    1.577825] ulpi_viewport_write: reg 0x0016 = 0xaa
</span></strong>[    1.589383] ULPI integrity check: passed.
<span style="color: #ff0000;"><strong>[    1.600057] ulpi_viewport_write: reg 0x000a = 0x06
[    1.611516] ulpi_viewport_write: reg 0x0007 = 0x00
[    1.622872] ulpi_viewport_write: reg 0x0004 = 0x41
</strong></span>[    1.634203] ci_hdrc ci_hdrc.0: It is OTG capable controller
[    1.634233] ci_hdrc ci_hdrc.0: EHCI Host Controller
[    1.645628] ci_hdrc ci_hdrc.0: new USB bus registered, assigned bus number 1
[    1.672482] ci_hdrc ci_hdrc.0: USB 2.0 started, EHCI 1.00
[    1.684475] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[    1.697770] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    1.711521] usb usb1: Product: EHCI Host Controller
[    1.722832] usb usb1: Manufacturer: Linux 4.4.30-xillinux-2.0 ehci_hcd
[    1.735797] usb usb1: SerialNumber: ci_hdrc.0
[    1.747236] hub 1-0:1.0: USB hub found
[    1.757421] hub 1-0:1.0: 1 port detected
<span style="color: #ff0000;"><strong>[    1.767881] ulpi_viewport_write: reg 0x000a = 0x67</strong></span></pre>
<p>The log entries in green above are just some other similar debug outputs I made, and they pretty much explain themselves.</p>
<p>Did you note that the ULPI was detected by vendor ID / product ID? It&#8217;s for real. These were obtained by ULPI registers read (not shown above). I&#8217;m not all that convinced that this detection made any difference, except for printing out the name of the device.</p>
<p>As for the meaning of these ulpi_viewport_write dumps, most is pretty boring: The first two writes to address 0x16 do nothing. It&#8217;s a scratch pad register. Most likely used by the driver to test the ULPI interface.</p>
<p>The following three writes just assign the default values. So this does effectively nothing as well.</p>
<p>The last write to register 0x0a (OTG register) sets bits 6, 5 and 0, which are DrvVbusExternal, DrvVbus and IdPullup. The interesting part to me was DrvVbusExternal and DrvVbus, because setting any of these two (or both) causes the chip&#8217;s CPEN pin to go high, which turns on the power supply for Vbus. This is the point where the USB port starts behaving like a host and feeds power.</p>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2018/09/linux-dump-ulpi-registers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Lubuntu 16.04 on ARM: Turning off the &#8220;Suspend&#8221; etc. options</title>
		<link>https://billauer.se/blog/2017/12/systemd-dbus-power-hibernate/</link>
		<comments>https://billauer.se/blog/2017/12/systemd-dbus-power-hibernate/#comments</comments>
		<pubDate>Sat, 02 Dec 2017 18:53:13 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Linux kernel]]></category>
		<category><![CDATA[systemd]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=5314</guid>
		<description><![CDATA[In short On an embedded ARM-based Lubuntu 16.04, I had LXDE&#8217;s logoff dialog window offering suspend as an option, and when that was chosen, the system got itself into some nasty state with network and keyboard off. The serial console was still active, and yet, I was better off without it. It turned out that [...]]]></description>
			<content:encoded><![CDATA[<h3>In short</h3>
<p>On an embedded ARM-based Lubuntu 16.04, I had LXDE&#8217;s logoff dialog window offering suspend as an option, and when that was chosen, the system got itself into some nasty state with network and keyboard off. The serial console was still active, and yet, I was better off without it.</p>
<p>It turned out that the kernel was misconfigured to announce that it supported suspend to RAM:</p>
<pre># cat /sys/power/state
freeze mem</pre>
<p>So no wonder that option was presented to the user on GUI. The solution: Turn off the CONFIG_SUSPEND kernel compilation flag. Recompile, deploy, and that&#8217;s it:</p>
<pre># cat /sys/power/state
#</pre>
<p>And the faulty options were gone.</p>
<p>The rest of this post contains things I jotted down as I wasted time trying to find out what the problem was.</p>
<h3>Irrelevant notes</h3>
<ul>
<li>There&#8217;s a systemd-inhibit utility for preventing suspends and sleeps while a certain program is running. Essentially, it issues an &#8220;Inhibit&#8221; command with what / who, why /mode info on DBus for&#8221;org.freedesktop.login1&#8243;.</li>
<li>polkit&#8217;s <a href="https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html" target="_blank">manual</a> (&#8220;man polkit&#8221; lacks some info) directs to a list of directories with  rules.d files written in JavaScript (!!!). The action/ directories are  policy files, in XML, which describe who might be allowed what  operation, and what to write (in several languages) in the dialog box  asking for authentication (typically a password).</li>
<li>Obtaining the sources for the study below
<pre># apt-get source lxsession-logout
# apt-get source systemd</pre>
</li>
</ul>
<h3>A journey in the sources (more wasted time)</h3>
<p>I tried to follow how lxsession-logout, which is LXDE&#8217;s program that displays the logout dialog box, decides which low-power modes to offer. And what actually happens when suspend is requested.</p>
<ul>
<li>lxsession-logout.c learns if the system can suspend (and hence the button shall be presented) by calling dbus_systemd_CanSuspend().</li>
<li>which is implemented in lxsession-logout-dbus-interface.c, and calls systemd_query() with &#8220;CanSuspend&#8221; as its parameter</li>
<li>which (implemented in the same file) in turn opens a session with &#8220;org.freedesktop.login1&#8243; over DBus and issues a query</li>
<li>Judging by the &#8220;BusName=org.freedesktop.login1&#8243; directive in /lib/systemd/system/systemd-logind.service, systemd-logind.service, (running systemd-login) is answering this query.</li>
<li>Looking in systemd&#8217;s login-dbus.c, &#8220;CanSuspend&#8221; calls the method method_can_suspend(), which in turn calls method_can_shutdown_or_sleep() with &#8220;org.freedesktop.login1.suspend&#8221; as the key argument, which calls bus_test_polkit() for an answer on that.</li>
<li>Implemented in systemd/shared/bus-util.c, bus_test_polkit() makes a DBus query on &#8220;org.freedesktop.PolicyKit1&#8243;</li>
<li>There are also references to upowerd in lxsession-logout.c, but since stopping this service changes nothing, I focused on logind.</li>
<li>Judging by the &#8220;BusName=org.freedesktop.PolicyKit1&#8243; directive in /lib/systemd/system/polkitd.service, polkitd.service (running /usr/lib/policykit-1/polkitd) answer this.</li>
<li>Back to login-dbus.c, a &#8220;Suspend&#8221; request causes a call to method_suspend(), which calls method_do_shutdown_or_sleep(), which calls bus_manager_shutdown_or_sleep_now_or_later(), which calls execute_shutdown_or_sleep(). The &#8220;unitname&#8221; parameter traverses these calls with the value SPECIAL_SUSPEND_TARGET. There are several checks on the way that may cancel the request, but this is the chain to fulfilling it.</li>
<li>execute_shutdown_or_sleep() issues a DBus request on &#8220;org.freedesktop.systemd1&#8243; (I have a wild guess which process is on the other side).</li>
<li>Apparently (without following the execution chain), systemd/src/sleep.c is responsible for putting the system in suspend mode and such. Among others, it writes to /sys/power/state. This is where it hit me that maybe the kernel&#8217;s configuration was the problem.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2017/12/systemd-dbus-power-hibernate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux Device Tree: What those status = &#8220;okay&#8221; are about</title>
		<link>https://billauer.se/blog/2017/02/linux-dts-dtsi-status-ok/</link>
		<comments>https://billauer.se/blog/2017/02/linux-dts-dtsi-status-ok/#comments</comments>
		<pubDate>Sat, 25 Feb 2017 14:19:45 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Linux kernel]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=5111</guid>
		<description><![CDATA[There are a lot of &#8220;okay&#8221; assignments in the kernel&#8217;s device tree. For example, arch/arm/boot/dts/zynq-zed.dts starts with /dts-v1/; #include "zynq-7000.dtsi" and later on there&#8217;s, among others, &#38;sdhci0 { status = "okay"; }; &#38;uart1 { status = "okay"; }; &#38;usb0 { status = "okay"; dr_mode = "host"; usb-phy = &#60;&#38;usb_phy0&#62;; }; Let&#8217;s look on the last [...]]]></description>
			<content:encoded><![CDATA[<p>There are a lot of &#8220;okay&#8221; assignments in the kernel&#8217;s device tree. For example, arch/arm/boot/dts/zynq-zed.dts starts with</p>
<pre>/dts-v1/;
#include "zynq-7000.dtsi"</pre>
<p>and later on there&#8217;s, among others,</p>
<pre>&amp;sdhci0 {
	status = "okay";
};

&amp;uart1 {
	status = "okay";
};

&amp;usb0 {
	<span style="color: #ff0000;"><strong>status = "okay";</strong></span>
	dr_mode = "host";
	usb-phy = &lt;&amp;usb_phy0&gt;;
};</pre>
<p>Let&#8217;s look on the last one, relating to the usb0 label. In zynq-7000.dtsi, there&#8217;s</p>
<pre>		usb0: usb@e0002000 {
			compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
			<span style="color: #ff0000;"><strong>status = "disabled";</strong></span>
			clocks = &lt;&amp;clkc 28&gt;;
			interrupt-parent = &lt;&amp;intc&gt;;
			interrupts = &lt;0 21 4&gt;;
			reg = &lt;0xe0002000 0x1000&gt;;
			phy_type = "ulpi";
		};</pre>
<p>So the &#8220;okay&#8221; assignment in zynq-zed.dts overrides the one in zynq-7000.dtsi, &#8220;disabled&#8221;.</p>
<p>As explained on <a href="http://elinux.org/Device_Tree_Linux#status_property" target="_blank">this page</a>, if the &#8220;status&#8221; property is present, it must be &#8220;ok&#8221; or &#8220;okay&#8221;, or the device entry node is ignored (or should be). This allows the .dtsi file to include all possible hardware entries, and keep them &#8220;disabled&#8221;, and let the .dts file including it hand-pick those required, only by changing the &#8220;status&#8221;.</p>
<p>And indeed, in drivers/of/base.c it says</p>
<pre>/**
 *  of_device_is_available - check if a device is available for use
 *
 *  @device: Node to check for availability
 *
 *  Returns true if the status property is absent or set to "okay" or "ok",
 *  false otherwise
 */
bool of_device_is_available(const struct device_node *device)
{
	unsigned long flags;
	bool res;

	raw_spin_lock_irqsave(&amp;devtree_lock, flags);
	res = __of_device_is_available(device);
	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);
	return res;

}
EXPORT_SYMBOL(of_device_is_available);</pre>
<p>and</p>
<pre>/**
 *  __of_device_is_available - check if a device is available for use
 *
 *  @device: Node to check for availability, with locks already held
 *
 *  Returns true if the status property is absent or set to "okay" or "ok",
 *  false otherwise
 */
static bool __of_device_is_available(const struct device_node *device)
{
	const char *status;
	int statlen;

	if (!device)
		return false;

	status = __of_get_property(device, "status", &amp;statlen);
	if (status == NULL)
		return true;

	if (statlen &gt; 0) {
		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
			return true;
	}

	return false;
}</pre>
<p>This feature was added to the kernel back in 2008 in commit 834d97d452208279edf11c57eca150360d2dd1d6, but it seems it took some time before it was actually adopted.</p>
<p>Note that when there&#8217;s no &#8220;status&#8221; entry, it&#8217;s treated as &#8220;okay&#8221;. This retains backward compatibility with DTS files that don&#8217;t care much about this feature.</p>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2017/02/linux-dts-dtsi-status-ok/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Simple GPIO on Zybo using command-line on Linux</title>
		<link>https://billauer.se/blog/2014/07/bash-gpio-xillinux/</link>
		<comments>https://billauer.se/blog/2014/07/bash-gpio-xillinux/#comments</comments>
		<pubDate>Sun, 06 Jul 2014 07:03:28 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=4154</guid>
		<description><![CDATA[Running Xillinux on the Zybo board, this is how I toggled a GPIO pin from a plain one-liner bash script in Linux. The same technique can be used for other Zynq-7000 boards (Zedboard in particular) to easily control GPIO pins. First, I looked up which GPIO pin it is. The pin assignments can be found [...]]]></description>
			<content:encoded><![CDATA[<p>Running Xillinux on the <a href="http://www.xilinx.com/products/boards-and-kits/1-4AZFTE.htm" target="_blank">Zybo</a> board, this is how I toggled a GPIO pin from a plain one-liner bash script in Linux. The same technique can be used for other Zynq-7000 boards (Zedboard in particular) to easily control GPIO pins.</p>
<p>First, I looked up which GPIO pin it is. The pin assignments can be found in the FPGA bundle, in xillydemo.ucf (or in xillydemo.sdc, if Vivado was used to build the project).</p>
<p>So I choose to connect to PMOD header JB, first pin, and the PMOD&#8217;s GND.</p>
<p>In the UCF file there&#8217;s a line saying</p>
<pre>## Pmod Header JB
NET PS_GPIO[32]       LOC=T20 | IOSTANDARD=LVCMOS33; #IO_L15P_T2_DQS_34</pre>
<p>and its counterpart in the SDC file is</p>
<pre>## Pmod Header JB
set_property -dict "PACKAGE_PIN T20 IOSTANDARD LVCMOS33" [get_ports "PS_GPIO[32]"]</pre>
<p>So it&#8217;s quite clear and cut that the PS_GPIO[32] signal is connected to PMOD B. It doesn&#8217;t hurt taking a look on the board&#8217;s schematics as well, if you&#8217;re convenient with those drawings, and see that the Zynq device&#8217;s pin T20 indeed goes to PMOD B, and which pin.</p>
<p>Hooked up as shown in this pic (click to enlarge):</p>
<p><a href="https://billauer.se/blog/wp-content/uploads/2014/03/smaller_IMG_1258.jpg"><img class="aligncenter size-medium wp-image-4159" title="Connecting to the PMOD" src="https://billauer.se/blog/wp-content/uploads/2014/03/smaller_IMG_1258-300x200.jpg" alt="" width="300" height="200" /></a></p>
<p>The offset between PS_GPIO numbers and those designated by Linux is 54. So this pin is found as number 32+54=86.</p>
<p>Hence</p>
<pre># echo 86 &gt; /sys/class/gpio/export
# echo out &gt; /sys/class/gpio/gpio86/direction</pre>
<p>And then poor man&#8217;s oscillator:</p>
<pre># while [ 1 ] ; do echo 1 &gt; /sys/class/gpio/gpio86/value ; echo 0 &gt; /sys/class/gpio/gpio86/value ; done</pre>
<p>This runs at a staggering 2.9 kHz. Pretty impressive for the slowest form of programming one can think about.</p>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2014/07/bash-gpio-xillinux/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Booting Vivado / EDK mixed FSBL on Zynq-7000</title>
		<link>https://billauer.se/blog/2014/07/vivado-ise-fsbl-zynq/</link>
		<comments>https://billauer.se/blog/2014/07/vivado-ise-fsbl-zynq/#comments</comments>
		<pubDate>Wed, 02 Jul 2014 10:52:01 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Vivado]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=4387</guid>
		<description><![CDATA[Background This is yet another war story about making the FSBL boot on a Zynq processor. I had prepared an FSBL for a certain target using SDK 14.6, and then someone needed it in a Vivado package, using the SDK attached to Vivado 2014.1. In a perfect world, I would have exported the system&#8217;s configuration [...]]]></description>
			<content:encoded><![CDATA[<h3>Background</h3>
<p>This is yet another war story about making the FSBL boot on a Zynq processor.</p>
<p>I had prepared an FSBL for a certain target using SDK 14.6, and then someone needed it in a Vivado package, using the SDK attached to Vivado 2014.1. In a perfect world, I would have exported the system&#8217;s configuration from XPS 14.6 to Vivado as an XML file, and generated the FSBL there. But experience shows that nothing really guarantees that the processor&#8217;s configuration will be adopted correctly in Vivado. As a matter of fact, I&#8217;ve seen that Vivado imports some parameters, and others are ignored.</p>
<p>But hey,  I could just copy the existing FSBL source files to a new workspace in the target SDK? After all, it&#8217;s just C code!</p>
<p>This is in fact possible, going File &gt; Import&#8230; &gt; General &gt; Existing Projects into Workspace. Then navigate to the path of the original project&#8217;s workspace. And don&#8217;t forget marking &#8220;Copy projects into workspace&#8221; so that the old one can be moved or deleted. A popup will allow selecting which projects to import, and it&#8217;s done!</p>
<p>Well, not. Selecting the three projects in an FSBL source set (fsbl, fsbl_bsp and system_hw_platform) will indeed create a fresh FSBL project, but it fails compiling (saying that it can&#8217;t find libxilffs as required by the -lxilffs or something like that).</p>
<p>To work around this, I imported only the system_hw_platform project, and generated the FSBL project in Vivado&#8217;s SDK, as usual: File &gt; New &gt; Application Project. Set the name to &#8220;fsbl&#8221;, make sure that the underlying hardware project it system_hw_platform. Click &#8220;Next&#8221; and pick &#8220;Zynq FSBL&#8221; as the template.</p>
<p>This makes sense, because the FSBL project relies on the C sources that were generated when XPS exported the project to SDK. So the hardware configuration remains correct, and the FSBL is new. No reason why this shouldn&#8217;t work, in theory.</p>
<p>The project compiled right away, and an fsbl.elf was ready for mixing into a boot.bin file.</p>
<p>Hurray! Not. It didn&#8217;t boot.</p>
<h3>Despair not</h3>
<p>The immediate measure for these cases in compiling the FSBL <a href="http://forums.xilinx.com/t5/Embedded-Linux/boot-bin-generated-Vivado-2014-1-does-not-boot/td-p/458994" target="_blank">with the -DFSBL_DEBUG compilation parameter</a> (which defines the FSBL_DEBUG compilation variable, turning on debug messages). With some luck, something informative will show up on the serial console, even if it appeared dead before.</p>
<p>I was one of those lucky bas#$%*s. I got:</p>
<pre>PS7_INIT_FAIL : PS7 initialization successful
FSBL Status = 0xA012</pre>
<p>Hmmm&#8230; That sounds like a mixed-up error message. It failed because it was successful? Well, in fact, the message itself represents the confusion causing the problem.</p>
<p>The FSBL status 0xA012 is returned when the call to ps7_init() fails in main.c. Or more precisely, when the returned value isn&#8217;t <strong>FSBL_PS7_INIT_SUCCESS</strong>. By the way, the FSBL generated by SDK 14.6 doesn&#8217;t even bother to check the return value of ps7_init(), but that&#8217;s irrelevant here.</p>
<p>Anyhow, note that ps7_init() is defined in the system_hw_platform, which consists of sources generated by XPS 14.6, but called by the FSBL, which was generated by Vivado.</p>
<p>This is a bit delicate, because ps7_init() returns <strong>PS7_INIT_SUCCESS</strong> when successful (see ps7_init.c), which happens to be defined in ps7_init.h as</p>
<pre>#define PS7_INIT_SUCCESS   (0)    // 0 is success in good old C</pre>
<p>and non-zero values meaning failure. This is the classic UNIX convention.</p>
<p>For some reason, this is what one finds in fsbl.h:</p>
<pre>#ifdef NEW_PS7_ERR_CODE
#define FSBL_PS7_INIT_SUCCESS	PS7_INIT_SUCCESS
#else
#define FSBL_PS7_INIT_SUCCESS	(1)
#endif</pre>
<p>In short: FSBL_PS7_INIT_SUCCESS=1, PS7_INIT_SUCCESS=0. A problem indeed.<strong><br />
</strong></p>
<p>So this is a direct consequence of mixing an old hardware project with a new FSBL. They changed the error code values somewhere in the middle.</p>
<h3>Solution</h3>
<p>The clean way to fix this is defining NEW_PS7_ERR_CODE during compilation. The less clean method is just remove this #ifdef statement and leave it as</p>
<pre>#define FSBL_PS7_INIT_SUCCESS	PS7_INIT_SUCCESS</pre>
<p>And with this FSBL booted correctly and all was well.</p>
<p><em>I know that getting the FSBL to boot is a recurring problem. Please don&#8217;t turn to me for help if your board doesn&#8217;t boot &#8212; there&#8217;s no secret trick, just good old debugging that takes time and effort.</em></p>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2014/07/vivado-ise-fsbl-zynq/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Unsupported machine ID&#8221; after upgrading Linux kernel or U-boot</title>
		<link>https://billauer.se/blog/2014/02/uboot-linux-dtb-fdt-device-tree/</link>
		<comments>https://billauer.se/blog/2014/02/uboot-linux-dtb-fdt-device-tree/#comments</comments>
		<pubDate>Thu, 20 Feb 2014 17:30:41 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[Linux kernel]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=4146</guid>
		<description><![CDATA[Unlike how I usually treat software tools I work with, my attitude towards U-boot is &#8220;if it works, never mind how and why&#8221;. Trying to understand the gory details of U-boot has never been very rewarding. Things work or break more or less randomly, depending on which git revision is checked out. Someone sent a [...]]]></description>
			<content:encoded><![CDATA[<p>Unlike how I usually treat software tools I work with, my attitude towards U-boot is &#8220;if  it works, never mind how and why&#8221;. Trying to understand the gory details of U-boot has never been very  rewarding. Things work or break more or less randomly, depending on which git revision is checked out. Someone sent a patch fixing this and breaking that, and then someone else sent another patch.</p>
<p>So this is my story: After upgrading the Linux kernel from 3.3 to 3.12 (both having a strong Xilinx flavor, as the target is a Zynq board), but kept an old version of U-boot, I ran through the drill that usually makes the kernel boot:</p>
<pre>zynq-uboot&gt; <strong>fatload mmc 0 0x8000 zImage</strong>
reading zImage

2797680 bytes read
zynq-uboot&gt; <strong>fatload mmc 0 0x1000000 devicetree.dtb</strong>
reading devicetree.dtb

5827 bytes read
zynq-uboot&gt; <strong>go 0x8000</strong>
## Starting application at 0x00008000 ...

Error: unrecognized/unsupported machine ID (r1 = 0x1fb5662c).

Available machine support:

ID (hex)        NAME
ffffffff        Generic DT based system
ffffffff        Xilinx Zynq Platform

Please check your kernel config and/or bootloader.</pre>
<p>So the kernel didn&#8217;t boot. Looking at the way I attempted to kick it off, one may wonder how it worked at all with kernel v3.3. But one can&#8217;t argue with the fact that it used to boot.</p>
<p>The first thing to understand about this error message, is that it&#8217;s fatally misleading. The real problem is that the device tree blob isn&#8217;t found by the kernel, so it reverts to looking for a machine ID in r1. And r1 just has some value. The error message comes from a piece of boot code that is never reached, if the device tree is found and used.</p>
<p>Now, let&#8217;s try to understand the logic behind the sequence of commands: The first command loaded the zImage into a known place in memory, 0x8000. One could ask why I didn&#8217;t use uImage. Well, why should I? zImage works, and that&#8217;s the classic way to boot a kernel.</p>
<p>The device tree blob is then loaded to address 0x10000000.</p>
<p>And then comes the fun part: U-boot just jumps to 0x8000, the beginning of the image. I think I recall that one can put zImage anywhere in memory, and it will take it from there.</p>
<p>But how does the kernel know that the device tree is at 0x10000000? Beats me. I suppose it&#8217;s hardcoded somewhere. But hey, it worked! At least on older kernels. And on U-boot 2012.10 and older (but not 2013.10).</p>
<p>For the newer kernel (say, 3.12), a completely different spell should be cast. Something like this (using U-Boot 2012.10 or 2013.10):</p>
<pre>zynq-uboot&gt; <strong>fatload mmc 0 0x3000000 uImage</strong>
reading uImage                                                                  

3054976 bytes read
zynq-uboot&gt; <strong>fatload mmc 0 0x2A00000 devicetree.dtb</strong>
reading devicetree.dtb                                                          

7863 bytes read
zynq-uboot&gt; <strong>bootm 0x3000000 - 0x2A00000</strong>
## Booting kernel from Legacy Image at 03000000 ...
   Image Name:   Linux-3.12.0-1.3-xilinx
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3054912 Bytes = 2.9 MiB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 02a00000
   Booting using the fdt blob at 0x02a00000
   Loading Kernel Image ... OK
OK
   Loading Device Tree to 1fb4f000, end 1fb53eb6 ... OK                         

Starting kernel ...                                                             

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
[ ... kernel boots, bliss and happiness ... ]</pre>
<p>OK, so I twisted it all around. All of the sudden, I use an uImage, rather than zImage. Why? Because bootm works with uImage, and bootz wasn&#8217;t supported by that specific U-boot version (or configuration, I&#8217;m not really sure).</p>
<p>The addresses I loaded into are different too, and I&#8217;m not sure it matters. What surely matters, is that bootm was explicitly given the address of the device tree blob, and therefore passed that through a register to the kernel. So in this case, it&#8217;s pretty obvious how the kernel finds what&#8217;s where.</p>
<p>Ah, but there&#8217;s a twist. The latter, bootm-based method didn&#8217;t work on the 3.3 kernel. In fact, I got a very similar error message when I tried that.</p>
<p>As I said in the beginning, I never cared dive deep into U-boot. So all I&#8217;m saying is &#8212; if you encounter an error message  like the one above, just try the other magic spell, and hope for good.</p>
<p>And if someone known more about what happened in the connection between U-boot and Linux somewhere in 2012, or has a link to some mailing list discussion where this was decided upon, please comment below. :)</p>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2014/02/uboot-linux-dtb-fdt-device-tree/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Setting up a cross compiler: Buildroot notes</title>
		<link>https://billauer.se/blog/2013/05/buildroot-cross-compiler-arm/</link>
		<comments>https://billauer.se/blog/2013/05/buildroot-cross-compiler-arm/#comments</comments>
		<pubDate>Thu, 02 May 2013 19:18:27 +0000</pubDate>
		<dc:creator>eli</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Zynq]]></category>

		<guid isPermaLink="false">https://billauer.se/blog/?p=3631</guid>
		<description><![CDATA[Just a quick summary on how to compile my own cross-compiler in 20 minutes. Download from Buildroot&#8217;s home page Run &#8220;make xconfig&#8221;. The configuration is stored in .config Possibly set BR2_JLEVEL=8 for parallel compilation(even though 0 should just do it right according to the number of processors present) Pick little Endian ARM Cortex-9 for Xillinux [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quick summary on how to compile my own cross-compiler in 20 minutes.</p>
<ul>
<li>Download from <a href="http://buildroot.uclibc.org/" target="_blank">Buildroot&#8217;s home page</a></li>
<li>Run &#8220;make xconfig&#8221;. The configuration is stored in .config</li>
<li>Possibly set BR2_JLEVEL=8 for parallel compilation(even though 0 should just do it right according to the number of processors present)</li>
<li>Pick little Endian ARM Cortex-9 for Xillinux (Zynq-7000)</li>
<li>&#8220;make source&#8221; to grab the tarballs</li>
<li>The run &#8220;make&#8221;. Should take 10 minutes on a quadcore with hyperthreading.</li>
<li>The cross compiler&#8217;s executable is at output/host/usr/arm-buildroot-linux-uclibcgnueabi/bin/gcc but don&#8217;t use it directly (or you get &#8220;error trying to exec &#8216;cc1&#8242;: execvp: No such file or directory&#8221;)</li>
<li>Instead, go something like
<pre>output/host/usr/bin/arm-buildroot-linux-uclibcgnueabi-gcc -Wall -O3 --static -o hello hello.c</pre>
</li>
<li>The same prefix goes for other cross-compilation binutils</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://billauer.se/blog/2013/05/buildroot-cross-compiler-arm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
