激情综合丁香-激情综合六月-激情综合婷婷亚洲图片-激情综合图区-激情综合网五月

精簡(jiǎn)ISA總線實(shí)現(xiàn)高速大容量數(shù)據(jù)采集

 2021-6-22     作者:Emtronix         

  《精簡(jiǎn)ISA總線編程接 – Part2》介紹了英創(chuàng)工控主板ESM7000在DMA驅(qū)動(dòng)的同步總線周期,在應(yīng)用層可獲得:


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


  本文在《精簡(jiǎn)ISA總線編程 – Part2》的基礎(chǔ)上,進(jìn)一步優(yōu)化總線參數(shù),總線同步時(shí)鐘BCLK從30MHz提高到40MHz,同時(shí)采用mmap存儲(chǔ)器映射方法在應(yīng)用層讀取ISA總線采集的數(shù)據(jù),使應(yīng)用層的讀取速度達(dá)到16MB/s。


  為達(dá)到優(yōu)化目標(biāo),首先需要預(yù)留1MB的DDR空間,作mmap使用。對(duì)客戶來說,就是配置特別的DTB文件(imx7d-esm7000-isa-v2.dtb)。ISA讀取數(shù)據(jù)的流程很簡(jiǎn)單,基本是初始化mmap指針,把需要采集的長(zhǎng)度等參數(shù)填到struct isa_transfer結(jié)構(gòu)中,然后就是調(diào)用讀取函數(shù)。以下介紹核心的代碼。


  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驅(qū)動(dòng)ISA數(shù)據(jù)的核心函數(shù):


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是打開設(shè)備/dev/em_isa的文件句柄。


  應(yīng)用層調(diào)用:


#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數(shù)據(jù)長(zhǎng)度,對(duì)上述代碼測(cè)試應(yīng)用層數(shù)據(jù):


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


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


精簡(jiǎn)ISA總線應(yīng)用于高速大容量數(shù)據(jù)采集.png

DMA-MEM同步總線讀時(shí)序


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

  ./test_isa D1000000 4000


  命令中參數(shù)”D”表示mmap dma-mem讀操作,后續(xù)的是16進(jìn)制的讀取字節(jié)數(shù),0x1000000表示16MB,第二個(gè)參數(shù)是16進(jìn)制的ISA總線地址偏移量,0x4000用于告訴驅(qū)動(dòng)程序執(zhí)行dma-mem操作,有關(guān)地址偏移量的說明可參考《精簡(jiǎn)ISA總線編程 – Part1》


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

主站蜘蛛池模板: 国产精品尤物在线| 中文字幕2022永久在线| 视频在线二区| 久久综合一区二区三区| 九九黄色大片| 成人久久久观看免费毛片| 国产精品视频一区二区噜噜| 国产日韩精品欧美一区喷水| 中国人免费的片| 中文一级毛片| 欧美成人免费在线视频| 精品一区二区三区在线观看视频| 日韩精品一区二区三区小说| 三级视频欧美| 亚洲综合久久久| 国产亚洲精品国产一区| 91久久网| 麻豆视频观看| 亚洲小younv另类| 女人被男人狂躁视频免费| 伊人99综合| 国产成人深夜福利短视频99| a久久| 麻豆网站在线看| 日韩1区2区3区| 真不卡网站| 91桃子| 无遮挡一级毛片呦女视频| 亚洲精品国产精品国自产| 欧美国产激情二区三区| 国产大片91精品免费观看不卡 | 日本三级黄色网址| 免费观看国产精品| 国产免费专区| 黄色一级a毛片| 国产成人精选视频69堂| 欧美视频在线观看免费精品欧美视频| 1024精品| 人与牲动交bbbbxxxx| 久久99精品国产免费观看| 四库影库免费永久在线|