Hey Everyone,
After spending a few nights on this - I have decided my project is to be a "microphone" based project. Sounds simple enough right ? ( ) As I progressed, it has later on branched out to be something else entirely. Read on!
Aim:
The main of my project is to record audio using Linux (would have used a switch -- but "Minized" doesn't have a switch, nor do I have a PMOD connector). I could, just supply 3.3V from my Arduino onto one of the PMOD pins ( but then where is the fun in that ). I wanted to do something related to the "Path to Programmable" material. I've tried my best to stick around the course material, but I doubt I've succeeded in that.
When you have thought it all : Audio recorder
First things first, I looked around for some ready-made TCL files I could use. These TCL files, generate the project for you, along with the whole IP design and they generate a bitstream too. When I searched long enough on Github, I stumbled across the "Avnet" repository, which contained different TCL files for Avnet boards HDL . I used the minized_mic.tcl on Vivado 2017.1 . Keep in mind you will also need this repository to generate the project.
Once you're done you will have IP designs such as this -
All the other TCL files contained a lot of unnecssary IPs and most of them are not required.
I'll briefly cover the function of IPs in this design and then explain the reasons why this design is flawed.
- microphone_mgr_0 : This module receives raw PDM (single-bit) data from PDM mic on MiniZed @ 160 MHz / 64 = 2.5 MHz. I don't really see the need of this IP except that it displays some data for the ILA in a registered format.
- pdm_fit_0 : This is the "deserialzer IP". It converts the input serial data line into 16-bit mono audio output which could then be compiled into an audio file. Probably the most important IP. One of the other guys in this programme - mconners put up this wonderful blog on this project here : Path to Programmable Project Blog. Do have a look.
- The two above mentioned IPs are connected to ILAs which can be used to monitor the output from the IPs. Please note they're connected to another clock of : 160MHz. And if one, opens the pdm_fit_0 IP to see the behavioral simulation file - There is a counter which divides the clock by a counter of 4096 times. So it's 2.5Mhz/4096 = 610Hz approximately [I think I've screwed up in this number. I am not a VHDL guy (Verilog one), but I can dive in again if you all are still curious]. At this frequency, it generates 16-bit output data from the modified microphone IP output [which is at a frequency of 2.5Mhz] .
So that covers up this design. Great. Now we have to find a way to store this data so that it can be accessed by the PS.
Now wait a minute here, firstly why can't I use the registers defined in the IPs --- cause they're not connected to the Zynq by any interconnect. That is to say there is no AXI connection in this diagram flow of the microphone. As a result, this design is ONLY limited to producing outputs for the ILA , which is something we don't want.
I came up with a solution to this problem which is the incorrect way of approaching it but will be listing it anyways -
a) The wrong approach : Creating a M-AXI IP.
I won't really get to the details of how I made the IP as it is given here quite well : UG-1119
So, what really did I want to implement? and why was it wrong? Since the Zynq PS would be reading the output of the microphone output , the IP would input the Microphone's PDM output and is connected to the PS through a M-AXI. Now a Master AXI interface drives stuff. We can't access any of the registers in this new IP of mine [through SDK] and it then absolutely defeats the purpose of using it.
b) The correct approach : Creating a S_AXI IP.
This is a much easier IP to use. This is because the PDM outputs can now be registered and are given an address. Thus, all I need to do is read from this address and I should be getting a 16-bit output. The final IP design came around to be like this :
So now as the output is mapped to a register [see code here audio_sink_1.0/hdl ] one can access the audio outputs.
So that's the easy part. Now comes the tricky bit, using the SDK. It's great! I've these registers, for the 16-bit audio data, but new data would be hammered into the registers at 610Hz. The question is how do I use this data. I planned to put it into the eMMC , since the miniZed doesn't have any SD card slot [ don't have a PMOD connector]. So the setup is pretty simple -
After launching SDK, create a new board support package (bsp), and click Finish. You would be greeted by another window to choose libraries - make sure to tick mark xillfs [Generic FAT library]. On the left click on the Overview Tab > standalone > xilffs [highlighted in pic below] and make sure that fs_interface = 1 [indicates it's a eMMC/SD]
Click on Finish. Next open your own bsp, scroll down and import the example for xilffs. And just for you all to compare the file , I've attached it here xilffs_polled_modified.c . Add the lines to reference the address space of the audio_sink [my custom made IP] in the file. So that sums up the SDK part, only for me to realize, that how will I know if I have written to the eMMC. It's a bare metal application, means it doesn't even have it's own TCP/IP stack. Thus, I cannot connect to it through the wireless IP. Also, just to mention, I do not have any wireless IP in my design. Looks like this has hit a dead end.
If only I could go down that easily :
A second Chance : Petalinux
Booting Linux from eMMC.
To continue the above project, we will implement "Petalinux" on the board. Now we all know that Minized has petalinux installed on the board. I wanted to do the process from scratch and go through it ab-initio. I am sure a lot of the community will benefit from my little experiment...
First thing we have to make sure that Card Detect line has been enabled. If this isn't enabled the memory controller on Zynq won't recognize eMMC and Linux won't be able to access this memory unit. Generate a bitstream after updating the output products and wrapper. Export the hardware so we have out Hardware Description File generated.
Next open the terminal create a new petalinux project :
petalinux-create --type project --template zynq --name mic_ptlnx
Next go to the directory where out hdf has been generated : for me it is different so include the changes accordingly in the following command -
cd ./minized_mic/minzed_mic.sdk/ petalinux-config --get-hw-description -p ../../mic_ptlnx/
You will be greeted with a blue DOS like menu. Looks pretty cool, gotta give it that ! The above command parses the hdf to get the hardware information to be updated in the device tree.
Make sure Subsystem AUTO Hardware Settings is starred . This menu allows customizing hardware . Have look through each of the various settings . One can modify them accordingly. Just to point to the users, if you go to SD/SDIO settings > Primary .. We can select where we want the eMMC to be connected through (SD 0 or SD 1), I am leaving it as a default setting - SD 0.
Exit the menu when done. Hit Yes if prompted to save config. This is done so as to create a checkpoint.
You can configure other options such as the kernel, but I won't be touching that now.
Onto the next step, installing linux on QSPI. But before that , let's look at the existing partitioning scheme on the QSPI :
These look like the default settings for generating these partitions. I plan to stick to this table as it saves me the trouble of resizing the table. My main aim for the petalinux to be setup is -
Boot image configured to boot (First Stage Bootloader and u-boot) --- QSPI
Kernel image for the linux build --- eMMC
File system or Device Tree configuration --- eMMC controller
Next change directory to the project folder. Type in petalinux-config and then go to Subsystem AUTO Hardware Settings > Advanced bootable image storage settings > boot image settings > image storage media and change the image storage media to primary flash.
Next press Exit and then go to kernel settings > image storage media > and change that to primary sd [Final look below when you press Exit once].
Press Exit once more and go to SD/SDIO settings. Here we want to refer to MIO configuration where our eMMC talks to the Zynq PS (As done in the initial steps). Change it to ps7_sd1 (we could use ps7_sd0 too , but since we are following a series of steps , go ahead with sd1)
Finally run the command on the terminal
petalinux-build
This is where I am stuck . I have updated all the locales to en_US.UTF_8. if I type locale, it shows to me it's all the LANGUAGE variables are set to a en_US.UTF-8
A little digging up on the net led me to this blog: https://forums.xilinx.com/t5/Embedded-Linux/PetaLinux-build-fails-with-locale-errors-How-to-disable-locale/m-p/894431/hi…
I have fixed each and every locale.py, I still land up with this error.
My solution is to install Ubuntu 14.04 and then install petalinux 2017.4. So this would probably be my 4th time installing petalinux tools [All the previous times have been attempts to build a docker image, and miserable attempts to run it on a VM]. And don't get me started with Vivado.
I am going to put a poll at the end of this blog for the e14 community to decide the future of this project.
Update
I finally managed to get the petalinux-build instruction to work. The following were the steps I performed to get it running :-
- Fixed the locales - by deleting all the packages already installed in my FS and replaced it with the only one I need en_US.UTF-8
- replaced the return statement of the function setlocale in locale.py with a try catch block.
- Similarly in the sanity.py with a try catch block.
So in other words , I disabled the check instruction of petalinux-build for locales. There were also one-two TCL instructions that refused to work. They all deal with a microblaze IP. I have included one of the lines which constantly gave me error :
if { [string match -nocase $proc_type "microblaze"] != 1} {
I commented out the lines and finally got the petlinux-build working !
Aah the relief! And now *DRUM ROLLS* packaging the petalinux image for deployment!
petalinux-package --boot --fsbl ./components/plnx_workspace/fsbl/fsbl/Release/fsbl.elf --fpga ./components/plnx_workspace/device-tree/device-tree-generation/minized_mic_wrapper.bit --uboot --force
The BOOT.BIN image is now ready for programming to the QSPI device. When I will boot the target with the minized mode switches set for QSPI, it will load the boot image from QSPI and u-boot will load the kernel image from eMMC.
It hit me hard but it seems like I was incorrect in how I was approaching a Petalinux deployment. I need a SD Card slot (PMOD connector for the Minized ) to load the kernel image onto the eMMC. Before the memory can be used I have to partition the eMMC, store the kernel image (image.ub) onto the eMMC and then have to modify the eMMC by tty-ing to it. After which I can remove the SD card slot PMOD connector and the Petalinux now is a standalone on the Minized.
Well that went down pretty quick
So is it possible ??
Of course it is ! With a SD card PMOD connector Petalinux would have been up and running smoothly! I had another wild idea which I am going to update this week ( I could have delayed the update for a later date but e14 doesn't allow to save drafts to a blog after it has been published) - I plan to program the new image.ub through a USB drive. It's a very vague idea but I have hopes this should work (If everything works fine ) . So yes this is far from over but we are almost there.
So that's about it folks. It has been a long journey alright, but I really want to see this project through. I want to see the audience and see if I should push through the last frontier. I really would like to thank rscasny and the rest of the team to give me this wonderful opportunity to work on Avnet stuff. And on that note, I'll be back hungry for more !
Top Comments