FC2カウンター FPGAの部屋 acc_sensor に WDTimer を実装する
fc2ブログ

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

FPGAの部屋

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

acc_sensor に WDTimer を実装する

Xilinx 社の AXI IIC IP で ADXL355 を使用する”で作った ADXL355 (3軸加速度センサー)の I2C の回路に”Watchdog timer を Vitis HLS 2020.1 で実装する3(デバック修正)”の WDTimer を実装する。

Vivado 2020.1 の acc_sensor プロジェクトを示す。
acc_sensor_22_210103.png

このプロジェクトに WDTimer IP を追加した。
acc_sensor_23_210103.png

WDTimer_0 の rst_out はインバータを通して、 rst_ps7_0_100M IP の aux_rest_in に接続されている。
WDTimer のタイムアウト時間は 5.24 ms だった。今回は、 300 Hz なので、 3.333 ms 毎に加速度データを取得しているので、その間隔でアプリケーション・ソフトウェアでAXI_GPIO 経由で rst_in に 1 を入れて WDTimer をリセットする。

Address Editor 画面を示す。
acc_sensor_24_210103.png

論理合成、インプリメンテーション、ビットストリームの生成を行った。
Project Summary を示す。
acc_sensor_25_210103.png

ハードウェアをエクスポートして XSA ファイルを作った。

Vitis 2020.1 を起動した。
すでにプラットフォームとアプリケーション・プロジェクトは作ってあるので、アップデートした。
ソフトウェアも、WDTimer をリセットするために AXI GPIO に 1 を書き込む部分を追加した。
acc_sensor_26_210103.png

今の所、 I2C が止まっていないので、よく分からない。結局、I2C の途中で止まっていると、ADXL355 をリセットできないので、ダメそうだ。 ADXL355 はリセット端子が無いので、電源をON, OFF できればよいのだが。。。

acc_sensor_test.c を貼っておく。

// acc_sensor_test.c
// 2020/10/12 by marsee
//

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include "xtime_l.h"

#include "xparameters.h"

#define TX_FIFO_EMPTY   0x80
#define RX_FIFO_EMPTY   0x40
#define BB              0x04

void acc_sensor_init(volatile uint32_t *axi_iic_ad){
    axi_iic_ad[72] = 0x0F; // RX_FIFI_PIRQ
    axi_iic_ad[64] = 0x2; // Control Register (100h) reset tx fifo
    axi_iic_ad[64] = 0x1; // Control Register (100h) enable i2c
}

void idle_check(volatile uint32_t *axi_iic_ad){
    int32_t status_reg;
    int32_t check_bit;

    do{
        status_reg = axi_iic_ad[65]; // Status Register (104h))
        check_bit = status_reg & (TX_FIFO_EMPTY | RX_FIFO_EMPTY | BB);
    }while(check_bit != (TX_FIFO_EMPTY | RX_FIFO_EMPTY)) ;
}

void acc_sensor_write(volatile uint32_t *axi_iic_ad, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){
    idle_check(axi_iic_ad);
    axi_iic_ad[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    axi_iic_ad[66] = write_addr & 0xff;           // address
    axi_iic_ad[66] = 0x200 | (write_data & 0xff);      // data
}

uint32_t acc_sensor_read(volatile uint32_t *axi_iic_ad, uint32_t device_addr, uint32_t read_addr){
    int32_t status_reg, rx_fifo_empty;

    idle_check(axi_iic_ad);
    axi_iic_ad[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    axi_iic_ad[66] = read_addr & 0xff;  // address byte
    axi_iic_ad[66] = 0x100 | device_addr & 0xff; // Slave IIC Read Address, address is 0x108, i2c_tx_fifo, with repeat start
    axi_iic_ad[66] = 0x201;      // 1 byte data, NACK condition

    do{
        status_reg = axi_iic_ad[65];
        rx_fifo_empty = status_reg & RX_FIFO_EMPTY;
    }while(rx_fifo_empty); // Wait untill not RX_FIFO_EMPTY(Status Register (104h))

    int32_t read_data = axi_iic_ad[67] & 0xff; // Read Receive FIFO (10Ch)
    return(read_data);
}

int main(){
    volatile uint32_t *axi_iic_ad;
    volatile uint32_t *axi_gpio0_ad, *axi_gpio1_ad;
    int32_t dataX, dataY, dataZ;
    int32_t read_data, data_ready;
    XTime cur_time;

    axi_iic_ad = (volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR;
    axi_gpio0_ad = (volatile uint32_t *)XPAR_AXI_GPIO_0_BASEADDR;
    axi_gpio1_ad = (volatile uint32_t *)XPAR_AXI_GPIO_1_BASEADDR;

    acc_sensor_init(axi_iic_ad);

    acc_sensor_write(axi_iic_ad, 0x3a, 0x2f, 0x52); // Reset
    axi_gpio1_ad[0] = 1; // reported reset
    usleep(1000);

    acc_sensor_write(axi_iic_ad, 0x3a, 0x2c, 0x82); // I2C speed is Hi speed, +-4g

    acc_sensor_write(axi_iic_ad, 0x3a, 0x1e, 0x00); // OFFSET_X_H
    acc_sensor_write(axi_iic_ad, 0x3a, 0x1f, 0x00); // OFFSET_X_L
    acc_sensor_write(axi_iic_ad, 0x3a, 0x20, 0x00); // OFFSET_Y_H
    acc_sensor_write(axi_iic_ad, 0x3a, 0x21, 0x00); // OFFSET_Y_L
    acc_sensor_write(axi_iic_ad, 0x3a, 0x22, 0x00); // OFFSET_Z_H
    acc_sensor_write(axi_iic_ad, 0x3a, 0x23, 0x00); // OFFSET_Z_L

    acc_sensor_write(axi_iic_ad, 0x3a, 0x2d, 0x00); // stanby clear

    do{
        read_data = acc_sensor_read(axi_iic_ad, 0x3b, 0x04);
        data_ready = read_data & 0x01;
    }while(data_ready != 0x01);

    axi_gpio0_ad[2] = 1; // WDTimer enable

    //for(int i=0; i<10000; i++){
    while(1){
        dataX = acc_sensor_read(axi_iic_ad, 0x3b, 0x08) << 12; // XDATA3
        dataX |= (acc_sensor_read(axi_iic_ad, 0x3b, 0x09) << 4); // XDATA2
        dataX |= ((acc_sensor_read(axi_iic_ad, 0x3b, 0x0a) & 0xf0) >> 4); // XDATA1
        if(dataX & 0x80000) // Is the 19th bit 1?
            dataX |= 0xfff00000; // sign extension

        dataY = acc_sensor_read(axi_iic_ad, 0x3b, 0x0b) << 12; // YDATA3
        dataY |= (acc_sensor_read(axi_iic_ad, 0x3b, 0x0c) << 4); // YDATA2
        dataY |= ((acc_sensor_read(axi_iic_ad, 0x3b, 0x0d) & 0xf0) >> 4); // YDATA1
        if(dataY & 0x80000) // Is the 19th bit 1?
            dataY |= 0xfff00000; // sign extension

        dataZ = acc_sensor_read(axi_iic_ad, 0x3b, 0x0e) << 12; // ZDATA3
        dataZ |= (acc_sensor_read(axi_iic_ad, 0x3b, 0x0f) << 4); // ZDATA2
        dataZ |= ((acc_sensor_read(axi_iic_ad, 0x3b, 0x10) & 0xf0) >> 4); // ZDATA1
        if(dataZ & 0x80000) // Is the 19th bit 1?
            dataZ |= 0xfff00000; // sign extension

        XTime_GetTime(&cur_time);
        //printf("time = %lf ms, datax = %x, dataY = %x, dataZ = %x\n", (double)((long long int)cur_time)/335000.0, (int)dataX, (int)dataY, (int)dataZ);
        printf("%lf,%x,%x,%x,%x\n", (double)((long long int)cur_time)/335000.0, (int)dataX, (int)dataY, (int)dataZ, axi_gpio1_ad[0]);

        axi_gpio0_ad[0] = 1;
        axi_gpio0_ad[0] = 0;
        axi_gpio1_ad[0] = 0;

        // usleep(2434); // for 400 kHz
        usleep(1581); // for 200 kHz
    }

    return(0);
}


  1. 2021年01月03日 20:41 |
  2. FPGAを使用したシステム
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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