This chapter explains how to build a user application for the host CPU using the ICS software that communicates with a TICS100MOD module.
The application builds on the files generated by the ICS Configurator (device_settings.c, channel_settings.c, repository.c, target_firmware.c); see Configurator. It covers the application lifecycle, project settings, the platform interfaces (HAL and OSAL), the callbacks the application provides, protocol initialisation, and object access. Reference applications are in the SDK examples/ics-host folder; see Examples.
The user application drives the system lifecycle by calling the ICS software layer through an ordered sequence of setup, run, and shutdown steps. Each step builds on the previous one, from creating the ICS instance through to destroying it, and the reference applications repeat this sequence in a loop to support restarts.
Ics_create — create the ICS instance.Ics_initialize — creates device and channel objects; calls IcsUser_getDeviceConfig and IcsUser_getChannelConfig. No SPI traffic yet.Ics_getDevice, then IcsDevice_getDefaultRepository — get the device and its repository.IcsChannelSettings_setParameter (ICS_CHANNEL_SETTINGS_SERIAL_NUMBER, ICS_CHANNEL_SETTINGS_MAC_ADDRESS).Ics_start — communication with the module starts here: opens the device, identifies the module, downloads (or boots from flash) the protocol firmware, sends channel init, sends channel settings via IcsUser_getChannelSetting, builds the repository via the generated IcsCommChannel_buildRepository (which ends by calling IcsRepository_initialize), then starts the channel.Ics_stop, IcsDevice_reset(device, IcsDeviceResetType_Hard), Ics_shutdown, Ics_destroy. The application may then start again from step 1.The reference applications run steps 1–8 in a loop and restart when a restart flag is set — for example, when the EtherNet/IP controller sends an Identity Reset (their reset handler sets the flag) or on terminal firmware commands. This restart handling is part of the reference applications and can be copied directly.
Before building a user application, the project must be configured according to the selected host platform operating system (e.g. Linux, FreeRTOS, etc.) and the target industrial communication protocol (PROFINET, EtherCAT or EtherNet/IP).
The ICS software includes platform abstraction layers, such as the Hardware Abstraction Layer (HAL) and Operating System Abstraction Layer (OSAL), allowing the same application code to be used across different environments. As part of the project configuration, the appropriate HAL and OSAL source files must be selected based on the target platform and operating system. In addition, platform- and protocol-specific source files that are not required by the application should be excluded from the build, and the corresponding preprocessor macros must be defined.
This chapter describes the required project settings, including source file selection and predefined compiler macros for the supported operating systems and industrial communication protocols.
Unless otherwise stated, all file and folder paths referenced in this chapter are relative to the SDK root directory.
The ICS software uses a Hardware Abstraction Layer (HAL) to isolate platform-specific functionality from the ICS software. Multiple HAL implementations are provided to support different host platforms and operating environments.
The HAL sources are located under:
Each subfolder within this directory contains the HAL implementation for a specific platform and operating system combination (for example, linux for Linux-based systems and ti-spd for TI-based FreeRTOS platforms).
When configuring the project, the folder corresponding to the target platform shall be included in the build, together with all its contained source files and subfolders. HAL folders that do not match the selected platform should be excluded from the build.
This ensures that the ICS software uses the correct hardware-specific implementation for the target platform.
The ICS software uses an Operating System Abstraction Layer (OSAL) to provide a common interface to operating system services. This allows the framework and user application to be used across different operating systems without requiring changes to the core software.
The OSAL sources are located under:
Each subfolder within this directory contains the OSAL implementation for a specific operating system (for example, linux for Linux-based systems and freertos for FreeRTOS-based systems).
When configuring the project, the folder corresponding to the operating system used by the application shall be included in the build, together with all its contained source files and subfolders. OSAL folders that do not match the selected operating system should be excluded from the build.
This ensures that the framework uses the appropriate operating system services for the target environment.
The ICS software includes protocol-specific components that provide support for the selected industrial communication protocol. Depending on the protocol used by the application, the corresponding protocol sources shall be included in the build.
The protocol-specific sources are located under:
The following folders are available:
When configuring the project, the folder corresponding to the selected industrial protocol shall be included in the build, together with all its contained source files and subfolders. Protocol folders that do not match the selected protocol should be excluded from the build.
This ensures that the protocol-specific functionality (e.g. built-in objects) required by the selected industrial communication protocol is available to the framework and user application.
The example applications also contain a folder per protocol (ics_protocol_<protocol>.c and a gen/ folder with the Configurator-generated files). Include the folder of the selected protocol and exclude the others.
In addition to the HAL, OSAL, and protocol-specific sources described in the previous sections, other files and folders may need to be excluded from the build.
Folders (excluded):
Files (excluded):
Folders (excluded):
Files (excluded):
The ICS software uses a set of predefined compiler symbols to enable and disable some features and functionalities. These symbols shall be added to the project's compiler settings before building the application.
The following table summarizes the predefined compiler symbols that must be configured in the project settings.
| Macro | Description | Required |
|---|---|---|
MEMORY_BUFFER_SIZE | Size in bytes of the static buffer used for one-time allocations (Mem_allocOnce), for example by the terminal. The build stops with #error if it is not defined. Reference projects use 0x2000. | Yes (always) |
HAL_SPI_ENABLED, HAL_PIN_ENABLED, HAL_ICU_ENABLED, HAL_TIMER_ENABLED | Enable the Hal_getSpiInstance, Hal_getPinInstance, Hal_getIcuInstance and Hal_getTimerInstance functions of the Linux HAL. | Linux only |
HAL_LINUX_USE_LIB_GPIOD | Select the libgpiod based GPIO implementation of the Linux HAL. | Linux only |
ICS_HOST_AM64, ICS_HOST_RASPBERRY_PI or ICS_HOST_BEAGLEBONE | Select the board in the Linux example application. Define exactly one. | Linux example application |
ENABLE_TRACING | Enable the TRC_* trace output. | Recommended |
SPI_TRANSFER_ACTIVE_WAIT_ENABLED | 1: wait for the module's Busy signal by polling a flag set from the Busy interrupt, so no OSAL event is needed. Default 0: wait on an OSAL event with timeout. The FreeRTOS example uses 1. | Optional |
RESET_TARGET_ON_STARTUP | Reset the module through the reset pin in the example HalInit_initializeHalTypes(). | Optional |
ICS_MAX_DATA_SIZE | Maximum SPI frame size in bytes, default 1536. Must not be larger than the value used by the module firmware. | Optional |
The ICS framework is designed to be portable across different hardware platforms and operating systems through the Hardware Abstraction Layer (HAL) and Operating System Abstraction Layer (OSAL).
When porting the framework to a new platform, implementations of the required HAL and OSAL interfaces must be provided. The ICS software relies on these interfaces to access hardware resources, perform communication, manage timing, and provide operating-system services.
The following sections describe the interfaces required by the ICS software; reference implementations are hal/source/linux, hal/source/ti-spd, osal/source/linux, osal/source/freertos.
The HAL implementation is responsible for providing access to platform-specific hardware resources.
Called once at start-up before any instance is requested. The reference implementations return true; the instance set-up is done in the application's HalInit_initializeHalTypes() (see Platform Initialization).
These functions return hardware objects associated with the specified logical channel.
The returned objects are used by the framework to access platform-specific peripherals without depending on hardware-specific implementations.
GPIO services are used by the framework for:
Depending on the communication role, additional GPIO instances may be required by the transport layer. In particular, slave-side implementations require a Busy output signal used to indicate transfer readiness.
These functions provide the communication channel between the host processor and the TICS100MOD module.
The current host application does not require asynchronous data transfers. Therefore, Spi_transferAsync() can be implemented as an empty stub.
The ICU interface is used to monitor communication handshake signals generated by the TICS100MOD module.
The framework uses these services to detect signal transitions and receive event notifications.
ICU callbacks use a linked list (QDLinkedInNoCalList). The pattern:
Icu_registerLevelDetectionCallback(icu, &callback) — appends to listIcu_notify(icu) → IntHandler_notifyHandler() walks listspi_transfer_handler.c registers its own callbacks (RequestFeedCallback, BusyFeedCallback) during SpiTransferHandler_start()So your GPIO ISR must call:
Timer services are used internally by the framework to implement timeout supervision and delayed processing.
Returns a monotonically increasing timestamp in microseconds.
This service is used by framework diagnostics and terminal logging functionality.
Invalidates cached memory before accessing data that may have been modified by another processing entity.
The current host application does not require explicit cache maintenance. This function may therefore be implemented as an empty stub.
Example:
Required when the terminal (Terminal, UartTerminal) is built, as in the FreeRTOS example. Functions used: Hal_getUartInstance, Uart_start, Uart_enableRxNotification, Uart_registerRxCallback/Uart_registerTxCallback (and the Data variants), Uart_receiveAsync, Uart_cancelReceiveAsync, Uart_sendAsync. See Hal.h for the prototypes.
The generated device configuration contains the hardware instance identifiers expected by the framework.
Example:
The generated host application expects the following hardware instances to be available:
00 used as the Host Request signal0 used as the Busy Feedback signal1 used as the Request Feedback signal10 used as the optional hardware reset signalAccordingly, the platform initialization shall provide valid implementations for:
These channel assignments are generated by the SDK and are expected by the generated application software. The platform-specific initialization code shall therefore create and register matching hardware instances for these identifiers.
The reference implementation performs the following initialization sequence:
The Request Feedback signal is configured for falling-edge detection because communication requests are initiated by driving the Request signal LOW.
When porting the framework to a different platform, equivalent hardware resources shall be created and registered for these instance identifiers before communication with the TICS100MOD module is started.
The host holds Request low to start a transaction; the module signals that it is ready by driving Busy high, which the host sees as a rising edge on the BusyFeed input; the host then clocks the data and sets Request high. The module can start a transfer by driving its request line low, seen as a falling edge on RequestFeed. SPI settings: mode 0, 8 bit, MSB first, 1 MHz (from the connection string). A Clock greater than 0 selects the master role.
The OSAL implementation provides access to operating-system services required by the framework.
Creates and destroys thread objects used by the framework.
These functions provide thread creation, execution control, and priority management.
The framework uses threads for communication handling, asynchronous operations, and protocol-specific services.
Suspends execution of the calling thread for the specified duration.
This service is used throughout the framework for delays, polling operations, and timeout handling.
Prototypes are in Osal.h: Mem_alloc, Mem_dealloc, Mem_allocOnce. Mem_allocOnce takes memory from the static buffer of MEMORY_BUFFER_SIZE bytes. Mem_alloc uses the system allocator (malloc on Linux, pvPortMalloc on FreeRTOS). The OSAL also provides worker threads (WorkerThread.c) and Osal_getThreadId; the reference implementations can be reused.
Creates and destroys mutex objects.
Provides mutual exclusion for shared resources accessed from multiple threads.
Creates and destroys event objects.
Provides thread synchronization and signaling services.
The framework uses events extensively for:
The ICS software invokes a set of callback functions that must be implemented by the user application. These callbacks allow the ICS software to delegate application-specific processing to the user application.
This callback is invoked by the ICS software when device configuration information is required. The user application shall populate the provided IcsDeviceConfig structure with the configuration corresponding to the specified index.
handle - ICS instance handle.index - Configuration entry index.config - Pointer to the configuration structure to be populated.IcsStatus_OKThis callback is invoked by the ICS software when the communication channel configuration associated with a device is required. The user application shall populate the provided IcsCommChannelConfig structure with the configuration corresponding to the specified device and channel index.
handle - ICS instance handle.device - Device for which the channel configuration is requested.index - Channel configuration index.config - Pointer to the configuration structure to be populated.IcsStatus_OKThis callback is invoked by the ICS software when channel configuration data is requested. The user application shall provide the requested channel settings data and copy it into the supplied buffer. The callback supports segmented transfers through the offset parameter, allowing configuration data larger than the provided buffer to be transferred in multiple requests.
handle - ICS instance handle.buffer - Destination buffer.bufferLength - Size of the destination buffer in bytes.offset - Offset within the channel settings data.dataSize - Number of bytes copied into the buffer.totalSize - Total size of the channel settings data.context - Not used.IcsStatus_OKThis callback is invoked by the ICS software after the repository has been created and initialized. It allows the user application to perform additional repository-specific initialization, such as locating repository objects, registering callbacks or performing other custom setup operations required by the application.
repository - Handle to the repository instance being initialized.IcsStatus_OKWhile the ICS software provides a common interface for application development, certain protocol-specific initialization steps are required depending on the selected industrial communication protocol. These APIs allow the framework to create and initialize protocol-specific objects and services within the repository.
The user application shall invoke the appropriate API during the initialization phase based on the target protocol.
Creates and initializes the EtherNet/IP-specific components and registers the required protocol objects in the repository.
Creates and initializes the PROFINET-specific components and registers the required protocol objects in the repository.
Creates and initializes the EtherCAT-specific components and registers the required protocol objects in the repository.
IcsEthercat_createServices() will be replaced by IcsEthercat_initialize() to provide a consistent API naming convention across all supported protocols.