diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/PeripheralNames.h b/targets/TARGET_Silicon_Labs/TARGET_EFM32/PeripheralNames.h
index f8690f98081..c055253c0df 100644
--- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/PeripheralNames.h
+++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/PeripheralNames.h
@@ -136,6 +136,17 @@ typedef enum {
} UARTName;
#endif
+#if DEVICE_CAN
+typedef enum {
+#ifdef CAN0_BASE
+ CAN_0 = (int)CAN0_BASE,
+#endif
+#ifdef CAN1_BASE
+ CAN_1 = (int)CAN1_BASE,
+#endif
+} CANName;
+#endif
+
#if DEVICE_QSPI
typedef enum {
#ifdef QSPI0_BASE
diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/can_api.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/can_api.c
new file mode 100644
index 00000000000..0e847400de9
--- /dev/null
+++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/can_api.c
@@ -0,0 +1,331 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2019 ToolSense
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "can_api.h"
+#include "clocking.h"
+
+
+#if DEVICE_CAN
+
+#include "cmsis.h"
+#include "pinmap.h"
+#include "pinmap_function.h"
+#include "PeripheralPins.h"
+#include "mbed_assert.h"
+#include "em_cmu.h"
+#include "em_can.h"
+
+static uint32_t can_irq_ids[CAN_COUNT] = {0};
+static can_irq_handler irq_handler;
+
+// CAN bus interfaces
+#define CAN_TX_IF 0
+#define CAN_RX_IF 1
+
+void can_init(can_t *obj, PinName rd, PinName td)
+{
+ can_init_freq(obj, rd, td, 100000);
+}
+
+void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
+{
+ CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RX);
+ CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TX);
+ obj->instance = (CAN_TypeDef *)pinmap_merge(can_rd, can_td);
+
+ CMU_Clock_TypeDef cmuClock_number;
+ switch ((CANName)obj->instance) {
+#ifdef CAN0
+ case CAN_0:
+ cmuClock_number = cmuClock_CAN0;
+ break;
+#endif
+#ifdef CAN1
+ case CAN_1:
+ cmuClock_number = cmuClock_CAN1;
+ break;
+#endif
+ }
+
+ MBED_ASSERT((unsigned int)rd != NC);
+ MBED_ASSERT((unsigned int)td != NC);
+
+
+ // Configure CAN pins
+ pinmap_pinout(rd, PinMap_CAN_RX);
+ pinmap_pinout(td, PinMap_CAN_TX);
+
+
+ CMU_ClockEnable(cmuClock_number, true);
+
+ CAN_Init_TypeDef CanInit = CAN_INIT_DEFAULT;
+ CanInit.bitrate=hz;
+ CAN_Init(obj->instance, &CanInit);
+ CAN_SetMode(obj->instance, canModeNormal);
+
+ uint32_t loc_rd = pin_location(rd, PinMap_CAN_RX);
+ uint32_t loc_td = pin_location(td, PinMap_CAN_TX);
+
+ CAN_SetRoute(obj->instance, true, loc_rd, loc_td);
+
+
+ // Add pull-ups
+ if (rd != NC) {
+ pin_mode(rd, gpioModeInput);
+ }
+ if (td != NC) {
+ pin_mode(td, gpioModePushPull);
+ }
+
+ CAN_ConfigureMessageObject(obj->instance, CAN_TX_IF, 1, true, true, false, true, true);
+
+ CAN_ConfigureMessageObject(obj->instance, CAN_RX_IF, 2, true, false, false, true, true);
+
+ CAN_MessageObject_TypeDef receiver;
+
+ receiver.msgNum = 2;
+ receiver.id = 0;
+ receiver.mask = 0;
+ receiver.extended = false;
+ receiver.extendedMask = false;
+
+ CAN_SetIdAndFilter(obj->instance, CAN_RX_IF, true, &receiver, true);
+}
+
+void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id)
+{
+ int index = 0;
+
+ switch ((CANName)obj->instance) {
+#ifdef CAN0
+ case CAN_0:
+ index = 0;
+ break;
+#endif
+#ifdef CAN1
+ case CAN_1:
+ index = 1;
+ break;
+#endif
+ }
+
+ irq_handler = handler;
+ can_irq_ids[index] = id;
+}
+
+void can_irq_free(can_t *obj)
+{
+ CAN_MessageIntDisable(obj->instance, _CAN_IF0IEN_MESSAGE_MASK);
+ CAN_MessageIntClear(obj->instance, 0xFFFFFFFF);
+
+ switch ((CANName)obj->instance) {
+#ifdef CAN0
+ case CAN_0:
+ NVIC_DisableIRQ(CAN0_IRQn);
+ break;
+#endif
+#ifdef CAN1
+ case CAN_1:
+ NVIC_DisableIRQ(CAN1_IRQn);
+ break;
+#endif
+ }
+}
+
+void can_free(can_t *obj)
+{
+ CAN_Enable(obj->instance, false);
+}
+
+int can_frequency(can_t *obj, int f)
+{
+ CAN_Init_TypeDef CanInit = CAN_INIT_DEFAULT;
+ CanInit.bitrate=f;
+
+ CAN_SetBitTiming(obj->instance,
+ CanInit.bitrate,
+ CanInit.propagationTimeSegment,
+ CanInit.phaseBufferSegment1,
+ CanInit.phaseBufferSegment2,
+ CanInit.synchronisationJumpWidth);
+ return 0;
+}
+
+int can_write(can_t *obj, CAN_Message msg, int cc)
+{
+ CAN_MessageObject_TypeDef message;
+
+ message.id = msg.id;
+ message.msgNum = 1;
+
+ if (msg.format == 0) message.extended = false;
+ else message.extended = true;
+
+ message.dlc = msg.len;
+
+ for (int i = 0; i < message.dlc; ++i) {
+ message.data[i] = (uint32_t)msg.data[i];
+ }
+
+ CAN_SendMessage(obj->instance, CAN_TX_IF, &message, true);
+
+ return 1;
+}
+
+int can_read(can_t *obj, CAN_Message *msg, int handle)
+{
+ CAN_MessageObject_TypeDef receiver;
+
+ if (CAN_HasNewdata(obj->instance)) {
+
+ receiver.msgNum = 2;
+ receiver.extended = false;
+ receiver.extendedMask = false;
+
+ CAN_ReadMessage(obj->instance, CAN_RX_IF, &receiver);
+
+ msg->id = receiver.id;
+ msg->len = receiver.dlc;
+
+ for (int i = 0; i < receiver.dlc; ++i) {
+ msg->data[i] = (unsigned char)receiver.data[i];
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void can_reset(can_t *obj)
+{
+ CAN_Reset(obj->instance);
+}
+
+unsigned char can_rderror(can_t *obj)
+{
+ return ((obj->instance->ERRCNT>>_CAN_ERRCNT_REC_SHIFT)&0xFF);
+}
+
+unsigned char can_tderror(can_t *obj)
+{
+ return ((obj->instance->ERRCNT)&0xFF);
+}
+
+void can_monitor(can_t *obj, int silent)
+{
+ CanMode mode = MODE_NORMAL;
+
+ if (silent) {
+ mode = MODE_SILENT;
+ }
+
+ CAN_SetMode(obj->instance, mode);
+}
+
+int can_mode(can_t *obj, CanMode mode)
+{
+ CAN_SetMode(obj->instance, mode);
+ return 1;
+}
+
+int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
+{
+ CAN_MessageObject_TypeDef message;
+
+ message.msgNum = 2;
+ message.id = id;
+ message.mask = mask;
+
+ if (format == CANStandard) {
+ message.extended = false;
+ message.extendedMask = false;
+ } else {
+ message.extended = true;
+ message.extendedMask = true;
+ }
+
+ CAN_SetIdAndFilter(obj->instance, CAN_RX_IF, true, &message, true);
+
+ return handle;
+}
+
+void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
+{
+ uint32_t ier = _CAN_IF0IEN_MESSAGE_MASK;
+
+ if (enable) {
+ CAN_MessageIntEnable(obj->instance, ier);
+ } else {
+ CAN_MessageIntDisable(obj->instance, ier);
+ }
+
+ switch ((CANName)obj->instance) {
+#ifdef CAN0
+ case CAN_0:
+ NVIC_SetVector(CAN0_IRQn, (uint32_t)CAN0_IRQHandler);
+ NVIC_EnableIRQ(CAN0_IRQn);
+ break;
+#endif
+#ifdef CAN1
+ case CAN_1:
+ NVIC_SetVector(CAN1_IRQn, (uint32_t)CAN1_IRQHandler);
+ NVIC_EnableIRQ(CAN1_IRQn);
+ break;
+#endif
+ }
+}
+
+static void can_irq(CANName name, int id)
+{
+ CAN_TypeDef *can;
+ can = (CAN_TypeDef *)name;
+
+ if (can->STATUS & CAN_STATUS_RXOK) {
+ irq_handler(can_irq_ids[id], IRQ_RX);
+ CAN_MessageIntClear(can, 0xFFFFFFFF);
+ }
+
+ if (can->STATUS & CAN_STATUS_TXOK) {
+ irq_handler(can_irq_ids[id], IRQ_TX);
+ CAN_MessageIntClear(can, 0xFFFFFFFF);
+ }
+}
+
+#ifdef CAN0
+void CAN0_IRQHandler(void)
+{
+ can_irq(CAN_0, 0);
+}
+#endif
+
+#ifdef CAN1
+void CAN1_IRQHandler(void)
+{
+ can_irq(CAN_1, 1);
+}
+#endif
+
+const PinMap *can_rd_pinmap()
+{
+ return PinMap_CAN_TX;
+}
+
+const PinMap *can_td_pinmap()
+{
+ return PinMap_CAN_RX;
+}
+
+#endif //DEVICE_CAN
diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/inc/em_can.h b/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/inc/em_can.h
index ead480eab7e..4d61f6f2c1d 100644
--- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/inc/em_can.h
+++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/inc/em_can.h
@@ -1,33 +1,32 @@
/***************************************************************************//**
- * @file em_can.h
+ * @file
* @brief Controller Area Network API
- * @version 5.3.3
+ * @version 5.7.2
*******************************************************************************
* # License
- * Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com
+ * Copyright 2018 Silicon Laboratories Inc. www.silabs.com
*******************************************************************************
*
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
* 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.
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
* 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
@@ -61,9 +60,9 @@ extern "C" {
******************************** ENUMS ************************************
******************************************************************************/
-/** CAN Status codes */
+/** CAN Status codes. */
typedef enum {
- /** No error occurred during last CAN bus event. */
+ /** No error occurred during the last CAN bus event. */
canErrorNoError = CAN_STATUS_LEC_NONE,
/**
@@ -78,36 +77,36 @@ typedef enum {
/** 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. */
+ /** A wrong monitored bus value : dominant when the module wants to send a recessive. */
canErrorBit1 = CAN_STATUS_LEC_BIT1,
- /** Wrong monitored bus value : recessive when the module intended to send a dominant. */
+ /** A wrong monitored bus value : recessive when the module intends 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 */
+ /** Unused. No new error since the CPU wrote this value. */
canErrorUnused = CAN_STATUS_LEC_UNUSED
} CAN_ErrorCode_TypeDef;
-/** CAN peripheral mode */
+/** CAN peripheral mode. */
typedef enum {
- /** CAN peripheral in Normal mode : ready to send and receive messages */
+ /** CAN peripheral in Normal mode : ready to send and receive messages. */
canModeNormal,
- /** CAN peripheral in Basic mode : no use of the RAM */
+ /** 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
+ * 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
+ * disregarded and comes from TX instead ; no output on the CAN bus.
*/
canModeSilentLoopBack,
@@ -122,57 +121,57 @@ typedef enum {
******************************* STRUCTS ***********************************
******************************************************************************/
-/** CAN Message Object TypeDef structure. LSBs is used */
+/** CAN Message Object TypeDef structure. LSBs is used. */
typedef struct {
- /** Message number of this Message Object, [1 - 32] */
+ /** A message number of this Message Object, [1 - 32]. */
uint8_t msgNum;
- /** Id extended if true, standard if false */
+ /** 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
+ * ID of the message with 11 bits (standard) or 28 bits (extended).
+ * LSBs are used for both.
*/
uint32_t id;
- /** Data Length Code [0 - 8] */
+ /** Data Length Code [0 - 8]. */
uint8_t dlc;
- /** Pointer to the data, [0 - 8] bytes */
+ /** A pointer to data, [0 - 8] bytes. */
uint8_t data[8];
- /** Mask for id filtering */
+ /** A mask for ID filtering. */
uint32_t mask;
- /** Enable the use of 'extended' value for filtering */
+ /** Enable the use of 'extended' value for filtering. */
bool extendedMask;
- /** Enable the use of 'direction' value for filtering */
+ /** 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 */
+ /** True to set the CAN Device in normal mode after initialization. */
bool enable;
- /** True to reset messages during initialization */
+ /** True to reset messages during initialization. */
bool resetMessages;
- /** Default bitrate */
+ /** Default bitrate. */
uint32_t bitrate;
- /** Default Propagation Time Segment */
+ /** Default Propagation Time Segment. */
uint8_t propagationTimeSegment;
- /** Default Phase Buffer Segment 1 */
+ /** Default Phase Buffer Segment 1. */
uint8_t phaseBufferSegment1;
- /** Default Phase Buffer Segment 2 */
+ /** Default Phase Buffer Segment 2. */
uint8_t phaseBufferSegment2;
- /** Default Synchronisation Jump Width */
+ /** Default Synchronisation Jump Width. */
uint8_t synchronisationJumpWidth;
} CAN_Init_TypeDef;
@@ -180,17 +179,17 @@ typedef struct {
* 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).
+ * 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 */ \
+#define CAN_INIT_DEFAULT \
+ { \
+ true, /** Set the CAN Device in normal mode after initialization. */ \
+ 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. */ \
}
/*******************************************************************************
@@ -264,11 +263,11 @@ void CAN_SendRequest(CAN_TypeDef *can,
* Enable the Host Controller to send messages.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the 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).
+ * True to enable CAN device, false to disable it. If the CAN device is
+ * enabled, it goes to normal mode (the default working mode).
******************************************************************************/
__STATIC_INLINE void CAN_Enable(CAN_TypeDef *can, bool enable)
{
@@ -277,13 +276,13 @@ __STATIC_INLINE void CAN_Enable(CAN_TypeDef *can, bool enable)
/***************************************************************************//**
* @brief
- * Gives the communication capabilities state.
+ * Give the communication capabilities state.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
- * true if the Host Controller can send messages, false otherwise.
+ * True if the Host Controller can send messages, false otherwise.
******************************************************************************/
__STATIC_INLINE bool CAN_IsEnabled(CAN_TypeDef *can)
{
@@ -295,7 +294,7 @@ __STATIC_INLINE bool CAN_IsEnabled(CAN_TypeDef *can)
* Waiting function.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
@@ -328,13 +327,13 @@ __STATIC_INLINE CAN_ErrorCode_TypeDef CAN_GetLastErrorCode(CAN_TypeDef *can)
/***************************************************************************//**
* @brief
- * Indicates which messages objects have received new data.
+ * Indicates which message objects have received new data.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
- * State of MESSAGEDATA register indicating which messages objects have received
+ * State of MESSAGEDATA register indicating which message objects have received
* new data.
******************************************************************************/
__STATIC_INLINE uint32_t CAN_HasNewdata(CAN_TypeDef *can)
@@ -347,7 +346,7 @@ __STATIC_INLINE uint32_t CAN_HasNewdata(CAN_TypeDef *can)
* Clear one or more pending CAN status interrupts.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
* Pending CAN status interrupt source(s) to clear.
@@ -362,7 +361,7 @@ __STATIC_INLINE void CAN_StatusIntClear(CAN_TypeDef *can, uint32_t flags)
* Disable CAN status interrupts.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
* CAN status interrupt source(s) to disable.
@@ -377,7 +376,7 @@ __STATIC_INLINE void CAN_StatusIntDisable(CAN_TypeDef *can, uint32_t flags)
* Enable CAN status interrupts.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
* CAN status interrupt source(s) to enable.
@@ -392,10 +391,10 @@ __STATIC_INLINE void CAN_StatusIntEnable(CAN_TypeDef *can, uint32_t flags)
* Get pending CAN status interrupt flags.
*
* @note
- * The event bits are not cleared by the use of this function.
+ * This function does not clear event bits.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
* CAN interrupt source(s) pending.
@@ -410,10 +409,10 @@ __STATIC_INLINE uint32_t CAN_StatusIntGet(CAN_TypeDef *can)
* Get pending and enabled CAN status interrupt flags.
*
* @note
- * The event bits are not cleared by the use of this function.
+ * This function does not clear event bits.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
* CAN interrupt source(s) pending and enabled.
@@ -431,7 +430,7 @@ __STATIC_INLINE uint32_t CAN_StatusIntGetEnabled(CAN_TypeDef *can)
* Set one or more CAN status interrupts.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
* CAN status interrupt source(s) to set to pending.
@@ -446,10 +445,10 @@ __STATIC_INLINE void CAN_StatusIntSet(CAN_TypeDef *can, uint32_t flags)
* Get CAN status.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
- * Value of CAN register STATUS.
+ * A value of CAN register STATUS.
******************************************************************************/
__STATIC_INLINE uint32_t CAN_StatusGet(CAN_TypeDef *can)
{
@@ -461,7 +460,7 @@ __STATIC_INLINE uint32_t CAN_StatusGet(CAN_TypeDef *can)
* Clear CAN status.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
* CAN status bits to clear.
@@ -476,7 +475,7 @@ __STATIC_INLINE void CAN_StatusClear(CAN_TypeDef *can, uint32_t flags)
* Get the error count.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
* Error count.
@@ -491,7 +490,7 @@ __STATIC_INLINE uint32_t CAN_GetErrorCount(CAN_TypeDef *can)
* Clear one or more pending CAN message interrupts.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
* Pending CAN message interrupt source(s) to clear.
@@ -506,7 +505,7 @@ __STATIC_INLINE void CAN_MessageIntClear(CAN_TypeDef *can, uint32_t flags)
* Disable CAN message interrupts.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
* CAN message interrupt source(s) to disable.
@@ -521,7 +520,7 @@ __STATIC_INLINE void CAN_MessageIntDisable(CAN_TypeDef *can, uint32_t flags)
* Enable CAN message interrupts.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
* CAN message interrupt source(s) to enable.
@@ -536,10 +535,10 @@ __STATIC_INLINE void CAN_MessageIntEnable(CAN_TypeDef *can, uint32_t flags)
* Get pending CAN message interrupt flags.
*
* @note
- * The event bits are not cleared by the use of this function.
+ * This function does not clear event bits.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
* CAN message interrupt source(s) pending.
@@ -554,10 +553,10 @@ __STATIC_INLINE uint32_t CAN_MessageIntGet(CAN_TypeDef *can)
* Get CAN message interrupt flags that are pending and enabled.
*
* @note
- * The event bits are not cleared by the use of this function.
+ * This function does not clear event bits.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
* CAN message interrupt source(s) pending and enabled.
@@ -575,10 +574,10 @@ __STATIC_INLINE uint32_t CAN_MessageIntGetEnabled(CAN_TypeDef *can)
* Set one or more CAN message interrupts.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] flags
- * CAN message interrupt source(s) to set to pending.
+ * CAN message interrupt source(s) to set as pending.
******************************************************************************/
__STATIC_INLINE void CAN_MessageIntSet(CAN_TypeDef *can, uint32_t flags)
{
diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_can.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_can.c
index 643cfd23906..061473423b5 100644
--- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_can.c
+++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_can.c
@@ -1,33 +1,32 @@
/***************************************************************************//**
- * @file em_can.c
+ * @file
* @brief Controller Area Network API
- * @version 5.3.3
+ * @version 5.7.2
*******************************************************************************
* # License
- * Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com
+ * Copyright 2018 Silicon Laboratories Inc. www.silabs.com
*******************************************************************************
*
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
* 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.
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
* 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.
- *
******************************************************************************/
#include "em_can.h"
@@ -40,9 +39,9 @@
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
-/* Macros to use the ID field in the CANn_MIRx_ARB register as a 11 bit
- * standard id. The register field can be used for both an 11 bit standard
- * id and a 29 bit extended id. */
+/* Macros to use for the ID field in the CANn_MIRx_ARB register as an 11 bit
+ * standard ID. The register field can be used for both an 11 bit standard
+ * ID and a 29 bit extended ID. */
#define _CAN_MIR_ARB_STD_ID_SHIFT 18
#define _CAN_MIR_MASK_STD_SHIFT 18
#define _CAN_MIR_ARB_STD_ID_MASK 0x1FFC0000UL
@@ -71,8 +70,8 @@
* multi-master serial bus for connecting microcontrollers and devices, also
* known as nodes, to communicate with each other in applications without a host
* computer. CAN is a message-based protocol, designed originally for automotive
- * applications, but meanwhile used also in many other surroundings.
- * The complexity of the node can range from a simple I/O device up to an
+ * applications, but also used in many other scenarios.
+ * The complexity of a node can range from a simple I/O device up to an
* embedded computer with a CAN interface and sophisticated software. The node
* may also be a gateway allowing a standard computer to communicate over a USB
* or Ethernet port to the devices on a CAN network. Devices are connected to
@@ -92,10 +91,10 @@
* Initialize CAN.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] init
- * Pointer to CAN initialization structure.
+ * A pointer to the CAN initialization structure.
******************************************************************************/
void CAN_Init(CAN_TypeDef *can, const CAN_Init_TypeDef *init)
{
@@ -122,13 +121,13 @@ void CAN_Init(CAN_TypeDef *can, const CAN_Init_TypeDef *init)
* Get the CAN module frequency.
*
* @details
- * There is an internal prescaler of 2 inside the CAN module.
+ * An internal prescaler of 2 is inside the CAN module.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @return
- * Clock value
+ * A clock value.
******************************************************************************/
uint32_t CAN_GetClockFrequency(CAN_TypeDef *can)
{
@@ -153,33 +152,33 @@ uint32_t CAN_GetClockFrequency(CAN_TypeDef *can)
* 'Message Lost' flag.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
*
* @param[in] msgNum
- * Message number of the Message Object, [1 - 32].
+ * A message number of the Message Object, [1 - 32].
*
* @return
- * true if a message was lost, false otherwise.
+ * True if a message was lost, false otherwise.
******************************************************************************/
bool CAN_MessageLost(CAN_TypeDef *can, uint8_t interface, uint8_t msgNum)
{
CAN_MIR_TypeDef * mir = &can->MIR[interface];
bool messageLost;
- /* Make sure msgNum is in the correct range */
+ /* Make sure msgNum is in the correct range. */
EFM_ASSERT((msgNum > 0) && (msgNum <= 32));
CAN_ReadyWait(can, interface);
- /* Set which registers to read from the RAM */
+ /* Set which registers to read from RAM. */
mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
| CAN_MIR_CMDMASK_CONTROL
| CAN_MIR_CMDMASK_CLRINTPND;
- /* Send reading request and wait (3 to 6 cpu cycle) */
+ /* Send reading request and wait (3 to 6 cpu cycle). */
CAN_SendRequest(can, interface, msgNum, true);
messageLost = mir->CTRL & _CAN_MIR_CTRL_MESSAGEOF_MASK;
@@ -187,14 +186,14 @@ bool CAN_MessageLost(CAN_TypeDef *can, uint8_t interface, uint8_t msgNum)
if (messageLost) {
mir->CMDMASK = CAN_MIR_CMDMASK_WRRD | CAN_MIR_CMDMASK_CONTROL;
- /* Reset the 'MessageLost' bit */
+ /* Reset the 'MessageLost' bit. */
mir->CTRL &= ~_CAN_MIR_CTRL_MESSAGEOF_MASK;
- /* Send reading request and wait (3 to 6 cpu cycle) */
+ /* Send reading request and wait (3 to 6 cpu cycle). */
CAN_SendRequest(can, interface, msgNum, true);
}
- /* Return the state of the MESSAGEOF bit */
+ /* Return the state of the MESSAGEOF bit. */
return messageLost;
}
@@ -203,16 +202,16 @@ bool CAN_MessageLost(CAN_TypeDef *can, uint8_t interface, uint8_t msgNum)
* Set the ROUTE registers.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] active
- * Boolean to activate or not the ROUTE registers.
+ * A boolean indicating whether or not to activate the ROUTE registers.
*
* @param[in] pinRxLoc
- * Location of the rx pin.
+ * A location of the RX pin.
*
* @param[in] pinTxLoc
- * Location of the tx pin.
+ * A location of the TX pin.
******************************************************************************/
void CAN_SetRoute(CAN_TypeDef *can,
bool active,
@@ -232,34 +231,34 @@ void CAN_SetRoute(CAN_TypeDef *can,
/***************************************************************************//**
* @brief
- * Set the bitrate and its parameters
+ * Set the bitrate and its parameters.
*
* @details
- * There are multiple parameters which need to be properly configured.
- * Please refer to the reference manual for a detailed description.
+ * Multiple parameters need to be properly configured.
+ * See the reference manual for a detailed description.
* Careful : the BRP (Baud Rate Prescaler) is calculated by:
* 'brp = freq / (period * bitrate);'. freq is the frequency of the CAN
- * device, period the time of transmission of a bit. The result is an uint32_t
- * hence it's truncated, causing an approximation error. This error is non
- * negligeable when period is high, bitrate is high and freq is low.
+ * device, period the time of transmission of a bit. The result is an uint32_t.
+ * Hence it's truncated, causing an approximation error. This error is non
+ * negligible when the period is high, the bitrate is high, and frequency is low.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] bitrate
- * Wanted bitrate on the CAN bus.
+ * A wanted bitrate on the CAN bus.
*
* @param[in] propagationTimeSegment
- * Value for the Propagation Time Segment.
+ * A value for the Propagation Time Segment.
*
* @param[in] phaseBufferSegment1
- * Value for the Phase Buffer Segment 1.
+ * A value for the Phase Buffer Segment 1.
*
* @param[in] phaseBufferSegment2
- * Value for the Phase Buffer Segment 2.
+ * A value for the Phase Buffer Segment 2.
*
* @param[in] synchronisationJumpWidth
- * Value for the Synchronisation Jump Width.
+ * A value for the Synchronization Jump Width.
******************************************************************************/
void CAN_SetBitTiming(CAN_TypeDef *can,
uint32_t bitrate,
@@ -270,7 +269,7 @@ void CAN_SetBitTiming(CAN_TypeDef *can,
{
uint32_t sum, brp, period, freq, brpHigh, brpLow;
- /* Verification that the parameters are within range */
+ /* Verification that the parameters are in range. */
EFM_ASSERT((propagationTimeSegment <= 8) && (propagationTimeSegment > 0));
EFM_ASSERT((phaseBufferSegment1 <= 8) && (phaseBufferSegment1 > 0));
EFM_ASSERT((phaseBufferSegment2 <= 8) && (phaseBufferSegment2 > 0));
@@ -280,29 +279,29 @@ void CAN_SetBitTiming(CAN_TypeDef *can,
&& (synchronisationJumpWidth > 0));
/* propagationTimeSegment is counted as part of phaseBufferSegment1 in the
- BITTIMING register */
+ BITTIMING register. */
sum = phaseBufferSegment1 + propagationTimeSegment;
- /* period is the total length of one CAN bit. 1 is the Sync_seg */
+ /* Period is the total length of one CAN bit. 1 is the Sync_seg. */
period = 1 + sum + phaseBufferSegment2;
freq = CAN_GetClockFrequency(can);
brp = freq / (period * bitrate);
EFM_ASSERT(brp != 0);
- /* -1 because the hardware reads 'written value + 1' */
+ /* -1 because the hardware reads 'written value + 1'. */
brp = brp - 1;
- /* brp is divided between two registers */
+ /* brp is divided between two registers. */
brpHigh = brp / 64;
brpLow = brp % 64;
- /* Checking register limit */
+ /* Checking register limit. */
EFM_ASSERT(brpHigh <= 15);
bool enabled = CAN_IsEnabled(can);
- /* Enable access to the bittiming registers */
+ /* Enable access to the bittiming registers. */
can->CTRL |= CAN_CTRL_CCE | CAN_CTRL_INIT;
can->BITTIMING = (brpLow << _CAN_BITTIMING_BRP_SHIFT)
@@ -323,12 +322,12 @@ void CAN_SetBitTiming(CAN_TypeDef *can,
* Set the CAN operation mode.
*
* @details
- * In Init mode, the CAN module is deactivated. Reset of the Messages in all
- * the other modes to be sure that there are no leftover data and that they
- * need to be configured before being of use.
+ * In initialization mode, the CAN module is deactivated. Reset the messages in all
+ * other modes to be sure that there is no leftover data that
+ * needs to be configured before use.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] mode
* Mode of operation : Init, Normal, Loopback, SilentLoopback, Silent, Basic.
@@ -385,22 +384,22 @@ void CAN_SetMode(CAN_TypeDef *can, CAN_Mode_TypeDef mode)
/***************************************************************************//**
* @brief
- * Set the Id and the filter for a specific Message Object.
+ * Set the ID and the filter for a specific Message Object.
*
* @details
- * The Init bit have to be 0 to use this function.
+ * The initialization bit has to be 0 to use this function.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
*
* @param[in] useMask
- * Boolean to choose whether or not to use the masks.
+ * A boolean to choose whether or not to use the masks.
*
* @param[in] message
- * Message Object
+ * A Message Object.
*
* @param[in] wait
* If true, wait for the end of the transfer between the MIRx registers and
@@ -413,89 +412,90 @@ void CAN_SetIdAndFilter(CAN_TypeDef *can,
const CAN_MessageObject_TypeDef *message,
bool wait)
{
- /* Make sure msgNum is in the correct range */
+ /* Make sure msgNum is in the correct range. */
EFM_ASSERT((message->msgNum > 0) && (message->msgNum <= 32));
CAN_MIR_TypeDef * mir = &can->MIR[interface];
CAN_ReadyWait(can, interface);
- /* Set which registers to read from the RAM */
+ /* Set which registers to read from RAM. */
mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
| CAN_MIR_CMDMASK_ARBACC
| CAN_MIR_CMDMASK_CONTROL;
- /* Send reading request and wait (3 to 6 cpu cycle) */
+ /* Send reading request and wait (3 to 6 CPU cycle). */
CAN_SendRequest(can, interface, message->msgNum, true);
- /* Reset MSGVAL */
- mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD;
- mir->ARB &= ~(0x1 << _CAN_MIR_ARB_MSGVAL_SHIFT);
+ /* Reset MSGVAL. */
+ mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD_WRITE;
+ mir->ARB &= ~(0x1U << _CAN_MIR_ARB_MSGVAL_SHIFT);
CAN_SendRequest(can, interface, message->msgNum, true);
- /* Set which registers to write to the RAM */
+ /* Set which registers to write to RAM. */
mir->CMDMASK |= CAN_MIR_CMDMASK_MASKACC;
- /* Set UMASK bit */
+ /* Set UMASK bit. */
BUS_RegBitWrite(&mir->CTRL, _CAN_MIR_CTRL_UMASK_SHIFT, useMask);
- /* Configure the id */
+ /* Configure the ID. */
if (message->extended) {
EFM_ASSERT(message->id <= _CAN_MIR_ARB_ID_MASK);
mir->ARB = (mir->ARB & ~_CAN_MIR_ARB_ID_MASK)
| (message->id << _CAN_MIR_ARB_ID_SHIFT)
- | (uint32_t)(0x1 << _CAN_MIR_ARB_MSGVAL_SHIFT)
+ | (0x1UL << _CAN_MIR_ARB_MSGVAL_SHIFT)
| CAN_MIR_ARB_XTD_EXT;
} else {
EFM_ASSERT(message->id <= _CAN_MIR_ARB_STD_ID_MAX);
mir->ARB = (mir->ARB & ~(_CAN_MIR_ARB_ID_MASK | CAN_MIR_ARB_XTD_STD))
- | (message->id << _CAN_MIR_ARB_STD_ID_SHIFT)
- | (uint32_t)(0x1 << _CAN_MIR_ARB_MSGVAL_SHIFT);
+ | (_CAN_MIR_ARB_STD_ID_SHIFT)
+ | (0x1UL << _CAN_MIR_ARB_MSGVAL_SHIFT);
}
if (message->extendedMask) {
- mir->MASK = (message->mask << _CAN_MIR_MASK_MASK_SHIFT);
+ mir->MASK = (message->mask << _CAN_MIR_MASK_MASK_SHIFT)
+ & _CAN_MIR_MASK_MASK_MASK;
} else {
mir->MASK = (message->mask << _CAN_MIR_MASK_STD_SHIFT)
& _CAN_MIR_ARB_STD_ID_MASK;
}
- /* Configure the masks */
+ /* Configure the masks. */
mir->MASK |= (message->extendedMask << _CAN_MIR_MASK_MXTD_SHIFT)
| (message->directionMask << _CAN_MIR_MASK_MDIR_SHIFT);
- /* Send writing request */
+ /* Send a writing request. */
CAN_SendRequest(can, interface, message->msgNum, wait);
}
/***************************************************************************//**
* @brief
- * Configure valid, tx/rx, remoteTransfer for a specific Message Object.
+ * Configure valid, TX/RX, remoteTransfer for a specific Message Object.
*
* @details
- * The Init bit have to be 0 to use this function.
+ * The initialization bit has to be 0 to use this function.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
*
* @param[in] msgNum
- * Message number of this Message Object, [1 - 32].
+ * A message number of this Message Object, [1 - 32].
*
* @param[in] valid
- * true if Message Object is valid, false otherwise.
+ * True if the Message Object is valid, false otherwise.
*
* @param[in] tx
- * true if Message Object is used for transmission, false if used for
+ * True if the Message Object is used for transmission, false if used for
* reception.
*
* @param[in] remoteTransfer
- * true if Message Object is used for remote transmission, false otherwise.
+ * True if the Message Object is used for remote transmission, false otherwise.
*
* @param[in] endOfBuffer
- * true if it is for a single Message Object or the end of a fifo buffer,
- * false if the Message Object is part of a fifo buffer and not the last.
+ * True if it is for a single Message Object or the end of a FIFO buffer,
+ * false if the Message Object is part of a FIFO buffer and not the last.
*
* @param[in] wait
* If true, wait for the end of the transfer between the MIRx registers and
@@ -513,64 +513,64 @@ void CAN_ConfigureMessageObject(CAN_TypeDef *can,
{
CAN_MIR_TypeDef * mir = &can->MIR[interface];
- /* Make sure msgNum is in the correct range */
+ /* Make sure msgNum is in correct range. */
EFM_ASSERT((msgNum > 0) && (msgNum <= 32));
CAN_ReadyWait(can, interface);
- /* Set which registers to read from the RAM */
+ /* Set which registers to read from RAM. */
mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
| CAN_MIR_CMDMASK_ARBACC
| CAN_MIR_CMDMASK_CONTROL;
- /* Send reading request and wait (3 to 6 cpu cycle) */
+ /* Send reading request and wait (3 to 6 CPU cycle). */
CAN_SendRequest(can, interface, msgNum, true);
- /* Set which registers to write to the RAM */
- mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD;
+ /* Set which registers to write to RAM. */
+ mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD_WRITE;
- /* Configure valid message and direction */
+ /* Configure a valid message and direction. */
mir->ARB = (mir->ARB & ~(_CAN_MIR_ARB_DIR_MASK | _CAN_MIR_ARB_MSGVAL_MASK))
| (valid << _CAN_MIR_ARB_MSGVAL_SHIFT)
| (tx << _CAN_MIR_ARB_DIR_SHIFT);
- /* Set eob bit, rx and tx interrupts */
+ /* Set EOB bit, RX, and TX interrupts. */
mir->CTRL = (endOfBuffer << _CAN_MIR_CTRL_EOB_SHIFT)
| _CAN_MIR_CTRL_TXIE_MASK
| _CAN_MIR_CTRL_RXIE_MASK
| (remoteTransfer << _CAN_MIR_CTRL_RMTEN_SHIFT);
- /* Send writing request */
+ /* Send a writing request. */
CAN_SendRequest(can, interface, msgNum, wait);
}
/***************************************************************************//**
* @brief
- * Send the data from the Message Object message.
+ * Send data from the Message Object message.
*
* @details
- * If message is configured as tx and remoteTransfer = 0, calling this function
+ * If the message is configured as TX and remoteTransfer = 0, calling this function
* will send the data of this Message Object if its parameters are correct.
- * If message is tx and remoteTransfer = 1, this function will set the data of
- * message to the RAM and exit, the data will be automatically sent after
+ * If the message is TX and remoteTransfer = 1, this function will set the data of
+ * message to RAM and exit. Data will be automatically sent after
* reception of a remote frame.
- * If message is rx and remoteTransfer = 1, this function will send a remote
- * frame to the corresponding id.
- * If message is rx and remoteTransfer = 0, the user shouldn't call this
+ * If the message is RX and remoteTransfer = 1, this function will send a remote
+ * frame to the corresponding ID.
+ * If the message is RX and remoteTransfer = 0, the user shouldn't call this
* function. It will also send a remote frame.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
*
* @param[in] message
- * Message Object
+ * A Message Object.
*
* @param[in] wait
* If true, wait for the end of the transfer between the MIRx registers and
- * the RAM to exit. If false, exit immediately, the transfer can still be
+ * RAM to exit. If false, exit immediately. The transfer can still be
* in progress.
******************************************************************************/
void CAN_SendMessage(CAN_TypeDef *can,
@@ -580,85 +580,85 @@ void CAN_SendMessage(CAN_TypeDef *can,
{
CAN_MIR_TypeDef * mir = &can->MIR[interface];
- /* Make sure msgNum is in the correct range */
+ /* Make sure msgNum is in correct range. */
EFM_ASSERT((message->msgNum > 0) && (message->msgNum <= 32));
- /* Make sure dlc is in the correct range */
+ /* Make sure dlc is in correct range. */
EFM_ASSERT(message->dlc <= _CAN_MIR_CTRL_DLC_MASK);
CAN_ReadyWait(can, interface);
- /* Set LEC to unused value to be sure it is reset to 0 after sending */
+ /* Set LEC to an unused value to be sure it is reset to 0 after sending. */
BUS_RegMaskedWrite(&can->STATUS, _CAN_STATUS_LEC_MASK, 0x7);
- /* Set which registers to read from the RAM */
+ /* Set which registers to read from RAM. */
mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
| CAN_MIR_CMDMASK_ARBACC
| CAN_MIR_CMDMASK_CONTROL;
- /* Send reading request and wait (3 to 6 cpu cycle) */
+ /* Send a reading request and wait (3 to 6 CPU cycle). */
CAN_SendRequest(can, interface, message->msgNum, true);
- /* Reset MSGVAL */
- mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD;
- mir->ARB &= ~(0x1 << _CAN_MIR_ARB_MSGVAL_SHIFT);
+ /* Reset MSGVAL. */
+ mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD_WRITE;
+ mir->ARB &= ~(0x1UL << _CAN_MIR_ARB_MSGVAL_SHIFT);
CAN_SendRequest(can, interface, message->msgNum, true);
- /* Set which registers to write to the RAM */
+ /* Set which registers to write to RAM. */
mir->CMDMASK |= CAN_MIR_CMDMASK_DATAA
| CAN_MIR_CMDMASK_DATAB;
- /* If tx = 1 and remoteTransfer = 1, nothing is sent */
+ /* If TX = 1 and remoteTransfer = 1, nothing is sent. */
if ( ((mir->CTRL & _CAN_MIR_CTRL_RMTEN_MASK) == 0)
|| ((mir->ARB & _CAN_MIR_ARB_DIR_MASK) == _CAN_MIR_ARB_DIR_RX)) {
mir->CTRL |= CAN_MIR_CTRL_TXRQST;
- /* DATAVALID is set only if it is not sending a remote message */
+ /* DATAVALID is set only if it is not sending a remote message. */
if ((mir->CTRL & _CAN_MIR_CTRL_RMTEN_MASK) == 0) {
mir->CTRL |= CAN_MIR_CTRL_DATAVALID;
}
}
- /* Set the Data length Code */
+ /* Set the data length code. */
mir->CTRL = (mir->CTRL & ~_CAN_MIR_CTRL_DLC_MASK)
| message->dlc;
- /* Configure the id */
+ /* Configure the ID. */
if (message->extended) {
EFM_ASSERT(message->id <= _CAN_MIR_ARB_ID_MASK);
mir->ARB = (mir->ARB & ~_CAN_MIR_ARB_ID_MASK)
| (message->id << _CAN_MIR_ARB_ID_SHIFT)
- | (uint32_t)(0x1 << _CAN_MIR_ARB_MSGVAL_SHIFT)
+ | (0x1UL << _CAN_MIR_ARB_MSGVAL_SHIFT)
| CAN_MIR_ARB_XTD_EXT;
} else {
EFM_ASSERT(message->id <= _CAN_MIR_ARB_STD_ID_MAX);
mir->ARB = (mir->ARB & ~(_CAN_MIR_ARB_ID_MASK | _CAN_MIR_ARB_XTD_MASK))
- | (uint32_t)(0x1 << _CAN_MIR_ARB_MSGVAL_SHIFT)
+ | (0x1UL << _CAN_MIR_ARB_MSGVAL_SHIFT)
| (message->id << _CAN_MIR_ARB_STD_ID_SHIFT)
| CAN_MIR_ARB_XTD_STD;
}
- /* Set the data */
+ /* Set data. */
CAN_WriteData(can, interface, message);
- /* Send writing request */
+ /* Send a writing request. */
CAN_SendRequest(can, interface, message->msgNum, wait);
}
/***************************************************************************//**
* @brief
- * Read the data from a Message Object in the RAM and store it in message.
+ * Read data from a Message Object in RAM and store it in a message.
*
* @details
- * Read all the information from the RAM on this Message Object : the data but
+ * Read the information from RAM on this Message Object : data but
* also the configuration of the other registers.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
*
* @param[in] message
- * Message Object
+ * A Message Object.
******************************************************************************/
void CAN_ReadMessage(CAN_TypeDef *can,
uint8_t interface,
@@ -668,12 +668,12 @@ void CAN_ReadMessage(CAN_TypeDef *can,
uint32_t buffer;
uint32_t i;
- /* Make sure msgNum is in the correct range */
+ /* Make sure msgNum is in correct range. */
EFM_ASSERT((message->msgNum > 0) && (message->msgNum <= 32));
CAN_ReadyWait(can, interface);
- /* Set which registers to read from the RAM */
+ /* Set which registers to read from RAM. */
mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
| CAN_MIR_CMDMASK_MASKACC
| CAN_MIR_CMDMASK_ARBACC
@@ -683,16 +683,23 @@ void CAN_ReadMessage(CAN_TypeDef *can,
| CAN_MIR_CMDMASK_DATAA
| CAN_MIR_CMDMASK_DATAB;
- /* Send reading request and wait (3 to 6 cpu cycle) */
+ /* Send a reading request and wait (3 to 6 cpu cycle). */
CAN_SendRequest(can, interface, message->msgNum, true);
- /* Get dlc from the control register */
+ /* Get dlc from the control register. */
message->dlc = ((mir->CTRL & _CAN_MIR_CTRL_DLC_MASK) >> _CAN_MIR_CTRL_DLC_SHIFT);
- /* Make sure dlc is in the correct range */
+ /* Make sure dlc is in correct range. */
EFM_ASSERT(message->dlc <= 8);
- /* Copy the data from the MIR registers to the Message Object message */
+ /* Get id from the control register */
+ if (message->extended) {
+ message->id = (mir->ARB & _CAN_MIR_ARB_ID_MASK);
+ } else {
+ message->id = ((mir->ARB & _CAN_MIR_ARB_STD_ID_MASK) >> _CAN_MIR_ARB_STD_ID_SHIFT);
+ }
+
+ /* Copy data from the MIR registers to the Message Object message. */
buffer = mir->DATAL;
for (i = 0; i < SL_MIN(message->dlc, 4U); ++i) {
message->data[i] = buffer & 0xFF;
@@ -709,25 +716,25 @@ void CAN_ReadMessage(CAN_TypeDef *can,
/***************************************************************************//**
* @brief
- * Abort the sending of a message
+ * Abort sending a message.
*
* @details
- * Set the TXRQST of the CTRL register to 0. Doesn't touch the data ot the
- * others parameters. The user can reuse CAN_SendMessage() to send the object
+ * Set the TXRQST of the CTRL register to 0. Doesn't touch data or the
+ * other parameters. The user can call CAN_SendMessage() to send the object
* after using CAN_AbortSendMessage().
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
*
* @param[in] msgNum
- * Message number of this Message Object, [1 - 32].
+ * A message number of this Message Object, [1 - 32].
*
* @param[in] wait
* If true, wait for the end of the transfer between the MIRx registers and
- * the RAM to exit. If false, exit immediately, the transfer can still be
+ * the RAM to exit. If false, exit immediately. The transfer can still be
* in progress.
******************************************************************************/
void CAN_AbortSendMessage(CAN_TypeDef *can,
@@ -735,29 +742,36 @@ void CAN_AbortSendMessage(CAN_TypeDef *can,
uint8_t msgNum,
bool wait)
{
- /* Make sure msgNum is in the correct range */
+ /* Make sure msgNum is in correct range. */
EFM_ASSERT((msgNum > 0) && (msgNum <= 32));
CAN_MIR_TypeDef * mir = &can->MIR[interface];
CAN_ReadyWait(can, interface);
- /* Set which registers to write to the RAM */
+ /* Set which registers to read from RAM. */
+ mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
+ | CAN_MIR_CMDMASK_CONTROL;
+
+ /* Send a reading request and wait (3 to 6 cpu cycle). */
+ CAN_SendRequest(can, interface, msgNum, true);
+
+ /* Set which registers to write to RAM. */
mir->CMDMASK = CAN_MIR_CMDMASK_WRRD
- | CAN_MIR_CMDMASK_ARBACC;
+ | CAN_MIR_CMDMASK_CONTROL;
- /* Set TXRQST bit to 0 */
- mir->ARB &= ~_CAN_MIR_CTRL_TXRQST_MASK;
+ /* Set TXRQST bit to 0. */
+ mir->CTRL &= ~_CAN_MIR_CTRL_TXRQST_MASK;
- /* Send writing request */
+ /* Send a writing request. */
CAN_SendRequest(can, interface, msgNum, wait);
}
/***************************************************************************//**
* @brief
- * Reset all the Message Objects and set their data to 0.
+ * Reset all Message Objects and set their data to 0.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
@@ -767,7 +781,7 @@ void CAN_ResetMessages(CAN_TypeDef *can, uint8_t interface)
CAN_MIR_TypeDef * mir = &can->MIR[interface];
CAN_ReadyWait(can, interface);
- /* Set which registers to read from the RAM */
+ /* Set which registers to read from RAM. */
mir->CMDMASK = CAN_MIR_CMDMASK_WRRD
| CAN_MIR_CMDMASK_MASKACC
| CAN_MIR_CMDMASK_ARBACC
@@ -781,7 +795,7 @@ void CAN_ResetMessages(CAN_TypeDef *can, uint8_t interface)
mir->DATAL = 0x00000000;
mir->DATAH = 0x00000000;
- /* Write each reset Message Object to the RAM */
+ /* Write each reset Message Object to RAM. */
for (int i = 1; i <= 32; ++i) {
CAN_SendRequest(can, interface, i, true);
}
@@ -789,10 +803,10 @@ void CAN_ResetMessages(CAN_TypeDef *can, uint8_t interface)
/***************************************************************************//**
* @brief
- * Set all the CAN registers to RESETVALUE. Leave the CAN Device disabled.
+ * Set all CAN registers to RESETVALUE. Leave the CAN device disabled.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
******************************************************************************/
void CAN_Reset(CAN_TypeDef *can)
{
@@ -833,56 +847,61 @@ void CAN_Reset(CAN_TypeDef *can)
/***************************************************************************//**
* @brief
- * Write the data from message to the MIRx registers
+ * Write data from a message to the MIRx registers.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
*
* @param[in] message
- * Message Object
+ * A Message Object.
******************************************************************************/
void CAN_WriteData(CAN_TypeDef *can,
uint8_t interface,
const CAN_MessageObject_TypeDef *message)
{
- CAN_MIR_TypeDef * mir = &can->MIR[interface];
+ uint32_t tmp;
uint8_t data[8] = { 0 };
size_t length = SL_MIN(8, message->dlc);
+ CAN_MIR_TypeDef * mir = &can->MIR[interface];
for (size_t i = 0; i < length; i++) {
data[i] = message->data[i];
}
CAN_ReadyWait(can, interface);
- mir->DATAL = (data[3] << 24)
- | (data[2] << 16)
- | (data[1] << 8)
- | (data[0] << 0);
- mir->DATAH = (data[7] << 24)
- | (data[6] << 16)
- | (data[5] << 8)
- | (data[4] << 0);
+
+ tmp = data[0];
+ tmp |= data[1] << 8;
+ tmp |= data[2] << 16;
+ tmp |= data[3] << 24;
+ mir->DATAL = tmp;
+
+ tmp = data[4];
+ tmp |= data[5] << 8;
+ tmp |= data[6] << 16;
+ tmp |= data[7] << 24;
+ mir->DATAH = tmp;
}
/***************************************************************************//**
* @brief
- * Send request for writing or reading the RAM of Message Object msgNum.
+ * Send a request for writing or reading RAM of the Message Object msgNum.
*
* @param[in] can
- * Pointer to CAN peripheral register block.
+ * A pointer to the CAN peripheral register block.
*
* @param[in] interface
* Indicate which Message Interface Register to use.
*
* @param[in] msgNum
- * Message number of the Message Object, [1 - 32].
+ * A message number of the Message Object, [1 - 32].
*
* @param[in] wait
* If true, wait for the end of the transfer between the MIRx registers and
- * the RAM to exit. If false, exit immediately, the transfer can still be
+ * the RAM to exit. If false, exit immediately. The transfer can still be
* in progress.
******************************************************************************/
void CAN_SendRequest(CAN_TypeDef *can,
@@ -892,13 +911,13 @@ void CAN_SendRequest(CAN_TypeDef *can,
{
CAN_MIR_TypeDef * mir = &can->MIR[interface];
- /* Make sure msgNum is in the correct range */
+ /* Make sure msgNum is in correct range. */
EFM_ASSERT((msgNum > 0) && (msgNum <= 32));
- /* Make sure the MIRx registers aren't busy */
+ /* Make sure the MIRx registers aren't busy. */
CAN_ReadyWait(can, interface);
- /* Write msgNum to the CMDREQ register */
+ /* Write msgNum to the CMDREQ register. */
mir->CMDREQ = msgNum << _CAN_MIR_CMDREQ_MSGNUM_SHIFT;
if (wait) {
diff --git a/targets/targets.json b/targets/targets.json
index 278cd63b03f..baac3eaf55b 100644
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -6237,6 +6237,7 @@
"device_name": "EFM32GG11B820F2048GL192",
"device_has": [
"ANALOGIN",
+ "CAN",
"CRC",
"EMAC",
"I2C",