Skip to content

Commit 2f1e894

Browse files
nuttx/can: in trunk support to Send message cancel mechanism.
VELAFORCAR-2405 add Send message cancel mechanism_1 based priority list. Change-Id: Iabffab3755d7a3b0fe8090fd7101b60d18660b58 Signed-off-by: zhaohaiyang1 <[email protected]> (cherry picked from commit 8be6223d17862e67595e364c6459fafb901dc104)
1 parent dfdbf4d commit 2f1e894

File tree

5 files changed

+156
-4
lines changed

5 files changed

+156
-4
lines changed

drivers/can/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ config CAN_TXPRIORITY
134134
---help---
135135
Prioritize sending based on canid.
136136

137+
config CAN_TXCANCEL
138+
bool "Implement tx cancel ability"
139+
default n
140+
depends on CAN_TXPRIORITY
141+
---help---
142+
Enabling this feature adds support for the can cancel ability.
143+
this ability can cancel the msg with the largest msgID in the
144+
mailbox and return true if success.
145+
137146
choice
138147
prompt "TX Ready Work Queue"
139148
default CAN_TXREADY_HIPRI

drivers/can/can.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,25 @@ static int can_xmit(FAR struct can_dev_s *dev)
595595
}
596596
}
597597

598+
#ifdef CONFIG_CAN_TXCANCEL
599+
if (TX_PENDING(&dev->cd_sender) && can_txneed_cancel(&dev->cd_sender))
600+
{
601+
if (can_cancel_mbmsg(dev))
602+
{
603+
msg = can_get_msg(&dev->cd_sender);
604+
605+
/* Send the next message at the sender */
606+
607+
ret = dev_send(dev, msg);
608+
if (ret < 0)
609+
{
610+
canerr("dev_send failed: %d\n", ret);
611+
can_revert_msg(&dev->cd_sender, msg);
612+
}
613+
}
614+
}
615+
#endif
616+
598617
/* Make sure that TX interrupts are enabled */
599618

600619
dev_txint(dev, true);
@@ -627,13 +646,18 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer,
627646

628647
flags = enter_critical_section();
629648

630-
/* Check if the H/W TX is inactive when we started. In certain race
649+
/* if CONFIG_CAN_TXCANCEL is enable, inactive will be always true, else
650+
* Check if the H/W TX is inactive when we started. In certain race
631651
* conditions, there may be a pending interrupt to kick things back off,
632652
* but we will be sure here that there is not. That the hardware is IDLE
633653
* and will need to be kick-started.
634654
*/
635655

636-
inactive = dev_txempty(dev);
656+
#ifdef CONFIG_CAN_TXCANCEL
657+
inactive = true;
658+
#else
659+
inactive = dev_txready(dev);
660+
#endif
637661

638662
/* Add the messages to the sender. Ignore any trailing messages that are
639663
* shorter than the minimum.
@@ -686,7 +710,11 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer,
686710

687711
/* Re-check the H/W sender state */
688712

689-
inactive = dev_txempty(dev);
713+
#ifdef CONFIG_CAN_TXCANCEL
714+
inactive = true;
715+
#else
716+
inactive = dev_txready(dev);
717+
#endif
690718
}
691719

692720
/* We get here if there is space in sender. Add the new

drivers/can/can_sender.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,86 @@ void can_send_done(FAR struct can_txcache_s *cd_sender)
245245
}
246246
#endif
247247
}
248+
249+
/****************************************************************************
250+
* Name: can_txneed_cancel
251+
*
252+
* Description:
253+
* Compare the msgID between tx_sending and tx_pending's head when
254+
* dev_txready return false and tx_pending is not empty, preserve the node
255+
* with largest msgID in tx_sending into *callbackmsg_node. return true if
256+
* the msgID in tx_pending's head < the smallest msgID in tx_sending.
257+
*
258+
****************************************************************************/
259+
260+
#ifdef CONFIG_CAN_TXCANCEL
261+
bool can_txneed_cancel(FAR struct can_txcache_s *cd_sender)
262+
{
263+
FAR struct can_msg_node_s *msg_node;
264+
FAR struct can_msg_node_s *tmp_node;
265+
266+
/* acquire min msgID from tx_sending and compare it with masgID
267+
* in tx_pending list's head.
268+
*/
269+
270+
if (SENDING_COUNT(cd_sender) == 0)
271+
{
272+
return false;
273+
}
274+
275+
msg_node = list_first_entry(&cd_sender->tx_pending,
276+
struct can_msg_node_s, list);
277+
tmp_node = list_first_entry(&cd_sender->tx_sending,
278+
struct can_msg_node_s, list);
279+
if (msg_node->msg.cm_hdr.ch_id < tmp_node->msg.cm_hdr.ch_id)
280+
{
281+
return true;
282+
}
283+
284+
return false;
285+
}
286+
#endif
287+
288+
/****************************************************************************
289+
* Name: can_cancel_mbmsg
290+
*
291+
* Description:
292+
* cancel the msg with the largest msgID in the mailbox and
293+
* return true if success.
294+
*
295+
****************************************************************************/
296+
297+
#ifdef CONFIG_CAN_TXCANCEL
298+
bool can_cancel_mbmsg(FAR struct can_dev_s *dev)
299+
{
300+
FAR struct can_msg_node_s *tmp_node;
301+
FAR struct can_msg_node_s *callbackmsg_node;
302+
FAR struct can_txcache_s *cd_sender = &dev->cd_sender;
303+
304+
callbackmsg_node = list_last_entry(&cd_sender->tx_sending,
305+
struct can_msg_node_s, list);
306+
if (dev->cd_ops->co_cancel != NULL &&
307+
dev_cancel(dev, &callbackmsg_node->msg))
308+
{
309+
/* take tx_sending's specfic msg back into tx_pending. */
310+
311+
list_delete(&callbackmsg_node->list);
312+
313+
list_for_every_entry(&cd_sender->tx_pending, tmp_node,
314+
struct can_msg_node_s, list)
315+
{
316+
if (tmp_node->msg.cm_hdr.ch_id >=
317+
callbackmsg_node->msg.cm_hdr.ch_id)
318+
{
319+
break;
320+
}
321+
}
322+
323+
list_add_before(&tmp_node->list, &callbackmsg_node->list);
324+
325+
return true;
326+
}
327+
328+
return false;
329+
}
330+
#endif

include/nuttx/can/can.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@
396396
#define dev_send(dev,m) (dev)->cd_ops->co_send(dev,m)
397397
#define dev_txready(dev) (dev)->cd_ops->co_txready(dev)
398398
#define dev_txempty(dev) (dev)->cd_ops->co_txempty(dev)
399+
#define dev_cancel(dev,m) (dev)->cd_ops->co_cancel(dev,m)
399400

400401
/* CAN message support ******************************************************/
401402

@@ -815,6 +816,9 @@ struct can_ops_s
815816
*/
816817

817818
CODE bool (*co_txempty)(FAR struct can_dev_s *dev);
819+
820+
CODE bool (*co_cancel)(FAR struct can_dev_s *dev,
821+
FAR struct can_msg_s *msg);
818822
};
819823

820824
/* This is the device structure used by the driver. The caller of

include/nuttx/can/can_sender.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,5 +235,33 @@ void can_revert_msg(FAR struct can_txcache_s *cd_sender,
235235

236236
void can_send_done(FAR struct can_txcache_s *cd_sender);
237237

238+
/****************************************************************************
239+
* Name: can_txneed_cancel
240+
*
241+
* Description:
242+
* Compare the msgID between tx_sending and tx_pending's head when
243+
* dev_txready return false and tx_pending is not empty, preserve the node
244+
* with largest msgID in tx_sending into *callbackmsg_node. return true if
245+
* the msgID in tx_pending's head < the smallest msgID in tx_sending.
246+
*
247+
****************************************************************************/
248+
249+
#ifdef CONFIG_CAN_TXCANCEL
250+
bool can_txneed_cancel(FAR struct can_txcache_s *cd_sender);
251+
#endif
252+
253+
/****************************************************************************
254+
* Name: can_cancel_mbmsg
255+
*
256+
* Description:
257+
* cancel the msg with the largest msgID in the mailbox and
258+
* return true if success.
259+
*
260+
****************************************************************************/
261+
262+
#ifdef CONFIG_CAN_TXCANCEL
263+
bool can_cancel_mbmsg(FAR struct can_dev_s *dev);
264+
#endif
265+
238266
#endif /* CONFIG_CAN */
239-
#endif /* __INCLUDE_NUTTX_CAN_SENDER_H */
267+
#endif /* __INCLUDE_NUTTX_CAN_SENDER_H */

0 commit comments

Comments
 (0)