mirror of https://github.com/ARMmbed/mbed-os.git
Add can_api.c for efm32
parent
6bdbe754cd
commit
0a82591470
|
|
@ -136,6 +136,13 @@ typedef enum {
|
|||
} UARTName;
|
||||
#endif
|
||||
|
||||
#if DEVICE_CAN
|
||||
typedef enum {
|
||||
CAN_0 = (int)CAN0_BASE,
|
||||
CAN_1 = (int)CAN1_BASE
|
||||
} CANName;
|
||||
#endif
|
||||
|
||||
#if DEVICE_QSPI
|
||||
typedef enum {
|
||||
#ifdef QSPI0_BASE
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MBED_CAN_DEVICE_H
|
||||
#define MBED_CAN_DEVICE_H
|
||||
|
||||
#include "cmsis.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if DEVICE_CAN
|
||||
|
||||
#define CAN_COUNT 2 // Number of CAN peripherals
|
||||
|
||||
|
||||
#endif // DEVICE_CAN
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
*
|
||||
* 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 "can_device.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) {
|
||||
case CAN_0:
|
||||
cmuClock_number = cmuClock_CAN0;
|
||||
break;
|
||||
case CAN_1:
|
||||
cmuClock_number = cmuClock_CAN1;
|
||||
break;
|
||||
}
|
||||
|
||||
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) {
|
||||
case CAN_0:
|
||||
index = 0;
|
||||
break;
|
||||
case CAN_1:
|
||||
index = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
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) {
|
||||
case CAN_0:
|
||||
NVIC_DisableIRQ(CAN0_IRQn);
|
||||
break;
|
||||
case CAN_1:
|
||||
NVIC_DisableIRQ(CAN1_IRQn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
case CAN_0:
|
||||
NVIC_SetVector(CAN0_IRQn, CAN0_IRQHandler);
|
||||
NVIC_EnableIRQ(CAN0_IRQn);
|
||||
break;
|
||||
case CAN_1:
|
||||
NVIC_SetVector(CAN1_IRQn, CAN1_IRQHandler);
|
||||
NVIC_EnableIRQ(CAN1_IRQn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void CAN0_IRQHandler(void)
|
||||
{
|
||||
can_irq(CAN_0, 0);
|
||||
}
|
||||
|
||||
void CAN1_IRQHandler(void)
|
||||
{
|
||||
can_irq(CAN_1, 1);
|
||||
}
|
||||
|
||||
|
||||
const PinMap *can_rd_pinmap()
|
||||
{
|
||||
return PinMap_CAN_TX;
|
||||
}
|
||||
|
||||
const PinMap *can_td_pinmap()
|
||||
{
|
||||
return PinMap_CAN_RX;
|
||||
}
|
||||
|
||||
#endif // DEVICE_CAN
|
||||
|
|
@ -1,33 +1,32 @@
|
|||
/***************************************************************************//**
|
||||
* @file em_can.h
|
||||
* @file
|
||||
* @brief Controller Area Network API
|
||||
* @version 5.3.3
|
||||
* @version 5.7.2
|
||||
*******************************************************************************
|
||||
* # License
|
||||
* <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b>
|
||||
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,33 +1,32 @@
|
|||
/***************************************************************************//**
|
||||
* @file em_can.c
|
||||
* @file
|
||||
* @brief Controller Area Network API
|
||||
* @version 5.3.3
|
||||
* @version 5.7.2
|
||||
*******************************************************************************
|
||||
* # License
|
||||
* <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b>
|
||||
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* 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) {
|
||||
|
|
|
|||
|
|
@ -6237,6 +6237,7 @@
|
|||
"device_name": "EFM32GG11B820F2048GL192",
|
||||
"device_has": [
|
||||
"ANALOGIN",
|
||||
"CAN",
|
||||
"CRC",
|
||||
"EMAC",
|
||||
"I2C",
|
||||
|
|
|
|||
Loading…
Reference in New Issue