1616#include "py/mperrno.h"
1717#include "py/mphal.h"
1818#include "driver/twai.h"
19+ #include "esp_clk_tree.h"
20+ #include "esp_private/esp_clk.h"
1921
20- #define DEBUG 0
22+ #define DEBUG 1
2123#if DEBUG
2224#define DEBUG_printf (...) mp_printf(&mp_plat_print, __VA_ARGS__)
2325#else
2426#define DEBUG_printf (...) (void)0
2527#endif
2628
2729// Default timings; 125Kbps
28- #define CAN_DEFAULT_PRESCALER (32)
29- #define CAN_DEFAULT_SJW (3)
30- #define CAN_DEFAULT_BS1 (15)
31- #define CAN_DEFAULT_BS2 (4)
30+ #define CAN_DEFAULT_CLK_SRC TWAI_CLK_SRC_DEFAULT
31+ #define CAN_DEFAULT_QUANTA_RESOLUTION_HZ (2500000)
32+ #define CAN_DEFAULT_BRP (0)
33+ #define CAN_DEFAULT_TSEG1 (15)
34+ #define CAN_DEFAULT_TSEG2 (4)
35+ #define CAN_DEFAULT_SJW (3)
3236
3337#define CAN_MAXIMUM_NBRP (512)
3438#define CAN_MAXIMUM_NBS1 (256)
5862#define CAN_STATE_RECOVERING 5
5963#define CAN_STATE_RUNNING 6
6064
65+ typedef struct {
66+ int xtal ; // MHz
67+ int bitrate ; // kbit
68+ twai_timing_config_t config ;
69+ } twai_timing_entry_t ;
70+
71+ static const twai_timing_entry_t timing_table [] = {
72+ // XTAL = 32 MHz
73+ {32 ,
74+ 25 ,
75+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
76+ .quanta_resolution_hz = 400000 ,
77+ .brp = 0 ,
78+ .tseg_1 = 11 ,
79+ .tseg_2 = 4 ,
80+ .sjw = 3 ,
81+ .triple_sampling = false}},
82+ {32 ,
83+ 50 ,
84+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
85+ .quanta_resolution_hz = 1000000 ,
86+ .brp = 0 ,
87+ .tseg_1 = 15 ,
88+ .tseg_2 = 4 ,
89+ .sjw = 3 ,
90+ .triple_sampling = false}},
91+ {32 ,
92+ 100 ,
93+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
94+ .quanta_resolution_hz = 2000000 ,
95+ .brp = 0 ,
96+ .tseg_1 = 15 ,
97+ .tseg_2 = 4 ,
98+ .sjw = 3 ,
99+ .triple_sampling = false}},
100+ {32 ,
101+ 125 ,
102+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
103+ .quanta_resolution_hz = 4000000 ,
104+ .brp = 0 ,
105+ .tseg_1 = 23 ,
106+ .tseg_2 = 8 ,
107+ .sjw = 3 ,
108+ .triple_sampling = false}},
109+ {32 ,
110+ 250 ,
111+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
112+ .quanta_resolution_hz = 4000000 ,
113+ .brp = 0 ,
114+ .tseg_1 = 11 ,
115+ .tseg_2 = 4 ,
116+ .sjw = 3 ,
117+ .triple_sampling = false}},
118+ {32 ,
119+ 500 ,
120+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
121+ .quanta_resolution_hz = 8000000 ,
122+ .brp = 0 ,
123+ .tseg_1 = 11 ,
124+ .tseg_2 = 4 ,
125+ .sjw = 3 ,
126+ .triple_sampling = false}},
127+ {32 ,
128+ 800 ,
129+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
130+ .quanta_resolution_hz = 16000000 ,
131+ .brp = 0 ,
132+ .tseg_1 = 15 ,
133+ .tseg_2 = 4 ,
134+ .sjw = 3 ,
135+ .triple_sampling = false}},
136+ {32 ,
137+ 1000 ,
138+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
139+ .quanta_resolution_hz = 16000000 ,
140+ .brp = 0 ,
141+ .tseg_1 = 11 ,
142+ .tseg_2 = 4 ,
143+ .sjw = 3 ,
144+ .triple_sampling = false}},
145+
146+ // XTAL = 40 MHz
147+ {40 ,
148+ 25 ,
149+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
150+ .quanta_resolution_hz = 625000 ,
151+ .brp = 0 ,
152+ .tseg_1 = 16 ,
153+ .tseg_2 = 8 ,
154+ .sjw = 3 ,
155+ .triple_sampling = false}},
156+ {40 ,
157+ 50 ,
158+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
159+ .quanta_resolution_hz = 1000000 ,
160+ .brp = 0 ,
161+ .tseg_1 = 15 ,
162+ .tseg_2 = 4 ,
163+ .sjw = 3 ,
164+ .triple_sampling = false}},
165+ {40 ,
166+ 100 ,
167+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
168+ .quanta_resolution_hz = 2000000 ,
169+ .brp = 0 ,
170+ .tseg_1 = 15 ,
171+ .tseg_2 = 4 ,
172+ .sjw = 3 ,
173+ .triple_sampling = false}},
174+ {40 ,
175+ 125 ,
176+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
177+ .quanta_resolution_hz = 2500000 ,
178+ .brp = 0 ,
179+ .tseg_1 = 15 ,
180+ .tseg_2 = 4 ,
181+ .sjw = 3 ,
182+ .triple_sampling = false}},
183+ {40 ,
184+ 250 ,
185+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
186+ .quanta_resolution_hz = 5000000 ,
187+ .brp = 0 ,
188+ .tseg_1 = 15 ,
189+ .tseg_2 = 4 ,
190+ .sjw = 3 ,
191+ .triple_sampling = false}},
192+ {40 ,
193+ 500 ,
194+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
195+ .quanta_resolution_hz = 10000000 ,
196+ .brp = 0 ,
197+ .tseg_1 = 15 ,
198+ .tseg_2 = 4 ,
199+ .sjw = 3 ,
200+ .triple_sampling = false}},
201+ {40 ,
202+ 800 ,
203+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
204+ .quanta_resolution_hz = 20000000 ,
205+ .brp = 0 ,
206+ .tseg_1 = 16 ,
207+ .tseg_2 = 8 ,
208+ .sjw = 3 ,
209+ .triple_sampling = false}},
210+ {40 ,
211+ 1000 ,
212+ {.clk_src = CAN_DEFAULT_CLK_SRC ,
213+ .quanta_resolution_hz = 20000000 ,
214+ .brp = 0 ,
215+ .tseg_1 = 15 ,
216+ .tseg_2 = 4 ,
217+ .sjw = 3 ,
218+ .triple_sampling = false}},
219+ };
220+
221+ static int find_timing_config (int xtal , int bitrate , twai_timing_config_t * out ) {
222+ for (size_t i = 0 ; i < sizeof (timing_table ) / sizeof (timing_table [0 ]); ++ i ) {
223+ if (timing_table [i ].bitrate == bitrate && timing_table [i ].xtal == xtal ) {
224+ * out = timing_table [i ].config ;
225+ return 0 ;
226+ }
227+ }
228+ return -1 ;
229+ }
230+
61231typedef struct _pyb_can_obj_t {
62232 mp_obj_base_t base ;
63233 mp_uint_t can_id ;
@@ -96,36 +266,74 @@ static void pyb_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
96266
97267// init(mode, prescaler=100, *, sjw=1, bs1=6, bs2=8)
98268static mp_obj_t pyb_can_init_helper (pyb_can_obj_t * self , size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
99- enum { ARG_mode , ARG_tx , ARG_rx , ARG_prescaler , ARG_sjw , ARG_bs1 , ARG_bs2 , ARG_triple_sampling };
269+ enum {
270+ ARG_mode ,
271+ ARG_tx ,
272+ ARG_rx ,
273+ ARG_quanta_resolution_hz ,
274+ ARG_brp ,
275+ ARG_tseg_1 ,
276+ ARG_tseg_2 ,
277+ ARG_sjw ,
278+ ARG_triple_sampling ,
279+ ARG_baudrate ,
280+ };
100281 static const mp_arg_t allowed_args [] = {
101282 {MP_QSTR_mode , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = CAN_MODE_NORMAL }},
102283 {MP_QSTR_tx , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 2 }},
103284 {MP_QSTR_rx , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 1 }},
104- {MP_QSTR_prescaler , MP_ARG_INT , {.u_int = CAN_DEFAULT_PRESCALER }},
285+ {MP_QSTR_quanta_resolution_hz , MP_ARG_INT , {.u_int = CAN_DEFAULT_QUANTA_RESOLUTION_HZ }},
286+ {MP_QSTR_brp , MP_ARG_INT , {.u_int = CAN_DEFAULT_BRP }},
287+ {MP_QSTR_tseg_1 , MP_ARG_INT , {.u_int = CAN_DEFAULT_TSEG1 }},
288+ {MP_QSTR_tseg_2 , MP_ARG_INT , {.u_int = CAN_DEFAULT_TSEG2 }},
105289 {MP_QSTR_sjw , MP_ARG_INT , {.u_int = CAN_DEFAULT_SJW }},
106- {MP_QSTR_bs1 , MP_ARG_INT , {.u_int = CAN_DEFAULT_BS1 }},
107- {MP_QSTR_bs2 , MP_ARG_INT , {.u_int = CAN_DEFAULT_BS2 }},
108290 {MP_QSTR_triple_sampling , MP_ARG_BOOL , {.u_bool = false}},
291+ {MP_QSTR_baudrate , MP_ARG_INT , {.u_int = 0 }},
109292 };
110293
111294 // parse args
112295 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
113296 mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
114297
115- self -> t_config .brp = args [ARG_prescaler ].u_int ;
116- self -> t_config .tseg_1 = args [ARG_bs1 ].u_int ;
117- self -> t_config .tseg_2 = args [ARG_bs2 ].u_int ;
118- self -> t_config .sjw = args [ARG_sjw ].u_int ;
119- self -> t_config .triple_sampling = args [ARG_triple_sampling ].u_bool ;
120-
121298 self -> g_config .tx_io = args [ARG_tx ].u_int ;
122299 self -> g_config .rx_io = args [ARG_rx ].u_int ;
123300 self -> g_config .mode = args [ARG_mode ].u_int ;
124301
125- DEBUG_printf (& mp_plat_print , "prescaler=%u, sjw=%u, bs1=%u, bs2=%u, triple_sampling=%u\n" , self -> t_config .brp ,
126- self -> t_config .tseg_1 , self -> t_config .tseg_2 , self -> t_config .sjw , self -> t_config .triple_sampling );
127- DEBUG_printf (& mp_plat_print , "mode=%u, tx=%u, rx=%u\n" , self -> g_config .mode , self -> g_config .tx_io ,
128- self -> g_config .rx_io );
302+ if (args [ARG_baudrate ].u_int != 0 ) {
303+ int xtal = esp_clk_xtal_freq () / 1000000 ;
304+ DEBUG_printf ("XTAL frequency: %d MHz\n" , xtal );
305+ DEBUG_printf ("find_timing_config: xtal=%d MHz, baudrate=%d kbps\n" , xtal , args [ARG_baudrate ].u_int );
306+ if (find_timing_config (xtal , args [ARG_baudrate ].u_int , & self -> t_config ) != 0 ) {
307+ DEBUG_printf ("Timing config not found for baudrate %d kbps\n" , args [ARG_baudrate ].u_int );
308+ mp_raise_msg_varg (& mp_type_ValueError ,
309+ MP_ERROR_TEXT ("Unsupported baudrate %d kbps for %d MHz crystal. Supported: 25, 50, 100, "
310+ "125, 250, 500, 800, 1000" ),
311+ args [ARG_baudrate ].u_int , xtal );
312+ }
313+ } else {
314+ self -> t_config .clk_src = CAN_DEFAULT_CLK_SRC ;
315+ if (args [ARG_quanta_resolution_hz ].u_int == 0 && args [ARG_brp ].u_int != 0 ) {
316+ uint32_t xtal_apb_freq_hz ;
317+
318+ esp_clk_tree_src_get_freq_hz (CAN_DEFAULT_CLK_SRC , ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT , & xtal_apb_freq_hz );
319+ DEBUG_printf ("XTAL APB frequency: %d MHz\n" , xtal_apb_freq_hz / 1000000 );
320+ args [ARG_quanta_resolution_hz ].u_int = xtal_apb_freq_hz / args [ARG_brp ].u_int ;
321+ DEBUG_printf ("Using quanta_resolution_hz=%u based on brp=%u\n" , args [ARG_quanta_resolution_hz ].u_int ,
322+ args [ARG_brp ].u_int );
323+ args [ARG_brp ].u_int = 0 ;
324+ }
325+ self -> t_config .quanta_resolution_hz = args [ARG_quanta_resolution_hz ].u_int ;
326+ self -> t_config .brp = args [ARG_brp ].u_int ;
327+ self -> t_config .tseg_1 = args [ARG_tseg_1 ].u_int ;
328+ self -> t_config .tseg_2 = args [ARG_tseg_2 ].u_int ;
329+ self -> t_config .sjw = args [ARG_sjw ].u_int ;
330+ self -> t_config .triple_sampling = args [ARG_triple_sampling ].u_bool ;
331+ }
332+
333+ DEBUG_printf ("tx=%u, rx=%u, mode=%u\n" , self -> g_config .tx_io , self -> g_config .rx_io , self -> g_config .mode );
334+ DEBUG_printf ("quanta_resolution_hz=%u brp=%u, tseg_1=%u, tseg_2=%u, sjw=%u, triple_sampling=%u\n" ,
335+ self -> t_config .quanta_resolution_hz , self -> t_config .brp , self -> t_config .tseg_1 , self -> t_config .tseg_2 ,
336+ self -> t_config .sjw , self -> t_config .triple_sampling );
129337
130338 check_esp_err (twai_driver_install (& self -> g_config , & self -> t_config , & self -> f_config ));
131339 check_esp_err (twai_start ());
@@ -157,9 +365,11 @@ static mp_obj_t pyb_can_make_new(const mp_obj_type_t *type, size_t n_args, size_
157365 }
158366
159367 {
160- self -> t_config .brp = CAN_DEFAULT_PRESCALER ;
161- self -> t_config .tseg_1 = CAN_DEFAULT_BS1 ;
162- self -> t_config .tseg_2 = CAN_DEFAULT_BS2 ;
368+ self -> t_config .clk_src = CAN_DEFAULT_CLK_SRC ;
369+ self -> t_config .quanta_resolution_hz = CAN_DEFAULT_QUANTA_RESOLUTION_HZ ;
370+ self -> t_config .brp = CAN_DEFAULT_BRP ;
371+ self -> t_config .tseg_1 = CAN_DEFAULT_TSEG1 ;
372+ self -> t_config .tseg_2 = CAN_DEFAULT_TSEG2 ;
163373 self -> t_config .sjw = CAN_DEFAULT_SJW ;
164374 self -> t_config .triple_sampling = false;
165375 };
@@ -187,7 +397,7 @@ static mp_obj_t pyb_can_make_new(const mp_obj_type_t *type, size_t n_args, size_
187397 twai_stop ();
188398 // check_esp_err(twai_driver_uninstall());
189399 int err = twai_driver_uninstall ();
190- mp_printf ( & mp_plat_print , "twai_driver_uninstall() returned %d\n" , err );
400+ DEBUG_printf ( "twai_driver_uninstall() returned %d\n" , ( int ) err );
191401
192402 vTaskDelay (10 / portTICK_PERIOD_MS );
193403 self -> is_enabled = false;
@@ -340,24 +550,24 @@ static mp_obj_t pyb_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
340550 tx_msg .rtr = args [ARG_rtr ].u_bool ;
341551 tx_msg .extd = args [ARG_extframe ].u_bool ;
342552 #if DEBUG
343- DEBUG_printf (& mp_plat_print , "Income Data:" );
553+ DEBUG_printf ("Send Data:" );
344554 for (size_t i = 0 ; i < bufinfo .len ; i ++ ) {
345- DEBUG_printf (& mp_plat_print , "0x%02X " , ((uint8_t * )bufinfo .buf )[i ]);
555+ DEBUG_printf ("0x%02X " , ((uint8_t * )bufinfo .buf )[i ]);
346556 }
347- DEBUG_printf (& mp_plat_print , "\n - extd: %d\n" , tx_msg .extd );
348- DEBUG_printf (& mp_plat_print , " - rtr: %d\n" , tx_msg .rtr );
349- DEBUG_printf (& mp_plat_print , " - ss: %d\n" , tx_msg .ss );
350- DEBUG_printf (& mp_plat_print , " - self: %d\n" , tx_msg .self );
351- DEBUG_printf (& mp_plat_print , " - dlc_non_comp: %d\n" , tx_msg .dlc_non_comp );
352- DEBUG_printf (& mp_plat_print , "Complete tx_msg:\n" );
353- DEBUG_printf (& mp_plat_print , " flags: 0x%08X\n" , tx_msg .flags );
354- DEBUG_printf (& mp_plat_print , " identifier: 0x%08X\n" , tx_msg .identifier );
355- DEBUG_printf (& mp_plat_print , " data_length_code: %d\n" , tx_msg .data_length_code );
356- DEBUG_printf (& mp_plat_print , " data: " );
557+ DEBUG_printf ("\n - extd: %d\n" , tx_msg .extd );
558+ DEBUG_printf (" - rtr: %d\n" , tx_msg .rtr );
559+ DEBUG_printf (" - ss: %d\n" , tx_msg .ss );
560+ DEBUG_printf (" - self: %d\n" , tx_msg .self );
561+ DEBUG_printf (" - dlc_non_comp: %d\n" , tx_msg .dlc_non_comp );
562+ DEBUG_printf ("Complete tx_msg:\n" );
563+ DEBUG_printf (" flags: 0x%08X\n" , tx_msg .flags );
564+ DEBUG_printf (" identifier: 0x%08X\n" , tx_msg .identifier );
565+ DEBUG_printf (" data_length_code: %d\n" , tx_msg .data_length_code );
566+ DEBUG_printf (" data: " );
357567 for (int i = 0 ; i < bufinfo .len ; i ++ ) {
358- DEBUG_printf (& mp_plat_print , "0x%02X " , tx_msg .data [i ]);
568+ DEBUG_printf ("0x%02X " , tx_msg .data [i ]);
359569 }
360- DEBUG_printf (& mp_plat_print , "\n\n" );
570+ DEBUG_printf ("\n\n" );
361571 #endif
362572 check_esp_err (twai_transmit (& tx_msg , args [ARG_timeout ].u_int ));
363573 return mp_const_none ;
@@ -382,12 +592,12 @@ static mp_obj_t pyb_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
382592 twai_message_t rx_msg ;
383593 esp_err_t ret = twai_receive (& rx_msg , args [ARG_timeout ].u_int );
384594 #if DEBUG
385- DEBUG_printf (& mp_plat_print , "Received identifier: 0x%08X\n" , rx_msg .identifier );
386- DEBUG_printf (& mp_plat_print , "received data: " );
595+ DEBUG_printf ("Received identifier: 0x%08X\n" , rx_msg .identifier );
596+ DEBUG_printf ("received data: " );
387597 for (int i = 0 ; i < rx_msg .data_length_code ; i ++ ) {
388- DEBUG_printf (& mp_plat_print , "0x%02X " , rx_msg .data [i ]);
598+ DEBUG_printf ("0x%02X " , rx_msg .data [i ]);
389599 }
390- DEBUG_printf (& mp_plat_print , "\r\n" );
600+ DEBUG_printf ("\r\n" );
391601 #endif
392602 if (ret != ESP_OK || rx_msg .data_length_code > 8 ) {
393603 return mp_const_none ;
@@ -540,8 +750,8 @@ MP_DEFINE_CONST_OBJ_TYPE(pyb_can_type, MP_QSTR_CAN, MP_TYPE_FLAG_NONE, make_new,
540750MP_REGISTER_ROOT_POINTER (struct _pyb_can_obj_t * pyb_can_obj_all [1 ]);
541751
542752static const mp_rom_map_elem_t m5can_module_globals_table [] = {
543- { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_m5can ) },
544- { MP_ROM_QSTR (MP_QSTR_CAN ), MP_ROM_PTR (& pyb_can_type ) },
753+ {MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_m5can )},
754+ {MP_ROM_QSTR (MP_QSTR_CAN ), MP_ROM_PTR (& pyb_can_type )},
545755};
546756
547757static MP_DEFINE_CONST_DICT (m5can_module_globals , m5can_module_globals_table ) ;
0 commit comments