Skip to content

Commit 2eccc39

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

File tree

3 files changed

+294
-109
lines changed

3 files changed

+294
-109
lines changed

esp_isotp/README.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,12 @@ void app_main(void) {
5454
twai_node_handle_t twai_node;
5555
ESP_ERROR_CHECK(twai_new_node_onchip(&twai_cfg, &twai_node));
5656

57-
// 2) Create ISO-TP (11-bit IDs)
57+
// 2) Create ISO-TP (11-bit IDs, auto-detected)
5858
esp_isotp_config_t config = {
59-
.tx_id = 0x7E0, // request ID
60-
.rx_id = 0x7E8, // response ID
59+
.tx_id = 0x7E0, // request ID (11-bit, auto-detected)
60+
.rx_id = 0x7E8, // response ID (11-bit, auto-detected)
6161
.tx_buffer_size = 4096,
6262
.rx_buffer_size = 4096,
63-
.use_extended_id = false, // Use 11-bit standard IDs
6463
};
6564
esp_isotp_handle_t isotp_handle;
6665
ESP_ERROR_CHECK(esp_isotp_new_transport(twai_node, &config, &isotp_handle));
@@ -87,16 +86,15 @@ void app_main(void) {
8786
8887
## Extended (29-bit) IDs
8988
90-
- Set `use_extended_id = true`; use IDs ≤ 0x1FFFFFFF.
91-
- `tx_id` and `rx_id` must differ and match peer IDE.
89+
- ID format is auto-detected: IDs > 0x7FF use 29-bit extended format, others use 11-bit standard format.
90+
- `tx_id` and `rx_id` must differ and match peer's expected format.
9291
9392
```c
9493
esp_isotp_config_t cfg = {
95-
.tx_id = 0x18DAF110,
96-
.rx_id = 0x18DA10F1,
94+
.tx_id = 0x18DAF110, // 29-bit ID (auto-detected as extended)
95+
.rx_id = 0x18DA10F1, // 29-bit ID (auto-detected as extended)
9796
.tx_buffer_size = 4096,
9897
.rx_buffer_size = 4096,
99-
.use_extended_id = true, // Set to true for 29-bit IDs
10098
};
10199
```
102100

esp_isotp/inc/esp_isotp.h

Lines changed: 64 additions & 9 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
*/
@@ -37,11 +69,15 @@ typedef struct esp_isotp_link_t *esp_isotp_handle_t;
3769
* @brief Configuration structure for creating a new ISO-TP link
3870
*/
3971
typedef struct {
40-
uint32_t tx_id; /*!< TWAI ID for transmitting ISO-TP frames (11-bit or 29-bit) */
41-
uint32_t rx_id; /*!< TWAI ID for receiving ISO-TP frames (11-bit or 29-bit) */
72+
uint32_t tx_id; /*!< TWAI ID for transmitting ISO-TP frames (11-bit or 29-bit, auto-detected from value) */
73+
uint32_t rx_id; /*!< TWAI ID for receiving ISO-TP frames (11-bit or 29-bit, auto-detected from value) */
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) */
44-
bool use_extended_id; /*!< true: use 29-bit extended ID, false: use 11-bit standard ID */
76+
uint32_t tx_frame_pool_size; /*!< Size of TX frame pool (0 for default: 8) */
77+
78+
esp_isotp_rx_callback_t rx_callback; /*!< Receive completion callback (NULL for polling mode) */
79+
esp_isotp_tx_callback_t tx_callback; /*!< Transmit completion callback (NULL to disable) */
80+
void *callback_arg; /*!< User argument passed to callbacks */
4581
} esp_isotp_config_t;
4682

4783
/**
@@ -63,11 +99,16 @@ typedef struct {
6399
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);
64100

65101
/**
66-
* @brief Send data over an ISO-TP link (non-blocking)
102+
* @brief Send data over an ISO-TP link (non-blocking, ISR-safe)
67103
*
68104
* Immediately sends first/single frame and returns. For multi-frame messages,
69105
* remaining frames are sent during subsequent esp_isotp_poll() calls.
70106
*
107+
* @note This function is ISR-safe and can be called from interrupt context.
108+
* @note TX completion callback timing:
109+
* - Single-frame: Called immediately from isotp_send()
110+
* - Multi-frame: Called from isotp_poll() when last frame is sent
111+
*
71112
* @param handle ISO-TP handle
72113
* @param data Data to send
73114
* @param size Data length in bytes
@@ -83,12 +124,17 @@ esp_err_t esp_isotp_new_transport(twai_node_handle_t twai_node, const esp_isotp_
83124
esp_err_t esp_isotp_send(esp_isotp_handle_t handle, const uint8_t *data, uint32_t size);
84125

85126
/**
86-
* @brief Send data over an ISO-TP link with specified TWAI ID (non-blocking)
127+
* @brief Send data over an ISO-TP link with specified TWAI ID (non-blocking, ISR-safe)
87128
*
88129
* Similar to esp_isotp_send(), but allows specifying a different TWAI ID for transmission.
89130
* This function is primarily used for functional addressing where multiple nodes
90131
* may respond to the same request.
91132
*
133+
* @note This function is ISR-safe and can be called from interrupt context.
134+
* @note TX completion callback timing:
135+
* - Single-frame: Called immediately from isotp_send_with_id()
136+
* - Multi-frame: Called from isotp_poll() when last frame is sent
137+
*
92138
* @param handle ISO-TP handle
93139
* @param id TWAI identifier to use for transmission (overrides configured tx_id)
94140
* @param data Data to send
@@ -99,19 +145,24 @@ esp_err_t esp_isotp_send(esp_isotp_handle_t handle, const uint8_t *data, uint32_
99145
* - ESP_ERR_NO_MEM: Data too large for buffer or no space available
100146
* - ESP_ERR_INVALID_SIZE: Invalid data size
101147
* - ESP_ERR_TIMEOUT: Send operation timed out
102-
* - ESP_ERR_INVALID_ARG: Invalid parameters
148+
* - ESP_ERR_INVALID_ARG: Invalid parameters or ID exceeds maximum value
103149
* - ESP_FAIL: Other send errors
104150
*/
105151
esp_err_t esp_isotp_send_with_id(esp_isotp_handle_t handle, uint32_t id, const uint8_t *data, uint32_t size);
106152

107153
/**
108-
* @brief Extract a complete received message (non-blocking)
154+
* @brief Extract a complete received message (non-blocking, task context only)
109155
*
110156
* This function only extracts data that has already been assembled by esp_isotp_poll().
111157
* It does NOT process incoming TWAI frames - that happens in esp_isotp_poll().
112158
*
113159
* Process: TWAI frames → esp_isotp_poll() assembles → esp_isotp_receive() extracts
114160
*
161+
* @warning This function is NOT ISR-safe and must only be called from task context.
162+
* @note When using callback mode (rx_callback != NULL), received messages are
163+
* automatically delivered via callback. This function should only be used
164+
* in polling mode (rx_callback == NULL).
165+
*
115166
* @param handle ISO-TP handle
116167
* @param data Buffer to store received data
117168
* @param size Buffer size in bytes
@@ -125,10 +176,10 @@ esp_err_t esp_isotp_send_with_id(esp_isotp_handle_t handle, uint32_t id, const u
125176
* - ESP_ERR_INVALID_ARG: Invalid parameters
126177
* - ESP_FAIL: Other receive errors
127178
*/
128-
esp_err_t esp_isotp_receive(esp_isotp_handle_t handle, uint8_t *data, uint32_t size, uint32_t *received_size);
179+
esp_err_t esp_isotp_receive(esp_isotp_handle_t handle, uint8_t *data, const uint32_t size, uint32_t *received_size);
129180

130181
/**
131-
* @brief Poll the ISO-TP link to process messages (CRITICAL - call regularly!)
182+
* @brief Poll the ISO-TP link to process messages (CRITICAL - call regularly, task context only)
132183
*
133184
* This function drives the ISO-TP state machine. Call every 1-10ms for proper operation.
134185
*
@@ -137,9 +188,13 @@ esp_err_t esp_isotp_receive(esp_isotp_handle_t handle, uint8_t *data, uint32_t s
137188
* - Processes incoming TWAI frames and assembles complete messages
138189
* - Handles flow control and timeouts
139190
* - Updates internal state machine
191+
* - Triggers TX completion callbacks for multi-frame messages
140192
*
141193
* Without regular polling: multi-frame sends will stall and receives won't complete.
142194
*
195+
* @warning This function is NOT ISR-safe and must only be called from task context.
196+
* @note TX completion callbacks for multi-frame messages are triggered from this function.
197+
*
143198
* @param handle ISO-TP handle
144199
* @return
145200
* - ESP_OK: Processing successful

0 commit comments

Comments
 (0)