1515#include "esp_intr_alloc.h"
1616#include "esp_pm.h"
1717#include "esp_attr.h"
18+ #include "esp_check.h"
1819#include "esp_heap_caps.h"
1920#include "esp_clk_tree.h"
2021#include "clk_ctrl_os.h"
2829#include "soc/io_mux_reg.h"
2930#include "soc/twai_periph.h"
3031#include "hal/twai_hal.h"
32+ #include "hal/twai_ll.h"
3133#include "esp_rom_gpio.h"
3234#if SOC_TWAI_SUPPORT_SLEEP_RETENTION
3335#include "esp_private/sleep_retention.h"
@@ -79,7 +81,7 @@ typedef struct twai_obj_t {
7981 gpio_num_t rx_io ;
8082 gpio_num_t clkout_io ;
8183 gpio_num_t bus_off_io ;
82- twai_hal_context_t hal ; // hal context
84+ twai_hal_context_t * hal ; // hal context
8385 //Control and status members
8486 twai_state_t state ;
8587 twai_mode_t mode ;
@@ -136,11 +138,11 @@ static void twai_alert_handler(twai_obj_t *p_twai_obj, uint32_t alert_code, int
136138static inline void twai_handle_rx_buffer_frames (twai_obj_t * p_twai_obj , BaseType_t * task_woken , int * alert_req )
137139{
138140#ifdef SOC_TWAI_SUPPORTS_RX_STATUS
139- uint32_t msg_count = twai_hal_get_rx_msg_count (& p_twai_obj -> hal );
141+ uint32_t msg_count = twai_hal_get_rx_msg_count (p_twai_obj -> hal );
140142
141143 for (uint32_t i = 0 ; i < msg_count ; i ++ ) {
142144 twai_hal_frame_t frame ;
143- if (twai_hal_read_rx_buffer_and_clear ( & p_twai_obj -> hal , & frame )) {
145+ if (twai_hal_read_rx_fifo ( p_twai_obj -> hal , & frame )) {
144146 //Valid frame copied from RX buffer
145147 if (xQueueSendFromISR (p_twai_obj -> rx_queue , & frame , task_woken ) == pdTRUE ) {
146148 p_twai_obj -> rx_msg_count ++ ;
@@ -155,12 +157,12 @@ static inline void twai_handle_rx_buffer_frames(twai_obj_t *p_twai_obj, BaseType
155157 }
156158 }
157159#else //SOC_TWAI_SUPPORTS_RX_STATUS
158- uint32_t msg_count = twai_hal_get_rx_msg_count (& p_twai_obj -> hal );
160+ uint32_t msg_count = twai_hal_get_rx_msg_count (p_twai_obj -> hal );
159161 bool overrun = false;
160162 //Clear all valid RX frames
161163 for (int i = 0 ; i < msg_count ; i ++ ) {
162164 twai_hal_frame_t frame ;
163- if (twai_hal_read_rx_buffer_and_clear ( & p_twai_obj -> hal , & frame )) {
165+ if (twai_hal_read_rx_fifo ( p_twai_obj -> hal , & frame )) {
164166 //Valid frame copied from RX buffer
165167 if (xQueueSendFromISR (p_twai_obj -> rx_queue , & frame , task_woken ) == pdTRUE ) {
166168 p_twai_obj -> rx_msg_count ++ ;
@@ -176,16 +178,16 @@ static inline void twai_handle_rx_buffer_frames(twai_obj_t *p_twai_obj, BaseType
176178 }
177179 //All remaining frames are treated as overrun. Clear them all
178180 if (overrun ) {
179- p_twai_obj -> rx_overrun_count += twai_hal_clear_rx_fifo_overrun (& p_twai_obj -> hal );
181+ p_twai_obj -> rx_overrun_count += twai_hal_clear_rx_fifo_overrun (p_twai_obj -> hal );
180182 twai_alert_handler (p_twai_obj , TWAI_ALERT_RX_FIFO_OVERRUN , alert_req );
181183 }
182184#endif //SOC_TWAI_SUPPORTS_RX_STATUS
183185}
184186
185- static inline void twai_handle_tx_buffer_frame (twai_obj_t * p_twai_obj , BaseType_t * task_woken , int * alert_req )
187+ static inline void twai_handle_tx_buffer_frame (twai_obj_t * p_twai_obj , bool tx_success , BaseType_t * task_woken , int * alert_req )
186188{
187189 //Handle previously transmitted frame
188- if (twai_hal_check_last_tx_successful ( & p_twai_obj -> hal ) ) {
190+ if (tx_success ) {
189191 twai_alert_handler (p_twai_obj , TWAI_ALERT_TX_SUCCESS , alert_req );
190192 } else {
191193 p_twai_obj -> tx_failed_count ++ ;
@@ -197,13 +199,13 @@ static inline void twai_handle_tx_buffer_frame(twai_obj_t *p_twai_obj, BaseType_
197199 assert (p_twai_obj -> tx_msg_count >= 0 ); //Sanity check
198200
199201 //If not bus-off, check if there are more frames to transmit
200- if (!twai_hal_check_state_flags (& p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_BUS_OFF )
202+ if (!twai_hal_check_state_flags (p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_BUS_OFF )
201203 && p_twai_obj -> tx_msg_count > 0
202204 && p_twai_obj -> tx_queue != NULL ) {
203205 twai_hal_frame_t frame ;
204206 int res = xQueueReceiveFromISR (p_twai_obj -> tx_queue , & frame , task_woken );
205207 if (res == pdTRUE ) {
206- twai_hal_set_tx_buffer_and_transmit (& p_twai_obj -> hal , & frame );
208+ twai_hal_set_tx_buffer_and_transmit (p_twai_obj -> hal , & frame , 0 );
207209 } else {
208210 assert (false && "failed to get a frame from TX queue" );
209211 }
@@ -220,16 +222,16 @@ static void twai_intr_handler_main(void *arg)
220222 int alert_req = 0 ;
221223 uint32_t events ;
222224 portENTER_CRITICAL_ISR (& p_twai_obj -> spinlock );
223- events = twai_hal_get_events (& p_twai_obj -> hal ); //Get the events that triggered the interrupt
225+ events = twai_hal_get_events (p_twai_obj -> hal ); //Get the events that triggered the interrupt
224226
225227#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID ) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT )
226228 if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET ) {
227- twai_hal_prepare_for_reset (& p_twai_obj -> hal );
229+ twai_hal_prepare_for_reset (p_twai_obj -> hal );
228230 TWAI_RCC_ATOMIC () {
229231 twai_ll_reset_register (p_twai_obj -> controller_id );
230232 }
231- twai_hal_recover_from_reset (& p_twai_obj -> hal );
232- p_twai_obj -> rx_missed_count += twai_hal_get_reset_lost_rx_cnt (& p_twai_obj -> hal );
233+ twai_hal_recover_from_reset (p_twai_obj -> hal );
234+ p_twai_obj -> rx_missed_count += twai_hal_get_reset_lost_rx_cnt (p_twai_obj -> hal );
233235 twai_alert_handler (p_twai_obj , TWAI_ALERT_PERIPH_RESET , & alert_req );
234236 }
235237#endif
@@ -238,7 +240,7 @@ static void twai_intr_handler_main(void *arg)
238240 twai_handle_rx_buffer_frames (p_twai_obj , & task_woken , & alert_req );
239241 }
240242 if (events & TWAI_HAL_EVENT_TX_BUFF_FREE ) {
241- twai_handle_tx_buffer_frame (p_twai_obj , & task_woken , & alert_req );
243+ twai_handle_tx_buffer_frame (p_twai_obj , ( events & TWAI_HAL_EVENT_TX_SUCCESS ), & task_woken , & alert_req );
242244 }
243245
244246 //Handle events that only require alerting (i.e. no handler)
@@ -270,7 +272,7 @@ static void twai_intr_handler_main(void *arg)
270272 //Returned to error active
271273 twai_alert_handler (p_twai_obj , TWAI_ALERT_ERR_ACTIVE , & alert_req );
272274 }
273- if (events & TWAI_HAL_EVENT_ABOVE_EWL ) {
275+ if (events & TWAI_HAL_EVENT_ERROR_WARNING ) {
274276 //TEC or REC surpassed error warning limit
275277 twai_alert_handler (p_twai_obj , TWAI_ALERT_ABOVE_ERR_WARN , & alert_req );
276278 }
@@ -392,7 +394,7 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw
392394 esp_err_t ret ;
393395
394396 //Create a TWAI driver object
395- twai_obj_t * p_obj = heap_caps_calloc (1 , sizeof (twai_obj_t ), TWAI_MALLOC_CAPS );
397+ twai_obj_t * p_obj = heap_caps_calloc (1 , sizeof (twai_obj_t ) + twai_hal_get_mem_requirment () , TWAI_MALLOC_CAPS );
396398 if (p_obj == NULL ) {
397399 return ESP_ERR_NO_MEM ;
398400 }
@@ -416,6 +418,7 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw
416418 }
417419
418420 p_obj -> controller_id = controller_id ;
421+ p_obj -> hal = (twai_hal_context_t * )(p_obj + 1 ); //hal context is place at end of driver context
419422
420423#if CONFIG_PM_ENABLE
421424#if SOC_TWAI_CLK_SUPPORT_APB
@@ -550,12 +553,12 @@ esp_err_t twai_driver_install_v2(const twai_general_config_t *g_config, const tw
550553 twai_hal_config_t hal_config = {
551554 .clock_source_hz = clock_source_hz ,
552555 .controller_id = controller_id ,
556+ .intr_mask = DRIVER_DEFAULT_INTERRUPTS ,
557+ .enable_self_test = (p_twai_obj -> mode == TWAI_MODE_NO_ACK ),
558+ .enable_listen_only = (p_twai_obj -> mode == TWAI_MODE_LISTEN_ONLY ),
553559 };
554- if (twai_hal_init (& p_twai_obj -> hal , & hal_config ) == false) {
555- ret = ESP_ERR_INVALID_STATE ;
556- goto err ;
557- }
558- twai_hal_configure (& p_twai_obj -> hal , t_config , f_config , DRIVER_DEFAULT_INTERRUPTS , g_config -> clkout_divider );
560+ ESP_GOTO_ON_FALSE (twai_hal_init (p_twai_obj -> hal , & hal_config ), ESP_ERR_INVALID_STATE , err , TWAI_TAG , "hardware not in reset state" );
561+ twai_hal_configure (p_twai_obj -> hal , t_config , f_config , g_config -> clkout_divider );
559562
560563 //Assign GPIO and Interrupts
561564 twai_configure_gpio (p_twai_obj );
@@ -610,7 +613,7 @@ esp_err_t twai_driver_uninstall_v2(twai_handle_t handle)
610613 ESP_ERROR_CHECK (esp_intr_disable (p_twai_obj -> isr_handle ));
611614
612615 //Clear registers by reading
613- twai_hal_deinit (& p_twai_obj -> hal );
616+ twai_hal_deinit (p_twai_obj -> hal );
614617 TWAI_PERI_ATOMIC () {
615618 twai_ll_enable_clock (controller_id , false);
616619 }
@@ -655,7 +658,7 @@ esp_err_t twai_start_v2(twai_handle_t handle)
655658 }
656659 p_twai_obj -> rx_msg_count = 0 ;
657660 p_twai_obj -> tx_msg_count = 0 ;
658- twai_hal_start (& p_twai_obj -> hal , p_twai_obj -> mode );
661+ twai_hal_start (p_twai_obj -> hal );
659662
660663 p_twai_obj -> state = TWAI_STATE_RUNNING ;
661664 portEXIT_CRITICAL (& handle -> spinlock );
@@ -680,7 +683,7 @@ esp_err_t twai_stop_v2(twai_handle_t handle)
680683 return ESP_ERR_INVALID_STATE ;
681684 }
682685
683- twai_hal_stop (& p_twai_obj -> hal );
686+ twai_hal_stop (p_twai_obj -> hal );
684687
685688 //Reset TX Queue and message count
686689 if (p_twai_obj -> tx_queue != NULL ) {
@@ -720,12 +723,27 @@ esp_err_t twai_transmit_v2(twai_handle_t handle, const twai_message_t *message,
720723 //Format frame
721724 esp_err_t ret = ESP_FAIL ;
722725 twai_hal_frame_t tx_frame ;
723- twai_hal_format_frame (message , & tx_frame );
726+ twai_frame_header_t header = {
727+ .id = message -> identifier ,
728+ .dlc = message -> data_length_code ,
729+ .ide = message -> extd ,
730+ .rtr = message -> rtr ,
731+ };
732+ twai_hal_trans_desc_t hal_trans = {
733+ .frame = {
734+ .header = & header ,
735+ .buffer = (uint8_t * )message -> data ,
736+ .buffer_len = TWAI_FRAME_MAX_LEN ,
737+ },
738+ .config .retry_cnt = message -> ss ? 0 : -1 ,
739+ .config .loopback = message -> self ,
740+ };
741+ twai_hal_format_frame (& hal_trans , & tx_frame );
724742
725743 //Check if frame can be sent immediately
726744 if (p_twai_obj -> tx_msg_count == 0 ) {
727745 //No other frames waiting to transmit. Bypass queue and transmit immediately
728- twai_hal_set_tx_buffer_and_transmit (& p_twai_obj -> hal , & tx_frame );
746+ twai_hal_set_tx_buffer_and_transmit (p_twai_obj -> hal , & tx_frame , 0 );
729747 p_twai_obj -> tx_msg_count ++ ;
730748 ret = ESP_OK ;
731749 }
@@ -738,17 +756,17 @@ esp_err_t twai_transmit_v2(twai_handle_t handle, const twai_message_t *message,
738756 } else if (xQueueSend (p_twai_obj -> tx_queue , & tx_frame , ticks_to_wait ) == pdTRUE ) {
739757 //Copied to TX Queue
740758 portENTER_CRITICAL (& handle -> spinlock );
741- if ((!twai_hal_check_state_flags (& p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED )) && uxQueueMessagesWaiting (p_twai_obj -> tx_queue ) > 0 ) {
759+ if ((!twai_hal_check_state_flags (p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED )) && uxQueueMessagesWaiting (p_twai_obj -> tx_queue ) > 0 ) {
742760 //If the TX buffer is free but the TX queue is not empty. Check if we need to manually start a transmission
743- if (twai_hal_check_state_flags (& p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_BUS_OFF ) || !twai_hal_check_state_flags (& p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_RUNNING )) {
761+ if (twai_hal_check_state_flags (p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_BUS_OFF ) || !twai_hal_check_state_flags (p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_RUNNING )) {
744762 //TX buffer became free due to bus-off or is no longer running. No need to start a transmission
745763 ret = ESP_ERR_INVALID_STATE ;
746764 } else {
747765 //Manually start a transmission
748766 int res = xQueueReceive (p_twai_obj -> tx_queue , & tx_frame , 0 );
749767 assert (res == pdTRUE );
750768 (void )res ;
751- twai_hal_set_tx_buffer_and_transmit (& p_twai_obj -> hal , & tx_frame );
769+ twai_hal_set_tx_buffer_and_transmit (p_twai_obj -> hal , & tx_frame , 0 );
752770 p_twai_obj -> tx_msg_count ++ ;
753771 ret = ESP_OK ;
754772 }
@@ -790,7 +808,14 @@ esp_err_t twai_receive_v2(twai_handle_t handle, twai_message_t *message, TickTyp
790808 portEXIT_CRITICAL (& handle -> spinlock );
791809
792810 //Decode frame
793- twai_hal_parse_frame (& rx_frame , message );
811+ twai_frame_header_t header = {0 };
812+ twai_hal_parse_frame (& rx_frame , & header , message -> data , TWAI_FRAME_MAX_LEN );
813+ message -> identifier = header .id ;
814+ message -> data_length_code = header .dlc ;
815+ message -> extd = header .ide ;
816+ message -> rtr = header .rtr ;
817+ //Set remaining bytes of data to 0
818+ memset (message -> data + message -> data_length_code , 0 , TWAI_FRAME_MAX_LEN - message -> data_length_code );
794819 return ESP_OK ;
795820}
796821
@@ -870,7 +895,7 @@ esp_err_t twai_initiate_recovery_v2(twai_handle_t handle)
870895 p_twai_obj -> tx_msg_count = 0 ;
871896
872897 //Trigger start of recovery process
873- twai_hal_start_bus_recovery (& p_twai_obj -> hal );
898+ twai_hal_start_bus_recovery (p_twai_obj -> hal );
874899 p_twai_obj -> state = TWAI_STATE_RECOVERING ;
875900 portEXIT_CRITICAL (& handle -> spinlock );
876901
@@ -896,8 +921,8 @@ esp_err_t twai_get_status_info_v2(twai_handle_t handle, twai_status_info_t *stat
896921 status_info -> tx_error_counter = 0 ;
897922 status_info -> rx_error_counter = 0 ;
898923 } else {
899- status_info -> tx_error_counter = twai_hal_get_tec (& p_twai_obj -> hal );
900- status_info -> rx_error_counter = twai_hal_get_rec (& p_twai_obj -> hal );
924+ status_info -> tx_error_counter = twai_hal_get_tec (p_twai_obj -> hal );
925+ status_info -> rx_error_counter = twai_hal_get_rec (p_twai_obj -> hal );
901926 }
902927 status_info -> msgs_to_tx = p_twai_obj -> tx_msg_count ;
903928 status_info -> msgs_to_rx = p_twai_obj -> rx_msg_count ;
@@ -927,7 +952,7 @@ esp_err_t twai_clear_transmit_queue_v2(twai_handle_t handle)
927952
928953 portENTER_CRITICAL (& handle -> spinlock );
929954 //If a message is currently undergoing transmission, the tx interrupt handler will decrement tx_msg_count
930- p_twai_obj -> tx_msg_count = twai_hal_check_state_flags (& p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED ) ? 1 : 0 ;
955+ p_twai_obj -> tx_msg_count = twai_hal_check_state_flags (p_twai_obj -> hal , TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED ) ? 1 : 0 ;
931956 xQueueReset (p_twai_obj -> tx_queue );
932957 portEXIT_CRITICAL (& handle -> spinlock );
933958
@@ -970,3 +995,21 @@ static esp_err_t s_twai_create_sleep_retention_link_cb(void *obj)
970995 twai_reg_retention_info [host -> controller_id ].module_id );
971996}
972997#endif
998+
999+ #if CONFIG_TWAI_SKIP_LEGACY_CONFLICT_CHECK
1000+ /**
1001+ * @brief This function will be called during start up, to check that this legacy TWAI driver is not running along with the new TWAI driver
1002+ */
1003+ __attribute__((constructor ))
1004+ static void check_twai_driver_conflict (void )
1005+ {
1006+ // This function was declared as weak here. The new TWAI driver has the implementation.
1007+ // So if the new TWAI driver is not linked in, then `twai_new_node_onchip()` should be NULL at runtime.
1008+ extern __attribute__((weak )) esp_err_t twai_new_node_onchip (const void * node_config , void * node_ret );
1009+ if ((void * )twai_new_node_onchip != NULL ) {
1010+ ESP_EARLY_LOGE (TWAI_TAG , "CONFLICT! driver_ng is not allowed to be used with this old driver" );
1011+ abort ();
1012+ }
1013+ ESP_EARLY_LOGW (TWAI_TAG , "This driver is an old driver, please migrate your application code to adapt `esp_twai_onchip.h`" );
1014+ }
1015+ #endif
0 commit comments