2020年6月28日日曜日

FreeRTOS v10.3.1: NiosII 用デモを DE0-Nano + Quartus/NiosII EDS v18.1 で動作させる

 

 
FreeRTOS.org からリリースされている Demo Example の中に、Intel FPGA / NiosII 向け Example があります(FreeRTOS/Demo/NiosII_CycloneIII_DBC3C40_GCC/)。

生憎、この Example は非常に古いため、そのままでは最新の NiosII EDS では動作しません。

そこで、DE0-Nano で(とりあえず)動作させる手順を、以下に纏めましたので、ご参考までに、ご紹介します。
 
 
 
※FreeRTOS.org 提供のNiosII向け Exampleコード「全体」に対して、詳細な動作検証までは行っておりませんので、その点はご了承ください。

* FreeRTOS.org:  オープンソースの RTOS https://freertos.org/
* FreeRTOS v10.3 コード(含 Examle): Github, FreeRTOS donwload v10.3
* NiosII 向け Example: FreeRTOS/Demo/NiosII_CycloneIII_DBC3C40_GCC/
* DE0-Nano:  Terasic社製 Cyclone IV 低価格評価ボード  
* Intel Quartus Prime / NiosII EDS: 今回は、v18.1 を使用


※1:モチベーション:
手持ちの低価格評価ボード DE0-Nano を使用して、最小限の工数で、一先ず、FreeRTOS を動かしてみたい。

※2:CPU 及び Cyclone IV 上のハードウェア(HW):
CPU: NiosII
HW: ゴールデン・リファレンス・デザイン (Terasic提供)をカスタマイズ

※3:HAL / OS
HAL: NiosII EDS にて生成
OS: FreeRTOS


[1] FreeRTOS.org 提供の Example は、そのまま DE0-Nano のゴールデン・リファレンス・デザイン (GRD) で動作させることはできるのか?
 
 
 
残念ながら、次の理由で、動作させることはできません。
 
 
(a) FreeRTOS.org提供のExampleコードには、UART を使用する コードがある。しかし、GRD には UART ペリフェラルがない。→ Platform Designer (旧Qsys) + Quartus で、Hardware デザインを変更 + コンパイルする必要がある。
 

(b) 追加のマクロ定義をしないと、Compile エラーとなる。→ ソースコードの変更
 

(c) 古い Quartus / NiosII EDS を前提にコードが提供されているため、そのままではBSP (Board Support Package) / HAL を生成できない。→ Platform Designer (旧Qsys)からの出力ファイル *.socinfo ファイルと BSP Editor を使用して生成する。
 

(d) LED の記述を、DE0-Nano の GRD に合わせて変更する必要がある。
 

(e) vTaskDelay() 関数を使用すると、vTaskDelay() 以降の処理が実行されない。→ FreeRTOS 提供の NiosII 用 Exampleには、Exception Handler が含まれている。これが、最新の NiosII HAL/BSP の記述と相性が悪い(前提が異なる)。
 

(f) alt_irq_handler() 内部で無限ループとなる。→ 前述(e)と同じで、恐らく相性問題。詳細は追っていないが、とりあえずの回避策あり。
 
 


[2] 対策方法:
前述の(a)~(f) の対策を以下に記載します。

(a) Platform Designer (旧Qsys) + Quartus で、Hardware デザインを変更 + コンパイルする必要がある。

DE0-Nano 付属の CD-ROM に、各種ファイルがあります。"Demonstration” フォルダー以下に、「DE0_Nano_QSYS_DEMO」というデザインがありますので、これを変更して使用します。

Quartus の使用方法の詳細は割愛します。
*DE0_Nano.qpf を使用して、Quartus を開きます。
*DE0_Nano_SOPC.qsys を使用して、Platform Designer を開きます。
*"UART" を追加します。"Name" の箇所を "uart" に変更します(下図参照)。クロックはNiosIIと同じクロックで、IRQ もNiosIIに接続します。

*上記変更&ファイルを保存後、Platform上で Generate HDL を行います。また、Quartus 上で、Compile を行い、*.sof ファイルを生成します。Quartus Lite Edition を使用している場合には、生成される sof ファイル名は、「DE0_Nano_time_limited.sof」になります。
*この sof ファイルを、ソフトウェアを動作させる前に、Quartus の Programmer を使用して、NE0-Nanoボードにダウンロードします。
 


(b) 追加のマクロ定義をしないと、Compile エラーとなる。→ ソースコードの変更
以下のコードを、FreeRTOS Example コードに追加します。

FreeRTOSConfig.hファイル:
//Added 100MHz clock for NiosII
#define SYS_CLK_FREQ 100000000

portable/GCC/NiosII/port.cファイル:
#include "altera_avalon_timer.h"
#define  SYS_CLK_IRQ  0

//SYS_CLK_BASE を TIMER_BASE に変更(6箇所)
//例:
IOWR_ALTERA_AVALON_TIMER_CONTROL( SYS_CLK_BASE, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK );
 ↓
IOWR_ALTERA_AVALON_TIMER_CONTROL( TIMER_BASE, ALTERA_AVALON_TIMER_CONTROL_STOP_MSK );

 

(c) Platform Designer (旧Qsys)からの出力ファイル *.socinfo ファイルと BSP Editor を使用して生成する。

NiosII EDS 上で、前述(a)の操作で生成された *.socinfo ファイルを使用して、BSP を生成する。BSP Editor 上では、特に変更する設定は無い。Generate ボタンをクリックするだけ。
(BSP Editor 操作の詳細は割愛)
 


(d) LED の記述を、DE0-Nano の GRD に合わせて変更する必要がある。

ParTest/ParTest.c ファイル:

//LED_PIO_BASE を LED_BASE に変更(2箇所)
//
//1.
IOWR_ALTERA_AVALON_PIO_DIRECTION( LED_PIO_BASE, ALTERA_AVALON_PIO_DIRECTION_OUTPUT );
 ↓
IOWR_ALTERA_AVALON_PIO_DIRECTION( LED_BASE, ALTERA_AVALON_PIO_DIRECTION_OUTPUT );

//2.
IOWR_ALTERA_AVALON_PIO_DATA( LED_PIO_BASE, ulLedStates );
 ↓
IOWR_ALTERA_AVALON_PIO_DATA( LED_BASE, ulLedStates );
 


(e) vTaskDelay() 関数を使用すると、vTaskDelay() 以降の処理が実行されない。→ FreeRTOS 提供の NiosII 用 Exampleには、Exception Handler が含まれている。これが、最新の NiosII HAL/BSP の記述と相性が悪い(前提が異なる)。

(ここが原因を探るのに最も苦労したところ)


portable/GCC/NiosII/port_asm.S ファイル:
 

[call_scheduler オリジナル記述]
call_scheduler:
addi ea, ea, 4 # A trap was called, increment the program counter so it is not called again.
stw ea, 72(sp) # Save the new program counter to the context.
call vTaskSwitchContext # Pick the next context.
br restore_sp_from_pxCurrentTCB # Switch in the task context and restore. 


[call_scheduler 変更後(line 147 に、movia,ldw,ldw の3行を追加)]
call_scheduler:
addi ea, ea, 4 # A trap was called, increment the program counter so it is not called again.

#New lines (start)
movia et, pxCurrentTCB # Load the address of the pxCurrentTCB pointer
ldw et, (et) # Load the value of the pxCurrentTCB pointer
ldw sp, (et) # Load the stack pointer with the top value of the TCB
#New lines (end)

stw ea, 72(sp) # Save the new program counter to the context.
call vTaskSwitchContext # Pick the next context.
br restore_sp_from_pxCurrentTCB # Switch in the task context and restore. 

 
 

(f) alt_irq_handler() 内部で無限ループとなる。対策は以下。

※注意事項: BSP Editor で生成する度に、以下の対策を実行する必要あり(上書きされてしまう)。

*_bsp/HAL/src/alt_irq_handler.cファイル:
line 141行の do{ ~ } while(1) を、if (active) { ~ } で囲む。

    if (active) //added for FreeRTOS demo
    {
    do
    {
      if (active & mask)
      { 
#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
        alt_irq[i].handler(alt_irq[i].context); 
#else
        alt_irq[i].handler(alt_irq[i].context, i); 
#endif
        break;
      }
      mask <<= 1;
      i++;

    } while (1);
    }

 


[3] 確認したFreeRTOS を含むソフトウェア・コード:

とりあえず、動作確認したコードを紹介します。ここでは、vTaskDelay() を使用したLEDの点滅動作を確認しています。ボード上のLED01 が点滅します。

#vTaskDelay()を動作させるには、前述(e) が不可欠ですのでご注意を!


Common_Demo_Tasks/flash.cファイル:

static portTASK_FUNCTION( debug_task, pvParameters ){
  for(;;) {
            vParTestToggleLED( 1 ); //LED01
    vTaskDelay(pdMS_TO_TICKS(50));
  }
}

void vStartLEDFlashTasks( UBaseType_t uxPriority )
{
if (xTaskCreate( debug_task, "DEBUGx", ledSTACK_SIZE, NULL, uxPriority + 1, ( TaskHandle_t * ) NULL ) != pdPASS) {
printf("debug: xTaskCreate failed, debug_task\n");
}
}



main.cファイル:

int main( void )
{
prvSetupHardware();
    
vStartLEDFlashTasks( tskIDLE_PRIORITY );

vTaskStartScheduler();

for( ;; );

return 0;
}



※その他1:

Makefile 中のALT_INCLUDE_DIRS変数の設定も忘れずに!

(設定例)
ALT_INCLUDE_DIRS := . FreeRTOS/include Common_Demo_Tasks/include FreeRTOS/portable/GCC/NiosII



※その他2:

UART を動作させるには、上記の他に、UART のTX/RX ピンを、GPIO に割り当てる処理が必要になります。こちらについては、今回の記載には含まれておりません。こちらは、別途更新しようと思います。


Enjoy !

 

2015年7月8日水曜日

RTOS不要! マルチコア・プロセッサによる 新しい組込みソフトウェア開発技術!

32bit RISCコア が8コ以上搭載されたプロセッサなのに、C言語さえ知っていれば、

「初心者でも簡単に組込みソフトウェアが開発できて」
「モーター制御や音楽ストリーミング・データの処理が簡単にできて」
「組込み製品開発が楽しくなる」

そんなマルチコア・プロセッサと、その開発環境を紹介していきます。


参考URLs:
www.xmos.com
www.youtube.com/user/xmosmmcu




「リアルタイムOS (RTOS)」不要
コンテキスト・スイッチによるオーバーヘッドなし
パイプライン・フラッシュによるペナルティなし
組込みソフトウェア・タスクの並列実行
ソフトウェア・パイプライン設計が容易

マルチコア・プロセッサ xCORE は、組込みソフトウェア開発の生産性と品質を向上させるソリューション


このマルチコア・プロセッサ xCORE デバイスには、「リアルタイムOS」がハードウェア実装されています。これはスケジューラと呼ばれるもので、ラウンドロビン方式(フェアネス・アルゴリズム)で各CPUに割り当てられたタスクを実行していきます。

(実は、xCOREデバイスは、 マルチコア・プロセッサといっても、8コのCPU毎に1系統のパイプラインが存在し、8コのCPUがパイプラインを共有するアーキテクチャなのです。このパイプラインは500MHz で動作しています。下記の16 CPUのデバイスでは、2系統のパイプラインがあります



Source: www.xmos.com


コンテキスト・スイッチや割り込みの概念が無いアーキテクチャのため、非常に見通しの良い「組込みソフトウェア」が開発できます。
(「割り込み」機能に相当する機能があります。外部ピンからの入力に対応して処理を実行するイベント駆動型ソフトウェア処理です)

マルチコア・プロセッサ xCORE デバイス上の各CPUは、それぞれにレジスタ・セットを持っています。
共有メモリを使用せずに、CPU間でデータを受け渡しすることが可能です。共有メモリを使用する代わりに、直接、他CPUのレジスタにアクセスして、データの受け渡しができます。このCPU間でデータを送受信する命令が、ISAに定義されています。

割り算以外の命令は、全て 1 CPU cycle で処理が完了します。また、64ビットの乗算及び積和演算といったDSP演算命令を持ち、それらも 1 CPU cycle で処理が完了します。

これらの仕組みにより、各CPU上で動作する各タスク(ソフトウェア)をパイプライン化した「組込みシステム」を実現することができます。


CPU/タスクのパイプライン例:
入力 ---> [CPU1(Task1)] ---> [CPU2(Task2)] ---> [CPU3(Task3)] ---> [CPU4(Task4)] ---> 出力



特に音楽業界では、このマルチコア・プロセッサ xCORE デバイスの採用が進んでいます。
パイプライン化された各タスクが、リアルタイムに入力される音楽ストリーム・データを処理します。
これまでご紹介してきた特徴により、マルチ・チャネル、ハイレゾ、ミキサー、エフェクタ機能を、容易にソフトウェアで実現することができるのです。



シンプルで見通しのよいアーキテクチャは、美しく、バグが入り込む余地が少ないことは、皆様もご承知の通りです。

そんな組込みシステム(ソフトウェア)アーキテクチャを実現できるマルチコア・プロセッサ xCORE と、ソフトウェア開発方法について、次回より詳しく見ていきます。



ソフトウェア統合開発環境「xTIMEcomposer STUDIO」

(その他の投稿については、右上の「ページ」をご確認ください)