Reader are expected to have basic knowledge on below IEEE specifications
This guide is intended to enhance user's understanding of the TSN stack and provide guidance on how to seamlessly integrate TSN modules into their own applications.
Ethernet TSN CPSW gPTP Bridge Example
Ethernet TSN CPSW gPTP TimeReceiver (gPTP Slave) Example
Ethernet TSN CPSW gPTP TimeTransmitter (gPTP Master) Example
TSN stack library is pre-built in SDK and located in <mcu_plus_sdk>/source/networking/enet/core/examples/tsn
directory as .lib files. Any changes in the stack source code needs rebuild of library. In order to re-build the library, follow the below steps-
The TSN Stack library is composed of the following source modules:
Module Name | lcoation | Description |
---|---|---|
Unibase | <mcu_plus_sdk>/source/networking/tsn/tsn_unibase | Universal utility libraries that are platform-independent |
Combase | <mcu_plus_sdk>/source/networking/tsn/tsn_combase | Communication utility libraries that provide support for functions like sockets, mutexes, and semaphores |
Uniconf | <mcu_plus_sdk>/source/networking/tsn/tsn_uniconf | Universal configuration daemon for Yang, provides APIs for developing a client application which retreives/writes yang parameters from/to database |
gPTP | <mcu_plus_sdk>/source/networking/tsn/tsn_gptp | Implementation of the IEEE 802.1 AS gptp protocol |
A reference example of the TSN stack initialization can be found in <mcu_plus_sdk>/source/networking/enet/core/examples/tsn/tsninit.c
. Prior to any module calls, it is necessary to initialize the unibase library once. This can be achieved by invoking the EnetApp_initTsnByCfg()
function.
By default, TSN logs are directed to STDOUT using the fwrite function: fwrite(str, 1, strlen(str), stdout);
However, it is possible to customize the log output by setting the Logger_init(cfg->consoleOutCb)
callback during the initialization of the unibase library in the EnetApp_initTsnByCfg()
function.
When a callback function is assigned to consoleOutCb
it takes a significant amount of time to log to the output device, it is advisable to log to a buffer and utilize another task to log from the buffer to the desired output device. This approach helps to prevent log delays that could adversely affect the gPTP task, such as incorrect Sync and FollowUp intervals. The option to log to a buffer is supported when the TSN_USE_LOG_BUFFER
macro is defined.
To enable specific log levels, you can modify the ub_log_initstr parameter in the EnetApp_initTsnByCfg(
) function. There are eight log levels available::
For example: init_para.ub_log_initstr = "4,ubase:45,cbase:45,gptp:55,uconf:45";
In the above example, uconf:45
signifies the following:
4 (INFO)
: Log level for printing to the console. 5 (INFOV)
: Log level for storing in internal memory (which can be dumped to a file).
Please note that enabling the DEBUG or DEBUGV level will result in a large number of logs being generated. If the log buffer is used, it may overflow, causing some logs to be lost.
The first '4' character in "4,ubase...
represents the default log level applied to all modules.
The gPTP functionality operates in a separate task, alongside the universal configuration daemon "uniconf". To start these tasks, use the EnetApp_startTsn()
in tsninit.c as reference .
This function will start the uniconf and gPTP tasks.
To deinitialize the TSN modules, you can invoke the EnetApp_stopTsn();
and EnetApp_deInitTsn();
functions.
To integrate the TSN stack into your application, follow these steps:
Initialize Enet LLD and setup board dependencies. In the TSN example application, the initialization routines can be found at <mcu_plus_sdk>/source/networking/enet/core/examples/tsn/tsnapp_cpsw_main.c.c
, which can be used as reference.
The main functions related to EVM board initialization are::
These functions are responsible for configuring pinmux, GPIOs, etc., as well as providing the MAC port and PHY configuration parameters, which are board specific.
EnetApp_initTsnByCfg()
.In the above code, the Ethernet device name and MAC port are required to create a virtual Ethernet device table that facilitates the conversion between the device name and the MAC port number.
In the above code, the Ethernet device name and MAC port are required to create a virtual Ethernet device table that facilitates the conversion between the device name and the MAC port number.
Please ensure that the ethdevs[i].netdev
pointer points to a global memory location rather than a stack memory. The combase layer will reference this address instead of making a copy.
If the "ethdevs[i].srcmac" is either unset or set to all zeroes, the "combase" will allocate a source MAC address. If the user's application requires manual assignment of a source MAC address to the interface, please ensure to set the "ethdevs[i].srcmac" variable accordingly.
cb_socket_set_lldcfg_update_cb()
` The parameter for this function is a callback function that updates the cb_socket_lldcfg_update_t values.EnetApp_startTsn()
. This will start the necessary threads for gPTP and uniconf. The uniconf, gPTP tasks are stored in EnetApp_ModuleCtx_t gModCtxTable
task's table.Universal configuration daemon for Yang, provides APIs for developing a client application which retreives/writes yang parameters from/to database and ask the uniconf for configurating HW.
Uniconf supports the following config paramaters:
dbname
: Specify the path of database file in the file system. If user wants to write all config parameters to database file to make the config parameter persist after a reboot, the full path of database file must be set via this parameter. Currently, as file system is not supported, this parameter is set to NULL
.configfiles
: array of runtime config files will be used by the uniconf. Run time config file is a text file which has one-to-one mapping with yang files, the format of each line of a run time config file is specified under <mcu_plus_sdk>/source/networking/tsn/tsn-stack/tsn_uniconf/README.org
. Currently, as file system is not supported, this parameter is set to NULL
.numofconfigfile
: Specify how many config files have been set via the the configfiles
array above. Currently, this parameter is set to 0
.ucmode
: This is for setting the expected mode of uniconf. The uniconf can only run in a separated thread, please set UC_CALLMODE_THREAD|UC_CALLMODE_UNICONF
for this parameter.stoprun
: Address to a flag which signals the uniconf to stop in case the flag is true.rval
: Error code of the uniconf in case error occurs.ucmanstart
: The name of semaphore or a semaphore object in case of FreeRTOS. If this parameter is not NULL
, the uniconf will post this semaphore to signal application layer indicating that it has been started successfully.hwmod
: Configure the HW for the uniconf. If an empty string is specified (hwmod=""), it means the uniconf will configure HW. If "NONE" is specified (hwmod="NONE"), the uniconf will not configure HW when client side writes the database and ask it for an update.This section describes the standard Yang parameters utilized for gPTP.
This implementation assumes user familiarity with the IEEE 1588 and 802.1AS YANG standards, and the mapping of these standards to our key-based enumeration. The gptp stack is developed based on below YANG standard:
First of all, the key-based (uint8_t) enums which are used to map with YANG (string-based) are generated during initialization. For example, the corresponding ptp generated enum are defined in <mcu_plus_sdk>/source/networking/tsn/tsn-stack/tsn_uniconf/yangs/cores/generated/ieee1588-ptp-tt.h
This section will explain on how to map between generated key-based and string-based.
Consider priority1 (assuming 248) in ieee1588-ptp-tt.yang, which should have string-based like below:
/ieee1588-ptp-tt/ptp/instances/instance|instance-index:0|/default-ds/priority1
The corresponding key-based array for priority1 will be:
k[0]
is IEEE1588_PTP_TT_RW to indicate the entry is configurable, similar with YANG model config true;
.User must take note and understand the YANG standard, to understand the entry is configurable or not.
In our example, the setting 'true' in EnetApp_DbKeyVal_IntItem_t
is to indicate whether the entry is RW or RO.
|instance-index:0|
: will be described in next section, together with ieee1588-ptp-tt_access.*
Beside of generated files eg:ieee1588-ptp-tt.h, there is APIs helper for each YANG generated file, named *access.h/c. Eg: for ieee1588-ptp-tt.yang, the corresponding helper will be ieee1588-ptp-tt_access.c/h.
The ieee1588-ptp-tt_access
provide wrapper APIs for quicker access ieee1588-ptp-tt
entries. Consider below set of APIs:
The suffix of ptk3vk0
can be extracted into 3 parts:
pt
is for ieee1588-ptp-ttk3
means the input will have 3 keys andvk0
no value key after instance-index
The uint32_t instIndex
is used to get corresponding |instance-index:0|
which we need in previous section. Please refer to set_dpara_k4vk1
for more detail of using instIndex.
The higher level DB API wrapper, which is using specificly for gptp, is defined in <mcu_plus_sdk>/source/networking/tsn/tsn-stack/tsn_gptp/gptpconf/gptpgcfg.h
.
Let's walk-through all of yang configuration those are using in <mcu_plus_sdk>/source/networking/enet/core/examples/tsn/gptp_init.c
.
KEY | Refer YANG's items | Short Explain |
---|---|---|
IEEE1588_PTP_TT_LOG_ANNOUNCE_INTERVAL | ieee1588-ptp-tt:log-announce-interval | Logarithm to the base 2 (log2(x)) of Announce Interval |
IEEE1588_PTP_TT_ANNOUNCE_RECEIPT_TIMEOUT | ieee1588-ptp-tt:announce-receipt-timeout | same with GPTP Cap timeout, apply for Announce packets |
IEEE1588_PTP_TT_INITIAL_LOG_ANNOUNCE_INTERVAL | ieee1588-ptp-tt:log-announce-interval | Default Init log2(x) of Announce Interval |
IEEE1588_PTP_TT_INITIAL_LOG_SYNC_INTERVAL | ieee802-dot1as-gptp:initial-log-sync-interval | Default Init log2(x) of Sync Interval |
IEEE1588_PTP_TT_LOG_SYNC_INTERVAL | ieee1588-ptp-tt:log-sync-interval | log2(x) of Sync Interval |
IEEE1588_PTP_TT_SYNC_RECEIPT_TIMEOUT | ieee802-dot1as-gptp:sync-receipt-timeout | same with GPTP Cap timeout, apply for Sync packets |
IEEE1588_PTP_TT_CURRENT_LOG_SYNC_INTERVAL | ieee802-dot1as-gptp:current-log-sync-interval | Current value of log-sync-interval |
IEEE1588_PTP_TT_INITIAL_LOG_PDELAY_REQ_INTERVAL | ieee802-dot1as-gptp:initial-log-pdelay-req-interval | Default Init log2(x) of PdelayReq Interval |
IEEE1588_PTP_TT_CURRENT_LOG_PDELAY_REQ_INTERVAL | ieee802-dot1as-gptp:current-log-pdelay-req-interval | Current value of log-pdelay-req-interval |
IEEE1588_PTP_TT_INITIAL_LOG_GPTP_CAP_INTERVAL | ieee802-dot1as-gptp:initial-log-gptp-cap-interval | Default Init log2(x) of GptpCapable Interval |
IEEE1588_PTP_TT_USE_MGT_LOG_GPTP_CAP_INTERVAL | ieee802-dot1as-gptp:use-mgt-log-gptp-cap-interval | False: Allow gptp-cap-interval can be changed by message Interval Request Signaling and True: Not allow, use default mgt-log-gptp-cap-interval |
IEEE1588_PTP_TT_MGT_LOG_GPTP_CAP_INTERVAL | ieee802-dot1as-gptp:mgt-log-gptp-cap-interval | Default value in case of use-mgt-log-gptp-cap-interval is False |
IEEE1588_PTP_TT_GPTP_CAP_RECEIPT_TIMEOUT | ieee802-dot1as-gptp:gptp-cap-receipt-timeout | GPTP Capable timeout time = Cap Interval * gptp-cap-receipt-timeout |
IEEE1588_PTP_TT_CURRENT_LOG_GPTP_CAP_INTERVAL | ieee802-dot1as-gptp:current-log-gptp-cap-interval | Current gptp-cap-interval value |
IEEE1588_PTP_TT_ALLOWED_LOST_RESPONSES | ieee802-dot1as-gptp:allowed-lost-responses | Maximum number of lost Pdelay_Respond/Follow_up of a PdelayRequest |
IEEE1588_PTP_TT_ALLOWED_FAULTS | ieee802-dot1as-gptp:allowed-faults | Number of faults above which asCapable is set to false |
IEEE1588_PTP_TT_MEAN_LINK_DELAY_THRESH | ieee802-dot1as-gptp:mean-link-delay-thresh | Threshold of a pdelay calculated. If it's higher than this threshold, port is not consider capable |
IEEE1588_PTP_TT_PORT_ENABLE | ieee1588-ptp-tt:port-enable | Must be True |
IEEE1588_PTP_TT_MINOR_VERSION_NUMBER | ieee1588-ptp-tt:minor-version-number | Minor PTP version number |
IEEE1588_PTP_TT_INITIAL_ONE_STEP_TX_OPER | ieee802-dot1as-gptp:initial-one-step-tx-oper | Init value of using one-step-tx, in our stack, we ONLY apply two-step-tx, so the value must be False |
IEEE1588_PTP_TT_CURRENT_ONE_STEP_TX_OPER | ieee802-dot1as-gptp:current-one-step-tx-oper | Current value of one-step-tx |
IEEE1588_PTP_TT_MGT_ONE_STEP_TX_OPER | ieee802-dot1as-gptp:mgt-one-step-tx-oper | Default case one-step-tx if use-mgt-one-step-tx-oper is true |
IEEE1588_PTP_TT_USE_MGT_ONE_STEP_TX_OPER | ieee802-dot1as-gptp:use-mgt-one-step-tx-oper | Must be False as we do not support one-step-tx |
IEEE1588_PTP_TT_PRIORITY1 | ieee1588-ptp-tt:priority1 | Use to configure ptp priority1 |
IEEE1588_PTP_TT_PRIORITY2 | ieee1588-ptp-tt:priority2 | Use to configure ptp priority2 |
IEEE1588_PTP_TT_EXTERNAL_PORT_CONFIG_ENABLE | ieee1588-ptp-tt:external-port-config-enable | We are not allow external-port-config-enable, so it should be False |
IEEE1588_PTP_TT_TIME_SOURCE | ieee1588-ptp-tt:time-source | Config time-source, refer YANG for possible value |
IEEE1588_PTP_TT_PTP_TIMESCALE | ieee1588-ptp-tt:ptp-timescale | Config ptp-timescale, refer YANG for possible value |
IEEE1588_PTP_TT_CLOCK_CLASS | ieee1588-ptp-tt:clock-class | Config clock-class, refer YANG for possible value |
IEEE1588_PTP_TT_CLOCK_ACCURACY | ieee1588-ptp-tt:clock-accuracy | Config clock-accuracy, refer YANG for possible value |
IEEE1588_PTP_TT_OFFSET_SCALED_LOG_VARIANCE | ieee1588-ptp-tt:offset-scaled-log-variance | Config offset-scaled-log-variance, refer YANG for possible value |
IEEE1588_PTP_TT_INGRESS_LATENCY | ieee1588-ptp-tt:ingress-latency | Config this if you know the internal ingress-latency of a rx ptp packets. Currently the value is 0 |
IEEE1588_PTP_TT_EGRESS_LATENCY | ieee1588-ptp-tt:egress-latency | Config this if you know the internal egress-latency of a tx ptp packets. Currently the value is 0 |
For more accessible parameters along with the default values in gPTP example, please refer to the file located at: -<mcu_plus_sdk>/source/networking/tsn/tsn-stack/tsn_gptp/gptpconf/gptp-yangconfig.xml
.
In addition to the standard Yang parameters, gPTP also includes a set of non-Yang configuration parameters that are specific to its implementation.
To modify the default value of the Non-Yang parameters, please refer to the gptp_nonyang_config()
function in the gptp_init.c
file. This function will invokes gptpgcfg_set_item()
to configure each params:
gptpInstanceIndex
: Index of the gptp to be configured. For TI FreeRTOS there is only one instance is applicable, this should be set to 0.confitem
: The configuration item. To create an item, prepend the parameter name from the gptp_nonyangconfig.xml with the "XL4_EXTMOD_XL4GPTP" prefix, as follows: "USE_HW_PHASE_ADJUSTMENT" becomes "XL4_EXTMOD_XL4GPTP_USE_HW_PHASE_ADJUSTMENT."status
: YDBI_CONFIG
or YDBI_STATUS
. YDBI_CONFIG
is used to configure the parameter at runtime. YDBI_STATUS
is used to configure the parameter at runtime and store the value in the database for persistence.value
: Pointer to the value to be set.vsize
: Size of the value to be set, for the items.Example usage: gptpgcfg_set_item(gpoptd.instnum, XL4_EXTMOD_XL4GPTP_USE_HW_PHASE_ADJUSTMENT, YDBI_CONFIG, &use_hwphase, sizeof(use_hwphase));
<mcu_plus_sdk>/source/networking/enet/core/examples/tsn/gptp_init.c
file.gptpman_run()
function inside the gptp_init.c
file, and it should follow the the gptpgcfg_init function call.KEY | Short Explain |
---|---|
SINGLE_CLOCK_MODE | Set 1 for single clock with multiple ports |
USE_HW_PHASE_ADJUSTMENT | Set 1 to make the adjustment apply on HW clock |
FREQ_OFFSET_IIR_ALPHA_START_VALUE | ptp clock offset and freq adjustment IIR filter coefficients reciprocal number is used at the beginning |
FREQ_OFFSET_IIR_ALPHA_STABLE_VALUE | ptp clock offset and freq adjustment IIR filter coefficients reciprocal number is used after stable time |
PHASE_OFFSET_IIR_ALPHA_START_VALUE | ptp clock offset and freq adjustment IIR filter coefficients reciprocal number is used at the beginning |
PHASE_OFFSET_IIR_ALPHA_STABLE_VALUE | ptp clock offset and freq adjustment IIR filter coefficients reciprocal number is used after stable time |
MAX_DOMAIN_NUMBER | Support up to 2 domains |
QUICK_SYNC_ALGO | Enables the slave clock to match the master's rate before applying phase offset adjustments. |
SKIP_FREQADJ_COUNT_MAX | Number of Sync message cycle in which freq adjustment will be skipped after offset has just been adjusted. |
PHASE_OFFSET_ADJUST_BY_FREQ | Sets the phase offset adjustment threshold in nanoseconds. |
FREQ_OFFSET_STABLE_PPB | Stable adjustment determination and thresholds freq. adjustment is considered stable if delta of adj rate is less then this threshold |
FREQ_OFFSET_UPDATE_MRATE_PPB | update freq offset only when the abs of diff to the new rate is bigger than this |
STATIC_PORT_STATE_SLAVE_PORT | -1: Enable BMCA mode, 0: Disable BMCA and all ports are GM, >0: Disable BMCA, the selected port is Slave port, and other ports are master port |
SUPPORT_RUNTIME_NOTICE_CHECK | Enable this flag, then gptp stack will listener for event to trigger Message Interval Request signaling to the other side |
CLOCK_COMPUTE_INTERVAL_MSEC | compute phase and freq every this time |
CMLDS_MODE | In case of number of domain is 2, CMLDS_MODE must be True to apply common link delay |
SECOND_DOMAIN_THIS_CLOCK | In case of number of domain is 2, this flag also need to be set to one to indicate software clock mode |
To access the list of these parameters, along with their descriptions and default values for gPTP, please refer to the file located at: <mcu_plus_sdk>/source/networking/tsn/tsn-stack/tsn_gptp/gptpconf/gptp_nonyangconfig.xml
.
At the moment, our system supports two domains, but this feature is turned off by default. To turn on multiple domains, follow these steps:
#define GPTP_MAX_DOMAINS 2
in the <mcu_plus_sdk>/source/networking/tsn/tsn-stack/tsn_buildconf/sitara_buildconf.h
file<mcu_plus_sdk>/source/networking/enet/core/examples/tsn/gptp_init.c
, you will see the following settings are set: This will activate the second domain in the gPTP system.
By default, the gPTP Sync interval is set to 125 milliseconds (log2(0.125)=-3) which is corresponding to the default SYNC_LOG value is -3 (refer gptp_init.c
)
#define SYNC_LOG -3 // Default: 125ms
If you need a shorter Sync interval (eg: apply for Quick SYNC), you can adjust it by setting a specific value in the gptp_init.c
file:
As explained in previous section, the SYNC_LOG will be applied to ieee802-dot1as-gptp:log-sync-interval
, and the gptp stack will base on the setting to have proper SYNC interval.
This SYNC_LOG understanding is also applicable for:
Out of box configuration is not optimized for performance as the connected devices (e.g. Intel I218/219) may not be compatible with these optimal configuration. The following configurations can be tuned for optimizing the gPTP performance:
XL4_EXTMOD_XL4GPTP_CLOCK_COMPUTE_INTERVAL_MSEC
: The interval in milliseconds at which the gPTP clock is computed. The default value is currently set to 1000
, and has a parameter vsize of 1
(uint8_t).XL4_EXTMOD_XL4GPTP_FREQ_OFFSET_UPDATE_MRATE_PPB
: The rate at which the frequency offset is updated. The default value is currently set to 10
, and has a parameter vsize of 4
(uint32_t).XL4_EXTMOD_XL4GPTP_PHASE_OFFSET_IIR_ALPHA_STABLE_VALUE
: The reciprocal of this is the alpha value of the IIR filter used to compute the phase offset. The default value is currently set to 10
, and has a parameter vsize of 4
(uint32_t).XL4_EXTMOD_XL4GPTP_FREQ_OFFSET_IIR_ALPHA_STABLE_VALUE
: The reciprocal of this is the alpha value of the IIR filter used to compute the frequency offset. The default value is currently set to 10
, and has a parameter vsize of 4
(uint32_t).e.g. The following is an example configuration which you can use in the example to get better accuaracy if compatible with your devices in the setup. The following configuration is tested with the Intel I210 card and in between two EVMs.
For all parameters related to interval, the minimum interval can be configured for gPTP is 7.8125ms. The reason for that minimum interval is the implementation uses a base timer which has minimum period is 7.8125ms. Thus, increasing the interval parameters like sync-interval
which is not a multiple of 7.8125ms may produce inaccurate interval of sending sync message.Or reducing interval of sync message below 7.8125ms is not possible. And the same limitation applied for all remaining interval parameters.