Ethernet Firmware
Introduction
This Ethernet Firmware example demonstrates ability to perform traffic steering from CPSW to multiple cores. This uses hardware capabilities of CPSW to direct unicast traffic, and a shared memory based layer to send multicast and broadcast traffic.
Ethernet Firmware server is the application which owns the CPSW peripheral, and controls the behaviour. Ethernet firmware clients are the applications which are running on different cores, which send requests to ethernet firmware server based on their requirements.
The demo configures the R5F server to acquire a DHCP address and registers the MCU-R5 client, allocating a MAC address and IP address to it. The client’s assigned IP is printed to the UART terminal.
Note
This is in work-in-progress state currently, and complete feature list and functionality will be updates as functional validation progresses.
Please refer to Networking Ethernet Firmware for more detailed information about Ethfw features
Attention
For more information, please refer to the link https://software-dl.ti.com/jacinto7/esd/processor-sdk-rtos-j784s4/latest/exports/docs/ethfw/docs/user_guide/ethfw_c_ug_top.html
Supported Combinations
Ethernet Firmware Server
Parameter |
Value |
|---|---|
CPU + OS |
wkup-r5fss0-0_freertos |
Toolchain |
ti-arm-clang |
Board |
am62px-sk |
Example folder |
source/networking/ethfw/apps/app_remoteswitchcfg_server/sitara/ |
Ethernet Firmware Client
Parameter |
Value |
|---|---|
CPU + OS |
mcu-r5fss0-0_freertos |
Toolchain |
ti-arm-clang |
Board |
am62px-sk |
Example folder |
source/networking/ethfw/apps/app_remoteswitchcfg_client/sitara/ |
Other Clients supported
Client Env |
Supported Core + OS |
|---|---|
MCAL Client |
mcu-r5fss0-0_freertos |
Linux Client |
A53-linux |
Steps to Run the Example
Prerequisites
EVM Board
CAT6 Ethernet cable
Build the example
When using CCS projects to build, import the CCS project for the required combination and build it using the CCS project menu (see Using SDK with CCS Projects).
When using makefiles to build, note the required combination and build using make command (see Using SDK with Makefiles)
HW Setup
Connect the One end of the CAT6 cable to the EVM and the other end of the CAT6 cable to network.
Run the example
Attention
If you need to reload and run again, a CPU power-cycle is MUST.
Note
CCS loading is not supported for any core. Applications are tested with OSPI boot mode
Load wkup-r5 Server binary to the evm via OSPI boot mode.
Load other binaries via SBL flow or U-boot flow.
You will see logs in the UART terminal as shown in the next section.
The prints will indicate the IP address acquired by clients against their corresponding MAC addresses
Sample output
WKUP-R5 Server Application logs
=======================================================
CPSW Ethernet Firmware
=======================================================
EnetAppUtils_reduceCoreMacAllocation: Reduced Mac Address Allocation for CoreId:1 From 4 To 3
Open MAC port 1
EnetPhy_bindDriver:1942
Open MAC port 2
EnetPhy_bindDriver:1942
PHY 0 is alive
PHY 1 is alive
ETHFW: Shared multicasts:
ETHFW: 01:00:5e:00:00:01
ETHFW: 01:00:5e:00:00:fb
ETHFW: 01:00:5e:00:00:fc
ETHFW: 33:33:00:00:00:01
ETHFW: 33:33:ff:1d:92:c2
ETHFW: 01:80:c2:00:00:00
ETHFW: 01:80:c2:00:00:03
ETHFW: Reserved multicasts:
ETHFW: 01:80:c2:00:00:0e
ETHFW: 01:1b:19:00:00:00
ETHFW: VLAN 1024 member=0x7 virtMember=0xe000000 regMcastFlood=0x7 unregMcastFlood=0x7 untag=0x0
ETHFW: 1 VLAN entries added in ALE table
ETHFW: PPS via GenF is not supported for this SoC
ETHFW Version : 0.05.00
ETHFW Build Date: Dec 3, 2025
ETHFW Build Time: 11:20:04
ETHFW Commit SHA:
ETHFW: Virtual port configuration:
ETHFW: CpswProxyServer: initialization completed (core: mcu2_0)
unibase-1.1.4
Starting lwIP, local interface IP is dhcp-enabled
[LWIPIF_LWIP] NETIF INIT SUCCESS
Host MAC address-0 : 70:ff:76:1d:ec:f2
ETHFW: Enable gPTP on MAC port 1 (tilld1)
ETHFW: Enable gPTP on MAC port 2 (tilld2)
[LWIPIF_LWIP_IC] Interface started successfully
[LWIPIF_LWIP_IC] NETIF INIT SUCCESS
[LWIPIF_LWIP_IC] Interface started successfully
[LWIPIF_LWIP_IC] NETIF INIT SUCCESS
[LWIPIF_LWIP] Enet has been started successfully
Added interface 'br3', IP is 0.0.0.0
ETHFW: ATTACH | C2S | core=0 endpt=36 virtPort=26
ETHFW: TimeSync PTP enabled
ETHFW: ATTACH | S2C | token=2600 rxMtu=1522 features=3
ETHFW: ALLOC_TX | C2S | core=0 endpt=36 token=2600
ETHFW: ALLOC_TX | S2C | txPsil=0xc603 status=0
ETHFW: ALLOC_RX | C2S | core=0 endpt=36 token=2600
ETHFW: ALLOC_RX | S2C | flow=20,5 rxPsil=0x4600 status=0
ETHFW: ALLOC_MAC | C2S | core=0 endpt=36 token=2600
ETHFW: ALLOC_MAC | S2C | macAddr=70:ff:76:1d:ec:e7 status=0
ETHFW: REGISTER_MAC | C2S | core=0 endpt=36 token=2600 macAdd=70:ff:76:1d:ec:e7 flowIdx=20,5
Cpsw_internalIoctl_handler_ENET_IOCTL_REGISTER_DSTMAC_RX_FLOW:432
ETHFW: REGISTER_MAC | S2C | status=0
tilld1: has mac: 70:FF:76:1D:EC:F2
tilld2: has mac: 70:FF:76:1D:EC:F2
cb_lld_task_create: Uniconf Task stack_size=16384
cb_rawsock_open:combase-1.1.3
Is=1 dmaRxChId=-1 nTxPkts=0 nRxPkts=0 pktSize=0
cb_lld_task_create: gPTP Task stack_size=16384
cbl_query_response:tilld1 link DOWN !!!!
cbl_query_response:tilld2 limax_ports=2
cb_rawsock_open:combase-1.1.3
cb_rawsock_open:dmaTxChId=1 numRxChannels=1 dmaRxChId=2 nTxPkts=16 nRxPkts=16 pktSize=1536
rxChId 2 has owner dmaRxSharedv:tilld2 open success
gptpnet_init:supportRtNotice=0 tout_interval=125000000Ns
gptpnet_init:Open lldtsync OK!
IEEE1588-2019 performance monitoring disabled.
current-log-gptp-cap-interval=3 initial-log-gptp-cap-interval=3
pp_glb_init: use-mgt-log-gptp-cap-interval=0
current-log-gptp-cap-interval=3 initial-log-gptp-cap-intervalerval=0
current-log-gptp-cap-interval=3 initial-log-gptp-cap-interval=3
static_domains_init: instance=0, di=0, pi=1, currentToutIntervalNs=125000000
syncIntervalNs=1200000,gPtpCapableMessageInterval=0
static_domains_init: instance=0, di=0, pi=2, currentToutIntervalNs=125000000
syncIntervalNs=125000000, announceInterval=0,pdelayReqInterval=10enet_activate:tilld1 status=0, duplex=1, speed=0Mbps
onenet_activate:tilld2 status=0, duplex=1, speed=0Mbps
GPTP_MEDIUM_ALLOC: fragsize=16 fragused/fragnum=865/944 (91)
INF:ub=19/74 (25)
SM_DATA_INST: fragsize=8 fragused/fragnum=2032/2032 (100)
domainIndex=0, GM changed old=00:00:00:00:00:00:00:00, new=70:FF:76:FF:FE:1D:EC:F2
INF:gptpnIndex=0, gmstate=2
Cpsw_handleLinkUp:1423
MAC Port 1: link up
cbl_query_response:tilld1: link UP, speed=1000, duplex=1 !!!! (138us since link change event)
[0]Network Link UP Event
index=1 speed=1000, duplex=full
Added interface 'br3', IP is 10.24.72.242
ETHFW: REGISTER_IPv4 | C2S | core=0 endpt=36 token=2600 ipAddr=10.24.69.84 macAdd=70:ff:76:1d:ec:e7
ETHFW:
SNo. MAC Address VLAN IP Address
ETHFW: ------ ------------------- ------ -----------------
ETHFW: 1 70:ff:76:1d:ec:e7 0 10.24.69.84
ETHFW: REGISTER_IPv4 | S2C | status=0
MCU-R5 Client Application logs
CpswProxy: Local cmd endpt 36, notify endpt 30
CpswProxy: ETHFW services found at core 1 endpts 34 (ti.ethfw.ethdevice) and 24 (ti.ethfw.notifyservice)
Starting lwIP, local interface IP is dhcp-enabled
[LWIPIF_LWIP] NETIF INIT SUCCESS
CpswProxy: ATTACH | C2S | virtPort=26
CpswProxy: ATTACH | S2C | token=2600 rxMtu=1522 features=3 numTxCh=1 numRxFlow=1 status=0
CpswProxy: ALLOC_TX | C2S | token=2600 chRelPri=0
CpswProxy: ALLOC_TX | S2C | token=2600 txPsil=0xc603 chRelPri=0 status=0
CpswProxy: ALLOC_RX | C2S | token=2600
CpswProxy: ALLOC_RX | S2C | token=2600 flow=20,5 rxPsil=0x4600 status=0
CpswProxy: ALLOC_MAC | C2S | token=2600
CpswProxy: ALLOC_MAC | S2C | token=2600 macAddr=70:ff:76:1d:ec:e7 status=0
CpswProxy: REGISTER_MAC | C2S | token=2600 flowIdx=20,5
CpswProxy: REGISTER_MAC | S2C | token=2600 status=0
Host MAC address : 70:ff:76:1d:ec:e7
[LWIPIF_LWIP] Enet has been started successfully
Added interface 'ti0', IP is 0.0.0.0
[0]Network Link UP Event
Added interface 'ti0', IP is 10.24.69.84
CpswProxy: REGISTER_IPv4 | C2S | token=2600 ipAddr=10.24.69.84 macAdd=70:ff:76:1d:ec:e7
CpswProxy: REGISTER_IPv4 | S2C | token=2600 status=0
Audio Stream Table
AVB streams are identified by an 8-byte Stream ID and a destination multicast MAC address. The last byte of both (referred to as the stream’s “App No.”, 0–5 in this demo) is what this demo uses to tell streams apart. All 3 default streams use VLAN ID 110 on MAC port 1:
App No. |
Stream ID |
Destination MAC |
Talker (TX) |
Listener (RX) |
AVB Class |
PCP |
Interval |
Channels |
Format |
Frame size |
|---|---|---|---|---|---|---|---|---|---|---|
0 |
00:01:02:03:04:05-00:00 |
91:E0:F0:00:FE:00 |
|
|
Class A |
3 |
125 μs |
16 |
48 kHz, 16-bit PCM |
192 bytes |
1 |
00:01:02:03:04:05-00:01 |
91:E0:F0:00:FE:01 |
|
|
Class D1 |
2 |
1000 μs |
8 |
48 kHz, 16-bit PCM |
768 bytes |
2 |
00:01:02:03:04:05-00:02 |
91:E0:F0:00:FE:02 |
|
|
Class A |
3 |
125 μs |
16 |
48 kHz, 16-bit PCM |
192 bytes |
In steady state:
avb_audio_sourcetransmits 2 streams (App No. 1 and 2) toavb_audio_sink, and receives 1 stream (App No. 0) sent back byavb_audio_sink.avb_audio_sinktransmits 1 stream (App No. 0) toavb_audio_source, and receives 2 streams (App No. 1 and 2) sent byavb_audio_source.
On the C7x side, PCM samples are exchanged with the R5F AVTP tasks through fixed-size shared-memory ring buffers:
Board |
Ring Buffer |
Base Address |
Block Size |
Carries |
|---|---|---|---|---|
|
Class A buffer |
|
192 bytes |
App No. 2 (Class A from source) |
|
Class D buffer |
|
768 bytes |
App No. 1 (Class D1 from source) |
|
Class A buffer |
|
192 bytes |
App No. 0 (Class A from sink) |
Adding or Removing Talker Streams {#AVB_ADD_REMOVE_TALKER}
All talker (TX) streams are configured in /source/networking/ethfw/apps/app_remoteswitchcfg_server/sitara/ethfw_avtp.c.
To add a talker stream on a board:
Define the stream by adding a new
#define AAF_TX_<name>_APPNO <appno>(picking a free App No. from 0–5) and its correspondinginit_aaf_pcm_talker("tilld1", AAF_TX_<name>_APPNO, <intervalUs>, <channels>);call insideEnetApp_talkerTask(). Note:EnetApp_talkerTask()already has two spare Class D1 slots stubbed out (AAF_TX_CLASS_D1_2_APPNO,AAF_TX_CLASS_D1_3_APPNO)—to use one, simply uncomment and set the define; no further code change is needed, as the matchinginit_aaf_pcm_talker()call is already guarded by#ifdef.On the peer board, enable a matching listener stream (see below) with the same App No. so it knows to expect the new stream.
Rebuild the R5F server app for both boards (
ethfw_avtp.cis part of theavb_audio_source/avb_audio_sinkR5F build) and the C7x remote app if the new stream needs to reach the DSP.
To remove a talker stream:
Remove (or comment out) the corresponding
AAF_TX_*_APPNOdefine—itsinit_aaf_pcm_talker()call is#ifdef-guarded and will be skipped automatically.Remove the matching
AAF_RX_*_APPNOdefine on the peer board so it stops expecting that stream.
Adding or Removing Listener Streams {#AVB_ADD_REMOVE_LISTENER}
All listener (RX) streams are also configured in ethfw_avtp.c.
To add a listener stream:
Add a
#define AAF_RX_<n>_APPNO <appno>for the App No. you want to receive (must match the App No. used by the talker on the peer board), following the pattern of the existingAAF_RX_1_APPNO/AAF_RX_2_APPNO.enable_monitor_stream()automatically starts logging packet counts for any ofAAF_RX_1_APPNOthroughAAF_RX_4_APPNOthat is defined—up to 4 monitored RX streams, no extra code needed for monitoring alone.Only
AAF_RX_1_APPNOandAAF_RX_2_APPNOhave a shared-memory ring buffer wired up instart_aaf_pcm_listener()today. If you addAAF_RX_3_APPNO/AAF_RX_4_APPNO(or repurpose the existing ones) and want that audio delivered to the C7x core, you must also allocate a ring buffer for it there (aaf_init_shm()+gaudioListener.shmHandle[<appno>], sized to the stream’s frame size), and updateremote_main.cto read from it. Note:enable_monitor_stream()only logs packet counts; it does not forward audio to the DSP unless a shared-memory buffer is allocated.audio_aaf_avtp_push_packet()unconditionally callsshm_write()on whatever handle is registered for an incoming App No., so a stream without a ring buffer allocated for it will fail to be delivered.
To remove a listener stream:
Remove (or comment out) the corresponding
AAF_RX_*_APPNOdefine—enable_monitor_stream()andaudio_aaf_avtp_push_packet()skip App Nos. that aren’t defined.Remove its ring buffer allocation from
start_aaf_pcm_listener()/remote_main.cif one was added, and also delete any correspondingshm_write()calls if they were added manually.
Attention
The App No. (last byte of the Stream ID and multicast MAC) must be unique per stream and identical on both the talker and the listener side of that stream—it is how audio_aaf_avtp_push_packet() demultiplexes incoming packets into gaudioListener.rxstreams[streamId].
MAC-only port
Ethernet Firmware enables MAC-only mode on MAC port 2 for AM62Dx, this allows all incoming traffic from MAC port 2 to be transferred only to the host port. This effectively excludes the MAC port from rest of packet switching in the CPSW switch.
The key concepts of a system with MAC-only mode enabled are as follows:
Logical switch ports - Defined based on packet header match criteria, typically created based on destination MAC address, VLAN IDs, etc. Two possible types:
Local Switch port - owned exclusively by Ethernet Firmware.
Virtual Switch port - owned by remote clients.
Logical MAC-only ports - Defined with 1-to-1 correspondence to physical ports (port configured in MAC-only mode), owned by remote clients.
Virtual MAC port - owned by remote clients.
The default port configuration for AM62Dx is shown below:
Port Configuration
Enable MAC-only mode on MAC port 2 {#MAC_ONLY_PORT}
Add
-DENABLE_MAC_ONLY_PORTSflag toDEFINES_commonin the client app, server app and ethfw library makefilesClient app makefile in
<SDK_INSTALL_PATH>/source/networking/ethfw/apps/app_remoteswitchcfg_client/sitara/<device>/<core_os_combo>/ti-arm-clang/makefileServer app makefile in
<SDK_INSTALL_PATH>/source/networking/ethfw/apps/app_remoteswitchcfg_server/sitara/<device>/<core_os_combo>/ti-arm-clang/makefileEthfw device specific lib makefiles in
<SDK_INSTALL_PATH>/source/networking/ethfw/makefile.cpsw.<device>.<core>.ti-arm-clang
Set
numMacAddress = 2for MCU-R5 in the structure defined inenet_cpsw_top.syscfg.js:
MAC Address Setting
Make the following changes to the server app example.syscfg
Add an additional MAC address for the Virtual MAC port in
System Integration > MAC Address ListIncrease the large pool packet count to 80 in
Packet Pool Config > Large Pool Packet CountEnable No learning and MAC-only mode for MAC port 2 as below in
ALE Config > ALE Port Config
ALE Port Configuration
- Next, the `ALE Config > ALE Port Config > Port default VLAN config` for MAC ports and Host port needs to be modified as below (highlighted sections have been modified):
VLAN Configuration
Make the following changes to the client app example.syscfg
Add an additional netif and increase the number of MAC addresses for the Rx DMA channel as below
Netif Configuration Changes
Rebuild the libraries first, then the apps before loading the binaries.
See Also
Glossary
CPSW: Common Platform Ethernet Switch
ALE: Address Lookup Engine
gPTP: Generalized Precision Time Protocol (IEEE 802.1AS)
AVTP: Audio Video Transport Protocol
VLAN: Virtual Local Area Network
MAC-only: MAC-only port mode
R5F: ARM Cortex-R5F core
C7x: TMS320C7x DSP core
MCU-R5: MCU domain Cortex-R5F core
Device Under Test (DUT): Physical board being tested
App No.: Application number (stream identifier)
Class D1: The first of up to four Class D AVTP streams in the autoamp application. Class D uses a 1000 μs transmit interval; the numeric suffix (D1, D2, …) distinguishes multiple Class D streams within the same demo.