Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nuttx/can: in trunk support to Send message cancel mechanism. #166

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions drivers/can/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,15 @@ config CAN_TXPRIORITY
---help---
Prioritize sending based on canid.

config CAN_TXCANCEL
bool "Implement tx cancel ability"
default n
depends on CAN_TXPRIORITY
---help---
Enabling this feature adds support for the can cancel ability.
this ability can cancel the msg with the largest msgID in the
mailbox and return true if success.

choice
prompt "TX Ready Work Queue"
default CAN_TXREADY_HIPRI
Expand Down
34 changes: 31 additions & 3 deletions drivers/can/can.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,25 @@ static int can_xmit(FAR struct can_dev_s *dev)
}
}

#ifdef CONFIG_CAN_TXCANCEL
if (TX_PENDING(&dev->cd_sender) && can_txneed_cancel(&dev->cd_sender))
{
if (can_cancel_mbmsg(dev))
{
msg = can_get_msg(&dev->cd_sender);

/* Send the next message at the sender */

ret = dev_send(dev, msg);
if (ret < 0)
{
canerr("dev_send failed: %d\n", ret);
can_revert_msg(&dev->cd_sender, msg);
}
}
}
#endif

/* Make sure that TX interrupts are enabled */

dev_txint(dev, true);
Expand Down Expand Up @@ -594,13 +613,18 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer,

flags = enter_critical_section();

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

inactive = dev_txempty(dev);
#ifdef CONFIG_CAN_TXCANCEL
inactive = true;
#else
inactive = dev_txready(dev);
#endif

/* Add the messages to the sender. Ignore any trailing messages that are
* shorter than the minimum.
Expand Down Expand Up @@ -653,7 +677,11 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer,

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

inactive = dev_txempty(dev);
#ifdef CONFIG_CAN_TXCANCEL
inactive = true;
#else
inactive = dev_txready(dev);
#endif
}

/* We get here if there is space in sender. Add the new
Expand Down
83 changes: 83 additions & 0 deletions drivers/can/can_sender.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,86 @@ void can_send_done(FAR struct can_txcache_s *cd_sender)
}
#endif
}

/****************************************************************************
* Name: can_txneed_cancel
*
* Description:
* Compare the msgID between tx_sending and tx_pending's head when
* dev_txready return false and tx_pending is not empty, preserve the node
* with largest msgID in tx_sending into *callbackmsg_node. return true if
* the msgID in tx_pending's head < the smallest msgID in tx_sending.
*
****************************************************************************/

#ifdef CONFIG_CAN_TXCANCEL
bool can_txneed_cancel(FAR struct can_txcache_s *cd_sender)
{
FAR struct can_msg_node_s *msg_node;
FAR struct can_msg_node_s *tmp_node;

/* acquire min msgID from tx_sending and compare it with masgID
* in tx_pending list's head.
*/

if (SENDING_COUNT(cd_sender) == 0)
{
return false;
}

msg_node = list_first_entry(&cd_sender->tx_pending,
struct can_msg_node_s, list);
tmp_node = list_first_entry(&cd_sender->tx_sending,
struct can_msg_node_s, list);
if (msg_node->msg.cm_hdr.ch_id < tmp_node->msg.cm_hdr.ch_id)
{
return true;
}

return false;
}
#endif

/****************************************************************************
* Name: can_cancel_mbmsg
*
* Description:
* cancel the msg with the largest msgID in the mailbox and
* return true if success.
*
****************************************************************************/

#ifdef CONFIG_CAN_TXCANCEL
bool can_cancel_mbmsg(FAR struct can_dev_s *dev)
{
FAR struct can_msg_node_s *tmp_node;
FAR struct can_msg_node_s *callbackmsg_node;
FAR struct can_txcache_s *cd_sender = &dev->cd_sender;

callbackmsg_node = list_last_entry(&cd_sender->tx_sending,
struct can_msg_node_s, list);
if (dev->cd_ops->co_cancel != NULL &&
dev_cancel(dev, &callbackmsg_node->msg))
{
/* take tx_sending's specfic msg back into tx_pending. */

list_delete(&callbackmsg_node->list);

list_for_every_entry(&cd_sender->tx_pending, tmp_node,
struct can_msg_node_s, list)
{
if (tmp_node->msg.cm_hdr.ch_id >=
callbackmsg_node->msg.cm_hdr.ch_id)
{
break;
}
}

list_add_before(&tmp_node->list, &callbackmsg_node->list);

return true;
}

return false;
}
#endif
4 changes: 4 additions & 0 deletions include/nuttx/can/can.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@
#define dev_send(dev,m) (dev)->cd_ops->co_send(dev,m)
#define dev_txready(dev) (dev)->cd_ops->co_txready(dev)
#define dev_txempty(dev) (dev)->cd_ops->co_txempty(dev)
#define dev_cancel(dev,m) (dev)->cd_ops->co_cancel(dev,m)

/* CAN message support ******************************************************/

Expand Down Expand Up @@ -786,6 +787,9 @@ struct can_ops_s
*/

CODE bool (*co_txempty)(FAR struct can_dev_s *dev);

CODE bool (*co_cancel)(FAR struct can_dev_s *dev,
FAR struct can_msg_s *msg);
};

/* This is the device structure used by the driver. The caller of
Expand Down
30 changes: 29 additions & 1 deletion include/nuttx/can/can_sender.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,5 +235,33 @@ void can_revert_msg(FAR struct can_txcache_s *cd_sender,

void can_send_done(FAR struct can_txcache_s *cd_sender);

/****************************************************************************
* Name: can_txneed_cancel
*
* Description:
* Compare the msgID between tx_sending and tx_pending's head when
* dev_txready return false and tx_pending is not empty, preserve the node
* with largest msgID in tx_sending into *callbackmsg_node. return true if
* the msgID in tx_pending's head < the smallest msgID in tx_sending.
*
****************************************************************************/

#ifdef CONFIG_CAN_TXCANCEL
bool can_txneed_cancel(FAR struct can_txcache_s *cd_sender);
#endif

/****************************************************************************
* Name: can_cancel_mbmsg
*
* Description:
* cancel the msg with the largest msgID in the mailbox and
* return true if success.
*
****************************************************************************/

#ifdef CONFIG_CAN_TXCANCEL
bool can_cancel_mbmsg(FAR struct can_dev_s *dev);
#endif

#endif /* CONFIG_CAN */
#endif /* __INCLUDE_NUTTX_CAN_SENDER_H */
#endif /* __INCLUDE_NUTTX_CAN_SENDER_H */
Loading