44 * SPDX-License-Identifier: Apache-2.0
55 */
66
7- #include <stdatomic.h>
8- #include <stdint.h>
9- #include "soc/soc_caps.h"
10- #include "soc/twai_periph.h"
11- #include "soc/io_mux_reg.h"
12- #include "hal/twai_hal.h"
13- #include "freertos/FreeRTOS.h"
14- #include "esp_check.h"
15- #include "esp_pm.h"
16- #include "esp_heap_caps.h"
17- #include "esp_intr_alloc.h"
18- #include "esp_clk_tree.h"
197#include "esp_twai.h"
208#include "esp_twai_onchip.h"
219#include "esp_private/twai_interface.h"
22- #include "esp_private/twai_priv.h"
23- #include "esp_private/gpio.h"
24- #include "esp_private/esp_gpio_reserve.h"
25- #include "esp_private/periph_ctrl.h"
26-
27- static const char * TAG = "twai" ;
28-
29- #ifdef CONFIG_TWAI_ISR_INTO_IRAM
30- #define TWAI_MALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
31- #else
32- #define TWAI_MALLOC_CAPS MALLOC_CAP_DEFAULT
33- #endif //CONFIG_TWAI_ISR_INTO_IRAM
10+ #include "esp_private/twai_utils.h"
11+ #include "twai_private.h"
3412
3513#if !SOC_RCC_IS_INDEPENDENT
3614#define TWAI_RCC_ATOMIC () PERIPH_RCC_ATOMIC()
@@ -203,10 +181,10 @@ static void _node_isr_main(void *arg)
203181 if (int_stat & (TWAIFD_LL_INTR_BUS_ERR | TWAIFD_LL_INTR_ARBI_LOST )) {
204182 uint32_t err_reason = twaifd_ll_get_err_reason_code (twai_ctx -> hal .dev );
205183 twai_error_event_data_t e_data = {0 };
206- e_data .err_type .arb_lost = !!(int_stat & TWAIFD_LL_INTR_ARBI_LOST );
207- e_data .err_type .bit_err = (err_reason == TWAIFD_LL_ERR_BIT_ERR );
208- e_data .err_type .form_err = (err_reason == TWAIFD_LL_ERR_FRM_ERR );
209- e_data .err_type .stuff_err = (err_reason == TWAIFD_LL_ERR_STUF_ERR );
184+ e_data .err_code .arb_lost = !!(int_stat & TWAIFD_LL_INTR_ARBI_LOST );
185+ e_data .err_code .bit_err = (err_reason == TWAIFD_LL_ERR_BIT_ERR );
186+ e_data .err_code .form_err = (err_reason == TWAIFD_LL_ERR_FRM_ERR );
187+ e_data .err_code .stuff_err = (err_reason == TWAIFD_LL_ERR_STUF_ERR );
210188
211189 twai_ctx -> history .bus_err_num ++ ;
212190 if (twai_ctx -> cbs .on_error ) {
@@ -233,7 +211,7 @@ static void _node_isr_main(void *arg)
233211 // only call tx_done_cb when tx without error, otherwise on_error_cb should triggered if it is registered
234212 if (twai_ctx -> cbs .on_tx_done && (int_stat & TWAIFD_LL_INTR_TX_DONE )) {
235213 twai_tx_done_event_data_t tx_ev = {
236- .done_trans_tx = ( twai_frame_t * ) twai_ctx -> p_curr_tx ,
214+ .done_tx_frame = twai_ctx -> p_curr_tx ,
237215 };
238216 do_yield |= twai_ctx -> cbs .on_tx_done (& twai_ctx -> api_base , & tx_ev , twai_ctx -> user_data );
239217 }
@@ -268,22 +246,31 @@ static void _node_isr_main(void *arg)
268246 }
269247}
270248
249+ static void _node_destroy (twai_onchip_ctx_t * twai_ctx )
250+ {
251+ if (twai_ctx -> pm_lock ) {
252+ esp_pm_lock_delete (twai_ctx -> pm_lock );
253+ }
254+ if (twai_ctx -> intr_hdl ) {
255+ esp_intr_free (twai_ctx -> intr_hdl );
256+ }
257+ if (twai_ctx -> tx_mount_queue ) {
258+ vQueueDeleteWithCaps (twai_ctx -> tx_mount_queue );
259+ }
260+ if (twai_ctx -> ctrlr_id != -1 ) {
261+ _ctrlr_release (twai_ctx -> ctrlr_id );
262+ }
263+ free (twai_ctx );
264+ }
265+
271266static esp_err_t _node_delete (twai_node_handle_t node )
272267{
273268 twai_onchip_ctx_t * twai_ctx = __containerof (node , twai_onchip_ctx_t , api_base );
274269 ESP_RETURN_ON_FALSE (atomic_load (& twai_ctx -> state ) == TWAI_ERROR_BUS_OFF , ESP_ERR_INVALID_STATE , TAG , "delete node must when node stopped" );
275270
276271 _node_release_io (twai_ctx );
277- _ctrlr_release (twai_ctx -> ctrlr_id );
278272 _twai_rcc_clock_ctrl (twai_ctx -> ctrlr_id , false);
279- #if CONFIG_PM_ENABLE
280- if (twai_ctx -> pm_lock ) {
281- ESP_RETURN_ON_ERROR (esp_pm_lock_delete (twai_ctx -> pm_lock ), TAG , "delete power manager failed" );
282- }
283- #endif //CONFIG_PM_ENABLE
284- esp_intr_free (twai_ctx -> intr_hdl );
285- vQueueDeleteWithCaps (twai_ctx -> tx_mount_queue );
286- free (twai_ctx );
273+ _node_destroy (twai_ctx );
287274 return ESP_OK ;
288275}
289276
@@ -339,16 +326,18 @@ static esp_err_t _node_set_bit_timing(twai_node_handle_t node, const twai_timing
339326 if (timing ) {
340327 twaifd_ll_set_nominal_bitrate (twai_ctx -> hal .dev , timing );
341328 if (timing -> ssp_offset ) {
342- ssp_offset = timing -> ssp_offset ;
329+ // the underlying hardware calculates the ssp in system clock cycles, not in quanta time
330+ ssp_offset = timing -> ssp_offset * timing -> brp ;
343331 }
344332 }
345333#if SOC_TWAI_SUPPORT_FD
346334 if (timing_fd ) {
347335 twai_ctx -> valid_fd_timing = true;
348336 twaifd_ll_set_fd_bitrate (twai_ctx -> hal .dev , timing_fd );
337+ // Note, the ssp_offset set for the data phase can override the nominal phase, because ssp is more necessary for a high bitrate communication
349338 if (timing_fd -> ssp_offset ) {
350- // prefer to config ssp by fd param
351- ssp_offset = timing_fd -> ssp_offset ;
339+ // the underlying hardware calculates the ssp in system clock cycles, not in quanta time
340+ ssp_offset = timing_fd -> ssp_offset * timing_fd -> brp ;
352341 }
353342 }
354343#endif
@@ -475,12 +464,10 @@ static esp_err_t _node_config_range_filter(twai_node_handle_t node, uint8_t filt
475464 ESP_RETURN_ON_FALSE (filter_id < SOC_TWAI_RANGE_FILTER_NUM , ESP_ERR_INVALID_ARG , TAG , "Invalid range filter id %d" , filter_id );
476465 ESP_RETURN_ON_FALSE (atomic_load (& twai_ctx -> state ) == TWAI_ERROR_BUS_OFF , ESP_ERR_INVALID_STATE , TAG , "config filter must when node stopped" );
477466
478- bool full_open = (range_cfg -> range_high == 0 ) && (range_cfg -> range_low == 0 );
479- bool full_close = (range_cfg -> range_high == UINT32_MAX ) && (range_cfg -> range_low == UINT32_MAX );
480- bool cc_ext = full_open || (!full_close && range_cfg -> is_ext && !range_cfg -> no_classic );
481- bool fd_ext = full_open || (!full_close && range_cfg -> is_ext && !range_cfg -> no_fd );
482- bool cc_std = full_open || (!full_close && !range_cfg -> is_ext && !range_cfg -> no_classic );
483- bool fd_std = full_open || (!full_close && !range_cfg -> is_ext && !range_cfg -> no_fd );
467+ bool cc_ext = range_cfg -> is_ext && !range_cfg -> no_classic ;
468+ bool fd_ext = range_cfg -> is_ext && !range_cfg -> no_fd ;
469+ bool cc_std = !range_cfg -> is_ext && !range_cfg -> no_classic ;
470+ bool fd_std = !range_cfg -> is_ext && !range_cfg -> no_fd ;
484471 twaifd_ll_filter_enable_basic_ext (twai_ctx -> hal .dev , filter_id , true, cc_ext );
485472 twaifd_ll_filter_enable_fd_ext (twai_ctx -> hal .dev , filter_id , true, fd_ext );
486473 twaifd_ll_filter_enable_basic_std (twai_ctx -> hal .dev , filter_id , true, cc_std );
@@ -575,21 +562,24 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
575562 // Allocate TWAI node object memory
576563 twai_onchip_ctx_t * node = heap_caps_calloc (1 , sizeof (twai_onchip_ctx_t ), TWAI_MALLOC_CAPS );
577564 ESP_RETURN_ON_FALSE (node , ESP_ERR_NO_MEM , TAG , "No mem" );
565+ node -> ctrlr_id = -1 ;
578566 // Acquire controller
579567 int ctrlr_id = _ctrlr_acquire (node );
580- ESP_GOTO_ON_FALSE (ctrlr_id != -1 , ESP_ERR_NOT_FOUND , ctrlr_err , TAG , "Controller not available" );
568+ ESP_GOTO_ON_FALSE (ctrlr_id != -1 , ESP_ERR_NOT_FOUND , err , TAG , "Controller not available" );
581569 node -> ctrlr_id = ctrlr_id ;
582570
583571 // state is in bus_off before enabled
584572 atomic_store (& node -> state , TWAI_ERROR_BUS_OFF );
585573 node -> tx_mount_queue = xQueueCreateWithCaps (node_config -> tx_queue_depth , sizeof (twai_frame_t * ), TWAI_MALLOC_CAPS );
586- ESP_GOTO_ON_FALSE (node -> tx_mount_queue , ESP_ERR_NO_MEM , create_err , TAG , "no_mem" );
587- uint32_t intr_flags = node_config -> intr_priority ? BIT (node_config -> intr_priority ) | ESP_INTR_FLAG_INTRDISABLED : ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_INTRDISABLED ;
588- #if CONFIG_TWAI_ISR_CACHE_SAFE
589- intr_flags |= ESP_INTR_FLAG_IRAM ;
590- #endif
574+ ESP_GOTO_ON_FALSE (node -> tx_mount_queue , ESP_ERR_NO_MEM , err , TAG , "no_mem" );
575+ uint32_t intr_flags = TWAI_INTR_ALLOC_FLAGS ;
576+ if (node_config -> intr_priority > 0 ) {
577+ intr_flags |= BIT (node_config -> intr_priority );
578+ } else {
579+ intr_flags |= ESP_INTR_FLAG_LOWMED ;
580+ }
591581 ESP_GOTO_ON_ERROR (esp_intr_alloc (twai_controller_periph_signals .controllers [ctrlr_id ].irq_id , intr_flags , _node_isr_main , (void * )node , & node -> intr_hdl ),
592- create_err , TAG , "Alloc interrupt failed" );
582+ err , TAG , "Alloc interrupt failed" );
593583
594584 // Enable bus clock and reset controller
595585 _twai_rcc_clock_ctrl (ctrlr_id , true);
@@ -599,20 +589,20 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
599589 .intr_mask = DRIVER_DEFAULT_INTERRUPTS ,
600590 .enable_listen_only = node_config -> flags .enable_listen_only ,
601591 };
602- ESP_GOTO_ON_FALSE (twai_hal_init (& node -> hal , & hal_config ), ESP_ERR_INVALID_STATE , config_err , TAG , "hardware not in reset state" );
592+ ESP_GOTO_ON_FALSE (twai_hal_init (& node -> hal , & hal_config ), ESP_ERR_INVALID_STATE , err , TAG , "hardware not in reset state" );
603593 twaifd_ll_set_mode (node -> hal .dev , node_config -> flags .enable_listen_only , node_config -> flags .enable_self_test , node_config -> flags .enable_loopback );
604594 twaifd_ll_set_tx_retrans_limit (node -> hal .dev , node_config -> fail_retry_cnt );
605595 twaifd_ll_filter_block_rtr (node -> hal .dev , node_config -> flags .no_receive_rtr );
606596 twaifd_ll_enable_filter_mode (node -> hal .dev , true); // each filter still has independent enable control
607597 twaifd_ll_enable_fd_mode (node -> hal .dev , true); // fd frame still controlled by `header.fdf`
608598
609599 // Configure bus timing
610- ESP_GOTO_ON_ERROR (_node_calc_set_bit_timing (& node -> api_base , node_config -> clk_src , & node_config -> bit_timing , & node_config -> data_timing ), config_err , TAG , "bitrate error" );
600+ ESP_GOTO_ON_ERROR (_node_calc_set_bit_timing (& node -> api_base , node_config -> clk_src , & node_config -> bit_timing , & node_config -> data_timing ), err , TAG , "bitrate error" );
611601
612602 // Configure GPIO
613- ESP_GOTO_ON_ERROR (_node_config_io (node , node_config ), config_err , TAG , "gpio config failed" );
603+ ESP_GOTO_ON_ERROR (_node_config_io (node , node_config ), err , TAG , "gpio config failed" );
614604#if CONFIG_PM_ENABLE
615- ESP_GOTO_ON_ERROR (esp_pm_lock_create (ESP_PM_NO_LIGHT_SLEEP , 0 , twai_controller_periph_signals .controllers [ctrlr_id ].module_name , & node -> pm_lock ), config_err , TAG , "init power manager failed" );
605+ ESP_GOTO_ON_ERROR (esp_pm_lock_create (ESP_PM_NO_LIGHT_SLEEP , 0 , twai_controller_periph_signals .controllers [ctrlr_id ].module_name , & node -> pm_lock ), err , TAG , "init power manager failed" );
616606#endif //CONFIG_PM_ENABLE
617607
618608 node -> api_base .enable = _node_enable ;
@@ -621,7 +611,7 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
621611 node -> api_base .recover = _node_recover ;
622612 node -> api_base .config_mask_filter = _node_config_mask_filter ;
623613 node -> api_base .config_range_filter = _node_config_range_filter ;
624- node -> api_base .timing_reconfig = _node_set_bit_timing ;
614+ node -> api_base .reconfig_timing = _node_set_bit_timing ;
625615 node -> api_base .register_cbs = _node_register_callbacks ;
626616 node -> api_base .transmit = _node_queue_tx ;
627617 node -> api_base .receive_isr = _node_parse_rx ;
@@ -630,16 +620,9 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
630620 * node_ret = & node -> api_base ;
631621 return ESP_OK ;
632622
633- config_err :
634- if (node -> intr_hdl ) {
635- esp_intr_free (node -> intr_hdl );
636- }
637- if (node -> tx_mount_queue ) {
638- vQueueDeleteWithCaps (node -> tx_mount_queue );
623+ err :
624+ if (node ) {
625+ _node_destroy (node );
639626 }
640- create_err :
641- _ctrlr_release (ctrlr_id );
642- ctrlr_err :
643- free (node );
644627 return ret ;
645628}
0 commit comments