はじめに
ルネサスエレクトロニクス株式会社の32ビットマイコンであるRX74Mが搭載された評価ボードのEK-RX74Mで、イーサネットモジュール (ESWM) のサンプルプログラムを動かしてみました。RX74MはRXファミリ初の22nmプロセスとMRAMを採用した、最大600MHz動作の最上位32ビットマイコンです。一番の特徴は、TSN対応ギガビットEthernetスイッチを搭載し、FSP(Flexible Software Package)が使用できることだと言えるでしょう。今回はEK-RX74MでFSPを使用してTSN対応ギガビットEthernetスイッチであるイーサネットモジュール (ESWM) を動かしてみます。
準備した環境は以下の通りです。
- EK-RX74M (評価ボード)
- e2 studio 2026-10 (統合開発環境)
- RX FSP (Flexible Software Package) v1.0.0 (ソフトウェアパッケージ)
EK-RX74M用のFSPプロジェクトの作成
最初にe2 studio上でEK-RX74M用のFSPプロジェクトを作成します。
e2 studioにRX FSPがインストールされた状態で、「ファイル」から「Renesas C/C++ Project」、「Renesas RX」を選びます。
次の画面で、Renesas RX C/C++ FSP Projectを選択します。
プロジェクト名を入力したら、次の画面で「Board」として「EK-RX74M」を選択します。
次の画面でプロジェクトタイプを選択します。
今回はプロテクトゾーンを使用しないので、「Flat (Non-Protect Zone)」を選択します。
下記画面では「Executable」および「No RTOS」を選択してください。
テンプレートとして、「Bare Metal - Minimal」を選択します。
「終了」を押してプロジェクト作成を完了してください。
FSPの設定変更
プロジェクトの作成が完了すると、FSPの設定画面が表示されます。
プロジェクト作成時にはBSPとI/Oポートドライバのみがインストールされた状態なので、ここにイーサネットモジュール (ESWM) ドライバである「r_layer3_switch」を追加します。
下のタブから「Stacks」を押してください。
「Stacks」画面では、プロジェクトで使用するソフトウェアコンポーネントを追加/削除できます。「New Stack」から「Networking」、「Switch (r_layer3_switch)」を選択します。
依存モジュールも一緒に追加されるため、下の画面のような構成になります。しかし、各ドライバがEK-RX74M用の設定になっていないので、「r_layer3_switch」、「r_mac_phy」、「r_mac_phy_lsi0」、「r_mac_phy_lsi1」を選択後に「プロパティー」を押して表の通りにデフォルト値を変更します。
- r_layer3_switchの設定
| オプション名 | デフォルト値 | 変更後の値 |
|---|---|---|
| Common -> gPTP Enable | Enable | Disable |
| Module -> Ports -> Port 0 -> MAC address | 00:11:22:33:44:55 | 任意のMACアドレス |
- r_rmac_phyの設定
| オプション名 | デフォルト値 | 変更後の値 |
|---|---|---|
| Common -> VSC8541 Target | Disable | Enable |
| Module -> Select MII type | GMII | MII |
| Module -> MDIO hold timing adjustment | 0 | 1 |
| Module -> MDIO capture timing adjustment | 0 | 1 |
- r_mac_phy_lsi0の設定
| オプション名 | デフォルト値 | 変更後の値 |
|---|---|---|
| Module -> PHY-LSI type | Kit Component | VSC8541 |
- r_mac_phy_lsi1の設定
| オプション名 | デフォルト値 | 変更後の値 |
|---|---|---|
| Module -> PHY-LSI Address | 0 | 1 |
| Module -> PHY-LSI type | Kit Component | VSC8541 |
設定が完了できたら、右上の「Generate Project Content」を押してコードを生成します。
サンプルプログラムの作成
次にサンプルプログラムを作成します。
今回は「r_layer3_switch」を利用して、イーサネットフレームを送信するサンプルプログラムを作成していきます。参考にしたソースコードは以下のRX FSP Documentationの「Basic Example」です。
プロジェクトのhal_entry.cに以下のソースコードを張り付けてください。
「Basic Example」をそのまま動かしても正常に動作しないので、下記の通り、上記「Basic Example」からプログラムを変更しています。
| 変更箇所 | 変更内容 | 変更理由 |
|---|---|---|
| LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE | 1514 -> 60に変更 | バッファに格納するデータサイズは60バイトにも関わらず、実際は1514バイトが送信されるため |
| LAYER3_SWITCH_EXAMPLE_DESTINATION_MAC_ADDRESS | 送信先MACアドレスをブロードキャストアドレスに変更 | 送信先がイーサネットフレームを受信するため |
| layer3_switch_transmit_example内のtransmission_descriptor.basic.ptr_l | gpp_ether_buffers -> gpp_ether_buffers[0]に変更 | 「Basic Example」が送信バッファのポインタ指定が間違っており、意図しないデータが送信されるため |
| layer3_switch_transmit_example内のR_LAYER3_SWITCH_Open()呼び出し前 | GPIO制御でP413をHigh出力するように変更 | P413はEthernet-PHYのリセット端子に接続されている。初期値はLow出力なので、High出力にしないとリセット解除されない |
| layer3_switch_transmit_example内のR_RMAC_PHY_ChipInit()呼び出し前 | R_RMAC_PHY_ChipSelect()でPort 0のEthernet-PHYを指すように変更 | R_LAYER3_SWITCH_Open()でEthernet-PHYのIndexが更新されて、Port 1のEthernet-PHYを指すようになる。「Basic Example」はPort 0からフレーム送信を行う。したがって、このままではリンクアップ待機処理で無限ループするため (Port 1にはイーサネットケーブルを挿さないため) |
/*
* Copyright (c) 2020 - 2026 Renesas Electronics Corporation and/or its affiliates
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "hal_data.h"
#define LAYER3_SWITCH_EXAMPLE_DESCRIPTOR_POOL_SIZE (8)
#define LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE (60)
#define LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE_UPPER ((uint8_t) ((LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE & \
0xFF00) >> 8))
#define LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE_LOWER ((uint8_t) LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE & \
0x00FF)
#define LAYER3_SWITCH_EXAMPLE_TRANSMIT_ETHERNET_FRAME_SIZE (60)
#define LAYER3_SWITCH_EXAMPLE_SOURCE_MAC_ADDRESS 0x74, 0x90, 0x50, 0x00, 0x79, 0x01
#define LAYER3_SWITCH_EXAMPLE_DESTINATION_MAC_ADDRESS 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
#define LAYER3_SWITCH_EXAMPLE_FRAME_TYPE 0x00, 0x2E
#define LAYER3_SWITCH_EXAMPLE_PAYLOAD 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
/* Swap bytes of a 32-bit value */
#if defined(__BIG)
static uint32_t layer3_switch_example_bytes_swap_32_func (uint32_t x)
{
return ((x & 0x000000FFUL) << 24) |
((x & 0x0000FF00UL) << 8) |
((x & 0x00FF0000UL) >> 8) |
((x & 0xFF000000UL) >> 24);
}
#define LAYER3_SWITCH_EXAMPLE_BYTES_SWAP_32(x) layer3_switch_example_bytes_swap_32_func(x)
#endif
layer3_switch_descriptor_t gp_descriptor_pool[LAYER3_SWITCH_EXAMPLE_DESCRIPTOR_POOL_SIZE];
uint8_t gp_ether_buffer0[LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE];
uint8_t gp_ether_buffer1[LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE];
uint8_t gp_ether_buffer2[LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE];
uint8_t gp_ether_buffer3[LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE];
uint8_t gp_ether_buffer4[LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE];
uint8_t gp_ether_buffer5[LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE];
uint8_t gp_ether_buffer6[LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE];
uint8_t gp_ether_buffer7[LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE];
uint8_t * gpp_ether_buffers[8] =
{
&gp_ether_buffer0[0],
&gp_ether_buffer1[0],
&gp_ether_buffer2[0],
&gp_ether_buffer3[0],
&gp_ether_buffer4[0],
&gp_ether_buffer5[0],
&gp_ether_buffer6[0],
&gp_ether_buffer7[0],
};
/* Transmit data buffer */
uint8_t gp_send_data[LAYER3_SWITCH_EXAMPLE_TRANSMIT_ETHERNET_FRAME_SIZE] =
{
LAYER3_SWITCH_EXAMPLE_DESTINATION_MAC_ADDRESS, /* Destination MAC address */
LAYER3_SWITCH_EXAMPLE_SOURCE_MAC_ADDRESS, /* Source MAC address */
LAYER3_SWITCH_EXAMPLE_FRAME_TYPE, /* Type field */
LAYER3_SWITCH_EXAMPLE_PAYLOAD /* Payload value (46byte) */
};
void layer3_switch_transmit_example (void);
/*******************************************************************************************************************//**
* @brief Blinky example application
*
* Blinks all leds at a rate of 1 second using the software delay function provided by the BSP.
*
**********************************************************************************************************************/
void hal_entry (void)
{
layer3_switch_transmit_example();
while(1);
}
void layer3_switch_transmit_example (void)
{
fsp_err_t err = FSP_SUCCESS;
uint32_t queue_index = 0;
uint32_t link_speed_duplex = 0;
uint32_t l_pause = 0;
uint32_t p_pause = 0;
/* Configure transmission queue. */
layer3_switch_descriptor_queue_cfg_t transmission_queue_cfg =
{
.descriptor_format = LAYER3_SWITCH_DISCRIPTOR_FORMTAT_EXTENDED,
.type = LAYER3_SWITCH_QUEUE_TYPE_TX,
.write_back_mode = LAYER3_SWITCH_WRITE_BACK_MODE_FULL,
.p_descriptor_array = gp_descriptor_pool,
.p_ts_descriptor_array = NULL,
.rx_timestamp_storage = LAYER3_SWITCH_RX_TIMESTAMP_STORAGE_DISABLE,
.array_length = LAYER3_SWITCH_EXAMPLE_DESCRIPTOR_POOL_SIZE,
.ports = LAYER3_SWITCH_PORT_BITMASK_PORT0,
};
/* Prepare data for transmission. */
memcpy(gpp_ether_buffers[0], gp_send_data, LAYER3_SWITCH_EXAMPLE_TRANSMIT_ETHERNET_FRAME_SIZE);
/* Initialize transmission descriptor. */
layer3_switch_descriptor_t transmission_descriptor = {0};
transmission_descriptor.basic.ds_l = LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE_LOWER;
transmission_descriptor.basic.ds_h = LAYER3_SWITCH_EXAMPLE_MAXIMUM_FRAME_SIZE_UPPER;
transmission_descriptor.basic.die = 1;
#if defined(__BIG)
/* Endian conversion must be applied to ptr_l before writing. */
transmission_descriptor.basic.ptr_l = LAYER3_SWITCH_EXAMPLE_BYTES_SWAP_32((uintptr_t) gpp_ether_buffers);
#else
transmission_descriptor.basic.ptr_l = (uintptr_t) gpp_ether_buffers[0];
#endif
transmission_descriptor.basic.dt = LAYER3_SWITCH_DESCRIPTOR_TYPE_FSINGLE;
transmission_descriptor.info1_tx.fmt = 1;
transmission_descriptor.info1_tx.dv = LAYER3_SWITCH_PORT_BITMASK_PORT0;
err = R_IOPORT_Open(&g_ioport_ctrl, &g_bsp_pin_cfg);
assert(FSP_SUCCESS == err);
err = R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_13, BSP_IO_LEVEL_HIGH);
assert(FSP_SUCCESS == err);
R_BSP_SoftwareDelay(15, BSP_DELAY_UNITS_MILLISECONDS);
/* Open the layer3 switch instance with initial configuration. */
err = R_LAYER3_SWITCH_Open(&g_layer3_switch0_ctrl, &g_layer3_switch0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
err = R_RMAC_PHY_ChipSelect(&g_rmac_phy0_ctrl, 0);
assert(FSP_SUCCESS == err);
/* Initialize PHY-LSI chip. */
err = R_RMAC_PHY_ChipInit(&g_rmac_phy0_ctrl, &g_rmac_phy0_cfg);
assert(FSP_SUCCESS == err);
/* Start auto negotiation. */
err = R_RMAC_PHY_StartAutoNegotiate(&g_rmac_phy0_ctrl);
assert(FSP_SUCCESS == err);
do
{
/* Get the Ethernet link status read from the PHY-LSI Basic Status registers until link-up. */
err = R_RMAC_PHY_LinkStatusGet(&g_rmac_phy0_ctrl);
R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
} while (FSP_SUCCESS != err);
err = R_RMAC_PHY_LinkPartnerAbilityGet(&g_rmac_phy0_ctrl, &link_speed_duplex, &l_pause, &p_pause);
assert(FSP_SUCCESS == err);
/* Create descriptor queue. */
err = R_LAYER3_SWITCH_CreateDescriptorQueue(&g_layer3_switch0_ctrl, &queue_index, &transmission_queue_cfg);
assert(FSP_SUCCESS == err);
/* Set descriptor to queue. */
err = R_LAYER3_SWITCH_SetDescriptor(&g_layer3_switch0_ctrl, queue_index, &transmission_descriptor);
assert(FSP_SUCCESS == err);
/* Start transmission. */
err = R_LAYER3_SWITCH_StartDescriptorQueue(&g_layer3_switch0_ctrl, queue_index);
assert(FSP_SUCCESS == err);
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
/* Get descriptor status. */
err = R_LAYER3_SWITCH_GetDescriptor(&g_layer3_switch0_ctrl, queue_index, &transmission_descriptor);
assert(FSP_SUCCESS == err);
/* Check if transmission is completed. */
assert(LAYER3_SWITCH_DESCRIPTOR_TYPE_FEMPTY == transmission_descriptor.basic.dt);
/* Disable transmission and receive function and close the layer3 switch instance. */
err = R_LAYER3_SWITCH_Close(&g_layer3_switch0_ctrl);
assert(FSP_SUCCESS == err);
}
サンプルプログラムの実行
最後にサンプルプログラムを実行します。
EK-RX74Mの上段のイーサネットコネクタ (Port 0)をイーサネットケーブルを介して、PCに接続しておきます。
その後、「デバッグ構成」から今回作成したプロジェクトを選択して、「デバッグ」を実行します。デフォルトでは「Debugger」タブの「Connection Settings」の接続タイプがJTAGになっているので、FINEに変更してデバッグを開始します。
プログラムを実行して、WireShark等でEK-RX74Mが送信したイーサネットフレームをPC側で受信できることを確認します。
さいごに
EK-RX74MでFSPを使用してTSN対応ギガビットEthernetスイッチであるイーサネットモジュール (ESWM) のサンプルプログラムを動かしてみました。今回は単にイーサネットフレームを送信しただけなので、次回はEthernetスイッチ機能やEthernet TSN機能を試してみたいと思います。









