Skip to content

Commit 5a49f7b

Browse files
committed
feat(isotp): enhance ISO-TP transport with callback support and thread safety features
1 parent a776f41 commit 5a49f7b

File tree

3 files changed

+302
-109
lines changed

3 files changed

+302
-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: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,40 @@
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 (commonly used
45+
* to identify which ISO-TP link triggered the callback)
46+
*/
47+
typedef void (*esp_isotp_rx_callback_t)(const uint8_t *data, uint32_t size, void *user_arg);
48+
49+
/**
50+
* @brief ISO-TP transmit callback function type
51+
*
52+
* Called when a complete message has been transmitted successfully.
53+
*
54+
* @note Execution context depends on message type:
55+
* - Single-frame: Called immediately from isotp_send() in caller's context
56+
* - Multi-frame: Called from isotp_poll() in task context
57+
* @note Keep callback execution time minimal to avoid affecting system performance.
58+
*
59+
* @param[in] tx_size Size of transmitted data in bytes
60+
* @param[in] user_arg User argument provided during configuration (commonly used
61+
* to identify which ISO-TP link triggered the callback)
62+
*/
63+
typedef void (*esp_isotp_tx_callback_t)(uint32_t tx_size, void *user_arg);
64+
3165
/**
3266
* @brief ISO-TP link handle
3367
*/
@@ -37,11 +71,15 @@ typedef struct esp_isotp_link_t *esp_isotp_handle_t;
3771
* @brief Configuration structure for creating a new ISO-TP link
3872
*/
3973
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) */
74+
uint32_t tx_id; /*!< TWAI ID for transmitting ISO-TP frames (11-bit or 29-bit, auto-detected from value) */
75+
uint32_t rx_id; /*!< TWAI ID for receiving ISO-TP frames (11-bit or 29-bit, auto-detected from value) */
4276
uint32_t tx_buffer_size; /*!< Size of the transmit buffer (max message size to send) */
4377
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 */
78+
uint32_t tx_frame_pool_size; /*!< Size of TX frame pool (0 for default: 8) */
79+
80+
esp_isotp_rx_callback_t rx_callback; /*!< Receive completion callback (NULL for polling mode) */
81+
esp_isotp_tx_callback_t tx_callback; /*!< Transmit completion callback (NULL to disable) */
82+
void *callback_arg; /*!< User argument passed to callbacks */
4583
} esp_isotp_config_t;
4684

4785
/**
@@ -63,11 +101,16 @@ typedef struct {
63101
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);
64102

65103
/**
66-
* @brief Send data over an ISO-TP link (non-blocking)
104+
* @brief Send data over an ISO-TP link (non-blocking, ISR-safe)
67105
*
68106
* Immediately sends first/single frame and returns. For multi-frame messages,
69107
* remaining frames are sent during subsequent esp_isotp_poll() calls.
70108
*
109+
* @note This function is ISR-safe and can be called from interrupt context.
110+
* @note TX completion callback timing:
111+
* - Single-frame: Called immediately from isotp_send()
112+
* - Multi-frame: Called from isotp_poll() when last frame is sent
113+
*
71114
* @param handle ISO-TP handle
72115
* @param data Data to send
73116
* @param size Data length in bytes
@@ -83,12 +126,17 @@ esp_err_t esp_isotp_new_transport(twai_node_handle_t twai_node, const esp_isotp_
83126
esp_err_t esp_isotp_send(esp_isotp_handle_t handle, const uint8_t *data, uint32_t size);
84127

85128
/**
86-
* @brief Send data over an ISO-TP link with specified TWAI ID (non-blocking)
129+
* @brief Send data over an ISO-TP link with specified TWAI ID (non-blocking, ISR-safe)
87130
*
88131
* Similar to esp_isotp_send(), but allows specifying a different TWAI ID for transmission.
89132
* This function is primarily used for functional addressing where multiple nodes
90133
* may respond to the same request.
91134
*
135+
* @note This function is ISR-safe and can be called from interrupt context.
136+
* @note TX completion callback timing:
137+
* - Single-frame: Called immediately from isotp_send_with_id()
138+
* - Multi-frame: Called from isotp_poll() when last frame is sent
139+
*
92140
* @param handle ISO-TP handle
93141
* @param id TWAI identifier to use for transmission (overrides configured tx_id)
94142
* @param data Data to send
@@ -99,19 +147,24 @@ esp_err_t esp_isotp_send(esp_isotp_handle_t handle, const uint8_t *data, uint32_
99147
* - ESP_ERR_NO_MEM: Data too large for buffer or no space available
100148
* - ESP_ERR_INVALID_SIZE: Invalid data size
101149
* - ESP_ERR_TIMEOUT: Send operation timed out
102-
* - ESP_ERR_INVALID_ARG: Invalid parameters
150+
* - ESP_ERR_INVALID_ARG: Invalid parameters or ID exceeds maximum value
103151
* - ESP_FAIL: Other send errors
104152
*/
105153
esp_err_t esp_isotp_send_with_id(esp_isotp_handle_t handle, uint32_t id, const uint8_t *data, uint32_t size);
106154

107155
/**
108-
* @brief Extract a complete received message (non-blocking)
156+
* @brief Extract a complete received message (non-blocking, task context only)
109157
*
110158
* This function only extracts data that has already been assembled by esp_isotp_poll().
111159
* It does NOT process incoming TWAI frames - that happens in esp_isotp_poll().
112160
*
113161
* Process: TWAI frames → esp_isotp_poll() assembles → esp_isotp_receive() extracts
114162
*
163+
* @warning This function is NOT ISR-safe and must only be called from task context.
164+
* @note When using callback mode (rx_callback != NULL), received messages are
165+
* automatically delivered via callback. This function should only be used
166+
* in polling mode (rx_callback == NULL).
167+
*
115168
* @param handle ISO-TP handle
116169
* @param data Buffer to store received data
117170
* @param size Buffer size in bytes
@@ -128,7 +181,7 @@ esp_err_t esp_isotp_send_with_id(esp_isotp_handle_t handle, uint32_t id, const u
128181
esp_err_t esp_isotp_receive(esp_isotp_handle_t handle, uint8_t *data, uint32_t size, uint32_t *received_size);
129182

130183
/**
131-
* @brief Poll the ISO-TP link to process messages (CRITICAL - call regularly!)
184+
* @brief Poll the ISO-TP link to process messages (CRITICAL - call regularly, task context only)
132185
*
133186
* This function drives the ISO-TP state machine. Call every 1-10ms for proper operation.
134187
*
@@ -137,9 +190,13 @@ esp_err_t esp_isotp_receive(esp_isotp_handle_t handle, uint8_t *data, uint32_t s
137190
* - Processes incoming TWAI frames and assembles complete messages
138191
* - Handles flow control and timeouts
139192
* - Updates internal state machine
193+
* - Triggers TX completion callbacks for multi-frame messages
140194
*
141195
* Without regular polling: multi-frame sends will stall and receives won't complete.
142196
*
197+
* @warning This function is NOT ISR-safe and must only be called from task context.
198+
* @note TX completion callbacks for multi-frame messages are triggered from this function.
199+
*
143200
* @param handle ISO-TP handle
144201
* @return
145202
* - ESP_OK: Processing successful

0 commit comments

Comments
 (0)