TICS100MOD-SDK  2026.0.0
TICS100MOD-SDK
Loading...
Searching...
No Matches
Application Development

Introduction

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.

Application Lifecycle

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.

  1. Ics_create — create the ICS instance.
  2. Ics_initialize — creates device and channel objects; calls IcsUser_getDeviceConfig and IcsUser_getChannelConfig. No SPI traffic yet.
  3. Ics_getDevice, then IcsDevice_getDefaultRepository — get the device and its repository.
  4. Optional, EtherNet/IP and PROFINET: IcsChannelSettings_setParameter (ICS_CHANNEL_SETTINGS_SERIAL_NUMBER, ICS_CHANNEL_SETTINGS_MAC_ADDRESS).
  5. 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.
  6. Find the repository objects the application needs and register callbacks (see "Working with Objects").
  7. Run. The application uses the object API; the ICS software invokes registered callbacks.
  8. Shutdown or restart: stop application threads and unregister callbacks, then 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.

Project Settings

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.

Source Files Selection

HAL

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:

source/TICOM/hal/source/

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.

OSAL

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:

source/TICOM/osal/source/

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.

Protocol-Specific

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:

source/TICOM/protocol/

The following folders are available:

source/TICOM/protocol/ethernetip/
source/TICOM/protocol/ethercat/
source/TICOM/protocol/profinet/

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.

Other Sources

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.

Linux

Folders (excluded):

source/TICOM/terminal
source/TICOM/terminal-adapter

Files (excluded):

source/TICOM/config/*.c

FreeRTOS

Folders (excluded):

source/TICOM/terminal
source/TICOM/terminal-adapter

Files (excluded):

source/TICOM/config/*.c
source/TICOM/osal/source/Memory.c

Predefined Macros

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

Platform Porting

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.

Required HAL Interface

The HAL implementation is responsible for providing access to platform-specific hardware resources.

HAL Initialization

Bool Hal_init(void);

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).

Hardware Resource Access

PinObject Hal_getPinInstance(U32 channel);
SpiObject Hal_getSpiInstance(U32 channel);
IcuObject Hal_getIcuInstance(U32 channel);
TimerObject Hal_getTimerInstance(U32 channel);

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

Bool Pin_setDirection(
PinObject pin,
PinDirection direction);
Bool Pin_setDirectionWithDefaultState(
PinObject pin,
PinDirection direction,
PinState defaultState);
Bool Pin_setValue(
PinObject pin,
PinState value);

GPIO services are used by the framework for:

  • Module reset control
  • Host request signaling
  • Status indication LEDs
  • Emergency indication outputs

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.

SPI Services

Bool Spi_startMaster( SpiObject object, U32 spiMasterClock, SpiClockMode spiMasterClockMode, SpiBitDirection spiMasterBitDirection );
Bool Spi_startSlave( SpiObject object, SpiClockMode spiMasterClockMode, SpiBitDirection spiMasterBitDirection);
Bool Spi_transfer(
SpiObject object,
SpiTransferData* transferData);
Bool Spi_transferMultiple(SpiObject object, SpiTransferData* transferData, uint32_t count);
Bool Spi_transferAsync(SpiObject object, SpiTransferData* transferData);
Bool Spi_cancelTransfer(
SpiObject object);

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.

ICU Services

Bool Icu_setDetectionLevel(
IcuObject object,
IcuDetectionLevel level);
Bool Icu_enable(
IcuObject object);
Bool Icu_disable(
IcuObject object);
Bool Icu_getValue (IcuObject object, PinState* pinstate);
Bool Icu_registerLevelDetectionCallback (IcuObject object, IntNotificationCallback* callback);
Bool Icu_unregisterLevelDetectionCallback (IcuObject object, IntNotificationCallback* callback);

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.

Interrupt notification chain

ICU callbacks use a linked list (QDLinkedInNoCalList). The pattern:

  1. Icu_registerLevelDetectionCallback(icu, &callback) — appends to list
  2. Your ISR calls Icu_notify(icu) → IntHandler_notifyHandler() walks list
  3. spi_transfer_handler.c registers its own callbacks (RequestFeedCallback, BusyFeedCallback) during SpiTransferHandler_start()

So your GPIO ISR must call:

void GPIO_ISR_for_pin_N(void) {
// clear interrupt flag if required by your platform
Icu_notify(icuObject); // dispatches IntHandler_notifyHandler → walks callback list
}

Timer Services

Bool Timer_startMsWithCallack(TimerObject object, TimeoutUsType period, TimerMode mode, IntNotificationDelegate callback, void* context);
Bool Timer_stop(
TimerObject object);

Timer services are used internally by the framework to implement timeout supervision and delayed processing.

Timestamp Services

U64 Timestamp_getMicroSeconds(void); (declared in `Timestamp.h`)

Returns a monotonically increasing timestamp in microseconds.

This service is used by framework diagnostics and terminal logging functionality.

Cache Services

Bool Cache_invalidate(
void* memory,
uint32_t length);

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:

Bool Cache_invalidate(
void* memory,
uint32_t length)
{
(void)memory;
(void)length;
return true;
}

UART Services

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.

Required Hardware Instances

The generated device configuration contains the hardware instance identifiers expected by the framework.

Example:

IcsDeviceConfig deviceConfigObjects[] =
{
{
.Type = IcsDeviceType_Spi,
.ConnectionString =
"Spi=0;Request=0;BusyFeed=0;RequestFeed=1;Clock=1000000;Mode=0",
.ResetPin = 10,
.Name = "MyDevice",
}
};

The generated host application expects the following hardware instances to be available:

  • SPI instance 0
  • GPIO instance 0 used as the Host Request signal
  • ICU instance 0 used as the Busy Feedback signal
  • ICU instance 1 used as the Request Feedback signal
  • GPIO instance 10 used as the optional hardware reset signal

Accordingly, the platform initialization shall provide valid implementations for:

Hal_getSpiInstance(0);
Hal_getPinInstance(0);
Hal_getPinInstance(10);
Hal_getIcuInstance(0);
Hal_getIcuInstance(1);

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.

Platform Initialization

The reference implementation performs the following initialization sequence:

  1. Initialize the HAL.
    Hal_init();
  2. Obtain the SPI instance referenced by the generated connection string.
    hostSpi = Hal_getSpiInstance(0);
  3. Configure the Busy Feedback ICU instance.
    hostBusyFeedIcu = Hal_getIcuInstance(0);
    Icu_setDetectionLevel(
    hostBusyFeedIcu,
    ICU_DL_RISING_EDGE);
    The Busy Feedback signal is configured for rising-edge detection because the module drives the Busy signal HIGH when it becomes ready to accept a transfer.
  4. Configure the Host Request GPIO instance.
    hostRequestPin = Hal_getPinInstance(0);
    Pin_setDirection(
    hostRequestPin,
    PIN_IO_OUT);
    Pin_setValue(
    hostRequestPin,
    PIN_HIGH);
  5. Configure the Request Feedback ICU instance.
    hostRequestFeedIcu = Hal_getIcuInstance(1);
    Icu_setDetectionLevel(
    hostRequestFeedIcu,
    ICU_DL_FALLING_EDGE);

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.

Transfer Handshake

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.

Required OSAL Interface

The OSAL implementation provides access to operating-system services required by the framework.

Thread Management

OsalThreadObject Osal_createThread (const char* name);
void Osal_destroyThread (OsalThreadObject thread);

Creates and destroys thread objects used by the framework.

Bool Thread_start (OsalThreadObject thread, ThreadCallback* callback);
Bool Thread_startWithCallback(OsalThreadObject thread, RunDelegate runCallback, StopDelegate stopCallback, void* context);
Bool Thread_stop (OsalThreadObject thread);
Bool Thread_isRunning (OsalThreadObject thread);
Bool Thread_setPriority (OsalThreadObject thread, U32 priority);

These functions provide thread creation, execution control, and priority management.

The framework uses threads for communication handling, asynchronous operations, and protocol-specific services.

Sleep Services

void Osal_sleep(TimeMsType milliseconds);

Suspends execution of the calling thread for the specified duration.

This service is used throughout the framework for delays, polling operations, and timeout handling.

Memory Services

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.

Mutex Services

OsalMutexObject Osal_createMutex (const char* name);
void Osal_destroyMutex (OsalMutexObject mutex);

Creates and destroys mutex objects.

void Mutex_lock (OsalMutexObject mutex);
void Mutex_unlock (OsalMutexObject mutex);

Provides mutual exclusion for shared resources accessed from multiple threads.

Event Services

OsalEventObject Osal_createEvent (const char* name);
void Osal_destroyEvent (OsalEventObject event);

Creates and destroys event objects.

void Event_wait (OsalEventObject event);
Bool Event_waitTimeout (OsalEventObject event, TimeMsType timeout_ms);
void Event_signal (OsalEventObject event);
void Event_lock (OsalEventObject event);
void Event_unlock (OsalEventObject event);

Provides thread synchronization and signaling services.

The framework uses events extensively for:

  • SPI transfer synchronization
  • Command handler operation
  • Worker thread control
  • Communication state changes

Core Callbacks

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.

IcsUser_getDeviceConfig

IcsStatus IcsUser_getDeviceConfig(
IcsHandle handle,
int32_t index,
IcsDeviceConfig* config);

Description

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.

Parameters

  • handle - ICS instance handle.
  • index - Configuration entry index.
  • config - Pointer to the configuration structure to be populated.

Return Value

  • IcsStatus_OK
  • Error code otherwise.

IcsUser_getChannelConfig

IcsStatus IcsUser_getChannelConfig(
IcsHandle handle,
IcsDevice device,
int32_t index,
IcsCommChannelConfig* config);

Description

This 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.

Parameters

  • 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.

Return Value

  • IcsStatus_OK
  • Error code otherwise.

IcsUser_getChannelSetting

IcsStatus IcsUser_getChannelSetting(
IcsHandle handle,
uint8_t* buffer,
uint32_t bufferLength,
uint32_t offset,
uint32_t* dataSize,
uint32_t* totalSize,
void* context);

Description

This 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.

Parameters

  • 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.

Return Value

  • IcsStatus_OK
  • Error code otherwise.

IcsRepository_initialize

IcsStatus IcsRepository_initialize(
IcsRepository repository);

Description

This 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.

Note
Behavior may depend on the protocol being used (PROFINET, EtherCAT, or EtherNet/IP).

Parameters

  • repository - Handle to the repository instance being initialized.

Return Value

  • IcsStatus_OK
  • Error code otherwise.

Protocol Specific API

While 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.

EtherNet/IP

IcsStatus IcsEthernetip_initialize(IcsRepository repository);

Creates and initializes the EtherNet/IP-specific components and registers the required protocol objects in the repository.

PROFINET

Bool IcsProfinet_initialize(IcsRepository repository);

Creates and initializes the PROFINET-specific components and registers the required protocol objects in the repository.

EtherCAT

Bool IcsEthercat_createServices(IcsRepository repository);

Creates and initializes the EtherCAT-specific components and registers the required protocol objects in the repository.

Note
In a future release, IcsEthercat_createServices() will be replaced by IcsEthercat_initialize() to provide a consistent API naming convention across all supported protocols.