--- /dev/null
+#include <stdlib.h>
+#include <types.h>
+#include <lpc21xx.h>
+
+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;
+
+typedef void (*can_rx_callback)(can_msg_t *msg);
+
+/* public global variables */
+volatile static int can_msg_received = 0;
+volatile static can_msg_t can_rx_msg;
+
+/* private global variables */
+uint32_t *can_rx_msg_data = (uint32_t*)can_rx_msg.data;
+can_rx_callback can_rx_cb;
+
+/* * */
+
+void can_rx_isr(void) __attribute__ ((interrupt));
+
+void can_init(uint32_t btr, unsigned rx_isr_vect, can_rx_callback rx_cb) {
+ /* 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;
+ /* register Rx handler */
+ //can_rx_cb = rx_cb;
+ /* set interrupt vector */
+ //((uint32_t*)&VICVectAddr0)[rx_isr_vect] = (uint32_t)can_rx_isr;
+ //((uint32_t*)&VICVectCntl0)[rx_isr_vect] = 0x20 | 26;
+ //VICVectAddr0 = (uint32_t)can_rx_isr;
+ VICVectAddr0 = (unsigned)can_rx_isr;
+ VICVectCntl0 = 0x20 | 26;
+ /* enable Rx int */
+ VICIntEnable = 0x04000000;
+ C1IER = 0x1;
+ /* normal (operating) mode */
+ C1MOD = 0x0;
+#if 0
+ /* LPC2119 CAN.5 erratum workaround */
+ C1TFI1 = 0x00000000;
+ C1TID1 = 0x0;
+ C1CMR = 0x23;
+#endif
+}
+
+int can_tx_msg(can_msg_t *tx_msg);
+
+void can_rx_isr(void) {
+ IOCLR0 |= 0x00000080;
+ can_rx_msg.flags = C1RFS;
+ can_rx_msg.dlc = (can_rx_msg.flags>>16) & 0x7;
+ can_rx_msg.id = C1RID;
+ can_rx_msg_data[0] = C1RDA;
+ can_rx_msg_data[1] = C1RDB;
+ can_msg_received = 1;
+ if (can_rx_cb != NULL)
+ can_rx_cb(&can_rx_msg);
+
+ /*DBG*/can_tx_msg(&can_rx_msg);
+
+ /* release Rx buffer */
+ C1CMR = 0x4;
+ /* int acknowledge */
+ VICVectAddr = 0;
+}
+
+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 = 0x21; //0x21; //0x30; //0x20;
+ return 0; /* OK */
+}
+
+/* * * * */
+
+void DefaultISR (void) __attribute__ ((interrupt));
+
+void DefaultISR(void) {
+ IOCLR0 |= 0x00000080;
+ while (1)
+ { // We should never get here, if we do it is an error
+ }
+}
+
+int main() {
+ can_msg_t msg;
+
+ /*DBG*/IODIR0 |= 0x00000080;
+ IOSET0 |= 0x00000080;
+ //IOCLR0 |= 0x00000080;
+
+ /* peripheral clock = CPU clock (10MHz) */
+ VPBDIV = 1;
+
+ MEMMAP = 0x2;
+
+ // --- cizi moudra
+ // Init Vector Interrupt Controller
+ VICIntEnClr = 0xFFFFFFFFL; // Disable all Ints
+ VICIntSelect = 0x00000000L;
+
+ // Install Default IRQVec
+ VICDefVectAddr = (uint32_t)DefaultISR; // set interrupt vector
+ // ---------------
+
+ 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';
+
+ can_init(0x25c013, 0, NULL);
+
+ while (can_tx_msg(&msg));
+
+ for (;;)
+ if (can_msg_received) {
+ if (can_rx_msg.id == 3)
+ while(can_tx_msg(&msg));
+ can_msg_received = 0;
+ }
+
+ return(0);
+}