30. Linux on Zynq / Piano Project
Post date: Aug 04, 2016 2:46:17 PM
Completed the next project on learning Linux for the Zynq! In short, the zybo behaves like a piano! The video basically covers everything covered in this blog, but I felt as though I didn't do a good job of explaining the goals and challenges of the project. The repository for the project can be found here under "zybo_petalinux_piano".
So, the original goals --- and the expected challenges --- of the project were to 1 ) figure out how a user application running in Linux can access the memory map of a core running in programmable logic and 2 ) learn how to configure and use the Linux SPIdev Sysfs driver. However, I had some unexpected challenges dealing with 3 ) making sure the kernel loaded properly from flash.
1 ) Accessing devices from user-space
Accessing physical addresses from a bare-metal application is, well, pretty straightforward since virtual memory isn't really a thing. You just go ahead access whatever physical address. From a user-space application whose memory space doesn't directly map to physical addresses, there's a necessary extra step in which the right block of physical addresses must be mapped to a block of virtual addresses. This step is obviously something a device driver would do in order to free the user from having to worry about such a low-level detail ( and, not to mention, protect the memory space ). However, I'm going to leave writing a Linux driver --- which will likely consist of finding another driver and using it as a template --- for another project.
2 ) Using SPIdev
Unlike I2Cdev, SPIdev took a bit more effort to get working, surprisingly. Not sure why or how, but the configurations related to I2Cdev are completely automated when configuring PetaLinux project with the hardware description. Specifically, I didn't need to add any lines to the device tree, nor did I have to manually configure the project to include the right drivers in u-boot and the kernel. I simply wrote the application and it worked like a dream! Alas, I needed to do everything for the SPIdev that I didn't have to do for I2Cdev. Wasn't a big deal, especially considering it forced me to learn a bit more on how to configure the device tree, u-boot, and the kernel.
3 ) Loading kernel from flash
What I found surprising was the difficultly in getting u-boot to load the kernel correctly. I ran into the issue once I got the infamous "Wrong Image for bootm command" message from u-boot, which is infamous because many other people ran into similar errors that resulted in the same message. From what I gathered from a bunch of forum posts and blogs, the infamous message is typically the consequence of u-boot trying to load the kernel image from a wrong place in memory. More accurately, the kernel might actually be located in the wrong place, but of course u-boot doesn't know that.
What I didn't realize was the command "petalinux-package --boot --fsbl <FSBL> --fpga <BITSTREAM> --u-boot" doesn't automatically include the kernel when it generates the boot file. The "--kernel" argument needs to be added at the end of the command, else the generated boot file will have a size far less than that of the image itself. I had totally thought the inclusion of the kernel was implied, mostly because UG1144 gave me that impression initially. Upon closer inspection, though, I now realize the instructions on creating a boot image "contains first stage boot loader image, FPGA bitstream, and u-boot". So, the misuse of the command "petalinux-package --boot" was totally on me.
However, even though the size of the boot file started to make sense, u-boot still couldn't load the kernel. The culprit this time was the "petalinux-package --boot" command doesn't actually put the kernel at the correct offset on its own. In fact, I'm 99% certain it places all the data files directly next to each other, even though the kernel is supposed to be located in its own partition. I mean, was it wrong to assume the packaging command would automatically know to do this, considering the project was already configured for specific partitions? Anyways, I had thought the fix would be to simply add the "--offset" argument with the correct offset to the packaging command, but u-boot still couldn't load the image!
So, I dropped "petalinux-package --boot" altogether, and instead I run bootgen from the SDK. Works like a charm.