Forums

LPC2119 CAN Rx interrupt handler problem -- never got invoked

Started by Marek Peca September 6, 2005
Dear colleagues,

playing half a day with LPC2119 CAN controller, I really halted at
problem, that interrupt service routine for CAN message reception
does not work.

I have a board with LPC2119 (TPN0431AY), crystal, CPU and peripheral
frequency equal to 10MHz. It communicates well via CAN with laptop
CAN analyser software (both reception and transmission), using
50kb/s. Programmed to RAM using bootloader software (other programs
works well, even with interrupts). Compiled on Linux using gcc,
header file lpc21xx.h and crt0.s downloaded somewhere.

* When I use polling for incoming message (C1GSR&0x1), everything
works well. When I setup CAN receive interrupt handler, it does not
work -- the handler is never called after message reception.

Here is minimalized code (single-file), which works without ISR and
fails using it. It toggles level at pin P0.7 after msg reception if
DONT_USE_IRQ defined, P0.7 remains high if undefined. Any suggestions? Am I missing some point?
Thank you very much for your help.
Marek.

---CAN-does-not-work-with-Rx-ISR---

#include <stdlib.h>
#include <types.h>
#include <lpc21xx.h>

//#define DONT_USE_IRQ

typedef struct _can_msg_t {
#define CAN_MSG_RTR 0x40000000
#define CAN_MSG_EXTID 0x80000000
uint32_t flags;
unsigned short dlc;
uint32_t id;
unsigned char data[8];
} can_msg_t;

void debug_toggle_pin() {
if (IOPIN0 & 0x00000080)
IOCLR0 |= 0x00000080;
else
IOSET0 |= 0x00000080;
}

void can_rx_isr(void) __attribute__ ((interrupt));

void can_init(uint32_t btr) {
/* enable CAN1 Rx pin */
PINSEL1 |= 0x00040000;
PINSEL1 &= 0xfff7ffff;
/* receive all messages, no filtering */
AFMR = 0x2;
/* reset mode */
C1MOD = 0x1;
/* -- addition from lpc2000 maillist msg #3052: */
C1CMR = 0x0e; //Clear receive buffer, data overrun, abort tx
/* -- end of addition */
C1IER = 0x0;
C1GSR = 0x0;
/* set baudrate & timing */
C1BTR = btr;
/* set interrupt vector */
#ifndef DONT_USE_IRQ
VICVectAddr0 = (uint32_t)can_rx_isr;
VICVectCntl0 = 0x20 | 26;
/* enable Rx int */
VICIntEnable = 0x04000000;
C1IER = 0x1;
#endif
/* normal (operating) mode */
C1MOD = 0x0;
#if 0
/* LPC2119 CAN.5 erratum workaround */
C1TFI1 = 0x00000000;
C1TID1 = 0x0;
C1CMR = 0x23;
#endif
}

void can_rx_isr(void) {
/** The Action **/
debug_toggle_pin();
/* release Rx buffer */
C1CMR = 0x4;
/* int acknowledge */
VICVectAddr = 0xffffffff;
}

int can_tx_msg(can_msg_t *tx_msg) {
uint32_t *data = (uint32_t*)tx_msg->data;

/* check, if buffer is ready (previous Tx completed) */
if ((C1SR & 0x4) == 0)
return -1; /* busy */
C1TFI1 = (tx_msg->flags & 0xc0000000) |
((tx_msg->dlc<<16) & 0x000f0000);
C1TID1 = tx_msg->id;
C1TDA1 = data[0];
C1TDB1 = data[1];
/* start transmission */
C1CMR = 0x30; //0x21; //0x30; //0x20;
return 0; /* OK */
}

void DefaultISR (void) __attribute__ ((interrupt));

void DefaultISR(void) {
debug_toggle_pin();
for (;;);
}

int main() {
can_msg_t msg;

/*DEBUG*/
IODIR0 |= 0x00000080;
IOSET0 |= 0x00000080;

/* peripheral clock = CPU clock (10MHz) */
VPBDIV = 1;
// ---------------
VICIntEnClr = 0xFFFFFFFF;
VICIntSelect = 0x00000000;
VICDefVectAddr = (uint32_t)DefaultISR;
// ---------------

/* Tx test message */
msg.flags = 0;
msg.dlc = 4;
msg.id = 0x123;
msg.data[0] = 'A';
msg.data[1] = 'h';
msg.data[2] = 'o';
msg.data[3] = 'j';

/* 0x25c013 -- 10MHz, 50kb/s, tested & measured -- OK */
can_init(0x25c013);

/* send test msg */
while (can_tx_msg(&msg));

#ifdef DONT_USE_IRQ
for (;;)
if (C1GSR & 0x1) {
debug_toggle_pin();
C1CMR = 0x4;
}
#else
for (;;);
#endif
}
------------------THE-END---


An Engineer's Guide to the LPC2100 Series

Hello,

the problem was in incorrect MEMMAP setting. In LPC2106 chip other
interrupt service programs worked well, because it had
ldr pc,[pc,#-0xff0] programmed in the flash by our vendor.

Now, with addition of MEMMAP=0x2, posted CAN ISR code works well.

Best regards,
Marek P.

--- In lpc2000@lpc2..., Marek Peca <marek@d...> wrote:
> Dear colleagues,
>
> playing half a day with LPC2119 CAN controller, I really halted at
> problem, that interrupt service routine for CAN message reception
> does not work.
>
> I have a board with LPC2119 (TPN0431AY), crystal, CPU and peripheral
> frequency equal to 10MHz. It communicates well via CAN with laptop
> CAN analyser software (both reception and transmission), using
> 50kb/s. Programmed to RAM using bootloader software (other programs
> works well, even with interrupts). Compiled on Linux using gcc,
> header file lpc21xx.h and crt0.s downloaded somewhere.
>
> * When I use polling for incoming message (C1GSR&0x1), everything
> works well. When I setup CAN receive interrupt handler, it does not
> work -- the handler is never called after message reception.