コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2020年9月4日 >>> 2020年9月4日
link もっと後

2020年9月4日

FreeRTOSで遊ぼう その2 - FreeRTOSをvirtに移植(ドライバ準備編)

目次: FreeRTOS

前回は既にあるデモアプリのビルドシステムを組み替えてRISC-V QEMU sifive_eマシン(SiFive HiFive1相当)上でFreeRTOSを動かしました。今回はRISC-V QEMU virtマシン上でFreeRTOSを動かします。

マシンの違いですが、まずUARTが違います。HiFive1はSiFive UART、virtは16550です。UARTを動かすための簡易的なドライバを書きます。

16550の出力だけするドライバ

// freertos/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/ns16550.c

#include <stdint.h>

#include "ns16550.h"

/* register definitions */
#define REG_RBR		0x00 /* Receiver buffer reg. */
#define REG_THR		0x00 /* Transmitter holding reg. */
#define REG_IER		0x01 /* Interrupt enable reg. */
#define REG_IIR		0x02 /* Interrupt ID reg. */
#define REG_FCR		0x02 /* FIFO control reg. */
#define REG_LCR		0x03 /* Line control reg. */
#define REG_MCR		0x04 /* Modem control reg. */
#define REG_LSR		0x05 /* Line status reg. */
#define REG_MSR		0x06 /* Modem status reg. */
#define REG_SCR		0x07 /* Scratch reg. */
#define REG_BRDL	0x00 /* Divisor latch (LSB) */
#define REG_BRDH	0x01 /* Divisor latch (MSB) */

/* Line status */
#define LSR_DR			0x01 /* Data ready */
#define LSR_OE			0x02 /* Overrun error */
#define LSR_PE			0x04 /* Parity error */
#define LSR_FE			0x08 /* Framing error */
#define LSR_BI			0x10 /* Break interrupt */
#define LSR_THRE		0x20 /* Transmitter holding register empty */
#define LSR_TEMT		0x40 /* Transmitter empty */
#define LSR_EIRF		0x80 /* Error in RCVR FIFO */

uint8_t readb( uintptr_t addr )
{
	return *((uint8_t *) addr );
}

void writeb( uint8_t b, uintptr_t addr )
{
	*((uint8_t *) addr ) = b;
}

void ns16550_out( struct device *dev, unsigned char c )
{
	uintptr_t addr = dev->addr;

	while ( (readb( addr + REG_LSR ) & LSR_THRE) == 0 ) {
		/* busy wait */
	}

	writeb( c, addr + REG_THR );
}

このドライバは初期化も設定も何もせず、いきなり出力だけ行う手抜き実装です。QEMUでは動きますが、おそらく実機では動かないでしょう。

mainを書き換える

元のコードはmain.cにSiFive UART用のシリアルの出力コードが入っているので、これを削ります。またmain.cとmain_blinky.c, main_full.cに別れていますが、あまり複雑なデモは要りません。main_full.cの方は削って、main.cに統合します。

main.c(一部)

// freertos/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/main.c

static void prvQueueSendTask( void *pvParameters )
{
TickType_t xNextWakeTime;
const unsigned long ulValueToSend = 100UL;
BaseType_t xReturned;

	/* Remove compiler warning about unused parameter. */
	( void ) pvParameters;

	/* Initialise xNextWakeTime - this only needs to be done once. */
	xNextWakeTime = xTaskGetTickCount();

	for( ;; )
	{
		/* Place this task in the blocked state until it is time to run again. */
		vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );

		/* Send to the queue - causing the queue receive task to unblock and
		toggle the LED.  0 is used as the block time so the sending operation
		will not block - it shouldn't need to block as the queue should always
		be empty at this point in the code. */
		xReturned = xQueueSend( xQueue, &ulValueToSend, 0U );
		configASSERT( xReturned == pdPASS );
	}
}

/*-----------------------------------------------------------*/

static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;
const unsigned long ulExpectedValue = 100UL;
const char * const pcPassMessage = "Blink\r\n";
const char * const pcFailMessage = "Unexpected value received\r\n";

	/* Remove compiler warning about unused parameter. */
	( void ) pvParameters;

	for( ;; )
	{
		/* Wait until something arrives in the queue - this task will block
		indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
		FreeRTOSConfig.h. */
		xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );

		/*  To get here something must have been received from the queue, but
		is it the expected value?  If it is, toggle the LED. */
		if( ulReceivedValue == ulExpectedValue )
		{
			puts( pcPassMessage );
			ulReceivedValue = 0U;
		}
		else
		{
			puts( pcFailMessage );
		}
	}
}

/*-----------------------------------------------------------*/

int main( void )
{
	puts( "Hello FreeRTOS!" );

	/* Create the queue. */
	xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );

	if( xQueue != NULL )
	{
		/* Start the two tasks as described in the comments at the top of this
		file. */
		xTaskCreate( prvQueueReceiveTask, "Rx", configMINIMAL_STACK_SIZE * 2U, NULL,
					mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );
		xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE * 2U, NULL,
					mainQUEUE_SEND_TASK_PRIORITY, NULL );
	}

	vTaskStartScheduler();

	return 0;
}


// freertos/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/riscv-virt.c

int puts( const char *s )
{
	struct device dev;
	size_t i;

	dev.addr = NS16550_ADDR;

	for (i = 0; i < strlen(s); i++)
	{
		ns16550_out( &dev, s[i] );
	}
	ns16550_out( &dev, '\n' );

	return 0;
}

別にPOSIX信者というわけでもないんですが、ついでにputs() もどきを実装しておきました。

続きはまた今度。

編集者:すずき(2023/09/24 08:51)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2020年9月4日 >>> 2020年9月4日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<09>>>
--12345
6789101112
13141516171819
20212223242526
27282930---

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事3件

  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
  • link 24年4月17日
    すずき (04/18 22:44)
    「[VSCodeとMarkdownとPlantUMLのローカルサーバー] 目次: LinuxVSCodeのPlantUML Ex...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/24 08:36