- Before start, please review this tutorial.
In the DUNE experiment, the photon detection system, DAPHNE, has undergone an evolution that led to the use of SoM (System on Modules). This transition aims to achieve greater compactness in hardware and software task implementation, enhanced system control, and operational security. Given the context of the DUNE experiment, this system will be situated 1 km underground in the Fermilab caverns, making subsequent system servicing challenging. Therefore, a high level of security and robustness is required in the system implementation. Here, the KRIA KR260 takes center stage as the chosen SoM to manage the photon detection system's operation.
In this tutorial, I'll demonstrate the necessary steps to include certain external pin control peripherals and establish connectivity through the AXI port. This addition will provide support for the RPi and PMOD connectors included in the KRIA KR260 carrier board. Once the project is configured in Vivado 2022.2, synthesis and implementation are completed, the bitstream is created, and the platform is exported. This exported platform will be sent to create the Device Tree Overlay on the KRIA KR260. Subsequently, the embedded hardware will be implemented, and control will be provided to the peripherals through the AXI port from Petalinux 2022.2.
One of the compelling features that drew my attention towards the Kria KR260 for my robotics applications, unlike the Kria KV260, was its additional I/O connectors capable of driving various peripherals like motors. Understanding that mapping I/Os on an FPGA involves more complexity compared to conventional microcontroller boards such as the Raspberry Pi or BeagleBone, I opted to create a comprehensive guide detailing how I tackle the I/O mapping for a new AMD-Xilinx development board.
Moreover, owing to the Kria's SoM (System on Module) architecture, the I/O mapping presents an additional layer of complexity as it spans across two distinct boards: the Kria K26 base board and the KR260 carrier board. For newcomers, pinpointing the necessary information to fully map a signal from a PMOD or the RPi header to a package pin on the Kria's K26 FPGA itself might seem somewhat obscured.
Furthermore, the PMODs and RPi header on the KR260 are linked to the programmable logic of the K26, unlike most other peripherals connected to the MIO/EMIO pins. This necessitates modifying the block design in Vivado or adding HDL code to incorporate the required interface for each connector. Consequently, generating a new bitstream and creating a corresponding hardware node in the device tree becomes essential.
For those unfamiliar, the boot process of the Kria's embedded Linux image initiates the ARM-core processors of the Zynq MPSoC in the K26 FPGA before flashing a bitstream onto its programmable logic (PL). Thus, any hardware nodes in the device tree for components located in the PL must be loaded later as a device tree overlay. Otherwise, the boot process would stall while searching for device tree nodes not yet present in the system, as the PL hasn't been programmed yet. This explains why the default boot binary (boot.bin) for the Kria boards downloaded from the K26 SoM wiki lacks a packaged device tree.
Certainly, it's possible to reconfigure a PetaLinux project derived from the KR260/KV260 BSP to alter the boot sequence and program the PL during boot, integrating a device tree into the boot binary. Alternatively, creating a Petalinux project from scratch with this configuration is feasible. However, configuring a PetaLinux project for the Kria boards remains intricate enough that it's far more convenient and efficient to modify a project created from a BSP. This explains why I won't provide a project tutorial for a KR260/KV260 Petalinux project built entirely from scratch, as 99% of it would involve copying and pasting content from a project created using the BSP.
Nonetheless, I've discovered that the simplest solution involves loading the device tree overlay in the same manner as I would for an accelerated application, enabling a smoother workflow. This is precisely what I'll demonstrate in this project.Download KR260 schematic
The schematic for the KR260 carrier board (XTP743) can be accessed here. It must be directly downloaded from AMD-Xilinx’s site, as a user agreement needs to be digitally signed prior to downloading.
The schematic for the Kria K26 base board is not publicly available due to it being a commercial product rather than just a development part. However, included in the KR260 schematic download is a master pinout constraints file that provides the necessary information for signal mapping.
Modify the block design in Vivado 2022.2As previously mentioned, since the PMOD and RPi headers are connected via the PL, the block design in Vivado requires updating to incorporate the specific desired interface for each connector. Constraint files also need inclusion to specify the package pins on the FPGA. I'll utilize a copy of the previous Vivado project created to configure the PS side to run Petalinux, as demonstrated in the previous posts. To achieve this, simply navigate to the project menu and save a copy of this project.
For this purpose, I'll be using the AXI GPIO IP block for everything. I won’t cover the RPi special functions at the moment, but the process involves adding appropriate IPs for each special function, such as I2C or SPI. I've included 5 AXI GPIO IP blocks in the block design: four consist of one channel of 8 bits for the PMOD connectors, while the fifth is one channel of 28 bits for the RPi connector.
Once added, run the corresponding Connection Automation that appeared, leaving all selections for clock as the default.
Validate the block design and save it, then generate the block design again.
Create a new HDL wrapper by right-clicking on the block design file in the Hierarchy tab of the Sources window and selecting Create HDL Wrapper
. Select to either allow Vivado to auto-manage it or allow for user edits.
Once the signal names have been brought up to the top-level HDL file, they require connections to specific package pins on the FPGA using constraint files.
I've included two new constraint files in the design (Add Sources > Add or create constraints > Create File): one for the PMODs and another for the RPi header. While it's entirely feasible to have everything in a single constraints file with the same compliance, I prefer organizing them separately for different connector types, finding it easier to manage.
The complexity surrounding the KR260's PMOD IO lies in the differentiation between PMOD IO numbering and the physical connector’s pin numbering. Specifically, pin 1 and pin 8 on the connector correspond to PMOD IO1 and PMOD IO8, whereas the remaining pins on the connector alternate sides, unlike the consecutive arrangement of PMOD IOs across the connectors:
In the follow table, it is provide a mapping of the PMOD outputs and the SoM pin name:
Since the PMOD IO signal names go across the connectors, that’s how is structured in the constraints file with each broken up into the “upper” and “lower” IOs.
In the case of RPi connector it was made something similar to map the pins of the SoM and the output pins of the FPGA:
You'll notice that I've also updated the spreadsheet by including the Sysfs GPIO numbers once they were registered in the Linux system (as explained in the previous section). I strongly advocate for maintaining comprehensive documentation systems for designs like this. Without such documentation, attempting to reverse-engineer the setup a few weeks or months later could become a daunting task.
Below, you'll find the constraint file specifically created for the PMODs:
##################### PMOD 1 Upper ###################################
set_property PACKAGE_PIN H12 [get_ports {pmod1_io_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod1_io_tri_io[0]}]
set_property PACKAGE_PIN E10 [get_ports {pmod1_io_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod1_io_tri_io[1]}]
set_property PACKAGE_PIN D10 [get_ports {pmod1_io_tri_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod1_io_tri_io[2]}]
set_property PACKAGE_PIN C11 [get_ports {pmod1_io_tri_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod1_io_tri_io[3]}]
##################### PMOD 1 Lower ###################################
set_property PACKAGE_PIN B10 [get_ports {pmod1_io_tri_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod1_io_tri_io[4]}]
set_property PACKAGE_PIN E12 [get_ports {pmod1_io_tri_io[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod1_io_tri_io[5]}]
set_property PACKAGE_PIN D11 [get_ports {pmod1_io_tri_io[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod1_io_tri_io[6]}]
set_property PACKAGE_PIN B11 [get_ports {pmod1_io_tri_io[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod1_io_tri_io[7]}]
##################### PMOD 2 Upper ###################################
set_property PACKAGE_PIN J11 [get_ports {pmod2_io_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod2_io_tri_io[0]}]
set_property PACKAGE_PIN J10 [get_ports {pmod2_io_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod2_io_tri_io[1]}]
set_property PACKAGE_PIN K13 [get_ports {pmod2_io_tri_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod2_io_tri_io[2]}]
set_property PACKAGE_PIN K12 [get_ports {pmod2_io_tri_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod2_io_tri_io[3]}]
##################### PMOD 2 Lower ###################################
set_property PACKAGE_PIN H11 [get_ports {pmod2_io_tri_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod2_io_tri_io[4]}]
set_property PACKAGE_PIN G10 [get_ports {pmod2_io_tri_io[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod2_io_tri_io[5]}]
set_property PACKAGE_PIN F12 [get_ports {pmod2_io_tri_io[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod2_io_tri_io[6]}]
set_property PACKAGE_PIN F11 [get_ports {pmod2_io_tri_io[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod2_io_tri_io[7]}]
##################### PMOD 3 Upper ###################################
set_property PACKAGE_PIN AE12 [get_ports {pmod3_io_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod3_io_tri_io[0]}]
set_property PACKAGE_PIN AF12 [get_ports {pmod3_io_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod3_io_tri_io[1]}]
set_property PACKAGE_PIN AG10 [get_ports {pmod3_io_tri_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod3_io_tri_io[2]}]
set_property PACKAGE_PIN AH10 [get_ports {pmod3_io_tri_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod3_io_tri_io[3]}]
##################### PMOD 3 Lower ###################################
set_property PACKAGE_PIN AF11 [get_ports {pmod3_io_tri_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod3_io_tri_io[4]}]
set_property PACKAGE_PIN AG11 [get_ports {pmod3_io_tri_io[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod3_io_tri_io[5]}]
set_property PACKAGE_PIN AH12 [get_ports {pmod3_io_tri_io[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod3_io_tri_io[6]}]
set_property PACKAGE_PIN AH11 [get_ports {pmod3_io_tri_io[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod3_io_tri_io[7]}]
##################### PMOD 4 Upper ###################################
set_property PACKAGE_PIN AC12 [get_ports {pmod4_io_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod4_io_tri_io[0]}]
set_property PACKAGE_PIN AD12 [get_ports {pmod4_io_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod4_io_tri_io[1]}]
set_property PACKAGE_PIN AE10 [get_ports {pmod4_io_tri_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod4_io_tri_io[2]}]
set_property PACKAGE_PIN AF10 [get_ports {pmod4_io_tri_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod4_io_tri_io[3]}]
##################### PMOD 3 Lower ###################################
set_property PACKAGE_PIN AD11 [get_ports {pmod4_io_tri_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod4_io_tri_io[4]}]
set_property PACKAGE_PIN AD10 [get_ports {pmod4_io_tri_io[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod4_io_tri_io[5]}]
set_property PACKAGE_PIN AA11 [get_ports {pmod4_io_tri_io[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod4_io_tri_io[6]}]
set_property PACKAGE_PIN AA10 [get_ports {pmod4_io_tri_io[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {pmod4_io_tri_io[7]}]
And this is the constrain file for the RPi connector:
##################### Raspberry Pi GPIO Header #######################
### AXI GPIO ###
set_property PACKAGE_PIN AD15 [get_ports {rpi_gpio_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[0]}]
set_property PACKAGE_PIN AD14 [get_ports {rpi_gpio_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[1]}]
set_property PACKAGE_PIN AE15 [get_ports {rpi_gpio_tri_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[2]}]
set_property PACKAGE_PIN AE14 [get_ports {rpi_gpio_tri_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[3]}]
set_property PACKAGE_PIN AG14 [get_ports {rpi_gpio_tri_io[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[4]}]
set_property PACKAGE_PIN AH14 [get_ports {rpi_gpio_tri_io[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[5]}]
set_property PACKAGE_PIN AG13 [get_ports {rpi_gpio_tri_io[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[6]}]
set_property PACKAGE_PIN AH13 [get_ports {rpi_gpio_tri_io[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[7]}]
set_property PACKAGE_PIN AC14 [get_ports {rpi_gpio_tri_io[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[8]}]
set_property PACKAGE_PIN AC13 [get_ports {rpi_gpio_tri_io[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[9]}]
set_property PACKAGE_PIN AE13 [get_ports {rpi_gpio_tri_io[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[10]}]
set_property PACKAGE_PIN AF13 [get_ports {rpi_gpio_tri_io[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[11]}]
set_property PACKAGE_PIN AA13 [get_ports {rpi_gpio_tri_io[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[12]}]
set_property PACKAGE_PIN AB13 [get_ports {rpi_gpio_tri_io[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[13]}]
set_property PACKAGE_PIN W14 [get_ports {rpi_gpio_tri_io[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[14]}]
set_property PACKAGE_PIN W13 [get_ports {rpi_gpio_tri_io[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[15]}]
set_property PACKAGE_PIN AB15 [get_ports {rpi_gpio_tri_io[16]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[16]}]
set_property PACKAGE_PIN AB14 [get_ports {rpi_gpio_tri_io[17]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[17]}]
set_property PACKAGE_PIN Y14 [get_ports {rpi_gpio_tri_io[18]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[18]}]
set_property PACKAGE_PIN Y13 [get_ports {rpi_gpio_tri_io[19]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[19]}]
set_property PACKAGE_PIN W12 [get_ports {rpi_gpio_tri_io[20]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[20]}]
set_property PACKAGE_PIN W11 [get_ports {rpi_gpio_tri_io[21]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[21]}]
set_property PACKAGE_PIN Y12 [get_ports {rpi_gpio_tri_io[22]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[22]}]
set_property PACKAGE_PIN AA12 [get_ports {rpi_gpio_tri_io[23]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[23]}]
set_property PACKAGE_PIN Y9 [get_ports {rpi_gpio_tri_io[24]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[24]}]
set_property PACKAGE_PIN AA8 [get_ports {rpi_gpio_tri_io[25]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[25]}]
set_property PACKAGE_PIN AB10 [get_ports {rpi_gpio_tri_io[26]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[26]}]
set_property PACKAGE_PIN AB9 [get_ports {rpi_gpio_tri_io[27]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rpi_gpio_tri_io[27]}]
Generate Bitstream with Binary File IncludedBy default, Vivado generates only a .bit
file for the bitstream, containing extra configuration information unnecessary in this scenario, as the ARM processor is already booted when flashing the bitstream onto the PL. To include a .bin
file alongside the .bit
file, a specific option in Vivado needs to be enabled.
Access Settings from the Flow Navigator window, and within the Bitstream tab, enable the -bin_file option. Enabling this option will generate a <design_name>.bin
file, which will be output into /<Vivado project>/<Vivado project>.runs/impl_1/
.
Proceed by performing synthesis, implementation, and generating the bitstream for the design. Then, export the platform in the same manner as previously done.
Generate the Device Tree Overlay from the PL DesignThe device tree blob containing the overlay nodes needs to be compiled for the design, which is easily done by using the Xilinx Software Command Line Tools (XSCT), for this, locate in the hardware project folder (./Kria_KR260
) and run the follow commands:
source /tools/Xilinx/Vitis/2022.1/settings64.sh
xsct
In the xsct environment (xsct%
), open the exported XSA from Vivado and use the createdts
command to create the device tree source files for the PL design:
xsct% hsi::open_hw_design kria_base.xsa
xsct% createdts -hw kria_base.xsa -zocl -platform-name kria_kr260 -git-branch xlnx_rel_v2022.2 -overlay -compile -out ./dtg_kr260_v0
xsct% exit
After exiting XSCT, use the standard Linux device tree compiler (dtc
) to compile the source files into the needed device tree blob:
dtc -@ -O dtb -o ./dtg_kr260_v0/dtg_kr260_v0/kria_kr260/psu_cortexa53_0/device_tree_domain/bsp/pl.dtbo ./dtg_kr260_v0/dtg_kr260_v0/kria_kr260/psu_cortexa53_0/device_tree_domain/bsp/pl.dtsi
Transfer the files of the PL Design to the KR260I like to create a folder to copy all of the necessary design files to that need to be uploaded to the KR260 for an accelerated application or PL design like this
Note: the Kria_KR260 directory is the top level directory of the Vivado project:
mkdir -p gpio_file_transfer
cd ./gpio_file_transfer/
It’s here I’ll create the description file, shell.json
, for the design:
~/Kria_KR260/gpio_file_transfer$ nano shell.json
And copy+paste the following to shell.json
:
{
"shell_type": "XRT_FLAT",
"num_slots": "1"
}
Then copy the generated device tree blob and .bin file into the folder:
cp ../dtg_kr260_v0/dtg_kr260_v0/kria_kr260/psu_cortexa53_0/device_tree_domain/bsp/pl.dtbo ./
cp ../Kria_KR260.runs/impl_1/kria_bd_wrapper.bin ./
Rename the device tree blob and .bin file to the same thing (the only difference should be their respect file extensions (also change the .bin
extension to .bit.bin
):
mv kria_bd_wrapper.bin kr260_gpio.bit.bin
mv pl.dtbo kr260_gpio.dtbo
Then, with the KR260 booted up and running with the new SD card image generated in the previous tutorials and connected to the local network, transfer the new PL design files to it:
scp kr260_gpio.dtbo kr260_gpio.bit.bin shell.json petalinux@xilinx-kr260-starterkit-20222:/home/petalinux
Run PL Design on KR260This part of the tutorial is execute in the KRIA KR260, you need to connect to it through SSH using the follow command and your access password:
ssh petalinux@xilinx-kr260-starterkit-20222
In the KRIA KR260 terminal, verify if the files are presented there, then create a directory in the /lib/firmware/xilinx
directory with the same name as was given to the device tree blob and.bin file and copy them into it:
sudo mkdir /lib/firmware/xilinx/kr260_gpio
sudo mv kr260_gpio.dtbo kr260_gpio.bit.bin shell.json /lib/firmware/xilinx/kr260_gpio
At this point, the PL design will show up just like an accelerated application would using the xmutil commands:
sudo xmutil listapps
Unload the default application then load the PL design which flashes the PL design’s bitstream into the PL and loads its device tree overlay:
sudo xmutil unloadapp
sudo xmutil loadapp kr260_gpio
When the device tree overlay loads, the terminal will print out as such indicating the new device tree nodes for each of the AXI GPIO IP blocks are now present in the system.
Testing the GPIOUsing the Sysfs driver, list out the GPIO available in the system:
ls /sys/class/gpio/
export gpiochip0 gpiochip440 gpiochip468 gpiochip476 gpiochip484 gpiochip492 gpiochip500 gpiochip508 unexport
You can print the label for each to determine what each gpiochip number correlates to:
xilinx-kr260-starterkit-20222:~$ cat /sys/class/gpio/gpiochip440/label
80050000.gpio
xilinx-kr260-starterkit-20222:~$ cat /sys/class/gpio/gpiochip468/label
80040000.gpio
xilinx-kr260-starterkit-20222:~$ cat /sys/class/gpio/gpiochip476/label
80030000.gpio
xilinx-kr260-starterkit-20222:~$ cat /sys/class/gpio/gpiochip484/label
80020000.gpio
xilinx-kr260-starterkit-20222:~$ cat /sys/class/gpio/gpiochip492/label
80010000.gpio
xilinx-kr260-starterkit-20222:~$ cat /sys/class/gpio/gpiochip0/label
zynqmp_gpio
xilinx-kr260-starterkit-20222:~$ cat /sys/class/gpio/gpiochip500/label
slg7xl45106
xilinx-kr260-starterkit-20222:~$ cat /sys/class/gpio/gpiochip508/label
firmware:zynqmp-firmware:gpio
The Zynq MPSoC MIO pins are gpiochip0, gpiochip508 is the ZynqMPSoC modepin GPIO controller, and gpiochip500 is the KR260’s I2C GPO reset controller. These three gpiochips are standard to the KR260 and will always be there, and you don’t need to mess with them.
The other gpiochips (gpiochip440, gpiochip468, gpiochip476, gpiochip484, and gpiochip492 in my case) all have the corresponding AXI GPIO’s address from the Vivado block design address editor as their label. So for example, I can now see that the AXI GPIO for the RPi header (address 0x8005_0000) is gpiochip440. And since I have that AXI GPIO IP configured for 28 inout pins, that means RPi_GPIO0 on the AXI GPIO for the RPi header is GPIO 440 in the Sysfs driver, RPi_GPIO1 is GPIO 441, and so on up to RPi_GPIO27 which is GPIO 467.
I attached 8 LEDs to the 8 I/O of PMOD4 which is gpiochip476 and exported each IO as an output pin. Which again means PMOD4 IO1 is 476 through PMOD 4 IO8 which is 483:
echo 476 | sudo tee /sys/class/gpio/export
echo out | sudo tee /sys/class/gpio/gpio476/direction
echo 477 | sudo tee /sys/class/gpio/export
echo out | sudo tee /sys/class/gpio/gpio477/direction
echo 478 | sudo tee /sys/class/gpio/export
echo out | sudo tee /sys/class/gpio/gpio478/direction
echo 479 | sudo tee /sys/class/gpio/export
echo out | sudo tee /sys/class/gpio/gpio479/direction
echo 480 | sudo tee /sys/class/gpio/export
echo out | sudo tee /sys/class/gpio/gpio480/direction
echo 481 | sudo tee /sys/class/gpio/export
echo out | sudo tee /sys/class/gpio/gpio481/direction
echo 482 | sudo tee /sys/class/gpio/export
echo out | sudo tee /sys/class/gpio/gpio482/direction
I then simply went through each toggling them on and off to verify the expected LED turned on/off:
echo 1 | sudo tee /sys/class/gpio/gpio476/value
echo 0 | sudo tee /sys/class/gpio/gpio476/value
.
.
.
echo 1 | sudo tee /sys/class/gpio/gpio483/value
echo 0 | sudo tee /sys/class/gpio/gpio483/value
The GPIO will stay present in the system so long as the PL design is loaded as the current application. You can run any basic (not accelerated) Linux application utilizing them at this point. If the KR260 is power cycled, it will manually need to be reloaded.
After testing LEDs on the other PMOD connectors, I did discover that the grounds for each of the PMODs is not common to each other even though they appear to be on the schematic (meaning I had to connect a ground pin from each PMOD to my breadboard if I wanted to drive an LED from that respective PMOD). So if your external circuit is depending on a common ground between each of the PMODs and RPi header, it will be up to that external circuit to make those connections.
Using Python script to blinking LEDsThis part of the tutorial is based on the following link
First of all, you need to provide the permissions to petalinux user to execute system commands from a Python script, for this you need to do a owner change:
sudo chown petalinux:petalinux -R /sys/class/gpio/*
echo 480 > /sys/class/gpio/export
sudo chown petalinux:petalinux -R /sys/class/gpio/gpio480/*
echo 481 > /sys/class/gpio/export
sudo chown petalinux:petalinux -R /sys/class/gpio/gpio481/*
echo 482 > /sys/class/gpio/export
sudo chown petalinux:petalinux -R /sys/class/gpio/gpio482/*
Now you can to use the command without superuser sudo
:
echo out > /sys/class/gpio/gpio480/direction
echo out > /sys/class/gpio/gpio481/direction
echo in > /sys/class/gpio/gpio482/direction
echo 1 > /sys/class/gpio/gpio480/value
echo 0 > /sys/class/gpio/gpio480/value
Now create a Python Script using the follow commands:
mkdir python_test
cd python_test
nano gpio_test.py
In the script, copy the follow code:
gpio_test.py
import os
import sys
import time
import subprocess
import multiprocessing
for i in range(0,10):
os.system('echo 1 > /sys/class/gpio/gpio492/value') # Turn on the led
time.sleep(1)
os.system('echo 0 > /sys/class/gpio/gpio492/value') # Turn off the led
time.sleep(1)
# also we can to read the state of a pin in case it is an input
gpio_in_pin = open('/sys/class/gpio/gpio493/value', 'r')
gpio_in = gpio_in_pin.read()
print('entrada = ', gpio_in)
if int(gpio_in) == 1:
os.system('echo 1 > /sys/class/gpio/gpio494/value')
else:
os.system('echo 0 > /sys/class/gpio/gpio494/value')
Finally, run the script:
python gpio_test.py
With this we can see how the Leds begin to blink for 20 seconds.
Code AutomationAlso, we can to generate a bash script to automate the permision, the upload of the overlay and the python script running, this file is called led_test.sh
echo "################################################"
echo " ------ Configuracion de salidas -----"
echo "################################################"
echo petalinux | sudo -S xmutil unloadapp # despues del echo va el password para el "sudo" y el comando>
echo petalinux | sudo -S xmutil loadapp kr260_gpio
echo petalinux | sudo -S chown petalinux:petalinux -R /sys/class/gpio/*
echo 439 > /sys/class/gpio/export
echo petalinux | sudo -S chown petalinux:petalinux -R /sys/class/gpio/gpio439/*
echo out > /sys/class/gpio/gpio439/direction
echo "################################################"
echo " ------ Inicio de prueba python ------ "
echo "################################################"
python gpio_test.py
echo "################################################"
echo " ------ Finalizacion de prueba ------ "
echo "################################################"
Pin MappingUnderstanding the pin mapping between the KR260 and the K26 SoM might seem a bit confusing. However, here is a quick guide that explains how you can effectively map the pinout while considering the connections between the KR260 modules and the KRIA SoM.
Refer to the schematic of the carrier board KR260, which illustrates the connections with various peripherals on the carrier board.
Our focus will be specifically on the connections of the Mezzanine ports.
Now, we can to look some peripherals like the PMOD connectors, the RPi and the User Leds.
- User Leds
- PMODs
- RPi Holder
Finally, we can use the constrains.xdc
for search and mapping the PL pins.
Then, we can to map the user leds pins as follow.
Map between peripheral and mezzanine connector.
Map between mezzanine connector and KRIA SoM
Comments