HeroGian

Members
  • Content Count

    3
  • Joined

  • Last visited

About HeroGian

  • Rank
    Newbie

Recent Profile Visitors

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

  1. Hello, I'm writing a simple Vivado example in which I have a HLS IP that performs a memcpy in hardware. From a baremetal software I can pass a src and dst pointers and the IP can write the src memory into the dst memory range. This is the hardware design that I implemented: And this is a portion of the baremetal code: #define N 12 #define SRC_ADDR 0x10000000 #define DST_ADDR SRC_ADDR + N ... ... uint8_t *src = (uint8_t *)SRC_ADDR; uint8_t *dst = (uint8_t *)DST_ADDR; ... ... XCopymem XCopyMemInstance; XCopymem_Initialize(&XCopyMemInstance, 0); XCopymem_Set_dst(&XCopyMemInstance, dst); XCopymem_Set_src(&XCopyMemInstance, src); XCopymem_Set_bytes(&XCopyMemInstance, N); XCopymem_Start(&XCopyMemInstance); while(!XCopymem_IsDone(&XCopyMemInstance)); Xil_DCacheInvalidate(); and after the Xil_DCacheInvalidate I can correctly read the values written by the IP. The I am trying to port this software in Linux. I created a kernel image with PetaLinux 2018.1 and it works, but I have to invalidate the Data Cache as I did in baremetal. How can I implement this functionality in Linux Userspace? Maybe there is something like Xil_DCacheInvalidate? I tried with __clear_cache(), but seems not work. This is the code that I wrote: /* * Copyright (c) 2012 Xilinx, Inc. All rights reserved. * * Xilinx, Inc. * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. * */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <stdint.h> #include "xcopymem/xcopymem.h" #define N 12 #define SRC_ADDR 0x10000000 #define DST_ADDR SRC_ADDR + N int main() { size_t pagesize = sysconf(_SC_PAGE_SIZE); off_t page_base_src = (SRC_ADDR / pagesize) * pagesize; off_t page_base_dst = (DST_ADDR / pagesize) * pagesize; off_t page_offset_src = SRC_ADDR - page_base_src; off_t page_offset_dst = DST_ADDR - page_base_dst; int fd = open("/dev/mem", O_SYNC); uint8_t * src = mmap(NULL, page_offset_src + N, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, page_base_src); uint8_t * dst = mmap(NULL, page_offset_dst + N, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, page_base_dst); if (src == MAP_FAILED) { printf("Can't map src memory\n"); return -1; } if (dst == MAP_FAILED) { printf("Can't map src memory\n"); return -1; } for(int i = 0; i < N; ++i){ src[i] = i; } memset(dst, 0, N); printf("\nsrc =\n"); for(int i = 0; i < N; ++i) { printf("%X ", src[i]); } printf("\n"); printf("\ndst ( before memcpy ) =\n\n"); for(int i = 0; i < N; ++i) { printf("%X ", dst[i]); } printf("\n"); XCopymem XCopyMemInstance; XCopymem_Initialize(&XCopyMemInstance, "copyMem"); XCopymem_Set_dst(&XCopyMemInstance, dst); XCopymem_Set_src(&XCopyMemInstance, src); XCopymem_Set_bytes(&XCopyMemInstance, N); XCopymem_Start(&XCopyMemInstance); while(!XCopymem_IsDone(&XCopyMemInstance)); __clear_cache(dst, dst + N); printf("\ndst ( after memcpy and clear cache ) =\n\n"); for(int i = 0; i < N; ++i) { printf("%X ", dst[i]); } printf("\n"); close(fd); return 0; } thank you
  2. hello, I'm trying to port a baremetal design, in which I have a simple HLS IP that performs vector additions, that triggers an interrupt when it finishes its computation. After the bitstream generation I exported the hdf and I generated the Petalinux project based on it, in which I specified "generic-uio" in the compatible field as follows: amba_pl: amba_pl { #address-cells = ; #size-cells = ; compatible = "simple-bus"; ranges ; &irq_gen_0: irq_gen@43c00000 { clock-names = "ap_clk"; clocks = ; compatible = "generic-uio"; interrupt-names = "interrupt"; interrupt-parent = ; interrupts = ; reg = ; xlnx,s-axi-axilites-addr-width = ; xlnx,s-axi-axilites-data-width = ; }; }; Then I created an appropriate bootargs configuration and placed inside the uEnv.txt file: bootargs=console=ttyPS0,115200 earlyprintk uio_pdrv_genirq.of_id=generic-uio and I enabled the following modules: CONFIG_UIO=y CONFIG_UIO_PDRV_GENIRQ=M CONFIG_UIO_DMEM_GENIRQ=M then I create a simple application that runs the initialization drivers of the IP and wait for interrupts: int main() { int a ; int b ; for(int i = 0; i < N; i) { a = i; b = i; } XIrq_gen HLSdevice; XIrq_gen_Initialize(&HLSdevice, "irq_gen"); XIrq_gen_Write_a_Words(&HLSdevice, 0, a, N); XIrq_gen_Write_b_Words(&HLSdevice, 0, b, N); int uioFd = open(UIO_DEVICE, O_RDWR); if( uioFd < 0) { fprintf(stderr, "Cannot open %s: %s ", UIO_DEVICE, strerror(errno)); return -1; } volatile uint32_t* counters = mmap(NULL, MMAP_SIZE, PROT_READ, MAP_SHARED, uioFd, 0); if(counters == MAP_FAILED) { fprintf(stderr, "Cannot mmap: %s ", strerror(errno)); close(uioFd); return -1; } uint32_t intInfo; ssize_t readSize; for(int i = 0; i < 10; i) { XIrq_gen_Start(&HLSdevice); printf("XIrq_gen_Start() "); intInfo = 1; if(write(uioFd, &intInfo, sizeof(intInfo)) < 0) { fprintf(stderr, "Cannot acknowledge uio device interrupt: %s ", strerror(errno)); break; } printf("write() "); // Wait for interrupt readSize = read(uioFd, &intInfo, sizeof(intInfo)); if(readSize < 0) { fprintf(stderr, "Cannot wait for uio device interrupt: %s ", strerror(errno)); break; } // Display counter value printf("We got %lu interrupts, counter value: 0xx ", intInfo, counters ); } XIrq_gen_Release(&HLSdevice); return 0; } The program blocks on the read call and does not receive any interrupts. Under /proc/interrupts I can see my HLS IP, but the interrupt counter is still zero: root@InterruptLinux:~# cat /proc/interrupts CPU0 CPU1 16: 1 0 GIC-0 27 Edge gt 17: 0 0 GIC-0 43 Level ttc_clockevent 18: 2998 **** GIC-0 29 Edge twd 19: 0 0 GIC-0 37 Level arm-pmu 20: 0 0 GIC-0 38 Level arm-pmu 21: 43 0 GIC-0 39 Level f8007100.adc 24: 0 0 GIC-0 35 Level f800c000.ocmc 25: 726 0 GIC-0 82 Level xuartps 26: 11 0 GIC-0 51 Level e000d000.spi 27: 534 0 GIC-0 54 Level eth0 28: 248 0 GIC-0 56 Level mmc0 29: 0 0 GIC-0 45 Level f8003000.dmac 30: 0 0 GIC-0 46 Level f8003000.dmac 31: 0 0 GIC-0 47 Level f8003000.dmac 32: 0 0 GIC-0 48 Level f8003000.dmac 33: 0 0 GIC-0 49 Level f8003000.dmac 34: 0 0 GIC-0 72 Level f8003000.dmac 35: 0 0 GIC-0 73 Level f8003000.dmac 36: 0 0 GIC-0 74 Level f8003000.dmac 37: 0 0 GIC-0 75 Level f8003000.dmac 38: 0 0 GIC-0 40 Level f8007000.devcfg 45: 0 0 GIC-0 41 Edge f8005000.watchdog 46: 0 0 GIC-0 61 Level irq_gen IPI1: 0 0 Timer broadcast interrupts IPI2: 844 1294 Rescheduling interrupts IPI3: 1 2 Function call interrupts IPI4: 0 0 CPU stop interrupts IPI5: 0 0 IRQ work interrupts IPI6: 0 0 completion interrupts Err: 0 could you please give me some hints? thanks