tinySA/os/hal/platforms/SPC5xx/FlexCAN_v1/can_lld.c

1668 lines
39 KiB
C

/*
SPC5 HAL - Copyright (C) 2013 STMicroelectronics
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.
*/
/**
* @file FlexCAN_v1/can_lld.c
* @brief SPC5xx CAN subsystem low level driver source.
*
* @addtogroup CAN
* @{
*/
#include "ch.h"
#include "hal.h"
#if HAL_USE_CAN || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief CAN1 driver identifier.*/
#if SPC5_CAN_USE_FLEXCAN0 || defined(__DOXYGEN__)
CANDriver CAND1;
#endif
/** @brief CAN2 driver identifier.*/
#if SPC5_CAN_USE_FLEXCAN1 || defined(__DOXYGEN__)
CANDriver CAND2;
#endif
/** @brief CAN3 driver identifier.*/
#if SPC5_CAN_USE_FLEXCAN2 || defined(__DOXYGEN__)
CANDriver CAND3;
#endif
/** @brief CAN4 driver identifier.*/
#if SPC5_CAN_USE_FLEXCAN3 || defined(__DOXYGEN__)
CANDriver CAND4;
#endif
/** @brief CAN5 driver identifier.*/
#if SPC5_CAN_USE_FLEXCAN4 || defined(__DOXYGEN__)
CANDriver CAND5;
#endif
/** @brief CAN6 driver identifier.*/
#if SPC5_CAN_USE_FLEXCAN5 || defined(__DOXYGEN__)
CANDriver CAND6;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Common TX ISR handler.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
static void can_lld_tx_handler(CANDriver *canp) {
uint32_t iflag1, iflag2;
iflag1 = canp->flexcan->IFRL.R;
iflag2 = canp->flexcan->IFRH.R;
/* No more events until a message is transmitted.*/
canp->flexcan->IFRL.R |= iflag1 & 0xFFFFFF00;
canp->flexcan->IFRH.R |= canp->flexcan->IFRH.R & 0xFFFFFFFF;
chSysLockFromIsr();
while (chSemGetCounterI(&canp->txsem) < 0)
chSemSignalI(&canp->txsem);
#if SPC5_CAN_USE_FLEXCAN0 && (SPC5_FLEXCAN0_MB == 32)
if(&CAND1 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag1 & 0xFFFFFF00);
}
#elif SPC5_CAN_USE_FLEXCAN0 && (SPC5_FLEXCAN0_MB == 64)
if(&CAND1 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag2 | (iflag1 & 0xFFFFFF00));
}
#endif
#if SPC5_CAN_USE_FLEXCAN1 && (SPC5_FLEXCAN1_MB == 32)
if(&CAND2 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag1 & 0xFFFFFF00);
}
#elif SPC5_CAN_USE_FLEXCAN1 && (SPC5_FLEXCAN1_MB == 64)
if(&CAND2 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag2 | (iflag1 & 0xFFFFFF00));
}
#endif
#if SPC5_CAN_USE_FLEXCAN2 && (SPC5_FLEXCAN2_MB == 32)
if(&CAND3 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag1 & 0xFFFFFF00);
}
#elif SPC5_CAN_USE_FLEXCAN2 && (SPC5_FLEXCAN2_MB == 64)
if(&CAND3 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag2 | (iflag1 & 0xFFFFFF00));
}
#endif
#if SPC5_CAN_USE_FLEXCAN3 && (SPC5_FLEXCAN3_MB == 32)
if(&CAND4 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag1 & 0xFFFFFF00);
}
#elif SPC5_CAN_USE_FLEXCAN3 && (SPC5_FLEXCAN3_MB == 64)
if(&CAND4 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag2 | (iflag1 & 0xFFFFFF00));
}
#endif
#if SPC5_CAN_USE_FLEXCAN4 && (SPC5_FLEXCAN4_MB == 32)
if(&CAND5 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag1 & 0xFFFFFF00);
}
#elif SPC5_CAN_USE_FLEXCAN4 && (SPC5_FLEXCAN4_MB == 64)
if(&CAND5 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag2 | (iflag1 & 0xFFFFFF00));
}
#endif
#if SPC5_CAN_USE_FLEXCAN5 && (SPC5_FLEXCAN5_MB == 32)
if(&CAND6 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag1 & 0xFFFFFF00);
}
#elif SPC5_CAN_USE_FLEXCAN5 && (SPC5_FLEXCAN5_MB == 64)
if(&CAND6 == canp) {
chEvtBroadcastFlagsI(&canp->txempty_event, iflag2 | (iflag1 & 0xFFFFFF00));
}
#endif
chSysUnlockFromIsr();
}
/**
* @brief Common RX ISR handler.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
static void can_lld_rx_handler(CANDriver *canp) {
uint32_t iflag1;
iflag1 = canp->flexcan->IFRL.R;
if ((iflag1 & 0x000000FF) != 0) {
chSysLockFromIsr();
while (chSemGetCounterI(&canp->rxsem) < 0)
chSemSignalI(&canp->rxsem);
chEvtBroadcastFlagsI(&canp->rxfull_event, iflag1 & 0x000000FF);
chSysUnlockFromIsr();
/* Release the mailbox.*/
canp->flexcan->IFRL.R |= iflag1 & 0x000000FF;
}
}
/**
* @brief Common error ISR handler.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
static void can_lld_err_handler(CANDriver *canp) {
uint32_t esr = canp->flexcan->ESR.R;
flagsmask_t flags = 0;
/* Error event.*/
if ((esr & CAN_ESR_TWRN_INT) || (esr & CAN_ESR_RWRN_INT)) {
canp->flexcan->ESR.B.TXWRN = 1U;
canp->flexcan->ESR.B.RXWRN = 1U;
flags |= CAN_LIMIT_WARNING;
}
if (esr & CAN_ESR_BOFF_INT) {
canp->flexcan->ESR.B.BOFFINT = 1U;
flags |= CAN_BUS_OFF_ERROR;
}
if (esr & CAN_ESR_ERR_INT) {
canp->flexcan->ESR.B.ERRINT = 1U;
flags |= CAN_FRAMING_ERROR;
}
chSysLockFromIsr();
chEvtBroadcastFlagsI(&canp->error_event, flags);
chSysUnlockFromIsr();
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if SPC5_CAN_USE_FLEXCAN0 || defined(__DOXYGEN__)
/**
* @brief CAN1 TX interrupt handler for MB 8-11.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN0_FLEXCAN_BUF_08_11_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN1 TX interrupt handler for MB 12-15.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN0_FLEXCAN_BUF_12_15_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN1 TX interrupt handler for MB 16-31.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN0_FLEXCAN_BUF_16_31_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
#if (SPC5_FLEXCAN0_MB == 64)
/**
* @brief CAN1 TX interrupt handler for MB 32-63.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN0_FLEXCAN_BUF_32_63_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
#endif
/*
* @brief CAN1 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN0_FLEXCAN_BUF_00_03_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
/*
* @brief CAN1 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN0_FLEXCAN_BUF_04_07_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN1 ESR_ERR_INT interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN0_FLEXCAN_ESR_ERR_INT_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN1 ESR_BOFF interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN0_FLEXCAN_ESR_BOFF_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND1);
CH_IRQ_EPILOGUE();
}
#endif /* SPC5_CAN_USE_FLEXCAN0 */
#if SPC5_CAN_USE_FLEXCAN1 || defined(__DOXYGEN__)
/**
* @brief CAN2 TX interrupt handler for MB 8-11.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN1_FLEXCAN_BUF_08_11_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND2);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN2 TX interrupt handler for MB 12-15.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN1_FLEXCAN_BUF_12_15_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND2);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN2 TX interrupt handler for MB 16-31.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN1_FLEXCAN_BUF_16_31_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND2);
CH_IRQ_EPILOGUE();
}
#if (SPC5_FLEXCAN1_MB == 64)
/**
* @brief CAN2 TX interrupt handler for MB 32-63.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN1_FLEXCAN_BUF_32_63_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND2);
CH_IRQ_EPILOGUE();
}
#endif
/*
* @brief CAN2 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN1_FLEXCAN_BUF_00_03_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND2);
CH_IRQ_EPILOGUE();
}
/*
* @brief CAN2 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN1_FLEXCAN_BUF_04_07_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND2);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN2 ESR_ERR_INT interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN1_FLEXCAN_ESR_ERR_INT_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND2);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN2 ESR_BOFF interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN1_FLEXCAN_ESR_BOFF_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND2);
CH_IRQ_EPILOGUE();
}
#endif /* SPC5_CAN_USE_FLEXCAN1 */
#if SPC5_CAN_USE_FLEXCAN2 || defined(__DOXYGEN__)
/**
* @brief CAN3 TX interrupt handler for MB 8-11.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN2_FLEXCAN_BUF_08_11_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND3);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN3 TX interrupt handler for MB 12-15.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN2_FLEXCAN_BUF_12_15_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND3);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN3 TX interrupt handler for MB 16-31.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN2_FLEXCAN_BUF_16_31_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND3);
CH_IRQ_EPILOGUE();
}
#if (SPC5_FLEXCAN2_MB == 64)
/**
* @brief CAN3 TX interrupt handler for MB 32-63.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN2_FLEXCAN_BUF_32_63_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND3);
CH_IRQ_EPILOGUE();
}
#endif
/*
* @brief CAN3 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN2_FLEXCAN_BUF_00_03_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND3);
CH_IRQ_EPILOGUE();
}
/*
* @brief CAN3 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN2_FLEXCAN_BUF_04_07_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND3);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN3 ESR_ERR_INT interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN2_FLEXCAN_ESR_ERR_INT_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND3);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN3 ESR_BOFF interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN2_FLEXCAN_ESR_BOFF_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND3);
CH_IRQ_EPILOGUE();
}
#endif /* SPC5_CAN_USE_FLEXCAN2 */
#if SPC5_CAN_USE_FLEXCAN3 || defined(__DOXYGEN__)
/**
* @brief CAN4 TX interrupt handler for MB 8-11.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN3_FLEXCAN_BUF_08_11_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND4);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN4 TX interrupt handler for MB 12-15.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN3_FLEXCAN_BUF_12_15_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND4);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN4 TX interrupt handler for MB 16-31.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN3_FLEXCAN_BUF_16_31_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND4);
CH_IRQ_EPILOGUE();
}
#if (SPC5_FLEXCAN3_MB == 64)
/**
* @brief CAN4 TX interrupt handler for MB 32-63.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN3_FLEXCAN_BUF_32_63_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND4);
CH_IRQ_EPILOGUE();
}
#endif
/*
* @brief CAN4 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN3_FLEXCAN_BUF_00_03_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND4);
CH_IRQ_EPILOGUE();
}
/*
* @brief CAN4 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN3_FLEXCAN_BUF_04_07_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND4);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN4 ESR_ERR_INT interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN3_FLEXCAN_ESR_ERR_INT_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND4);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN4 ESR_BOFF interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN3_FLEXCAN_ESR_BOFF_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND4);
CH_IRQ_EPILOGUE();
}
#endif /* SPC5_CAN_USE_FLEXCAN3 */
#if SPC5_CAN_USE_FLEXCAN4 || defined(__DOXYGEN__)
/**
* @brief CAN5 TX interrupt handler for MB 8-11.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN4_FLEXCAN_BUF_08_11_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND5);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN5 TX interrupt handler for MB 12-15.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN4_FLEXCAN_BUF_12_15_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND5);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN5 TX interrupt handler for MB 16-31.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN4_FLEXCAN_BUF_16_31_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND5);
CH_IRQ_EPILOGUE();
}
#if (SPC5_FLEXCAN4_MB == 64)
/**
* @brief CAN5 TX interrupt handler for MB 32-63.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN4_FLEXCAN_BUF_32_63_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND5);
CH_IRQ_EPILOGUE();
}
#endif
/*
* @brief CAN5 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN4_FLEXCAN_BUF_00_03_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND5);
CH_IRQ_EPILOGUE();
}
/*
* @brief CAN5 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN4_FLEXCAN_BUF_04_07_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND5);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN5 ESR_ERR_INT interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN4_FLEXCAN_ESR_ERR_INT_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND5);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN5 ESR_BOFF interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN4_FLEXCAN_ESR_BOFF_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND5);
CH_IRQ_EPILOGUE();
}
#endif /* SPC5_CAN_USE_FLEXCAN4 */
#if SPC5_CAN_USE_FLEXCAN5 || defined(__DOXYGEN__)
/**
* @brief CAN6 TX interrupt handler for MB 8-11.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN5_FLEXCAN_BUF_08_11_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND6);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN6 TX interrupt handler for MB 12-15.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN5_FLEXCAN_BUF_12_15_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND6);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN6 TX interrupt handler for MB 16-31.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN5_FLEXCAN_BUF_16_31_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND6);
CH_IRQ_EPILOGUE();
}
#if (SPC5_FLEXCAN5_MB == 64)
/**
* @brief CAN6 TX interrupt handler for MB 32-63.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN5_FLEXCAN_BUF_32_63_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_tx_handler(&CAND6);
CH_IRQ_EPILOGUE();
}
#endif
/*
* @brief CAN6 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN5_FLEXCAN_BUF_00_03_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND6);
CH_IRQ_EPILOGUE();
}
/*
* @brief CAN6 RX interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN5_FLEXCAN_BUF_04_07_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_rx_handler(&CAND6);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN6 ESR_ERR_INT interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN5_FLEXCAN_ESR_ERR_INT_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND6);
CH_IRQ_EPILOGUE();
}
/**
* @brief CAN6 ESR_BOFF interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(SPC5_FLEXCAN5_FLEXCAN_ESR_BOFF_HANDLER) {
CH_IRQ_PROLOGUE();
can_lld_err_handler(&CAND6);
CH_IRQ_EPILOGUE();
}
#endif /* SPC5_CAN_USE_FLEXCAN5 */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level CAN driver initialization.
*
* @notapi
*/
void can_lld_init(void) {
#if SPC5_CAN_USE_FLEXCAN0
/* Driver initialization.*/
canObjectInit(&CAND1);
CAND1.flexcan = &SPC5_FLEXCAN_0;
INTC.PSR[SPC5_FLEXCAN0_FLEXCAN_ESR_ERR_INT_NUMBER].R =
SPC5_CAN_FLEXCAN0_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN0_FLEXCAN_ESR_BOFF_NUMBER].R =
SPC5_CAN_FLEXCAN0_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN0_FLEXCAN_BUF_00_03_NUMBER].R =
SPC5_CAN_FLEXCAN0_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN0_FLEXCAN_BUF_04_07_NUMBER].R =
SPC5_CAN_FLEXCAN0_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN0_FLEXCAN_BUF_08_11_NUMBER].R =
SPC5_CAN_FLEXCAN0_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN0_FLEXCAN_BUF_12_15_NUMBER].R =
SPC5_CAN_FLEXCAN0_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN0_FLEXCAN_BUF_16_31_NUMBER].R =
SPC5_CAN_FLEXCAN0_IRQ_PRIORITY;
#endif
#if SPC5_CAN_USE_FLEXCAN1
/* Driver initialization.*/
canObjectInit(&CAND2);
CAND2.flexcan = &SPC5_FLEXCAN_1;
INTC.PSR[SPC5_FLEXCAN1_FLEXCAN_ESR_ERR_INT_NUMBER].R =
SPC5_CAN_FLEXCAN1_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN1_FLEXCAN_ESR_BOFF_NUMBER].R =
SPC5_CAN_FLEXCAN1_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN1_FLEXCAN_BUF_00_03_NUMBER].R =
SPC5_CAN_FLEXCAN1_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN1_FLEXCAN_BUF_04_07_NUMBER].R =
SPC5_CAN_FLEXCAN1_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN1_FLEXCAN_BUF_08_11_NUMBER].R =
SPC5_CAN_FLEXCAN1_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN1_FLEXCAN_BUF_12_15_NUMBER].R =
SPC5_CAN_FLEXCAN1_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN1_FLEXCAN_BUF_16_31_NUMBER].R =
SPC5_CAN_FLEXCAN1_IRQ_PRIORITY;
#endif
#if SPC5_CAN_USE_FLEXCAN2
/* Driver initialization.*/
canObjectInit(&CAND3);
CAND3.flexcan = &SPC5_FLEXCAN_2;
INTC.PSR[SPC5_FLEXCAN2_FLEXCAN_ESR_ERR_INT_NUMBER].R =
SPC5_CAN_FLEXCAN2_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN2_FLEXCAN_ESR_BOFF_NUMBER].R =
SPC5_CAN_FLEXCAN2_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN2_FLEXCAN_BUF_00_03_NUMBER].R =
SPC5_CAN_FLEXCAN2_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN2_FLEXCAN_BUF_04_07_NUMBER].R =
SPC5_CAN_FLEXCAN2_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN2_FLEXCAN_BUF_08_11_NUMBER].R =
SPC5_CAN_FLEXCAN2_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN2_FLEXCAN_BUF_12_15_NUMBER].R =
SPC5_CAN_FLEXCAN2_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN2_FLEXCAN_BUF_16_31_NUMBER].R =
SPC5_CAN_FLEXCAN2_IRQ_PRIORITY;
#endif
#if SPC5_CAN_USE_FLEXCAN3
/* Driver initialization.*/
canObjectInit(&CAND4);
CAND4.flexcan = &SPC5_FLEXCAN_3;
INTC.PSR[SPC5_FLEXCAN3_FLEXCAN_ESR_ERR_INT_NUMBER].R =
SPC5_CAN_FLEXCAN3_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN3_FLEXCAN_ESR_BOFF_NUMBER].R =
SPC5_CAN_FLEXCAN3_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN3_FLEXCAN_BUF_00_03_NUMBER].R =
SPC5_CAN_FLEXCAN3_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN3_FLEXCAN_BUF_04_07_NUMBER].R =
SPC5_CAN_FLEXCAN3_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN3_FLEXCAN_BUF_08_11_NUMBER].R =
SPC5_CAN_FLEXCAN3_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN3_FLEXCAN_BUF_12_15_NUMBER].R =
SPC5_CAN_FLEXCAN3_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN3_FLEXCAN_BUF_16_31_NUMBER].R =
SPC5_CAN_FLEXCAN3_IRQ_PRIORITY;
#endif
#if SPC5_CAN_USE_FLEXCAN4
/* Driver initialization.*/
canObjectInit(&CAND5);
CAND5.flexcan = &SPC5_FLEXCAN_4;
INTC.PSR[SPC5_FLEXCAN4_FLEXCAN_ESR_ERR_INT_NUMBER].R =
SPC5_CAN_FLEXCAN4_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN4_FLEXCAN_ESR_BOFF_NUMBER].R =
SPC5_CAN_FLEXCAN4_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN4_FLEXCAN_BUF_00_03_NUMBER].R =
SPC5_CAN_FLEXCAN4_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN4_FLEXCAN_BUF_04_07_NUMBER].R =
SPC5_CAN_FLEXCAN4_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN4_FLEXCAN_BUF_08_11_NUMBER].R =
SPC5_CAN_FLEXCAN4_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN4_FLEXCAN_BUF_12_15_NUMBER].R =
SPC5_CAN_FLEXCAN4_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN4_FLEXCAN_BUF_16_31_NUMBER].R =
SPC5_CAN_FLEXCAN4_IRQ_PRIORITY;
#endif
#if SPC5_CAN_USE_FLEXCAN5
/* Driver initialization.*/
canObjectInit(&CAND6);
CAND6.flexcan = &SPC5_FLEXCAN_5;
INTC.PSR[SPC5_FLEXCAN5_FLEXCAN_ESR_ERR_INT_NUMBER].R =
SPC5_CAN_FLEXCAN5_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN5_FLEXCAN_ESR_BOFF_NUMBER].R =
SPC5_CAN_FLEXCAN5_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN5_FLEXCAN_BUF_00_03_NUMBER].R =
SPC5_CAN_FLEXCAN5_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN5_FLEXCAN_BUF_04_07_NUMBER].R =
SPC5_CAN_FLEXCAN5_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN5_FLEXCAN_BUF_08_11_NUMBER].R =
SPC5_CAN_FLEXCAN5_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN5_FLEXCAN_BUF_12_15_NUMBER].R =
SPC5_CAN_FLEXCAN5_IRQ_PRIORITY;
INTC.PSR[SPC5_FLEXCAN5_FLEXCAN_BUF_16_31_NUMBER].R =
SPC5_CAN_FLEXCAN5_IRQ_PRIORITY;
#endif
}
/**
* @brief Configures and activates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
void can_lld_start(CANDriver *canp) {
uint8_t mb_index = 0, id = 0;
/* Clock activation.*/
#if SPC5_CAN_USE_FLEXCAN0
/* Set peripheral clock mode.*/
if(&CAND1 == canp)
SPC5_FLEXCAN0_ENABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN1
/* Set peripheral clock mode.*/
if(&CAND2 == canp)
SPC5_FLEXCAN1_ENABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN2
/* Set peripheral clock mode.*/
if(&CAND3 == canp)
SPC5_FLEXCAN2_ENABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN3
/* Set peripheral clock mode.*/
if(&CAND4 == canp)
SPC5_FLEXCAN3_ENABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN4
/* Set peripheral clock mode.*/
if(&CAND5 == canp)
SPC5_FLEXCAN4_ENABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN5
/* Set peripheral clock mode.*/
if(&CAND6 == canp)
SPC5_FLEXCAN5_ENABLE_CLOCK();
#endif
/* Entering initialization mode. */
canp->state = CAN_STARTING;
canp->flexcan->CR.R |= CAN_CTRL_CLK_SRC;
canp->flexcan->MCR.R &= ~CAN_MCR_MDIS;
/*
* Individual filtering per MB, disable frame self reception,
* disable the FIFO, enable SuperVisor mode.
*/
#if SPC5_CAN_USE_FLEXCAN0
if(&CAND1 == canp)
canp->flexcan->MCR.R |= CAN_MCR_SUPV | CAN_MCR_MAXMB(SPC5_FLEXCAN0_MB - 1);
#endif
#if SPC5_CAN_USE_FLEXCAN1
if(&CAND2 == canp)
canp->flexcan->MCR.R |= CAN_MCR_SUPV | CAN_MCR_MAXMB(SPC5_FLEXCAN1_MB - 1);
#endif
#if SPC5_CAN_USE_FLEXCAN2
if(&CAND3 == canp)
canp->flexcan->MCR.R |= CAN_MCR_SUPV | CAN_MCR_MAXMB(SPC5_FLEXCAN2_MB - 1);
#endif
#if SPC5_CAN_USE_FLEXCAN3
if(&CAND4 == canp)
canp->flexcan->MCR.R |= CAN_MCR_SUPV | CAN_MCR_MAXMB(SPC5_FLEXCAN3_MB - 1);
#endif
#if SPC5_CAN_USE_FLEXCAN4
if(&CAND5 == canp)
canp->flexcan->MCR.R |= CAN_MCR_SUPV | CAN_MCR_MAXMB(SPC5_FLEXCAN4_MB - 1);
#endif
#if SPC5_CAN_USE_FLEXCAN5
if(&CAND6 == canp)
canp->flexcan->MCR.R |= CAN_MCR_SUPV | CAN_MCR_MAXMB(SPC5_FLEXCAN5_MB - 1);
#endif
canp->flexcan->CR.R |= CAN_CTRL_TSYN | CAN_CTRL_RJW(3);
/* TX MB initialization.*/
#if SPC5_CAN_USE_FLEXCAN0
if(&CAND1 == canp) {
for(mb_index = 0; mb_index < (SPC5_FLEXCAN0_MB - CAN_RX_MAILBOXES);
mb_index++) {
canp->flexcan->BUF[mb_index + CAN_RX_MAILBOXES].CS.B.CODE = 8U;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN1
if(&CAND2 == canp) {
for(mb_index = 0; mb_index < (SPC5_FLEXCAN1_MB - CAN_RX_MAILBOXES);
mb_index++) {
canp->flexcan->BUF[mb_index + CAN_RX_MAILBOXES].CS.B.CODE = 8U;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN2
if(&CAND3 == canp) {
for(mb_index = 0; mb_index < (SPC5_FLEXCAN2_MB - CAN_RX_MAILBOXES);
mb_index++) {
canp->flexcan->BUF[mb_index + CAN_RX_MAILBOXES].CS.B.CODE = 8U;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN3
if(&CAND4 == canp) {
for(mb_index = 0; mb_index < (SPC5_FLEXCAN3_MB - CAN_RX_MAILBOXES);
mb_index++) {
canp->flexcan->BUF[mb_index + CAN_RX_MAILBOXES].CS.B.CODE = 8U;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN4
if(&CAND5 == canp) {
for(mb_index = 0; mb_index < (SPC5_FLEXCAN4_MB - CAN_RX_MAILBOXES);
mb_index++) {
canp->flexcan->BUF[mb_index + CAN_RX_MAILBOXES].CS.B.CODE = 8U;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN5
if(&CAND6 == canp) {
for(mb_index = 0; mb_index < (SPC5_FLEXCAN5_MB - CAN_RX_MAILBOXES);
mb_index++) {
canp->flexcan->BUF[mb_index + CAN_RX_MAILBOXES].CS.B.CODE = 8U;
}
}
#endif
/* Unlock Message buffers.*/
(void) canp->flexcan->TIMER.R;
/* MCR initialization.*/
canp->flexcan->MCR.R |= canp->config->mcr;
/* CTRL initialization.*/
canp->flexcan->CR.R |= canp->config->ctrl;
/* Interrupt sources initialization.*/
canp->flexcan->MCR.R |= CAN_MCR_WRN_EN;
canp->flexcan->CR.R |= CAN_CTRL_BOFF_MSK | CAN_CTRL_ERR_MSK |
CAN_CTRL_TWRN_MSK | CAN_CTRL_RWRN_MSK;
#if !SPC5_CAN_USE_FILTERS
/* RX MB initialization.*/
for(mb_index = 0; mb_index < CAN_RX_MAILBOXES; mb_index++) {
canp->flexcan->BUF[mb_index].CS.B.CODE = 0U;
if(mb_index < 4) {
canp->flexcan->BUF[mb_index].CS.B.IDE = 0U;
}
else {
canp->flexcan->BUF[mb_index].CS.B.IDE = 1U;
}
canp->flexcan->BUF[mb_index].ID.R = 0U;
canp->flexcan->BUF[mb_index].CS.B.CODE = 4U;
}
/* Receive all.*/
canp->flexcan->RXGMASK.R = 0x00000000;
#else
for (id = 0; id < CAN_RX_MAILBOXES; id++) {
canp->flexcan->BUF[id].CS.B.CODE = 0U;
if (canp->config->RxFilter[id].scale) {
canp->flexcan->BUF[id].CS.B.IDE = 1U;
canp->flexcan->BUF[id].ID.R = canp->config->RxFilter[id].register1;
}
else {
canp->flexcan->BUF[id].CS.B.IDE = 0U;
canp->flexcan->BUF[id].ID.B.STD_ID = canp->config->RxFilter[id].register1;
canp->flexcan->BUF[id].ID.B.EXT_ID = 0U;
}
/* RX MB initialization.*/
canp->flexcan->BUF[id].CS.B.CODE = 4U;
}
canp->flexcan->RXGMASK.R = 0x0FFFFFFF;
#endif
/* Enable MBs interrupts.*/
#if SPC5_CAN_USE_FLEXCAN0
if(&CAND1 == canp) {
if(SPC5_FLEXCAN0_MB == 32) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
}
else if(SPC5_FLEXCAN0_MB == 64) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
canp->flexcan->IMRH.R = 0xFFFFFFFF;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN1
if(&CAND2 == canp) {
if(SPC5_FLEXCAN1_MB == 32) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
}
else if(SPC5_FLEXCAN1_MB == 64) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
canp->flexcan->IMRH.R = 0xFFFFFFFF;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN2
if(&CAND3 == canp) {
if(SPC5_FLEXCAN2_MB == 32) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
}
else if(SPC5_FLEXCAN2_MB == 64) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
canp->flexcan->IMRH.R = 0xFFFFFFFF;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN3
if(&CAND4 == canp) {
if(SPC5_FLEXCAN3_MB == 32) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
}
else if(SPC5_FLEXCAN3_MB == 64) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
canp->flexcan->IMRH.R = 0xFFFFFFFF;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN4
if(&CAND5 == canp) {
if(SPC5_FLEXCAN4_MB == 32) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
}
else if(SPC5_FLEXCAN4_MB == 64) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
canp->flexcan->IMRH.R = 0xFFFFFFFF;
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN5
if(&CAND6 == canp) {
if(SPC5_FLEXCAN5_MB == 32) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
}
else if(SPC5_FLEXCAN5_MB == 64) {
canp->flexcan->IMRL.R = 0xFFFFFFFF;
canp->flexcan->IMRH.R = 0xFFFFFFFF;
}
}
#endif
/* CAN BUS synchronization.*/
canp->flexcan->MCR.B.HALT = 0;
}
/**
* @brief Deactivates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
void can_lld_stop(CANDriver *canp) {
/* If in ready state then disables the CAN peripheral.*/
if (canp->state == CAN_READY) {
/* Disable Interrupt sources.*/
canp->flexcan->MCR.R &= ~CAN_MCR_WRN_EN;
canp->flexcan->CR.R &= ~(CAN_CTRL_BOFF_MSK | CAN_CTRL_ERR_MSK |
CAN_CTRL_TWRN_MSK | CAN_CTRL_RWRN_MSK);
canp->flexcan->IMRL.R = 0x00000000;
canp->flexcan->MCR.R &= ~CAN_MCR_MDIS;
#if SPC5_CAN_USE_FLEXCAN0
/* Set peripheral clock mode.*/
if(&CAND1 == canp)
SPC5_FLEXCAN0_DISABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN1
/* Set peripheral clock mode.*/
if(&CAND2 == canp)
SPC5_FLEXCAN1_DISABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN2
/* Set peripheral clock mode.*/
if(&CAND3 == canp)
SPC5_FLEXCAN2_DISABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN3
/* Set peripheral clock mode.*/
if(&CAND4 == canp)
SPC5_FLEXCAN3_DISABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN4
/* Set peripheral clock mode.*/
if(&CAND5 == canp)
SPC5_FLEXCAN4_DISABLE_CLOCK();
#endif
#if SPC5_CAN_USE_FLEXCAN5
/* Set peripheral clock mode.*/
if(&CAND6 == canp)
SPC5_FLEXCAN5_DISABLE_CLOCK();
#endif
}
}
/**
* @brief Determines whether a frame can be transmitted.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
*
* @return The queue space availability.
* @retval FALSE no space in the transmit queue.
* @retval TRUE transmit slot available.
*
* @notapi
*/
bool_t can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) {
uint8_t mbid = 0;
if(mailbox == CAN_ANY_MAILBOX) {
#if SPC5_CAN_USE_FLEXCAN0
if(&CAND1 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN0_MB; mbid++) {
if (canp->flexcan->BUF[mbid].CS.B.CODE == 0x08) {
return TRUE;
}
}
return FALSE;
}
#endif
#if SPC5_CAN_USE_FLEXCAN1
if(&CAND2 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN1_MB; mbid++) {
if (canp->flexcan->BUF[mbid].CS.B.CODE == 0x08) {
return TRUE;
}
}
return FALSE;
}
#endif
#if SPC5_CAN_USE_FLEXCAN2
if(&CAND3 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN2_MB; mbid++) {
if (canp->flexcan->BUF[mbid].CS.B.CODE == 0x08) {
return TRUE;
}
}
return FALSE;
}
#endif
#if SPC5_CAN_USE_FLEXCAN3
if(&CAND4 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN3_MB; mbid++) {
if (canp->flexcan->BUF[mbid].CS.B.CODE == 0x08) {
return TRUE;
}
}
return FALSE;
}
#endif
#if SPC5_CAN_USE_FLEXCAN4
if(&CAND5 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN4_MB; mbid++) {
if (canp->flexcan->BUF[mbid].CS.B.CODE == 0x08) {
return TRUE;
}
}
return FALSE;
}
#endif
#if SPC5_CAN_USE_FLEXCAN5
if(&CAND6 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN5_MB; mbid++) {
if (canp->flexcan->BUF[mbid].CS.B.CODE == 0x08) {
return TRUE;
}
}
return FALSE;
}
#endif
}
else {
return canp->flexcan->BUF[mailbox + 7].CS.B.CODE == 0x08;
}
return FALSE;
}
/**
* @brief Inserts a frame into the transmit queue.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] ctfp pointer to the CAN frame to be transmitted
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
*
* @notapi
*/
void can_lld_transmit(CANDriver *canp,
canmbx_t mailbox,
const CANTxFrame *ctfp) {
CAN_TxMailBox_TypeDef *tmbp = NULL;
uint8_t mbid = 0;
/* Pointer to a free transmission mailbox.*/
if (mailbox == CAN_ANY_MAILBOX) {
#if SPC5_CAN_USE_FLEXCAN0
if(&CAND1 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN0_MB; mbid++) {
if ((canp->flexcan->BUF[mbid].CS.B.CODE & 8U) == 1) {
tmbp = (CAN_TxMailBox_TypeDef *)&canp->flexcan->BUF[mbid];
break;
}
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN1
if(&CAND2 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN1_MB; mbid++) {
if ((canp->flexcan->BUF[mbid].CS.B.CODE & 8U) == 1) {
tmbp = (CAN_TxMailBox_TypeDef *)&canp->flexcan->BUF[mbid];
break;
}
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN2
if(&CAND3 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN2_MB; mbid++) {
if ((canp->flexcan->BUF[mbid].CS.B.CODE & 8U) == 1) {
tmbp = (CAN_TxMailBox_TypeDef *)&canp->flexcan->BUF[mbid];
break;
}
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN3
if(&CAND4 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN3_MB; mbid++) {
if ((canp->flexcan->BUF[mbid].CS.B.CODE & 8U) == 1) {
tmbp = (CAN_TxMailBox_TypeDef *)&canp->flexcan->BUF[mbid];
break;
}
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN4
if(&CAND5 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN4_MB; mbid++) {
if ((canp->flexcan->BUF[mbid].CS.B.CODE & 8U) == 1) {
tmbp = (CAN_TxMailBox_TypeDef *)&canp->flexcan->BUF[mbid];
break;
}
}
}
#endif
#if SPC5_CAN_USE_FLEXCAN5
if(&CAND6 == canp) {
for (mbid = 8; mbid < SPC5_FLEXCAN5_MB; mbid++) {
if ((canp->flexcan->BUF[mbid].CS.B.CODE & 8U) == 1) {
tmbp = (CAN_TxMailBox_TypeDef *)&canp->flexcan->BUF[mbid];
break;
}
}
}
#endif
}
else {
tmbp = (CAN_TxMailBox_TypeDef *)&canp->flexcan->BUF[mailbox + 7];
}
/* Preparing the message.*/
if (ctfp->IDE) {
tmbp->CS.B.IDE = 1U;
tmbp->CS.B.RTR = 0U;
tmbp->ID.R = ctfp->EID;
}
else {
tmbp->CS.B.IDE = 0U;
tmbp->CS.B.RTR = 0U;
tmbp->ID.R = ctfp->SID << 18;
}
tmbp->CS.B.LENGTH = ctfp->LENGTH;
tmbp->DATA[0] = ctfp->data32[0];
tmbp->DATA[1] = ctfp->data32[1];
tmbp->CS.B.CODE = 0x0C;
}
/**
*
* @brief Determines whether a frame has been received.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
*
* @return The queue space availability.
* @retval FALSE no space in the transmit queue.
* @retval TRUE transmit slot available.
*
* @notapi
*/
bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) {
uint8_t mbid = 0;
bool_t mb_status = FALSE;
switch (mailbox) {
case CAN_ANY_MAILBOX:
for (mbid = 0; mbid < CAN_RX_MAILBOXES; mbid++) {
if(canp->flexcan->BUF[mbid].CS.B.CODE == 2U) {
mb_status = TRUE;
}
}
return mb_status;
case 1:
return (canp->flexcan->BUF[0].CS.B.CODE == 2U);
case 2:
return (canp->flexcan->BUF[1].CS.B.CODE == 2U);
case 3:
return (canp->flexcan->BUF[2].CS.B.CODE == 2U);
case 4:
return (canp->flexcan->BUF[3].CS.B.CODE == 2U);
case 5:
return (canp->flexcan->BUF[4].CS.B.CODE == 2U);
case 6:
return (canp->flexcan->BUF[5].CS.B.CODE == 2U);
case 7:
return (canp->flexcan->BUF[6].CS.B.CODE == 2U);
case 8:
return (canp->flexcan->BUF[7].CS.B.CODE == 2U);
default:
return FALSE;
}
}
/**
* @brief Receives a frame from the input queue.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
* @param[out] crfp pointer to the buffer where the CAN frame is copied
*
* @notapi
*/
void can_lld_receive(CANDriver *canp,
canmbx_t mailbox,
CANRxFrame *crfp) {
uint32_t mbid = 0, index = 0;
if(mailbox != CAN_ANY_MAILBOX) {
mbid = mailbox;
}
else {
for (index = 0; index < CAN_RX_MAILBOXES; index++) {
if(canp->flexcan->BUF[index].CS.B.CODE == 2U) {
mbid = index;
break;
}
}
}
/* Lock the RX MB.*/
(void) canp->flexcan->BUF[mbid].CS.B.CODE;
/* Fetches the message.*/
crfp->data32[0] = canp->flexcan->BUF[mbid].DATA.W[0];
crfp->data32[1] = canp->flexcan->BUF[mbid].DATA.W[1];
/* Decodes the various fields in the RX frame.*/
crfp->RTR = canp->flexcan->BUF[mbid].CS.B.RTR;
crfp->IDE = canp->flexcan->BUF[mbid].CS.B.IDE;
if (crfp->IDE)
crfp->EID = canp->flexcan->BUF[mbid].ID.B.EXT_ID;
else
crfp->SID = canp->flexcan->BUF[mbid].ID.B.STD_ID;
crfp->LENGTH = canp->flexcan->BUF[mbid].CS.B.LENGTH;
crfp->TIME = canp->flexcan->BUF[mbid].CS.B.TIMESTAMP;
/* Unlock the RX MB.*/
(void) canp->flexcan->TIMER.R;
/* Reconfigure the RX MB in empty status.*/
canp->flexcan->BUF[mbid].CS.B.CODE = 4U;
}
#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
/**
* @brief Enters the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
void can_lld_sleep(CANDriver *canp) {
/*canp->can->MCR |= CAN_MCR_SLEEP;*/
}
/**
* @brief Enforces leaving the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @notapi
*/
void can_lld_wakeup(CANDriver *canp) {
/*canp->can->MCR &= ~CAN_MCR_SLEEP;*/
}
#endif /* CAN_USE_SLEEP_MODE */
#endif /* HAL_USE_CAN */
/** @} */