samples: boards: nxp_s32: add sample for NETC

The sample application shows how to configure NXP S32 Network Controller
(NETC) for different use-cases.

Signed-off-by: Manuel Arguelles <manuel.arguelles@nxp.com>
This commit is contained in:
Manuel Arguelles 2022-11-29 12:26:30 +07:00 committed by Carles Cufí
commit df1d148abc
7 changed files with 358 additions and 0 deletions

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(telnet)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -0,0 +1,24 @@
# Private config options for NXP S32 NETC sample app
# Copyright 2022 NXP
# SPDX-License-Identifier: Apache-2.0
mainmenu "NXP S32 NETC sample application"
config NET_SAMPLE_IFACE2_MY_IPV6_ADDR
string "My IPv6 address for second interface"
help
The value depends on your network setup.
config NET_SAMPLE_IFACE2_MY_IPV4_ADDR
string "My IPv4 address for second interface"
help
The value depends on your network setup.
config NET_SAMPLE_IFACE2_MY_IPV4_NETMASK
string "My IPv4 netmask for second interface"
default "255.255.255.0"
help
Static netmask to use.
source "Kconfig.zephyr"

View file

@ -0,0 +1,124 @@
.. nxp_s32_netc-samples:
NXP S32 NETC Sample Application
###############################
Overview
********
The sample application shows how to configure NXP S32 Network Controller (NETC)
for the different use-cases:
1. Zephyr application controls the Physical Station Interface (PSI) and the
Ethernet PHY through EMDIO.
2. Zephyr application controls the PSI, Virtual SI 1, and the Ethernet PHY
through EMDIO.
The sample enables the net-shell and mdio-shell (only available when Zephyr
controls PSI) to allow users visualize the networking settings. Telnet shell
and backend is also enabled.
The source code for this sample application can be found at:
:zephyr_file:`samples/boards/nxp_s32/netc`.
Requirements
************
To run this sample is needed to set-up a host machine running GNU/Linux or Windows
with a network adapter connected to the target board ETH0 port through an Ethernet
cable.
Building and Running
********************
To build and run the sample application for use-case 1:
.. zephyr-app-commands::
:zephyr-app: samples/boards/nxp_s32/netc
:board: s32z270dc2_rtu0_r52
:goals: build flash
Once started, you should see the network interface details, for example:
.. code-block:: console
[00:00:00.051,000] <inf> phy_mii: PHY (7) ID 1CC916
[00:00:00.052,000] <inf> nxp_s32_eth_psi: SI0 MAC: 00:00:00:01:02:00
[00:00:00.058,000] <inf> shell_telnet: Telnet shell backend initialized
[00:00:00.058,000] <inf> nxp_s32_netc_sample: Starting sample
[00:00:00.058,000] <inf> nxp_s32_netc_sample: Waiting for iface 1 to come up
[00:00:07.595,000] <inf> phy_mii: PHY (7) Link speed 1000 Mb, full duplex
[00:00:07.595,000] <inf> nxp_s32_netc_sample: Configuring iface 1 (0x318008f0)
[00:00:07.595,000] <inf> nxp_s32_netc_sample: IPv6 address: 2001:db8::1
[00:00:07.595,000] <inf> nxp_s32_netc_sample: IPv4 address: 192.0.2.1
To build and run the sample application for use-case 2:
.. zephyr-app-commands::
:zephyr-app: samples/boards/nxp_s32/netc
:board: s32z270dc2_rtu0_r52
:goals: build flash
:gen-args: -DDTC_OVERLAY_FILE="./vsi-and-psi.overlay"
Once started, you should see the network interfaces details, for example:
.. code-block:: console
[00:00:00.051,000] <inf> phy_mii: PHY (7) ID 1CC916
[00:00:00.052,000] <inf> nxp_s32_eth_psi: SI0 MAC: 00:00:00:01:02:00
[00:00:00.052,000] <inf> nxp_s32_eth_vsi: SI1 MAC: 00:00:00:01:02:11
[00:00:00.058,000] <inf> shell_telnet: Telnet shell backend initialized
[00:00:00.058,000] <inf> nxp_s32_netc_sample: Starting sample
[00:00:00.058,000] <inf> nxp_s32_netc_sample: Waiting for iface 1 to come up
[00:00:07.595,000] <inf> phy_mii: PHY (7) Link speed 1000 Mb, full duplex
[00:00:07.595,000] <inf> nxp_s32_netc_sample: Configuring iface 1 (0x3182f31c)
[00:00:07.595,000] <inf> nxp_s32_netc_sample: IPv6 address: 2001:db8::1
[00:00:07.595,000] <inf> nxp_s32_netc_sample: IPv4 address: 192.0.2.1
[00:00:07.595,000] <inf> nxp_s32_netc_sample: Configuring iface 2 (0x3182f328)
[00:00:07.595,000] <inf> nxp_s32_netc_sample: IPv6 address: 2001:db8::2
[00:00:07.595,000] <inf> nxp_s32_netc_sample: IPv4 address: 192.0.2.2
Setting up Host
***************
To be able to reach the board from the host, it's needed to configure the host
network interface IP's and default routes. This guide assumes the host IPv4 and
IPv6 addresses are `192.0.2.3` and `2001:db8::3`, respectively. For example,
using a network interface named `enp1s0` in a GNU/Linux host or `Ethernet` in
a Windows host, this can be done with the following commands:
.. tabs::
.. group-tab:: Linux
.. code-block:: console
ip -4 addr add 192.0.2.3/24 dev enp1s0
ip -6 addr add 2001:db8::3/128 dev enp1s0
route -A inet6 add default dev enp1s0
.. group-tab:: Windows
.. code-block:: console
netsh interface ipv4 set address "Ethernet" static 192.0.2.3 255.255.255.0
netsh interface ipv6 add address "Ethernet" 2001:db8::3/128
netsh interface ipv6 add route ::/0 "Ethernet" ::
.. note::
The above commands must be run as priviledged user.
If everything is configured correctly, you will be able to successfully execute
the following commands from the Zephyr shell:
.. code-block:: console
net ping -I<iface> 192.0.2.3
net ping -I<iface> 2001:db8::3
Where `<iface>` is the interface number starting from 1.

View file

@ -0,0 +1,47 @@
CONFIG_NETWORKING=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=y
CONFIG_NET_ARP=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_DHCPV4=n
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_L2_ETHERNET_MGMT=y
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MAX_IPV6_COUNT=2
CONFIG_NET_IF_MAX_IPV4_COUNT=2
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_PKT_TX_COUNT=20
CONFIG_NET_BUF_TX_COUNT=100
CONFIG_NET_BUF_RX_COUNT=100
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_INIT_STACKS=y
CONFIG_LOG=y
CONFIG_NET_BUF_LOG=n
CONFIG_NET_LOG=y
CONFIG_NET_SHELL=y
CONFIG_KERNEL_SHELL=y
CONFIG_SHELL_BACKEND_TELNET=y
CONFIG_SHELL_TELNET_SUPPORT_COMMAND=y
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_AUTO_INIT=n
# First ethernet interface
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_CONFIG_MY_IPV4_NETMASK="255.255.255.0"
# Second ethernet interface
CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR="2001:db8::2"
CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR="192.0.2.2"
CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_NETMASK="255.255.255.0"
CONFIG_ETH_NXP_S32_TX_RING_LEN=16
CONFIG_ETH_NXP_S32_RX_RING_LEN=16
CONFIG_ETH_NXP_S32_RX_IRQ_PACKET_THRESHOLD=8

View file

@ -0,0 +1,13 @@
sample:
description: Sample for show-casing the different use-cases of NXP S32 NETC driver
name: NXP S32 NETC sample
common:
platform_allow: s32z270dc2_rtu0_r52
depends_on: netif
tags: net
tests:
sample.boards.nxp_s32.netc.psi:
harness: net
sample.boards.nxp_s32.netc.vsi_and_psi:
extra_args: DTC_OVERLAY_FILE="./vsi-and-psi.overlay"
harness: net

View file

@ -0,0 +1,119 @@
/*
* Copyright 2022 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(nxp_s32_netc_sample, LOG_LEVEL_DBG);
#include <zephyr/kernel.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_mgmt.h>
#define PSI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_netc_psi)
#define VSI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_netc_vsi)
static K_SEM_DEFINE(iface_up, 0, 1);
static int setup_iface(struct net_if *iface, const char *ipv6_addr,
const char *ipv4_addr, const char *netmask)
{
struct net_if_addr *ifaddr;
struct in_addr addr4;
struct in6_addr addr6;
LOG_INF("Configuring iface %d (%p)", net_if_get_by_iface(iface), iface);
if (IS_ENABLED(CONFIG_NET_IPV6) && net_if_flag_is_set(iface, NET_IF_IPV6)) {
if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) {
LOG_ERR("Invalid address: %s", ipv6_addr);
return -EINVAL;
}
ifaddr = net_if_ipv6_addr_add(iface, &addr6, NET_ADDR_MANUAL, 0);
if (!ifaddr) {
LOG_ERR("Cannot add %s to interface %p", ipv6_addr, iface);
return -EINVAL;
}
LOG_INF("IPv6 address: %s", ipv6_addr);
}
if (IS_ENABLED(CONFIG_NET_IPV4) && net_if_flag_is_set(iface, NET_IF_IPV4)) {
if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) {
LOG_ERR("Invalid address: %s", ipv4_addr);
return -EINVAL;
}
ifaddr = net_if_ipv4_addr_add(iface, &addr4, NET_ADDR_MANUAL, 0);
if (!ifaddr) {
LOG_ERR("Cannot add %s to interface %p", ipv4_addr, iface);
return -EINVAL;
}
LOG_INF("IPv4 address: %s", ipv4_addr);
if (netmask && netmask[0]) {
if (net_addr_pton(AF_INET, netmask, &addr4)) {
LOG_ERR("Invalid netmask: %s", netmask);
return -EINVAL;
}
net_if_ipv4_set_netmask(iface, &addr4);
}
}
return 0;
}
static void iface_up_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event, struct net_if *iface)
{
if (mgmt_event == NET_EVENT_IF_UP) {
k_sem_give(&iface_up);
}
}
static void wait_for_iface(struct net_if *iface)
{
struct net_mgmt_event_callback iface_up_cb;
if (net_if_is_up(iface)) {
return;
}
net_mgmt_init_event_callback(&iface_up_cb, iface_up_handler, NET_EVENT_IF_UP);
net_mgmt_add_event_callback(&iface_up_cb);
LOG_INF("Waiting for iface %d to come up", net_if_get_by_iface(iface));
k_sem_take(&iface_up, K_FOREVER);
net_mgmt_del_event_callback(&iface_up_cb);
}
void main(void)
{
struct net_if *iface;
LOG_INF("Starting sample");
iface = net_if_lookup_by_dev(DEVICE_DT_GET(PSI_NODE));
if (iface) {
/* Wait for PSI iface to come up before attempting configuration */
wait_for_iface(iface);
setup_iface(iface,
CONFIG_NET_CONFIG_MY_IPV6_ADDR,
CONFIG_NET_CONFIG_MY_IPV4_ADDR,
CONFIG_NET_CONFIG_MY_IPV4_NETMASK);
}
#if DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_netc_vsi)
iface = net_if_lookup_by_dev(DEVICE_DT_GET(VSI_NODE));
if (iface) {
setup_iface(iface,
CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR,
CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR,
CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_NETMASK);
}
#endif /* DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_netc_vsi)*/
}

View file

@ -0,0 +1,23 @@
/*
* Copyright 2022 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
&mru0 {
rx-channels = <3>;
status = "okay";
};
&enetc_psi0 {
mboxes = <&mru0 0>, <&mru0 1>;
mbox-names = "rx", "vsi-msg";
vsis = <1>;
};
&enetc_vsi1 {
local-mac-address = [00 00 00 01 02 11];
mboxes = <&mru0 2>;
mbox-names = "rx";
status = "okay";
};