こんにちは。NoMaYです。別スレッド『Amazon AWSのFreeRTOS Kernel Developer GuideのサンプルコードをRenesas RX SimulatorのDebug Consoleで試せるようにしてみた』で気付いたことですが、FreeRTOSでは、ポートレイヤーの実装に内蔵周辺のソフトウェア割り込み機能(これはCPUのソフトウェア割り込み命令のことでは無いです)を使用することで、素朴に簡単に割り込みルーチンからFreeRTOS APIを呼び出せるようになることに気付きました。そこで、FreeRTOS v10.2.1 RL78ポートレイヤーをそのように改変してみました。以下、プロジェクトのファイル一式です。(CC-RL版はCS+ V8.01/e2 stuiod v7.40+CC-RL V1.02でビルド(e2 studio用.project/.cproject等を同梱))(GNURL78版はe2 studio v7.40+GNURL78 2019q2(4.9.2.201902)でビルド)(共にzipファイルをe2 studioに直接インポート可能) プロジェクト構造は極力RX版と同じにしてあります。([追記] すみません。以下に含まれるMAPファイルが別のものでした。タスク側のクリティカルセクションが以前のままのものでした。この投稿の末尾に追加したMOTファイルのzipファイルには訂正版を入れてあります。)sim_rl78_freertos_full_demo_ccrl_c_csplus_20190705.zip 628KBsim_rl78_freertos_full_demo_gnurl78_c_e2v740_20190705.zip 582KBそのスレッドに投稿していたRL78ポートレイヤー(これもFreeRTOS v10.2.1 RL78ポートレイヤーを改変したものです)では、割り込みルーチンからFreeRTOS APIを呼び出すには以下のような特別なおまじないを記述する必要がありました。(以下はCC-RLの場合のものですがGNURL78でも同様です。)
#pragma interrupt r_intc3_interrupt(vect=INTP3)/* Start user code for pragma. Do not edit comment generated here */R_PRAGMA_FREERTOS_INTERRUPT(r_intc3_interrupt)#define r_intc3_interrupt _r_intc3_interrupt/* End user code. Do not edit comment generated here */
そのスレッドにはRXポートレイヤーの改変についても投稿していたのですが、その時、最初に書いたことに気付きました。RL78の内蔵周辺には専用のソフトウェア割り込み機能はありませんが、以下のハードウェアマニュアルに記載されている通り、プログラムで割り込み要求フラグをセットすると割り込みを発生させることが出来ますので、実質的に任意の空き割り込みをソフトウェア割り込み機能として使うことが出来ます。(今回は、とりあえず、ウォッチドッグタイマのオーバフロー時間の75%到達のインターバル割り込みを使用してみました。) RL78/G13 ユーザーズマニュアル ハードウェア編からの抜粋www.renesas.com/ja-jp/doc/products/mpumcu/doc/rl78/r01uh0146jj0340_rl78g13.pdfなお、今回のRL78ポートレイヤーの改変で、先ほどの特別なおまじないを記述する必要は無くなりますが、割り込みルーチンからFreeRTOS APIを呼び出してブロック解除待ちタスクをブロック解除する場合のタスク切り替えの遅延時間が以下のRenesas RL78 SimulatorのSimulator GUIの画面コピーのように数十クロックほど(32MHz動作では600nsほど)延びます。(以下はCC-RLの場合のものですがGNURL78でも同様(ただし数百nsほど長い)です。) ちなみに、タスク側のクリティカルセクション(その区間では割り込み禁止となる)への出入りによるタイミングへの影響を避ける為、今回はクリティカルセクションとして扱うことしていませんので、以下の画面コピーでは別スレッドの画面コピーよりもポート出力トグルの速さが速くなっています。今回の改変前:今回の改変後:以下、今回のRL78ポートレイヤの改変内容です。コメントの訂正や不要になったルーチンの削除は省略しています。(以下はCC-RLの場合のものですがGNURL78でも同様です。)src/FreeRTOS/Source/portable/Renesas/RL78/portmacro.h今回の改変前:
/* Task utilities. */#define portYIELD() __brk()#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()#define portNOP() __nop()
今回の改変後: 赤文字行を追加/変更
#include "iodefine.h"
/* Task utilities. */#define portYIELD() do{ WDTIIF = 1; } while (0)#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) portYIELD()#define portNOP() __nop()
src/FreeRTOS/Source/portable/Renesas/RL78/port.c今回の改変後: 赤文字行を追加
BaseType_t xPortStartScheduler( void ){ /* Setup the hardware to generate the tick. Interrupts are disabled when this function is called. */ configSETUP_TICK_INTERRUPT(); /* Setup the hardware to generate the yield interrupt. */ WDTIPR1 = 1; WDTIPR0 = 1; WDTIMK = 0; /* Restore the context of the first task that is going to run. */ vPortStartFirstTask(); /* Execution should not reach here as the tasks are now running! */ return pdTRUE;}
src/FreeRTOS/Source/portable/Renesas/RL78/portasm.asm今回の改変前:
_vPortYield: portSAVE_CONTEXT ; Save the context of the current task. call@ _vTaskSwitchContext ; Call the scheduler to select the next task. portRESTORE_CONTEXT ; Restore the context of the next task to run. retb
_vPortYield .VECTOR 0x7E
今回の改変後: 赤文字行を変更
_vPortYield: portSAVE_CONTEXT ; Save the context of the current task. call@ _vTaskSwitchContext ; Call the scheduler to select the next task. portRESTORE_CONTEXT ; Restore the context of the next task to run. reti
_vPortYield .VECTOR 0x04
以下、今回のタスク側のプログラムです。先ほど書いた通り、今回は各タスクのポート出力をトグルさせる部分をクリティカルセクションとして扱うことしていません。(なお、src/frtos_config/FreeRTOSConfig.hの#define FREERTOS_USER_MAIN 0の行で0→1の変更を行うことで以下が実行されるようになります。)src/user_main.c
void main_task(void *pvParameters){ (void) pvParameters; while (1) { P1_bit.no6 = !P1_bit.no6; }}void second_task(void *pvParameters){ (void) pvParameters; while (1) { P1_bit.no5 = !P1_bit.no5; }}void third_task(void *pvParameters){ (void) pvParameters; while (1) { P1_bit.no4 = !P1_bit.no4; }}void intp3_task(void *pvParameters){ (void) pvParameters; R_INTC3_Start(); LED_INIT(); while (1) { xSemaphoreTake( xSemaphoreINTP3, portMAX_DELAY ); LED_BIT = !LED_BIT; }}
[追記]MOTファイルsim_rl78_freertos_full_demo_ccrl_c_csplus_20190705_mot.zip 2019/07/12追加sim_rl78_freertos_full_demo_gnurl78_c_e2v740_20190705_mot.zip 2019/07/24追加
こんにちは。NoMaYです。#4連投の1つ目です。自作の以下のRX-TBのFreeRTOS Sample ProgramをRL78/G14 Fast Prototyping Boardへ移植してみました。実は何パターンか実装するつもりでいて、今回、まず、UART送受信をDTCで行う版を投稿します。(後で、UART受信にチョコさんのリングバッファのソースコードを使用する版とか(デバッグ中)、UART送受信をコード生成機能が生成した割り込み処理のソースコードを素朴に使用する版とか(まだ未着手)、投稿してみようと思っています。)CSplusでFreeRTOSプロジェクトもどきSample Programを作ってRenesas RX Simulator/TB-RX65Nで試せるようにしてみたhttps://japan.renesasrulz.com/cafe_rene/f/forum21/5980/csplus-freertos-sample-program-renesas-rx-simulator-tb-rx65ne2 studio+GNURXでFreeRTOSプロジェクトもどきSample Programを作ってRenesas RX Simulator/TB-RX65Nで試せるようにしてみたjapan.renesasrulz.com/cafe_rene/f/forum21/6012/e2-studio-gnurx-freertos-sample-program-renesas-rx-simulator-tb-rx65n「(1) TBボードのLED0を500ms毎にOn/Offする(FreeRTOS APIのvTaskDelay()を使用)(2) TBボードのSW1押下毎にLED1をOn/Offする(タスクでセマフォ待ちして割り込みでセマフォ待ち解除)(3) TBボードのSCI1で3文字受信毎に3文字エコーバックする(タスクでセマフォ待ちして割り込みで3文字毎にセマフォ待ち解除)」RL78/G14 Fast Prototyping BoardではRX65NのSCI1の置き換えとしてRL78/G14のUART3を使用また、このスレッドの前に投稿していた以下のスレッドで、RL78/G13ですが、UART受信をDMAで行う際に受信エラーを返せるようにしたFreeRTOSサンプルプログラムを投稿したことがありましたので、今回、それを基に、受信エラー処理として以下の(3')の処理を追加しました。また、その時の投稿と同様に、Renesas RL78 Simulatorで読み込めるシリアル送信データファイル(.serファイル)も同梱しています。(なお、今回、.serファイルを1つ追加しています。)Amazon AWSのFreeRTOS Kernel Developer GuideのサンプルコードをRenesas RX SimulatorのDebug Consoleで試せるようにしてみたjapan.renesasrulz.com/cafe_rene/f/forum21/5790/amazon-aws-freertos-kernel-developer-guide-renesas-rx-simulator-debug-console/32271#32271これに投稿したRL78/G13のFreeRTOSサンプルプログラムを基に今回追加した動作『(3') 受信エラーを検出したらLED1を200ms毎にOn/OffさせるようにしてSW1が押下されたら受信エラー状態をクリアする 検出する受信エラー:パリティエラー、フレーミングエラー、オーバーランエラー、タイムアウト(60秒)』以下、プロジェクトのファイル一式です。(CC-RL版はCS+ V8.02/e2 stuiod v7.6.0+CC-RL V1.02でビルド(e2 studio用.project/.cproject等を同梱)(当方特有の事情でCC-RL V1.02を使用))(GNURL78版はe2 studio v7.6.0+GNURL78 2019q4(4.9.2.201904)でビルド)(共にzipファイルをe2 studioに直接インポート可能) プロジェクト構造は極力RX-TBの自作のFreeRTOSプロジェクトもどきSample Programに似せてあります。rl78g14fpb_freertos_sampleprog1_ccrl_c_csplus_20200106.zip (*1) 406KBrl78g14fpb_freertos_sampleprog1_gnurl78_c_e2v760_20200106.zip (*1,*2) 372KB*1:実機用のデバッガプロパティ設定(CS+)や.launchファイル設定(e2 studio)は当方特有の事情でオンボードエミュレータが使えない為に未確認です。(ひと通りは設定してあります。)*2:リンカスクリプトには別スレッド「GNURL78でconst領域/Mirror領域をちょっと安全に使えるようにlinker scriptのASSERT()で小技(TIPS)を考えてみた」に投稿した内容を反映してあります。この後、2投目~4投目は以下の通りです。2投目ソースコードの記述でちょっと特殊なことをしている点(1) コード生成機能が生成した割り込み関数を自前の割り込み関数で置き換える(2) コード生成機能が生成した関数で使用すると都合が悪くなる関数を使用不可にする(3) Renesas RL78 SimulatorがN-chオープンドレイン出力でLEDを駆動する方法に未対応であることへの対処(4) DTC転送時の送信開始処理と送信終了判定処理(5) DTC保留命令によりタスク切り替えが起きなくなってしまったことへの対処3投目・各タスクのソース task_LED0 task_LED1 task_CONIO・Renesas RL78 Simulatorでシリアル送信データのファイルを使った実行例の画面コピー CC-RL+CS+ sim_rl78_serial_data_ok_2.ser(今回追加)を使用 sim_rl78_serial_data_err_uart_format.serを使用 GNURL78+e2 studio (CC-RL+e2 studioも同様) sim_rl78_serial_data_ok_2.ser(今回追加)を使用 sim_rl78_serial_data_err_uart_format.serを使用4投目・コード生成機能の設定の画面コピー DTC設定(転送元アドレスと転送先アドレスは単に仮の値) シリアル設定 外部割込み設定(かふぇルネの他の投稿にありましたが単なるSW入力ぐらいでは外部割り込みは使われないようです) ポート設定 ウォッチドッグタイマ設定(単に使用しない設定) 安全機能設定(単に使用しない設定) リセット要因確認設定(単に確認関数を出力しない設定) 端子割り当て設定 クロック設定・GNURL78+e2 studio+コード生成機能でDTCを使用する場合のGNURL78のobjcopyコマンドの設定の画面コピー (MOTファイルにRAM領域のレコードが直接出力されてしまうことへの対処です)以下、実機で実行中の写真と画面コピーですRL78/G14 Fast Prototyping Boardの今回のSample Programで使用したUART3のArduioソケット端子の位置RxD3 : J7-D0TxD3 : J7-D1GND : J8-GCC-RL+CS+の場合GNURL78+e2 studioの場合 (CC-RL+e2 studioの場合も同様です)