kadionik

Members
  • Content Count

    6
  • Joined

  • Last visited

About kadionik

  • Rank
    Newbie

Profile Information

  • Location
    ENSEIRB-MATMECA, Bordeaux, France

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Please find enclosed source files for reading the onboard I2C temperature sensor (ADT7420) of the Nexys4 DDR board under Linux. For cross compiling: make CC=microblazeel-xilinx-linux-gnu-gcc -f Makefile I'm using the gcc cross compiler from Vivado 2016.3 SDK. Pat. Makefile libi2c.c libi2c.h main.c
  2. 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: 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. 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: tmp3_sensor_scl_io signal is for SCL I2C signal. tmp3_sensor_sda_io signal is for SDA I2C signal 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.
  3. kadionik

    I2C PMOD access under Linux

    OK. With my first design based on the PMOD TMP3 IP from Digilent's vivado_library, I have in my Device Tree: PmodTMP3_0: PmodTMP3@40900000 { compatible = "xlnx,PmodTMP3-1.0"; interrupt-names = "I2C_Interrupt"; interrupt-parent = <&microblaze_0_axi_intc>; interrupts = <4 2>; reg = <0x40900000 0x1000>; And I have in my IO Vivado report file: | C14 | temp_sensor_scl_io | High Range | IO_L1N_T0_AD0N_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | C15 | temp_sensor_sda_io | High Range | IO_L12N_T1_MRCC_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | C17 | ja_pin1_io | High Range | IO_L20N_T3_A19_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | D17 | ja_pin7_io | High Range | IO_L16N_T2_A27_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | D18 | ja_pin2_io | High Range | IO_L21N_T3_DQS_A18_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | E17 | ja_pin8_io | High Range | IO_L16P_T2_A28_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | E18 | ja_pin3_io | High Range | IO_L21P_T3_DQS_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | F18 | ja_pin9_io | High Range | IO_L22N_T3_A16_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | G17 | ja_pin4_io | High Range | IO_L18N_T2_A23_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | | G18 | ja_pin10_io | High Range | IO_L22P_T3_A17_15 | BIDIR | LVCMOS33 | 15 | 12 | SLOW | | FP_VTT_50 | | FIXED | | | | NONE | | | | Pins are considered as GPIO pins and no as SCL and SDA signals. In this case, using MOD TMP3 IP from Digilent's vivado_library is well sweeted to bare-metal programming and not to Linux programming.We can see that for the onboard sensor, we have temp_sensor_scl_io temp_sensor_sda_io signals corresponding to I2C SCL and SDA signals. What's what I want! With, the second design based on the AXI IIC IP, the Device Tree is now: axi_iic_1: i2c@40810000 { #address-cells = <1>; #size-cells = <0>; clock-frequency = <100000000>; clocks = <&clk_bus_0>; compatible = "xlnx,xps-iic-2.00.a"; interrupt-names = "iic2intc_irpt"; interrupt-parent = <&microblaze_0_axi_intc>; interrupts = <4 2>; reg = <0x40810000 0x10000>; }; The second design with the AXI IIC IP is the solution for Linux. The Linux driver used existing one and is i2c-xiic.c. You have just to add XDC file for manual ouput SCL and SDA signal routing from AXII IIC outputs to PMOD connector of your board. I'll make a tutorial. Pat.
  4. kadionik

    I2C PMOD access under Linux

    Eureka! It works with the second solution: instanciate a IIC ´╗┐AXI IP, route SCL and SDA signals to 2 pins from the PMOD JA connector and connect with wires to the TMP3 sensor. I was confused with the onboard sensor that worked directly and driven by the Xilinx's I2C Linux driver (file drivers/i2c/busses/i2c-xiic.c). I guessed that the AXI IIC IP worked as a I2C passthrough device but with help of PG090 AXI IIC Bus Interface manual (https://www.xilinx.com/products/intellectual-property/axi_iic.html), I saw It's just a gateway and you have to drive many registers. That's what does the i2c-xiic.c Linux driver. With the driver that drives the registers of the AXI IIC IP, it's easy to use the Linux API (open(), close(), read(), write(), ioctl()). For the first I2C sensor, we must use the /dev/i2c/0 character driver file (Major=89 minor=0). I've enabled I2C debugging in the Linux kernel and found that a second I2C interface was detected for my second AXI IIC IP. So I have created a second character driver file /dev/i2c/1 (Major=89, minor=1) and I have now: 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: -- -- -- -- -- -- -- -- nexys4ddr:/# I2C Id=0x4b: ADT7420 temperature onboard sensor of the Nexys4 DDR board. I2C Id=0x48: TCN75A PMOD TMP3 temperature sensor. With 2 Linux programs, I can read now temperature: nexys4ddr:/# adt7420 TEMP=31.2 oC nexys4ddr:/# tcn75a TEMP=25.00 oC nexys4ddr:/# Everything is ok now. I'll write a howto in a future post. I'll analyze my first design with the PMOD TMP3 IP from Digilent's vivado_library too. Cheers. Pat.
  5. kadionik

    I2C PMOD access under Linux

    Hi Ciprian, Thank you for your response. I agree with you. In the first case, with the TMP3 IP with the Digilent's vivado_library, what is the connection between the PMOD A pins from the Nexyx4 DDR board and the TMP3 pins? The TMP3 doesn't respect the PMOD connector. To be clearer, which pins between JA1, JA2, JA3, JA4, JA7, JA8, JA9, JA10 from the PMOD A connector must I use to connect to SCL and SDA pins of the TMP3 sensor? I'm trying meanwhile the second solution. Cheers. Pat.
  6. kadionik

    I2C PMOD access under Linux

    Hi all, I've built with the Nexyx4 DDR board a system running Linux. In my running HW design, I've added the onboard temperature sensor of the board and the PMOD A connector to connect a I2C TMP3 temperature sensor. The HW interface for the onboard temperature sensor is the AXI IIC interface. For the TMP3 sensor with the Digilent's vivado library (as explained in: https://reference.digilentinc.com/learn/programmable-logic/tutorials/pmod-ips/start), it's the AXI LITE IIC interface. With the Linux I2C tools, I see the onboard sensor: nexys4ddr:/# uname -r 4.14.0-00493-gb68293ad2c93-dirty 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: -- -- -- -- -- -- -- -- And I can read temperature with the Linux I2C API: nexys4ddr:/# tsttemp TEMP=29.2 oC nexys4ddr:/# But I don't see the I2C TMP3 sensor. My questions are: - The vivado TMP3 instance has a I2C interface (AXI LITE IIC). Can I use the Linux I2C API? If yes, on the PMOD ja port, what are the pins of the connector corresponding to SCL, SDA (easy for ground and 3V3 ;-)? I didn't find this information in the Digilent's vivado library. - If I I can't use the Linux I2C API, I must generate by hand and by software the SCL and SDA signals and what is the role of AXI LITE IIC interface? In this case, would it better to use directly the IIC AXI interface as with the onboard sensor and precise after in a XDC file connexions between to the PMOD A port and TMP3 sensor? Thank you for your help. Pat.