1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EK-RX74Mでイーサネットモジュール (ESWM) を動かしてみる

1
Posted at

はじめに

ルネサスエレクトロニクス株式会社の32ビットマイコンであるRX74Mが搭載された評価ボードのEK-RX74Mで、イーサネットモジュール (ESWM) のサンプルプログラムを動かしてみました。RX74MはRXファミリ初の22nmプロセスとMRAMを採用した、最大600MHz動作の最上位32ビットマイコンです。一番の特徴は、TSN対応ギガビットEthernetスイッチを搭載し、FSP(Flexible Software Package)が使用できることだと言えるでしょう。今回はEK-RX74MでFSPを使用してTSN対応ギガビットEthernetスイッチであるイーサネットモジュール (ESWM) を動かしてみます。
準備した環境は以下の通りです。

  1. EK-RX74M (評価ボード)
  2. e2 studio 2026-10 (統合開発環境)
  3. 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」を選びます。

image.png

次の画面で、Renesas RX C/C++ FSP Projectを選択します。

image.png

プロジェクト名を入力したら、次の画面で「Board」として「EK-RX74M」を選択します。

image.png

次の画面でプロジェクトタイプを選択します。
今回はプロテクトゾーンを使用しないので、「Flat (Non-Protect Zone)」を選択します。

image.png

下記画面では「Executable」および「No RTOS」を選択してください。

image.png

テンプレートとして、「Bare Metal - Minimal」を選択します。
「終了」を押してプロジェクト作成を完了してください。

image.png

FSPの設定変更

プロジェクトの作成が完了すると、FSPの設定画面が表示されます。
プロジェクト作成時にはBSPとI/Oポートドライバのみがインストールされた状態なので、ここにイーサネットモジュール (ESWM) ドライバである「r_layer3_switch」を追加します。
下のタブから「Stacks」を押してください。

image.png

「Stacks」画面では、プロジェクトで使用するソフトウェアコンポーネントを追加/削除できます。「New Stack」から「Networking」、「Switch (r_layer3_switch)」を選択します。

image.png

依存モジュールも一緒に追加されるため、下の画面のような構成になります。しかし、各ドライバがEK-RX74M用の設定になっていないので、「r_layer3_switch」、「r_mac_phy」、「r_mac_phy_lsi0」、「r_mac_phy_lsi1」を選択後に「プロパティー」を押して表の通りにデフォルト値を変更します。

image.png

  • 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側で受信できることを確認します。

image.png

さいごに

EK-RX74MでFSPを使用してTSN対応ギガビットEthernetスイッチであるイーサネットモジュール (ESWM) のサンプルプログラムを動かしてみました。今回は単にイーサネットフレームを送信しただけなので、次回はEthernetスイッチ機能やEthernet TSN機能を試してみたいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?