Simplified CAN state machine.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7766 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2015-03-13 10:12:37 +00:00
parent ef809b45c0
commit cc7f8758b0
3 changed files with 22 additions and 21 deletions

View File

@ -48,10 +48,9 @@
stop -> stop [label="\ncanStop()"]; stop -> stop [label="\ncanStop()"];
stop -> ready [label="\ncanStart()\n(fast implementation)"]; stop -> ready [label="\ncanStart()\n(fast implementation)"];
stop -> starting [label="\ncanStart()\n(slow implementation)"]; stop -> starting [label="\ncanStart()\n(slow implementation)"];
starting -> starting [label="\ncanStart()\n(other thread)"];
starting -> ready [label="\ninitialization complete\n(all threads)"]; starting -> ready [label="\ninitialization complete\n(all threads)"];
ready -> stop [label="\ncanStop()"]; ready -> stop [label="\ncanStop()"];
ready -> ready [label="\ncanStart()\ncanReceive()\ncanTransmit()"]; ready -> ready [label="\ncanReceive()\ncanTransmit()"];
ready -> sleep [label="\ncanSleep()"]; ready -> sleep [label="\ncanSleep()"];
sleep -> sleep [label="\ncanSleep()"]; sleep -> sleep [label="\ncanSleep()"];
sleep -> ready [label="\ncanWakeup()"]; sleep -> ready [label="\ncanWakeup()"];

View File

@ -429,14 +429,11 @@ void can_lld_start(CANDriver *canp) {
} }
#endif #endif
/* Entering initialization mode. */ /* Configuring CAN. */
canp->state = CAN_STARTING;
canp->can->MCR = CAN_MCR_INRQ; canp->can->MCR = CAN_MCR_INRQ;
while ((canp->can->MSR & CAN_MSR_INAK) == 0) while ((canp->can->MSR & CAN_MSR_INAK) == 0)
osalThreadSleepS(1); osalThreadSleepS(1);
/* BTR initialization.*/
canp->can->BTR = canp->config->btr; canp->can->BTR = canp->config->btr;
/* MCR initialization.*/
canp->can->MCR = canp->config->mcr; canp->can->MCR = canp->config->mcr;
/* Interrupt sources initialization.*/ /* Interrupt sources initialization.*/

View File

@ -85,9 +85,9 @@ void canObjectInit(CANDriver *canp) {
/** /**
* @brief Configures and activates the CAN peripheral. * @brief Configures and activates the CAN peripheral.
* @note Activating the CAN bus can be a slow operation this this function * @note Activating the CAN bus can be a slow operation.
* is not atomic, it waits internally for the initialization to * @note Unlike other drivers it is not possible to restart the CAN
* complete. * driver without first stopping it using canStop().
* *
* @param[in] canp pointer to the @p CANDriver object * @param[in] canp pointer to the @p CANDriver object
* @param[in] config pointer to the @p CANConfig object. Depending on * @param[in] config pointer to the @p CANConfig object. Depending on
@ -100,18 +100,18 @@ void canStart(CANDriver *canp, const CANConfig *config) {
osalDbgCheck(canp != NULL); osalDbgCheck(canp != NULL);
osalSysLock(); osalSysLock();
osalDbgAssert((canp->state == CAN_STOP) || osalDbgAssert(canp->state == CAN_STOP, "invalid state");
(canp->state == CAN_STARTING) ||
(canp->state == CAN_READY), /* Entering initialization mode. */
"invalid state"); canp->state = CAN_STARTING;
while (canp->state == CAN_STARTING) { canp->config = config;
osalThreadSleepS((systime_t)1);
} /* Low level initialization, could be a slow process and sleeps could
if (canp->state == CAN_STOP) { be performed inside.*/
canp->config = config; can_lld_start(canp);
can_lld_start(canp);
canp->state = CAN_READY; /* The driver finally goes into the ready state.*/
} canp->state = CAN_READY;
osalSysUnlock(); osalSysUnlock();
} }
@ -129,8 +129,13 @@ void canStop(CANDriver *canp) {
osalSysLock(); osalSysLock();
osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY),
"invalid state"); "invalid state");
/* The low level driver is stopped.*/
can_lld_stop(canp); can_lld_stop(canp);
canp->state = CAN_STOP; canp->state = CAN_STOP;
/* Threads waiting on CAN APIs are notified that the driver has been
stopped in order to not have stuck threads.*/
osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET); osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET);
osalThreadDequeueAllI(&canp->txqueue, MSG_RESET); osalThreadDequeueAllI(&canp->txqueue, MSG_RESET);
osalOsRescheduleS(); osalOsRescheduleS();