Skip to content

Commit abf8778

Browse files
committed
feat(isotp): enhance ISO-TP transport with callback support and thread safety features
1 parent 0c24950 commit abf8778

File tree

2 files changed

+256
-83
lines changed

2 files changed

+256
-83
lines changed

esp_isotp/inc/esp_isotp.h

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,38 @@
2828
extern "C" {
2929
#endif
3030

31+
/**
32+
* @brief ISO-TP receive callback function type
33+
*
34+
* Called when a complete message has been received successfully.
35+
*
36+
* @warning This callback executes in the same context as isotp_on_can_message(),
37+
* which is typically ISR context. Keep callback execution time minimal
38+
* and avoid blocking operations.
39+
* @note The data pointer is only valid during the callback execution.
40+
* Copy data immediately if needed beyond the callback scope.
41+
*
42+
* @param[in] data Pointer to received data (valid only during callback)
43+
* @param[in] size Size of received data in bytes
44+
* @param[in] user_arg User argument provided during configuration
45+
*/
46+
typedef void (*esp_isotp_rx_callback_t)(const uint8_t *data, uint32_t size, void *user_arg);
47+
48+
/**
49+
* @brief ISO-TP transmit callback function type
50+
*
51+
* Called when a complete message has been transmitted successfully.
52+
*
53+
* @note Execution context depends on message type:
54+
* - Single-frame: Called immediately from isotp_send() in caller's context
55+
* - Multi-frame: Called from isotp_poll() in task context
56+
* @note Keep callback execution time minimal to avoid affecting system performance.
57+
*
58+
* @param[in] tx_size Size of transmitted data in bytes
59+
* @param[in] user_arg User argument provided during configuration
60+
*/
61+
typedef void (*esp_isotp_tx_callback_t)(uint32_t tx_size, void *user_arg);
62+
3163
/**
3264
* @brief ISO-TP link handle
3365
*/
@@ -41,7 +73,12 @@ typedef struct {
4173
uint32_t rx_id; /*!< TWAI ID for receiving ISO-TP frames (11-bit or 29-bit) */
4274
uint32_t tx_buffer_size; /*!< Size of the transmit buffer (max message size to send) */
4375
uint32_t rx_buffer_size; /*!< Size of the receive buffer (max message size to receive) */
76+
uint32_t tx_frame_pool_size; /*!< Size of TX frame pool (0 for default: 8) */
4477
bool use_extended_id; /*!< true: use 29-bit extended ID, false: use 11-bit standard ID */
78+
79+
esp_isotp_rx_callback_t rx_callback; /*!< Receive completion callback (NULL for polling mode) */
80+
esp_isotp_tx_callback_t tx_callback; /*!< Transmit completion callback (NULL to disable) */
81+
void *callback_arg; /*!< User argument passed to callbacks */
4582
} esp_isotp_config_t;
4683

4784
/**
@@ -63,11 +100,16 @@ typedef struct {
63100
esp_err_t esp_isotp_new_transport(twai_node_handle_t twai_node, const esp_isotp_config_t *config, esp_isotp_handle_t *out_handle);
64101

65102
/**
66-
* @brief Send data over an ISO-TP link (non-blocking)
103+
* @brief Send data over an ISO-TP link (non-blocking, ISR-safe)
67104
*
68105
* Immediately sends first/single frame and returns. For multi-frame messages,
69106
* remaining frames are sent during subsequent esp_isotp_poll() calls.
70107
*
108+
* @note This function is ISR-safe and can be called from interrupt context.
109+
* @note TX completion callback timing:
110+
* - Single-frame: Called immediately from isotp_send()
111+
* - Multi-frame: Called from isotp_poll() when last frame is sent
112+
*
71113
* @param handle ISO-TP handle
72114
* @param data Data to send
73115
* @param size Data length in bytes
@@ -83,12 +125,17 @@ esp_err_t esp_isotp_new_transport(twai_node_handle_t twai_node, const esp_isotp_
83125
esp_err_t esp_isotp_send(esp_isotp_handle_t handle, const uint8_t *data, uint32_t size);
84126

85127
/**
86-
* @brief Send data over an ISO-TP link with specified TWAI ID (non-blocking)
128+
* @brief Send data over an ISO-TP link with specified TWAI ID (non-blocking, ISR-safe)
87129
*
88130
* Similar to esp_isotp_send(), but allows specifying a different TWAI ID for transmission.
89131
* This function is primarily used for functional addressing where multiple nodes
90132
* may respond to the same request.
91133
*
134+
* @note This function is ISR-safe and can be called from interrupt context.
135+
* @note TX completion callback timing:
136+
* - Single-frame: Called immediately from isotp_send_with_id()
137+
* - Multi-frame: Called from isotp_poll() when last frame is sent
138+
*
92139
* @param handle ISO-TP handle
93140
* @param id TWAI identifier to use for transmission (overrides configured tx_id)
94141
* @param data Data to send
@@ -99,19 +146,24 @@ esp_err_t esp_isotp_send(esp_isotp_handle_t handle, const uint8_t *data, uint32_
99146
* - ESP_ERR_NO_MEM: Data too large for buffer or no space available
100147
* - ESP_ERR_INVALID_SIZE: Invalid data size
101148
* - ESP_ERR_TIMEOUT: Send operation timed out
102-
* - ESP_ERR_INVALID_ARG: Invalid parameters
149+
* - ESP_ERR_INVALID_ARG: Invalid parameters or ID exceeds format mask
103150
* - ESP_FAIL: Other send errors
104151
*/
105152
esp_err_t esp_isotp_send_with_id(esp_isotp_handle_t handle, uint32_t id, const uint8_t *data, uint32_t size);
106153

107154
/**
108-
* @brief Extract a complete received message (non-blocking)
155+
* @brief Extract a complete received message (non-blocking, task context only)
109156
*
110157
* This function only extracts data that has already been assembled by esp_isotp_poll().
111158
* It does NOT process incoming TWAI frames - that happens in esp_isotp_poll().
112159
*
113160
* Process: TWAI frames → esp_isotp_poll() assembles → esp_isotp_receive() extracts
114161
*
162+
* @warning This function is NOT ISR-safe and must only be called from task context.
163+
* @note When using callback mode (rx_callback != NULL), received messages are
164+
* automatically delivered via callback. This function should only be used
165+
* in polling mode (rx_callback == NULL).
166+
*
115167
* @param handle ISO-TP handle
116168
* @param data Buffer to store received data
117169
* @param size Buffer size in bytes
@@ -125,10 +177,10 @@ esp_err_t esp_isotp_send_with_id(esp_isotp_handle_t handle, uint32_t id, const u
125177
* - ESP_ERR_INVALID_ARG: Invalid parameters
126178
* - ESP_FAIL: Other receive errors
127179
*/
128-
esp_err_t esp_isotp_receive(esp_isotp_handle_t handle, uint8_t *data, uint32_t size, uint32_t *received_size);
180+
esp_err_t esp_isotp_receive(esp_isotp_handle_t handle, uint8_t *data, const uint32_t size, uint32_t *received_size);
129181

130182
/**
131-
* @brief Poll the ISO-TP link to process messages (CRITICAL - call regularly!)
183+
* @brief Poll the ISO-TP link to process messages (CRITICAL - call regularly, task context only)
132184
*
133185
* This function drives the ISO-TP state machine. Call every 1-10ms for proper operation.
134186
*
@@ -137,9 +189,13 @@ esp_err_t esp_isotp_receive(esp_isotp_handle_t handle, uint8_t *data, uint32_t s
137189
* - Processes incoming TWAI frames and assembles complete messages
138190
* - Handles flow control and timeouts
139191
* - Updates internal state machine
192+
* - Triggers TX completion callbacks for multi-frame messages
140193
*
141194
* Without regular polling: multi-frame sends will stall and receives won't complete.
142195
*
196+
* @warning This function is NOT ISR-safe and must only be called from task context.
197+
* @note TX completion callbacks for multi-frame messages are triggered from this function.
198+
*
143199
* @param handle ISO-TP handle
144200
* @return
145201
* - ESP_OK: Processing successful

0 commit comments

Comments
 (0)