queueの活用 printデバッグのシリアライズ - renesas/rx72n-envision-kit GitHub Wiki

準備する物

  • 必須
    • RX72N Envision Kit × 1台
    • USBケーブル(USB Micro-B --- USB Type A) × 2 本
    • Windows PC × 1 台

前提条件

シリアライズとは

  • シリアル(連続的)に要求を並べること
  • その実装体として適切なデータ構造は キュー(queue) である
  • ハードウェアが1個であるのに対し、そのハードウェアを使用するタスクが複数存在する場合に有効な手法
  • 代表例として、printデバッグのシリアライズを説明する
    • 複数タスクからの文字列送信要求を キュー(queue) で受け、SCIの送信関数に流し込む
    • SCIの送信関数はノンブロッキングコールであるため関数終了時に処理自体は完了していない
    • 処理完了はコールバック関数で通知される形式である
    • SCIの送信関数終了後にセマフォ(semaphore)を取り(take)待ち状態とする
    • SCIの送信完了通知のコールバック時にセマフォ(semaphore)を与え(give)待ち状態を解除する

回路確認

スマートコンフィグレータによるSCI用ドライバソフトウェアの設定

コンポーネント追加

コンポーネント設定

  • r_sci_rx
    • 参考
    • 上記参考に含まれていない設定として、「送信完了時に割り込みを発生させる設定」を有効にする
  • FreeRTOS_Object
    • タスク登録
      • FreeRTOS_Object -> Taskを選択
      • Task CodeとTask Nameに task_2, task_3, print_task と入力
    • セマフォ登録
      • FreeRTOS_Object -> Semaphores を選択
      • Semaphore Type に binaryを選択
    • キュー登録
      • FreeRTOS_Object -> Queues を選択
      • Queue Length に 16 を入力
      • Item Size に 256 を入力
        • 256文字のデータを16個まで行列を作ることができる、という設定

端子設定

print_task.c のコーディング

#include "task_function.h"
/* Start user code for import. Do not edit comment generated here */
#include "r_sci_rx_if.h"
#include "r_sci_rx_pinset.h"
#include "platform.h"
#include <string.h>

void sci_callback(void *arg);

static sci_hdl_t sci_handle;
static signed portBASE_TYPE xHigherPriorityTaskWoken;

extern QueueHandle_t queue_handle_1;
extern SemaphoreHandle_t semaphore_handle_1;

/* End user code. Do not edit comment generated here */

void print_task(void * pvParameters)
{
/* Start user code for function. Do not edit comment generated here */
	sci_cfg_t   my_sci_config;
	static char string[256];

    /* Set up the configuration data structure for asynchronous (UART) operation. */
    my_sci_config.async.baud_rate    = 115200;
    my_sci_config.async.clk_src      = SCI_CLK_INT;
    my_sci_config.async.data_size    = SCI_DATA_8BIT;
    my_sci_config.async.parity_en    = SCI_PARITY_OFF;
    my_sci_config.async.parity_type  = SCI_EVEN_PARITY;
    my_sci_config.async.stop_bits    = SCI_STOPBITS_1;
    my_sci_config.async.int_priority = 15; /* disable 0 - low 1 - 15 high */

    R_SCI_Open(SCI_CH2, SCI_MODE_ASYNC, &my_sci_config, sci_callback, &sci_handle);
    R_SCI_PinSet_SCI2();

    while(1)
    {
    	xQueueReceive(queue_handle_1, string, portMAX_DELAY);
    	R_SCI_Send(sci_handle, (uint8_t *)string, strlen(string));
    	xSemaphoreTake( semaphore_handle_1, portMAX_DELAY );
    }
/* End user code. Do not edit comment generated here */
}
/* Start user code for other. Do not edit comment generated here */
void sci_callback(void *arg)
{
	xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR(semaphore_handle_1, &xHigherPriorityTaskWoken);
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

/* End user code. Do not edit comment generated here */

task_2.c のコーディング

#include "task_function.h"
/* Start user code for import. Do not edit comment generated here */
#include "platform.h"

extern QueueHandle_t queue_handle_1;
/* End user code. Do not edit comment generated here */

void task_2(void * pvParameters)
{
/* Start user code for function. Do not edit comment generated here */
	char string[256];
	while(1)
	{
		vTaskDelay(1000);
		sprintf(string, "task_2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
		xQueueSend(queue_handle_1, string, portMAX_DELAY);
	}
/* End user code. Do not edit comment generated here */
}
/* Start user code for other. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

task_3.c のコーディング

#include "task_function.h"
/* Start user code for import. Do not edit comment generated here */
#include "platform.h"

extern QueueHandle_t queue_handle_1;
/* End user code. Do not edit comment generated here */

void task_3(void * pvParameters)
{
/* Start user code for function. Do not edit comment generated here */
	char string[256];
	while(1)
	{
		vTaskDelay(1000);
		sprintf(string, "task_3: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n");
		xQueueSend(queue_handle_1, string, portMAX_DELAY);
	}
/* End user code. Do not edit comment generated here */
}
/* Start user code for other. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

ヒープ容量を調整する

動作確認

  • Windows PC上でTeratermを立ち上げ、COMポート(COMx: RSK USB Serial Port(COMx))を選択し接続
    • 設定 -> シリアルポート で以下設定を行う
      • ボーレート: 115200 bps
      • データ: 8 bit
      • パリティ: none
      • ストップ: 1 bit
      • フロー制御: none
    • 設定 -> 端末 で以下設定を行う
      • 改行コード
        • 受信: AUTO
        • 送信: CR+LF
      • ローカルエコー
        • チェックを外す
  • 実行:参考
  • 1秒おきに、以下のようなログが出力されることを確認
task_2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
task_3: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
task_2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
task_3: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
task_2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
task_3: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
  • task_2 および、task_3 からのprint出力が衝突せずに出力されていることを確認
  • 仮に task_2 および、task_3 からxQueueSend()を使用せずに直接R_SCI_Send()を呼び出したとすると、task_2の送信中にtask_3の送信が混じり、上記のように衝突せず出力することができない
⚠️ **GitHub.com Fallback** ⚠️