Detailed Description

Generic CAN Driver.

This module implements a generic CAN (Controller Area Network) driver allowing the exchange of information at frame level.

Precondition:
In order to use the CAN driver the HAL_USE_CAN option must be enabled in halconf.h.

Driver State Machine

The driver implements a state machine internally, not all the driver functionalities can be used in any moment,

any transition not explicitly shown in the following diagram has to be considered an error and shall be captured by an assertion (if enabled).

 /*
00002 ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
00003
00004 Licensed under the Apache License, Version 2.0 (the "License");
00005 you may not use this file except in compliance with the License.
00006 You may obtain a copy of the License at
00007
00008 http://www.apache.org/licenses/LICENSE-2.0
00009
00010 Unless required by applicable law or agreed to in writing, software
00011 distributed under the License is distributed on an "AS IS" BASIS,
00012 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 See the License for the specific language governing permissions and
00014 limitations under the License.
00015 */ /**
00018 * @file templates/can_lld.h
00019 * @brief CAN Driver subsystem low level driver header template.
00020 *
00021 * @addtogroup CAN
00022 * @{
00023 */ #ifndef _CAN_LLD_H_
#define _CAN_LLD_H_ #if HAL_USE_CAN || defined(__DOXYGEN__) /*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/ /**
00035 * @brief This switch defines whether the driver implementation supports
00036 * a low power switch mode with automatic an wakeup feature.
00037 */
#define CAN_SUPPORTS_SLEEP TRUE /**
00041 * @brief This implementation supports three transmit mailboxes.
00042 */
#define CAN_TX_MAILBOXES 3 /**
00046 * @brief This implementation supports two receive mailboxes.
00047 */
#define CAN_RX_MAILBOXES 2 /*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/ /**
00055 * @name Configuration options
00056 * @{
00057 */
/**
00059 * @brief CAN1 driver enable switch.
00060 * @details If set to @p TRUE the support for CAN1 is included.
00061 */
#if !defined(PLATFORM_CAN_USE_CAN1) || defined(__DOXYGEN__)
#define PLATFORM_CAN_USE_CAN1 FALSE
#endif
/** @} */ /*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/ #if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP
#error "CAN sleep mode not supported in this architecture"
#endif /*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/ /**
00080 * @brief Type of a transmission mailbox index.
00081 */
typedef uint32_t canmbx_t; /**
00085 * @brief CAN transmission frame.
00086 * @note Accessing the frame data as word16 or word32 is not portable because
00087 * machine data endianness, it can be still useful for a quick filling.
00088 */
typedef struct {
struct {
uint8_t DLC:; /**< @brief Data length. */
uint8_t RTR:; /**< @brief Frame type. */
uint8_t IDE:; /**< @brief Identifier type. */
};
union {
struct {
uint32_t SID:; /**< @brief Standard identifier.*/
};
struct {
uint32_t EID:; /**< @brief Extended identifier.*/
};
};
union {
uint8_t data8[]; /**< @brief Frame data. */
uint16_t data16[]; /**< @brief Frame data. */
uint32_t data32[]; /**< @brief Frame data. */
};
} CANTxFrame; /**
00111 * @brief CAN received frame.
00112 * @note Accessing the frame data as word16 or word32 is not portable because
00113 * machine data endianness, it can be still useful for a quick filling.
00114 */
typedef struct {
struct {
uint8_t DLC:; /**< @brief Data length. */
uint8_t RTR:; /**< @brief Frame type. */
uint8_t IDE:; /**< @brief Identifier type. */
};
union {
struct {
uint32_t SID:; /**< @brief Standard identifier.*/
};
struct {
uint32_t EID:; /**< @brief Extended identifier.*/
};
};
union {
uint8_t data8[]; /**< @brief Frame data. */
uint16_t data16[]; /**< @brief Frame data. */
uint32_t data32[]; /**< @brief Frame data. */
};
} CANRxFrame; /**
00137 * @brief CAN filter.
00138 * @note Implementations may extend this structure to contain more,
00139 * architecture dependent, fields.
00140 * @note It could not be present on some architectures.
00141 */
typedef struct {
uint32_t dummy;
} CANFilter; /**
00147 * @brief Driver configuration structure.
00148 * @note Implementations may extend this structure to contain more,
00149 * architecture dependent, fields.
00150 * @note It could be empty on some architectures.
00151 */
typedef struct {
uint32_t dummy;
} CANConfig; /**
00157 * @brief Structure representing an CAN driver.
00158 */
typedef struct {
/**
00161 * @brief Driver state.
00162 */
canstate_t state;
/**
00165 * @brief Current configuration data.
00166 */
const CANConfig *config;
/**
00169 * @brief Transmission queue semaphore.
00170 */
Semaphore txsem;
/**
00173 * @brief Receive queue semaphore.
00174 */
Semaphore rxsem;
/**
00177 * @brief One or more frames become available.
00178 * @note After broadcasting this event it will not be broadcasted again
00179 * until the received frames queue has been completely emptied. It
00180 * is <b>not</b> broadcasted for each received frame. It is
00181 * responsibility of the application to empty the queue by
00182 * repeatedly invoking @p chReceive() when listening to this event.
00183 * This behavior minimizes the interrupt served by the system
00184 * because CAN traffic.
00185 * @note The flags associated to the listeners will indicate which
00186 * receive mailboxes become non-empty.
00187 */
EventSource rxfull_event;
/**
00190 * @brief One or more transmission mailbox become available.
00191 * @note The flags associated to the listeners will indicate which
00192 * transmit mailboxes become empty.
00193 *
00194 */
EventSource txempty_event;
/**
00197 * @brief A CAN bus error happened.
00198 * @note The flags associated to the listeners will indicate the
00199 * error(s) that have occurred.
00200 */
EventSource error_event;
#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
/**
00204 * @brief Entering sleep state event.
00205 */
EventSource sleep_event;
/**
00208 * @brief Exiting sleep state event.
00209 */
EventSource wakeup_event;
#endif /* CAN_USE_SLEEP_MODE */
/* End of the mandatory fields.*/
} CANDriver; /*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/ /*===========================================================================*/
/* External declarations. */
/*===========================================================================*/ #if PLATFORM_CAN_USE_CAN1 && !defined(__DOXYGEN__)
extern CANDriver CAND1;
#endif #ifdef __cplusplus
extern "C" {
#endif
void can_lld_init(void);
void can_lld_start(CANDriver *canp);
void can_lld_stop(CANDriver *canp);
bool_t can_lld_is_tx_empty(CANDriver *canp,
canmbx_t mailbox);
void can_lld_transmit(CANDriver *canp,
canmbx_t mailbox,
const CANTxFrame *crfp);
bool_t can_lld_is_rx_nonempty(CANDriver *canp,
canmbx_t mailbox);
void can_lld_receive(CANDriver *canp,
canmbx_t mailbox,
CANRxFrame *ctfp);
#if CAN_USE_SLEEP_MODE
void can_lld_sleep(CANDriver *canp);
void can_lld_wakeup(CANDriver *canp);
#endif /* CAN_USE_SLEEP_MODE */
#ifdef __cplusplus
}
#endif #endif /* HAL_USE_CAN */ #endif /* _CAN_LLD_H_ */ /** @} */
 /*
00002 ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
00003
00004 Licensed under the Apache License, Version 2.0 (the "License");
00005 you may not use this file except in compliance with the License.
00006 You may obtain a copy of the License at
00007
00008 http://www.apache.org/licenses/LICENSE-2.0
00009
00010 Unless required by applicable law or agreed to in writing, software
00011 distributed under the License is distributed on an "AS IS" BASIS,
00012 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 See the License for the specific language governing permissions and
00014 limitations under the License.
00015 */ /**
00018 * @file templates/can_lld.c
00019 * @brief CAN Driver subsystem low level driver source template.
00020 *
00021 * @addtogroup CAN
00022 * @{
00023 */ #include "ch.h"
#include "hal.h" #if HAL_USE_CAN || defined(__DOXYGEN__) /*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/ /*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/ /**
00039 * @brief CAN1 driver identifier.
00040 */
#if PLATFORM_CAN_USE_CAN1 || defined(__DOXYGEN__)
CANDriver CAND1;
#endif /*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/ /*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/ /*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/ /*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/ /**
00062 * @brief Low level CAN driver initialization.
00063 *
00064 * @notapi
00065 */
void can_lld_init(void) { #if PLATFORM_CAN_USE_CAN1
/* Driver initialization.*/
canObjectInit(&CAND1);
#endif /* PLATFORM_CAN_USE_CAN1 */
} /**
00075 * @brief Configures and activates the CAN peripheral.
00076 *
00077 * @param[in] canp pointer to the @p CANDriver object
00078 *
00079 * @notapi
00080 */
void can_lld_start(CANDriver *canp) { if (canp->state == CAN_STOP) {
/* Enables the peripheral.*/
#if PLATFORM_CAN_USE_CAN1
if (&CAND1 == canp) { }
#endif /* PLATFORM_CAN_USE_CAN1 */
}
/* Configures the peripheral.*/ } /**
00096 * @brief Deactivates the CAN peripheral.
00097 *
00098 * @param[in] canp pointer to the @p CANDriver object
00099 *
00100 * @notapi
00101 */
void can_lld_stop(CANDriver *canp) { if (canp->state == CAN_READY) {
/* Resets the peripheral.*/ /* Disables the peripheral.*/
#if PLATFORM_CAN_USE_CAN1
if (&CAND1 == canp) { }
#endif /* PLATFORM_CAN_USE_CAN1 */
}
} /**
00117 * @brief Determines whether a frame can be transmitted.
00118 *
00119 * @param[in] canp pointer to the @p CANDriver object
00120 * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00121 *
00122 * @return The queue space availability.
00123 * @retval FALSE no space in the transmit queue.
00124 * @retval TRUE transmit slot available.
00125 *
00126 * @notapi
00127 */
bool_t can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { (void)canp; switch (mailbox) {
case CAN_ANY_MAILBOX:
return FALSE;
case :
return FALSE;
case :
return FALSE;
case :
return FALSE;
default:
return FALSE;
}
} /**
00147 * @brief Inserts a frame into the transmit queue.
00148 *
00149 * @param[in] canp pointer to the @p CANDriver object
00150 * @param[in] ctfp pointer to the CAN frame to be transmitted
00151 * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00152 *
00153 * @notapi
00154 */
void can_lld_transmit(CANDriver *canp,
canmbx_t mailbox,
const CANTxFrame *ctfp) { (void)canp;
(void)mailbox;
(void)ctfp; } /**
00166 * @brief Determines whether a frame has been received.
00167 *
00168 * @param[in] canp pointer to the @p CANDriver object
00169 * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00170 *
00171 * @return The queue space availability.
00172 * @retval FALSE no space in the transmit queue.
00173 * @retval TRUE transmit slot available.
00174 *
00175 * @notapi
00176 */
bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { (void)canp;
(void)mailbox; switch (mailbox) {
case CAN_ANY_MAILBOX:
return FALSE;
case :
return FALSE;
case :
return FALSE;
default:
return FALSE;
}
} /**
00195 * @brief Receives a frame from the input queue.
00196 *
00197 * @param[in] canp pointer to the @p CANDriver object
00198 * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00199 * @param[out] crfp pointer to the buffer where the CAN frame is copied
00200 *
00201 * @notapi
00202 */
void can_lld_receive(CANDriver *canp,
canmbx_t mailbox,
CANRxFrame *crfp) { (void)canp;
(void)mailbox;
(void)crfp; } #if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
/**
00215 * @brief Enters the sleep mode.
00216 *
00217 * @param[in] canp pointer to the @p CANDriver object
00218 *
00219 * @notapi
00220 */
void can_lld_sleep(CANDriver *canp) { (void)canp; } /**
00228 * @brief Enforces leaving the sleep mode.
00229 *
00230 * @param[in] canp pointer to the @p CANDriver object
00231 *
00232 * @notapi
00233 */
void can_lld_wakeup(CANDriver *canp) { (void)canp; }
#endif /* CAN_USE_SLEEP_MODE */ #endif /* HAL_USE_CAN */ /** @} */
 /*
00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003 2011,2012,2013 Giovanni Di Sirio.
00004
00005 This file is part of ChibiOS/RT.
00006
00007 ChibiOS/RT is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 3 of the License, or
00010 (at your option) any later version.
00011
00012 ChibiOS/RT is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015 GNU General Public License for more details.
00016
00017 You should have received a copy of the GNU General Public License
00018 along with this program. If not, see <http://www.gnu.org/licenses/>.
00019
00020 ---
00021
00022 A special exception to the GPL can be applied should you wish to distribute
00023 a combined work that includes ChibiOS/RT, without being obliged to provide
00024 the source code for any proprietary components. See the file exception.txt
00025 for full details of how and when the exception can be applied.
00026 */ /**
00029 * @file can.h
00030 * @brief CAN Driver macros and structures.
00031 *
00032 * @addtogroup CAN
00033 * @{
00034 */ #ifndef _CAN_H_
#define _CAN_H_ #if HAL_USE_CAN || defined(__DOXYGEN__) /*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/ /**
00046 * @name CAN status flags
00047 * @{
00048 */
/**
00050 * @brief Errors rate warning.
00051 */
#define CAN_LIMIT_WARNING 1
/**
00054 * @brief Errors rate error.
00055 */
#define CAN_LIMIT_ERROR 2
/**
00058 * @brief Bus off condition reached.
00059 */
#define CAN_BUS_OFF_ERROR 4
/**
00062 * @brief Framing error of some kind on the CAN bus.
00063 */
#define CAN_FRAMING_ERROR 8
/**
00066 * @brief Overflow in receive queue.
00067 */
#define CAN_OVERFLOW_ERROR 16
/** @} */ /**
00072 * @brief Special mailbox identifier.
00073 */
#define CAN_ANY_MAILBOX 0 /*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/ /**
00081 * @name CAN configuration options
00082 * @{
00083 */
/**
00085 * @brief Sleep mode related APIs inclusion switch.
00086 * @details This option can only be enabled if the CAN implementation supports
00087 * the sleep mode, see the macro @p CAN_SUPPORTS_SLEEP exported by
00088 * the underlying implementation.
00089 */
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
/** @} */ /*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/ #if !CH_USE_SEMAPHORES || !CH_USE_EVENTS
#error "CAN driver requires CH_USE_SEMAPHORES and CH_USE_EVENTS"
#endif /*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/ /**
00108 * @brief Driver state machine possible states.
00109 */
typedef enum {
CAN_UNINIT = , /**< Not initialized. */
CAN_STOP = , /**< Stopped. */
CAN_STARTING = , /**< Starting. */
CAN_READY = , /**< Ready. */
CAN_SLEEP = /**< Sleep state. */
} canstate_t; #include "can_lld.h" /*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/ /**
00125 * @name Macro Functions
00126 * @{
00127 */
/**
00129 * @brief Converts a mailbox index to a bit mask.
00130 */
#define CAN_MAILBOX_TO_MASK(mbx) (1 << ((mbx) - 1))
/** @} */ /*===========================================================================*/
/* External declarations. */
/*===========================================================================*/ #ifdef __cplusplus
extern "C" {
#endif
void canInit(void);
void canObjectInit(CANDriver *canp);
void canStart(CANDriver *canp, const CANConfig *config);
void canStop(CANDriver *canp);
msg_t canTransmit(CANDriver *canp,
canmbx_t mailbox,
const CANTxFrame *ctfp,
systime_t timeout);
msg_t canReceive(CANDriver *canp,
canmbx_t mailbox,
CANRxFrame *crfp,
systime_t timeout);
#if CAN_USE_SLEEP_MODE
void canSleep(CANDriver *canp);
void canWakeup(CANDriver *canp);
#endif /* CAN_USE_SLEEP_MODE */
#ifdef __cplusplus
}
#endif #endif /* HAL_USE_CAN */ #endif /* _CAN_H_ */ /** @} */
 /*
00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003 2011,2012,2013 Giovanni Di Sirio.
00004
00005 This file is part of ChibiOS/RT.
00006
00007 ChibiOS/RT is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 3 of the License, or
00010 (at your option) any later version.
00011
00012 ChibiOS/RT is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015 GNU General Public License for more details.
00016
00017 You should have received a copy of the GNU General Public License
00018 along with this program. If not, see <http://www.gnu.org/licenses/>.
00019
00020 ---
00021
00022 A special exception to the GPL can be applied should you wish to distribute
00023 a combined work that includes ChibiOS/RT, without being obliged to provide
00024 the source code for any proprietary components. See the file exception.txt
00025 for full details of how and when the exception can be applied.
00026 */ /**
00029 * @file can.c
00030 * @brief CAN Driver code.
00031 *
00032 * @addtogroup CAN
00033 * @{
00034 */ #include "ch.h"
#include "hal.h" #if HAL_USE_CAN || defined(__DOXYGEN__) /*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/ /*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/ /*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/ /*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/ /*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/ /**
00062 * @brief CAN Driver initialization.
00063 * @note This function is implicitly invoked by @p halInit(), there is
00064 * no need to explicitly initialize the driver.
00065 *
00066 * @init
00067 */
void canInit(void) { can_lld_init();
} /**
00074 * @brief Initializes the standard part of a @p CANDriver structure.
00075 *
00076 * @param[out] canp pointer to the @p CANDriver object
00077 *
00078 * @init
00079 */
void canObjectInit(CANDriver *canp) { canp->state = CAN_STOP;
canp->config = NULL;
chSemInit(&canp->txsem, );
chSemInit(&canp->rxsem, );
chEvtInit(&canp->rxfull_event);
chEvtInit(&canp->txempty_event);
chEvtInit(&canp->error_event);
#if CAN_USE_SLEEP_MODE
chEvtInit(&canp->sleep_event);
chEvtInit(&canp->wakeup_event);
#endif /* CAN_USE_SLEEP_MODE */
} /**
00096 * @brief Configures and activates the CAN peripheral.
00097 * @note Activating the CAN bus can be a slow operation this this function
00098 * is not atomic, it waits internally for the initialization to
00099 * complete.
00100 *
00101 * @param[in] canp pointer to the @p CANDriver object
00102 * @param[in] config pointer to the @p CANConfig object. Depending on
00103 * the implementation the value can be @p NULL.
00104 *
00105 * @api
00106 */
void canStart(CANDriver *canp, const CANConfig *config) { chDbgCheck(canp != NULL, "canStart"); chSysLock();
chDbgAssert((canp->state == CAN_STOP) ||
(canp->state == CAN_STARTING) ||
(canp->state == CAN_READY),
"canStart(), #1", "invalid state");
while (canp->state == CAN_STARTING)
chThdSleepS();
if (canp->state == CAN_STOP) {
canp->config = config;
can_lld_start(canp);
canp->state = CAN_READY;
}
chSysUnlock();
} /**
00127 * @brief Deactivates the CAN peripheral.
00128 *
00129 * @param[in] canp pointer to the @p CANDriver object
00130 *
00131 * @api
00132 */
void canStop(CANDriver *canp) { chDbgCheck(canp != NULL, "canStop"); chSysLock();
chDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY),
"canStop(), #1", "invalid state");
can_lld_stop(canp);
canp->state = CAN_STOP;
chSemResetI(&canp->rxsem, );
chSemResetI(&canp->txsem, );
chSchRescheduleS();
chSysUnlock();
} /**
00149 * @brief Can frame transmission.
00150 * @details The specified frame is queued for transmission, if the hardware
00151 * queue is full then the invoking thread is queued.
00152 * @note Trying to transmit while in sleep mode simply enqueues the thread.
00153 *
00154 * @param[in] canp pointer to the @p CANDriver object
00155 * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00156 * @param[in] ctfp pointer to the CAN frame to be transmitted
00157 * @param[in] timeout the number of ticks before the operation timeouts,
00158 * the following special values are allowed:
00159 * - @a TIME_IMMEDIATE immediate timeout.
00160 * - @a TIME_INFINITE no timeout.
00161 * .
00162 * @return The operation result.
00163 * @retval RDY_OK the frame has been queued for transmission.
00164 * @retval RDY_TIMEOUT The operation has timed out.
00165 * @retval RDY_RESET The driver has been stopped while waiting.
00166 *
00167 * @api
00168 */
msg_t canTransmit(CANDriver *canp,
canmbx_t mailbox,
const CANTxFrame *ctfp,
systime_t timeout) { chDbgCheck((canp != NULL) && (ctfp != NULL) && (mailbox <= CAN_TX_MAILBOXES),
"canTransmit"); chSysLock();
chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
"canTransmit(), #1", "invalid state");
while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) {
msg_t msg = chSemWaitTimeoutS(&canp->txsem, timeout);
if (msg != RDY_OK) {
chSysUnlock();
return msg;
}
}
can_lld_transmit(canp, mailbox, ctfp);
chSysUnlock();
return RDY_OK;
} /**
00193 * @brief Can frame receive.
00194 * @details The function waits until a frame is received.
00195 * @note Trying to receive while in sleep mode simply enqueues the thread.
00196 *
00197 * @param[in] canp pointer to the @p CANDriver object
00198 * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
00199 * @param[out] crfp pointer to the buffer where the CAN frame is copied
00200 * @param[in] timeout the number of ticks before the operation timeouts,
00201 * the following special values are allowed:
00202 * - @a TIME_IMMEDIATE immediate timeout (useful in an
00203 * event driven scenario where a thread never blocks
00204 * for I/O).
00205 * - @a TIME_INFINITE no timeout.
00206 * .
00207 * @return The operation result.
00208 * @retval RDY_OK a frame has been received and placed in the buffer.
00209 * @retval RDY_TIMEOUT The operation has timed out.
00210 * @retval RDY_RESET The driver has been stopped while waiting.
00211 *
00212 * @api
00213 */
msg_t canReceive(CANDriver *canp,
canmbx_t mailbox,
CANRxFrame *crfp,
systime_t timeout) { chDbgCheck((canp != NULL) && (crfp != NULL) && (mailbox <= CAN_RX_MAILBOXES),
"canReceive"); chSysLock();
chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
"canReceive(), #1", "invalid state");
while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) {
msg_t msg = chSemWaitTimeoutS(&canp->rxsem, timeout);
if (msg != RDY_OK) {
chSysUnlock();
return msg;
}
}
can_lld_receive(canp, mailbox, crfp);
chSysUnlock();
return RDY_OK;
} #if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
/**
00239 * @brief Enters the sleep mode.
00240 * @details This function puts the CAN driver in sleep mode and broadcasts
00241 * the @p sleep_event event source.
00242 * @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must
00243 * be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported
00244 * by the low level driver.
00245 *
00246 * @param[in] canp pointer to the @p CANDriver object
00247 *
00248 * @api
00249 */
void canSleep(CANDriver *canp) { chDbgCheck(canp != NULL, "canSleep"); chSysLock();
chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
"canSleep(), #1", "invalid state");
if (canp->state == CAN_READY) {
can_lld_sleep(canp);
canp->state = CAN_SLEEP;
chEvtBroadcastI(&canp->sleep_event);
chSchRescheduleS();
}
chSysUnlock();
} /**
00267 * @brief Enforces leaving the sleep mode.
00268 * @note The sleep mode is supposed to be usually exited automatically by
00269 * an hardware event.
00270 *
00271 * @param[in] canp pointer to the @p CANDriver object
00272 */
void canWakeup(CANDriver *canp) { chDbgCheck(canp != NULL, "canWakeup"); chSysLock();
chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
"canWakeup(), #1", "invalid state");
if (canp->state == CAN_SLEEP) {
can_lld_wakeup(canp);
canp->state = CAN_READY;
chEvtBroadcastI(&canp->wakeup_event);
chSchRescheduleS();
}
chSysUnlock();
}
#endif /* CAN_USE_SLEEP_MODE */ #endif /* HAL_USE_CAN */ /** @} */

void canInit(void )

CAN Driver initialization.

Note:
This function is implicitly invoked by halInit(), there is no need to explicitly initialize the driver.
Function Class:
Initializer, this function just initializes an object and can be invoked before the kernel is initialized.

Here is the call graph for this function:

void canObjectInit ( CANDriver * canp )

Initializes the standard part of a CANDriver structure.

Function Class:
Initializer, this function just initializes an object and can be invoked before the kernel is initialized.
 
void canStart ( CANDriver * canp, const CANConfig * config )

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.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

void canStop ( CANDriver * canp )

Deactivates the CAN peripheral.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

msg_t canTransmit ( CANDriver * canp, canmbx_t mailbox, const CANTxFrame * ctfp, systime_t timeout )

Can frame transmission.

The specified frame is queued for transmission, if the hardware queue is full then the invoking thread is queued.

Note:
Trying to transmit while in sleep mode simply enqueues the thread.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

msg_t canReceive ( CANDriver * canp, canmbx_t mailbox, CANRxFrame * crfp, systime_t timeout )

Can frame receive.

The function waits until a frame is received.

Note:
Trying to receive while in sleep mode simply enqueues the thread.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

void canSleep ( CANDriver * canp )

Enters the sleep mode.

This function puts the CAN driver in sleep mode and broadcasts the sleep_event event source.

Precondition:
In order to use this function the option CAN_USE_SLEEP_MODE must be enabled
and the CAN_SUPPORTS_SLEEP mode must be supported by the low level driver.

Function Class:Normal API, this function can be invoked by regular system threads but not from within a lock zone.

void canWakeup ( CANDriver * canp )

Enforces leaving the sleep mode.

Note:
The sleep mode is supposed to be usually exited automatically by an hardware event.
/**
* This switch defines whether the driver implementation supports
* a low power switch mode with automatic an wakeup feature.
*/
#define CAN_SUPPORTS_SLEEP TRUE /**
* This implementation supports three transmit mailboxes.
*/
#define CAN_TX_MAILBOXES 3 /**
* This implementation supports two receive mailboxes.
*/
#define CAN_RX_MAILBOXES 2 /*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/ /**
* @name Configuration options
* @{
*/
/**
* CAN1 driver enable switch.
* @details If set to @p TRUE the support for CAN1 is included.
*/
#if !defined(PLATFORM_CAN_USE_CAN1) || defined(__DOXYGEN__)
#define PLATFORM_CAN_USE_CAN1 FALSE
#endif /*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/ #if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP
#error "CAN sleep mode not supported in this architecture"
#endif /*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/ /**
* Type of a transmission mailbox index.
*/
typedef uint32_t canmbx_t; /**
* CAN transmission frame.
* @note Accessing the frame data as word16 or word32 is not portable because
* machine data endianness, it can be still useful for a quick filling.
*/
typedef struct
{
struct
{
uint8_t DLC :; /**< @brief Data length. */
uint8_t RTR :; /**< @brief Frame type. */
uint8_t IDE :; /**< @brief Identifier type. */
};
union
{
struct
{
uint32_t SID :; /**< @brief Standard identifier.*/
};
struct
{
uint32_t EID :; /**< @brief Extended identifier.*/
};
};
union
{
uint8_t data8[ ]; /**< @brief Frame data. */
uint16_t data16[ ]; /**< @brief Frame data. */
uint32_t data32[ ]; /**< @brief Frame data. */
};
} CANTxFrame; /**
* CAN received frame.
* @note Accessing the frame data as word16 or word32 is not portable because
* machine data endianness, it can be still useful for a quick filling.
*/
typedef struct
{
struct
{
uint8_t DLC :; /**< @brief Data length. */
uint8_t RTR :; /**< @brief Frame type. */
uint8_t IDE :; /**< @brief Identifier type. */
};
union
{
struct
{
uint32_t SID :; /**< @brief Standard identifier.*/
};
struct
{
uint32_t EID :; /**< @brief Extended identifier.*/
};
};
union
{
uint8_t data8[ ]; /**< @brief Frame data. */
uint16_t data16[ ]; /**< @brief Frame data. */
uint32_t data32[ ]; /**< @brief Frame data. */
};
} CANRxFrame; /**
* CAN filter.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
* @note It could not be present on some architectures.
*/
typedef struct
{
uint32_t dummy;
} CANFilter; /**
* Driver configuration structure.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
* @note It could be empty on some architectures.
*/
typedef struct
{
uint32_t dummy;
} CANConfig; /**
* Structure representing an CAN driver.
*/
typedef struct
{
/**
* Driver state.
*/
canstate_t state;
/**
* Current configuration data.
*/
const CANConfig *config;
/**
* Transmission queue semaphore.
*/
Semaphore txsem;
/**
* Receive queue semaphore.
*/
Semaphore rxsem;
/**
* One or more frames become available.
* @note After broadcasting this event it will not be broadcasted again
* until the received frames queue has been completely emptied. It
* is <b>not</b> broadcasted for each received frame. It is
* responsibility of the application to empty the queue by
* repeatedly invoking @p chReceive() when listening to this event.
* This behavior minimizes the interrupt served by the system
* because CAN traffic.
* @note The flags associated to the listeners will indicate which
* receive mailboxes become non-empty.
*/
EventSource rxfull_event;
/**
* One or more transmission mailbox become available.
* @note The flags associated to the listeners will indicate which
* transmit mailboxes become empty.
*
*/
EventSource txempty_event;
/**
* A CAN bus error happened.
* @note The flags associated to the listeners will indicate the
* error(s) that have occurred.
*/
EventSource error_event;
/**
* Entering sleep state event.
*/
EventSource sleep_event;
/**
* Exiting sleep state event.
*/
EventSource wakeup_event;
/* End of the mandatory fields.*/
} CANDriver; extern CANDriver CAND1;
void can_lld_init( void );
void can_lld_start( CANDriver *canp );
void can_lld_stop( CANDriver *canp );
uiknt32_t can_lld_is_tx_empty( CANDriver *canp, canmbx_t mailbox );
void can_lld_transmit( CANDriver *canp, canmbx_t mailbox,
const CANTxFrame *crfp );
uiknt32_t can_lld_is_rx_nonempty( CANDriver *canp, canmbx_t mailbox );
void can_lld_receive( CANDriver *canp, canmbx_t mailbox, CANRxFrame *ctfp );
void can_lld_sleep( CANDriver *canp );
void can_lld_wakeup( CANDriver *canp ); /**
* @file templates/can_lld.c
* CAN Driver subsystem low level driver source template.
*
* @addtogroup CAN
* @{
*/ /**
* CAN1 driver identifier.
*/
CANDriver CAND1; /**
* Low level CAN driver initialization.
*
* @notapi
*/
void can_lld_init( void )
{
/* Driver initialization.*/
canObjectInit( &CAND1 );
} /**
* Configures and activates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
void can_lld_start( CANDriver *canp )
{
if ( canp->state == CAN_STOP )
{
/* Enables the peripheral.*/
if ( &CAND1 == canp )
{
}
}
/* Configures the peripheral.*/ } /**
* Deactivates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
void can_lld_stop( CANDriver *canp )
{
if ( canp->state == CAN_READY )
{
/* Resets the peripheral.*/
/* Disables the peripheral.*/
if ( &CAND1 == canp )
{
}
}
} /**
* Determines whether a frame can be transmitted.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
*
* @return The queue space availability.
* @retval FALSE no space in the transmit queue.
* @retval TRUE transmit slot available.
*
* @notapi
*/
uiknt32_t can_lld_is_tx_empty( CANDriver *canp, canmbx_t mailbox )
{
(void) canp;
switch ( mailbox )
{
case CAN_ANY_MAILBOX:
return FALSE;
case :
return FALSE;
case :
return FALSE;
case :
return FALSE;
default:
return FALSE;
}
} /**
* Inserts a frame into the transmit queue.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] ctfp pointer to the CAN frame to be transmitted
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
*
* @notapi
*/
void can_lld_transmit( CANDriver *canp, canmbx_t mailbox,
const CANTxFrame *ctfp )
{
(void) canp;
(void) mailbox;
(void) ctfp; } /**
* Determines whether a frame has been received.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
*
* @return The queue space availability.
* @retval FALSE no space in the transmit queue.
* @retval TRUE transmit slot available.
*
* @notapi
*/
uiknt32_t can_lld_is_rx_nonempty( CANDriver *canp, canmbx_t mailbox )
{
(void) canp;
(void) mailbox; switch ( mailbox )
{
case CAN_ANY_MAILBOX:
return FALSE;
case :
return FALSE;
case :
return FALSE;
default:
return FALSE;
}
} /**
* Receives a frame from the input queue.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
* @param[out] crfp pointer to the buffer where the CAN frame is copied
*
* @notapi
*/
void can_lld_receive( CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp )
{
(void) canp;
(void) mailbox;
(void) crfp;
} /**
* Enters the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
void can_lld_sleep( CANDriver *canp )
{
(void) canp;
} /**
* Enforces leaving the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
void can_lld_wakeup( CANDriver *canp )
{
(void) canp; } /**
* @name CAN status flags
* @{
*/
/**
* Errors rate warning.
*/
#define CAN_LIMIT_WARNING 1
/**
* Errors rate error.
*/
#define CAN_LIMIT_ERROR 2
/**
* Bus off condition reached.
*/
#define CAN_BUS_OFF_ERROR 4
/**
* Framing error of some kind on the CAN bus.
*/
#define CAN_FRAMING_ERROR 8
/**
* Overflow in receive queue.
*/
#define CAN_OVERFLOW_ERROR 16 /**
* Special mailbox identifier.
*/
#define CAN_ANY_MAILBOX 0 /**
* @name CAN configuration options
* @{
*/
/**
* Sleep mode related APIs inclusion switch.
* @details This option can only be enabled if the CAN implementation supports
* the sleep mode, see the macro @p CAN_SUPPORTS_SLEEP exported by
* the underlying implementation.
*/ #define CAN_USE_SLEEP_MODE TRUE /**
* Driver state machine possible states.
*/
typedef enum
{
CAN_UNINIT = , /**< Not initialized. */
CAN_STOP = , /**< Stopped. */
CAN_STARTING = , /**< Starting. */
CAN_READY = , /**< Ready. */
CAN_SLEEP = /**< Sleep state. */
} canstate_t; #include "can_lld.h" /**
* Converts a mailbox index to a bit mask.
*/
#define CAN_MAILBOX_TO_MASK(mbx) (1 << ((mbx) - 1)) void canInit( void );
void canObjectInit( CANDriver *canp );
void canStart( CANDriver *canp, const CANConfig *config );
void canStop( CANDriver *canp );
msg_t canTransmit( CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp,
systime_t timeout );
msg_t canReceive( CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp,
systime_t timeout );
void canSleep( CANDriver *canp );
void canWakeup( CANDriver *canp ); #include "ch.h"
#include "hal.h" /**
* CAN Driver initialization.
* @note This function is implicitly invoked by @p halInit(), there is
* no need to explicitly initialize the driver.
*
* @init
*/
void canInit( void )
{ can_lld_init( );
} /**
* Initializes the standard part of a @p CANDriver structure.
*
* @param[out] canp pointer to the @p CANDriver object
*
* @init
*/
void canObjectInit( CANDriver *canp )
{ canp->state = CAN_STOP;
canp->config = NULL;
chSemInit( &canp->txsem, );
chSemInit( &canp->rxsem, );
chEvtInit( &canp->rxfull_event );
chEvtInit( &canp->txempty_event );
chEvtInit( &canp->error_event );
chEvtInit( &canp->sleep_event );
chEvtInit( &canp->wakeup_event );
} /**
* 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.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] config pointer to the @p CANConfig object. Depending on
* the implementation the value can be @p NULL.
*
* @api
*/
void canStart( CANDriver *canp, const CANConfig *config )
{ chDbgCheck( canp != NULL, "canStart" ); chSysLock( );
chDbgAssert(
( canp->state == CAN_STOP ) || ( canp->state == CAN_STARTING )
|| ( canp->state == CAN_READY ), "canStart(), #1", "invalid state" );
while ( canp->state == CAN_STARTING )
chThdSleepS( );
if ( canp->state == CAN_STOP )
{
canp->config = config;
can_lld_start( canp );
canp->state = CAN_READY;
}
chSysUnlock( );
} /**
* Deactivates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @api
*/
void canStop( CANDriver *canp )
{ chDbgCheck( canp != NULL, "canStop" ); chSysLock( );
chDbgAssert( ( canp->state == CAN_STOP ) || ( canp->state == CAN_READY ),
"canStop(), #1", "invalid state" );
can_lld_stop( canp );
canp->state = CAN_STOP;
chSemResetI( &canp->rxsem, );
chSemResetI( &canp->txsem, );
chSchRescheduleS( );
chSysUnlock( );
} /**
* Can frame transmission.
* @details The specified frame is queued for transmission, if the hardware
* queue is full then the invoking thread is queued.
* @note Trying to transmit while in sleep mode simply enqueues the thread.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
* @param[in] ctfp pointer to the CAN frame to be transmitted
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation result.
* @retval RDY_OK the frame has been queued for transmission.
* @retval RDY_TIMEOUT The operation has timed out.
* @retval RDY_RESET The driver has been stopped while waiting.
*
* @api
*/
msg_t canTransmit( CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp,
systime_t timeout )
{ chDbgCheck(
( canp != NULL ) && ( ctfp != NULL ) && ( mailbox <= CAN_TX_MAILBOXES ),
"canTransmit" ); chSysLock( );
chDbgAssert( ( canp->state == CAN_READY ) || ( canp->state == CAN_SLEEP ),
"canTransmit(), #1", "invalid state" );
while ( ( canp->state == CAN_SLEEP ) || !can_lld_is_tx_empty( canp, mailbox ) )
{
msg_t msg = chSemWaitTimeoutS( &canp->txsem, timeout );
if ( msg != RDY_OK )
{
chSysUnlock( );
return msg;
}
}
can_lld_transmit( canp, mailbox, ctfp );
chSysUnlock( );
return RDY_OK;
} /**
* Can frame receive.
* @details The function waits until a frame is received.
* @note Trying to receive while in sleep mode simply enqueues the thread.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
* @param[out] crfp pointer to the buffer where the CAN frame is copied
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout (useful in an
* event driven scenario where a thread never blocks
* for I/O).
* - @a TIME_INFINITE no timeout.
* .
* @return The operation result.
* @retval RDY_OK a frame has been received and placed in the buffer.
* @retval RDY_TIMEOUT The operation has timed out.
* @retval RDY_RESET The driver has been stopped while waiting.
*
* @api
*/
msg_t canReceive( CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp,
systime_t timeout )
{ chDbgCheck(
( canp != NULL ) && ( crfp != NULL ) && ( mailbox <= CAN_RX_MAILBOXES ),
"canReceive" ); chSysLock( );
chDbgAssert( ( canp->state == CAN_READY ) || ( canp->state == CAN_SLEEP ),
"canReceive(), #1", "invalid state" );
while ( ( canp->state == CAN_SLEEP )
|| !can_lld_is_rx_nonempty( canp, mailbox ) )
{
msg_t msg = chSemWaitTimeoutS( &canp->rxsem, timeout );
if ( msg != RDY_OK )
{
chSysUnlock( );
return msg;
}
}
can_lld_receive( canp, mailbox, crfp );
chSysUnlock( );
return RDY_OK;
} /**
* Enters the sleep mode.
* @details This function puts the CAN driver in sleep mode and broadcasts
* the @p sleep_event event source.
* @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must
* be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported
* by the low level driver.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @api
*/
void canSleep( CANDriver *canp )
{ chDbgCheck( canp != NULL, "canSleep" ); chSysLock( );
chDbgAssert( ( canp->state == CAN_READY ) || ( canp->state == CAN_SLEEP ),
"canSleep(), #1", "invalid state" );
if ( canp->state == CAN_READY )
{
can_lld_sleep( canp );
canp->state = CAN_SLEEP;
chEvtBroadcastI( &canp->sleep_event );
chSchRescheduleS( );
}
chSysUnlock( );
} /**
* Enforces leaving the sleep mode.
* @note The sleep mode is supposed to be usually exited automatically by
* an hardware event.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void canWakeup( CANDriver *canp )
{ chDbgCheck( canp != NULL, "canWakeup" ); chSysLock( );
chDbgAssert( ( canp->state == CAN_READY ) || ( canp->state == CAN_SLEEP ),
"canWakeup(), #1", "invalid state" );
if ( canp->state == CAN_SLEEP )
{
can_lld_wakeup( canp );
canp->state = CAN_READY;
chEvtBroadcastI( &canp->wakeup_event );
chSchRescheduleS( );
}
chSysUnlock( );
}

ChibiOS/RT 2.6.9 CAN Driver的更多相关文章

  1. ChibiOS/RT 2.6.9 CAN Low Level Driver for STM32

    /* ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio Licensed under the Apache License, Version 2 ...

  2. ChibiOS/RT移植到STM32F407

    官网地址:http://www.chibios.org/dokuwiki/doku.php 下载源码 找到STM32F407的demos程序(chibios\demos\STM32\RT-STM32F ...

  3. OpenOCD 0.9.0 release

    OpenOCD 0.9.0 release May 18th, 2015 I’m happy to announce the release of OpenOCD version 0.9.0, fin ...

  4. Open Source RTOS

    http://www.osrtos.com/     Name License Platforms Description Last updated FreeRTOS Modified GPL MSP ...

  5. ARM architecture

    http://en.wikipedia.org/wiki/ARM_architecture ARM architecture     ARM architectures The ARM logo De ...

  6. zubax_gnss移植到STM32F407

    源码下载:https://github.com/Zubax/zubax_gnss.git 源码默认支持STM32F107芯片 STM32 HAL库测试:zubax_gnss\bootloader\zu ...

  7. 深入linux kernel内核配置选项

    ============================================================================== 深入linux kernel内核配置选项 ...

  8. Linux Device Driver && Device File

    catalog . 设备驱动程序简介 . I/O体系结构 . 访问设备 . 与文件系统关联 . 字符设备操作 . 块设备操作 . 资源分配 . 总线系统 1. 设备驱动程序简介 设备驱动程序是内核的关 ...

  9. spark任务运行完成后在driver端的处理逻辑

    回顾 上一篇,我们分析了了任务在executor端的运行流程,任务运行结束后,在Executor.launchTask方法最后,通过调用execBackend.statusUpdate方法将任务结果以 ...

随机推荐

  1. 电容充放电时间常数RC计算方法

    进入正题前,我们先来回顾下电容的充放电时间计算公式,假设有电源Vu通过电阻R给电容C充电,V0为电容上的初始电压值,Vu为电容充满电后的电压值,Vt为任意时刻t时电容上的电压值,那么便可以得到如下的计 ...

  2. 安装.NET Framework返回1603错误的解决办法

    昨天正在忙其它事情,实然同事向我反馈TFS上的文档无法浏览查看.第一反映是他的机器环境问题,让他试了下其它项目的文档也无法查看,后来在我电脑上也尝试了一下,果然无法查看项目文档,看来是TFS出了问题. ...

  3. Python 驱动 MongoDB 示例(PyMongo)

    Python 的MongoDB驱动 pymongo ,使用pip Install pymongo安装即可 最近发现网上的很多实例已经过时了,在此自我探究记录下来. 编写一个接口类来支持MongoDB的 ...

  4. [转] 在安卓设备上使用 Chrome 远程调试功能

    你的网页内容在移动设备上的体验可能和电脑上完全不同.Chrome DevTools 提供了远程调试功能,这让你可以在安卓设备上实时调试开发的内容. 安卓远程调试支持: 在浏览器选项卡中调试网站. 在原 ...

  5. shell中信号处理

    参考: Shell 脚本中信号处理实践 Linux Shell 的信号 trap 功能你必须知道的细节   在 unix 里,可能发生的每一种类型的事件都是由一个独立的信号来描述,每一个信号都是一个小 ...

  6. 2018 Arab Collegiate Programming Contest (ACPC 2018) E - Exciting Menus AC自动机

    E - Exciting Menus 建个AC自动机求个fail指针就好啦. #include<bits/stdc++.h> #define LL long long #define fi ...

  7. Educational Codeforces Round 41 (Rated for Div. 2)

    这场没打又亏疯了!!! A - Tetris : 类似俄罗斯方块,模拟一下就好啦. #include<bits/stdc++.h> #define fi first #define se ...

  8. JMS(Java消息服务)

    JMS即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM:指的是利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来 ...

  9. Chart.js Y轴数据以百分比展示

    新手一枚,解决的问题喜欢记录,也许正好有人在网上迷茫的百度着.-0- 最近使用Chart.js做折线图的报表展示,直接显示整数啥的很好弄毕竟例子直接在哪里可以用,百分比就没办法了.百度慢慢汲取营养,虽 ...

  10. ADSL

    ADSL属于DSL技术的一种,全称Asymmetric Digital Subscriber Line( 非对称数字用户线路),亦可称作非对称数字用户环路.是一种新的数据传输方式. ADSL技术提供的 ...