From cfd4f943da82d0f4f75572f17de292738d0eefc5 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 18 Aug 2015 11:56:07 -0600 Subject: [PATCH] SAMV7 MCAN: When bitrate is changed, the MCAN has to be reset and there are lots of issues related to getting back to a healthy state if there is multithreaded access to the MCAN device. This commit handles a few of those issues, but there are more --- arch/arm/src/samv7/sam_mcan.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/samv7/sam_mcan.c b/arch/arm/src/samv7/sam_mcan.c index a94b1fea02d..45acfe49721 100755 --- a/arch/arm/src/samv7/sam_mcan.c +++ b/arch/arm/src/samv7/sam_mcan.c @@ -2110,6 +2110,15 @@ static void mcan_reset(FAR struct can_dev_s *dev) mcan_putreg(priv, SAM_MCAN_IE_OFFSET, 0); mcan_putreg(priv, SAM_MCAN_TXBTIE_OFFSET, 0); + /* Make sure that all buffers are released. + * + * REVISIT: What if a thread is waiting for a buffer? The following + * will not wake up any waiting threads. + */ + + sem_destroy(&priv->txfsem); + sem_init(&priv->txfsem, 0, config->ntxfifoq); + /* Disable peripheral clocking to the MCAN controller */ sam_disableperiph1(priv->config->pid); @@ -2403,6 +2412,12 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) * is returned with the errno variable set to indicate the * nature of the error. * Dependencies: None + * + * REVISIT: There is probably a limitation here: If there are multiple + * threads trying to send CAN packets, when one of these threads reconfigures + * the bitrate, the MCAN hardware will be reset and the context of operation + * will be lost. Hence, this IOCTL can only safely be executed in quiescent + * time periods. */ case CANIOC_SET_BITTIMING: @@ -2415,7 +2430,7 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) uint32_t tseg2; uint32_t sjw; uint32_t ie; - uint8_t state; + uint8_t state; DEBUGASSERT(bt != NULL); DEBUGASSERT(bt->bt_baud < SAMV7_MCANCLK_FREQUENCY); @@ -2461,11 +2476,14 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg) /* We we have successfully re-initialized, then restore the * interrupt state. + * + * REVISIT: Since the hardware was reset, any pending TX + * activity was lost. Should we disable TX interrupts? */ if (ret == OK) { - mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie); + mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie & ~priv->txints); } irqrestore(flags);