Xenomai и real-time Linux

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 09 май 2018, 11:29

Olej писал(а): 5. но если вам нужна обработка своих IRQ, драйвер собственных устройств (или не из числа немногих, реализуемых Xenomai) - то вам нужно писать собственные драйверы (kernel space), реализующие модель RTDM (RealTime Drivers Model);
Идея состоит в том, чтобы драйверы RTDM размещались в ядре Xenomai а не Linux, и перехватывали IRQ раньше, чем они поступят в Linux, и реагировать на них с realtime детерминированностью времени реакции. (Ядра операционных систем Xenomai & Linux они называют доменами в терминологии Adeos (Adaptive Domain Environment for Operating Systems), соответственно, первичный - Xenomai, и вторичный - Linux).
Иногда в их документации, относительно прикладных задач, используется терминология моды, в котрой выполняется задача: первичная realtime Xenomai + вторичная Linux, без realtime. Важно то, что один и тот же программный код (начинающийся с привычной функции main()) может, в разное время своего выполнения, переходить из первичной моды во вторичную, и наоборот.

При этом драйвера RTDM создают именованные интерфейсы устройств (в /dev/rtdm), точно так же, как это делают драйверы символьных устройств Linux.
Но! Обычные приложения Linux не могут оперировать с такими устройствами RTDM, только realtime задачи Xenomai!

P.S. Вообще то, всё это 2-ядерное взаимодействие достаточно непривычное, и необходимо внимательно следить что здесь и как происходит.
За realtime приходится дорого платить :-D .
Но это, судя по публикуемым результатам тестирования - hard realtime. Соизмеримый с тем, который обещают и обеспечивают специализированные ОС реального времени: QNX, pSOS, vxWorks.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 09 май 2018, 11:42

Olej писал(а):
Olej писал(а): 5. но если вам нужна обработка своих IRQ, драйвер собственных устройств (или не из числа немногих, реализуемых Xenomai) - то вам нужно писать собственные драйверы (kernel space), реализующие модель RTDM (RealTime Drivers Model);
Идея состоит в том, чтобы драйверы RTDM размещались в ядре Xenomai а не Linux, и перехватывали IRQ раньше, чем они поступят в Linux, и реагировать на них с realtime детерминированностью времени реакции.
Пример кода драйвера RTDM (абсолютно не смотрим что и как это написано - это совершенно черновой набросок!, и не заморачиваемся с тем, что делает этот драйвер ... но он работающий! - это тестирование управление пином нестандартного чипа GPIO, выдача уровня 0/1 на выход GPIO).

Код: Выделить всё

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/version.h>

#include <asm/uaccess.h>

#include <rtdm/driver.h>
#include <rtdm/gpio.h>
#define GPIO_OUT 330
#define RTDM_SUBCLASS_udoo 6789
static LIST_HEAD(rtdm_gpio_chips);
#define SIZEMAX         1024
struct rtdm_gpio_chan {
   int requested : 1,
   has_direction : 1,
   is_output : 1,
   is_interrupt : 1;
};

typedef struct buffer_t {
   int size;
   char data[SIZEMAX];
} buffer_s;


buffer_s buffer;

struct dev_context {	
   int gpio_irq;
   rtdm_irq_t irq_handle;
   rtdm_event_t gpio_event;
   char name[ 10 ];
};

int udoo_open(struct rtdm_fd *fd, int oflags) {
   int err=0;
   rtdm_printk( "try gpio_pin_open\n" );
   if( ( err = gpio_request( GPIO_OUT, THIS_MODULE->name ) ) != 0 ) {
      return err;
   }
   if( ( err = gpio_direction_output( GPIO_OUT, 1 ) ) != 0 ) {
      gpio_free(GPIO_OUT);
      return err;
   }
   rtdm_printk( "gpio_pin_open %d succsesfully\n", GPIO_OUT );
   return err;
}

void udoo_close( struct rtdm_fd *fd ) {
   gpio_free( GPIO_OUT );
   rtdm_printk( "gpio_pin_close\n" );
}

ssize_t udoo_read_rt( struct rtdm_fd *fd, void *buf, size_t nbyte ) {
   ssize_t ret = 0;
   rtdm_printk( "gpio_pin_read\n" );
   return ret;
}

ssize_t udoo_write_rt( struct rtdm_fd *fd, const void *buf, size_t nbyte ) {
   ssize_t ret=0;
   /* write the user buffer in the kernel buffer */
   buffer.size = ( nbyte > SIZE_MAX ) ? SIZE_MAX : nbyte;
   ret = rtdm_safe_copy_from_user( fd, buffer.data, buf, buffer.size );
   gpio_set_value( GPIO_OUT, buffer.data[ 0 ] );
   /* if an error has occured, send it to user */
   if( ret ) return ret;
   return nbyte;
}

static struct rtdm_driver udoo_driver = {
        .profile_info           =       RTDM_PROFILE_INFO( udoo,
                                                           RTDM_CLASS_EXPERIMENTAL,
                                                           RTDM_SUBCLASS_udoo,
                                                           42 ),
        .device_flags           =       RTDM_NAMED_DEVICE|RTDM_EXCLUSIVE,
        .device_count           =       2,
        .context_size           =       sizeof(struct dev_context),
        .ops = {
                .open           =       udoo_open,
                .read_rt       =        udoo_read_rt,
                .write_rt      =       	udoo_write_rt,
                .close          =       udoo_close,
        },
};

static struct rtdm_device udoo_devices[2] = {
        [ 0 ... 1 ] = {
                .driver = &udoo_driver,
                .label = "udooGpio-%d",
        },
};

static int __init init_gpio( void ) {
   int err;
   rtdm_printk( "init UDOO GPIO\n" );
   if( ( err = rtdm_dev_register( &udoo_devices[ 0 ] ) ) == 0 ) {
      rtdm_printk( "gpio rtdm module registered succesfully\n" );
   }
   else {
      switch( err ) {
	 case -EINVAL:
	    rtdm_printk( "err EINVAL = %d\n", err );
            break;
	 case -EEXIST:
	    rtdm_printk( "err EEXIST = %d\n", err );
            break;
   	 case -ENOMEM:
	    rtdm_printk( "err ENOMEM = %d\n", err );
            break;
	 case -EAGAIN:
	    rtdm_printk( "err EAGAIN = %d\n", err );  
	    break; 
	 case -ENOSYS:
	    rtdm_printk( "err ENOSYS = %d\n", err ); 
	    break; 
	 case -ENXIO:
	    rtdm_printk( "err ENXIO = %d\n", err );
	    break;
	 default:
	    rtdm_printk( "error = %d\n", err );
            break; 
      } 		
      return err;
   }
   return err;
}

static void __exit exit_gpio( void ) {
   gpio_free( GPIO_OUT );
   rtdm_dev_unregister( &udoo_devices[ 0 ] );
   rtdm_printk( "UDOO: BYE\n" );
}

module_init( init_gpio );
module_exit( exit_gpio );

MODULE_DESCRIPTION( "simple driver" );
MODULE_AUTHOR( "Taras Shevchenko" );
MODULE_VERSION( "0.0.1" );
MODULE_LICENSE( "GPL" );
Тот, кто минимально знакомился с написанием модулей ядра (драйверов) Linux, увидит прямую аналогию, только аналогичные функции в RTDM (первичном домене, Xenomai) вызываются с префиксом rtdm_*().
Makefile - обычный:

Код: Выделить всё

all: mod

obj-m := udoo_gpio.o
OS := $(shell uname -r)
EXTRA_CFLAGS += -I/usr/xenomai/include

mod:
        make -C /lib/modules/$(OS)/build M=$(PWD) modules

clean:
        $(RM) *.o *.ko *.mod.c Module*.symvers Module.markers modules.order
        $(RM) -R .tmp*

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 09 май 2018, 12:16

Olej писал(а): Makefile - обычный:
Сборка:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ make
make -C /lib/modules/4.9.90-xenomai-3.0.5/build M=/home/olej/2018_WORKS/Triol/Xen_works/udoo modules
make[1]: вход в каталог «/home/olej/2018_WORKS/Triol/linux-4.9.90»
  CC [M]  /home/olej/2018_WORKS/Triol/Xen_works/udoo/udoo_gpio.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/olej/2018_WORKS/Triol/Xen_works/udoo/udoo_gpio.mod.o
  LD [M]  /home/olej/2018_WORKS/Triol/Xen_works/udoo/udoo_gpio.ko
make[1]: выход из каталога «/home/olej/2018_WORKS/Triol/linux-4.9.90»

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ ls -l *.ko
-rw-rw-r-- 1 olej olej 262128 Май  9 01:05 udoo_gpio.ko

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ modinfo udoo_gpio.ko
filename:       /home/olej/2018_WORKS/Triol/Xen_works/udoo/udoo_gpio.ko
license:        GPL
version:        0.0.1
author:         Taras Shevchenko
description:    simple driver
srcversion:     44C433EB2571BC046D3458B
depends:
retpoline:      Y
vermagic:       4.9.90-xenomai-3.0.5 SMP mod_unload
Загрузка:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ sudo insmod udoo_gpio.ko
[sudo] пароль для olej:

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ lsmod | head -n4
Module                  Size  Used by
udoo_gpio               4488  0
vboxsf                 34702  0
joydev                 10176  0

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ ls -l /dev/rtdm/
итого 0
crw-rw---- 1 root xenomai 245, 0 Май  8 19:02 autotune
crw-rw---- 1 root xenomai 248, 0 Май  8 19:02 memdev-private
crw-rw---- 1 root xenomai 248, 1 Май  8 19:02 memdev-shared
crw-rw---- 1 root xenomai 247, 0 Май  8 19:02 memdev-sys
crw-rw---- 1 root xenomai 243, 0 Май  8 19:02 switchtest
crw-rw---- 1 root xenomai 244, 0 Май  8 19:02 timerbench
crw-rw---- 1 root xenomai 240, 0 Май  9 01:06 udooGpio-0

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ ls -l /dev/rtdm/
итого 0
crw-rw---- 1 root xenomai 245, 0 Май  4 13:32 autotune
crw-rw---- 1 root xenomai 248, 0 Май  4 13:32 memdev-private
crw-rw---- 1 root xenomai 248, 1 Май  4 13:32 memdev-shared
crw-rw---- 1 root xenomai 247, 0 Май  4 13:32 memdev-sys
crw-rw---- 1 root xenomai 243, 0 Май  4 13:32 switchtest
crw-rw---- 1 root xenomai 244, 0 Май  4 13:32 timerbench
crw-rw---- 1 root xenomai 240, 0 Май  4 18:15 udooGpio-0

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ ls -l /dev/rtdm/udooGpio-0
crw-rw---- 1 root xenomai 240, 0 Май  9 01:06 /dev/rtdm/udooGpio-0

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ dmesg | tail -n5
               00:00:00.003010 main     Package type: LINUX_64BITS_GENERIC
[   59.321126] 00:00:00.008851 main     5.2.8 r121009 started. Verbose level = 0
[17061.101341] udoo_gpio: module verification failed: signature and/or required key missing - tainting kernel
[17061.102145] init UDOO GPIO
[17061.105379] gpio rtdm module registered succesfully
Что оно делает - это уже не важно...
Но выглядит это так:

Код: Выделить всё

Cobalt udoo # export LD_LIBRARY_PATH=/usr/xenomai/lib; ./posix_timer_x3
Simple periodic thread using Posix.
ERROR : can't open device

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/udoo $ dmesg | tail -n3
[17979.514180] try gpio_pin_open
[18035.600402] try gpio_pin_open
[18120.719351] try gpio_pin_open
То, что оно не может open() устройство /dev/rtdm/udooGpio-0 - совершенно естественно: у меня на инструментальной машине нет GPIO, это готовилось и отлаживалось для нового одноплатного Intel изделия UDOO X86.
Но и здесь всё прекрасно видно что и как - оно работает!

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 09 май 2018, 14:27

Olej писал(а):
Olej писал(а):
Olej писал(а): 5. но если вам нужна обработка своих IRQ, драйвер собственных устройств (или не из числа немногих, реализуемых Xenomai) - то вам нужно писать собственные драйверы (kernel space), реализующие модель RTDM (RealTime Drivers Model);
Идея состоит в том, чтобы драйверы RTDM размещались в ядре Xenomai а не Linux, и перехватывали IRQ раньше, чем они поступят в Linux, и реагировать на них с realtime детерминированностью времени реакции.
Пример кода драйвера RTDM
Интересно здесь (и другие подобные вызовы):

Код: Выделить всё

   gpio_set_value( GPIO_OUT, buffer.data[ 0 ] );
Это из ядра (домена) Xenomai идёт прямой (по абсолютному адресу!) вызов API ядра (домена) Linux ... поскольку они а). исполняются в одном (0-м) кольце защиты (привилегий) процессора x86 + б). находятся в одном адресном пространстве.
Но при этом на время выполнения такого вызова вызывающая задача переходит во вторичную моду (Linux) и теряет свойства realtime, т.е. может быть прервана и приостановлена.

Вот как можем посмотреть набор таких имён функций, относящихся к GPIO, в ядре:

Код: Выделить всё

[olej@dell Cobalt]$ sudo cat /proc/kallsyms | grep gpio | grep " T "
[sudo] пароль для olej: 
ffffffffae45e300 T pinctrl_find_gpio_range_from_pin_nolock
ffffffffae45e390 T pinctrl_find_gpio_range_from_pin
ffffffffae45e4b0 T pinctrl_add_gpio_range
ffffffffae45e520 T pinctrl_add_gpio_ranges
ffffffffae45e570 T pinctrl_remove_gpio_range
ffffffffae45e600 T pinctrl_request_gpio
ffffffffae45e780 T pinctrl_free_gpio
ffffffffae45e8b0 T pinctrl_gpio_direction_input
ffffffffae45e8d0 T pinctrl_gpio_direction_output
ffffffffae45e8f0 T pinctrl_gpio_set_config
ffffffffae45fcf0 T pinctrl_find_and_add_gpio_range
ffffffffae4618a0 T pinmux_request_gpio
ffffffffae461920 T pinmux_free_gpio
ffffffffae461940 T pinmux_gpio_direction
ffffffffae466c20 T devm_gpiod_get_index
ffffffffae466cc0 T devm_gpiod_get
ffffffffae466ce0 T devm_gpiod_get_index_optional
ffffffffae466d10 T devm_gpiod_get_optional
ffffffffae466d40 T devm_fwnode_get_index_gpiod_from_child
ffffffffae466e80 T devm_gpiod_get_array
ffffffffae466f10 T devm_gpiod_get_array_optional
ffffffffae466f60 T devm_gpio_request
ffffffffae467010 T devm_gpio_request_one
ffffffffae4670b0 T devm_gpiod_put
ffffffffae4670f0 T devm_gpiod_put_array
ffffffffae467130 T devm_gpio_free
ffffffffae467170 T desc_to_gpio
ffffffffae4671a0 T gpiod_to_chip
ffffffffae4671d0 T gpiod_get_direction
ffffffffae467290 T gpiochip_get_data
ffffffffae4672b0 T gpiochip_find
ffffffffae467430 T gpiochip_is_requested
ffffffffae467580 T gpiod_to_irq
ffffffffae467780 T gpiochip_request_own_desc
ffffffffae4677f0 T gpiochip_lock_as_irq
ffffffffae4678a0 T gpiod_direction_input
ffffffffae467b50 T gpiod_set_debounce
ffffffffae467c70 T gpiod_get_raw_value
ffffffffae467d30 T gpiod_get_value
ffffffffae467e00 T gpiod_set_value
ffffffffae467eb0 T gpiod_get_value_cansleep
ffffffffae467fa0 T gpiochip_unlock_as_irq
ffffffffae468220 T gpiochip_free_own_desc
ffffffffae468520 T gpiochip_irqchip_add_key
ffffffffae468830 T gpiochip_generic_request
ffffffffae468850 T gpiochip_generic_free
ffffffffae468870 T gpiochip_generic_config
ffffffffae468890 T gpiochip_remove_pin_ranges
ffffffffae468920 T gpiod_add_lookup_table
ffffffffae468990 T gpiod_remove_lookup_table
ffffffffae468a80 T gpiod_count
ffffffffae468df0 T gpiochip_line_is_irq
ffffffffae468e30 T gpiochip_line_is_open_drain
ffffffffae468e70 T gpiochip_line_is_open_source
ffffffffae468eb0 T gpiochip_line_is_persistent
ffffffffae468f20 T gpio_to_desc
ffffffffae468fe0 T gpiod_direction_output_raw
ffffffffae469070 T gpiod_direction_output
ffffffffae469120 T gpiod_is_active_low
ffffffffae4691b0 T gpiod_set_raw_value
ffffffffae469240 T gpiod_cansleep
ffffffffae4692d0 T gpiod_get_raw_value_cansleep
ffffffffae469380 T gpiod_set_raw_value_cansleep
ffffffffae469410 T gpiod_set_value_cansleep
ffffffffae469630 T gpiochip_remove
ffffffffae469830 T devm_gpiochip_remove
ffffffffae4698c0 T gpiochip_set_chained_irqchip
ffffffffae4699d0 T gpiochip_set_nested_irqchip
ffffffffae469a40 T gpiochip_add_pingroup_range
ffffffffae469b90 T gpiochip_add_pin_range
ffffffffae469d00 T gpiochip_add_data
ffffffffae46a5b0 T devm_gpiochip_add_data
ffffffffae46a650 T gpiochip_get_desc
ffffffffae46a680 T gpiod_request
ffffffffae46a7e0 T gpiod_free
ffffffffae46b260 T gpiod_put
ffffffffae46b270 T gpiod_put_array
ffffffffae46b2b0 T gpiod_set_array_value_complex
ffffffffae46b6f0 T gpiod_set_raw_array_value
ffffffffae46b720 T gpiod_set_array_value
ffffffffae46b750 T gpiod_set_raw_array_value_cansleep
ffffffffae46b780 T gpiod_set_array_value_cansleep
ffffffffae46b7b0 T gpiod_configure_flags
ffffffffae46b830 T gpiod_get_index
ffffffffae46bac0 T gpiod_get
ffffffffae46bae0 T gpiod_get_index_optional
ffffffffae46bb10 T gpiod_get_optional
ffffffffae46bb40 T gpiod_get_array
ffffffffae46bc00 T gpiod_get_array_optional
ffffffffae46bc30 T fwnode_get_named_gpiod
ffffffffae46bd40 T gpiod_hog
ffffffffae46beb0 T gpio_free
ffffffffae46bed0 T gpio_free_array
ffffffffae46bf10 T gpio_request
ffffffffae46bf50 T gpio_request_one
ffffffffae46c010 T gpio_request_array
ffffffffae46c0b0 T devprop_gpiochip_set_names
ffffffffae46c260 T acpi_gpio_get_irq_resource
ffffffffae46c290 T acpi_dev_add_driver_gpios
ffffffffae46c320 T acpi_gpiochip_request_interrupts
ffffffffae46c460 T acpi_gpiochip_free_interrupts
ffffffffae46c5d0 T devm_acpi_dev_add_driver_gpios
ffffffffae46c7c0 T devm_acpi_dev_remove_driver_gpios
ffffffffae46ca10 T acpi_dev_gpio_irq_get
ffffffffae46d350 T acpi_gpio_update_gpiod_flags
ffffffffae46d370 T acpi_find_gpio
ffffffffae46d580 T acpi_node_get_gpiod
ffffffffae46d670 T acpi_gpiochip_add
ffffffffae46d990 T acpi_gpiochip_remove
ffffffffae46db40 T acpi_gpio_count
ffffffffae50f030 T clk_hw_register_gpio_gate
ffffffffae50f080 T clk_hw_register_gpio_mux
ffffffffae50f0c0 T clk_register_gpio_mux
ffffffffae50f0f0 T clk_register_gpio_gate
ffffffffae561e30 T agpioc_acquire_wrap
ffffffffae561f20 T agpioc_release_wrap
ffffffffae561f40 T agpioc_setup_wrap
ffffffffae561fa0 T agpioc_protect_wrap
ffffffffae561fb0 T agpioc_deallocate_wrap
ffffffffae6ae4d0 T i2c_generic_gpio_recovery
ffffffffc047a090 T mmc_gpiod_request_cd [mmc_core]
ffffffffc047a110 T mmc_gpiod_request_ro [mmc_core]
ffffffffc0479e30 T mmc_gpio_get_cd      [mmc_core]
ffffffffc0479dd0 T mmc_gpio_get_ro      [mmc_core]
ffffffffc0479db0 T mmc_can_gpio_cd      [mmc_core]
ffffffffc0479ff0 T mmc_gpio_set_cd_isr  [mmc_core]
ffffffffc0479e90 T mmc_gpio_request_ro  [mmc_core]
ffffffffc047a020 T mmc_gpio_request_cd  [mmc_core]
ffffffffc0479f10 T mmc_gpiod_request_cd_irq     [mmc_core]

[olej@dell Cobalt]$ cat /proc/kallsyms | grep gpio | grep " T " | wc -l
129

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 09 май 2018, 14:34

Olej писал(а): Тот, кто минимально знакомился с написанием модулей ядра (драйверов) Linux, увидит прямую аналогию, только аналогичные функции в RTDM (первичном домене, Xenomai) вызываются с префиксом rtdm_*().
Вот такой примерно перечень таких операций для драйверов RTDM:

Код: Выделить всё

olej@Cobalt ~ $ sudo cat /proc/kallsyms | grep ' rtdm_' | grep " T "
ffffffffb15a8d60 T rtdm_drv_set_sysclass
ffffffffb15a8fc0 T rtdm_dev_register
ffffffffb15a95b0 T rtdm_dev_unregister
ffffffffb15a98c0 T rtdm_cleanup
ffffffffb15a9930 T rtdm_get_iov_flatlen
ffffffffb15a99c0 T rtdm_task_join
ffffffffb15a9a30 T rtdm_task_busy_sleep
ffffffffb15a9a70 T rtdm_toseq_init
ffffffffb15a9aa0 T rtdm_nrtsig_pend
ffffffffb15a9bc0 T rtdm_mmap_to_user
ffffffffb15a9c40 T rtdm_iomap_to_user
ffffffffb15a9d50 T rtdm_mmap_iomem
ffffffffb15a9ec0 T rtdm_mmap_vmem
ffffffffb15a9ed0 T rtdm_munmap
ffffffffb15a9ee0 T rtdm_get_iovec
ffffffffb15a9fc0 T rtdm_put_iovec
ffffffffb15aa180 T rtdm_task_init
ffffffffb15aa260 T rtdm_irq_request
ffffffffb15aa2d0 T rtdm_schedule_nrt_work
ffffffffb15aa370 T rtdm_event_timedwait
ffffffffb15aa580 T rtdm_event_wait
ffffffffb15aa5a0 T rtdm_mmap_kmem
ffffffffb15aa5b0 T rtdm_ratelimit
ffffffffb15aa6f0 T rtdm_timer_destroy
ffffffffb15aa7b0 T rtdm_mutex_init
ffffffffb15aa890 T rtdm_mutex_unlock
ffffffffb15aa950 T rtdm_timer_start
ffffffffb15aaa40 T rtdm_timer_stop
ffffffffb15aab10 T rtdm_sem_init
ffffffffb15aac70 T rtdm_event_clear
ffffffffb15aaf00 T rtdm_event_pulse
ffffffffb15aaf80 T rtdm_mutex_destroy
ffffffffb15aaff0 T rtdm_event_destroy
ffffffffb15ab070 T rtdm_sem_destroy
ffffffffb15ab0f0 T rtdm_event_init
ffffffffb15ab270 T rtdm_event_select
ffffffffb15ab3e0 T rtdm_event_signal
ffffffffb15ab580 T rtdm_sem_up
ffffffffb15ab720 T rtdm_sem_select
ffffffffb15ab8c0 T rtdm_mutex_timedlock
ffffffffb15abab0 T rtdm_mutex_lock
ffffffffb15abad0 T rtdm_sem_timeddown
ffffffffb15abcf0 T rtdm_sem_down
ffffffffb15abf00 T rtdm_fd_lock
ffffffffb15ac020 T rtdm_fd_get
ffffffffb15ac5e0 T rtdm_fd_unlock
ffffffffb15ac670 T rtdm_fd_put
ffffffffb15ac680 T rtdm_fd_fcntl
ffffffffb15ac7b0 T rtdm_fd_read
ffffffffb15ac9e0 T rtdm_fd_write
ffffffffb15acc10 T rtdm_fd_recvmsg
ffffffffb15ace60 T rtdm_fd_sendmsg
ffffffffb15ad0b0 T rtdm_fd_close
ffffffffb15ad3e0 T rtdm_fd_ioctl
ffffffffb15ad690 T rtdm_fd_enter
ffffffffb15ad930 T rtdm_fd_register
ffffffffb15ada90 T rtdm_fd_mmap
ffffffffb15adcc0 T rtdm_fd_valid_p
ffffffffb15adde0 T rtdm_fd_select
ffffffffb15adf00 T rtdm_fd_cleanup
ffffffffb15adf30 T rtdm_fd_init
ffffffffb24428a7 T rtdm_init
Если это посмотреть в непатченом ядре без Xenomai, то таких точек входа не будет.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 09 май 2018, 14:50

Olej писал(а): 4. точно так так же, для реализации realtime для Ethernet, TCP/IP, поскольку они сидят на IRQ от Ethernet адаптера, нужно использовать RTDM драйверы сетевых карт (которых совсем немного, около 10 моделей, в составе Xenomai);
5. и для обеспечения realtime для UDP/TCP они используют ещё один open-проект - RTnet, заменяющий способ доступа Ethernet к физ. среде на TDMA (каждый хост использует свой временной слот и не конкурирует за канал);
Для RTnet мы определяем RTDM драйвера используемых адаптеров Ethernet при конфигурировании ядра после наложения патчей - это новость в Xenomai версий 3.0.Х.

Дальше готовим конфигурационный файл /usr/xenomai/etc/rtnet.conf ... для вот такой вот исходно сетевой конфигурации Linux:

Код: Выделить всё

olej@Cobalt ~ $ ifconfig
enp0s3    Link encap:Ethernet  HWaddr 08:00:27:87:49:7f
          inet addr:192.168.1.106  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe87:497f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:143 errors:0 dropped:0 overruns:0 frame:0
          TX packets:125 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:19123 (19.1 KB)  TX bytes:17614 (17.6 KB)
          Interrupt:19 Base address:0xd020

enp0s8    Link encap:Ethernet  HWaddr 08:00:27:15:86:46
          inet addr:192.168.1.102  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::10b3:26fa:3697:d71e/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1238 errors:0 dropped:0 overruns:0 frame:0
          TX packets:636 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1230448 (1.2 MB)  TX bytes:56247 (56.2 KB)

lo        Link encap:Локальная петля (Loopback)
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:267 errors:0 dropped:0 overruns:0 frame:0
          TX packets:267 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:23599 (23.5 KB)  TX bytes:23599 (23.5 KB)
Собственно, в /usr/xenomai/etc/rtnet.conf меняем следующие поля (здесь самое неприятное - разобраться в синтаксисе):

Код: Выделить всё

...
RT_DRIVER="rt_e1000"                   # имя файла драйвера реалтайм
RT_DRIVER_OPTION="cards=0,1"  # используется если несколько сетвых карт

# PCI addresses of RT-NICs to claim (format: 0000:00:00.0)
#   If both Linux and RTnet drivers for the same hardware are loaded, this
#   list instructs the start script to rebind the given PCI devices, detaching
#   from their Linux driver, attaching it to the RT driver above. Example:
REBIND_RT_NICS=0000:00:08.0   # ввести команду lshw -C network  и посмотреть значение поля   bus info: pci@…

# IP address and netmask of this station
#   The TDMA_CONFIG file overrides these parameters for masters and backup
#   masters. Leave blank if you do not use IP addresses or if this station is
#   intended to retrieve its IP from the master based on its MAC address.
IPADDR="172.16.1.1"            #  присваиваемый сетевой адрес
NETMASK="255.255.240.0"  #  маска

# Start realtime loopback device ("yes" or "no")
RT_LOOPBACK="yes"    #  петлевой интерфейс или /loopback

# Use the following RTnet protocol drivers
RT_PROTOCOLS="udp packet"   #  используемые протоколы

# Start capturing interface ("yes" or "no")
RTCAP="yes"    #  для использования  wireshark нужно поставить YES

...
# TDMA mode of the station ("master" or "slave")
#   Start backup masters in slave mode, it will then be switched to master
#   mode automatically during startup.
TDMA_MODE="master"

# Master parameters
# Simple setup: List of TDMA slaves
TDMA_SLAVES="172.16.1.2 172.16.1.3"     
...
Дальше в каталоге /usr/xenomai/sbin :

Код: Выделить всё

Cobalt sbin # ./rtnet -v start
Turning on verbose mode
/usr/xenomai/sbin/rtifconfig rtlo up 127.0.0.1
/usr/xenomai/sbin/rtcfg rteth0 server
/usr/xenomai/sbin/rtifconfig rteth0 up 172.16.1.1 netmask 255.255.240.0
/usr/xenomai/sbin/tdmacfg rteth0 master 500
/usr/xenomai/sbin/tdmacfg rteth0 slot 0 0
/usr/xenomai/sbin/rtcfg rteth0 add 172.16.1.2 -stage1 -
/usr/xenomai/sbin/rtcfg rteth0 add 172.16.1.3 -stage1 -
Waiting for all slaves.../usr/xenomai/sbin/rtcfg rteth0 wait


olej@Cobalt /usr/xenomai/sbin $ sudo ./rtifconfig
[sudo] пароль для olej:
rteth0    Medium: Ethernet  Hardware address: 08:00:27:15:86:46
          IP address: 172.16.1.1  Broadcast address: 172.16.15.255
          UP BROADCAST RUNNING  MTU: 1500

rtlo      Medium: Local Loopback
          IP address: 127.0.0.1
          UP LOOPBACK RUNNING  MTU: 1500

olej@Cobalt /usr/xenomai/sbin $ sudo ./rtroute
Host Routing Table
Hash    Destination     HW Address              Device
00      0.0.0.0         00:00:00:00:00:00       rtlo
01      172.16.1.1      00:00:00:00:00:00       rtlo
01      127.0.0.1       00:00:00:00:00:00       rtlo
3F      172.16.15.255   FF:FF:FF:FF:FF:FF       rteth0

Код: Выделить всё

olej@Cobalt /usr/xenomai/sbin $ lspci -vvv -s00:08.0
00:08.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
        Subsystem: Intel Corporation PRO/1000 MT Desktop Adapter
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz+ UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 64 (63750ns min)
        Interrupt: pin A routed to IRQ 16
        Region 0: Memory at e1000000 (32-bit, non-prefetchable) [size=128K]
        Region 2: I/O ports at 1000 [size=8]
        Capabilities: <access denied>
        Kernel driver in use: rt_e1000
        Kernel modules: e1000, rt_e1000

olej@Cobalt /usr/xenomai/sbin $ lsmod | grep rt
rtmac                   9655  1 tdma
rtcfg                  37150  0
rtcap                   7413  3
rt_loopback             1467  1
rtpacket                8360  0
rtudp                  12694  0
rtipv4                 24259  2 rtudp,rtcfg
rt_e1000               91602  1
rtnet                  55340  10 rtipv4,rt_loopback,rtmac,rtpacket,rtcap,rtudp,rt_e1000,rtcfg,tdma
parport_pc             28236  0
parport                39055  3 lp,parport_pc,ppdev

Код: Выделить всё

olej@Cobalt /usr/xenomai/sbin $ sudo ./rtping 127.0.0.1
Real-time PING 127.0.0.1 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 time=95.6 us
64 bytes from 127.0.0.1: icmp_seq=2 time=21.7 us
64 bytes from 127.0.0.1: icmp_seq=3 time=20.7 us
64 bytes from 127.0.0.1: icmp_seq=4 time=22.2 us
^C
--- 127.0.0.1 rtping statistics ---
4 packets transmitted, 4 received, 0% packet loss
worst case rtt = 95.6 us

olej@Cobalt /usr/xenomai/sbin $ sudo ./rtping 172.16.1.1
Real-time PING 172.16.1.1 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 time=52.1 us
64 bytes from 127.0.0.1: icmp_seq=2 time=25.7 us
64 bytes from 127.0.0.1: icmp_seq=3 time=22.1 us
64 bytes from 127.0.0.1: icmp_seq=4 time=156.8 us
64 bytes from 127.0.0.1: icmp_seq=5 time=20.0 us
64 bytes from 127.0.0.1: icmp_seq=6 time=200.9 us
^C
--- 172.16.1.1 rtping statistics ---
6 packets transmitted, 6 received, 0% packet loss
worst case rtt = 200.9 us

olej@Cobalt /usr/xenomai/sbin $ sudo ./rtping 192.168.1.20
Real-time PING 192.168.1.20 56(84) bytes of data.
ioctl: No route to host

Код: Выделить всё

olej@Cobalt /usr/xenomai/sbin $ ./rtps
PID    TIME                THREAD                   CMD

0      000:00:20.368,439   44186129120072 ROOT/0 idle -1 0 -
0      000:00:20.377,419   43835667910690 ROOT/1 idle -1 0 -
0      000:00:14.654,201   43498983037921 ROOT/2 idle -1 0 -
0      000:00:18.040,593   43787708108929 ROOT/3 idle -1 0 -
6166   000:00:00.000,000   42348 rtnet-stack rt 98 0 -
6167   000:00:00.000,000   280975 rtnet-rtpc rt 0 0 -
9922   000:00:00.000,731   17578623 rtcfg-rx rt 0 0 -
9954   000:00:04.554,247   80602503563 rtnet-tdma rt 99 0 -
0      000:00:00.000,000   0 IRQ16: rteth0 idle 0 0 -
0      000:00:00.000,000   0 IRQ16: rteth0 idle 0 0 -
0      000:00:00.000,000   0 IRQ16: rteth0 idle 0 0 -
0      000:00:02.249,487   40543837545 IRQ16: rteth0 idle 0 0 -
0      000:00:00.823,140   133673460711 IRQ33026: [timer] idle 0 0 -
0      000:00:00.017,227   32522728519 IRQ33026: [timer] idle 0 0 -
Вот как-то так это выглядит.
Всё это более-менее описано здесь: RTnet Installation.
P.S. там, кстати, есть пример загрузки драйвера RTDM при нескольких сетевых картах:

Код: Выделить всё

# sudo insmod /usr/local/rtnet/modules/rt_e1000.ko cards=1,0

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 09 май 2018, 15:06

Olej писал(а): 4. точно так так же, для реализации realtime для Ethernet, TCP/IP, поскольку они сидят на IRQ от Ethernet адаптера, нужно использовать RTDM драйверы сетевых карт (которых совсем немного, около 10 моделей, в составе Xenomai);
5. и для обеспечения realtime для UDP/TCP они используют ещё один open-проект - RTnet, заменяющий способ доступа Ethernet к физ. среде на TDMA (каждый хост использует свой временной слот и не конкурирует за канал);
RTnet - это внешний, независимый относительно Xenomai проект, включённый в его состав.
Детальное описание RTnet здесь: RTnet – A Flexible Hard Real-Time Networking Framework.

Тестирование (в публикациях + нами проведенное) показывает, что детерминированность (максимальная латентность, задержка пакета) RTnet на порядок меньше! Т.е. при среднем времени доставки пакета примерно равном, отдельные задержки, изредка возникающие в Ethernet/TCP/IP, могут быть в 10-100 раз длиннее, чего просто нет в RTnet.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time Linux

Непрочитанное сообщение Olej » 13 июн 2018, 13:21

Ещё хороший материал в тему: Performance Evaluation of Xenomai 3
*Department of Computer Science and Information Engineering,
National Cheng Kung University, Taiwan
No.1, University Road, Tainan City 701, Taiwan (R.O.C.)
**Department of Electrical and Electronic Engineering,
National Taiwan University
No.1, Sec. 4, Roosevelt Road, Taipei, Taiwan (R.O.C.)
Особенно хорош тем, что это свежий материал - новая линия версий Xenomai 3.0.Х пошла развиваться год-два назад. Значительно отличаются от версий 2.6.Х, а 90% публикаций о Xenomai, за 15 лет этого проекта, относятся именно к версиям 2.6.Х.

Подробно описано
- 1.1 Adeos nanokernel
- 1.2 Xenomai
- 1.3 Cobalt
Cobalt, distinguished in Xenomai 3, is the real-time extension, built into the Linux kernel, dealing with all timecritical activities on top of Adeos I-pipe. The Cobalt core has higher priority over the native kernel activities and has the same behaviour as what Xenomai 2 delivers realtime.
- ... analyze the various benchmarks for ARM Cortex-A series ... - что особенно интересно!
2.0.1 Hardware
BeagleBone Black[10] is selected as our major testing hardware platform powered by TI AM335x [11] SoC, and it is an effective embedded platform, capable of running Linux and Xenomai (both 2 and 3), consisting of a single 1GHz ARM Cortex-A8 processor, a 512 MB memory, 32kB L1 caches and a 256kB L2 cache.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time Linux

Непрочитанное сообщение Olej » 13 июн 2018, 13:44

Готовый образ .img, который описывается здесь: Raspberry Pi image for the Pi zero,1,2,3 with Xenomai 3.0.5 on Raspbian linux 4.1.y Debian 8 jessie - голландский университет использует для курсов по embedded & realtime.
Изображение
Institute for Computing and Information Sciences
Visiting address
Toernooiveld 212
6525 EC Nijmegen

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time Linux

Непрочитанное сообщение Olej » 13 июн 2018, 13:46

Olej писал(а):Готовый образ .img, который описывается здесь: Raspberry Pi image for the Pi zero,1,2,3 with Xenomai 3.0.5 on Raspbian linux 4.1.y Debian 8 jessie - голландский университет использует для курсов по embedded & realtime.
Изображение
Institute for Computing and Information Sciences
Visiting address
Toernooiveld 212
6525 EC Nijmegen
Накатал этот образ на SD-карту и пробовал его поднять на Rapsberry Pi 2.
Не могу загрузить.
Причём на точно том же оборудовании какой-то там Raspbian (не я писал SD) грузится "на ура".
Или темнят голландцы что-то ... или нужно ещё как-то пробовать ... может с SD-карточкой что-то не так?

P.S. Кстати, там же у голландцев есть образы виртуальных машин под VirtualBox и под VMware (ну, это уже для совсем упоротых приверженцев бодаться с Linux из-под Windows ;D).
- Нужно будет поднять их VM под VirtualBox - голландцев "проверить на вшивость".
- Каждый желающий пощупать пальцами что оно такое realtime - может относительно небольшими затратами сил и времени сделать это в VM.

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 5 гостей