FC2カウンター FPGAの部屋 ZYBO Z7 の Debian LInux からパソコンへ TCP/IP で 3.333 ms 毎にデータを送る
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

ZYBO Z7 の Debian LInux からパソコンへ TCP/IP で 3.333 ms 毎にデータを送る

ZYBO Z7 の Debian LInux からパソコンへ TCP/IP でデータを送る”と”ikwzm さんの Debian Linux 上で axi timer の割り込みを試す”を組み合わせて、ZYBO Z7 の Debian LInux からパソコンへ TCP/IP で 3.333 ms 毎にデータを送ってみよう。

サーバー側のアプリケーション・ソフトウェアを tcp_timer_test.c として新規作成した。

// tcp_timer_test.c
// 2023/02/14 by marsee
// Reference URL:https://github.com/ikwzm/ZYBO_UIO_IRQ_SAMPLE/blob/master/c-sample/sample1.c
// 何回もクライアントと接続できるサーバ例(エラー処理付)のコードを引用した。
// https://www.geekpage.jp/programming/linux-network/tcp-3.php

#include        <stdio.h>
#include        <stdint.h>
#include        <stdlib.h>
#include        <fcntl.h>
#include        <string.h>
#include        <time.h>
#include        <sys/time.h>
#include        <poll.h>
#include        <sys/types.h>
#include        <sys/mman.h>
#include        <sys/socket.h>
#include        <netinet/in.h>
#include        <string.h>


#define ENABLE_ALL_TIMERS               (0x1<<10)
#define ENABLE_PULSE_WIDTH_MODULATION   (0x1<<9)
#define TIMER_INTERRUPT                 (0x1<<8)
#define ENABLE_TIMER                    (0x1<<7)
#define ENABLE_INTERRUPT                (0x1<<6)
#define LOAD_TIMER                      (0x1<<5)
#define AUTO_RELOAD_HOLD_TIMER          (0x1<<4)
#define ENABLE_EXT_CAPTURE_TRIG         (0x1<<3)
#define ENABLE_EXT_GENERATE_SIG         (0x1<<2)
#define DOWN_UP_COUNT_TIMER             (0x1<<1)
#define TIMER_MODE_CAP_GENE             (0x1)

int uio_irq_on(int uio_fd)
{
    unsigned int  irq_on = 1;
    write(uio_fd, &irq_on, sizeof(irq_on));
}

int uio_wait_irq(int uio_fd)
{
    unsigned int  count = 0;
    return read(uio_fd, &count,  sizeof(count));
}

void main()
{
    int            uio0_fd, uio1_fd;
    uint32_t    *axi_gpio, *axi_timer;
    static uint32_t led_stat = 0;
    int sock0;
    struct sockaddr_in addr;
    struct sockaddr_in client;
    int len;
    int sock;
    int n;
    struct tm *time_st;
    struct timeval myTime;
    char buf[500];


    if((uio0_fd = open("/dev/uio0", O_RDWR)) == -1) {
        printf("Can not open /dev/uio0\n");
        exit(1);
    }
    axi_gpio = (uint32_t*)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, uio0_fd, 0);
    
    if((uio1_fd = open("/dev/uio1", O_RDWR)) == -1) {
        printf("Can not open /dev/uio1\n");
        exit(1);
    }
    axi_timer = (uint32_t*)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, uio1_fd, 0);
    
    // axi_timer_0 -> Timer0
    axi_timer[1] = 333333; // TLR0, 100 MHz = 3.33333 ms
    axi_timer[0] = LOAD_TIMER; // TCR0, ENALL and LOAD0 = 1
    axi_timer[0] = TIMER_INTERRUPT | ENABLE_TIMER | ENABLE_INTERRUPT | AUTO_RELOAD_HOLD_TIMER | DOWN_UP_COUNT_TIMER; // timer interrupt clear
    
    // network settings
    sock0 = socket(AF_INET, SOCK_STREAM, 0);
    if (sock0 < 0) {
     perror("socket");
     return 1;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock0, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
     perror("bind");
     return 1;
    }

    if (listen(sock0, 5) != 0) {
     perror("listen");
     return 1;
    }
    
    len = sizeof(client);
    sock = accept(sock0, (struct sockaddr *)&client, &len);
    if (sock < 0) {
        perror("accept");
    }
    for(int i=0; i<100; i++){
        if(uio_irq_on(uio1_fd) == -1){
            fprintf(stderr, "uio_irq_on error\n");
            break;
        }
        if(uio_wait_irq(uio1_fd) == -1){
            fprintf(stderr, "uio_wait_irq error\n");
            break;
        }
        
        axi_timer[0] = TIMER_INTERRUPT | ENABLE_TIMER | ENABLE_INTERRUPT | AUTO_RELOAD_HOLD_TIMER | DOWN_UP_COUNT_TIMER; // timer interrupt clear
        
        gettimeofday(&myTime, NULL);
        sprintf(buf, "36066078,140059917,54448,1,19,-51,0,1,-36,-57,0,1,%07.3f,ffdee,fd2fe,f526,fe4df,ffa01,f7a8,ffe09,ffcd8,f8d6,ffee1,ffdd6,f8ec,e6b,ff0eb,f8e3,fee1a,1e19,f8ac,ff3a4,fcf05,f464,bd3,ffe69,f8d4,967,ff841,f7e2,9658,178f,f4c8,0,a\n", (float)myTime.tv_usec/1000.0);
        n = write(sock, buf, strlen(buf));
        if (n < 1) {
            perror("write");
            break;
        }
        usleep(1000); // wait 1 ms
    }
    close(uio0_fd);
    close(uio1_fd);
    close(sock);
    close(sock0);
}


アプリケーション側の tcp_client.c はそのまま使用する。

tcp_timer_test.c をコンパイルした。
gcc -o tcp_timer_test tcp_timer_test.c
tcp_timer_test 実行形式ファイルが生成された。

デバイスツリーは”ikwzm さんの Debian Linux 上で axi timer の割り込みを試す”のデバイスツリーがそのまま使用できる。
ZYBO Z7-20 上の Debian Linux で ~/examples/timer_test ディレクトリに移動して、timer_test をロードする。
sudo dtbocfg.rb -i --dts devicetree.dts timer test

uio の権限を 666 に変更してユーザーもオープンできるようにする。
sudo chmod 666 /dev/uio*

ZYBO Z7-20 上の Debian Linux でサーバー側ソフトウェアの tcp_timer_test を実行する。
./tcp_timer_test
TCPsoft_3_230214.png

パソコンの Windows 10 の WSL2 でクライアント側のソフトウェアを実行する。
./tcp_client
するとサーバー側から受信したデータが表示された。
TCPsoft_5_230214.png

大体、3.33 ms に間隔になっている。
  1. 2023年02月18日 04:22 |
  2. FPGAを使用したシステム
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/5856-698f707b
この記事にトラックバックする(FC2ブログユーザー)