FC2カウンター FPGAの部屋 axi_timer を使う 3 (割り込みを使用する)
fc2ブログ

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

FPGAの部屋

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

axi_timer を使う 3 (割り込みを使用する)

ikwzm さんの FPGA-SoC-Linux を ZYBO Z7-20 で起動して、axi_timer を使用したビットストリームを使用して、axi_timer を割り込みで使用したが、”axi_timerを使う2(割り込みを使用した)”のコードを参考に Debian Linux 上でアプリケーションを作成してもうまく行かなかった。

なお、axi timer については、”PG079 - AXI Timer v2.0 Product Guide (PG079) (v2.0)”を参照した。

どのような現象だったかと言うと、どんどん割り込みが掛かってしまった。割り込みした後の axi timer での割り込み信号の解除ができていなかった。System ILA で見ると、最初の設定からTCSR0の”T0INT”を 1 にしておかないと、最初からタイマー割込みが入ってしまう。

解決策は、”PG079 - AXI Timer v2.0 Product Guide (PG079) (v2.0)”の 13 ページの”Control/Status Register 0 (TCSR0)”の”T0INT”を 1 にしていなかったためだった。
割り込みの度に”Control/Status Register 0 (TCSR0)”の”T0INT”を 1 にして割り込みを解除する必要があった。
GPIO を使用して 0.5 秒ことに LED の点灯/消灯を繰り返すソフトウェアを示す。

// timer_test.c
// 2023/02/08 by marsee
// Reference URL:https://github.com/ikwzm/ZYBO_UIO_IRQ_SAMPLE/blob/master/c-sample/sample1.c

#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>

#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;

    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] = 0x02FAF080; // TLR0, Decimal = 50,000,000, 100 MHz = 0.5sec
    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
    
    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
        
        led_stat ^= 0xf;
        axi_gpio[0] = led_stat;
    }
    close(uio0_fd);
    close(uio1_fd);
}

  1. 2023年02月14日 04:15 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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