Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Message

LPC2119 CAN Rx interrupt handler problem -- never got invoked

2005-09-06 by Marek Peca

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---

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.