]> rtime.felk.cvut.cz Git - sysless.git/commitdiff
added highlevel CAN library lpcanvca, with API resembling OCERA VCA
authorMarek P <marek@tesla.(none)>
Wed, 21 Jan 2009 08:36:28 +0000 (09:36 +0100)
committerMarek P <marek@tesla.(none)>
Wed, 21 Jan 2009 08:36:28 +0000 (09:36 +0100)
lpcanvca works atop of lowlevel lpcan library. API is sancta simplicitas,
inspired by OCERA Virtual CAN API (VCA), available in libvca, using LinCAN
on host computer.

Common points: blocking and nonblocking calls;
Differences: different initialization (need to supply IRQ vector numbers,
 CAN HW controller number 0 or 1 instead of /dev filename), no timeout
 support

arch/arm/mach-lpc21xx/libs/Makefile.omk
arch/arm/mach-lpc21xx/libs/lpcanvca/Makefile [new file with mode: 0644]
arch/arm/mach-lpc21xx/libs/lpcanvca/Makefile.omk [new file with mode: 0644]
arch/arm/mach-lpc21xx/libs/lpcanvca/lpcan_vca.h [new file with mode: 0644]
arch/arm/mach-lpc21xx/libs/lpcanvca/lpcanvca.c [new file with mode: 0644]

index 8fc5eb70257bd7aa24c0caa81471de9ea2d540ca..504872180dbbd02366c9d7341c5e6a8c857426dd 100644 (file)
@@ -1,3 +1,3 @@
 # -*- makefile -*-
 
-SUBDIRS = boot can lpcan uart_zen uart-nozen ldscripts
+SUBDIRS = boot can lpcan lpcanvca uart_zen uart-nozen ldscripts
diff --git a/arch/arm/mach-lpc21xx/libs/lpcanvca/Makefile b/arch/arm/mach-lpc21xx/libs/lpcanvca/Makefile
new file mode 100644 (file)
index 0000000..f595272
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" == `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else   
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/arch/arm/mach-lpc21xx/libs/lpcanvca/Makefile.omk b/arch/arm/mach-lpc21xx/libs/lpcanvca/Makefile.omk
new file mode 100644 (file)
index 0000000..77b90c6
--- /dev/null
@@ -0,0 +1,7 @@
+# -*- makefile -*-
+
+lib_LIBRARIES = lpcanvca
+
+lpcanvca_SOURCES = lpcanvca.c
+
+rename_include_HEADERS = lpcan_vca.h->can/lpcan_vca.h
diff --git a/arch/arm/mach-lpc21xx/libs/lpcanvca/lpcan_vca.h b/arch/arm/mach-lpc21xx/libs/lpcanvca/lpcan_vca.h
new file mode 100644 (file)
index 0000000..4a8a6de
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _CAN_VCA_H
+#define _CAN_VCA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************/
+/* VCA Basic Functions */
+
+#define VCA_OK 0
+
+typedef int vca_handle_t;
+
+long vca_h2log(vca_handle_t vcah);
+
+#define VCA_O_NONBLOCK 1
+
+int lpc_vca_open_handle(vca_handle_t *vcah_p, int dev, int flags, uint32_t btr, unsigned rx_ivect, unsigned tx_ivect, unsigned err_ivect);
+int vca_close_handle(vca_handle_t vcah);
+int vca_send_msg_seq(vca_handle_t vcah, canmsg_t *messages, int count);
+int vca_rec_msg_seq(vca_handle_t vcah, canmsg_t *messages, int count);
+int vca_wait(vca_handle_t vcah, int wait_msec, int what);
+
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /* _CAN_VCA_H */
diff --git a/arch/arm/mach-lpc21xx/libs/lpcanvca/lpcanvca.c b/arch/arm/mach-lpc21xx/libs/lpcanvca/lpcanvca.c
new file mode 100644 (file)
index 0000000..2b15373
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * ON-TRACK CAN abstraction layer library
+ * resembling and inspired by the Virtual CAN API from OCERA framework
+ *
+ * Contains parts of original Virtual/Versatile CAN API
+ *   by Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *   and Frantisek Vacek <vacek@rtime.felk.cvut.cz>, 2002
+ *
+ * Modified and adapted as a functional subset to run on system-less
+ *   Philips LPC2xxx atop of "lpcan" CAN driver library
+ *   by Marek Peca <mp@duch.cz>, 2008/04
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <types.h>
+#include <cpu_def.h>
+#include <errno.h>
+#include <can/canmsg.h>
+#include <can/lpcan.h>
+#include "lpcan_vca.h"
+
+#define valid(device) ((device >= 0) && (device < CAN_NUM_DEVICES))
+
+static struct vca_dev_t {
+  int open, flags;
+  uint32_t btr;
+  unsigned rx_ivect, tx_ivect, err_ivect;
+} vca_dev[CAN_NUM_DEVICES];
+
+inline void candev_init(int dev) {
+  can_init(dev, vca_dev[dev].btr,
+          vca_dev[dev].rx_ivect,
+          vca_dev[dev].tx_ivect,
+          vca_dev[dev].err_ivect,
+          NULL, 0);
+}
+
+inline int check_error(int dev) {
+  unsigned e = can_error(dev);
+  if (!e)
+    return 0;
+  if (e & ~CAN_ERR_RXOVER) {
+    /* CAN I/O error -- reinitialize the controller to recover operation */
+    cli();
+    can_off(dev);
+    candev_init(dev);
+    sti();
+  }
+  errno = EIO;
+  return e;
+}
+
+/**
+ * @param vcah_p points to location filled by new VCA handle
+ * @param dev CAN controller number (0, 1,...)
+ * @param flags flags modifying style of open (VCA_O_NOBLOCK)
+ * @param btr bit timing register (see LPC2xxx CAN docs), can be set by <code>lpcan_btr()</code> function from <em>lpcan</em> driver library
+ * @param rx_ivect receive interrupt vector number
+ * @param tx_ivect transmit interrupt vector number
+ * @param err_ivect error interrupt vector number
+ * @return VCA_OK in case of success
+ *
+ * Opens new VCA handle on LPC2xxx hardware.
+ *
+ * Interrupt vector numbers (see LPC2xxx VIC documentation) must be supplied
+ * by the caller in order to avoid conflicts with rest of hardware.
+ */
+int lpc_vca_open_handle(vca_handle_t *vcah_p, int dev, int flags, uint32_t btr, unsigned rx_ivect, unsigned tx_ivect, unsigned err_ivect) {
+  if (!valid(dev)) {
+    errno = ENODEV;
+    return -1;
+  }
+  vca_dev[dev].flags = flags;
+  vca_dev[dev].btr = btr;
+  vca_dev[dev].rx_ivect = rx_ivect;
+  vca_dev[dev].tx_ivect = tx_ivect;
+  vca_dev[dev].err_ivect = err_ivect;
+  vca_dev[dev].open = 1;
+  candev_init(dev);
+  *vcah_p = dev;
+  return VCA_OK;
+}
+
+/**
+ * @param vcah VCA handle
+ * @return VCA_OK in case of success
+ *
+ * Closes previously acquired VCA handle.
+ */
+int vca_close_handle(vca_handle_t vcah) {
+  if (!valid(vcah)) {
+    errno = ENODEV;
+    return -1;
+  }
+  if (!vca_dev[vcah].open) {
+    errno = EBADF;
+    return -1;
+  }
+  vca_dev[vcah].open = 0;
+  can_off(vcah);
+  return VCA_OK;
+}
+
+/**
+ * @param vcah VCA handle
+ * @param messages points to continuous array of CAN messages to send
+ * @param count count of messages in array
+ * @return Number of sucessfully sent messages or error < 0
+ *
+ * Sends sequentially block of CAN messages.
+ */
+int vca_send_msg_seq(vca_handle_t vcah, canmsg_t *messages, int count) {
+  int m, rc;
+  if (check_error(vcah))
+    return -1;
+  for (m = 0; m < count; m++) {
+    if (vca_dev[vcah].flags & VCA_O_NONBLOCK) {
+      rc = can_tx_msg(vcah, &messages[m]);
+      if (rc) {
+       if (check_error(vcah))
+         return -1;
+       errno = EAGAIN;
+       return m;
+      }
+    }
+    else {
+      do {
+       rc = can_tx_msg(vcah, &messages[m]);
+       if (check_error(vcah))
+         return -1;
+      } while (rc);
+    }
+  }
+  if (check_error(vcah))
+    return -1;
+  return m;
+}
+
+/**
+ * @param vcah VCA handle
+ * @param messages points to array for received CAN messages
+ * @param count number of message slots in array
+ * @return number of received messages or error < 0
+ *
+ * Receive sequential block of CAN messages.
+ */
+int vca_rec_msg_seq(vca_handle_t vcah, canmsg_t *messages, int count) {
+  int m, rc;
+  if (check_error(vcah))
+    return -1;
+  for (m = 0; m < count; m++) {
+    if (vca_dev[vcah].flags & VCA_O_NONBLOCK) {
+      rc = can_rx_msg(vcah, &messages[m]);
+      if (rc) {
+       if (check_error(vcah))
+         return -1;
+       errno = EAGAIN;
+       return m;
+      }
+    }
+    else {
+      do {
+       rc = can_rx_msg(vcah, &messages[m]);
+       if (check_error(vcah))
+         return -1;
+      } while (rc);
+    }
+  }
+  if (check_error(vcah))
+    return -1;
+  return m;
+}
+
+/**
+ * @param vcah VCA handle
+ * @param wait_msec number of miliseconds to wait, 0 => forever
+ * @param what 0,1 => wait for Rx message, 2 => wait for Tx - free
+ *        3 => wait for both
+ * @return Positive value if wait condition is satisfied
+ *
+ * Blocking wait for the new message(s) or sending.
+ * Currently, no timeout is implemented on LPC2xxx, so only infinite
+ * waiting (wait_msec = 0) or no waiting (wait_msec != 0) can be performed.
+ */
+int vca_wait(vca_handle_t vcah, int wait_msec, int what) {
+  if (!what)
+    what = 1;
+  do {
+    if (check_error(vcah))
+      return -1;
+    if ((what & 1) && !can_rx_empty(vcah))
+      return 1;
+    if ((what & 2) && can_tx_empty(vcah))
+      return 2;
+  } while (wait_msec == 0);
+  return 0;
+}
+
+/* EOF */