diff --git a/Doxyfile b/Doxyfile index 4eba72d..c94ff1b 100644 --- a/Doxyfile +++ b/Doxyfile @@ -3,12 +3,13 @@ PROJECT_NAME = "iolinki" PROJECT_NUMBER = "1.1.2" PROJECT_BRIEF = "Open-Source IO-Link Device Stack" OUTPUT_DIRECTORY = docs -INPUT = include/iolinki src/device.c src/dll.c src/isdu.c src/events.c src/params.c src/data_storage.c src/device_info.c src/phy_virtual.c src/crc.c -RECURSIVE = NO +INPUT = include/iolinki src +RECURSIVE = YES OPTIMIZE_OUTPUT_FOR_C = YES +JAVADOC_AUTOBRIEF = YES EXTRACT_ALL = YES EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES GENERATE_LATEX = NO GENERATE_MAN = NO GENERATE_RTF = NO @@ -30,3 +31,5 @@ GENERATE_HTML = YES HTML_OUTPUT = html HTML_DYNAMIC_SECTIONS = YES DISABLE_INDEX = NO +GENERATE_TREEVIEW = YES +SOURCE_BROWSER = YES diff --git a/include/iolinki/application.h b/include/iolinki/application.h index 5f7dac3..790aaaf 100644 --- a/include/iolinki/application.h +++ b/include/iolinki/application.h @@ -18,6 +18,12 @@ * @brief IO-Link Application Layer API for Process Data */ +/** + * @defgroup iolinki_application Application Layer Callbacks + * @brief Application lifecycle and process-data callback hooks. + * @{ + */ + /** * @brief Application lifecycle and Process Data callbacks. * @@ -36,4 +42,6 @@ typedef struct void (*on_pd_output)(uint8_t* data, uint8_t len); /**< Output PD received */ } iolink_app_callbacks_t; +/** @} */ /* end of iolinki_application */ + #endif // IOLINK_APPLICATION_H diff --git a/include/iolinki/config.h b/include/iolinki/config.h index 345e28c..c968699 100644 --- a/include/iolinki/config.h +++ b/include/iolinki/config.h @@ -18,6 +18,12 @@ * or in a private config header included before this file. */ +/** + * @defgroup iolinki_config Compile-time Configuration + * @brief Overridable buffer sizes, queue depths and timing defaults. + * @{ + */ + /* ------------------------------------------------------------------------- * ISDU Configuration * ------------------------------------------------------------------------- */ @@ -125,4 +131,6 @@ #define IOLINK_OD_EVENT_MODE 0U #endif +/** @} */ /* end of iolinki_config */ + #endif // IOLINK_CONFIG_H diff --git a/include/iolinki/crc.h b/include/iolinki/crc.h index 3fed5e7..a114acd 100644 --- a/include/iolinki/crc.h +++ b/include/iolinki/crc.h @@ -16,6 +16,12 @@ * @brief IO-Link CRC calculation (Spec V1.1.5) */ +/** + * @defgroup iolinki_crc CRC / Checksum + * @brief IO-Link 6-bit CRC and 8-bit checksum computation. + * @{ + */ + /** * @brief Calculate IO-Link 6-bit CRC * @@ -39,4 +45,6 @@ uint8_t iolink_crc6(const uint8_t* data, uint8_t len); */ uint8_t iolink_checksum_ck(uint8_t mc, uint8_t ckt); +/** @} */ /* end of iolinki_crc */ + #endif // IOLINK_CRC_H diff --git a/include/iolinki/data_storage.h b/include/iolinki/data_storage.h index c17af6b..5baddd4 100644 --- a/include/iolinki/data_storage.h +++ b/include/iolinki/data_storage.h @@ -20,6 +20,12 @@ * @brief IO-Link Data Storage (DS) for parameter backup and restore */ +/** + * @defgroup iolinki_data_storage Data Storage (DS) + * @brief Parameter image serialization, checksum compare, and upload/download services. + * @{ + */ + /** * @brief Maximum size of the serialized Data Storage parameter image. * @@ -106,6 +112,13 @@ typedef struct * @param storage Optional storage implementation hooks (can be NULL for RAM-only) */ void iolink_ds_init(iolink_ds_ctx_t* ctx, const iolink_ds_storage_api_t* storage); + +/** + * @brief Bind the writable parameter context used as the DS parameter source. + * + * @param ctx DS context + * @param params_ctx Device-local parameter manager context to serialize/restore + */ void iolink_ds_bind_params(iolink_ds_ctx_t* ctx, iolink_params_ctx_t* params_ctx); /** @@ -155,6 +168,8 @@ int iolink_ds_start_upload(iolink_ds_ctx_t* ctx); int iolink_ds_start_download(iolink_ds_ctx_t* ctx); /** + * @brief Abort any in-progress DS upload/download and return to idle. + * * @param ctx DS context * @return int 0 on success */ @@ -211,4 +226,6 @@ const uint8_t* iolink_ds_get_image(iolink_ds_ctx_t* ctx, size_t* out_len); */ bool iolink_ds_verify(const iolink_ds_ctx_t* ctx); +/** @} */ /* end of iolinki_data_storage */ + #endif // IOLINK_DATA_STORAGE_H diff --git a/include/iolinki/device.h b/include/iolinki/device.h index b561149..76b04d6 100644 --- a/include/iolinki/device.h +++ b/include/iolinki/device.h @@ -20,55 +20,211 @@ #include #include +/** + * @file device.h + * @brief IO-Link Device application layer API. + * + * Top-level entry point for an IO-Link Device. Ties together the physical + * layer, data link layer, device identification, parameters and application + * callbacks behind a single opaque context, and exposes the lifecycle, + * process-data and introspection functions used by the application. + */ + +/** + * @defgroup iolinki_device Device Application Layer + * @brief Top-level IO-Link Device context, lifecycle and process-data API. + * @{ + */ + +/** @brief Callback returning a monotonic timestamp in microseconds. + * @param user Opaque user pointer supplied via ::iolink_device_config_t. + * @return Current time in microseconds. */ typedef uint64_t (*iolink_device_time_us_fn)(void* user); +/** @brief Callback acquiring the application-provided lock (critical section). + * @param user Opaque user pointer supplied via ::iolink_device_config_t. */ typedef void (*iolink_device_lock_fn)(void* user); +/** @brief Callback releasing the application-provided lock (critical section). + * @param user Opaque user pointer supplied via ::iolink_device_config_t. */ typedef void (*iolink_device_unlock_fn)(void* user); +/** @brief Physical layer API used by the device (alias of ::iolink_phy_api_t). */ typedef iolink_phy_api_t iolink_device_phy_t; +/** + * @brief Device configuration supplied at initialization. + * + * Aggregates the PHY driver, stack settings, application hooks, device + * identification, data-storage backend and platform integration callbacks. + */ typedef struct { - iolink_device_phy_t phy; - iolink_config_t stack; - const iolink_app_callbacks_t* app_callbacks; - const iolink_device_info_t* device_info; - const iolink_ds_storage_api_t* ds_storage; - iolink_device_time_us_fn time_us; - iolink_device_lock_fn lock; - iolink_device_unlock_fn unlock; - void* user; + iolink_device_phy_t phy; /**< Physical layer driver API. */ + iolink_config_t stack; /**< Stack behavior configuration. */ + const iolink_app_callbacks_t* + app_callbacks; /**< Application lifecycle/PD callbacks (may be NULL). */ + const iolink_device_info_t* device_info; /**< Static device identification data. */ + const iolink_ds_storage_api_t* + ds_storage; /**< Data-storage persistence backend (may be NULL). */ + iolink_device_time_us_fn time_us; /**< Microsecond timestamp source. */ + iolink_device_lock_fn lock; /**< Lock callback (may be NULL). */ + iolink_device_unlock_fn unlock; /**< Unlock callback (may be NULL). */ + void* user; /**< Opaque pointer passed back to callbacks. */ } iolink_device_config_t; +/** + * @brief Device runtime context. + * + * Allocate this object directly, but access it only through the API functions. + * All fields are private stack state. + */ typedef struct { /* Private fields. Allocate this object directly, but use API functions. */ - iolink_dll_ctx_t dll; - iolink_config_t stack_config; - iolink_device_info_ctx_t device_info; - iolink_params_ctx_t params; - const iolink_device_config_t* config; - iolink_reset_handler_t reset_handler; - uint8_t direct_param_page2[16]; + iolink_dll_ctx_t dll; /**< Data link layer context. */ + iolink_config_t stack_config; /**< Active stack configuration. */ + iolink_device_info_ctx_t device_info; /**< Device identification context. */ + iolink_params_ctx_t params; /**< Parameter manager context. */ + const iolink_device_config_t* config; /**< Pointer to the supplied configuration. */ + iolink_reset_handler_t reset_handler; /**< Application reset handler (may be NULL). */ + uint8_t direct_param_page2[16]; /**< Direct Parameter Page 2 storage. */ } iolink_device_ctx_t; +/** + * @brief Get the size in bytes of ::iolink_device_ctx_t. + * @return Size of the device context object, in bytes. + */ size_t iolink_device_ctx_size(void); + +/** + * @brief Initialize a device context from a configuration. + * @param ctx Device context to initialize. + * @param config Configuration to apply (must remain valid for the ctx lifetime). + * @return 0 on success, negative on error. + */ int iolink_device_init(iolink_device_ctx_t* ctx, const iolink_device_config_t* config); + +/** + * @brief Run one iteration of the device state machine. + * + * Drives the DLL/PHY: services pending frames, timing and application events. + * Call this periodically from the main loop. + * @param ctx Device context. + */ void iolink_device_process(iolink_device_ctx_t* ctx); + +/** + * @brief Update the input process data (Device -> Master). + * @param ctx Device context. + * @param data Input process data bytes to publish. + * @param len Length of @p data in bytes. + * @param valid Whether the process data is currently valid. + * @return 0 on success, negative on error. + */ int iolink_device_pd_input_update(iolink_device_ctx_t* ctx, const uint8_t* data, size_t len, bool valid); + +/** + * @brief Read the latest output process data (Master -> Device). + * @param ctx Device context. + * @param[out] data Buffer filled with the output process data. + * @param len Size of @p data in bytes. + * @return 0 on success, negative on error. + */ int iolink_device_pd_output_read(iolink_device_ctx_t* ctx, uint8_t* data, size_t len); + +/** + * @brief Register the handler invoked on Master reset commands. + * @param ctx Device context. + * @param handler Reset handler callback (may be NULL to clear). + */ void iolink_device_set_reset_handler(iolink_device_ctx_t* ctx, iolink_reset_handler_t handler); + +/** + * @brief Get the event handling context. + * @param ctx Device context. + * @return Pointer to the device's events context. + */ iolink_events_ctx_t* iolink_device_get_events_ctx(iolink_device_ctx_t* ctx); + +/** + * @brief Get the data-storage context. + * @param ctx Device context. + * @return Pointer to the device's data-storage context. + */ iolink_ds_ctx_t* iolink_device_get_ds_ctx(iolink_device_ctx_t* ctx); + +/** + * @brief Get the current DLL state. + * @param ctx Device context. + * @return Current data link layer state. + */ iolink_dll_state_t iolink_device_get_state(const iolink_device_ctx_t* ctx); + +/** + * @brief Get the current PHY communication mode. + * @param ctx Device context. + * @return Current physical layer mode. + */ iolink_phy_mode_t iolink_device_get_phy_mode(const iolink_device_ctx_t* ctx); + +/** + * @brief Get the current communication baud rate. + * @param ctx Device context. + * @return Active baud rate. + */ iolink_baudrate_t iolink_device_get_baudrate(const iolink_device_ctx_t* ctx); + +/** + * @brief Copy the DLL statistics counters. + * @param ctx Device context. + * @param[out] out_stats Filled with the current DLL statistics. + */ void iolink_device_get_dll_stats(const iolink_device_ctx_t* ctx, iolink_dll_stats_t* out_stats); + +/** + * @brief Enable or disable timing enforcement. + * @param ctx Device context. + * @param enable True to enforce timing limits, false to only measure. + */ void iolink_device_set_timing_enforcement(iolink_device_ctx_t* ctx, bool enable); + +/** + * @brief Set the response-time (t_ren) limit. + * @param ctx Device context. + * @param limit_us Response-time limit in microseconds. + */ void iolink_device_set_t_ren_limit_us(iolink_device_ctx_t* ctx, uint32_t limit_us); + +/** + * @brief Get the negotiated M-sequence type. + * @param ctx Device context. + * @return Active M-sequence type. + */ iolink_m_seq_type_t iolink_device_get_m_seq_type(const iolink_device_ctx_t* ctx); + +/** + * @brief Get the input process data length. + * @param ctx Device context. + * @return Input process data length in bytes. + */ uint8_t iolink_device_get_pd_in_len(const iolink_device_ctx_t* ctx); + +/** + * @brief Get the output process data length. + * @param ctx Device context. + * @return Output process data length in bytes. + */ uint8_t iolink_device_get_pd_out_len(const iolink_device_ctx_t* ctx); + +/** + * @brief Set the input and output process data lengths. + * @param ctx Device context. + * @param pd_in_len Input process data length in bytes. + * @param pd_out_len Output process data length in bytes. + * @return 0 on success, negative on error. + */ int iolink_device_set_pd_length(iolink_device_ctx_t* ctx, uint8_t pd_in_len, uint8_t pd_out_len); +/** @} */ /* end of iolinki_device */ + #endif // IOLINK_DEVICE_H diff --git a/include/iolinki/device_info.h b/include/iolinki/device_info.h index 99177b6..bfd890d 100644 --- a/include/iolinki/device_info.h +++ b/include/iolinki/device_info.h @@ -19,52 +19,97 @@ */ /** - * Device identification structure. - * Configure these values for your specific device. + * @defgroup iolinki_device_info Device Identification + * @brief Device identification data and the mandatory identity ISDU indices. + * @{ + */ + +/** + * @brief Device identification structure. + * + * Configure these values for your specific device. Each field maps to a + * mandatory or optional IO-Link identity ISDU index. */ typedef struct { /* Mandatory ID Indices (0x0010-0x0018) */ - const char* vendor_name; /* Index 0x0010 */ - const char* vendor_text; /* Index 0x0011 */ - const char* product_name; /* Index 0x0012 */ - const char* product_id; /* Index 0x0013 */ - const char* product_text; /* Index 0x0014 */ - const char* serial_number; /* Index 0x0015 */ - const char* hardware_revision; /* Index 0x0016 */ - const char* firmware_revision; /* Index 0x0017 */ - const char* application_tag; /* Index 0x0018 (optional) */ + const char* vendor_name; /**< Vendor name string (Index 0x0010). */ + const char* vendor_text; /**< Vendor text string (Index 0x0011). */ + const char* product_name; /**< Product name string (Index 0x0012). */ + const char* product_id; /**< Product ID string (Index 0x0013). */ + const char* product_text; /**< Product text string (Index 0x0014). */ + const char* serial_number; /**< Serial number string (Index 0x0015). */ + const char* hardware_revision; /**< Hardware revision string (Index 0x0016). */ + const char* firmware_revision; /**< Firmware revision string (Index 0x0017). */ + const char* application_tag; /**< Application tag string (Index 0x0018, optional). */ /* Device IDs (Mandatory Indices) */ - uint16_t vendor_id; /* Index 0x000A */ - uint32_t device_id; /* Index 0x000B */ - uint16_t function_id; /* Index 0x001C */ - uint16_t profile_characteristic; /* Index 0x000D */ + uint16_t vendor_id; /**< Vendor ID (Index 0x000A). */ + uint32_t device_id; /**< Device ID (Index 0x000B). */ + uint16_t function_id; /**< Function ID (Index 0x001C). */ + uint16_t profile_characteristic; /**< Profile characteristic (Index 0x000D). */ /* System Info */ - uint8_t min_cycle_time; /* Index 0x0024 (in 100μs units) */ - uint16_t revision_id; /* Index 0x001E */ - uint8_t device_status; /* Index 0x001B */ - uint16_t detailed_device_status; /* Index 0x001C (optional) */ + uint8_t min_cycle_time; /**< Minimum cycle time in 100us units (Index 0x0024). */ + uint16_t revision_id; /**< Revision ID (Index 0x001E). */ + uint8_t device_status; /**< Device status (Index 0x001B). */ + uint16_t detailed_device_status; /**< Detailed device status (Index 0x001C, optional). */ /* Access Control */ - uint16_t access_locks; /* Index 0x000C - Device Access Locks */ + uint16_t access_locks; /**< Device access locks bitmask (Index 0x000C). */ } iolink_device_info_t; +/** + * @brief Per-device identification runtime context. + * + * Wraps the static configured identity with mutable runtime values + * (application tag, access locks) and factory defaults. + */ typedef struct { - const iolink_device_info_t* configured; - iolink_device_info_t defaults; - char application_tag[33]; - uint16_t access_locks; + const iolink_device_info_t* configured; /**< Static configured identity. */ + iolink_device_info_t defaults; /**< Factory-default identity snapshot. */ + char application_tag[33]; /**< Runtime application tag (32 bytes + NUL). */ + uint16_t access_locks; /**< Runtime device access locks value. */ } iolink_device_info_ctx_t; +/** + * @brief Initialize a device-info context. + * @param ctx Context to initialize. + * @param configured Static device identity to bind (must remain valid). + */ void iolink_device_info_ctx_init(iolink_device_info_ctx_t* ctx, const iolink_device_info_t* configured); + +/** + * @brief Get the effective device identity from a context. + * @param ctx Device-info context. + * @return Pointer to the effective device identity. + */ const iolink_device_info_t* iolink_device_info_ctx_get(const iolink_device_info_ctx_t* ctx); + +/** + * @brief Set the runtime application tag (Index 0x0018) on a context. + * @param ctx Device-info context. + * @param tag String data (max 32 bytes). + * @param len Length of @p tag in bytes. + * @return 0 on success, negative on error. + */ int iolink_device_info_ctx_set_application_tag(iolink_device_info_ctx_t* ctx, const char* tag, uint8_t len); + +/** + * @brief Get the device access locks (Index 0x000C) from a context. + * @param ctx Device-info context. + * @return 16-bit access locks value. + */ uint16_t iolink_device_info_ctx_get_access_locks(const iolink_device_info_ctx_t* ctx); + +/** + * @brief Set the device access locks (Index 0x000C) on a context. + * @param ctx Device-info context. + * @param locks 16-bit access locks value. + */ void iolink_device_info_ctx_set_access_locks(iolink_device_info_ctx_t* ctx, uint16_t locks); /** @@ -99,4 +144,6 @@ uint16_t iolink_device_info_get_access_locks(void); */ void iolink_device_info_set_access_locks(uint16_t locks); +/** @} */ /* end of iolinki_device_info */ + #endif // IOLINK_DEVICE_INFO_H diff --git a/include/iolinki/dll.h b/include/iolinki/dll.h index 647efc0..ac8a66d 100644 --- a/include/iolinki/dll.h +++ b/include/iolinki/dll.h @@ -19,6 +19,12 @@ * @brief IO-Link Data Link Layer (DLL) Implementation */ +/** + * @defgroup iolinki_dll Data Link Layer (DLL) + * @brief Frame timing, M-sequence exchange, mode/baudrate control and DLL statistics. + * @{ + */ + /** * @brief IO-Link DLL State Machine states */ @@ -178,8 +184,8 @@ int iolink_dll_set_pd_length(iolink_dll_ctx_t* ctx, uint8_t pd_in_len, uint8_t p * @brief Get current PD lengths * * @param ctx DLL context - * @param pd_in_len [out] Current PD_In length - * @param pd_out_len [out] Current PD_Out length + * @param[out] pd_in_len Current PD_In length + * @param[out] pd_out_len Current PD_Out length */ void iolink_dll_get_pd_length(const iolink_dll_ctx_t* ctx, uint8_t* pd_in_len, uint8_t* pd_out_len); @@ -228,7 +234,7 @@ iolink_baudrate_t iolink_dll_get_baudrate(const iolink_dll_ctx_t* ctx); * @brief Get DLL statistics * * @param ctx DLL context - * @param out_stats Output stats structure + * @param[out] out_stats Output stats structure, populated with a counter snapshot */ void iolink_dll_get_stats(const iolink_dll_ctx_t* ctx, iolink_dll_stats_t* out_stats); @@ -248,4 +254,6 @@ void iolink_dll_set_timing_enforcement(iolink_dll_ctx_t* ctx, bool enable); */ void iolink_dll_set_t_ren_limit_us(iolink_dll_ctx_t* ctx, uint32_t limit_us); +/** @} */ /* end of iolinki_dll */ + #endif // IOLINK_DLL_H diff --git a/include/iolinki/events.h b/include/iolinki/events.h index 22476a4..3e6fc21 100644 --- a/include/iolinki/events.h +++ b/include/iolinki/events.h @@ -18,6 +18,12 @@ * @brief IO-Link Event Handling */ +/** + * @defgroup iolinki_events Event Handling + * @brief Diagnostic event codes, severity levels and the Device event queue. + * @{ + */ + /** * @brief IO-Link Event Severity Levels */ @@ -194,4 +200,6 @@ uint8_t iolink_events_get_all(iolink_events_ctx_t* ctx, iolink_event_t* out_even */ iolink_event_type_t iolink_event_classify(uint16_t code); +/** @} */ /* end of iolinki_events */ + #endif // IOLINK_EVENTS_H diff --git a/include/iolinki/frame.h b/include/iolinki/frame.h index b423869..42649a4 100644 --- a/include/iolinki/frame.h +++ b/include/iolinki/frame.h @@ -17,25 +17,81 @@ /** * @file frame.h * @brief Shared IO-Link frame encoding and decoding helpers. + * + * Provides M-sequence frame builders for Type-0 and Type-1 requests and a + * decoder for the Device's OPERATE-mode response frame. + */ + +/** + * @defgroup iolinki_frame M-sequence Frame Handling + * @brief Encode/decode helpers for IO-Link M-sequence frames. + * @{ */ +/** + * @brief Decoded OPERATE-mode response frame. + * + * Holds the fields extracted from a Device response during cyclic exchange. + */ typedef struct { - uint8_t status; - bool pd_valid; - bool event_pending; - bool checksum_ok; - uint8_t pd[IOLINK_PD_IN_MAX_SIZE]; - uint8_t pd_len; - uint8_t od[IOLINK_OD_MAX_SIZE]; - uint8_t od_len; + uint8_t status; /**< Status/checksum (CKS) byte from the frame. */ + bool pd_valid; /**< True if the Process Data valid flag is set. */ + bool event_pending; /**< True if the frame signals a pending event. */ + bool checksum_ok; /**< True if the frame checksum verified correctly. */ + uint8_t pd[IOLINK_PD_IN_MAX_SIZE]; /**< Decoded input Process Data bytes. */ + uint8_t pd_len; /**< Number of valid bytes in @ref pd. */ + uint8_t od[IOLINK_OD_MAX_SIZE]; /**< Decoded On-request Data bytes. */ + uint8_t od_len; /**< Number of valid bytes in @ref od. */ } iolink_frame_operate_response_t; +/** + * @brief Encode a Type-0 (read) request frame. + * + * @param mc Master Control (MC) byte for the request. + * @param[out] out Destination buffer for the encoded frame. + * @param out_size Capacity of @p out in bytes. + * @return Number of bytes written on success, negative on error (e.g. buffer too small). + */ int iolink_frame_encode_type0(uint8_t mc, uint8_t* out, size_t out_size); + +/** + * @brief Encode a Type-0 write request frame with a single On-request Data byte. + * + * @param mc Master Control (MC) byte for the request. + * @param od On-request Data byte to transmit. + * @param[out] out Destination buffer for the encoded frame. + * @param out_size Capacity of @p out in bytes. + * @return Number of bytes written on success, negative on error. + */ int iolink_frame_encode_type0_write(uint8_t mc, uint8_t od, uint8_t* out, size_t out_size); + +/** + * @brief Encode a Type-1 cyclic exchange frame. + * + * @param pd_out Pointer to the output Process Data to embed. + * @param pd_out_len Number of output Process Data bytes. + * @param od_len Number of On-request Data bytes in the exchange. + * @param[out] out Destination buffer for the encoded frame. + * @param out_size Capacity of @p out in bytes. + * @return Number of bytes written on success, negative on error. + */ int iolink_frame_encode_type1_cycle(const uint8_t* pd_out, uint8_t pd_out_len, uint8_t od_len, uint8_t* out, size_t out_size); + +/** + * @brief Decode a Device OPERATE-mode response frame. + * + * @param frame Pointer to the raw received frame bytes. + * @param frame_len Length of @p frame in bytes. + * @param pd_in_len Expected input Process Data length. + * @param od_len Expected On-request Data length. + * @param[out] out Structure populated with the decoded response fields. + * @return 0 on success, negative on decode/length error. + */ int iolink_frame_decode_operate_response(const uint8_t* frame, size_t frame_len, uint8_t pd_in_len, uint8_t od_len, iolink_frame_operate_response_t* out); +/** @} */ /* end of iolinki_frame */ + #endif /* IOLINK_FRAME_H */ diff --git a/include/iolinki/iolink.h b/include/iolinki/iolink.h index 218ab89..ace4472 100644 --- a/include/iolinki/iolink.h +++ b/include/iolinki/iolink.h @@ -16,6 +16,12 @@ * @brief Shared IO-Link stack types */ +/** + * @defgroup iolinki_core Core Types and Baudrates + * @brief Shared IO-Link enumerations, configuration and callback types. + * @{ + */ + /** * @brief IO-Link M-sequence types * @@ -63,4 +69,6 @@ typedef enum */ typedef void (*iolink_reset_handler_t)(iolink_reset_type_t type); +/** @} */ /* end of iolinki_core */ + #endif // IOLINK_H diff --git a/include/iolinki/isdu.h b/include/iolinki/isdu.h index fe2f143..55c4864 100644 --- a/include/iolinki/isdu.h +++ b/include/iolinki/isdu.h @@ -20,6 +20,12 @@ * @brief IO-Link Indexed Service Data Unit (ISDU) Acyclic Messaging */ +/** + * @defgroup iolinki_isdu ISDU Service (acyclic parameters) + * @brief Indexed acyclic read/write service engine and request/response handling. + * @{ + */ + /** * @brief ISDU Service Types */ @@ -145,4 +151,6 @@ int iolink_isdu_get_response_byte(iolink_isdu_ctx_t* ctx, uint8_t* byte); */ uint8_t iolink_isdu_direct_param_page1_octet(iolink_isdu_ctx_t* ctx, uint8_t addr); +/** @} */ /* end of iolinki_isdu */ + #endif // IOLINK_ISDU_H diff --git a/include/iolinki/params.h b/include/iolinki/params.h index 46abd33..350d6d4 100644 --- a/include/iolinki/params.h +++ b/include/iolinki/params.h @@ -20,24 +20,61 @@ */ /** - * Per-device parameter manager context. + * @defgroup iolinki_params Parameter Manager + * @brief Read/write access to IO-Link parameters by ISDU index/subindex. + * @{ + */ + +/** + * @brief Per-device parameter manager context. */ typedef struct { - char application_tag[33]; - char function_tag[33]; - char location_tag[33]; - bool application_tag_valid; - bool function_tag_valid; - bool location_tag_valid; - iolink_device_info_ctx_t* device_info; + char application_tag[33]; /**< Application tag (32 bytes + NUL). */ + char function_tag[33]; /**< Function tag (32 bytes + NUL). */ + char location_tag[33]; /**< Location tag (32 bytes + NUL). */ + bool application_tag_valid; /**< True if the application tag has been set. */ + bool function_tag_valid; /**< True if the function tag has been set. */ + bool location_tag_valid; /**< True if the location tag has been set. */ + iolink_device_info_ctx_t* device_info; /**< Associated device-info context. */ } iolink_params_ctx_t; +/** + * @brief Initialize a parameter manager context. + * @param ctx Context to initialize. + * @param device_info Device-info context to bind (must remain valid). + */ void iolink_params_ctx_init(iolink_params_ctx_t* ctx, iolink_device_info_ctx_t* device_info); + +/** + * @brief Retrieve a parameter value from a context by its IO-Link address. + * @param ctx Parameter manager context. + * @param index ISDU index. + * @param subindex ISDU subindex (0 for entire index, or 1-255). + * @param[out] buffer Destination buffer to store the value. + * @param max_len Size of the destination buffer. + * @return Number of bytes read on success, or negative IO-Link ErrorCode. + */ int iolink_params_ctx_get(const iolink_params_ctx_t* ctx, uint16_t index, uint8_t subindex, uint8_t* buffer, size_t max_len); + +/** + * @brief Update a parameter value on a context. + * @param ctx Parameter manager context. + * @param index ISDU index. + * @param subindex ISDU subindex. + * @param data Pointer to the new data to write. + * @param len Length of the new data in bytes. + * @param persist If true, synchronously commit the change to NVM. + * @return 0 on success, or negative IO-Link ErrorCode. + */ int iolink_params_ctx_set(iolink_params_ctx_t* ctx, uint16_t index, uint8_t subindex, const uint8_t* data, size_t len, bool persist); + +/** + * @brief Reset all parameters in a context to factory defaults. + * @param ctx Parameter manager context. + */ void iolink_params_ctx_factory_reset(iolink_params_ctx_t* ctx); /** @@ -78,4 +115,6 @@ int iolink_params_set(uint16_t index, uint8_t subindex, const uint8_t* data, siz */ void iolink_params_factory_reset(void); +/** @} */ /* end of iolinki_params */ + #endif // IOLINK_PARAMS_H diff --git a/include/iolinki/phy.h b/include/iolinki/phy.h index 81a570b..e91b960 100644 --- a/include/iolinki/phy.h +++ b/include/iolinki/phy.h @@ -18,6 +18,12 @@ * @brief IO-Link Physical Layer (PHY) Abstraction Interface */ +/** + * @defgroup iolinki_phy Physical Layer (PHY) Interface + * @brief Hardware-agnostic transceiver contract, operating modes and baudrates. + * @{ + */ + /** * @brief IO-Link Operating Modes */ @@ -46,7 +52,7 @@ typedef enum */ typedef struct { - void* user; + void* user; /**< Opaque driver context passed back to every callback. */ /** * @brief Initialize transceiver hardware @@ -108,4 +114,6 @@ typedef struct bool (*is_short_circuit)(void* user); } iolink_phy_api_t; +/** @} */ /* end of iolinki_phy */ + #endif // IOLINK_PHY_H diff --git a/include/iolinki/phy_generic.h b/include/iolinki/phy_generic.h index 876c379..5ef12e8 100644 --- a/include/iolinki/phy_generic.h +++ b/include/iolinki/phy_generic.h @@ -23,6 +23,12 @@ extern "C" { * to the target transceiver and MCU/SoC peripherals. */ +/** + * @defgroup iolinki_phy_generic Generic UART PHY Adapter + * @brief Reference PHY template to adapt for real transceiver hardware. + * @{ + */ + /** * @brief Get the generic PHY API (template). * @@ -30,6 +36,8 @@ extern "C" { */ const iolink_phy_api_t* iolink_phy_generic_get(void); +/** @} */ /* end of iolinki_phy_generic */ + #ifdef __cplusplus } #endif diff --git a/include/iolinki/phy_virtual.h b/include/iolinki/phy_virtual.h index b6104b3..cb3b4d2 100644 --- a/include/iolinki/phy_virtual.h +++ b/include/iolinki/phy_virtual.h @@ -16,6 +16,12 @@ * @brief Virtual PHY implementation for simulation */ +/** + * @defgroup iolinki_phy_virtual Virtual PHY (loopback/testing) + * @brief Socket/TTY-backed PHY for simulating an IO-Link Master. + * @{ + */ + /** * @brief Get the virtual PHY provider * @@ -31,4 +37,6 @@ const iolink_phy_api_t* iolink_phy_virtual_get(void); */ void iolink_phy_virtual_set_port(const char* port); +/** @} */ /* end of iolinki_phy_virtual */ + #endif // IOLINK_PHY_VIRTUAL_H diff --git a/include/iolinki/platform.h b/include/iolinki/platform.h index 045f154..a5c4f80 100644 --- a/include/iolinki/platform.h +++ b/include/iolinki/platform.h @@ -20,6 +20,12 @@ * Platforms/RTOS integrations should override these to ensure thread safety. */ +/** + * @defgroup iolinki_platform Platform Abstraction + * @brief Critical-section and non-volatile memory hooks the integrator provides. + * @{ + */ + #ifdef __cplusplus extern "C" { #endif @@ -64,4 +70,6 @@ int iolink_nvm_write(uint32_t offset, const uint8_t* data, size_t len); } #endif +/** @} */ /* end of iolinki_platform */ + #endif // IOLINK_PLATFORM_H diff --git a/include/iolinki/protocol.h b/include/iolinki/protocol.h index 42baf3f..2dce8ed 100644 --- a/include/iolinki/protocol.h +++ b/include/iolinki/protocol.h @@ -14,113 +14,191 @@ * @brief IO-Link Protocol Constants and Definitions (Spec V1.1.2) */ -/* M-Sequence Type Lengths */ -#define IOLINK_M_SEQ_TYPE0_LEN 2U -#define IOLINK_M_SEQ_HEADER_LEN 2U /* MC + CKT */ -#define IOLINK_M_SEQ_MIN_LEN 3U /* MC + CKT + CK (Type 1/2) */ +/** + * @defgroup iolinki_protocol IO-Link Protocol Constants + * @brief M-sequence, Master Command, ISDU, index, command and status constants. + * + * The constants are split into the sub-modules below, each mirroring a table + * or field layout from the IO-Link Interface Specification. + */ -/* Master Command (MC) Definitions */ -#define IOLINK_MC_RW_MASK 0x80U -#define IOLINK_MC_COMM_CHANNEL_MASK 0x60U -#define IOLINK_MC_ADDR_MASK 0x1FU +/** + * @defgroup iolinki_protocol_mseq M-Sequence Type Lengths + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_M_SEQ_TYPE0_LEN 2U /**< Type 0 M-sequence length in bytes. */ +#define IOLINK_M_SEQ_HEADER_LEN 2U /**< M-sequence header length: MC + CKT. */ +#define IOLINK_M_SEQ_MIN_LEN 3U /**< Minimum M-sequence length: MC + CKT + CK (Type 1/2). */ +/** @} */ -#define IOLINK_MC_TRANSITION_COMMAND 0x0FU +/** + * @defgroup iolinki_protocol_mc Master Command (MC) Definitions + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_MC_RW_MASK 0x80U /**< Read/Write bit mask in the MC byte. */ +#define IOLINK_MC_COMM_CHANNEL_MASK 0x60U /**< Communication channel field mask in the MC byte. */ +#define IOLINK_MC_ADDR_MASK 0x1FU /**< Address field mask in the MC byte. */ + +#define IOLINK_MC_TRANSITION_COMMAND 0x0FU /**< Address used for the transition command. */ -/* MasterCommand values written to Direct Parameter page address 0x00 (Table B.2). */ +/** @brief MasterCommand value written to Direct Parameter page address 0x00 (Table B.2). */ #define IOLINK_CMD_DEVICE_OPERATE 0x99U +/** @} */ + +/** + * @defgroup iolinki_protocol_isdu_ctrl ISDU Control Byte Bits + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_ISDU_CTRL_START 0x80U /**< Start-of-transfer flag. */ +#define IOLINK_ISDU_CTRL_LAST 0x40U /**< Last-segment flag. */ +#define IOLINK_ISDU_CTRL_SEQ_MASK 0x3FU /**< Sequence counter mask. */ +/** @} */ -/* ISDU Control Byte Bits */ -#define IOLINK_ISDU_CTRL_START 0x80U -#define IOLINK_ISDU_CTRL_LAST 0x40U -#define IOLINK_ISDU_CTRL_SEQ_MASK 0x3FU - -/* ISDU Service IDs */ -/* I-Service nibble, IO-Link spec Table A.12 (16-bit Index + Subindex form). */ -#define IOLINK_ISDU_SERVICE_READ 0x0BU -#define IOLINK_ISDU_SERVICE_WRITE 0x03U - -/* Mandatory ISDU Indices */ -#define IOLINK_IDX_DIRECT_PARAMETERS_1 0x0000U -#define IOLINK_IDX_DIRECT_PARAMETERS_2 0x0001U -#define IOLINK_IDX_SYSTEM_COMMAND 0x0002U -#define IOLINK_IDX_DATA_STORAGE 0x0003U /**< Data Storage object (parameter image) */ -#define IOLINK_IDX_VENDOR_ID 0x000AU -#define IOLINK_IDX_DEVICE_ID 0x000BU -#define IOLINK_IDX_DEVICE_ACCESS_LOCKS 0x000CU -#define IOLINK_IDX_PROFILE_CHARACTERISTIC 0x000DU -#define IOLINK_IDX_VENDOR_NAME 0x0010U -#define IOLINK_IDX_VENDOR_TEXT 0x0011U -#define IOLINK_IDX_PRODUCT_NAME 0x0012U -#define IOLINK_IDX_PRODUCT_ID 0x0013U -#define IOLINK_IDX_PRODUCT_TEXT 0x0014U -#define IOLINK_IDX_SERIAL_NUMBER 0x0015U -#define IOLINK_IDX_HARDWARE_REVISION 0x0016U -#define IOLINK_IDX_FIRMWARE_REVISION 0x0017U -#define IOLINK_IDX_APPLICATION_TAG 0x0018U -#define IOLINK_IDX_FUNCTION_TAG 0x0019U -#define IOLINK_IDX_LOCATION_TAG 0x001AU -#define IOLINK_IDX_DEVICE_STATUS 0x001BU -#define IOLINK_IDX_DETAILED_DEVICE_STATUS 0x001CU -#define IOLINK_IDX_PDIN_DESCRIPTOR 0x001DU -#define IOLINK_IDX_REVISION_ID 0x001EU -#define IOLINK_IDX_MIN_CYCLE_TIME 0x0024U -#define IOLINK_IDX_ERROR_STATS 0x0025U /**< Vendor-specific error statistics */ - -/* System Commands (Index 0x0002) */ -#define IOLINK_CMD_PARAM_DOWNLOAD_START 0x05U -#define IOLINK_CMD_PARAM_DOWNLOAD_END 0x06U -#define IOLINK_CMD_PARAM_UPLOAD_START 0x07U -#define IOLINK_CMD_PARAM_UPLOAD_END 0x08U -#define IOLINK_CMD_PARAM_DOWNLOAD_STORE 0x09U /* V1.0 legacy or optional */ - -/* Legacy/Non-Standard Commands (Deprecating) */ -#define IOLINK_CMD_DEVICE_RESET 0x80U -#define IOLINK_CMD_APPLICATION_RESET 0x81U -#define IOLINK_CMD_RESTORE_FACTORY_SETTINGS 0x82U -#define IOLINK_CMD_RESTORE_APP_DEFAULTS 0x83U -#define IOLINK_CMD_SET_COMM_MODE 0x84U -#define IOLINK_CMD_PARAM_UPLOAD 0x95U -#define IOLINK_CMD_PARAM_DOWNLOAD 0x96U -#define IOLINK_CMD_PARAM_BREAK 0x97U - -/* Device Access Locks (Index 0x000C) */ -#define IOLINK_LOCK_PARAM 0x01U /* Bit 0: Parameter (Write) Access */ -#define IOLINK_LOCK_DS 0x02U /* Bit 1: Data Storage Access */ -#define IOLINK_LOCK_LOCAL_PARAM 0x04U /* Bit 2: Local Parameterization */ -#define IOLINK_LOCK_LOCAL_UI 0x08U /* Bit 3: Local User Interface */ - -/* ISDU Error Codes (0x80xx) */ -#define IOLINK_ISDU_ERROR_NONE 0x00U -#define IOLINK_ISDU_ERROR_SERVICE_NOT_AVAIL 0x11U -#define IOLINK_ISDU_ERROR_SUBINDEX_NOT_AVAIL 0x12U -#define IOLINK_ISDU_ERROR_BUSY 0x30U -#define IOLINK_ISDU_ERROR_WRITE_PROTECTED 0x33U -#define IOLINK_ISDU_ERROR_PARAM_INCONSISTENT 0x40U /**< Parameter set inconsistent */ -#define IOLINK_ISDU_ERROR_SEGMENTATION 0x81U - -/* Event Constants */ -#define IOLINK_EVENT_BIT_STATUS 0x80U /* MSB of status byte in Type 1/2 */ - -/* Standard IO-Link Event Codes (0x1XXX–0x8XXX) */ -#define IOLINK_EVENT_CODE_COMM_ERR_GENERAL 0x1800U -#define IOLINK_EVENT_CODE_COMM_ERR_FRAMING 0x1801U -#define IOLINK_EVENT_CODE_COMM_ERR_CRC 0x1803U - -/* On-Request Data (OD) Constants */ -#define IOLINK_OD_LEN_8BIT 1U /* 1-byte OD (Type 1_x) */ -#define IOLINK_OD_LEN_16BIT 2U /* 2-byte OD (Type 2_x) */ -#define IOLINK_OD_LEN_32BIT 4U /* 4-byte OD (Type 2_V extended) */ - -/* OD Status Byte Bit Definitions (First byte of OD) */ -#define IOLINK_OD_STATUS_EVENT 0x80U /* Bit 7: Event present */ -#define IOLINK_OD_STATUS_PD_TOGGLE 0x40U /* Bit 6: PD Toggle (Consistency) */ -#define IOLINK_OD_STATUS_PD_VALID 0x20U /* Bit 5: PD_In valid */ -#define IOLINK_OD_STATUS_DEVICE_MASK 0x1FU /* Bits 4-0: Device status flags */ - -/* Device Status Flags (lower 5 bits of OD status) */ -#define IOLINK_DEVICE_STATUS_OK 0x00U /* Device operating normally */ -#define IOLINK_DEVICE_STATUS_MAINTENANCE 0x01U /* Maintenance required */ -#define IOLINK_DEVICE_STATUS_OUT_OF_SPEC 0x02U /* Out of specification */ -#define IOLINK_DEVICE_STATUS_FAILURE 0x03U /* Functional failure */ +/** + * @defgroup iolinki_protocol_isdu_service ISDU Service IDs + * @ingroup iolinki_protocol + * @brief I-Service nibble, IO-Link spec Table A.12 (16-bit Index + Subindex form). + * @{ + */ +#define IOLINK_ISDU_SERVICE_READ 0x0BU /**< ISDU read service. */ +#define IOLINK_ISDU_SERVICE_WRITE 0x03U /**< ISDU write service. */ +/** @} */ + +/** + * @defgroup iolinki_protocol_indices Mandatory ISDU Indices + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_IDX_DIRECT_PARAMETERS_1 0x0000U /**< Direct Parameter page 1. */ +#define IOLINK_IDX_DIRECT_PARAMETERS_2 0x0001U /**< Direct Parameter page 2. */ +#define IOLINK_IDX_SYSTEM_COMMAND 0x0002U /**< System Command index. */ +#define IOLINK_IDX_DATA_STORAGE 0x0003U /**< Data Storage object (parameter image). */ +#define IOLINK_IDX_VENDOR_ID 0x000AU /**< Vendor ID index. */ +#define IOLINK_IDX_DEVICE_ID 0x000BU /**< Device ID index. */ +#define IOLINK_IDX_DEVICE_ACCESS_LOCKS 0x000CU /**< Device Access Locks index. */ +#define IOLINK_IDX_PROFILE_CHARACTERISTIC 0x000DU /**< Profile characteristic index. */ +#define IOLINK_IDX_VENDOR_NAME 0x0010U /**< Vendor name index. */ +#define IOLINK_IDX_VENDOR_TEXT 0x0011U /**< Vendor text index. */ +#define IOLINK_IDX_PRODUCT_NAME 0x0012U /**< Product name index. */ +#define IOLINK_IDX_PRODUCT_ID 0x0013U /**< Product ID index. */ +#define IOLINK_IDX_PRODUCT_TEXT 0x0014U /**< Product text index. */ +#define IOLINK_IDX_SERIAL_NUMBER 0x0015U /**< Serial number index. */ +#define IOLINK_IDX_HARDWARE_REVISION 0x0016U /**< Hardware revision index. */ +#define IOLINK_IDX_FIRMWARE_REVISION 0x0017U /**< Firmware revision index. */ +#define IOLINK_IDX_APPLICATION_TAG 0x0018U /**< Application tag index. */ +#define IOLINK_IDX_FUNCTION_TAG 0x0019U /**< Function tag index. */ +#define IOLINK_IDX_LOCATION_TAG 0x001AU /**< Location tag index. */ +#define IOLINK_IDX_DEVICE_STATUS 0x001BU /**< Device status index. */ +#define IOLINK_IDX_DETAILED_DEVICE_STATUS 0x001CU /**< Detailed device status index. */ +#define IOLINK_IDX_PDIN_DESCRIPTOR 0x001DU /**< Process Data In descriptor index. */ +#define IOLINK_IDX_REVISION_ID 0x001EU /**< Revision ID index. */ +#define IOLINK_IDX_MIN_CYCLE_TIME 0x0024U /**< Minimum cycle time index. */ +#define IOLINK_IDX_ERROR_STATS 0x0025U /**< Vendor-specific error statistics. */ +/** @} */ + +/** + * @defgroup iolinki_protocol_sys_cmd System Commands (Index 0x0002) + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_CMD_PARAM_DOWNLOAD_START 0x05U /**< ParamDownloadStart command. */ +#define IOLINK_CMD_PARAM_DOWNLOAD_END 0x06U /**< ParamDownloadEnd command. */ +#define IOLINK_CMD_PARAM_UPLOAD_START 0x07U /**< ParamUploadStart command. */ +#define IOLINK_CMD_PARAM_UPLOAD_END 0x08U /**< ParamUploadEnd command. */ +#define IOLINK_CMD_PARAM_DOWNLOAD_STORE 0x09U /**< ParamDownloadStore (V1.0/optional). */ +/** @} */ + +/** + * @defgroup iolinki_protocol_legacy_cmd Legacy / Non-Standard Commands (Deprecating) + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_CMD_DEVICE_RESET 0x80U /**< Device reset command. */ +#define IOLINK_CMD_APPLICATION_RESET 0x81U /**< Application reset command. */ +#define IOLINK_CMD_RESTORE_FACTORY_SETTINGS 0x82U /**< Restore factory settings command. */ +#define IOLINK_CMD_RESTORE_APP_DEFAULTS 0x83U /**< Restore application defaults command. */ +#define IOLINK_CMD_SET_COMM_MODE 0x84U /**< Set communication mode command. */ +#define IOLINK_CMD_PARAM_UPLOAD 0x95U /**< Parameter upload command. */ +#define IOLINK_CMD_PARAM_DOWNLOAD 0x96U /**< Parameter download command. */ +#define IOLINK_CMD_PARAM_BREAK 0x97U /**< Parameter break command. */ +/** @} */ + +/** + * @defgroup iolinki_protocol_locks Device Access Locks (Index 0x000C) + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_LOCK_PARAM 0x01U /**< Bit 0: Parameter (write) access lock. */ +#define IOLINK_LOCK_DS 0x02U /**< Bit 1: Data Storage access lock. */ +#define IOLINK_LOCK_LOCAL_PARAM 0x04U /**< Bit 2: Local parameterization lock. */ +#define IOLINK_LOCK_LOCAL_UI 0x08U /**< Bit 3: Local user interface lock. */ +/** @} */ + +/** + * @defgroup iolinki_protocol_isdu_err ISDU Error Codes (0x80xx) + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_ISDU_ERROR_NONE 0x00U /**< No error. */ +#define IOLINK_ISDU_ERROR_SERVICE_NOT_AVAIL 0x11U /**< Requested service not available. */ +#define IOLINK_ISDU_ERROR_SUBINDEX_NOT_AVAIL 0x12U /**< Requested subindex not available. */ +#define IOLINK_ISDU_ERROR_BUSY 0x30U /**< Device busy. */ +#define IOLINK_ISDU_ERROR_WRITE_PROTECTED 0x33U /**< Parameter is write-protected. */ +#define IOLINK_ISDU_ERROR_PARAM_INCONSISTENT 0x40U /**< Parameter set inconsistent. */ +#define IOLINK_ISDU_ERROR_SEGMENTATION 0x81U /**< Segmentation error. */ +/** @} */ + +/** + * @defgroup iolinki_protocol_event Event Constants + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_EVENT_BIT_STATUS 0x80U /**< MSB of status byte in Type 1/2 (event flag). */ +/** @} */ + +/** + * @defgroup iolinki_protocol_event_codes Standard IO-Link Event Codes (0x1XXX-0x8XXX) + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_EVENT_CODE_COMM_ERR_GENERAL 0x1800U /**< General communication error. */ +#define IOLINK_EVENT_CODE_COMM_ERR_FRAMING 0x1801U /**< Framing communication error. */ +#define IOLINK_EVENT_CODE_COMM_ERR_CRC 0x1803U /**< CRC communication error. */ +/** @} */ + +/** + * @defgroup iolinki_protocol_od On-Request Data (OD) Constants + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_OD_LEN_8BIT 1U /**< 1-byte OD (Type 1_x). */ +#define IOLINK_OD_LEN_16BIT 2U /**< 2-byte OD (Type 2_x). */ +#define IOLINK_OD_LEN_32BIT 4U /**< 4-byte OD (Type 2_V extended). */ +/** @} */ + +/** + * @defgroup iolinki_protocol_od_status OD Status Byte Bit Definitions (First byte of OD) + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_OD_STATUS_EVENT 0x80U /**< Bit 7: Event present. */ +#define IOLINK_OD_STATUS_PD_TOGGLE 0x40U /**< Bit 6: PD Toggle (consistency). */ +#define IOLINK_OD_STATUS_PD_VALID 0x20U /**< Bit 5: PD_In valid. */ +#define IOLINK_OD_STATUS_DEVICE_MASK 0x1FU /**< Bits 4-0: Device status flags. */ +/** @} */ + +/** + * @defgroup iolinki_protocol_device_status Device Status Flags (lower 5 bits of OD status) + * @ingroup iolinki_protocol + * @{ + */ +#define IOLINK_DEVICE_STATUS_OK 0x00U /**< Device operating normally. */ +#define IOLINK_DEVICE_STATUS_MAINTENANCE 0x01U /**< Maintenance required. */ +#define IOLINK_DEVICE_STATUS_OUT_OF_SPEC 0x02U /**< Out of specification. */ +#define IOLINK_DEVICE_STATUS_FAILURE 0x03U /**< Functional failure. */ +/** @} */ #endif /* IOLINK_PROTOCOL_H */ diff --git a/include/iolinki/time_utils.h b/include/iolinki/time_utils.h index aa73023..97227e1 100644 --- a/include/iolinki/time_utils.h +++ b/include/iolinki/time_utils.h @@ -16,6 +16,17 @@ * @brief Time abstractions for IO-Link timing enforcement */ +/** + * @defgroup iolinki_time Time Utilities + * @brief Time-unit conversions and system time sources. + * @{ + */ + +/** + * @brief Convert milliseconds to microseconds. + * @param ms Duration in milliseconds. + * @return Equivalent duration in microseconds. + */ static inline uint64_t iolink_us_from_ms(uint32_t ms) { return (uint64_t) ms * 1000ULL; @@ -33,4 +44,6 @@ uint32_t iolink_time_get_ms(void); */ uint64_t iolink_time_get_us(void); +/** @} */ /* end of iolinki_time */ + #endif // IOLINK_TIME_UTILS_H diff --git a/include/iolinki/utils.h b/include/iolinki/utils.h index db0722d..a9eac66 100644 --- a/include/iolinki/utils.h +++ b/include/iolinki/utils.h @@ -13,11 +13,42 @@ #include #include +/** + * @file utils.h + * @brief Miscellaneous helper utilities. + * + * Small inline helpers for buffer validation and context zeroing used + * throughout the IO-Link stack. + */ + +/** + * @defgroup iolinki_utils Miscellaneous Utilities + * @brief Inline buffer-validation and memory helpers. + * @{ + */ + +/** + * @brief Validate a (pointer, length) buffer pair. + * + * A buffer is considered valid unless it is NULL while claiming a non-zero + * length. A NULL pointer with zero length is valid. + * + * @param data Buffer pointer to validate. + * @param len Claimed length of @p data in bytes. + * @return true if the pair is valid, false otherwise. + */ static inline bool iolink_buf_is_valid(const void* data, size_t len) { return !((data == NULL) && (len > 0U)); } +/** + * @brief Zero-initialize a context object. + * + * @param[out] ctx Object to clear; ignored (returns false) if NULL. + * @param len Number of bytes to zero. + * @return true if @p ctx was cleared, false if @p ctx was NULL. + */ static inline bool iolink_ctx_zero(void* ctx, size_t len) { if (ctx == NULL) { @@ -27,4 +58,6 @@ static inline bool iolink_ctx_zero(void* ctx, size_t len) return true; } +/** @} */ /* end of iolinki_utils */ + #endif /* IOLINK_UTILS_H */ diff --git a/src/crc.c b/src/crc.c index f024d03..092c30d 100644 --- a/src/crc.c +++ b/src/crc.c @@ -6,6 +6,15 @@ * See LICENSE for details. */ +/** + * @file crc.c + * @brief IO-Link CRC6 / checksum implementation. + * @ingroup iolinki_crc + * + * Implements the 6-bit M-sequence CRC and the derived checksum used to + * protect IO-Link frames. + */ + #include "iolinki/crc.h" #include "iolinki/utils.h" #include diff --git a/src/data_storage.c b/src/data_storage.c index f05dd9b..fa125c3 100644 --- a/src/data_storage.c +++ b/src/data_storage.c @@ -6,13 +6,10 @@ * See LICENSE for details. */ -#include "iolinki/data_storage.h" -#include "iolinki/params.h" -#include "iolinki/utils.h" -#include - -/* - * IO-Link Data Storage parameter server. +/** + * @file data_storage.c + * @brief IO-Link Data Storage (DS) parameter server. + * @ingroup iolinki_data_storage * * The Master keeps an opaque backup of a device's parameters so a replacement * unit can be restored automatically. The device serializes its DS-backed @@ -21,6 +18,11 @@ * [Index(2, big-endian)][Subindex(1)][Length(1)][Data(Length)] */ +#include "iolinki/data_storage.h" +#include "iolinki/params.h" +#include "iolinki/utils.h" +#include + /* Parameters included in the Data Storage set (V1.1.5 device identification parameters that are writable and therefore worth backing up). */ static const struct @@ -53,6 +55,7 @@ void iolink_ds_bind_params(iolink_ds_ctx_t* ctx, iolink_params_ctx_t* params_ctx } } +/** @brief Read a parameter via the bound params context, or the legacy global set. */ static int ds_params_get(const iolink_ds_ctx_t* ctx, uint16_t index, uint8_t subindex, uint8_t* buffer, size_t max_len) { @@ -62,6 +65,7 @@ static int ds_params_get(const iolink_ds_ctx_t* ctx, uint16_t index, uint8_t sub return iolink_params_get(index, subindex, buffer, max_len); } +/** @brief Write a parameter via the bound params context, or the legacy global set. */ static int ds_params_set(iolink_ds_ctx_t* ctx, uint16_t index, uint8_t subindex, const uint8_t* data, size_t len, bool persist) { diff --git a/src/device.c b/src/device.c index 6b23ad3..6b01a02 100644 --- a/src/device.c +++ b/src/device.c @@ -6,11 +6,22 @@ * See LICENSE for details. */ +/** + * @file device.c + * @brief Device application layer: top-level stack lifecycle and I/O. + * @ingroup iolinki_device + * + * Wires together the DLL, ISDU, parameter, device-info and data-storage + * sub-contexts, drives the per-cycle processing, and exposes process-data + * exchange and status accessors to the application. + */ + #include "iolinki/device.h" #include "iolinki/platform.h" #include "iolinki/time_utils.h" #include +/** @brief DLL state-change callback: dispatches to the app startup/preoperate/operate hooks. */ static void device_state_cb(void* user, iolink_dll_state_t state) { iolink_device_ctx_t* ctx = (iolink_device_ctx_t*) user; @@ -40,6 +51,7 @@ static void device_state_cb(void* user, iolink_dll_state_t state) } } +/** @brief Copy the user stack configuration into the DLL context and derive lengths/timing. */ static void device_apply_stack_config(iolink_device_ctx_t* ctx) { ctx->dll.m_seq_type = (uint8_t) ctx->stack_config.m_seq_type; diff --git a/src/device_info.c b/src/device_info.c index 9602c07..f6ba859 100644 --- a/src/device_info.c +++ b/src/device_info.c @@ -6,6 +6,16 @@ * See LICENSE for details. */ +/** + * @file device_info.c + * @brief Device identification storage and access. + * @ingroup iolinki_device_info + * + * Holds the device identification parameters (vendor/product strings, IDs, + * access locks) in a context, with a legacy singleton wrapper for callers that + * do not manage their own context. + */ + #include "iolinki/device_info.h" #include #include @@ -111,6 +121,7 @@ void iolink_device_info_ctx_set_access_locks(iolink_device_info_ctx_t* ctx, uint ctx->defaults.access_locks = locks; } +/** @brief Lazily initialize and return the process-wide legacy device-info context. */ static iolink_device_info_ctx_t* legacy_device_info_ctx(void) { if (!g_legacy_device_info_ctx_initialized) { diff --git a/src/dll.c b/src/dll.c index 341710c..ece24d2 100644 --- a/src/dll.c +++ b/src/dll.c @@ -15,10 +15,25 @@ #include #include +/** + * @file dll.c + * @brief Data Link Layer (DLL): M-sequence state machine and framing. + * @ingroup iolinki_dll + * + * Drives the IO-Link device DLL: wake-up detection, mode/baudrate management, + * per-frame reception and CRC validation, the STARTUP -> PREOPERATE -> + * OPERATE state machine, timing enforcement, fallback handling, and dispatch + * of Type-0/Type-1/Type-2 M-sequences into the ISDU engine. + */ + #define DLL_LOG(...) -/* Centralised state transition: updates the state and notifies the optional - state-change hook on an actual change, so no transition is ever missed. */ +/** + * @brief Centralised state transition. + * + * Updates the state and notifies the optional state-change hook on an actual + * change, so no transition is ever missed. + */ static void dll_set_state(iolink_dll_ctx_t* ctx, iolink_dll_state_t new_state) { if (ctx->state != new_state) { @@ -29,6 +44,7 @@ static void dll_set_state(iolink_dll_ctx_t* ctx, iolink_dll_state_t new_state) } } +/** @brief Return the response-time (t_REN) limit in us for the active baudrate/override. */ static uint32_t dll_get_t_ren_limit_us(const iolink_dll_ctx_t* ctx) { if (ctx == NULL) { @@ -50,6 +66,7 @@ static uint32_t dll_get_t_ren_limit_us(const iolink_dll_ctx_t* ctx) } } +/** @brief Return the inter-byte timeout (16 bit-times) in us for the active baudrate. */ static uint32_t dll_get_t_byte_limit_us(const iolink_dll_ctx_t* ctx) { if (ctx == NULL) { @@ -73,6 +90,7 @@ static uint32_t dll_get_t_byte_limit_us(const iolink_dll_ctx_t* ctx) return t_bit_us * 16U; } +/** @brief Return true while the power-down/PD guard window (t_PD) is still active. */ static bool dll_t_pd_active(const iolink_dll_ctx_t* ctx) { if ((ctx == NULL) || (ctx->t_pd_deadline_us == 0U)) { @@ -81,6 +99,7 @@ static bool dll_t_pd_active(const iolink_dll_ctx_t* ctx) return iolink_time_get_us() < ctx->t_pd_deadline_us; } +/** @brief Drain all pending RX bytes from the PHY; returns true if any were seen. */ static bool dll_drain_rx(iolink_dll_ctx_t* ctx) { if ((ctx == NULL) || (ctx->phy == NULL) || (ctx->phy->recv_byte == NULL)) { @@ -94,6 +113,7 @@ static bool dll_drain_rx(iolink_dll_ctx_t* ctx) return saw_byte; } +/** @brief Handle a communication failure: count retries and revert toward SIO/STARTUP. */ static void dll_enter_fallback(iolink_dll_ctx_t* ctx) { if (ctx == NULL) { @@ -121,6 +141,7 @@ static void dll_enter_fallback(iolink_dll_ctx_t* ctx) } } +/** @brief Handle a PREOPERATE master command: advance to ESTAB_COM on the transition command. */ static void dll_handle_preoperate(iolink_dll_ctx_t* ctx, uint8_t mc, uint8_t ck) { (void) ck; @@ -131,10 +152,14 @@ static void dll_handle_preoperate(iolink_dll_ctx_t* ctx, uint8_t mc, uint8_t ck) } } -/* Answer a startup Type-0 read on the page communication channel (spec startup - transition T1): the master reads a Direct Parameter page octet (address in the - MC address field, e.g. 0x02 = MinCycleTime). Reply with a 2-octet Type-0 frame - carrying that octet, rather than feeding the MC into the ISDU engine. */ +/** + * @brief Answer a startup Type-0 read on the page communication channel. + * + * Spec startup transition T1: the master reads a Direct Parameter page octet + * (address in the MC address field, e.g. 0x02 = MinCycleTime). Reply with a + * 2-octet Type-0 frame carrying that octet, rather than feeding the MC into the + * ISDU engine. + */ static void dll_handle_page_channel_read(iolink_dll_ctx_t* ctx, uint8_t mc) { uint8_t resp[2]; @@ -146,6 +171,7 @@ static void dll_handle_page_channel_read(iolink_dll_ctx_t* ctx, uint8_t mc) } } +/** @brief Process a 2-octet Type-0 request through ISDU and send the OD response. */ static void dll_handle_operate_type0(iolink_dll_ctx_t* ctx, uint8_t mc, uint8_t cks) { (void) cks; @@ -163,6 +189,7 @@ static void dll_handle_operate_type0(iolink_dll_ctx_t* ctx, uint8_t mc, uint8_t } } +/** @brief Process a Type-1/Type-2 OPERATE frame (PD+OD) and build the response, enforcing t_REN. */ static void dll_handle_operate_type1_2(iolink_dll_ctx_t* ctx) { /* IO-Link V1.1 M-sequence structure: MC | CKT | PD | OD | CK */ @@ -221,6 +248,7 @@ static void dll_handle_operate_type1_2(iolink_dll_ctx_t* ctx) ctx->last_response_us = iolink_time_get_us(); } +/** @brief Poll PHY voltage and short-circuit status and raise events on faults. */ static void dll_poll_diagnostics(iolink_dll_ctx_t* ctx) { if ((ctx == NULL) || (ctx->phy == NULL)) { diff --git a/src/dll_internal.h b/src/dll_internal.h index 87dcbab..0760be1 100644 --- a/src/dll_internal.h +++ b/src/dll_internal.h @@ -25,17 +25,18 @@ #define IOLINK_M_SEQ_TYPE2_LEN(pd_len, od_len) \ (3 + (pd_len) + (od_len)) /* MC(8) + CKT(8) + PD(var) + OD(var) + CK(8) */ +/** @brief Decoded 2-octet Type-0 M-sequence (master command + checksum). */ typedef struct { - uint8_t master_command; - uint8_t ck; + uint8_t master_command; /**< Master command octet (MC). */ + uint8_t ck; /**< Checksum octet (CK). */ } iolink_m_seq_type0_t; -/* Definitions for OD handling */ +/** @brief On-request data (OD) octet paired with a validity flag. */ typedef struct { - uint8_t od_data; - uint8_t valid; + uint8_t od_data; /**< On-request data octet. */ + uint8_t valid; /**< Non-zero when @ref od_data holds a valid value. */ } iolink_od_req_t; #endif // IOLINK_DLL_INTERNAL_H diff --git a/src/events.c b/src/events.c index 40e648d..a08896e 100644 --- a/src/events.c +++ b/src/events.c @@ -9,6 +9,10 @@ /** * @file events.c * @brief IO-Link Event Handling + * @ingroup iolinki_events + * + * Implements the device event queue (enqueue/pop/peek), severity ranking and + * event-code classification used to report diagnostics to the master. */ #include "iolinki/events.h" diff --git a/src/frame.c b/src/frame.c index a5aec2d..0482bf5 100644 --- a/src/frame.c +++ b/src/frame.c @@ -6,6 +6,15 @@ * See LICENSE for details. */ +/** + * @file frame.c + * @brief M-sequence frame encoding and decoding. + * @ingroup iolinki_frame + * + * Builds Type-0/Type-1 request frames and decodes OPERATE-mode response + * frames, computing and verifying the associated M-sequence checksums. + */ + #include "iolinki/frame.h" #include "iolinki/crc.h" #include "iolinki/protocol.h" diff --git a/src/isdu.c b/src/isdu.c index 47c4644..e3409fa 100644 --- a/src/isdu.c +++ b/src/isdu.c @@ -20,8 +20,15 @@ #include #include -/* - * IO-Link ISDU Segmentation Engine +/** + * @file isdu.c + * @brief ISDU service engine: acyclic parameter read/write handling. + * @ingroup iolinki_isdu + * + * Implements the ISDU segmentation state machine (byte collection, header + * parsing, sequence tracking and response segmentation) and dispatches + * standard indices and system commands to the device parameter, device-info, + * event, direct-parameter and data-storage handlers. * * ISDU Header (2 or 3 bytes): * [7:4] Service (Read/Write) @@ -43,6 +50,7 @@ void iolink_isdu_init(iolink_isdu_ctx_t* ctx) ctx->next_state = ISDU_STATE_IDLE; } +/** @brief Read a parameter via the bound params context, or the legacy global set. */ static int isdu_params_get(const iolink_isdu_ctx_t* ctx, uint16_t index, uint8_t subindex, uint8_t* buffer, size_t max_len) { @@ -52,6 +60,7 @@ static int isdu_params_get(const iolink_isdu_ctx_t* ctx, uint16_t index, uint8_t return iolink_params_get(index, subindex, buffer, max_len); } +/** @brief Write a parameter via the bound params context, or the legacy global set. */ static int isdu_params_set(iolink_isdu_ctx_t* ctx, uint16_t index, uint8_t subindex, const uint8_t* data, size_t len, bool persist) { @@ -61,6 +70,7 @@ static int isdu_params_set(iolink_isdu_ctx_t* ctx, uint16_t index, uint8_t subin return iolink_params_set(index, subindex, data, len, persist); } +/** @brief Factory-reset the bound parameter context, or the legacy global set. */ static void isdu_params_factory_reset(iolink_isdu_ctx_t* ctx) { /* Reset the device's own parameter context when one is bound (as device.c @@ -75,6 +85,7 @@ static void isdu_params_factory_reset(iolink_isdu_ctx_t* ctx) } } +/** @brief Begin a new ISDU transfer from the start control byte, resetting buffers. */ static int isdu_handle_idle(iolink_isdu_ctx_t* ctx, uint8_t byte) { bool start = ((byte & IOLINK_ISDU_CTRL_START) != 0U); @@ -257,6 +268,7 @@ int iolink_isdu_collect_byte(iolink_isdu_ctx_t* ctx, uint8_t byte) return 0; } +/** @brief Serve the mandatory identification/status indices (vendor, product, tags, etc.). */ static void handle_mandatory_indices(iolink_isdu_ctx_t* ctx) { const iolink_device_info_t* info = iolink_device_info_get(); @@ -469,6 +481,7 @@ static void handle_mandatory_indices(iolink_isdu_ctx_t* ctx) } } +/** @brief Execute a SystemCommand (reset, factory restore, data-storage commands). */ static void handle_system_command(iolink_isdu_ctx_t* ctx, uint8_t cmd) { switch (cmd) { @@ -576,6 +589,7 @@ static void handle_system_command(iolink_isdu_ctx_t* ctx, uint8_t cmd) ctx->state = ISDU_STATE_RESPONSE_READY; } +/** @brief Read or write the DeviceAccessLocks parameter (index 0x000C). */ static void handle_access_locks(iolink_isdu_ctx_t* ctx) { if (ctx->header.type == IOLINK_ISDU_SERVICE_TYPE_READ) { @@ -596,6 +610,7 @@ static void handle_access_locks(iolink_isdu_ctx_t* ctx) ctx->state = ISDU_STATE_RESPONSE_READY; } +/** @brief Serve DetailedDeviceStatus: encode up to 8 queued events as qualifier+code triplets. */ static void handle_detailed_device_status(iolink_isdu_ctx_t* ctx) { if (ctx->header.type != IOLINK_ISDU_SERVICE_TYPE_READ) { @@ -652,6 +667,7 @@ static void handle_detailed_device_status(iolink_isdu_ctx_t* ctx) iolink_critical_exit(); } +/** @brief Append a 32-bit value to a buffer in big-endian order, advancing the index. */ static void isdu_write_u32_be(uint8_t* buf, size_t* idx, uint32_t value) { buf[(*idx)++] = (uint8_t) ((value >> 24) & 0xFFU); @@ -660,6 +676,7 @@ static void isdu_write_u32_be(uint8_t* buf, size_t* idx, uint32_t value) buf[(*idx)++] = (uint8_t) (value & 0xFFU); } +/** @brief Serve the vendor error-statistics index as four big-endian DLL counters. */ static void handle_error_stats(iolink_isdu_ctx_t* ctx) { if (ctx->header.type != IOLINK_ISDU_SERVICE_TYPE_READ) { @@ -696,7 +713,7 @@ static void handle_error_stats(iolink_isdu_ctx_t* ctx) ctx->state = ISDU_STATE_RESPONSE_READY; } -/* Direct Parameter page 2 (device-specific, addresses 0x10-0x1F). */ +/** @brief Return the Direct Parameter page 2 storage (device-specific, addresses 0x10-0x1F). */ static uint8_t* direct_param_page2(iolink_isdu_ctx_t* ctx) { static uint8_t fallback_page2[16] = {0U}; @@ -707,8 +724,11 @@ static uint8_t* direct_param_page2(iolink_isdu_ctx_t* ctx) return fallback_page2; } -/* Encode a Process Data length (in octets) per IO-Link V1.1.5 Figure B.5: - <=2 octets are expressed as bit length (BYTE=0); larger as octets (BYTE=1). */ +/** + * @brief Encode a Process Data length (in octets) per IO-Link V1.1.5 Figure B.5. + * + * <=2 octets are expressed as bit length (BYTE=0); larger as octets (BYTE=1). + */ static uint8_t direct_param_encode_pd(uint8_t octets) { if (octets == 0U) { @@ -720,8 +740,11 @@ static uint8_t direct_param_encode_pd(uint8_t octets) return (uint8_t) (0x80U | (uint8_t) (octets - 1U)); /* BYTE=1, Length=octets-1 */ } -/* M-sequenceCapability byte (Direct Parameter addr 0x03, Figure B.3): - bit0 = ISDU supported, bits1-3 = OPERATE M-sequence code, bits4-5 = PREOPERATE. */ +/** + * @brief Build the M-sequenceCapability byte (Direct Parameter addr 0x03, Figure B.3). + * + * bit0 = ISDU supported, bits1-3 = OPERATE M-sequence code, bits4-5 = PREOPERATE. + */ static uint8_t direct_param_mseq_capability(uint8_t m_seq_type) { uint8_t cap = 0x01U; /* ISDU supported */ @@ -744,6 +767,7 @@ static uint8_t direct_param_mseq_capability(uint8_t m_seq_type) return cap; } +/** @brief Populate the 16-octet Direct Parameter page 1 from device-info and DLL state. */ static void build_direct_param_page1(iolink_isdu_ctx_t* ctx, uint8_t* page) { const iolink_device_info_t* info = iolink_device_info_get(); @@ -785,6 +809,7 @@ uint8_t iolink_isdu_direct_param_page1_octet(iolink_isdu_ctx_t* ctx, uint8_t add return page[addr]; } +/** @brief Read/write Direct Parameter pages 1 (read-only) and 2 (device-specific). */ static void handle_direct_parameters(iolink_isdu_ctx_t* ctx) { bool page2 = (ctx->header.index == IOLINK_IDX_DIRECT_PARAMETERS_2); @@ -843,6 +868,7 @@ static void handle_direct_parameters(iolink_isdu_ctx_t* ctx) ctx->state = ISDU_STATE_RESPONSE_READY; } +/** @brief Serve the Data Storage index: backup (read image) or restore (apply image). */ static void handle_data_storage(iolink_isdu_ctx_t* ctx) { iolink_ds_ctx_t* ds = (iolink_ds_ctx_t*) ctx->ds_ctx; @@ -884,6 +910,7 @@ static void handle_data_storage(iolink_isdu_ctx_t* ctx) ctx->state = ISDU_STATE_RESPONSE_READY; } +/** @brief Dispatch an executed ISDU request to the handler for its index. */ static void handle_standard_commands(iolink_isdu_ctx_t* ctx) { if (ctx->header.index == IOLINK_IDX_SYSTEM_COMMAND) { diff --git a/src/params.c b/src/params.c index 31faa0c..7750f42 100644 --- a/src/params.c +++ b/src/params.c @@ -6,6 +6,17 @@ * See LICENSE for details. */ +/** + * @file params.c + * @brief Parameter manager: writable device tags with NVM persistence. + * @ingroup iolinki_params + * + * Manages the application/function/location tag parameters, loading and + * persisting them via the platform NVM interface, and mirrors the application + * tag into the device-info context. A legacy singleton wrapper is provided for + * context-less callers. + */ + #include "iolinki/params.h" #include "iolinki/platform.h" #include "iolinki/protocol.h" @@ -27,6 +38,7 @@ static iolink_device_info_ctx_t g_legacy_device_info_ctx; static iolink_params_ctx_t g_legacy_params_ctx; static bool g_legacy_params_ctx_initialized = false; +/** @brief Copy up to 32 bytes into a NUL-terminated tag buffer and mark it valid. */ static void copy_tag(char* dst, bool* valid, const uint8_t* data, size_t len) { size_t copy_len = (len > 32U) ? 32U : len; @@ -38,6 +50,7 @@ static void copy_tag(char* dst, bool* valid, const uint8_t* data, size_t len) *valid = true; } +/** @brief Return the tag string length, clamped to the 32-byte maximum. */ static size_t bounded_tag_len(const char* tag) { size_t len = strlen(tag); @@ -47,6 +60,7 @@ static size_t bounded_tag_len(const char* tag) return len; } +/** @brief Copy a bounded tag string into an output buffer; returns bytes written. */ static int read_tag(const char* tag, uint8_t* buffer, size_t max_len) { size_t len = bounded_tag_len(tag); @@ -59,6 +73,7 @@ static int read_tag(const char* tag, uint8_t* buffer, size_t max_len) return (int) len; } +/** @brief Serialize the valid tags into the NVM record and write it to storage. */ static void params_ctx_write_nvm(const iolink_params_ctx_t* ctx) { iolink_params_nvm_t nvm; @@ -200,6 +215,7 @@ void iolink_params_ctx_factory_reset(iolink_params_ctx_t* ctx) params_ctx_write_nvm(ctx); } +/** @brief Lazily initialize and return the process-wide legacy parameter context. */ static iolink_params_ctx_t* legacy_params_ctx(void) { if (!g_legacy_params_ctx_initialized) { diff --git a/src/phy_generic.c b/src/phy_generic.c index 136437a..69647ae 100644 --- a/src/phy_generic.c +++ b/src/phy_generic.c @@ -6,8 +6,18 @@ * See LICENSE for details. */ +/** + * @file phy_generic.c + * @brief Template/skeleton generic UART PHY adapter. + * @ingroup iolinki_phy_generic + * + * Provides a non-functional reference PHY implementation whose hooks are meant + * to be filled in with target-specific UART/GPIO/transceiver code. + */ + #include "iolinki/phy_generic.h" +/** @brief Template PHY init hook (returns failure until implemented). */ static int generic_init(void* user) { (void) user; @@ -15,6 +25,7 @@ static int generic_init(void* user) return -1; } +/** @brief Template hook to configure the transceiver for SIO/SDCI mode. */ static void generic_set_mode(void* user, iolink_phy_mode_t mode) { (void) user; @@ -22,6 +33,7 @@ static void generic_set_mode(void* user, iolink_phy_mode_t mode) /* Template: configure transceiver for SIO/SDCI. */ } +/** @brief Template hook to configure UART speed for COM1/2/3. */ static void generic_set_baudrate(void* user, iolink_baudrate_t baudrate) { (void) user; @@ -29,6 +41,7 @@ static void generic_set_baudrate(void* user, iolink_baudrate_t baudrate) /* Template: configure UART speed for COM1/2/3. */ } +/** @brief Template hook to transmit data over the C/Q line. */ static int generic_send(void* user, const uint8_t* data, size_t len) { (void) user; @@ -38,6 +51,7 @@ static int generic_send(void* user, const uint8_t* data, size_t len) return -1; } +/** @brief Template hook for non-blocking single-byte receive. */ static int generic_recv_byte(void* user, uint8_t* byte) { (void) user; @@ -46,6 +60,7 @@ static int generic_recv_byte(void* user, uint8_t* byte) return 0; } +/** @brief Template hook to detect the 80us wake-up pulse on the C/Q line. */ static int generic_detect_wakeup(void* user) { (void) user; @@ -53,6 +68,7 @@ static int generic_detect_wakeup(void* user) return 0; } +/** @brief Template hook to drive the C/Q line high/low in SIO mode. */ static void generic_set_cq_line(void* user, uint8_t state) { (void) user; @@ -60,6 +76,7 @@ static void generic_set_cq_line(void* user, uint8_t state) /* Template: drive C/Q line high/low in SIO mode. */ } +/** @brief Template hook to read supply voltage in mV (negative if unavailable). */ static int generic_get_voltage_mv(void* user) { (void) user; @@ -67,6 +84,7 @@ static int generic_get_voltage_mv(void* user) return -1; } +/** @brief Template hook returning true when a short-circuit fault is detected. */ static bool generic_is_short_circuit(void* user) { (void) user; diff --git a/src/phy_virtual.c b/src/phy_virtual.c index 64ccab3..bd783c5 100644 --- a/src/phy_virtual.c +++ b/src/phy_virtual.c @@ -12,6 +12,16 @@ #define _DEFAULT_SOURCE 1 #endif +/** + * @file phy_virtual.c + * @brief Virtual PHY backed by a POSIX serial port / pseudo-terminal. + * @ingroup iolinki_phy_virtual + * + * Implements the PHY API over a host file descriptor (TTY or pipe) so the + * device stack can be exercised via loopback or a virtual serial link during + * development and testing. + */ + #include "iolinki/phy_virtual.h" #include #include @@ -28,6 +38,7 @@ void iolink_phy_virtual_set_port(const char* port) g_port_path = port; } +/** @brief Open and configure the backing serial port in raw, non-blocking mode. */ static int virtual_init(void* user) { (void) user; @@ -69,18 +80,21 @@ static int virtual_init(void* user) return 0; } +/** @brief Log the requested PHY mode (no electrical effect on the virtual link). */ static void virtual_set_mode(void* user, iolink_phy_mode_t mode) { (void) user; printf("[PHY-VIRTUAL] Mode set to: %d\n", (int) mode); } +/** @brief Log the requested baudrate (no effect on the virtual link). */ static void virtual_set_baudrate(void* user, iolink_baudrate_t baudrate) { (void) user; printf("[PHY-VIRTUAL] Baudrate set to: %d\n", (int) baudrate); } +/** @brief Write a buffer to the backing file descriptor. */ static int virtual_send(void* user, const uint8_t* data, size_t len) { (void) user; @@ -94,6 +108,7 @@ static int virtual_send(void* user, const uint8_t* data, size_t len) return (int) write(g_fd, data, len); } +/** @brief Non-blocking read of a single byte from the backing file descriptor. */ static int virtual_recv_byte(void* user, uint8_t* byte) { (void) user; @@ -106,6 +121,7 @@ static int virtual_recv_byte(void* user, uint8_t* byte) return (n > 0) ? 1 : 0; } +/** @brief Scan buffered input for a 0x55 wake-up marker byte. */ static int virtual_detect_wakeup(void* user) { (void) user; diff --git a/src/platform.c b/src/platform.c index 9b0090b..a645453 100644 --- a/src/platform.c +++ b/src/platform.c @@ -6,6 +6,16 @@ * See LICENSE for details. */ +/** + * @file platform.c + * @brief Default weak platform abstraction implementations. + * @ingroup iolinki_platform + * + * Provides no-op / not-implemented weak defaults for the critical-section and + * NVM access hooks so the stack links without a platform port; a real port + * overrides these symbols. + */ + #include "iolinki/platform.h" /* Weak definitions allow the application to override them without link errors */ diff --git a/src/platform/baremetal/time_utils.c b/src/platform/baremetal/time_utils.c index ff87fd5..87c010f 100644 --- a/src/platform/baremetal/time_utils.c +++ b/src/platform/baremetal/time_utils.c @@ -6,6 +6,16 @@ * See LICENSE for details. */ +/** + * @file time_utils.c + * @brief Bare-metal time utilities implementation (SysTick tick counter). + * @ingroup iolinki_time + * + * Provides the millisecond and microsecond time sources backed by a global + * tick counter that the application is expected to increment from a SysTick + * (or equivalent) ISR. + */ + #include "iolinki/time_utils.h" /* diff --git a/src/platform/linux/nvm_mock.c b/src/platform/linux/nvm_mock.c index b443800..90a8c63 100644 --- a/src/platform/linux/nvm_mock.c +++ b/src/platform/linux/nvm_mock.c @@ -6,6 +6,15 @@ * See LICENSE for details. */ +/** + * @file nvm_mock.c + * @brief Linux file-backed NVM mock implementation. + * @ingroup iolinki_platform + * + * Implements the platform NVM read/write hooks against a local binary file, + * used for host-side testing of parameter persistence. + */ + #include "iolinki/platform.h" #include "iolinki/utils.h" #include diff --git a/src/platform/linux/time_utils.c b/src/platform/linux/time_utils.c index 09ab9f4..a27e140 100644 --- a/src/platform/linux/time_utils.c +++ b/src/platform/linux/time_utils.c @@ -6,6 +6,15 @@ * See LICENSE for details. */ +/** + * @file time_utils.c + * @brief Linux time utilities implementation (CLOCK_MONOTONIC). + * @ingroup iolinki_time + * + * Provides the millisecond and microsecond monotonic time sources used by the + * stack, backed by POSIX clock_gettime(). + */ + #include "iolinki/time_utils.h" #include diff --git a/src/platform/zephyr/phy_uart.c b/src/platform/zephyr/phy_uart.c index 91edc0b..e1aa40b 100644 --- a/src/platform/zephyr/phy_uart.c +++ b/src/platform/zephyr/phy_uart.c @@ -6,6 +6,17 @@ * See LICENSE for details. */ +/** + * @file phy_uart.c + * @brief Zephyr UART-backed IO-Link PHY implementation. + * @ingroup iolinki_phy + * + * Implements the PHY API over a Zephyr UART device: interrupt-driven RX into a + * ring buffer, polled TX, runtime baudrate configuration, and devicetree-based + * device resolution. Wake-up and C/Q line control are not supported over a + * plain UART and are left unimplemented. + */ + #include "phy_uart.h" #include #include @@ -35,10 +46,11 @@ static const struct device* g_uart_dev; static uint8_t g_rx_storage[CONFIG_IOLINK_PHY_UART_RX_RING_SIZE]; static struct ring_buf g_rx_rb; -/* - * UART interrupt service routine: drains the hardware FIFO into the RX ring - * buffer. Bytes that do not fit are dropped (and counted via a log warning) to - * keep the ISR bounded. +/** + * @brief UART interrupt service routine. + * + * Drains the hardware FIFO into the RX ring buffer. Bytes that do not fit are + * dropped (and counted via a log warning) to keep the ISR bounded. */ static void uart_phy_isr(const struct device* dev, void* user_data) { @@ -63,6 +75,7 @@ static void uart_phy_isr(const struct device* dev, void* user_data) } } +/** @brief Initialize the bound UART, set up the RX ring buffer and enable IRQ RX. */ static int uart_phy_init(void* user) { (void) user; @@ -96,6 +109,7 @@ static int uart_phy_init(void* user) return 0; } +/** @brief Mode hint: no-op for a plain UART (mode is owned by the transceiver). */ static void uart_phy_set_mode(void* user, iolink_phy_mode_t mode) { (void) user; @@ -108,6 +122,7 @@ static void uart_phy_set_mode(void* user, iolink_phy_mode_t mode) LOG_DBG("set_mode(%d): no-op for plain UART PHY", mode); } +/** @brief Reconfigure the UART speed to match the requested IO-Link COM baudrate. */ static void uart_phy_set_baudrate(void* user, iolink_baudrate_t baudrate) { (void) user; @@ -149,6 +164,7 @@ static void uart_phy_set_baudrate(void* user, iolink_baudrate_t baudrate) } } +/** @brief Transmit a buffer via polled uart_poll_out(). */ static int uart_phy_send(void* user, const uint8_t* data, size_t len) { (void) user; @@ -163,6 +179,7 @@ static int uart_phy_send(void* user, const uint8_t* data, size_t len) return (int) len; } +/** @brief Receive one byte from the RX ring buffer, falling back to a polled read. */ static int uart_phy_recv_byte(void* user, uint8_t* byte) { (void) user; diff --git a/src/platform/zephyr/time_utils.c b/src/platform/zephyr/time_utils.c index fd5255f..ba99d09 100644 --- a/src/platform/zephyr/time_utils.c +++ b/src/platform/zephyr/time_utils.c @@ -6,6 +6,15 @@ * See LICENSE for details. */ +/** + * @file time_utils.c + * @brief Zephyr time utilities implementation (kernel uptime). + * @ingroup iolinki_time + * + * Provides the millisecond and microsecond time sources backed by the Zephyr + * kernel uptime. + */ + #include "iolinki/time_utils.h" #include diff --git a/src/platform_stubs.c b/src/platform_stubs.c index 7b35d01..c1dfd61 100644 --- a/src/platform_stubs.c +++ b/src/platform_stubs.c @@ -6,6 +6,15 @@ * See LICENSE for details. */ +/** + * @file platform_stubs.c + * @brief Test/stub weak platform NVM implementations. + * @ingroup iolinki_platform + * + * Weak NVM read/write stubs whose return values are driven by global test + * hooks, used when no real platform NVM port is linked. + */ + #include "iolinki/platform.h" /* Global variables for stubs to avoid static analysis "knownConditionTrueFalse"