66
77#include "esp_twai.h"
88#include "esp_twai_onchip.h"
9+ #include "soc/gpio_sig_map.h"
910#include "esp_private/twai_interface.h"
1011#include "esp_private/twai_utils.h"
1112#include "twai_private.h"
@@ -127,27 +128,25 @@ static esp_err_t _node_config_io(twai_onchip_ctx_t *node, const twai_onchip_node
127128 uint64_t reserve_mask = BIT64 (node_config -> io_cfg .tx );
128129
129130 // Set RX pin
130- gpio_input_enable (node_config -> io_cfg .rx );
131131 gpio_set_pull_mode (node_config -> io_cfg .rx , GPIO_PULLUP_ONLY ); // pullup to avoid noise if no connection to transceiver
132- gpio_func_sel (node_config -> io_cfg .rx , PIN_FUNC_GPIO );
133- esp_rom_gpio_connect_in_signal (node_config -> io_cfg .rx , twai_controller_periph_signals .controllers [node -> ctrlr_id ].rx_sig , false);
132+ gpio_matrix_input (node_config -> io_cfg .rx , twai_periph_signals [node -> ctrlr_id ].rx_sig , false);
134133
135134 // Set TX pin
136- gpio_func_sel (node_config -> io_cfg .tx , PIN_FUNC_GPIO );
137- esp_rom_gpio_connect_out_signal (node_config -> io_cfg .tx , twai_controller_periph_signals .controllers [node -> ctrlr_id ].tx_sig , false, false);
135+ // If enable_listen_only, disconnect twai signal, and output high to avoid any influence to bus
136+ gpio_set_level (node_config -> io_cfg .tx , 1 );
137+ int tx_sig = (node_config -> flags .enable_listen_only ) ? SIG_GPIO_OUT_IDX : twai_periph_signals [node -> ctrlr_id ].tx_sig ;
138+ gpio_matrix_output (node_config -> io_cfg .tx , tx_sig , false, false);
138139
139140 //Configure output clock pin (Optional)
140141 if (GPIO_IS_VALID_OUTPUT_GPIO (node_config -> io_cfg .quanta_clk_out )) {
141142 reserve_mask |= BIT64 (node_config -> io_cfg .quanta_clk_out );
142- gpio_func_sel (node_config -> io_cfg .quanta_clk_out , PIN_FUNC_GPIO );
143- esp_rom_gpio_connect_out_signal (node_config -> io_cfg .quanta_clk_out , twai_controller_periph_signals .controllers [node -> ctrlr_id ].clk_out_sig , false, false);
143+ gpio_matrix_output (node_config -> io_cfg .quanta_clk_out , twai_periph_signals [node -> ctrlr_id ].clk_out_sig , false, false);
144144 }
145145
146146 //Configure bus status pin (Optional)
147147 if (GPIO_IS_VALID_OUTPUT_GPIO (node_config -> io_cfg .bus_off_indicator )) {
148148 reserve_mask |= BIT64 (node_config -> io_cfg .bus_off_indicator );
149- gpio_func_sel (node_config -> io_cfg .bus_off_indicator , PIN_FUNC_GPIO );
150- esp_rom_gpio_connect_out_signal (node_config -> io_cfg .bus_off_indicator , twai_controller_periph_signals .controllers [node -> ctrlr_id ].bus_off_sig , false, false);
149+ gpio_matrix_output (node_config -> io_cfg .bus_off_indicator , twai_periph_signals [node -> ctrlr_id ].bus_off_sig , false, false);
151150 }
152151
153152 node -> gpio_reserved = reserve_mask ;
@@ -163,7 +162,7 @@ static esp_err_t _node_config_io(twai_onchip_ctx_t *node, const twai_onchip_node
163162
164163static void _node_release_io (twai_onchip_ctx_t * node )
165164{
166- esp_rom_gpio_connect_in_signal (GPIO_MATRIX_CONST_ONE_INPUT , twai_controller_periph_signals . controllers [node -> ctrlr_id ].rx_sig , false);
165+ esp_rom_gpio_connect_in_signal (GPIO_MATRIX_CONST_ONE_INPUT , twai_periph_signals [node -> ctrlr_id ].rx_sig , false);
167166 esp_gpio_revoke (node -> gpio_reserved );
168167 for (; node -> gpio_reserved > 0 ;) {
169168 uint8_t pos = __builtin_ctzll (node -> gpio_reserved );
@@ -321,6 +320,8 @@ static esp_err_t _node_delete(twai_node_handle_t node)
321320 _node_release_io (twai_ctx );
322321 twai_hal_deinit (twai_ctx -> hal );
323322 _twai_rcc_clock_ctrl (twai_ctx -> ctrlr_id , false);
323+ // curr_clk_src must not NULL as we already set to Default in twai_new_node_onchip
324+ ESP_RETURN_ON_ERROR (esp_clk_tree_enable_src (twai_ctx -> curr_clk_src , false), TAG , "disable clock source failed" );
324325 _node_destroy (twai_ctx );
325326 return ESP_OK ;
326327}
@@ -353,6 +354,30 @@ static esp_err_t _node_check_timing_valid(twai_onchip_ctx_t *twai_ctx, const twa
353354 return ESP_OK ;
354355}
355356
357+ static esp_err_t _node_set_clock_source (twai_node_handle_t node , twai_clock_source_t clock_src )
358+ {
359+ twai_onchip_ctx_t * twai_ctx = __containerof (node , twai_onchip_ctx_t , api_base );
360+ if (clock_src != twai_ctx -> curr_clk_src ) {
361+ // Order of operations is important here.
362+ // First enable and switch to the new clock source, then disable the old one.
363+ // To ensure the clock to controller is continuous.
364+ ESP_RETURN_ON_ERROR (esp_clk_tree_enable_src (clock_src , true), TAG , "enable clock source failed" );
365+ _twai_rcc_clock_sel (twai_ctx -> ctrlr_id , clock_src );
366+ if (twai_ctx -> curr_clk_src ) {
367+ // Disable previous clock source
368+ esp_err_t err = esp_clk_tree_enable_src (twai_ctx -> curr_clk_src , false);
369+ if (err != ESP_OK ) {
370+ ESP_LOGE (TAG , "disable previous clock source failed, err: %d" , err );
371+ esp_clk_tree_enable_src (clock_src , false);
372+ return err ;
373+ }
374+ }
375+ twai_ctx -> curr_clk_src = clock_src ;
376+ ESP_LOGD (TAG , "set clock source to %d" , clock_src );
377+ }
378+ return ESP_OK ;
379+ }
380+
356381static esp_err_t _node_set_bit_timing (twai_node_handle_t node , const twai_timing_advanced_config_t * timing , const twai_timing_advanced_config_t * timing_fd )
357382{
358383 twai_onchip_ctx_t * twai_ctx = __containerof (node , twai_onchip_ctx_t , api_base );
@@ -384,13 +409,7 @@ static esp_err_t _node_set_bit_timing(twai_node_handle_t node, const twai_timing
384409 }
385410#endif
386411
387- if (new_clock_src != twai_ctx -> curr_clk_src ) {
388- // TODO: IDF-13144
389- ESP_ERROR_CHECK (esp_clk_tree_enable_src ((soc_module_clk_t )(new_clock_src ), true));
390- twai_ctx -> curr_clk_src = new_clock_src ;
391- _twai_rcc_clock_sel (twai_ctx -> ctrlr_id , new_clock_src );
392- }
393- return ESP_OK ;
412+ return _node_set_clock_source (node , new_clock_src );
394413}
395414
396415static esp_err_t _node_calc_set_bit_timing (twai_node_handle_t node , twai_clock_source_t clk_src , const twai_timing_basic_config_t * timing , const twai_timing_basic_config_t * timing_fd )
@@ -615,9 +634,11 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
615634 ESP_GOTO_ON_FALSE (node -> tx_mount_queue , ESP_ERR_NO_MEM , err , TAG , "no_mem" );
616635 uint32_t intr_flags = TWAI_INTR_ALLOC_FLAGS ;
617636 intr_flags |= (node_config -> intr_priority > 0 ) ? BIT (node_config -> intr_priority ) : ESP_INTR_FLAG_LOWMED ;
618- 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 ),
637+ ESP_GOTO_ON_ERROR (esp_intr_alloc (twai_periph_signals [ctrlr_id ].irq_id , intr_flags , _node_isr_main , (void * )node , & node -> intr_hdl ),
619638 err , TAG , "Alloc interrupt failed" );
620639
640+ // Set default clock source first
641+ ESP_RETURN_ON_ERROR (_node_set_clock_source (& node -> api_base , TWAI_CLK_SRC_DEFAULT ), TAG , "enable default clock source failed" );
621642 // Enable bus clock and reset controller
622643 _twai_rcc_clock_ctrl (ctrlr_id , true);
623644 // Initialize HAL and configure register defaults.
@@ -638,10 +659,10 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
638659#if CONFIG_PM_ENABLE
639660#if SOC_TWAI_CLK_SUPPORT_APB
640661 // DFS can change APB frequency. So add lock to prevent sleep and APB freq from changing
641- ESP_GOTO_ON_ERROR (esp_pm_lock_create (ESP_PM_APB_FREQ_MAX , 0 , twai_controller_periph_signals . controllers [ctrlr_id ].module_name , & node -> pm_lock ), err , TAG , "init power manager failed" );
662+ ESP_GOTO_ON_ERROR (esp_pm_lock_create (ESP_PM_APB_FREQ_MAX , 0 , twai_periph_signals [ctrlr_id ].module_name , & node -> pm_lock ), err , TAG , "init power manager failed" );
642663#else // XTAL
643664 // XTAL freq can be closed in light sleep, so we need to create a lock to prevent light sleep
644- 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" );
665+ ESP_GOTO_ON_ERROR (esp_pm_lock_create (ESP_PM_NO_LIGHT_SLEEP , 0 , twai_periph_signals [ctrlr_id ].module_name , & node -> pm_lock ), err , TAG , "init power manager failed" );
645666#endif //SOC_TWAI_CLK_SUPPORT_APB
646667#endif //CONFIG_PM_ENABLE
647668
0 commit comments