aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-03-13 10:12:37 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-03-13 10:12:37 +0000
commitcc7f8758b011d78a00ac2a143e780d101af59bc4 (patch)
treeab10145c4169f765303f40171130c986b2f7e458 /os/hal
parentef809b45c0178be455f3c98c1889dbc7913fc307 (diff)
downloadChibiOS-cc7f8758b011d78a00ac2a143e780d101af59bc4.tar.gz
ChibiOS-cc7f8758b011d78a00ac2a143e780d101af59bc4.tar.bz2
ChibiOS-cc7f8758b011d78a00ac2a143e780d101af59bc4.zip
Simplified CAN state machine.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7766 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/dox/can.dox3
-rw-r--r--os/hal/ports/STM32/LLD/can_lld.c5
-rw-r--r--os/hal/src/can.c35
3 files changed, 22 insertions, 21 deletions
diff --git a/os/hal/dox/can.dox b/os/hal/dox/can.dox
index 6c39a52b3..234cb2dc6 100644
--- a/os/hal/dox/can.dox
+++ b/os/hal/dox/can.dox
@@ -48,10 +48,9 @@
stop -> stop [label="\ncanStop()"];
stop -> ready [label="\ncanStart()\n(fast implementation)"];
stop -> starting [label="\ncanStart()\n(slow implementation)"];
- starting -> starting [label="\ncanStart()\n(other thread)"];
starting -> ready [label="\ninitialization complete\n(all threads)"];
ready -> stop [label="\ncanStop()"];
- ready -> ready [label="\ncanStart()\ncanReceive()\ncanTransmit()"];
+ ready -> ready [label="\ncanReceive()\ncanTransmit()"];
ready -> sleep [label="\ncanSleep()"];
sleep -> sleep [label="\ncanSleep()"];
sleep -> ready [label="\ncanWakeup()"];
diff --git a/os/hal/ports/STM32/LLD/can_lld.c b/os/hal/ports/STM32/LLD/can_lld.c
index 06294ab26..44cb95281 100644
--- a/os/hal/ports/STM32/LLD/can_lld.c
+++ b/os/hal/ports/STM32/LLD/can_lld.c
@@ -429,14 +429,11 @@ void can_lld_start(CANDriver *canp) {
}
#endif
- /* Entering initialization mode. */
- canp->state = CAN_STARTING;
+ /* Configuring CAN. */
canp->can->MCR = CAN_MCR_INRQ;
while ((canp->can->MSR & CAN_MSR_INAK) == 0)
osalThreadSleepS(1);
- /* BTR initialization.*/
canp->can->BTR = canp->config->btr;
- /* MCR initialization.*/
canp->can->MCR = canp->config->mcr;
/* Interrupt sources initialization.*/
diff --git a/os/hal/src/can.c b/os/hal/src/can.c
index 08cdd5172..f6ef7011f 100644
--- a/os/hal/src/can.c
+++ b/os/hal/src/can.c
@@ -85,9 +85,9 @@ void canObjectInit(CANDriver *canp) {
/**
* @brief Configures and activates the CAN peripheral.
- * @note Activating the CAN bus can be a slow operation this this function
- * is not atomic, it waits internally for the initialization to
- * complete.
+ * @note Activating the CAN bus can be a slow operation.
+ * @note Unlike other drivers it is not possible to restart the CAN
+ * driver without first stopping it using canStop().
*
* @param[in] canp pointer to the @p CANDriver object
* @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);
osalSysLock();
- osalDbgAssert((canp->state == CAN_STOP) ||
- (canp->state == CAN_STARTING) ||
- (canp->state == CAN_READY),
- "invalid state");
- while (canp->state == CAN_STARTING) {
- osalThreadSleepS((systime_t)1);
- }
- if (canp->state == CAN_STOP) {
- canp->config = config;
- can_lld_start(canp);
- canp->state = CAN_READY;
- }
+ osalDbgAssert(canp->state == CAN_STOP, "invalid state");
+
+ /* Entering initialization mode. */
+ canp->state = CAN_STARTING;
+ canp->config = config;
+
+ /* Low level initialization, could be a slow process and sleeps could
+ be performed inside.*/
+ can_lld_start(canp);
+
+ /* The driver finally goes into the ready state.*/
+ canp->state = CAN_READY;
osalSysUnlock();
}
@@ -129,8 +129,13 @@ void canStop(CANDriver *canp) {
osalSysLock();
osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY),
"invalid state");
+
+ /* The low level driver is stopped.*/
can_lld_stop(canp);
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->txqueue, MSG_RESET);
osalOsRescheduleS();