All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wolfgang Grandegger <wg@domain.hid>
To: xenomai-core <xenomai@xenomai.org>
Subject: [Xenomai-core] [PATCH] RT-Socket-CAN fixes
Date: Mon, 30 Oct 2006 13:04:44 +0100	[thread overview]
Message-ID: <4545EA5C.7020105@domain.hid> (raw)

[-- Attachment #1: Type: text/plain, Size: 639 bytes --]

Hallo,

attached you will find a patch for Xenomai RT-Socket-CAN fixing:

2006-10-30  Wolfgang Grandegger  <wg@domain.hid>

         * src/utils/can/rtcanrecv: Add timestamp support via
           rt_dev_recvmsg().

         * ksrc/drivers/can/mscan/rtcan_mscan.c (rtcan_mscan_interrupt),
         ksrc/drivers/can/mscan/rtcan_mscan_regs.h: Restrict MSCAN TX
         hardware buffer usage to one for the sake of real-time. Fix bug
         with TX IRQ handling. Copy timestamp also for error messages.

         * ksrc/drivers/can/sja1000/rtcan_sja1000.c(rtcan_sja_interrupt):
         Copy timestamp also for error messages.

Wolfgang.


[-- Attachment #2: xenomai-rtcan-update.patch --]
[-- Type: text/x-patch, Size: 9340 bytes --]

Index: src/utils/can/rtcanrecv.c
===================================================================
--- src/utils/can/rtcanrecv.c	(revision 1770)
+++ src/utils/can/rtcanrecv.c	(working copy)
@@ -20,6 +20,7 @@
 	    " -f  --filter=id:mask[:id:mask]... apply filter\n"
 	    " -e  --error=mask      receive error messages\n"
 	    " -t, --timeout=MS      timeout in ms\n"
+	    " -T, --timestamp       with timestamp\n"
 	    " -v, --verbose         be verbose\n"
 	    " -p, --print=MODULO    print every MODULO message\n"
 	    " -h, --help            this help\n",
@@ -30,7 +31,7 @@
 extern int optind, opterr, optopt;
 
 static int s = -1, verbose = 0, print = 1;
-static nanosecs_rel_t timeout = 0;
+static nanosecs_rel_t timeout = 0, with_timestamp = 0;
 
 RT_TASK rt_task_desc;
 
@@ -84,10 +85,27 @@
     struct can_frame frame;
     struct sockaddr_can addr;
     socklen_t addrlen = sizeof(addr);
+    struct msghdr msg;
+    struct iovec iov;
+    nanosecs_abs_t timestamp;
 
+    if (with_timestamp) {
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_name = (void *)&addr;
+	msg.msg_namelen = sizeof(struct sockaddr_can);
+	msg.msg_control = (void *)&timestamp;
+	msg.msg_controllen = sizeof(nanosecs_abs_t);
+    }
+
     while (1) {
-	ret = rt_dev_recvfrom(s, (void *)&frame, sizeof(can_frame_t), 0,
-	                      (struct sockaddr *)&addr, &addrlen);
+	if (with_timestamp) {
+	    iov.iov_base = (void *)&frame;
+	    iov.iov_len = sizeof(can_frame_t);
+	    ret = rt_dev_recvmsg(s, &msg, 0);
+	} else
+	    ret = rt_dev_recvfrom(s, (void *)&frame, sizeof(can_frame_t), 0,
+				  (struct sockaddr *)&addr, &addrlen);
 	if (ret < 0) {
 	    switch (ret) {
 	    case -ETIMEDOUT:
@@ -106,6 +124,8 @@
 
 	if (print && (count % print) == 0) {
 	    printf("#%d: (%d) ", count, addr.can_ifindex);
+	    if (with_timestamp && msg.msg_controllen)
+		printf("%lldns ", timestamp);
 	    if (frame.can_id & CAN_ERR_FLAG)
 		printf("!0x%08x!", frame.can_id & CAN_ERR_MASK);
 	    else if (frame.can_id & CAN_EFF_FLAG)
@@ -147,6 +167,7 @@
 	{ "filter", required_argument, 0, 'f'},
 	{ "error", required_argument, 0, 'e'},
 	{ "timeout", required_argument, 0, 't'},
+	{ "timestamp", no_argument, 0, 'T'},
 	{ 0, 0, 0, 0},
     };
 
@@ -155,7 +176,7 @@
     signal(SIGTERM, cleanup_and_exit);
     signal(SIGINT, cleanup_and_exit);
 
-    while ((opt = getopt_long(argc, argv, "hve:f:t:p:",
+    while ((opt = getopt_long(argc, argv, "hve:f:t:p:T",
 			      long_options, NULL)) != -1) {
 	switch (opt) {
 	case 'h':
@@ -196,6 +217,10 @@
 	    timeout = (nanosecs_rel_t)strtoul(optarg, NULL, 0) * 1000000;
 	    break;
 
+	case 'T':
+	    with_timestamp = 1;
+	    break;
+
 	default:
 	    fprintf(stderr, "Unknown option %c\n", opt);
 	    break;
@@ -269,6 +294,14 @@
 	}
     }
 
+    if (with_timestamp) {
+	ret = rt_dev_ioctl(s, RTCAN_RTIOC_TAKE_TIMESTAMP, RTCAN_TAKE_TIMESTAMPS);
+	if (ret) {
+	    fprintf(stderr, "rt_dev_ioctl TAKE_TIMESTAMP: %s\n", strerror(-ret));
+	    goto failure;
+	}
+    }
+
     snprintf(name, sizeof(name), "rtcanrecv-%d", getpid());
     ret = rt_task_shadow(&rt_task_desc, name, 1, 0);
     if (ret) {
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1770)
+++ ChangeLog	(working copy)
@@ -1,3 +1,15 @@
+2006-10-30  Wolfgang Grandegger  <wg@domain.hid>
+
+	* src/utils/can/rtcanrecv: Add timestamp support via rt_dev_recvmsg().
+
+	* ksrc/drivers/can/mscan/rtcan_mscan.c (rtcan_mscan_interrupt),
+	ksrc/drivers/can/mscan/rtcan_mscan_regs.h: Restrict MSCAN TX hardware
+	buffer usage to one for the sake of real-time. Fix bug with TX IRQ
+	handling. Copy timestamp also for error messages.
+
+	* ksrc/drivers/can/sja1000/rtcan_sja1000.c (rtcan_sja_interrupt):
+	Copy timestamp also for error messages.
+
 2006-10-27  Jan Kiszka  <jan.kiszka@domain.hid>
 
 	* ksrc/nucleus/pod.c (xnpod_set_thread_periodic): Fix LART in
Index: ksrc/drivers/can/mscan/rtcan_mscan.c
===================================================================
--- ksrc/drivers/can/mscan/rtcan_mscan.c	(revision 1770)
+++ ksrc/drivers/can/mscan/rtcan_mscan.c	(working copy)
@@ -232,7 +232,7 @@
     struct rtcan_skb skb;
     struct rtcan_device *dev;
     struct mscan_regs *regs;
-    u8 t_status, r_status;
+    u8 canrflg;
     int recv_lock_free = 1;
     int ret = RTDM_IRQ_NONE;
 
@@ -242,29 +242,24 @@
 
     rtdm_lock_get(&dev->device_lock);
 
-    t_status = regs->cantflg;
-    r_status = regs->canrflg;
+    canrflg = regs->canrflg;
 
     ret = RTDM_IRQ_HANDLED;
 
     /* Transmit Interrupt? */
-    if ((t_status & MSCAN_TXE)) {
-	/* Disable transmit interrupt here or it will
-	 * constantly be pending.
-	 */
-	regs->cantier &= ~MSCAN_TXIE;
-
+    if ((regs->cantier & MSCAN_TXIE0) && (regs->cantflg & MSCAN_TXE0)) {
+	regs->cantier = 0;
 	/* Wake up a sender */
 	rtdm_sem_up(&dev->tx_sem);
     }
 
     /* Wakeup interrupt?  */
-    if ((r_status & MSCAN_WUPIF)) {
+    if ((canrflg & MSCAN_WUPIF)) {
 	rtdm_printk("WUPIF interrupt\n");
     }
 
     /* Receive Interrupt? */
-    if ((r_status & MSCAN_RXF)) {
+    if ((canrflg & MSCAN_RXF)) {
 	
 	/* Read out HW registers */
 	rtcan_mscan_rx_interrupt(dev, &skb);
@@ -289,10 +284,13 @@
     }
 
     /* Error Interrupt? */
-    if ((r_status & (MSCAN_CSCIF | MSCAN_OVRIF))) {
+    if ((canrflg & (MSCAN_CSCIF | MSCAN_OVRIF))) {
 	/* Check error condition and fill error frame */
-	rtcan_mscan_err_interrupt(dev, &skb, r_status);
+	rtcan_mscan_err_interrupt(dev, &skb, canrflg);
 
+	memcpy((void *)&skb.rb_frame + skb.rb_frame_size,
+	       &timestamp, TIMESTAMP_SIZE);
+
 	if (recv_lock_free) {
 	    recv_lock_free = 0;
 	    rtdm_lock_get(&rtcan_recv_list_lock);
@@ -306,8 +304,8 @@
     /* Acknowledge the handled interrupt within the controller.
      * Only do so for the receiver interrupts.
      */
-    if (r_status)
-	regs->canrflg = r_status;
+    if (canrflg)
+	regs->canrflg = canrflg;
 
     if (!recv_lock_free) {
         rtdm_lock_put(&rtcan_socket_lock);
@@ -422,8 +420,8 @@
     case CAN_STATE_STOPPED:
 	/* Set error active state */
 	state = CAN_STATE_ACTIVE;
-	/* Set up sender "mutex", we have three TX buffer in HW */
-	rtdm_sem_init(&dev->tx_sem, MSCAN_TX_BUFS);
+	/* Set up sender "mutex" */
+	rtdm_sem_init(&dev->tx_sem, 1);
 
 	if ((dev->ctrl_mode & CAN_CTRLMODE_LISTENONLY)) {
 	    regs->canctl1 |= MSCAN_LISTEN;
@@ -458,7 +456,7 @@
 	/* Trigger bus-off recovery */
 	regs->canrier = MSCAN_RIER;
 	/* Set up sender "mutex" */
-	rtdm_sem_init(&dev->tx_sem, MSCAN_TX_BUFS);
+	rtdm_sem_init(&dev->tx_sem, 1);
 	/* Set error active state */
 	state = CAN_STATE_ACTIVE;
 
@@ -595,7 +593,7 @@
 static int rtcan_mscan_start_xmit(struct rtcan_device *dev,
 				  can_frame_t *frame)
 {
-    int             i, id, buf;
+    int             i, id;
     /* "Real" size of the payload */
     unsigned char   size;
     /* Content of frame information register */
@@ -603,18 +601,13 @@
 
     struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
 
-    /* Find an empty TX buffer. */
-    for (buf = 0; buf < MSCAN_TX_BUFS; buf++) {
-	if ((regs->cantflg & (1 << buf)))
-	    break;
-    }
-    if (buf == MSCAN_TX_BUFS) {
-	/* No buffer is available. */
-	rtdm_printk("rtcan_mscan_start_xmit: no TX buffer availabe");
+    /* Is TX buffer empty? */
+    if (!(regs->cantflg & MSCAN_TXE0)) {
+	rtdm_printk("rtcan_mscan_start_xmit: TX buffer not empty");
 	return -EIO;
     }
     /* Select the buffer we've found. */
-    regs->cantbsel = 1 << buf;
+    regs->cantbsel = MSCAN_TXE0;
 
     /* Get DLC and ID */
     dlc = frame->can_dlc;
@@ -663,10 +656,10 @@
     regs->cantxfg.tbpr = 0;	/* all messages have the same prio */
 
     /* Trigger transmission. */
-    regs->cantflg = (1 << buf);
-    
+    regs->cantflg = MSCAN_TXE0;
+
     /* Enable interrupt. */
-    regs->cantier |= (1 << buf);
+    regs->cantier |= MSCAN_TXIE0;
 
     return 0;
 }
@@ -742,7 +735,6 @@
     int ret, irq;
     unsigned long addr;
     struct rtcan_device *dev;
-    struct rtcan_priv *priv;
     struct mscan_regs *regs;
 
     switch (port[idx]) {
@@ -767,7 +759,6 @@
 
     dev->can_sys_clock = mscan_clock;
 
-    priv = dev->priv;
     dev->base_addr = addr;
     regs = (struct mscan_regs *)dev->base_addr;
     
Index: ksrc/drivers/can/mscan/rtcan_mscan_regs.h
===================================================================
--- ksrc/drivers/can/mscan/rtcan_mscan_regs.h	(revision 1770)
+++ ksrc/drivers/can/mscan/rtcan_mscan_regs.h	(working copy)
@@ -182,7 +182,6 @@
 #define MSCAN_BUF_STD_RTR       0x10
 #define MSCAN_BUF_EXT_RTR       0x01
 #define MSCAN_BUF_EXTENDED      0x08
-#define MSCAN_TX_BUFS           3
 
 #define MSCAN_IDAM1	0x20
 /* Value for the interrupt enable register */
Index: ksrc/drivers/can/sja1000/rtcan_sja1000.c
===================================================================
--- ksrc/drivers/can/sja1000/rtcan_sja1000.c	(revision 1770)
+++ ksrc/drivers/can/sja1000/rtcan_sja1000.c	(working copy)
@@ -299,6 +299,9 @@
 	    /* Check error condition and fill error frame */
 	    rtcan_sja_err_interrupt(dev, chip, &skb, irq_source);
 
+            memcpy((void *)&skb.rb_frame + skb.rb_frame_size,
+		   &timestamp, TIMESTAMP_SIZE);
+
 	    if (recv_lock_free) {
 		recv_lock_free = 0;
 		rtdm_lock_get(&rtcan_recv_list_lock);

             reply	other threads:[~2006-10-30 12:04 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-10-30 12:04 Wolfgang Grandegger [this message]
2006-10-30 14:20 ` [Xenomai-core] [PATCH] RT-Socket-CAN fixes Philippe Gerum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4545EA5C.7020105@domain.hid \
    --to=wg@domain.hid \
    --cc=xenomai@xenomai.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.