<strike id="kiyse"></strike>
  • <tr id="kiyse"></tr>
  • <strike id="kiyse"></strike><samp id="kiyse"><tbody id="kiyse"></tbody></samp>
    <strike id="kiyse"><s id="kiyse"></s></strike>
    <tr id="kiyse"></tr>
    <noframes id="kiyse"><code id="kiyse"></code></noframes>
    <th id="kiyse"></th>
    <samp id="kiyse"></samp>
  • <th id="kiyse"><s id="kiyse"></s></th>
  • 精簡ISA總線實現高速大容量數據采集

     2021-6-22     作者:Emtronix         

      《精簡ISA總線編程接 – Part2》介紹了英創工控主板ESM7000在DMA驅動的同步總線周期,在應用層可獲得:


    模式傳輸速率CPU負載
    MemCpy DMA同步總線讀8.67MB/s6.01%
    MemCpy DMA同步總線寫7.93MB/s5.71%


      本文在《精簡ISA總線編程 – Part2》的基礎上,進一步優化總線參數,總線同步時鐘BCLK從30MHz提高到40MHz,同時采用mmap存儲器映射方法在應用層讀取ISA總線采集的數據,使應用層的讀取速度達到16MB/s。


      為達到優化目標,首先需要預留1MB的DDR空間,作mmap使用。對客戶來說,就是配置特別的DTB文件(imx7d-esm7000-isa-v2.dtb)。ISA讀取數據的流程很簡單,基本是初始化mmap指針,把需要采集的長度等參數填到struct isa_transfer結構中,然后就是調用讀取函數。以下介紹核心的代碼。


      Mmap指針初始化代碼如下:


    void* mmap_base(unsigned long mem_phys, unsigned int size)
    {
        void *base = NULL;
        int fd;
        fd = open("/dev/mem", O_RDWR|O_SYNC);
        if(fd < 0) {
            printf("%s open failed %d\n", __func__, fd);
            goto cleanup;
        }
        /* mmap mem */
        base = mmap(
            NULL,                   //Any adddress in our space will do
            size,                   //Map length
            PROT_READ|PROT_WRITE,   //Enable reading & writting to mapped memory
            MAP_SHARED,             //Shared with other processes
            fd,                     //File to map
            mem_phys                //Offset to DMTimer peripheral
        );
        close(fd);
    cleanup:
        return base;
    }


      通過mmap驅動ISA數據的核心函數:


    int mmap_dma_mem_read(int fd, struct isa_transfer *tp, void* mmapbuf, unsigned int mmapbuf_size)
    {
        int rc = 0;
        unsigned int rem_len, mmap_len, pack_len;
        u_int8_t *sbuf[2], *cbuf;
        unsigned int sbuf_len, sbuf_count, sbuf_idx;
        u_int8_t dbuf[256];
        unsigned dbuf_len = sizeof(dbuf);
        struct pollfd fds[1];
        rem_len = tp->len;
        if(!rem_len) {
            rc = -EINVAL;
            goto cleanup;
        }
        // init variables
        sbuf[0] = (u_int8_t*)mmapbuf;
        sbuf_len = mmapbuf_size / 2;
        sbuf[1] = sbuf[0] + sbuf_len;
        sbuf_count = 0;
        sbuf_idx = 0;
        cbuf = sbuf[sbuf_idx];
        memset(fds, 0, sizeof(fds));
        fds[0].fd = fd;
        fds[0].events = POLLIN;
        // start dma process
        rc = ioctl(fd, ISA_IOCTL_START, (unsigned long)tp);
        if(rc < 0) {
            printf("%s start dma-mmap failed %d\n", __func__, rc);
            goto cleanup;
        }
        while(rem_len) {
            // wait data ready with timeout
            rc = poll(fds, 1, POLL_TIMEOUT);
            if(rc == -1) {
                perror("poll failed!\n");
                ioctl(fd, ISA_IOCTL_STOP, (unsigned long)tp);
                return rc;
            }
            else if(rc == 0) {
                // timeout
                continue;
            }
            // setup source buffer length
            mmap_len = sbuf_len;
            if(mmap_len > rem_len) {
                mmap_len = rem_len;
            }
            // get data from mmap buffer
            while(mmap_len) {
                pack_len = dbuf_len;
                if(pack_len > mmap_len) {
                    pack_len = mmap_len;
                }
                memcpy(dbuf, sbuf[sbuf_idx] + sbuf_count, pack_len);
                sbuf_count += pack_len;
                mmap_len -= pack_len;
                if(INFINITE != rem_len)
                    rem_len -= pack_len;
            }
            // switch to next mmap buffer
            sbuf_idx = (sbuf_idx + 1) % 2;
            sbuf_count = 0;
        }
        // well done
        rc = tp->len - rem_len;
    cleanup:
        return rc;
    }


      上面的代碼中fd是打開設備/dev/em_isa的文件句柄。


      應用層調用:


    #define MMAP_BASE_PHYS          0xBFF00000
    #define MMAP_SIZE               0x80000             //512KB
        struct isa_transfer t;
        double elapsed, data_rate;
        unsigned int data_length;
        void *mmapbuf;
        unsigned int mmapbuf_size;
    //………
            // get mmap buffer
            mmapbuf = mmap_base(MMAP_BASE_PHYS, MMAP_SIZE);
            if(!mmapbuf) {
                printf("failed to get mmap buffer\n");
                break;
            }
            printf("mmap range(0x%08x, 0x%x) => %p\n", MMAP_BASE_PHYS, MMAP_SIZE, mmapbuf);
            memset(&t, 0, sizeof(struct isa_transfer));
            t.rx_buf = (void*)MMAP_BASE_PHYS;
            t.offset = offset;
            t.len = count;
            rc = mmap_dma_mem_read(fd, &t, mmapbuf, MMAP_SIZE);
            if(rc < 0) {
                printf("mmap_dma_mem_read failed %d\n", rc);
                break;
            }
            data_length = rc;


      采用64MB數據長度,對上述代碼測試應用層數據:


    模式傳輸速率CPU負載
    MemCpy DMA同步總線讀16.06MB/s38.7%


      函數mmap_dma_mem_read是軟件啟動DMA執行同步總線讀周期,其基本的總線時序與《精簡ISA總線編程 – Part2》的時序圖是一致的,不同之處僅僅是總線同步時鐘BCLK的周期從過去的33ns縮短到25ns。客戶的FPGA應盡可能靠近主板CN2布局,以保證總線信號的完整性。


    精簡ISA總線應用于高速大容量數據采集.png

    DMA-MEM同步總線讀時序


      測試程序test_isa包括了完整的ISA總線的讀寫測試,其中執行mmap dma-mem讀操作的命令為:

      ./test_isa D1000000 4000


      命令中參數”D”表示mmap dma-mem讀操作,后續的是16進制的讀取字節數,0x1000000表示16MB,第二個參數是16進制的ISA總線地址偏移量,0x4000用于告訴驅動程序執行dma-mem操作,有關地址偏移量的說明可參考《精簡ISA總線編程 – Part1》


      對測試程序干興趣的客戶可來郵件(suppport@www.jsjflaw.com)索取test_isa的源代碼。目前在Linux平臺上的開發環境是多種多樣,推薦使用微軟開源的Visual Studio Code作為基本的IDE環境,通過簡單的配置就可把ESM7000的SDK編譯工具加入環境,就可Build應用程序。再通過NFS的掛載,就可直接在ESM7000目標板上跑客戶的應用程序了。

    四虎永久在线精品免费影视 | 久久99热久久99精品| 久久精品国产精品亚洲蜜月| 精品久久综合1区2区3区激情| 国产揄拍国内精品对白| 97超碰精品成人国产| 中文字幕亚洲精品无码| 日本精品www色| 99热门精品一区二区三区无码| 777国产偷窥盗摄精品品在线| 久久国产精品一国产精品| 久久精品国产精品国产精品污| 国语自产精品视频| 黑人大战亚洲人精品一区| 老司机精品免费视频| 国产精品亚洲综合专区片高清久久久 | 亚洲精品国产高清不卡在线| 青草热在线精品视频99app| 国产真实乱子伦精品视| 国产热re99久久6国产精品| 国产成人亚综合91精品首页 | 国产成人亚洲综合无码精品| 一本一本久久aa综合精品| 国产成人精品无码一区二区三区 | 91精品福利在线观看| 精品国内在视频线2019 | 日本尤物精品视频在线看| 国产成人亚洲精品| 亚洲中文字幕久久精品无码VA| 曰产无码久久久久久精品| 高清国产精品久久| 国产99视频精品免费视频7| 国产亚洲情侣久久精品| 亚洲精品无码永久在线观看| 久久精品亚洲男人的天堂| 人妻少妇精品一区二区三区| 久久国产精品久久精| www.精品国产| 国产麻豆精品精东影业av网站| 成人精品综合免费视频| 99久久精品国内|