Added CAN driver for AT91SAM7.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@6536 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
01a0b816aa
commit
41e76064d6
|
@ -0,0 +1,640 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,2011 Giovanni Di Sirio.
|
||||||
|
2012,2013 Martin Schüßler and Florian Sehl, Embedded Software Laboratory,
|
||||||
|
RWTH Aachen University
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
A special exception to the GPL can be applied should you wish to distribute
|
||||||
|
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||||
|
the source code for any proprietary components. See the file exception.txt
|
||||||
|
for full details of how and when the exception can be applied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file AT91SAM7/can_lld.c
|
||||||
|
* @brief AT91SAM7 CAN Driver subsystem low level driver source.
|
||||||
|
*
|
||||||
|
* @pre - Make sure that the Mailbox you are receiving from is holding your
|
||||||
|
* data.
|
||||||
|
* - If you have more than one use the rxfull_event provided by the
|
||||||
|
* Driver.
|
||||||
|
* - In order to use the Events APIs the CH_USE_EVENTS option must
|
||||||
|
* be enabled in chconf.h.
|
||||||
|
* - In order to use the CAN driver the HAL_USE_CAN option must be
|
||||||
|
* enabled in halconf.h.
|
||||||
|
* - Mailbox0 is used as a Transmitmailbox.
|
||||||
|
* - Mailboxes 1-7 are used as receive Mailboxes.
|
||||||
|
*
|
||||||
|
* @addtogroup CAN
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ch.h"
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
#if HAL_USE_CAN || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver exported variables. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN driver identifier.
|
||||||
|
*/
|
||||||
|
#if AT91SAM7_CAN_USE_CAN || defined(__DOXYGEN__)
|
||||||
|
CANDriver CAND;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver local variables. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver local functions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver interrupt handlers. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN[0] interrupt handler.
|
||||||
|
*
|
||||||
|
* @isr
|
||||||
|
*/
|
||||||
|
CH_IRQ_HANDLER(CANIrqHandler) {
|
||||||
|
|
||||||
|
CH_IRQ_PROLOGUE();
|
||||||
|
can_lld_serve_interrupt(&CAND);
|
||||||
|
AT91C_BASE_AIC->AIC_EOICR = 0;
|
||||||
|
CH_IRQ_EPILOGUE();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
__attribute__((noinline))
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Handles CAN interrupts.
|
||||||
|
*
|
||||||
|
* @param[in] pointer to the driver that received the interrupt
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void can_lld_serve_interrupt(CANDriver *canp) {
|
||||||
|
|
||||||
|
canstatus_t status;
|
||||||
|
chSysLockFromIsr();
|
||||||
|
|
||||||
|
status = canp->base->CAN_SR & canp->base->CAN_IMR;
|
||||||
|
|
||||||
|
/* if AT91C_CAN_WAKEUP is set, the can test was successful
|
||||||
|
* such that the CAN is now able to Transmit and Receive Data.
|
||||||
|
*/
|
||||||
|
if ((status & AT91C_CAN_WAKEUP) == AT91C_CAN_WAKEUP) {
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_WAKEUP;
|
||||||
|
canp->testok = AT91C_TEST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
/* check the mailboxes (MB0-MB7) and broadcast the corresponding event.*/
|
||||||
|
|
||||||
|
/* configure send mailbox, mailbox 0 */
|
||||||
|
#if CAN_USE_MB0
|
||||||
|
if(status & AT91C_CAN_MB0 && canp->mb[CAN_TxMB0-1]->CAN_MB_MSR & AT91C_CAN_MRDY) {
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_MB0;
|
||||||
|
chSemSignalI(&(canp->txsem));
|
||||||
|
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#warning You need to acivate Mailbox0 to transmit.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAN_USE_MB1
|
||||||
|
if (status & AT91C_CAN_MB1 &&
|
||||||
|
canp->mb[CAN_RxMB1-1]->CAN_MB_MSR & AT91C_CAN_MRDY) {
|
||||||
|
chSemSignalI(&(canp->rxsem));
|
||||||
|
chEvtBroadcastFlagsI(&(canp->rxfull_event), EVENT_MASK (CAN_RxMB1-1));
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_MB1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAN_USE_MB2
|
||||||
|
if (status & AT91C_CAN_MB2 &&
|
||||||
|
canp->mb[CAN_RxMB2-1]->CAN_MB_MSR & AT91C_CAN_MRDY) {
|
||||||
|
chSemSignalI(&(canp->rxsem));
|
||||||
|
chEvtBroadcastFlagsI(&(canp->rxfull_event), EVENT_MASK (CAN_RxMB2-1));
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_MB2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAN_USE_MB3
|
||||||
|
if (status & AT91C_CAN_MB3 &&
|
||||||
|
canp->mb[CAN_RxMB3-1]->CAN_MB_MSR & AT91C_CAN_MRDY) {
|
||||||
|
chSemSignalI(&(canp->rxsem));
|
||||||
|
chEvtBroadcastFlagsI(&(canp->rxfull_event), EVENT_MASK (CAN_RxMB3-1));
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_MB3;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAN_USE_MB4
|
||||||
|
if (status & AT91C_CAN_MB4 && c
|
||||||
|
anp->mb[CAN_RxMB4-1]->CAN_MB_MSR & AT91C_CAN_MRDY) {
|
||||||
|
chSemSignalI(&(canp->rxsem));
|
||||||
|
chEvtBroadcastFlagsI(&(canp->rxfull_event), EVENT_MASK (CAN_RxMB4-1));
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_MB4;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAN_USE_MB5
|
||||||
|
if (status & AT91C_CAN_MB5 &&
|
||||||
|
canp->mb[CAN_RxMB5-1]->CAN_MB_MSR & AT91C_CAN_MRDY) {
|
||||||
|
chSemSignalI(&(canp->rxsem));
|
||||||
|
chEvtBroadcastFlagsI(&(canp->rxfull_event), EVENT_MASK (CAN_RxMB5-1));
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_MB5;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAN_USE_MB6
|
||||||
|
if (status & AT91C_CAN_MB6 &&
|
||||||
|
canp->mb[CAN_RxMB6-1]->CAN_MB_MSR & AT91C_CAN_MRDY) {
|
||||||
|
chSemSignalI(&(canp->rxsem));
|
||||||
|
chEvtBroadcastFlagsI(&(canp->rxfull_event, EVENT_MASK (CAN_RxMB6-1));
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_MB6;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAN_USE_MB7
|
||||||
|
if (status & AT91C_CAN_MB7 &&
|
||||||
|
canp->mb[CAN_RxMB7-1]->CAN_MB_MSR & AT91C_CAN_MRDY) {
|
||||||
|
chSemSignalI(&(canp->rxsem));
|
||||||
|
chEvtBroadcastFlagsI(&(canp->rxfull_event), EVENT_MASK (CAN_RxMB7-1));
|
||||||
|
canp->base->CAN_IDR = AT91C_CAN_MB7;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*check if error event is detected*/
|
||||||
|
if ((status & 0xFFCF0000) != 0) {
|
||||||
|
/*The content of the SR register is copied unchanged in the upper
|
||||||
|
half word of the listener flags mask*/
|
||||||
|
chEvtBroadcastFlagsI(&(canp->error_event), (eventmask_t)(status&0xFFFF0000));
|
||||||
|
}
|
||||||
|
|
||||||
|
chSysUnlockFromIsr();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver exported functions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Low level CAN driver initialization.
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void can_lld_init(void) {
|
||||||
|
/* Driver initialization.*/
|
||||||
|
canObjectInit(&CAND);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mailbox vector initialization
|
||||||
|
*/
|
||||||
|
#if CAN_USE_MB0
|
||||||
|
CAND.mb[CAN_TxMB0-1] = AT91C_BASE_CAN_MB0;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB1
|
||||||
|
CAND.mb[CAN_RxMB1-1] = AT91C_BASE_CAN_MB1;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB2
|
||||||
|
CAND.mb[CAN_RxMB2-1] = AT91C_BASE_CAN_MB2;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB3
|
||||||
|
CAND.mb[CAN_RxMB3-1] = AT91C_BASE_CAN_MB3;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB4
|
||||||
|
CAND.mb[CAN_RxMB4-1] = AT91C_BASE_CAN_MB4;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB5
|
||||||
|
CAND.mb[CAN_RxMB5-1] = AT91C_BASE_CAN_MB5;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB6
|
||||||
|
CAND.mb[CAN_RxMB6-1] = AT91C_BASE_CAN_MB6;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB7
|
||||||
|
CAND.mb[CAN_RxMB7-1] = AT91C_BASE_CAN_MB7;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PIO
|
||||||
|
*/
|
||||||
|
/* Disable interrupts on the pin(s)*/
|
||||||
|
AT91C_BASE_PIOA->PIO_IDR = AT91C_PA19_CANRX;
|
||||||
|
AT91C_BASE_PIOA->PIO_IDR = AT91C_PA20_CANTX;
|
||||||
|
/* Select peripheral function A*/
|
||||||
|
AT91C_BASE_PIOA->PIO_ASR = AT91C_PA19_CANRX;
|
||||||
|
AT91C_BASE_PIOA->PIO_ASR = AT91C_PA20_CANTX;
|
||||||
|
/* Disables the PIO from controlling the corresponding pin
|
||||||
|
* (enables peripheral control of the pin)
|
||||||
|
*/
|
||||||
|
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA19_CANRX;
|
||||||
|
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA20_CANTX;
|
||||||
|
/* Disable pull up */
|
||||||
|
AT91C_BASE_PIOA->PIO_PPUDR = AT91C_PA19_CANRX | AT91C_PA20_CANTX;
|
||||||
|
|
||||||
|
/* Configure the AIC for CAN interrupts */
|
||||||
|
AIC_ConfigureIT(AT91C_ID_CAN, AT91C_AIC_PRIOR_HIGHEST, CANIrqHandler);
|
||||||
|
CAND.base = AT91C_BASE_CAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief configures and starts the CAN peripheral.
|
||||||
|
*/
|
||||||
|
static void can_startsequence(CANDriver *canp) {
|
||||||
|
canp->state = CAN_STARTING;
|
||||||
|
canp->testok = AT91C_TEST_NOK;
|
||||||
|
|
||||||
|
/* clock */
|
||||||
|
/* Enable clock for PIOA */
|
||||||
|
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA);
|
||||||
|
/* Enable the CAN controller peripheral clock */
|
||||||
|
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_CAN);
|
||||||
|
|
||||||
|
/* interrupts */
|
||||||
|
|
||||||
|
/* disable all interrupts */
|
||||||
|
canp->base->CAN_IDR = 0x1FFFFFFF;
|
||||||
|
/* Enable the interrupt on the interrupt controller*/
|
||||||
|
AIC_EnableIT(AT91C_ID_CAN);
|
||||||
|
|
||||||
|
canp->base->CAN_BR = canp->config->br;
|
||||||
|
|
||||||
|
|
||||||
|
/* configure send mailbox, mailbox 0 */
|
||||||
|
#if CAN_USE_MB0
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MCR = 0x0;
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MMR = AT91C_CAN_MOT_TX | AT91C_CAN_PRIOR;
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MAM = 0x00000000;
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MID = AT91C_CAN_MIDE;
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MDL = 0x11223344;
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MDH = 0x01234567;
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MCR = (AT91C_CAN_MDLC & (0x8 << 16));
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MMR = AT91C_CAN_MOT_TX | AT91C_CAN_PRIOR;
|
||||||
|
#else
|
||||||
|
#warning You need to acivate Mailbox0 to transmit.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAN_USE_MB1
|
||||||
|
canp->mb[CAN_RxMB1-1]->CAN_MB_MCR = 0x0;
|
||||||
|
canp->mb[CAN_RxMB1-1]->CAN_MB_MMR = AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR;
|
||||||
|
canp->mb[CAN_RxMB1-1]->CAN_MB_MAM = AT91C_CAN_MIDE
|
||||||
|
|(AT91C_CAN_MIDvB & canp->config->mb1_acceptance_mask)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb1_acceptance_mask);
|
||||||
|
canp->mb[CAN_RxMB1-1]->CAN_MB_MID = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb1_can_id)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb1_can_id);
|
||||||
|
canp->mb[CAN_RxMB1-1]->CAN_MB_MDL = 0x00000000;
|
||||||
|
canp->mb[CAN_RxMB1-1]->CAN_MB_MDH = 0x00000000;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB2
|
||||||
|
canp->mb[CAN_RxMB2-1]->CAN_MB_MCR = 0x0;
|
||||||
|
canp->mb[CAN_RxMB2-1]->CAN_MB_MMR = AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR;
|
||||||
|
canp->mb[CAN_RxMB2-1]->CAN_MB_MAM = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb2_acceptance_mask)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb2_acceptance_mask);
|
||||||
|
canp->mb[CAN_RxMB2-1]->CAN_MB_MID = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb2_can_id)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb2_can_id);
|
||||||
|
canp->mb[CAN_RxMB2-1]->CAN_MB_MDL = 0x00000000;
|
||||||
|
canp->mb[CAN_RxMB2-1]->CAN_MB_MDH = 0x00000000;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB3
|
||||||
|
canp->mb[CAN_RxMB3-1]->CAN_MB_MCR = 0x0;
|
||||||
|
canp->mb[CAN_RxMB3-1]->CAN_MB_MMR = AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR;
|
||||||
|
canp->mb[CAN_RxMB3-1]->CAN_MB_MAM = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb3_acceptance_mask)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb3_acceptance_mask);
|
||||||
|
canp->mb[CAN_RxMB3-1]->CAN_MB_MID = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb3_can_id)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb3_can_id);
|
||||||
|
canp->mb[CAN_RxMB3-1]->CAN_MB_MDL = 0x00000000;
|
||||||
|
canp->mb[CAN_RxMB3-1]->CAN_MB_MDH = 0x00000000;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB4
|
||||||
|
canp->mb[CAN_RxMB4-1]->CAN_MB_MCR = 0x0;
|
||||||
|
canp->mb[CAN_RxMB4-1]->CAN_MB_MMR = AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR;_MAM = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb4_acceptance_mask)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb4_acceptance_mask);
|
||||||
|
canp->mb[CAN_RxMB4-1]->CAN_MB_MID = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb4_can_id)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb4_can_id);
|
||||||
|
canp->mb[CAN_RxMB4-1]->CAN_MB_MDL = 0x00000000;
|
||||||
|
canp->mb[CAN_RxMB4-1]->CAN_MB_MDH = 0x00000000;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB5
|
||||||
|
canp->mb[CAN_RxMB5-1]->CAN_MB_MCR = 0x0;
|
||||||
|
canp->mb[CAN_RxMB4-1]->CAN_MB_MMR = AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR;
|
||||||
|
canp->mb[CAN_RxMB5-1]->CAN_MB_MAM = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb5_acceptance_mask)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb5_acceptance_mask);
|
||||||
|
canp->mb[CAN_RxMB5-1]->CAN_MB_MID = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb5_can_id)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb5_can_id);
|
||||||
|
canp->mb[CAN_RxMB5-1]->CAN_MB_MDL = 0x00000000;
|
||||||
|
canp->mb[CAN_RxMB5-1]->CAN_MB_MDH = 0x00000000;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB6
|
||||||
|
canp->mb[CAN_RxMB6-1]->CAN_MB_MCR = 0x0;
|
||||||
|
canp->mb[CAN_RxMB6-1]->CAN_MB_MMR = AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR;
|
||||||
|
canp->mb[CAN_RxMB6-1]->CAN_MB_MAM = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb6_acceptance_mask)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb6_acceptance_mask);
|
||||||
|
canp->mb[CAN_RxMB6-1]->CAN_MB_MID = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb6_can_id)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb6_can_id);
|
||||||
|
canp->mb[CAN_RxMB6-1]->CAN_MB_MDL = 0x00000000;
|
||||||
|
canp->mb[CAN_RxMB6-1]->CAN_MB_MDH = 0x00000000;
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB7
|
||||||
|
canp->mb[CAN_RxMB7-1]->CAN_MB_MCR = 0x0;
|
||||||
|
canp->mb[CAN_RxMB7-1]->CAN_MB_MMR = AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR;
|
||||||
|
canp->mb[CAN_RxMB7-1]->CAN_MB_MAM = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb7_acceptance_mask)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb7_acceptance_mask);
|
||||||
|
canp->mb[CAN_RxMB7-1]->CAN_MB_MID = AT91C_CAN_MIDE
|
||||||
|
| (AT91C_CAN_MIDvB & canp->config->mb7_can_id)
|
||||||
|
| (AT91C_CAN_MIDvA & canp->config->mb7_can_id);
|
||||||
|
canp->mb[CAN_RxMB7-1]->CAN_MB_MDL = 0x00000000;
|
||||||
|
canp->mb[CAN_RxMB7-1]->CAN_MB_MDH = 0x00000000;
|
||||||
|
#endif
|
||||||
|
/* Enable the interrupt with all error cases */
|
||||||
|
canp->base->CAN_IER = AT91C_CAN_CERR /* (CAN) CRC Error */
|
||||||
|
| AT91C_CAN_SERR /* (CAN) Stuffing Error */
|
||||||
|
| AT91C_CAN_BERR /* (CAN) Bit Error */
|
||||||
|
| AT91C_CAN_FERR /* (CAN) Form Error */
|
||||||
|
| AT91C_CAN_AERR; /* (CAN) Acknowledgment Error */
|
||||||
|
|
||||||
|
/* Enable CAN and */
|
||||||
|
canp->base->CAN_IER = AT91C_CAN_WAKEUP;
|
||||||
|
|
||||||
|
/* CAN Controller Enable */
|
||||||
|
canp->base->CAN_MR = AT91C_CAN_CANEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures and activates the CAN peripheral.
|
||||||
|
*
|
||||||
|
* @param[in] canp pointer to the @p CANDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
|
||||||
|
void can_lld_start(CANDriver *canp) {
|
||||||
|
|
||||||
|
/*start CAN*/
|
||||||
|
can_startsequence(canp);
|
||||||
|
/* wait until wakeup. If no wakeup after 1 sec restart. */
|
||||||
|
chThdSleepS(1);
|
||||||
|
while( (canp->testok) == AT91C_TEST_NOK) {
|
||||||
|
/* stop CAN */
|
||||||
|
/* Disable all interrupts */
|
||||||
|
canp->base->CAN_IDR = 0x1FFFFFFF;
|
||||||
|
/* Disable the interrupt on the interrupt controller */
|
||||||
|
AIC_DisableIT(AT91C_ID_CAN);
|
||||||
|
/* Disable the CAN controller peripheral clock */
|
||||||
|
AT91C_BASE_PMC->PMC_PCER = (0 << AT91C_ID_CAN);
|
||||||
|
/* restart CAN */
|
||||||
|
can_startsequence(canp);
|
||||||
|
|
||||||
|
chThdSleepS(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*enable Mailboxes */
|
||||||
|
#if CAN_USE_MB1
|
||||||
|
canp->base->CAN_IER = (0x1 << 1);
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB2
|
||||||
|
canp->base->CAN_IER = (0x1 << 2);
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB3
|
||||||
|
canp->base->CAN_IER = (0x1 << 3);
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB4
|
||||||
|
canp->base->CAN_IER = (0x1 << 4);
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB5
|
||||||
|
canp->base->CAN_IER = (0x1 << 5);
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB6
|
||||||
|
canp->base->CAN_IER = (0x1 << 6);
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB7
|
||||||
|
canp->base->CAN_IER = (0x1 << 7);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 all interrupts */
|
||||||
|
canp->base->CAN_IDR = 0x1FFFFFFF;
|
||||||
|
|
||||||
|
/* Disable the interrupt on the interrupt controller */
|
||||||
|
AIC_DisableIT(AT91C_ID_CAN);
|
||||||
|
|
||||||
|
/* Disable the CAN controller peripheral clock */
|
||||||
|
AT91C_BASE_PMC->PMC_PCER = (0 << AT91C_ID_CAN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
||||||
|
|
||||||
|
return ((canp->mb[CAN_TxMB0-1]->CAN_MB_MSR & AT91C_CAN_MRDY) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send specified frame.
|
||||||
|
*
|
||||||
|
* @param[in] canp pointer to the @p CANDriver object
|
||||||
|
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
|
||||||
|
* @param[in] ctfp pointer to the CAN frame to be transmitted
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void can_lld_transmit(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp) {
|
||||||
|
while (!( canp->mb[CAN_TxMB0-1]->CAN_MB_MSR & AT91C_CAN_MRDY)){
|
||||||
|
}
|
||||||
|
#if CAN_IDE_EXT
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MID =
|
||||||
|
AT91C_CAN_MIDE | (AT91C_CAN_MIDvB & ctfp->EID)
|
||||||
|
| (AT91C_CAN_MIDvA & (ctfp->EID)); //configure the id
|
||||||
|
#else
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MID = AT91C_CAN_MIDE |
|
||||||
|
(AT91C_CAN_MIDvB & 0x0)
|
||||||
|
| (AT91C_CAN_MIDvA & ctfp->SID); //configure the id
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set length of data */
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MCR = (AT91C_CAN_MDLC & (ctfp->DLC << 16));
|
||||||
|
|
||||||
|
/* fill low register if 0<Length<=8 */
|
||||||
|
if(ctfp->DLC>0)
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MDL = ctfp->data32[0];
|
||||||
|
/* fill high register 4<Length<=8 */
|
||||||
|
if(ctfp->DLC>4)
|
||||||
|
canp->mb[CAN_TxMB0-1]->CAN_MB_MDH = ctfp->data32[1];
|
||||||
|
canp->base->CAN_IER = 1 << CAN_TxMB0-1;
|
||||||
|
canp->base->CAN_TCR = 1 << 0; //send msg
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief check if some data is available mailbox.
|
||||||
|
*
|
||||||
|
* @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 mailbox is empty
|
||||||
|
* @retval TRUE some data in the mailbox
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) {
|
||||||
|
|
||||||
|
if(mailbox == CAN_ANY_MAILBOX){
|
||||||
|
/* get status of all receive mailboxes (Mailbox0 is transmit mailbox) */
|
||||||
|
if((canp->base->CAN_SR & 0xFE) != 0){
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
/* get status of specified mailbox */
|
||||||
|
if((canp->base->CAN_SR & (1<<(mailbox-1))) != 0){
|
||||||
|
/* data available */
|
||||||
|
return TRUE;
|
||||||
|
} else{
|
||||||
|
/* no data */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Receives a frame from the specified mailbox.
|
||||||
|
*
|
||||||
|
* @pre Make sure that the Mailbox you are receiving from is holding
|
||||||
|
* your data. If you have more than one use the rxfull_event
|
||||||
|
* provided by the Driver.
|
||||||
|
*
|
||||||
|
* @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) {
|
||||||
|
if(mailbox != CAN_ANY_MAILBOX){
|
||||||
|
/* get length of data */
|
||||||
|
crfp->DLC = (canp->mb[mailbox-1]->CAN_MB_MSR &
|
||||||
|
AT91C_CAN_MDLC) >> 16;
|
||||||
|
/* store data */
|
||||||
|
if(crfp->DLC>0){
|
||||||
|
crfp->data32[0] = canp->mb[mailbox-1]->CAN_MB_MDL;
|
||||||
|
}
|
||||||
|
if(crfp->DLC>=4){
|
||||||
|
crfp->data32[1] = canp->mb[mailbox-1]->CAN_MB_MDH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
/* TODO implement can_lld_receive for CAN_ANY_MAILBOX */
|
||||||
|
}
|
||||||
|
/* clear register */
|
||||||
|
canp->base->CAN_TCR = (0x1 << (mailbox-1));
|
||||||
|
/* reenable interrupt */
|
||||||
|
canp->base->CAN_IER = (0x1 << (mailbox-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#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) {
|
||||||
|
/* Wait till Tx Mailbox is ready */
|
||||||
|
while(!((canp->mb[CAN_TxMB0-1]->CAN_MB_MSR & AT91C_CAN_MRDY) == AT91C_CAN_MRDY)){
|
||||||
|
}
|
||||||
|
/* enable low power mode */
|
||||||
|
canp->base->CAN_MR |= AT91C_CAN_LPM;
|
||||||
|
/* wait till CAN is in low power mode */
|
||||||
|
while(!((canp->base->CAN_SR & AT91C_CAN_SLEEP) == AT91C_CAN_SLEEP)){
|
||||||
|
}
|
||||||
|
/* disable Clock */
|
||||||
|
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_CAN);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enforces leaving the sleep mode.
|
||||||
|
*
|
||||||
|
* @param[in] canp pointer to the @p CANDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void can_lld_wakeup(CANDriver *canp) {
|
||||||
|
/* enable clock */
|
||||||
|
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_CAN);
|
||||||
|
/* disable low power mode */
|
||||||
|
canp->base->CAN_MR &= ~(AT91C_CAN_SLEEP);
|
||||||
|
while(!((canp->base->CAN_SR & AT91C_CAN_WAKEUP)==AT91C_CAN_WAKEUP)){
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /* CAN_USE_SLEEP_MODE */
|
||||||
|
|
||||||
|
#endif /* HAL_USE_CAN */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,407 @@
|
||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,2011 Giovanni Di Sirio.
|
||||||
|
2012,2013 Martin Schüßler and Florian Sehl, Embedded Software Laboratory,
|
||||||
|
RWTH Aachen University
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
A special exception to the GPL can be applied should you wish to distribute
|
||||||
|
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||||
|
the source code for any proprietary components. See the file exception.txt
|
||||||
|
for full details of how and when the exception can be applied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file AT91SAM7/can_lld.h
|
||||||
|
* @brief AT91SAM7 CAN Driver subsystem low level driver header.
|
||||||
|
*
|
||||||
|
* @pre - Make sure that the Mailbox you are receiving from is holding your
|
||||||
|
* data.
|
||||||
|
* - If you have more than one use the rxfull_event provided by the
|
||||||
|
* Driver.
|
||||||
|
* - In order to use the Events APIs the CH_USE_EVENTS option must
|
||||||
|
* be enabled in chconf.h.
|
||||||
|
* - In order to use the CAN driver the HAL_USE_CAN option must be
|
||||||
|
* enabled in halconf.h.
|
||||||
|
* - Mailbox0 is used as a Transmitmailbox.
|
||||||
|
* - Mailboxes 1-7 are used as receive Mailboxes.
|
||||||
|
*
|
||||||
|
* @addtogroup CAN
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CAN_LLD_H_
|
||||||
|
#define _CAN_LLD_H_
|
||||||
|
|
||||||
|
#if HAL_USE_CAN || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver constants. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This switch defines whether the driver implementation supports
|
||||||
|
* a low power switch mode with automatic an wakeup feature.
|
||||||
|
*/
|
||||||
|
#define CAN_SUPPORTS_SLEEP TRUE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This implementation supports one transmit mailboxes.
|
||||||
|
*/
|
||||||
|
#define CAN_TX_MAILBOXES 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This implementation supports two receive mailboxes.
|
||||||
|
*/
|
||||||
|
#define CAN_RX_MAILBOXES 7
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN mailboxes (Mailbox0 should always enabled to transmit)
|
||||||
|
*/
|
||||||
|
#ifndef CAN_USE_MB0
|
||||||
|
#define CAN_USE_MB0 TRUE
|
||||||
|
#endif
|
||||||
|
#ifndef CAN_USE_MB1
|
||||||
|
#define CAN_USE_MB1 TRUE
|
||||||
|
#endif
|
||||||
|
#ifndef CAN_USE_MB2
|
||||||
|
#define CAN_USE_MB2 TRUE
|
||||||
|
#endif
|
||||||
|
#ifndef CAN_USE_MB3
|
||||||
|
#define CAN_USE_MB3 TRUE
|
||||||
|
#endif
|
||||||
|
#ifndef CAN_USE_MB4
|
||||||
|
#define CAN_USE_MB4 FALSE
|
||||||
|
#endif
|
||||||
|
#ifndef CAN_USE_MB5
|
||||||
|
#define CAN_USE_MB5 FALSE
|
||||||
|
#endif
|
||||||
|
#ifndef CAN_USE_MB6
|
||||||
|
#define CAN_USE_MB6 FALSE
|
||||||
|
#endif
|
||||||
|
#ifndef CAN_USE_MB7
|
||||||
|
#define CAN_USE_MB7 FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define CAN_IDE_STD FALSE /**< @brief Standard id. */
|
||||||
|
#define CAN_IDE_EXT TRUE /**< @brief Extended id. */
|
||||||
|
|
||||||
|
#define CAN_RTR_DATA FALSE /**< @brief Data frame. */
|
||||||
|
#define CAN_RTR_REMOTE TRUE /**< @brief Remote frame. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief timeout until can_lld_start stops waiting
|
||||||
|
* on CAN and ends up in error state
|
||||||
|
*/
|
||||||
|
#define AT91C_CAN_TIMEOUT 100
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver pre-compile time settings. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN driver enable switch.
|
||||||
|
* @details If set to @p TRUE the support for CAN0 is included.
|
||||||
|
* @note The default is @p TRUE.
|
||||||
|
*/
|
||||||
|
#if !defined(AT91SAM7_CAN_USE_CAN) || defined(__DOXYGEN__)
|
||||||
|
#define AT91SAM7_CAN_USE_CAN TRUE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN interrupt priority level setting.
|
||||||
|
*/
|
||||||
|
#if !defined(AT91SAM7_CAN_CAN_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||||
|
#define AT91SAM7_CAN_CAN_IRQ_PRIORITY 11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sleep mode related APIs inclusion switch.
|
||||||
|
* @note This switch is enforced to @p FALSE if the driver implementation
|
||||||
|
* does not support the sleep mode.
|
||||||
|
*/
|
||||||
|
#if CAN_SUPPORTS_SLEEP || defined(__DOXYGEN__)
|
||||||
|
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
|
||||||
|
#define CAN_USE_SLEEP_MODE TRUE
|
||||||
|
#endif
|
||||||
|
#else /* !CAN_SUPPORTS_SLEEP */
|
||||||
|
#define CAN_USE_SLEEP_MODE FALSE
|
||||||
|
#endif /* !CAN_SUPPORTS_SLEEP */
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Derived constants and error checks. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP
|
||||||
|
#error "CAN sleep mode not supported in this architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver data structures and types. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of a transmission mailbox index
|
||||||
|
*/
|
||||||
|
typedef uint32_t canmbx_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wakeup status possible states
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
AT91C_TEST_NOK = 0, /**< waiting for wakeup event */
|
||||||
|
AT91C_TEST_OK = 1 /**< wakeup event occured */
|
||||||
|
} canteststate_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief possible receive mailboxes.
|
||||||
|
* These Mailboxes get an offset to ensure that the Mailbox are not uninitialized.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
CAN_TxMB0 = 1, /**< Transmit Mailbox. */
|
||||||
|
CAN_RxMB1 = 2, /**< Receive Mailbox 1. */
|
||||||
|
CAN_RxMB2 = 3, /**< Receive Mailbox 2. */
|
||||||
|
CAN_RxMB3 = 4, /**< Receive Mailbox 3. */
|
||||||
|
CAN_RxMB4 = 5, /**< Receive Mailbox 4. */
|
||||||
|
CAN_RxMB5 = 6, /**< Receive Mailbox 5. */
|
||||||
|
CAN_RxMB6 = 7, /**< Receive Mailbox 6. */
|
||||||
|
CAN_RxMB7 = 8 /**< Receive Mailbox 7. */
|
||||||
|
} canmailbox_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN status flags.
|
||||||
|
*/
|
||||||
|
typedef uint32_t canstatus_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN transmission frame.
|
||||||
|
* @note Accessing the frame data as word16 or word32 is not portable
|
||||||
|
* because machine data endianness, it can be still useful for a
|
||||||
|
* quick filling.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
uint8_t DLC:4; /**< @brief Data length. */
|
||||||
|
uint8_t RTR:1; /**< @brief Frame type. */
|
||||||
|
uint8_t IDE:1; /**< @brief Identifier type. */
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t SID:11; /**< @brief Standard identifier.*/
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
uint32_t EID:29; /**< @brief Extended identifier.*/
|
||||||
|
};
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
uint8_t data8[8]; /**< @brief Frame data. */
|
||||||
|
uint16_t data16[4]; /**< @brief Frame data. */
|
||||||
|
uint32_t data32[2]; /**< @brief Frame data. */
|
||||||
|
};
|
||||||
|
}CANTxFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN received frame.
|
||||||
|
* @note Accessing the frame data as word16 or word32 is not portable
|
||||||
|
* because machine data endianness, it can be still useful for a
|
||||||
|
* quick filling.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
uint8_t DLC:4; /**< @brief Data length. */
|
||||||
|
uint8_t RTR:1; /**< @brief Frame type. */
|
||||||
|
uint8_t IDE:1; /**< @brief Identifier type. */
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint32_t SID:11; /**< @brief Standard identifier.*/
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
uint32_t EID:29; /**< @brief Extended identifier.*/
|
||||||
|
};
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
uint8_t data8[8]; /**< @brief Frame data. */
|
||||||
|
uint16_t data16[4]; /**< @brief Frame data. */
|
||||||
|
uint32_t data32[2]; /**< @brief Frame data. */
|
||||||
|
};
|
||||||
|
canmailbox_t mbid; /**< @brief mailbox to read from */
|
||||||
|
}CANRxFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN filter.
|
||||||
|
* @note NOT used on this platform
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
}CANFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Driver configuration structure.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
#if CAN_USE_MB1
|
||||||
|
uint32_t mb1_can_id; /**< @brief mailbox 1 can id */
|
||||||
|
uint32_t mb1_acceptance_mask; /**< @brief mailbox 1 acceptance mask */
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB2
|
||||||
|
uint32_t mb2_can_id; /**< @brief mailbox 2 can id */
|
||||||
|
uint32_t mb2_acceptance_mask; /**< @brief mailbox 2 acceptance mask */
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB3
|
||||||
|
uint32_t mb3_can_id; /**< @brief mailbox 3 can id */
|
||||||
|
uint32_t mb3_acceptance_mask; /**< @brief mailbox 3 acceptance mask */
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB4
|
||||||
|
uint32_t mb4_can_id; /**< @brief mailbox 4 can id */
|
||||||
|
uint32_t mb4_acceptance_mask; /**< @brief mailbox 4 acceptance mask */
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB5
|
||||||
|
uint32_t mb5_can_id; /**< @brief mailbox 5 can id */
|
||||||
|
uint32_t mb5_acceptance_mask; /**< @brief mailbox 5 acceptance mask */
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB6
|
||||||
|
uint32_t mb6_can_id; /**< @brief mailbox 6 can id */
|
||||||
|
uint32_t mb6_acceptance_mask; /**< @brief mailbox 6 acceptance mask */
|
||||||
|
#endif
|
||||||
|
#if CAN_USE_MB7
|
||||||
|
uint32_t mb7_can_id; /**< @brief mailbox 7 can id */
|
||||||
|
uint32_t mb7_acceptance_mask; /**< @brief mailbox 7 acceptance mask */
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief value of the BR register
|
||||||
|
* @note use 0x00050301 for 1MBit/s!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint32_t br;
|
||||||
|
|
||||||
|
}CANConfig;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure representing an CAN driver.
|
||||||
|
* @note Implementations may extend this structure to contain more,
|
||||||
|
* architecture dependent, fields.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* @brief Driver state.
|
||||||
|
*/
|
||||||
|
canstate_t state;
|
||||||
|
/**
|
||||||
|
* @brief Current configuration data.
|
||||||
|
*/
|
||||||
|
const CANConfig *config;
|
||||||
|
/**
|
||||||
|
* @brief Transmission queue semaphore.
|
||||||
|
*/
|
||||||
|
Semaphore txsem;
|
||||||
|
/**
|
||||||
|
* @brief Receive queue semaphore.
|
||||||
|
*/
|
||||||
|
Semaphore rxsem;
|
||||||
|
/**
|
||||||
|
* @brief One frame for one specified mailbox become available.
|
||||||
|
* @note The number of the mailbox will be broadcasted to all listening threads.
|
||||||
|
* It is responsibility of the application(thread) to empty the specified mailbox
|
||||||
|
* by invoking @p chReceive() when listening to this event.
|
||||||
|
*/
|
||||||
|
EventSource rxfull_event;
|
||||||
|
/**
|
||||||
|
* @brief transmission slot become available.
|
||||||
|
*/
|
||||||
|
EventSource txempty_event;
|
||||||
|
/**
|
||||||
|
* @brief A CAN bus error happened.
|
||||||
|
*/
|
||||||
|
EventSource error_event;
|
||||||
|
#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Entering sleep state event.
|
||||||
|
*/
|
||||||
|
EventSource sleep_event;
|
||||||
|
/**
|
||||||
|
* @brief Exiting sleep state event.
|
||||||
|
*/
|
||||||
|
EventSource wakeup_event;
|
||||||
|
#endif /* CAN_USE_SLEEP_MODE */
|
||||||
|
/* End of the mandatory fields.*/
|
||||||
|
/**
|
||||||
|
* @brief Driver test OK (wakeup event occurred).
|
||||||
|
*/
|
||||||
|
volatile canteststate_t testok;
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the Mailboxes registers block.
|
||||||
|
*/
|
||||||
|
AT91PS_CAN_MB mb[8];
|
||||||
|
/**
|
||||||
|
* @brief Pointer to the CAN registers.
|
||||||
|
*/
|
||||||
|
AT91PS_CAN base;
|
||||||
|
}CANDriver;
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver macros. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
/**
|
||||||
|
* @brief create event mask using enum of the corresponding mailbox.
|
||||||
|
*/
|
||||||
|
#define CAN_EVENT_MASK(mailbox) EVENT_MASK(mailbox-1)
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* External declarations. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#if AT91SAM7_CAN_USE_CAN && !defined(__DOXYGEN__)
|
||||||
|
extern CANDriver CAND;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void can_lld_init(void);
|
||||||
|
void can_lld_serve_interrupt(CANDriver *canp);
|
||||||
|
void can_lld_start(CANDriver *canp);
|
||||||
|
void can_lld_stop(CANDriver *canp);
|
||||||
|
bool_t can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox);
|
||||||
|
void can_lld_transmit(CANDriver *canp,
|
||||||
|
canmbx_t mailbox,
|
||||||
|
const CANTxFrame *crfp);
|
||||||
|
bool_t can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox);
|
||||||
|
void can_lld_receive(CANDriver *canp,
|
||||||
|
canmbx_t mailbox,
|
||||||
|
CANRxFrame *ctfp);
|
||||||
|
#if CAN_USE_SLEEP_MODE
|
||||||
|
void can_lld_sleep(CANDriver *canp);
|
||||||
|
void can_lld_wakeup(CANDriver *canp);
|
||||||
|
|
||||||
|
#endif /* CAN_USE_SLEEP_MODE */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAL_USE_CAN */
|
||||||
|
|
||||||
|
#endif /* _CAN_LLD_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -134,3 +134,18 @@
|
||||||
* .
|
* .
|
||||||
* @ingroup AT91SAM7
|
* @ingroup AT91SAM7
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup AT91SAM7_CAN AT91SAM7 CAN Support
|
||||||
|
* @details The CAN driver supports the AT91SAM7 CAN peripherals.
|
||||||
|
*
|
||||||
|
* @section at91sam7_can_1 Supported HW resources
|
||||||
|
* - CAN.
|
||||||
|
* .
|
||||||
|
* @section at91sam7_can_1 AT91SAM7 CAN driver implementation features
|
||||||
|
* - one send mailbox and seven receive mailboxes.
|
||||||
|
* - wakeup event on receive data.
|
||||||
|
* - deactivate unused mailbox to decrease memory usage and CPU usage
|
||||||
|
* .
|
||||||
|
* @ingroup AT91SAM7
|
||||||
|
*/
|
||||||
|
|
|
@ -8,6 +8,7 @@ PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/AT91SAM7/hal_lld.c \
|
||||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/spi_lld.c \
|
${CHIBIOS}/os/hal/platforms/AT91SAM7/spi_lld.c \
|
||||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/mac_lld.c \
|
${CHIBIOS}/os/hal/platforms/AT91SAM7/mac_lld.c \
|
||||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/pwm_lld.c \
|
${CHIBIOS}/os/hal/platforms/AT91SAM7/pwm_lld.c \
|
||||||
|
${CHIBIOS}/os/hal/platforms/AT91SAM7/can_lld.c \
|
||||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/at91sam7_mii.c \
|
${CHIBIOS}/os/hal/platforms/AT91SAM7/at91sam7_mii.c \
|
||||||
${CHIBIOS}/os/hal/platforms/AT91SAM7/at91lib/aic.c
|
${CHIBIOS}/os/hal/platforms/AT91SAM7/at91lib/aic.c
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,7 @@
|
||||||
- NEW: SPI driver for SPC560Pxx, SPC563Mxx, SPC564Axx, SPC56ELAxx, SPC560Dxx.
|
- NEW: SPI driver for SPC560Pxx, SPC563Mxx, SPC564Axx, SPC56ELAxx, SPC560Dxx.
|
||||||
- NEW: Support for SPC560Dxx devices.
|
- NEW: Support for SPC560Dxx devices.
|
||||||
- NEW: DMA-MUX support for SPC5xx devices.
|
- NEW: DMA-MUX support for SPC5xx devices.
|
||||||
|
- NEW: Added CAN driver for AT91SAM7.
|
||||||
- CHANGE: Moved the STM32 GPT, ICU and PWM low level drivers under
|
- CHANGE: Moved the STM32 GPT, ICU and PWM low level drivers under
|
||||||
./os/hal/platform/STM32/TIMv1. Updated all the impacted project files.
|
./os/hal/platform/STM32/TIMv1. Updated all the impacted project files.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue