@@ -170,6 +170,96 @@ STATIC void can_clearfilter(uint32_t f) {
170170 HAL_CAN_ConfigFilter (NULL , & filter );
171171}
172172
173+ // We have our own version of CAN transmit so we can handle Timeout=0 correctly.
174+ STATIC HAL_StatusTypeDef CAN_Transmit (CAN_HandleTypeDef * hcan , uint32_t Timeout ) {
175+ uint32_t transmitmailbox ;
176+ uint32_t tickstart ;
177+ uint32_t rqcpflag ;
178+ uint32_t txokflag ;
179+
180+ // Check the parameters
181+ assert_param (IS_CAN_IDTYPE (hcan -> pTxMsg -> IDE ));
182+ assert_param (IS_CAN_RTR (hcan -> pTxMsg -> RTR ));
183+ assert_param (IS_CAN_DLC (hcan -> pTxMsg -> DLC ));
184+
185+ // Select one empty transmit mailbox
186+ if ((hcan -> Instance -> TSR & CAN_TSR_TME0 ) == CAN_TSR_TME0 ) {
187+ transmitmailbox = CAN_TXMAILBOX_0 ;
188+ rqcpflag = CAN_FLAG_RQCP0 ;
189+ txokflag = CAN_FLAG_TXOK0 ;
190+ } else if ((hcan -> Instance -> TSR & CAN_TSR_TME1 ) == CAN_TSR_TME1 ) {
191+ transmitmailbox = CAN_TXMAILBOX_1 ;
192+ rqcpflag = CAN_FLAG_RQCP1 ;
193+ txokflag = CAN_FLAG_TXOK1 ;
194+ } else if ((hcan -> Instance -> TSR & CAN_TSR_TME2 ) == CAN_TSR_TME2 ) {
195+ transmitmailbox = CAN_TXMAILBOX_2 ;
196+ rqcpflag = CAN_FLAG_RQCP2 ;
197+ txokflag = CAN_FLAG_TXOK2 ;
198+ } else {
199+ transmitmailbox = CAN_TXSTATUS_NOMAILBOX ;
200+ }
201+
202+ if (transmitmailbox != CAN_TXSTATUS_NOMAILBOX ) {
203+ // Set up the Id
204+ hcan -> Instance -> sTxMailBox [transmitmailbox ].TIR &= CAN_TI0R_TXRQ ;
205+ if (hcan -> pTxMsg -> IDE == CAN_ID_STD ) {
206+ assert_param (IS_CAN_STDID (hcan -> pTxMsg -> StdId ));
207+ hcan -> Instance -> sTxMailBox [transmitmailbox ].TIR |= ((hcan -> pTxMsg -> StdId << 21 ) | \
208+ hcan -> pTxMsg -> RTR );
209+ } else {
210+ assert_param (IS_CAN_EXTID (hcan -> pTxMsg -> ExtId ));
211+ hcan -> Instance -> sTxMailBox [transmitmailbox ].TIR |= ((hcan -> pTxMsg -> ExtId << 3 ) | \
212+ hcan -> pTxMsg -> IDE | \
213+ hcan -> pTxMsg -> RTR );
214+ }
215+
216+ // Set up the DLC
217+ hcan -> pTxMsg -> DLC &= (uint8_t )0x0000000F ;
218+ hcan -> Instance -> sTxMailBox [transmitmailbox ].TDTR &= (uint32_t )0xFFFFFFF0 ;
219+ hcan -> Instance -> sTxMailBox [transmitmailbox ].TDTR |= hcan -> pTxMsg -> DLC ;
220+
221+ // Set up the data field
222+ hcan -> Instance -> sTxMailBox [transmitmailbox ].TDLR = (((uint32_t )hcan -> pTxMsg -> Data [3 ] << 24 ) |
223+ ((uint32_t )hcan -> pTxMsg -> Data [2 ] << 16 ) |
224+ ((uint32_t )hcan -> pTxMsg -> Data [1 ] << 8 ) |
225+ ((uint32_t )hcan -> pTxMsg -> Data [0 ]));
226+ hcan -> Instance -> sTxMailBox [transmitmailbox ].TDHR = (((uint32_t )hcan -> pTxMsg -> Data [7 ] << 24 ) |
227+ ((uint32_t )hcan -> pTxMsg -> Data [6 ] << 16 ) |
228+ ((uint32_t )hcan -> pTxMsg -> Data [5 ] << 8 ) |
229+ ((uint32_t )hcan -> pTxMsg -> Data [4 ]));
230+ // Request transmission
231+ hcan -> Instance -> sTxMailBox [transmitmailbox ].TIR |= CAN_TI0R_TXRQ ;
232+
233+ if (Timeout == 0 ) {
234+ return HAL_OK ;
235+ }
236+
237+ // Get tick
238+ tickstart = HAL_GetTick ();
239+ // Check End of transmission flag
240+ while (!(__HAL_CAN_TRANSMIT_STATUS (hcan , transmitmailbox ))) {
241+ // Check for the Timeout
242+ if (Timeout != HAL_MAX_DELAY ) {
243+ if ((HAL_GetTick () - tickstart ) > Timeout ) {
244+ // When the timeout expires, we try to abort the transmission of the packet
245+ __HAL_CAN_CANCEL_TRANSMIT (hcan , transmitmailbox );
246+ while (!__HAL_CAN_GET_FLAG (hcan , rqcpflag )) {
247+ }
248+ if (__HAL_CAN_GET_FLAG (hcan , txokflag )) {
249+ // The abort attempt failed and the message was sent properly
250+ return HAL_OK ;
251+ } else {
252+ return HAL_TIMEOUT ;
253+ }
254+ }
255+ }
256+ }
257+ return HAL_OK ;
258+ } else {
259+ return HAL_BUSY ;
260+ }
261+ }
262+
173263/******************************************************************************/
174264// Micro Python bindings
175265
@@ -348,7 +438,7 @@ STATIC mp_obj_t pyb_can_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
348438 static const mp_arg_t allowed_args [] = {
349439 { MP_QSTR_send , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
350440 { MP_QSTR_addr , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 0 } },
351- { MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 5000 } },
441+ { MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
352442 };
353443
354444 // parse args
@@ -380,7 +470,7 @@ STATIC mp_obj_t pyb_can_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
380470 tx_msg .Data [i ] = ((byte * )bufinfo .buf )[i ]; // Data is uint32_t but holds only 1 byte
381471 }
382472 self -> can .pTxMsg = & tx_msg ;
383- HAL_StatusTypeDef status = HAL_CAN_Transmit (& self -> can , args [2 ].u_int );
473+ HAL_StatusTypeDef status = CAN_Transmit (& self -> can , args [2 ].u_int );
384474
385475 if (status != HAL_OK ) {
386476 mp_hal_raise (status );
0 commit comments