Niosにタイマー(Internal Timer Intel FPGA IP)を実装してみる ソフトウェア編

FPGA

Niosにタイマーを実装するためのソフトウェアについてまとめてみました。

ハードウェアはこちらをご参照ください。

今回も使用するFPGAはDE0-Nanoボードです。

スポンサーリンク

Nios II Software Build Tools for Eclipseで新規プロジェクトの作成

ハードウェア編の記事では、Quartusのプロジェクトをコピーしましたが、Eclipseのプロジェクトまではコピーされませんでした。

そのため、ちょっと面倒でしたが、イチからEclipseのプロジェクトを新規に作成しました。

作成方法は以下の過去記事を参考にしてください。

上の過去記事でプロジェクトを新規作成した後、soft_test_bspを右クリックし、Nios II -> BSP Editorを選択します。

すると、以下の画面が表示されます。

この中のsys_clk_timerの項目を見ると、Platform Designerで追加したInternal Timer Intel FPGA IPの名前が表示されていると思います。

ソースコード

続いてソースコードの作成です。

作成したソースコードは以下です。

#include "sys/alt_stdio.h"
#include "system.h"
#include <stdio.h>
#include <string.h>

#include "altera_avalon_uart_regs.h"
#include "sys/alt_irq.h"

#include "sys/alt_alarm.h"
#include "alt_types.h"


unsigned char ReadData;

int Count;

alt_u32	Alarm_Int(void* context)
{
	Count++;

	return	1;
}

void uart_irq_handler()
{

	ReadData = IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);

}

int main()
{
	int i=0;
	int reg;
	int context_uart1;
	unsigned char buf;
	unsigned char led_data=0;

	static alt_alarm	Alarm;

	alt_printf("Hello World !! \n");

	//LED OFF
	*(volatile unsigned char *) LED_OUTPUT_BASE = 0x00;


	alt_ic_isr_register(UART_0_IRQ_INTERRUPT_CONTROLLER_ID, UART_0_IRQ,uart_irq_handler,&context_uart1,0x0 );
	alt_ic_irq_enable(UART_0_IRQ_INTERRUPT_CONTROLLER_ID, UART_0_IRQ);

	alt_alarm_start(&Alarm,1,Alarm_Int,NULL);


	buf = 0;
	Count = 0;

   while(1){

	   //Timer 10ms
	   if(Count >= 50){
		   Count = 0;
		   led_data = ~led_data;
		   *(volatile unsigned char *) LED_OUTPUT_BASE = led_data;
	   }

	   //SW Input
	   reg = *(volatile unsigned char *) SW_INPUT_BASE;

	   if(buf != ReadData){
		   buf = ReadData;

		   switch(buf){
	   	   	   case '1':	//LED1
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x01;
	   	   		   Send_LED(buf);
	   	   		   break;

	   	   	   case '2':	//LED2
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x02;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '3':	//LED3
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x04;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '4':	//LED4
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x08;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '5':	//LED5
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x10;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '6':	//LED6
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x20;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '7':	//LED7
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x40;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '8':	//LED8
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x80;
	   	   		   Send_LED(buf);
	   			   break;

		   }

	   }


   }

   return (0);
}

void Send_LED(unsigned char buf)
{
	unsigned char LED[] = {'L','E','D'};
	int i;
	unsigned int rdy;

	for(i=0;i<sizeof(LED);i++){

		rdy = 0;

		IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE, LED[i]);

		while(1){
			rdy = IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE) & ALTERA_AVALON_UART_STATUS_TRDY_MSK;
			if(rdy)
				break;
		}

	}

	IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE, buf);

}

シリアル通信用のソースコードにタイマーを追加したので、ごちゃごちゃしていますが、タイマー用に追加したソースコードは以下です。

#include "sys/alt_alarm.h"
#include "alt_types.h"

int Count;

alt_u32	Alarm_Int(void* context)
{
	Count++;

	return	1;
}
   unsigned char led_data=0;

	static alt_alarm	Alarm;

	alt_alarm_start(&Alarm,1,Alarm_Int,NULL);

	Count = 0;

   while(1){

	   //Timer 10ms
	   if(Count >= 50){
		   Count = 0;
		   led_data = ~led_data;
		   *(volatile unsigned char *) LED_OUTPUT_BASE = led_data;
	   }
  }

作成したのは10msタイマーなので、10msごとにAlarm_Int関数が呼ばれます。この関数が呼ばれたら、Countをインクリメントしています。

そして、main関数のwhileの中で、Countが50以上になったら、変数led_dataを反転させて、DE0-Nano上のLEDをON/OFFさせています。

10msタイマーで、Countが50なので、500msごとにLEDを点滅させるようにしました。

実行結果

実行した結果、LEDは点滅しました。

ただ、測定器がないので、本当に500msで点滅していたかは不明です。

目で見た感じではちゃんと動いていそうでしたので、一応は期待した結果は得られました。

まとめ

シリアル通信に続いて、タイマーもNiosに実装できました。

一応、期待通りに動いていますが、本当にこれで正しいのかという不安はちょっとあります。。。

Terasic DE0-NANO開発ボード 【P0082】

新品価格
¥14,520から
(2020/7/8 23:36時点)

タイトルとURLをコピーしました