Amazon FreeRTOS でFreeRTOS+TCPのみ使う方法 - renesas/amazon-freertos GitHub Wiki

はじめに

  • Amazon FreeRTOSのリファレンス実装をそのまま使う場合mbed TLSが統合されている
  • 一方で、SSL/TLS実装が不要なシステム(LAN内接続のみである場合等)や、mbed TLSの代わりに別のSSL/TLS実装体を使う場合等、FreeRTOSの上位にFreeRTOS+TCPのみを実装したくなるケースがある
  • ここではこういったケースに対応するための方法を解説する

前提条件

利用した環境

  • e2 studio 2021-10
  • CC-RX 3.02
  • Amazon FreeRTOS 202107.00

プロジェクト組み立て

Etherドライバの組み込み

  • FreeRTOS(Kernel Only)が組み込まれた新規プロジェクトに対し以下手順でEtherドライバの追加を行う
  • 「端子設定」の項目は省略してOK(プロジェクト新規作成時にボードを選んでいてBDFによりボード依存の設定が実施されるため)
  • コンポーネント設定の以下モジュールはFreeRTOS/FreeRTOS+TCPに代替されるため不要
    • r_t4_rx
    • r_t4_driver_rx
    • r_sys_time_rx
  • コンポーネント設定のr_ether_rxでは、RX65N RSKに適合した以下設定値とする

FreeRTOS+TCPの組み込み

  • Amazon FreeRTOS 202107.00 (commit: a038063c3b0216e0b4d46d72425388a0c2938b13) のコンポーネントであるFreeRTOS+TCPの参照先を確認
  • git でこのコミット番号のソースコードを入手
  • 新規プロジェクトの src フォルダに git で入手した FreeRTOS-Plus-TCP をコピー
  • FreeRTOS-Plus-TCP関連フォルダにインクルードパスを通す
      • ${workspace_loc:/${ProjName}/src/FreeRTOS-Plus-TCP/portable/Compiler/Renesas}
      • ${workspace_loc:/${ProjName}/src/FreeRTOS-Plus-TCP/include}
  • リソースフィルタ機能を活用し、不要なフォルダ・ファイルをフィルタしていく
    • FreeRTOS-Plus-TCP/include フォルダを使用する
    • FreeRTOS-Plus-TCP/portable フォルダを使用する
      • BufferManagement
        • BufferAllocation_2.c のみ使用する <- 代表例として以下にスクリーンショットを貼っている
      • Compiler
        • Renesas のみ使用する
      • NetworkInterface
        • RX のみ使用する
  • FreeRTOSIPConfig.h を以下から新規プロジェクトのfreertos_configフォルダにコピー
    • コピー元: /src/FreeRTOS-Plus-TCP/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h
    • コピー先: /src/frtos_config/FreeRTOSIPConfig.h
    • ucGatewayAddress と ucDNSServerAddress の定義が足りていないので足しておく
      • 上記反映したコードはソースコードリストの FreeRTOSConfig.h 参照 (コード生成しなおしてもカスタム部分は消えないのでこの追加は初回のみ必要であり、コード生成しなおした後はこの追加は不要)
  • スマートコンフィグレータでFreeRTOSのヒープを128ブロック(128KB)確保し
  • スマートコンフィグレータでMACアドレスの設定を変更し、コード生成する (ルータによってはこの実験用のデフォルトのMACアドレスを受け付けないため)
  • Etherドライバに必要なセクション「B_ETHERNET_BUFFERS_1」の先頭番地を0x00010000から0x00800000(拡張RAM)に変更
  • この時点でビルドすると、FreeRTOS+TCPから呼び出される以下ユーザ定義関数群が未定義となる(コンパイルは通る)

main_task()の実装

動作確認

最適化をOFFにして、デバッグ時にウォッチ可能なローカル変数のスコープを最大化する

    • 最適化設定を変更後、ビルドを再度行う

RX65N RSK用のデバッガ設定を施す

プログラムをダウンロード・実行しDHCPで割り当てられたIPアドレスを調べる

    • /src/rx65n_rsk_freertos_tcp.c の vApplicationIPNetworkEventHook の181行目にブレークを設定し実行
    • 1秒程度でブレークすることを確認
      • ブレークしない場合は、RX65N RSKに正しくLANケーブルが接続されているか、LANケーブル接続先のネットワークにDHCPサーバが存在するかを確認する
    • この例では、cBuffer に 192.168.1.204 が格納されていることが分かる

割り当てられたIPアドレスに対しpingで導通確認を行う

ソースコードリスト

/src/frtos_config/FreeRTOSIPConfig.h

/*
 * FreeRTOS Kernel V10.0.0
 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. If you wish to use our Amazon
 * FreeRTOS name, please do so in a fair use way that does not cause confusion.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * http://www.FreeRTOS.org
 * http://aws.amazon.com/freertos
 *
 * 1 tab == 4 spaces!
 */

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/* Prevent Renesas headers redefining some stdint.h types. */
#define __TYPEDEF__	1

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/

#define configUSE_PREEMPTION			1
#define configUSE_IDLE_HOOK				1
#define configUSE_TICK_HOOK				1
#define configCPU_CLOCK_HZ				(BSP_ICLK_HZ)
#define configPERIPHERAL_CLOCK_HZ		(BSP_PCLKB_HZ)
#define configTICK_RATE_HZ				(( TickType_t ) 1000)
#define configMINIMAL_STACK_SIZE		(( unsigned short ) 140)
#define configTOTAL_HEAP_SIZE_N			(128)
#define configTOTAL_HEAP_SIZE			(( size_t ) ( configTOTAL_HEAP_SIZE_N * 1024 ))
#define configMAX_TASK_NAME_LEN			(12)
#define configUSE_TRACE_FACILITY		1
#define configUSE_16_BIT_TICKS			0
#define configIDLE_SHOULD_YIELD			1
#define configUSE_CO_ROUTINES 			0
#define configUSE_MUTEXES				1
#define configGENERATE_RUN_TIME_STATS	0
#define configCHECK_FOR_STACK_OVERFLOW	2
#define configUSE_RECURSIVE_MUTEXES		1
#define configQUEUE_REGISTRY_SIZE		0
#define configUSE_MALLOC_FAILED_HOOK	1
#define configUSE_APPLICATION_TASK_TAG	0
#define configUSE_QUEUE_SETS			1
#define configUSE_COUNTING_SEMAPHORES	1
#define configMAX_PRIORITIES			(7)
#define configMAX_CO_ROUTINE_PRIORITIES (2)
#define configUSE_TASK_NOTIFICATIONS     1
#define configRECORD_STACK_HIGH_ADDRESS  0
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS  0

/* Dynamic allocation and static allocation. */
#define configSUPPORT_DYNAMIC_ALLOCATION        1
#define configSUPPORT_STATIC_ALLOCATION         0

/* Run time stats gathering definitions. */
unsigned long ulGetRunTimeCounterValue( void );
void vConfigureTimerForRunTimeStats( void );
#define configGENERATE_RUN_TIME_STATS    0
//#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()    vConfigureTimerForRunTimeStats()
//#define portGET_RUN_TIME_COUNTER_VALUE()            ulGetRunTimeCounterValue()

/* Software timer definitions. */
#define configUSE_TIMERS				1
#define configTIMER_TASK_PRIORITY		(6)
#define configTIMER_QUEUE_LENGTH		5
#define configTIMER_TASK_STACK_DEPTH	(configMINIMAL_STACK_SIZE)

/* The interrupt priority used by the kernel itself for the tick interrupt and
the pended interrupt.  This would normally be the lowest priority. */
#define configKERNEL_INTERRUPT_PRIORITY         1

/* The maximum interrupt priority from which FreeRTOS API calls can be made.
Interrupts that use a priority above this will not be effected by anything the
kernel is doing. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    4

/* The peripheral used to generate the tick interrupt is configured as part of
the application code.  This constant should be set to the vector number of the
peripheral chosen.  As supplied this is CMT0. */
#define configTICK_VECTOR						_CMT0_CMI0

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet			1
#define INCLUDE_uxTaskPriorityGet			1
#define INCLUDE_vTaskDelete					1
#define INCLUDE_vTaskCleanUpResources		0
#define INCLUDE_vTaskSuspend				1
#define INCLUDE_vTaskDelayUntil				1
#define INCLUDE_vTaskDelay					1
#define INCLUDE_uxTaskGetStackHighWaterMark	1
#define INCLUDE_xTaskGetSchedulerState		1
#define INCLUDE_eTaskGetState				1
#define INCLUDE_xTimerPendFunctionCall		1

void vAssertCalled( void );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled()

/* Override some of the priorities set in the common demo tasks.  This is
required to ensure flase positive timing errors are not reported. */
#define bktPRIMARY_PRIORITY		(( configMAX_PRIORITIES - 3 ))
#define bktSECONDARY_PRIORITY	(( configMAX_PRIORITIES - 4 ))
#define intqHIGHER_PRIORITY		(( configMAX_PRIORITIES - 3 ))


/*-----------------------------------------------------------
 * Ethernet configuration.
 *-----------------------------------------------------------*/

/* MAC address configuration. */
#define configMAC_ADDR0	0x74
#define configMAC_ADDR1	0x90
#define configMAC_ADDR2	0x50
#define configMAC_ADDR3	0x00
#define configMAC_ADDR4	0x79
#define configMAC_ADDR5	0x03

/* IP address configuration. */
#define configIP_ADDR0		192
#define configIP_ADDR1		168
#define configIP_ADDR2		0
#define configIP_ADDR3		200

/* Netmask configuration. */
#define configNET_MASK0		255
#define configNET_MASK1		255
#define configNET_MASK2		255
#define configNET_MASK3		0

/* Default gateway IP address configuration.  Used in ipconfigUSE_DHCP is set to
 * 0, or ipconfigUSE_DHCP is set to 1 but a DNS server cannot be contacted. */
#define configGATEWAY_ADDR0                  10
#define configGATEWAY_ADDR1                  136
#define configGATEWAY_ADDR2                  247
#define configGATEWAY_ADDR3                  254

/* Default DNS server configuration.  OpenDNS addresses are 208.67.222.222 and
 * 208.67.220.220.  Used in ipconfigUSE_DHCP is set to 0, or ipconfigUSE_DHCP is
 * set to 1 but a DNS server cannot be contacted.*/
#define configDNS_SERVER_ADDR0               172
#define configDNS_SERVER_ADDR1               23
#define configDNS_SERVER_ADDR2               84
#define configDNS_SERVER_ADDR3               110

/* When the FIT configurator or the Smart Configurator is used, platform.h has to be used. */
#define configINCLUDE_PLATFORM_H_INSTEAD_OF_IODEFINE_H  1

#endif /* FREERTOS_CONFIG_H */

/src/rx65n_rsk_freertos_tcp.c

/***********************************************************************
*
*  FILE        : rx65n_rsk_freertos_tcp.c
*  DATE        : 2021-11-24
*  DESCRIPTION : Main Program
*
*  NOTE:THIS IS A TYPICAL EXAMPLE.
*
***********************************************************************/
#include "FreeRTOS.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOSIPConfig.h"
#include "task.h"

static const uint8_t ucIPAddress[ 4 ] =
{
    configIP_ADDR0,
    configIP_ADDR1,
    configIP_ADDR2,
    configIP_ADDR3
};
static const uint8_t ucNetMask[ 4 ] =
{
    configNET_MASK0,
    configNET_MASK1,
    configNET_MASK2,
    configNET_MASK3
};
static const uint8_t ucGatewayAddress[ 4 ] =
{
    configGATEWAY_ADDR0,
    configGATEWAY_ADDR1,
    configGATEWAY_ADDR2,
    configGATEWAY_ADDR3
};

/* The following is the address of an OpenDNS server. */
static const uint8_t ucDNSServerAddress[ 4 ] =
{
    configDNS_SERVER_ADDR0,
    configDNS_SERVER_ADDR1,
    configDNS_SERVER_ADDR2,
    configDNS_SERVER_ADDR3
};

static uint8_t ucMACAddress[ 6 ] =
{
    configMAC_ADDR0,
    configMAC_ADDR1,
    configMAC_ADDR2,
    configMAC_ADDR3,
    configMAC_ADDR4,
    configMAC_ADDR5
}; //XXX

void main_task(void *pvParameters)
{

	/* Create all other application tasks here */
    FreeRTOS_IPInit( ucIPAddress,
                     ucNetMask,
                     ucGatewayAddress,
                     ucDNSServerAddress,
                     ucMACAddress );

	while(1)
	{
		vTaskDelay(1);
	}

	vTaskDelete(NULL);

}

uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
                                             uint16_t usSourcePort,
                                             uint32_t ulDestinationAddress,
                                             uint16_t usDestinationPort )
{
	uint32_t random;
	xApplicationGetRandomNumber(&random);
	return random;
}

BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
{
    static uint32_t y = 2463534242;
    static uint32_t *z = (uint32_t *)&ucMACAddress[0];
    uint32_t res;
    uint32_t lp;
    uint8_t *bPtr;
    uint32_t len = 4;

    if(z != NULL)
    {
        y ^= *z;
        z = NULL;
    }
    res = len / 4;
    /* WAIT_LOOP */
    for (lp = 0; lp < res; lp++)
    {
        y = y ^ (y << 13);
        y = y ^ (y >> 17);
        y = y ^ (y << 5);
        bPtr = (uint8_t*) & y;
#if __LIT
        *((uint32_t *)pulNumber) = (*(bPtr + 3) << 24) | (*(bPtr + 2) << 16) | (*(bPtr + 1) << 8) | *(bPtr + 0);
#else
        *((uint32_t *)data) = y;
#endif
        pulNumber += 4;
    }
    y = y ^ (y << 13);
    y = y ^ (y >> 17);
    y = y ^ (y << 5);
    res = (uint32_t)len % 4;
    bPtr = (uint8_t*) & y;
    switch (res)
    {
        case 3:
#if __LIT
            *pulNumber++ = bPtr[3];
            *pulNumber++ = bPtr[2];
            *pulNumber++ = bPtr[1];
#else
            *pulNumber++ = bPtr[0];
            *pulNumber++ = bPtr[1];
            *pulNumber++ = bPtr[2];
#endif
            break;

        case 2:
#if __LIT
            *pulNumber++ = bPtr[3];
            *pulNumber++ = bPtr[2];
#else
            *pulNumber++ = bPtr[0];
            *pulNumber++ = bPtr[1];
#endif
            break;

        case 1:
#if __LIT
            *pulNumber++ = bPtr[3];
#else
            *pulNumber++ = bPtr[0];
#endif
            break;

        default:
            /* no op */
            break;
    }
    return pdTRUE;
}

const char * pcApplicationHostnameHook( void )
{
    /* This function will be called during the DHCP: the machine will be registered
     * with an IP address plus this name. */
    return "RX65NRSK";
}

void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
    static BaseType_t xTasksAlreadyCreated = pdFALSE;
    uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;
    char cBuffer[ 16 ];

    /* If the network has just come up...*/
    if( ( eNetworkEvent == eNetworkUp ) && ( xTasksAlreadyCreated == pdFALSE ) )
    {
        xTasksAlreadyCreated = pdTRUE;
        /* Print out the network configuration, which may have come from a DHCP
         * server. */
        FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress );
        FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
        FreeRTOS_printf( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulNetMask, cBuffer );
        FreeRTOS_printf( ( "Subnet Mask: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );
        FreeRTOS_printf( ( "Gateway Address: %s\r\n", cBuffer ) );

        FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer );
        FreeRTOS_printf( ( "DNS Server Address: %s\r\n\r\n\r\n", cBuffer ) );
    }
}
⚠️ **GitHub.com Fallback** ⚠️