The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.
Dependents: hello SerialTestv11 SerialTestv12 Sierpinski ... more
mbed 2
This is the mbed 2 library. If you'd like to learn about Mbed OS please see the mbed-os docs.
Diff: TARGET_EFM32HG_STK3400/TOOLCHAIN_GCC_ARM/em_can.h
- Revision:
- 171:3a7713b1edbc
- Parent:
- 160:5571c4ff569f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TARGET_EFM32HG_STK3400/TOOLCHAIN_GCC_ARM/em_can.h Thu Nov 08 11:45:42 2018 +0000 @@ -0,0 +1,596 @@ +/***************************************************************************//** + * @file em_can.h + * @brief Controller Area Network API + * @version 5.3.3 + ******************************************************************************* + * # License + * <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b> + ******************************************************************************* + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no + * obligation to support this Software. Silicon Labs is providing the + * Software "AS IS", with no express or implied warranties of any kind, + * including, but not limited to, any implied warranties of merchantability + * or fitness for any particular purpose or warranties against infringement + * of any proprietary rights of a third party. + * + * Silicon Labs will not be liable for any consequential, incidental, or + * special damages, or any other relief, or for any claim by any third party, + * arising from your use of this Software. + * + ******************************************************************************/ + +#ifndef EM_CAN_H +#define EM_CAN_H + +#include "em_bus.h" +#include "em_device.h" +#include <stdbool.h> + +#if defined(CAN_COUNT) && (CAN_COUNT > 0) + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************//** + * @addtogroup emlib + * @{ + ******************************************************************************/ + +/***************************************************************************//** + * @addtogroup CAN + * @{ + ******************************************************************************/ + +/******************************************************************************* + ******************************* DEFINES *********************************** + ******************************************************************************/ + +/******************************************************************************* + ******************************** ENUMS ************************************ + ******************************************************************************/ + +/** CAN Status codes */ +typedef enum { + /** No error occurred during last CAN bus event. */ + canErrorNoError = CAN_STATUS_LEC_NONE, + + /** + * More than 5 equal bits in a sequence have occurred in a part of a received + * message where this is not allowed. + */ + canErrorStuff = CAN_STATUS_LEC_STUFF, + + /** A fixed format part of a received frame has the wrong format. */ + canErrorForm = CAN_STATUS_LEC_FORM, + + /** The message this CAN Core transmitted was not acknowledged by another node. */ + canErrorAck = CAN_STATUS_LEC_ACK, + + /** Wrong monitored bus value : dominant when the module wanted to send a recessive. */ + canErrorBit1 = CAN_STATUS_LEC_BIT1, + + /** Wrong monitored bus value : recessive when the module intended to send a dominant. */ + canErrorBit0 = CAN_STATUS_LEC_BIT0, + + /** CRC check sum incorrect. */ + canErrorCrc = CAN_STATUS_LEC_CRC, + + /** Unused. No new error since the cpu wrote this value */ + canErrorUnused = CAN_STATUS_LEC_UNUSED +} CAN_ErrorCode_TypeDef; + +/** CAN peripheral mode */ +typedef enum { + /** CAN peripheral in Normal mode : ready to send and receive messages */ + canModeNormal, + + /** CAN peripheral in Basic mode : no use of the RAM */ + canModeBasic, + + /** + * CAN peripheral in Loopback mode : input from the CAN bus is disregarded + * and comes from TX instead + */ + canModeLoopBack, + + /** + * CAN peripheral in SilentLoopback mode : input from the CAN bus is + * disregarded and comes from TX instead ; no output on the CAN bus + */ + canModeSilentLoopBack, + + /** CAN peripheral in Silent mode : no output on the CAN bus. If required to + * send a dominant bit, it's rerouted internally so that the CAN module + * monitors it but the CAN bus stays recessive. + */ + canModeSilent +} CAN_Mode_TypeDef; + +/******************************************************************************* + ******************************* STRUCTS *********************************** + ******************************************************************************/ + +/** CAN Message Object TypeDef structure. LSBs is used */ +typedef struct { + /** Message number of this Message Object, [1 - 32] */ + uint8_t msgNum; + + /** Id extended if true, standard if false */ + bool extended; + + /** + * Id of the message, with 11 bits (standard) or 28 bits (extended). + * LSBs are used for both of them + */ + uint32_t id; + + /** Data Length Code [0 - 8] */ + uint8_t dlc; + + /** Pointer to the data, [0 - 8] bytes */ + uint8_t data[8]; + + /** Mask for id filtering */ + uint32_t mask; + + /** Enable the use of 'extended' value for filtering */ + bool extendedMask; + + /** Enable the use of 'direction' value for filtering */ + bool directionMask; +} CAN_MessageObject_TypeDef; + +/** CAN initialization structure. */ +typedef struct { + /** true to set the CAN Device in normal mode after init */ + bool enable; + + /** True to reset messages during initialization */ + bool resetMessages; + + /** Default bitrate */ + uint32_t bitrate; + + /** Default Propagation Time Segment */ + uint8_t propagationTimeSegment; + + /** Default Phase Buffer Segment 1 */ + uint8_t phaseBufferSegment1; + + /** Default Phase Buffer Segment 2 */ + uint8_t phaseBufferSegment2; + + /** Default Synchronisation Jump Width */ + uint8_t synchronisationJumpWidth; +} CAN_Init_TypeDef; + +/** + * Default initialization of CAN_Init_TypeDef. The total duration of a bit with + * these default parameters is 10 tq (time quantum : tq = brp/fsys, brp being + * the baudrate prescaler and being set according to the wanted bitrate, fsys + * beeing the CAN Device frequency). + */ +#define CAN_INIT_DEFAULT \ + { \ + true, /** Set the CAN Device in normal mode after init */ \ + true, /** Reset messages during initialization */ \ + 100000, /** Set bitrate to 100 000 */ \ + 1, /** Set the Propagation Time Segment to 1 */ \ + 4, /** Set the Phase Buffer Segment 1 to 4 */ \ + 4, /** Set the Phase Buffer Segment 2 to 4 */ \ + 1 /** Set the Synchronization Jump Width to 1 */ \ + } + +/******************************************************************************* + ***************************** PROTOTYPES ********************************** + ******************************************************************************/ + +void CAN_Init(CAN_TypeDef *can, const CAN_Init_TypeDef *init); + +uint32_t CAN_GetClockFrequency(CAN_TypeDef *can); + +bool CAN_MessageLost(CAN_TypeDef *can, uint8_t interface, uint8_t msgNum); + +void CAN_SetRoute(CAN_TypeDef *can, + bool active, + uint16_t pinRxLoc, + uint16_t pinTxLoc); + +void CAN_SetBitTiming(CAN_TypeDef *can, + uint32_t bitrate, + uint16_t propagationTimeSegment, + uint16_t phaseBufferSegment1, + uint16_t phaseBufferSegment2, + uint16_t synchronisationJumpWidth); + +void CAN_SetMode(CAN_TypeDef *can, CAN_Mode_TypeDef mode); + +void CAN_SetIdAndFilter(CAN_TypeDef *can, + uint8_t interface, + bool useMask, + const CAN_MessageObject_TypeDef *message, + bool wait); + +void CAN_ConfigureMessageObject(CAN_TypeDef *can, + uint8_t interface, + uint8_t msgNum, + bool valid, + bool tx, + bool remoteTransfer, + bool endOfBuffer, + bool wait); + +void CAN_SendMessage(CAN_TypeDef *can, + uint8_t interface, + const CAN_MessageObject_TypeDef *message, + bool wait); + +void CAN_ReadMessage(CAN_TypeDef *can, + uint8_t interface, + CAN_MessageObject_TypeDef *message); + +void CAN_AbortSendMessage(CAN_TypeDef *can, + uint8_t interface, + uint8_t msgNum, + bool wait); + +void CAN_ResetMessages(CAN_TypeDef *can, uint8_t interface); + +void CAN_Reset(CAN_TypeDef *can); + +void CAN_WriteData(CAN_TypeDef *can, + uint8_t interface, + const CAN_MessageObject_TypeDef *message); + +void CAN_SendRequest(CAN_TypeDef *can, + uint8_t interface, + uint8_t msgNum, + bool wait); + +/***************************************************************************//** + * @brief + * Enable the Host Controller to send messages. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] enable + * true to enable CAN device, false to disable it. If the CAN device is + * enabled, it goes in normal mode (the default working mode). + ******************************************************************************/ +__STATIC_INLINE void CAN_Enable(CAN_TypeDef *can, bool enable) +{ + BUS_RegBitWrite(&can->CTRL, _CAN_CTRL_INIT_SHIFT, (enable ? 0 : 1)); +} + +/***************************************************************************//** + * @brief + * Gives the communication capabilities state. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * true if the Host Controller can send messages, false otherwise. + ******************************************************************************/ +__STATIC_INLINE bool CAN_IsEnabled(CAN_TypeDef *can) +{ + return (can->CTRL & _CAN_CTRL_INIT_MASK) == 0; +} + +/***************************************************************************//** + * @brief + * Waiting function. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] interface + * Indicate which Message Interface Register to use. + * + ******************************************************************************/ +__STATIC_INLINE void CAN_ReadyWait(CAN_TypeDef *can, + uint8_t interface) +{ + while ((_CAN_MIR_CMDREQ_BUSY_MASK & can->MIR[interface].CMDREQ) != 0) { + } +} + +/***************************************************************************//** + * @brief + * Get the last error code and clear its register. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * return Last error code. + ******************************************************************************/ +__STATIC_INLINE CAN_ErrorCode_TypeDef CAN_GetLastErrorCode(CAN_TypeDef *can) +{ + CAN_ErrorCode_TypeDef errorCode = (CAN_ErrorCode_TypeDef) + (can->STATUS & _CAN_STATUS_LEC_MASK); + can->STATUS |= ~_CAN_STATUS_LEC_MASK; + return errorCode; +} + +/***************************************************************************//** + * @brief + * Indicates which messages objects have received new data. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * State of MESSAGEDATA register indicating which messages objects have received + * new data. + ******************************************************************************/ +__STATIC_INLINE uint32_t CAN_HasNewdata(CAN_TypeDef *can) +{ + return can->MESSAGEDATA; +} + +/***************************************************************************//** + * @brief + * Clear one or more pending CAN status interrupts. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * Pending CAN status interrupt source(s) to clear. + ******************************************************************************/ +__STATIC_INLINE void CAN_StatusIntClear(CAN_TypeDef *can, uint32_t flags) +{ + can->IF1IFC = flags; +} + +/***************************************************************************//** + * @brief + * Disable CAN status interrupts. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * CAN status interrupt source(s) to disable. + ******************************************************************************/ +__STATIC_INLINE void CAN_StatusIntDisable(CAN_TypeDef *can, uint32_t flags) +{ + can->IF1IEN &= ~flags; +} + +/***************************************************************************//** + * @brief + * Enable CAN status interrupts. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * CAN status interrupt source(s) to enable. + ******************************************************************************/ +__STATIC_INLINE void CAN_StatusIntEnable(CAN_TypeDef *can, uint32_t flags) +{ + can->IF1IEN |= flags; +} + +/***************************************************************************//** + * @brief + * Get pending CAN status interrupt flags. + * + * @note + * The event bits are not cleared by the use of this function. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * CAN interrupt source(s) pending. + ******************************************************************************/ +__STATIC_INLINE uint32_t CAN_StatusIntGet(CAN_TypeDef *can) +{ + return can->IF1IF; +} + +/***************************************************************************//** + * @brief + * Get pending and enabled CAN status interrupt flags. + * + * @note + * The event bits are not cleared by the use of this function. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * CAN interrupt source(s) pending and enabled. + ******************************************************************************/ +__STATIC_INLINE uint32_t CAN_StatusIntGetEnabled(CAN_TypeDef *can) +{ + uint32_t ien; + + ien = can->IF1IEN; + return can->IF1IF & ien; +} + +/***************************************************************************//** + * @brief + * Set one or more CAN status interrupts. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * CAN status interrupt source(s) to set to pending. + ******************************************************************************/ +__STATIC_INLINE void CAN_StatusIntSet(CAN_TypeDef *can, uint32_t flags) +{ + can->IF1IFS = flags; +} + +/***************************************************************************//** + * @brief + * Get CAN status. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * Value of CAN register STATUS. + ******************************************************************************/ +__STATIC_INLINE uint32_t CAN_StatusGet(CAN_TypeDef *can) +{ + return can->STATUS & ~_CAN_STATUS_LEC_MASK; +} + +/***************************************************************************//** + * @brief + * Clear CAN status. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * CAN status bits to clear. + ******************************************************************************/ +__STATIC_INLINE void CAN_StatusClear(CAN_TypeDef *can, uint32_t flags) +{ + can->STATUS &= ~flags; +} + +/***************************************************************************//** + * @brief + * Get the error count. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * Error count. + ******************************************************************************/ +__STATIC_INLINE uint32_t CAN_GetErrorCount(CAN_TypeDef *can) +{ + return can->ERRCNT; +} + +/***************************************************************************//** + * @brief + * Clear one or more pending CAN message interrupts. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * Pending CAN message interrupt source(s) to clear. + ******************************************************************************/ +__STATIC_INLINE void CAN_MessageIntClear(CAN_TypeDef *can, uint32_t flags) +{ + can->IF0IFC = flags; +} + +/***************************************************************************//** + * @brief + * Disable CAN message interrupts. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * CAN message interrupt source(s) to disable. + ******************************************************************************/ +__STATIC_INLINE void CAN_MessageIntDisable(CAN_TypeDef *can, uint32_t flags) +{ + can->IF0IEN &= ~flags; +} + +/***************************************************************************//** + * @brief + * Enable CAN message interrupts. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * CAN message interrupt source(s) to enable. + ******************************************************************************/ +__STATIC_INLINE void CAN_MessageIntEnable(CAN_TypeDef *can, uint32_t flags) +{ + can->IF0IEN |= flags; +} + +/***************************************************************************//** + * @brief + * Get pending CAN message interrupt flags. + * + * @note + * The event bits are not cleared by the use of this function. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * CAN message interrupt source(s) pending. + ******************************************************************************/ +__STATIC_INLINE uint32_t CAN_MessageIntGet(CAN_TypeDef *can) +{ + return can->IF0IF; +} + +/***************************************************************************//** + * @brief + * Get CAN message interrupt flags that are pending and enabled. + * + * @note + * The event bits are not cleared by the use of this function. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @return + * CAN message interrupt source(s) pending and enabled. + ******************************************************************************/ +__STATIC_INLINE uint32_t CAN_MessageIntGetEnabled(CAN_TypeDef *can) +{ + uint32_t ien; + + ien = can->IF0IEN; + return can->IF0IF & ien; +} + +/***************************************************************************//** + * @brief + * Set one or more CAN message interrupts. + * + * @param[in] can + * Pointer to CAN peripheral register block. + * + * @param[in] flags + * CAN message interrupt source(s) to set to pending. + ******************************************************************************/ +__STATIC_INLINE void CAN_MessageIntSet(CAN_TypeDef *can, uint32_t flags) +{ + can->IF0IFS = flags; +} + +/** @} (end addtogroup CAN) */ +/** @} (end addtogroup emlib) */ + +#ifdef __cplusplus +} +#endif + +#endif /* defined(CAN_COUNT) && (CAN_COUNT > 0) */ +#endif /* EM_CAN_H */