imxrt: flexcan use hpwork for receiving frames
FlexCAN before used interrupts to process incoming frames. This patch adds a HPWORK workqueue to process incoming frames in the workqueue context instead. Also renamed mbi to txmb for better readability.
This commit is contained in:
parent
72de29422a
commit
0b721ac21c
@ -66,7 +66,8 @@
|
||||
* is required.
|
||||
*/
|
||||
|
||||
#define CANWORK LPWORK
|
||||
#define CANWORK LPWORK
|
||||
#define CANRCVWORK HPWORK
|
||||
|
||||
/* CONFIG_IMXRT_FLEXCAN_NETHIFS determines the number of physical
|
||||
* interfaces that will be supported.
|
||||
@ -268,6 +269,7 @@ struct imxrt_driver_s
|
||||
#ifdef TX_TIMEOUT_WQ
|
||||
struct wdog_s txtimeout[TXMBCOUNT]; /* TX timeout timer */
|
||||
#endif
|
||||
struct work_s rcvwork; /* For deferring interrupt work to the wq */
|
||||
struct work_s irqwork; /* For deferring interrupt work to the wq */
|
||||
struct work_s pollwork; /* For deferring poll work to the work wq */
|
||||
struct canfd_frame *txdesc_fd; /* A pointer to the list of TX descriptor for FD frames */
|
||||
@ -482,6 +484,7 @@ static void imxrt_txdone(struct imxrt_driver_s *priv);
|
||||
|
||||
static int imxrt_flexcan_interrupt(int irq, void *context,
|
||||
void *arg);
|
||||
static void imxrt_flexcan_interrupt_work(void *arg);
|
||||
|
||||
/* Watchdog timer expirations */
|
||||
#ifdef TX_TIMEOUT_WQ
|
||||
@ -578,6 +581,7 @@ static int imxrt_transmit(struct imxrt_driver_s *priv)
|
||||
#endif
|
||||
#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
|
||||
int32_t timeout;
|
||||
uint32_t txmb = 0;
|
||||
#endif
|
||||
|
||||
mbi = RXMBCOUNT + 1;
|
||||
@ -596,6 +600,9 @@ static int imxrt_transmit(struct imxrt_driver_s *priv)
|
||||
|
||||
mb_bit <<= 1;
|
||||
mbi++;
|
||||
#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
|
||||
txmb++;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mbi == TOTALMBCOUNT)
|
||||
@ -613,7 +620,7 @@ static int imxrt_transmit(struct imxrt_driver_s *priv)
|
||||
{
|
||||
struct timeval *tv =
|
||||
(struct timeval *)(priv->dev.d_buf + priv->dev.d_len);
|
||||
priv->txmb[mbi].deadline = *tv;
|
||||
priv->txmb[txmb].deadline = *tv;
|
||||
timeout = (tv->tv_sec - ts.tv_sec)*CLK_TCK
|
||||
+ ((tv->tv_usec - ts.tv_nsec / 1000)*CLK_TCK) / 1000000;
|
||||
if (timeout < 0)
|
||||
@ -629,15 +636,15 @@ static int imxrt_transmit(struct imxrt_driver_s *priv)
|
||||
{
|
||||
timeout = ((CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE / 1000000)
|
||||
*CLK_TCK);
|
||||
priv->txmb[mbi].deadline.tv_sec = ts.tv_sec +
|
||||
priv->txmb[txmb].deadline.tv_sec = ts.tv_sec +
|
||||
CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE / 1000000;
|
||||
priv->txmb[mbi].deadline.tv_usec = (ts.tv_nsec / 1000) +
|
||||
priv->txmb[txmb].deadline.tv_usec = (ts.tv_nsec / 1000) +
|
||||
CONFIG_NET_CAN_RAW_DEFAULT_TX_DEADLINE % 1000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->txmb[mbi].deadline.tv_sec = 0;
|
||||
priv->txmb[mbi].deadline.tv_usec = 0;
|
||||
priv->txmb[txmb].deadline.tv_sec = 0;
|
||||
priv->txmb[txmb].deadline.tv_usec = 0;
|
||||
timeout = -1;
|
||||
}
|
||||
}
|
||||
@ -726,7 +733,7 @@ static int imxrt_transmit(struct imxrt_driver_s *priv)
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
wd_start(&priv->txtimeout[mbi - RXMBCOUNT], timeout + 1,
|
||||
wd_start(&priv->txtimeout[txmb], timeout + 1,
|
||||
imxrt_txtimeout_expiry, (wdparm_t)priv);
|
||||
}
|
||||
#endif
|
||||
@ -981,6 +988,9 @@ static void imxrt_txdone(struct imxrt_driver_s *priv)
|
||||
uint32_t flags;
|
||||
uint32_t mbi;
|
||||
uint32_t mb_bit;
|
||||
#ifdef TX_TIMEOUT_WQ
|
||||
uint32_t txmb;
|
||||
#endif
|
||||
|
||||
flags = getreg32(priv->base + IMXRT_CAN_IFLAG1_OFFSET);
|
||||
flags &= IFLAG1_TX;
|
||||
@ -989,8 +999,13 @@ static void imxrt_txdone(struct imxrt_driver_s *priv)
|
||||
|
||||
/* Process TX completions */
|
||||
|
||||
mb_bit = 1 << RXMBCOUNT;
|
||||
for (mbi = 0; flags && mbi < TXMBCOUNT; mbi++)
|
||||
mbi = RXMBCOUNT + 1;
|
||||
mb_bit = 1 << mbi;
|
||||
#ifdef TX_TIMEOUT_WQ
|
||||
txmb = 0;
|
||||
#endif
|
||||
|
||||
while (mbi < TOTALMBCOUNT)
|
||||
{
|
||||
if (flags & mb_bit)
|
||||
{
|
||||
@ -1003,13 +1018,17 @@ static void imxrt_txdone(struct imxrt_driver_s *priv)
|
||||
* mailbox be set to inactive
|
||||
*/
|
||||
|
||||
wd_cancel(&priv->txtimeout[mbi]);
|
||||
struct mb_s *mb = flexcan_get_mb(priv, mbi + RXMBCOUNT);
|
||||
wd_cancel(&priv->txtimeout[txmb]);
|
||||
struct mb_s *mb = flexcan_get_mb(priv, mbi);
|
||||
mb->cs.code = CAN_TXMB_INACTIVE;
|
||||
#endif
|
||||
}
|
||||
|
||||
mb_bit <<= 1;
|
||||
mbi++;
|
||||
#ifdef TX_TIMEOUT_WQ
|
||||
txmb++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1046,6 +1065,43 @@ static void imxrt_txdone_work(void *arg)
|
||||
net_unlock();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: imxrt_flexcan_interrupt_work
|
||||
*
|
||||
* Description:
|
||||
* Three interrupt sources will vector this this function:
|
||||
* 1. CAN MB transmit interrupt handler
|
||||
* 2. CAN MB receive interrupt handler
|
||||
* 3.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Number of the IRQ that generated the interrupt
|
||||
* context - Interrupt register state save info (architecture-specific)
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void imxrt_flexcan_interrupt_work(void *arg)
|
||||
{
|
||||
struct imxrt_driver_s *priv = (struct imxrt_driver_s *)arg;
|
||||
|
||||
uint32_t flags;
|
||||
flags = getreg32(priv->base + IMXRT_CAN_IFLAG1_OFFSET);
|
||||
flags &= IFLAG1_RX;
|
||||
|
||||
net_lock();
|
||||
imxrt_receive(priv, flags);
|
||||
net_unlock();
|
||||
|
||||
/* Mask MB again */
|
||||
|
||||
modifyreg32(priv->base + IMXRT_CAN_IMASK1_OFFSET, 0, IFLAG1_RX);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: imxrt_flexcan_interrupt
|
||||
*
|
||||
@ -1079,11 +1135,9 @@ static int imxrt_flexcan_interrupt(int irq, void *context,
|
||||
|
||||
if (flags)
|
||||
{
|
||||
/* Process immediately since scheduling a workqueue is too slow
|
||||
* which causes us to drop CAN frames
|
||||
*/
|
||||
|
||||
imxrt_receive(priv, flags);
|
||||
modifyreg32(priv->base + IMXRT_CAN_IMASK1_OFFSET, IFLAG1_RX, 0);
|
||||
work_queue(CANRCVWORK, &priv->rcvwork,
|
||||
imxrt_flexcan_interrupt_work, priv, 0);
|
||||
}
|
||||
|
||||
flags = getreg32(priv->base + IMXRT_CAN_IFLAG1_OFFSET);
|
||||
@ -1095,9 +1149,7 @@ static int imxrt_flexcan_interrupt(int irq, void *context,
|
||||
* condition here.
|
||||
*/
|
||||
|
||||
flags = getreg32(priv->base + IMXRT_CAN_IMASK1_OFFSET);
|
||||
flags &= ~(IFLAG1_TX);
|
||||
putreg32(flags, priv->base + IMXRT_CAN_IMASK1_OFFSET);
|
||||
modifyreg32(priv->base + IMXRT_CAN_IMASK1_OFFSET, IFLAG1_TX, 0);
|
||||
work_queue(CANWORK, &priv->irqwork, imxrt_txdone_work, priv, 0);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user