Skip to contentSkip to conversation

add tut02-skeleton

PATCH In review trem 3 participants 7 messages May 28, 2007 – May 29, 2007 Kbuild

lore
Share & tools
lore

trem

author
#0 lore raw

PATCH 1/1 add tut02-skeleton

Hi

Here is the second part of the tutorial serie about rtdm. I've just added rt-task and semaphore. It's still a very very simple example.

Now, I don't know how to continue, have you got any idea of "topic/subject" that could help people to understand xenomai ?

regards,
Philippe

tut02-skeleton-app.c +114 -0
Index: tut02-skeleton-app.c
===================================================================
@@ -0,0 +1,114 @@
+/***************************************************************************
+ *   Copyright (C) 2007 by trem (Philippe Reynes)                          *
+ *   [email protected]                                                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+/**
+ * This is an example that shows how RTDM devices can be used
+ * with a user space program in realtime context.
+ *
+ * The device tut02-skeleton-drv01 stores data that you write into.
+ * When you read from this device, previously stored data is returned,
+ * and the internal buffer is erased. But you can only do a read once per
+ * write. If you try to read more than you have written, the read is
+ * blocked unless a write is done.
+ *
+ * This program does the following:
+ * - If you give an argument to the command line, this argument is written
+ *   in the device (with rt_dev_write)
+ * - If you don't give an argument to the command line, the progam read
+ *   in the device (with rt_dev_read).
+ *
+ * To test this application, you just need to:
+ *
+ * $ export LD_LIBRARY_PATH=<path of xenomai>/lib
+ * $ insmod tut02-skeleton-drv.ko
+ * $ ./tut02-skeleton-app "Hello Master"
+ * $ ./tut02-skeleton-app
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>	/* for MCL_CURRENT and MCL_FUTURE */
+#include <string.h>
+#include <rtdm/rtdm.h>
+#include <native/task.h>
+
+#define DEVICE_NAME		"tut02-skeleton-drv01"
+
+RT_TASK rt_task_desc;
+
+int main(int argc, char *argv[])
+{
+	char buf[1024];
+	ssize_t size;
+	int device;
+	int ret;
+
+	/* no memory-swapping for this programm */
+	mlockall(MCL_CURRENT | MCL_FUTURE);
+
+	/* 
+		change the current task to RT-task
+		the task has no name to allow this program to be run several times
+	*/
+	ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0);
+	if (ret)
+	{
+		fprintf(stderr, "ERROR : rt_task_shadow: %s\n", strerror(-ret));
+		fflush(stdout);
+		exit(1);		
+	}
+
+	/* open the device */
+	device = rt_dev_open(DEVICE_NAME, 0);
+	if (device < 0) {
+		printf("ERROR : can't open device %s (%s)\n",
+		       DEVICE_NAME, strerror(-device));
+		fflush(stdout);
+		exit(1);
+	}
+
+	/*
+		if an argument was given on the command line, write it to the device,
+		otherwise, read in the device.		
+	*/
+	if (argc == 2)
+	{
+		sprintf(buf, "%s", argv[1]);
+		size = rt_dev_write (device, (const void *)buf, strlen(buf) + 1);
+		printf("Write from device %s\t: %d bytes\n", DEVICE_NAME, size);
+	}
+	else
+	{
+		size = rt_dev_read (device, (void *)buf, 1024);
+		printf("Read in device %s\t: %s\n", DEVICE_NAME, buf);
+	}
+
+	/* close the device */
+	ret = rt_dev_close(device);
+	if (ret < 0) {
+		printf("ERROR : can't close device %s (%s)\n",
+		       DEVICE_NAME, strerror(-ret));
+		fflush(stdout);
+		exit(1);
+	}
+
+	return 0;
+}

Modification de propri���t���s sur tut02-skeleton-app.c
___________________________________________________________________
Nom : svn:eol-style
+ native

tut02-skeleton-drv.c +245 -0

245 lines not on this page · raw message

Modification de propri���t���s sur tut02-skeleton-drv.c
___________________________________________________________________
Nom : svn:eol-style
+ native

Makefile +3 -3
Index: Makefile
===================================================================
@@ -1,13 +1,13 @@
 ###### CONFIGURATION ######
 
 ### List of applications to be build
-APPLICATIONS = tut01-skeleton-app
+APPLICATIONS = tut01-skeleton-app tut02-skeleton-app
 
 ### Note: to override the search path for the xeno-config script, use "make XENO=..."
 
 
 ### List of modules to be build
-MODULES = heartbeat-x86 tut01-skeleton-drv
+MODULES = heartbeat-x86 tut01-skeleton-drv tut02-skeleton-drv
 
 ### Note: to override the kernel source path, use "make KSRC=..."
 
@@ -86,6 +86,6 @@
 
 clean::
 	$(RM) $(CLEANMOD) *.o *.ko *.mod.c Module*.symvers
-	$(RM) -R .tmp*
+	$(RM) -R *~ .tmp*
 
 endif
#1 lore raw
Quoted 4 lines · trem

Hi

Here is the second part of the tutorial serie about rtdm. I've just added rt-task and semaphore. It's still a very very simple example.

Thanks again for your contribution. I have a few comments below.

Quoted 3 lines

Now, I don't know how to continue, have you got any idea of "topic/subject" that could help people to understand xenomai ?

I think it would be good to dive into IRQ handling as this is part of most drivers. Have a look at irqbench, specifically the UART part of it, and the 16550A serial driver. Maybe you can try to create some topics around a basic null-modem link between a Xenomai box and some other PC. That would give you an IRQ source, a data source (the transmitted characters), and enough food for things like synchronisation (mutexes, spinlocks). Don't reimplement the full 16550A driver, only pick simple aspects.

Quoted 7 lines

regards,
Philippe

------------------------------------------------------------------------

...

Quoted 17 lines

Index: tut02-skeleton-drv.c
===================================================================

tut02-skeleton-drv.c +12 -0
@@ -0,0 +1,245 @@
+/***************************************************************************
+ *   Copyright (C) 2007 by trem (Philippe Reynes)                          *
+ *   [email protected]                                                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *

tut02-skeleton-drv.c line 22

Quoted 10 lines
tut02-skeleton-drv.c +10 -0
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+/**
+ * This kernel driver demonstrates how an RTDM device can be set up.

This sounds familiar, like the first example. Doesn't this emphasis a new, different topic?

Quoted 29 lines
tut02-skeleton-drv.c +29 -0
+ *
+ * It is a simple device, only 4 operation are provided:
+ *  - open:  start device usage
+ *  - close: ends device usage
+ *  - write: store transfered data in an internal buffer (realtime context)
+ *  - read:  return previously stored data and erase buffer (realtime context)
+ *
+ */
+
+#include <linux/module.h>
+#include <rtdm/rtdm_driver.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("trem");
+
+#define SIZE_MAX		1024
+#define DEVICE_NAME		"tut02-skeleton-drv01"
+#define SOME_SUB_CLASS		4711
+
+/**
+ * The structure of the buffer
+ *
+ */
+typedef struct buffer_s {
+	int size;
+	char data[SIZE_MAX];
+} buffer_t;
+
+/**

tut02-skeleton-drv.c line 61

Quoted 10 lines
tut02-skeleton-drv.c +10 -0
+ * The global buffer
+ *
+ */
+buffer_t buffer;
+
+/**
+ * The global semaphore
+ *
+ */
+rtdm_sem_t sem;

Having plain global variables doesn't scale well. That actually makes me think of further topcis for tutorials:
o Handling multiple devices with one driver
o Making use of device context buffers (rtdm_device::context_size)

Quoted 14 lines
tut02-skeleton-drv.c +14 -0
+
+/**
+ * Open the device
+ *
+ * This function is called when the device shall be opened.
+ *
+ */
+static int simple_rtdm_open_nrt(struct rtdm_dev_context *context,
+				rtdm_user_info_t * user_info, int oflags)
+{
+	return 0;
+}
+
+/**

tut02-skeleton-drv.c line 85

Quoted 10 lines
tut02-skeleton-drv.c +10 -0
+ * Open the device
+ *
+ * This function is called when the device shall be opened in realtime-context.
+ *
+ */
+static int simple_rtdm_open_rt(struct rtdm_dev_context *context,
+				rtdm_user_info_t * user_info, int oflags)
+{
+	return 0;
+}

Don't register separate handlers for the same operation if they are identical.

Quoted 14 lines
tut02-skeleton-drv.c +14 -0
+
+/**
+ * Close the device
+ *
+ * This function is called when the device shall be closed.
+ *
+ */
+static int simple_rtdm_close_nrt(struct rtdm_dev_context *context,
+				 rtdm_user_info_t * user_info)
+{
+	return 0;
+}
+
+/**

tut02-skeleton-drv.c line 109

Quoted 10 lines
tut02-skeleton-drv.c +10 -0
+ * Close the device
+ *
+ * This function is called when the device shall be closed in realtime-context.
+ *
+ */
+static int simple_rtdm_close_rt(struct rtdm_dev_context *context,
+				 rtdm_user_info_t * user_info)
+{
+	return 0;
+}

Same here.

tut02-skeleton-drv.c line 122

Quoted 13 lines
tut02-skeleton-drv.c +13 -0
+
+/**
+ * Read from the device
+ *
+ * This function is called when the device is read in non-realtime context.
+ *
+ */
+static ssize_t simple_rtdm_read_nrt(struct rtdm_dev_context *context,
+				    rtdm_user_info_t * user_info, void *buf,
+				    size_t nbyte)
+{
+	rtdm_printk("DEBUG : read is not implemented in non-realtime context\n");
+	return 0;

Don't do this. If there is no nrt handler registered, Xenomai will nicely switch a shadowed caller into RT mode (when required) and call simple_rtdm_read_rt instead. With this handler registered, nothing useful happens. Rather demonstrate context-sensitive handlers by doing different things with them (but that's advanced stuff anyway).

Quoted 11 lines
tut02-skeleton-drv.c +11 -0
+}
+
+/**
+ * Read from the device
+ *
+ * This function is called when the device is read in realtime context.
+ *
+ */
+static ssize_t simple_rtdm_read_rt(struct rtdm_dev_context *context,
+				    rtdm_user_info_t * user_info, void *buf,
+				    size_t nbyte)

tut02-skeleton-drv.c line 143

Quoted 10 lines
tut02-skeleton-drv.c +10 -0
+{
+	int size;
+
+	/* take the semaphore */
+	rtdm_sem_down(&sem);
+
+	/* read the kernel buffer and sent it to user space */
+	size = (buffer.size > nbyte) ? nbyte : buffer.size;
+	if (rtdm_safe_copy_to_user(user_info, buf, buffer.data, size))
+		rtdm_printk("ERROR : can't copy data from driver\n");

Send the error code to the user instead of dumping it to the log. The user will then be able to react on it.

Quoted 10 lines
tut02-skeleton-drv.c +10 -0
+
+	/* clean the kernel buffer */
+	buffer.size = 0;
+
+	return size;
+}
+
+/**
+ * Write in the device
+ *

tut02-skeleton-drv.c line 163

Quoted 10 lines
tut02-skeleton-drv.c +10 -0
+ * This function is called when the device is written in non-realtime context.
+ *
+ */
+static ssize_t simple_rtdm_write_nrt(struct rtdm_dev_context *context,
+				     rtdm_user_info_t * user_info,
+				     const void *buf, size_t nbyte)
+{
+	rtdm_printk("DEBUG : write is not implemented in non-realtime context\n");
+	return 0;
+}

See above.

tut02-skeleton-drv.c line 176

Quoted 13 lines
tut02-skeleton-drv.c +13 -0
+
+/**
+ * Write in the device
+ *
+ * This function is called when the device is written in realtime context.
+ *
+ */
+static ssize_t simple_rtdm_write_rt(struct rtdm_dev_context *context,
+				     rtdm_user_info_t * user_info,
+				     const void *buf, size_t nbyte)
+{
+	/* release the semaphore */
+	rtdm_sem_up(&sem);

Oops, that creates a race: Data will be written to the buffer AFTER you signal some reader that there is data available...

Quoted 96 lines
tut02-skeleton-drv.c +69 -0
+
+	/* write the user buffer in the kernel buffer */
+	buffer.size = (nbyte > SIZE_MAX) ? SIZE_MAX : nbyte;
+	if (rtdm_safe_copy_from_user(user_info, buffer.data, buf, buffer.size))
+		rtdm_printk("ERROR : can't copy data to driver\n");
+
+	return nbyte;
+}
+
+/**
+ * This structure describe the simple RTDM device
+ *
+ */
+static struct rtdm_device device = {
+	.struct_version = RTDM_DEVICE_STRUCT_VER,
+
+	.device_flags = RTDM_NAMED_DEVICE,
+	.context_size = 0,
+	.device_name = DEVICE_NAME,
+
+	.open_nrt = simple_rtdm_open_nrt,
+	.open_rt  = simple_rtdm_open_rt,
+
+	.ops = {
+		.close_nrt = simple_rtdm_close_nrt,
+		.close_rt  = simple_rtdm_close_rt,
+		.read_nrt  = simple_rtdm_read_nrt,
+		.read_rt   = simple_rtdm_read_rt,
+		.write_nrt = simple_rtdm_write_nrt,
+		.write_rt  = simple_rtdm_write_rt,
+	},
+
+	.device_class = RTDM_CLASS_EXPERIMENTAL,
+	.device_sub_class = SOME_SUB_CLASS,
+	.profile_version = 1,
+	.driver_name = "SimpleRTDM",
+	.driver_version = RTDM_DRIVER_VER(0, 1, 2),
+	.peripheral_name = "Simple RTDM example",
+	.provider_name = "trem",
+	.proc_name = device.device_name,
+};
+
+/**
+ * This function is called when the module is loaded
+ *
+ * It simply registers the RTDM device.
+ *
+ */
+int __init simple_rtdm_init(void)
+{
+	buffer.size = 0;		/* clear the buffer */
+	rtdm_sem_init(&sem, 0);	/* init the global semaphore */
+
+	return rtdm_dev_register(&device);
+}
+
+/**
+ * This function is called when the module is unloaded
+ *
+ * It unregister the RTDM device, polling at 1000 ms for pending users.
+ *
+ */
+void __exit simple_rtdm_exit(void)
+{
+	rtdm_dev_unregister(&device, 1000);
+}
+
+module_init(simple_rtdm_init);
+module_exit(simple_rtdm_exit);

Modification de propriétés sur tut02-skeleton-drv.c
___________________________________________________________________
Nom : svn:eol-style
+ native

Index: Makefile
===================================================================

Makefile +2 -2
@@ -1,13 +1,13 @@
 ###### CONFIGURATION ######
 
 ### List of applications to be build
-APPLICATIONS = tut01-skeleton-app
+APPLICATIONS = tut01-skeleton-app tut02-skeleton-app
 
 ### Note: to override the search path for the xeno-config script, use "make XENO=..."
 
 
 ### List of modules to be build
-MODULES = heartbeat-x86 tut01-skeleton-drv
+MODULES = heartbeat-x86 tut01-skeleton-drv tut02-skeleton-drv
 
 ### Note: to override the kernel source path, use "make KSRC=..."
 

Makefile line 89

Quoted 5 lines
Makefile +1 -1
@@ -86,6 +86,6 @@
 
 clean::
 	$(RM) $(CLEANMOD) *.o *.ko *.mod.c Module*.symvers
-	$(RM) -R .tmp*
+	$(RM) -R *~ .tmp*

This last hunk looks unrelated.

Jan

#2 lore raw
In reply to trem

tut02-skeleton-app.c line 65

Quoted 1 line · trem
tut02-skeleton-app.c +1 -0
+	mlockall(MCL_CURRENT | MCL_FUTURE);

Please show people the right way to code, check the return value of mlockall here.

tut02-skeleton-drv.c line 148

Quoted 7 lines
tut02-skeleton-drv.c +7 -0
+	if (rtdm_safe_copy_to_user(user_info, buf, buffer.data, size))
+		rtdm_printk("ERROR : can't copy data from driver\n");
+
+	/* clean the kernel buffer */
+	buffer.size = 0;
+
+	return size;

Same here, if rtdm_safe_copy_to_user returns an error, return that error to user-space.

Signature · 1 line
					    Gilles Chanteperdrix.
author
#3 lore raw

Hi

Thanks for the reply (jan too). I've tried to use all of your feedback, and I send you the new release of this tut02.

regards,
Philippe

Quoted 6 lines · Gilles Chanteperdrix

Review

Quoted 1 line · trem
(quoted diff) +1 -0
+	mlockall(MCL_CURRENT | MCL_FUTURE);

Please show people the right way to code, check the return value of mlockall here.

Quoted 13 lines

Review

Quoted 7 lines
(quoted diff) +7 -0
+	if (rtdm_safe_copy_to_user(user_info, buf, buffer.data, size))
+		rtdm_printk("ERROR : can't copy data from driver\n");
+
+	/* clean the kernel buffer */
+	buffer.size = 0;
+
+	return size;

Same here, if rtdm_safe_copy_to_user returns an error, return that error to user-space.

tut02-skeleton-app.c +119 -0
Index: tut02-skeleton-app.c
===================================================================
@@ -0,0 +1,119 @@
+/***************************************************************************
+ *   Copyright (C) 2007 by trem (Philippe Reynes)                          *
+ *   [email protected]                                                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+/**
+ * This is an example that shows how RTDM devices can be used
+ * with a user space program in realtime context.
+ *
+ * The device tut02-skeleton-drv01 stores data that you write into.
+ * When you read from this device, previously stored data is returned,
+ * and the internal buffer is erased. But you can only do a read once per
+ * write. If you try to read more than you have written, the read is
+ * blocked unless a write is done.
+ *
+ * This program does the following:
+ * - If you give an argument to the command line, this argument is written
+ *   in the device (with rt_dev_write)
+ * - If you don't give an argument to the command line, the progam read
+ *   in the device (with rt_dev_read).
+ *
+ * To test this application, you just need to:
+ *
+ * $ export LD_LIBRARY_PATH=<path of xenomai>/lib
+ * $ insmod tut02-skeleton-drv.ko
+ * $ ./tut02-skeleton-app "Hello Master"
+ * $ ./tut02-skeleton-app
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>	/* for MCL_CURRENT and MCL_FUTURE */
+#include <string.h>		/* for strerror */
+#include <rtdm/rtdm.h>
+#include <native/task.h>
+
+#define DEVICE_NAME		"tut02-skeleton-drv01"
+
+RT_TASK rt_task_desc;
+
+int main(int argc, char *argv[])
+{
+	char buf[1024];
+	ssize_t size;
+	int device;
+	int ret;
+
+	/* no memory-swapping for this programm */
+	ret = mlockall(MCL_CURRENT | MCL_FUTURE);
+	if (ret) {
+		fprintf(stderr, "ERROR : mlockall failled: %s\n", strerror(-ret));
+		fflush(stdout);
+		exit(1);
+	}
+
+	/*
+		change the current task to RT-task
+		the task has no name to allow this program to be run several times
+	*/
+	ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0);
+	if (ret)
+	{
+		fprintf(stderr, "ERROR : rt_task_shadow: %s\n", strerror(-ret));
+		fflush(stdout);
+		exit(1);
+	}
+
+	/* open the device */
+	device = rt_dev_open(DEVICE_NAME, 0);
+	if (device < 0) {
+		printf("ERROR : can't open device %s (%s)\n",
+		       DEVICE_NAME, strerror(-device));
+		fflush(stdout);
+		exit(1);
+	}
+
+	/*
+		if an argument was given on the command line, write it to the device,
+		otherwise, read in the device.
+	*/
+	if (argc == 2)
+	{
+		sprintf(buf, "%s", argv[1]);
+		size = rt_dev_write (device, (const void *)buf, strlen(buf) + 1);
+		printf("Write from device %s\t: %d bytes\n", DEVICE_NAME, size);
+	}
+	else
+	{
+		size = rt_dev_read (device, (void *)buf, 1024);
+		printf("Read in device %s\t: %s\n", DEVICE_NAME, buf);
+	}
+
+	/* close the device */
+	ret = rt_dev_close(device);
+	if (ret < 0) {
+		printf("ERROR : can't close device %s (%s)\n",
+		       DEVICE_NAME, strerror(-ret));
+		fflush(stdout);
+		exit(1);
+	}
+
+	return 0;
+}

Modification de propri���t���s sur tut02-skeleton-app.c
___________________________________________________________________
Nom : svn:eol-style
+ native

tut02-skeleton-drv.c +198 -0

198 lines not on this page · raw message

Modification de propri���t���s sur tut02-skeleton-drv.c
___________________________________________________________________
Nom : svn:eol-style
+ native

Makefile +2 -2
Index: Makefile
===================================================================
@@ -1,13 +1,13 @@
 ###### CONFIGURATION ######
 
 ### List of applications to be build
-APPLICATIONS = tut01-skeleton-app
+APPLICATIONS = tut01-skeleton-app tut02-skeleton-app
 
 ### Note: to override the search path for the xeno-config script, use "make XENO=..."
 
 
 ### List of modules to be build
-MODULES = heartbeat-x86 tut01-skeleton-drv
+MODULES = heartbeat-x86 tut01-skeleton-drv tut02-skeleton-drv
 
 ### Note: to override the kernel source path, use "make KSRC=..."
 
#4 lore raw

tut02-skeleton-app.c line 70

Quoted 13 lines · trem

Hi

Thanks for the reply (jan too). I've tried to use all of your feedback, and I send you the new release of this tut02.

(...)

tut02-skeleton-app.c +7 -0
+	/* no memory-swapping for this programm */
+	ret = mlockall(MCL_CURRENT | MCL_FUTURE);
+	if (ret) {
+		fprintf(stderr, "ERROR : mlockall failled: %s\n", strerror(-ret));
+		fflush(stdout);
+		exit(1);
+	}

Some further comment, mlockall returns its error in errno, so you should replace strerror(-ret) with strerror(errno), or to make it short, use perror.
Also note that since you fflush stdout after having printed the error message, if there are any non printed message in stdout, they will only appear after the error message, which will make it hard for the user to catch the error message. Besides, exit already flushes the file descriptors, so flushing stdout before calling exit is useless. IMHO, you should call fflush(stdout) before printing the error message.

Signature · 1 line
					    Gilles Chanteperdrix.
author
#5 lore raw

Hi

You're right, perror could be used instead of strerror(-ret), it's simpler. And I've remoded all "fflush", as you said, there are useless and it's a tutorial about xenomai. So I think that those "fflush" aren't necessary.

Thanks for feedback,
Philippe

Quoted 16 lines · Gilles Chanteperdrix

Review

Quoted 13 lines · trem

Hi

Thanks for the reply (jan too). I've tried to use all of your feedback, and I send you the new release of this tut02.

(...)

(quoted diff) +7 -0
+	/* no memory-swapping for this programm */
+	ret = mlockall(MCL_CURRENT | MCL_FUTURE);
+	if (ret) {
+		fprintf(stderr, "ERROR : mlockall failled: %s\n", strerror(-ret));
+		fflush(stdout);
+		exit(1);
+	}

Some further comment, mlockall returns its error in errno, so you should

Quoted 9 lines

replace strerror(-ret) with strerror(errno), or to make it short, use perror.
Also note that since you fflush stdout after having printed the error message, if there are any non printed message in stdout, they will only appear after the error message, which will make it hard for the user to catch the error message. Besides, exit already flushes the file descriptors, so flushing stdout before calling exit is useless. IMHO, you should call fflush(stdout) before printing the error message.

tut02-skeleton-app.c +114 -0
Index: tut02-skeleton-app.c
===================================================================
@@ -0,0 +1,114 @@
+/***************************************************************************
+ *   Copyright (C) 2007 by trem (Philippe Reynes)                          *
+ *   [email protected]                                                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+/**
+ * This is an example that shows how RTDM devices can be used
+ * with a user space program in realtime context.
+ *
+ * The device tut02-skeleton-drv01 stores data that you write into.
+ * When you read from this device, previously stored data is returned,
+ * and the internal buffer is erased. But you can only do a read once per
+ * write. If you try to read more than you have written, the read is
+ * blocked unless a write is done.
+ *
+ * This program does the following:
+ * - If you give an argument to the command line, this argument is written
+ *   in the device (with rt_dev_write)
+ * - If you don't give an argument to the command line, the progam read
+ *   in the device (with rt_dev_read).
+ *
+ * To test this application, you just need to:
+ *
+ * $ export LD_LIBRARY_PATH=<path of xenomai>/lib
+ * $ insmod tut02-skeleton-drv.ko
+ * $ ./tut02-skeleton-app "Hello Master"
+ * $ ./tut02-skeleton-app
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>	/* for MCL_CURRENT and MCL_FUTURE */
+#include <rtdm/rtdm.h>
+#include <native/task.h>
+
+#define DEVICE_NAME		"tut02-skeleton-drv01"
+
+RT_TASK rt_task_desc;
+
+int main(int argc, char *argv[])
+{
+	char buf[1024];
+	ssize_t size;
+	int device;
+	int ret;
+
+	/* no memory-swapping for this programm */
+	ret = mlockall(MCL_CURRENT | MCL_FUTURE);
+	if (ret) {
+		perror("ERROR : mlockall has failled");
+		exit(1);
+	}
+
+	/*
+		change the current task to RT-task
+		the task has no name to allow this program to be run several times
+	*/
+	ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0);
+	if (ret)
+	{
+		fprintf(stderr, "ERROR : rt_task_shadow: %s\n", strerror(-ret));
+		exit(1);
+	}
+
+	/* open the device */
+	device = rt_dev_open(DEVICE_NAME, 0);
+	if (device < 0) {
+		printf("ERROR : can't open device %s (%s)\n",
+		       DEVICE_NAME, strerror(-device));
+		exit(1);
+	}
+
+	/*
+		if an argument was given on the command line, write it to the device,
+		otherwise, read in the device.
+	*/
+	if (argc == 2)
+	{
+		sprintf(buf, "%s", argv[1]);
+		size = rt_dev_write (device, (const void *)buf, strlen(buf) + 1);
+		printf("Write from device %s\t: %d bytes\n", DEVICE_NAME, size);
+	}
+	else
+	{
+		size = rt_dev_read (device, (void *)buf, 1024);
+		printf("Read in device %s\t: %s\n", DEVICE_NAME, buf);
+	}
+
+	/* close the device */
+	ret = rt_dev_close(device);
+	if (ret < 0) {
+		printf("ERROR : can't close device %s (%s)\n",
+		       DEVICE_NAME, strerror(-ret));
+		exit(1);
+	}
+
+	return 0;
+}

Modification de propri���t���s sur tut02-skeleton-app.c
___________________________________________________________________
Nom : svn:eol-style
+ native

tut02-skeleton-drv.c +198 -0

198 lines not on this page · raw message

Modification de propri���t���s sur tut02-skeleton-drv.c
___________________________________________________________________
Nom : svn:eol-style
+ native

Makefile +2 -2
Index: Makefile
===================================================================
@@ -1,13 +1,13 @@
 ###### CONFIGURATION ######
 
 ### List of applications to be build
-APPLICATIONS = tut01-skeleton-app
+APPLICATIONS = tut01-skeleton-app tut02-skeleton-app
 
 ### Note: to override the search path for the xeno-config script, use "make XENO=..."
 
 
 ### List of modules to be build
-MODULES = heartbeat-x86 tut01-skeleton-drv
+MODULES = heartbeat-x86 tut01-skeleton-drv tut02-skeleton-drv
 
 ### Note: to override the kernel source path, use "make KSRC=..."
 
#6 lore raw
Quoted 7 lines · trem

Hi

You're right, perror could be used instead of strerror(-ret), it's simpler. And I've remoded all "fflush", as you said, there are useless and it's a tutorial about xenomai. So I think that those "fflush" aren't necessary.

Thanks, merged with minor beautifications.

Please provide your future patches according to [1]. That would make importing them into my quilt stacks easier.

Jan

[1] http://www.xenomai.org/index.php/Xenomai:Contributing_Patches