Skip to content

Commit

Permalink
Merge pull request #20 from matthewelse/master
Browse files Browse the repository at this point in the history
CAN-Related Pull Request
  • Loading branch information
emilmont committed Aug 6, 2013
2 parents 2c88219 + 45470ab commit 790a71b
Show file tree
Hide file tree
Showing 46 changed files with 5,003 additions and 65 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -29,6 +29,7 @@ NXP:
* LPC4330 (Cortex-M4 + Cortex-M0)
* LPC1347 (Cortex-M3)
* LPC1114 (Cortex-M0)
* LPC11C24 (Cortex-M0)

Freescale:
* [KL25Z](http://mbed.org/handbook/mbed-FRDM-KL25Z) (Cortex-M0+)
Expand Down
55 changes: 44 additions & 11 deletions libraries/mbed/api/CAN.h
Expand Up @@ -150,6 +150,25 @@ class CAN {
*/
void monitor(bool silent);

enum Mode {
Reset = 0,
Normal,
Silent,
LocalTest,
GlobalTest,
SilentTest
};

/** Change CAN operation to the specified mode
*
* @param mode The new operation mode (CAN::Normal, CAN::Silent, CAN::LocalTest, CAN::GlobalTest, CAN::SilentTest)
*
* @returns
* 0 if mode change failed or unsupported,
* 1 if mode change was successful
*/
int mode(Mode mode);

/** Returns number of read errors to detect read overflow errors.
*/
unsigned char rderror();
Expand All @@ -158,35 +177,49 @@ class CAN {
*/
unsigned char tderror();

enum IrqType {
RxIrq = 0,
TxIrq,
EwIrq,
DoIrq,
WuIrq,
EpIrq,
AlIrq,
BeIrq,
IdIrq
};

/** Attach a function to call whenever a CAN frame received interrupt is
* generated.
*
* @param fptr A pointer to a void function, or 0 to set as none
* @param event Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, CAN::TxIrq for transmitted or aborted, CAN::EwIrq for error warning, CAN::DoIrq for data overrun, CAN::WuIrq for wake-up, CAN::EpIrq for error passive, CAN::AlIrq for arbitration lost, CAN::BeIrq for bus error)
*/
void attach(void (*fptr)(void));
void attach(void (*fptr)(void), IrqType type=RxIrq);

/** Attach a member function to call whenever a CAN frame received interrupt
* is generated.
*
* @param tptr pointer to the object to call the member function on
* @param mptr pointer to the member function to be called
* @param event Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, TxIrq for transmitted or aborted, EwIrq for error warning, DoIrq for data overrun, WuIrq for wake-up, EpIrq for error passive, AlIrq for arbitration lost, BeIrq for bus error)
*/
template<typename T>
void attach(T* tptr, void (T::*mptr)(void)) {
void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq) {
if((mptr != NULL) && (tptr != NULL)) {
_rxirq.attach(tptr, mptr);
setup_interrupt();
} else {
remove_interrupt();
_irq[type].attach(tptr, mptr);
can_irq_set(&_can, (CanIrqType)type, 1);
}
else {
can_irq_set(&_can, (CanIrqType)type, 0);
}
}

private:
can_t _can;
FunctionPointer _rxirq;
static void _irq_handler(uint32_t id, CanIrqType type);

void setup_interrupt(void);
void remove_interrupt(void);
protected:
can_t _can;
FunctionPointer _irq[9];
};

} // namespace mbed
Expand Down
65 changes: 14 additions & 51 deletions libraries/mbed/common/CAN.cpp
Expand Up @@ -23,10 +23,12 @@ namespace mbed {

CAN::CAN(PinName rd, PinName td) {
can_init(&_can, rd, td);
can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this);
}

CAN::~CAN() {
can_free(&_can);
can_irq_free(&_can);
}

int CAN::frequency(int f) {
Expand Down Expand Up @@ -57,62 +59,23 @@ void CAN::monitor(bool silent) {
can_monitor(&_can, (silent) ? 1 : 0);
}

static FunctionPointer* can_obj[2] = { NULL };

// Have to check that the CAN block is active before reading the Interrupt
// Control Register, or the mbed hangs
void can_irq(void) {
uint32_t icr;

if(LPC_SC->PCONP & (1 << 13)) {
icr = LPC_CAN1->ICR;

if(icr && (can_obj[0] != NULL)) {
can_obj[0]->call();
}
}

if(LPC_SC->PCONP & (1 << 14)) {
icr = LPC_CAN2->ICR;
if(icr && (can_obj[1] != NULL)) {
can_obj[1]->call();
}
}

int CAN::mode(Mode mode) {
return can_mode(&_can, (CanMode)mode);
}

void CAN::setup_interrupt(void) {
switch ((int)_can.dev) {
case CAN_1: can_obj[0] = &_rxirq; break;
case CAN_2: can_obj[1] = &_rxirq; break;
}
_can.dev->MOD |= 1;
_can.dev->IER |= 1;
_can.dev->MOD &= ~1;
NVIC_SetVector(CAN_IRQn, (uint32_t) &can_irq);
NVIC_EnableIRQ(CAN_IRQn);
}

void CAN::remove_interrupt(void) {
switch ((int)_can.dev) {
case CAN_1: can_obj[0] = NULL; break;
case CAN_2: can_obj[1] = NULL; break;
}

_can.dev->IER &= ~(1);
if ((can_obj[0] == NULL) && (can_obj[1] == NULL)) {
NVIC_DisableIRQ(CAN_IRQn);
void CAN::attach(void (*fptr)(void), IrqType type) {
if (fptr) {
_irq[(CanIrqType)type].attach(fptr);
can_irq_set(&_can, (CanIrqType)type, 1);
} else {
can_irq_set(&_can, (CanIrqType)type, 0);
}
}
}

void CAN::attach(void (*fptr)(void)) {
if (fptr != NULL) {
_rxirq.attach(fptr);
setup_interrupt();
} else {
remove_interrupt();
void CAN::_irq_handler(uint32_t id, CanIrqType type) {
CAN *handler = (CAN*)id;
handler->_irq[type].call();
}
}

} // namespace mbed

Expand Down
30 changes: 30 additions & 0 deletions libraries/mbed/hal/can_api.h
Expand Up @@ -28,13 +28,43 @@
extern "C" {
#endif

typedef enum {
IRQ_RX,
IRQ_TX,
IRQ_ERROR,
IRQ_OVERRUN,
IRQ_WAKEUP,
IRQ_PASSIVE,
IRQ_ARB,
IRQ_BUS,
IRQ_READY
} CanIrqType;


typedef enum {
MODE_RESET,
MODE_NORMAL,
MODE_SILENT,
MODE_TEST_GLOBAL,
MODE_TEST_LOCAL,
MODE_TEST_SILENT
} CanMode;

typedef void (*can_irq_handler)(uint32_t id, CanIrqType type);

typedef struct can_s can_t;

void can_init (can_t *obj, PinName rd, PinName td);
void can_free (can_t *obj);
int can_frequency(can_t *obj, int hz);

void can_irq_init (can_t *obj, can_irq_handler handler, uint32_t id);
void can_irq_free (can_t *obj);
void can_irq_set (can_t *obj, CanIrqType irq, uint32_t enable);

int can_write (can_t *obj, CAN_Message, int cc);
int can_read (can_t *obj, CAN_Message *msg);
int can_mode (can_t *obj, CanMode mode);
void can_reset (can_t *obj);
unsigned char can_rderror (can_t *obj);
unsigned char can_tderror (can_t *obj);
Expand Down

0 comments on commit 790a71b

Please sign in to comment.