This is a quick and dirty howto. This howto describes how to use I2C modules (onboard and through PMOD connector) under embedded Linux.
I've chosen to build my own Linux distro based on Linux kernel source for MicroBlaze softcore and busybox project for the init RAM DISK.
My board is the Nexys4 DDR board. If you respect the following requirements for the HW design compatible with Linux, you can use Petalinux too.
HW Vivado requirements (according to Xilinx UG1144) design to boot Linux:
MicroBlaze with MMU support by selecting either Linux with MMU or Low-end Linux with MMU configuration template in the MicroBlaze configuration wizard.
External memory controller with at least 32 MB of memory.
Dual channel timer with interrupt connected.
UART with interrupt connected.
Ethernet with interrupt connected.
Note that all peripherals you use must be interrupt capable. For the UART peripheral, if you have not enabled interrupts, you have no Linux console outputs.
At this stage, for the Nexys4 DDR board, you can add the onboard i2C temperature sensor (ADT7420) that uses the AXI IIC IP block.
I've added a second external temperature sensor (PMOD TMP3) connected to PMOD JA pins of the Nexys4 DDR board.
I've chosen to connect SCL TMP3 pin to JA1 PMOD JA pin (C17 FPGA pin) and SDA MP3 pin to JA2 PMOD JA pin (D18 FPGA pin). You connect GND and 3V3 pins from PMOD JA connector to corresponding TMP3 pins. You have finally 4 pins to connect.
You obtain the Vivado design shown below. Notice that both AXI IIC IP blocks have interrupts connected for Linux compatibility.
For the TMP3 sensor, I have an external port named temp3_sensor. I've created a XDC file containing:
Copy the generated pl.dtsi file (under project_1/project_1.sdk/device_tree_bsp_0/ directory) into arch/microblaze/boot/dts/ Linux directory. Use the generated system-top.dts file (under project_1/project_1.sdk/device_tree_bsp_0/ directory) to create the xilinx.dts file into arch/microblaze/boot/dts/ Linux directory.
Be carefull with stdout options in the xilinx.dts file if you want Linux output enabled. Mine is:
Generate your init RAM Disk for root File sytem. I suppose that you can do this.
Generate your Linux kernel. I suppose that you can do this:
$ make ARCH=microblaze CROSS_COMPILE=microblazeel-xilinx-linux-gnu- simpleImage.xilinx -j 4
Program the FPGA device and download the simpleImage.xilinx file (kernel + init RAM Disk) under arch/microblaze/boot directory into RAM with the JTAG interface and finally execute.
That's all folks!
Ramdisk addr 0x00000000,
Compiled-in FDT at c03ad4f8
Linux version 4.14.0-00493-gb68293ad2c93-dirty (kadionik@ipcchip) (gcc version 8
setup_cpuinfo: initialising
setup_cpuinfo: Using full CPU PVR support
wt_msr_noirq
setup_memory: max_mapnr: 0x8000
setup_memory: min_low_pfn: 0x80000
setup_memory: max_low_pfn: 0x88000
setup_memory: max_pfn: 0x88000
Zone ranges:
DMA [mem 0x0000000080000000-0x0000000087ffffff]
Normal empty
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000080000000-0x0000000087ffffff]
Initmem setup node 0 [mem 0x0000000080000000-0x0000000087ffffff]
On node 0 totalpages: 32768
free_area_init_node: node 0, pgdat c0525af4, node_mem_map c07a2000
DMA zone: 256 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 32768 pages, LIFO batch:7
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0
Built 1 zonelists, mobility grouping on. Total pages: 32512
Kernel command line: console=ttyUL0,9600
PID hash table entries: 512 (order: -1, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 121948K/131072K available (3765K kernel code, 121K rwdata, 1312K rodata)
Kernel virtual memory layout:
* 0xffffe000..0xfffff000 : fixmap
* 0xffffe000..0xffffe000 : early ioremap
* 0xf0000000..0xffffe000 : vmalloc & ioremap
NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
irq-xilinx: /amba_pl/interrupt-controller@41200000: num_irq=5, edge=0x6
/amba_pl/timer@41c00000: irq=1
clocksource: xilinx_clocksource: mask: 0xffffffff max_cycles: 0xffffffff, max_is
xilinx_timer_shutdown
xilinx_timer_set_periodic
sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 21474836475ns
Calibrating delay loop... 49.15 BogoMIPS (lpj=245760)
pid_max: default: 4096 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
random: get_random_u32 called from bucket_table_alloc+0x2e4/0x35c with crng_ini0
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 191s
NET: Registered protocol family 16
clocksource: Switched to clocksource xilinx_clocksource
NET: Registered protocol family 2
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 1024 (order: 2, 20480 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 128 (order: 0, 6144 bytes)
UDP-Lite hash table entries: 128 (order: 0, 6144 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
random: fast init done
Skipping unavailable RESET gpio -2 (reset)
workingset: timestamp_bits=30 max_order=15 bucket_order=0
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
io scheduler mq-deadline registered
io scheduler kyber registered
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
40600000.serial: ttyUL0 at MMIO 0x40600000 (irq = 5, base_baud = 0) is a uartlie
console [ttyUL0] enabled
brd: module loaded
libphy: Fixed MDIO Bus: probed
xilinx_emaclite 40e00000.ethernet: Device Tree Probing
xilinx_emaclite 40e00000.ethernet: Failed to register mdio bus.
xilinx_emaclite 40e00000.ethernet: MAC address is now 00:0a:35:00:00:00
xilinx_emaclite 40e00000.ethernet: Xilinx EmacLite at 0x40E00000 mapped to 0xF02
i2c /dev entries driver
NET: Registered protocol family 17
Freeing unused kernel memory: 2296K
This architecture does not have kernel memory protection.
Hostname : nexys4ddr
Kernel release : Linux 4.14.0-00493-gb68293ad2c93-dirty
Kernel version : #120 Thu Dec 6 16:51:57 CET 2018
Please press Enter to activate this console.
nexys4ddr:/#
For the first I2C sensor (onboard ADT7420 sensor of the Nexys4 DDR board), we must use the /dev/i2c/0 (or /dev/i2c/i2c-0) character driver file (Major=89 minor=0).
For the second I2C sensor (external TCN75A PMOD TMP3 sensor), we must use the /dev/i2c/1 (or /dev/i2c/i2c-1) character driver file (Major=89 minor=1).
Question
kadionik
Hi all,
This is a quick and dirty howto. This howto describes how to use I2C modules (onboard and through PMOD connector) under embedded Linux.
I've chosen to build my own Linux distro based on Linux kernel source for MicroBlaze softcore and busybox project for the init RAM DISK.
My board is the Nexys4 DDR board. If you respect the following requirements for the HW design compatible with Linux, you can use Petalinux too.
HW Vivado requirements (according to Xilinx UG1144) design to boot Linux:
Note that all peripherals you use must be interrupt capable. For the UART peripheral, if you have not enabled interrupts, you have no Linux console outputs.
For the Nexys4 DDR, you can follow this online tutorial: https://reference.digilentinc.com/learn/programmable-logic/tutorials/nexys-4-ddr-getting-started-with-microblaze-servers/start
At this stage, for the Nexys4 DDR board, you can add the onboard i2C temperature sensor (ADT7420) that uses the AXI IIC IP block.
I've added a second external temperature sensor (PMOD TMP3) connected to PMOD JA pins of the Nexys4 DDR board.
I've chosen to connect SCL TMP3 pin to JA1 PMOD JA pin (C17 FPGA pin) and SDA MP3 pin to JA2 PMOD JA pin (D18 FPGA pin). You connect GND and 3V3 pins from PMOD JA connector to corresponding TMP3 pins. You have finally 4 pins to connect.
You obtain the Vivado design shown below. Notice that both AXI IIC IP blocks have interrupts connected for Linux compatibility.
For the TMP3 sensor, I have an external port named temp3_sensor. I've created a XDC file containing:
set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { eth_ref_clk }]; # Sch=eth_ref_clk set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { tmp3_sensor_scl_io }]; set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { tmp3_sensor_sda_io }];
You can see that:
Please respect notation: xxx external I2C port gives xxx_scl_io and xxx_sda_io signal names in the XDC file.
Generate .bit file. Launch Vivado SDK tool, install the device tree plugin and generate Device Tree files. You can follow this link: https://numato.com/kb/neso-microblaze-linux-run-linux-neso-artix-7-fpga-module/
Copy the generated pl.dtsi file (under project_1/project_1.sdk/device_tree_bsp_0/ directory) into arch/microblaze/boot/dts/ Linux directory. Use the generated system-top.dts file (under project_1/project_1.sdk/device_tree_bsp_0/ directory) to create the xilinx.dts file into arch/microblaze/boot/dts/ Linux directory.
Be carefull with stdout options in the xilinx.dts file if you want Linux output enabled. Mine is:
/dts-v1/; /include/ "pl.dtsi" / { chosen { bootargs = "console=ttyUL0,9600"; linux,stdout-path = &axi_uartlite_0; stdout-path = &axi_uartlite_0; }; aliases { ethernet0 = &axi_ethernetlite_0; serial0 = &axi_uartlite_0; i2c0 = &axi_iic_0; i2c1 = &axi_iic_1; }; memory { device_type = "memory"; reg = <0x80000000 0x8000000>; }; }; &axi_ethernetlite_0 { local-mac-address = [00 0a 35 00 00 00]; };
Generate your init RAM Disk for root File sytem. I suppose that you can do this.
Generate your Linux kernel. I suppose that you can do this:
$ make ARCH=microblaze CROSS_COMPILE=microblazeel-xilinx-linux-gnu- simpleImage.xilinx -j 4
Program the FPGA device and download the simpleImage.xilinx file (kernel + init RAM Disk) under arch/microblaze/boot directory into RAM with the JTAG interface and finally execute.
That's all folks!
Ramdisk addr 0x00000000, Compiled-in FDT at c03ad4f8 Linux version 4.14.0-00493-gb68293ad2c93-dirty (kadionik@ipcchip) (gcc version 8 setup_cpuinfo: initialising setup_cpuinfo: Using full CPU PVR support wt_msr_noirq setup_memory: max_mapnr: 0x8000 setup_memory: min_low_pfn: 0x80000 setup_memory: max_low_pfn: 0x88000 setup_memory: max_pfn: 0x88000 Zone ranges: DMA [mem 0x0000000080000000-0x0000000087ffffff] Normal empty Movable zone start for each node Early memory node ranges node 0: [mem 0x0000000080000000-0x0000000087ffffff] Initmem setup node 0 [mem 0x0000000080000000-0x0000000087ffffff] On node 0 totalpages: 32768 free_area_init_node: node 0, pgdat c0525af4, node_mem_map c07a2000 DMA zone: 256 pages used for memmap DMA zone: 0 pages reserved DMA zone: 32768 pages, LIFO batch:7 pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768 pcpu-alloc: [0] 0 Built 1 zonelists, mobility grouping on. Total pages: 32512 Kernel command line: console=ttyUL0,9600 PID hash table entries: 512 (order: -1, 2048 bytes) Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) Memory: 121948K/131072K available (3765K kernel code, 121K rwdata, 1312K rodata) Kernel virtual memory layout: * 0xffffe000..0xfffff000 : fixmap * 0xffffe000..0xffffe000 : early ioremap * 0xf0000000..0xffffe000 : vmalloc & ioremap NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0 irq-xilinx: /amba_pl/interrupt-controller@41200000: num_irq=5, edge=0x6 /amba_pl/timer@41c00000: irq=1 clocksource: xilinx_clocksource: mask: 0xffffffff max_cycles: 0xffffffff, max_is xilinx_timer_shutdown xilinx_timer_set_periodic sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 21474836475ns Calibrating delay loop... 49.15 BogoMIPS (lpj=245760) pid_max: default: 4096 minimum: 301 Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) random: get_random_u32 called from bucket_table_alloc+0x2e4/0x35c with crng_ini0 clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 191s NET: Registered protocol family 16 clocksource: Switched to clocksource xilinx_clocksource NET: Registered protocol family 2 TCP established hash table entries: 1024 (order: 0, 4096 bytes) TCP bind hash table entries: 1024 (order: 2, 20480 bytes) TCP: Hash tables configured (established 1024 bind 1024) UDP hash table entries: 128 (order: 0, 6144 bytes) UDP-Lite hash table entries: 128 (order: 0, 6144 bytes) NET: Registered protocol family 1 RPC: Registered named UNIX socket transport module. RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. random: fast init done Skipping unavailable RESET gpio -2 (reset) workingset: timestamp_bits=30 max_order=15 bucket_order=0 io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) io scheduler mq-deadline registered io scheduler kyber registered Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled 40600000.serial: ttyUL0 at MMIO 0x40600000 (irq = 5, base_baud = 0) is a uartlie console [ttyUL0] enabled brd: module loaded libphy: Fixed MDIO Bus: probed xilinx_emaclite 40e00000.ethernet: Device Tree Probing xilinx_emaclite 40e00000.ethernet: Failed to register mdio bus. xilinx_emaclite 40e00000.ethernet: MAC address is now 00:0a:35:00:00:00 xilinx_emaclite 40e00000.ethernet: Xilinx EmacLite at 0x40E00000 mapped to 0xF02 i2c /dev entries driver NET: Registered protocol family 17 Freeing unused kernel memory: 2296K This architecture does not have kernel memory protection. Hostname : nexys4ddr Kernel release : Linux 4.14.0-00493-gb68293ad2c93-dirty Kernel version : #120 Thu Dec 6 16:51:57 CET 2018 Please press Enter to activate this console. nexys4ddr:/#
For the first I2C sensor (onboard ADT7420 sensor of the Nexys4 DDR board), we must use the /dev/i2c/0 (or /dev/i2c/i2c-0) character driver file (Major=89 minor=0).
For the second I2C sensor (external TCN75A PMOD TMP3 sensor), we must use the /dev/i2c/1 (or /dev/i2c/i2c-1) character driver file (Major=89 minor=1).
nexys4ddr:/# i2cdetect -y 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- 4b -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- nexys4ddr:/# i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
You can now use the Linux API for reading the I2C sensors...
Pat.
Link to comment
Share on other sites
1 answer to this question
Recommended Posts
Archived
This topic is now archived and is closed to further replies.