реклама на сайте
подробности

 
 
> свой драйвер АЦП, два пути
TigerSHARC
сообщение Jun 13 2013, 11:29
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 688
Регистрация: 4-09-09
Пользователь №: 52 195



Надобно написать драйвер(модуль ядра) АЦП.

Прочитав Linux Device Drevers вижу очевидный путь: пишу модуль ядра, который представляет собой standalone программу, принимающую данные от АЦП поп рерыванию от АЦП(сигнал когда данные готовы), и оформленную как собственно модуль/драйвер для Linux (благо доступ к регистрам есть из пространства ядра)

Но! Вижу что устройства "по-хорошему" регистрируются в sysfs, а вот этот путь не совсем понятен.

Вопрос: чем чреват первый путь и и как писать для второго(статейки может какие есть с примерами...)?

Сообщение отредактировал TigerSHARC - Jun 13 2013, 11:30
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Hoodwin
сообщение Jun 13 2013, 21:50
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107



С sysfs пробовал немного, все же это не совсем файловая система, это скорее некая обертка для kernel objects. А с procfs все достаточно просто.
Сначала нужно в своем модуле в методе init зарегистрировать драйвер устройства. Проще всего это сделать для platform_bus, так как для этой шины правило соответствия довольно простое - одинаковые имена у драйвера и устройства. Итого:
Код
static int __init my_driver_init(void)
{
    int rc;

    my_proc_dir = proc_mkdir("my_dir", 0);
    if (!my_proc_dir)
        bail_out...

    rc = platform_driver_register(&my_driver);
    if (rc!=0)
        bail_out...

    // тут же можно зарегистрировать и само устройство, если нет более подходящего места.
    // вообще говоря, LDM подразумевает, что устройство регистрируется на шине неким сканером шины
    // для реализации механизма plug and play, но это необязательно.

    return 0;
}


В данном коде все довольно просто, системе зарегистрировали базовый каталог в proc и драйвер для устройства. Драйвер устройства теперь будет проверяться всякий раз, когда в системе происходят изменения на шине platform_bus. Если драйвер найдет устройство, то будет вызван метод probe драйвера, где он сможет устройство взять под свой контроль. Там же происходит инициализация рабочих структур управления устройством: выделение памяти, ремаппинг адресного пространства ввода-вывода, назначение irq, а также регистрация в procfs файлов для управления устройством из пользовательского приложения. Вот примерно так:

Код
static int my_driver_probe(struct platform_device *pdev)
{
        struct resource  *r_mem, *r_irq;
        my_device_t       *ctx;
        int               rc;

        pdev_info(pdev, "starting device...\n");

        r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!r_mem || !r_irq)
                return -EINVAL;

        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;

        platform_set_drvdata(pdev, ctx);
        ctx->pdev = pdev;

        /* check the resources */
        ctx->irq = r_irq->start;
        ctx->mem_base = r_mem->start;
        ctx->mem_size = r_mem->end - r_mem->start + 1;

        /* registering module base directory */
        snprintf(ctx->name_base, sizeof(ctx->name_base), "%u", pdev->id);
        ctx->proc_base = proc_mkdir(ctx->name_base, my_proc_dir);
        if (!ctx->proc_base) {
                rc = -ENOMEM;
                goto fail_proc_base;
        }

        /* registering interface to work with ADC */
        ctx->proc_adc = create_proc_entry("adc_data", 0644, ctx->proc_base);
        if (!ctx->proc_adc) {
                rc = -ENOMEM;
                goto fail_proc_adc;
        } else {
                /* fill in the table of registers operations */
                extern struct file_operations  mors8_registers_fops;

                ctx->proc_regs->data = ctx;
                ctx->proc_regs->size = 256;  // размер файла АЦП, если имеет смысл
                ctx->proc_regs->proc_fops = &my_adc_fops;
                atomic_set(&ctx->open_adc, 0);
        }

        // аналогично создаем прочие файловые интерфейсы к драйверу
        ...

        /* now register irq handler */
        rc = request_irq(ctx->irq, my_interrupt_handler, IRQF_SHARED, "my_adc", ctx);
        if (rc) {
                pdev_err(pdev, "unable to set up irq %d, error %d\n", ctx->irq, rc );
                goto fail_irq;
        } else {
                /* setup interrupt enable for the device */
        }

        return 0;

fail_irq:
fail_proc_adc:
        remove_proc_entry(ctx->name_base, my_proc_base);
fail_proc_base:
        return rc;
}


static int my_driver_remove(struct platform_device *pdev)
{
        my_device_t *ctx;

        ctx = platform_get_drvdata(pdev);

        pdev_info(pdev, "stopping device...\n");

        /* removing interrupt handler */
        free_irq(ctx->irq, ctx);                    /* free handler */

        /* removing file adc_data */
        if (ctx->proc_adc)
                remove_proc_entry("adc_data", ctx->proc_base);

        return 0;
}


Дальше нужно описать файловый интерфейс управления АЦП. Приведу лишь только процедуру чтения и структуру дескриптора:
Код
static int fops_adc_read(struct file *f, char __user *buf, size_t n, loff_t *pos)
{
        my_device_t *ctx = (my_device_t *) f->private_data;
        loff_t      offs = (*pos) & ~3;
        size_t      total = 0;

        if (offs >= ctx->proc_adc->size)
                return 0;

        if (offs + n >= ctx->proc_adc->size )
                n = ctx->proc_adc->size - offs;

        n &= ~3;

        while(n > 0) {
                u32 data;
                int rc;

                rc = my_read_adc (ctx, &data);
                if (rc)
                        break;

                // copy data to user
                copy_to_user(buf, &data, 4);

                // take next word
                buf   += 4;
                offs  += 4;
                total += 4;
                n -= 4;
        }

        *pos = offs;

        return total;
}


struct file_operations my_adc_fops = {
        .owner =        THIS_MODULE,
        .open =         fops_adc_open,
        .release =      fops_adc_close,
        .read =         fops_adc_read,
        .write =        fops_adc_write,
        .ioctl =        fops_adc_ioctl,
        .llseek =       fops_adc_seek,
};


Собственно и все. После insmod такого драйвера в системе появится "файл" в пути /proc/my_dir/0/adc_data, который можно открыть и читать любыми средствами, доступными в линукс. Например, можно сделать dd if=/proc/my_dir/0/adc_data of=/mnt/nfs/test bs=512 count=1, и тогда можно скинуть в файлик на NFS результаты АЦП, и потом их глазками быстро посмотреть, скажем в mc или через QUI.

Сообщение отредактировал Hoodwin - Jun 14 2013, 06:58
Go to the top of the page
 
+Quote Post
Муравей
сообщение Jul 12 2013, 10:47
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 52
Регистрация: 30-11-11
Пользователь №: 68 593



Цитата(Hoodwin @ Jun 14 2013, 01:50) *
Собственно и все. После insmod такого драйвера в системе появится "файл" в пути /proc/my_dir/0/adc_data, который можно открыть и читать любыми средствами, доступными в линукс. Например, можно сделать dd if=/proc/my_dir/0/adc_data of=/mnt/nfs/test bs=512 count=1, и тогда можно скинуть в файлик на NFS результаты АЦП, и потом их глазками быстро посмотреть, скажем в mc или через QUI.

Тоже задумался над написанием драйвера , который будет принимать поток с 8 каналов АЦП по msasp в режиме tdm на пладе Beaglebone. Вроде бы понятно как создать устройство в /proc, создать файловый интерфейс для записи чтения.
Предполагаю, что из буфера DMA буду пихать данные в большой промежуточный циклический буфер, а при вызове read() брать сколько есть, но не более чем указанное количество значений из буфера.
Остался один не понятный момент, как внутри драйвера организовать функцию, в которой постоянно будет проверяться сколько в буфере DMA есть данных . Как в драйвере можно организовать функцию, в которую гарантированно буду попадать не реже ~10 ms? Какие есть стандартные средства для этого?

И ещё вопрос. Возможен ли такой вариант: в драйвере заряжаю DMA на определённую область памяти и уже из USER_SPACE получаю доступ к ней. А информацию по поводу по какому адресу делать mmap зачитаваю из файла устройства в /proc. Так же из файлов читаю текущее положение кольцевых указателей.

Заранее спасибо за ответы.

Сообщение отредактировал Муравей - Jul 12 2013, 11:27
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- TigerSHARC   свой драйвер АЦП   Jun 13 2013, 11:29
- - DASM   Ну вообще доступ к регистрам можно и из пользовате...   Jun 13 2013, 12:21
|- - TigerSHARC   Цитата(DASM @ Jun 13 2013, 16:21) Ну вооб...   Jun 13 2013, 13:39
- - DASM   Не, так делать не надо. Но можно.. Мне если лень д...   Jun 13 2013, 14:37
|- - DASM   Цитата(Муравей @ Jul 12 2013, 14:47) Тоже...   Aug 6 2013, 02:47
- - Idle   Цитата(TigerSHARC @ Jun 13 2013, 15:29) В...   Jun 18 2013, 03:57
- - Ya_Mike   Как-то пользовался драйвером АЦП для at91-adc, для...   Jun 28 2013, 13:13
|- - denyslb   Цитата(Ya_Mike @ Jun 28 2013, 16:13) Как-...   Jun 29 2013, 01:38
|- - Ya_Mike   Цитата(denyslb @ Jun 29 2013, 05:38) Мне ...   Jul 4 2013, 13:24
|- - sasamy   Цитата(Ya_Mike @ Jul 4 2013, 17:24) Можно...   Jul 4 2013, 14:52
|- - denyslb   Цитата(Ya_Mike @ Jul 4 2013, 16:24) Откры...   Jul 26 2013, 09:22
- - vshemm   В ядре (хоть и в staging) есть специальный фреймво...   Jul 5 2013, 11:44
|- - sasamy   Цитата(vshemm @ Jul 5 2013, 15:44) В ядре...   Jul 5 2013, 19:29
- - Tarbal   в /sys драйвер появится усилиями операционной сист...   Aug 22 2013, 15:14
|- - Dubov   Цитата(Tarbal @ Aug 22 2013, 19:14) в /sy...   Aug 26 2013, 13:38
|- - Tarbal   Цитата(Dubov @ Aug 26 2013, 17:38) интере...   Aug 26 2013, 14:34
- - Dubov   Ну а кроме устарелости моей практики, что можно ск...   Aug 26 2013, 15:16
|- - Tarbal   Цитата(Dubov @ Aug 26 2013, 19:16) Ну а к...   Aug 27 2013, 01:25
- - Hoodwin   В новой модели драйверов тоже есть свои неудобства...   Aug 27 2013, 14:17
|- - Tarbal   Цитата(Hoodwin @ Aug 27 2013, 18:17) В но...   Aug 27 2013, 22:50
||- - Tarbal   Цитата(Tarbal @ Aug 28 2013, 02:50) Это н...   Aug 28 2013, 13:08
||- - A. Fig Lee   Цитата(Tarbal @ Aug 28 2013, 09:08) А как...   Aug 29 2013, 00:26
||- - Tarbal   Цитата(A. Fig Lee @ Aug 29 2013, 04:26) Н...   Aug 29 2013, 19:57
||- - A. Fig Lee   Цитата(Tarbal @ Aug 29 2013, 15:57) What ...   Aug 29 2013, 22:20
||- - Tarbal   Цитата(A. Fig Lee @ Aug 30 2013, 02:20) h...   Aug 30 2013, 11:21
||- - A. Fig Lee   Цитата(Tarbal @ Aug 30 2013, 07:21) Если ...   Aug 30 2013, 16:04
||- - Tarbal   Цитата(A. Fig Lee @ Aug 30 2013, 20:04) ...   Aug 30 2013, 22:08
||- - A. Fig Lee   Цитата(Tarbal @ Aug 30 2013, 18:08) Это н...   Aug 30 2013, 23:57
|- - A. Fig Lee   Цитата(Hoodwin @ Aug 27 2013, 10:17) В но...   Aug 28 2013, 02:28
- - psL   Драйвер АЦП, имхо, по простому - это символьное у...   Aug 30 2013, 15:33
|- - Tarbal   Цитата(psL @ Aug 30 2013, 19:33) Драйвер ...   Aug 30 2013, 16:21
|- - psL   Цитата(Tarbal @ Aug 30 2013, 20:21) V4L э...   Aug 30 2013, 20:09
|- - Tarbal   Цитата(psL @ Aug 31 2013, 00:09) по повод...   Aug 31 2013, 17:11
|- - sasamy   ЦитатаНо если вы настаиваете, то имея ПДП фифо не ...   Aug 31 2013, 17:37
||- - Tarbal   Цитата(sasamy @ Aug 31 2013, 21:37) Скоро...   Aug 31 2013, 17:57
||- - sasamy   Цитата(Tarbal @ Aug 31 2013, 21:57) Был в...   Aug 31 2013, 18:17
||- - Tarbal   Цитата(sasamy @ Aug 31 2013, 22:17) Приме...   Aug 31 2013, 19:51
||- - sasamy   Цитата(Tarbal @ Aug 31 2013, 23:51) я не ...   Sep 2 2013, 14:07
||- - Tarbal   Цитата(sasamy @ Aug 31 2013, 18:07) Кольц...   Sep 3 2013, 13:29
||- - sasamy   Цитата(Tarbal @ Sep 3 2013, 17:29) Я пола...   Sep 3 2013, 16:14
||- - Tarbal   ЦитатаУ процессора может и не быть ПДП к АЦП. Тогд...   Sep 3 2013, 16:24
||- - sasamy   Цитата(Tarbal @ Sep 3 2013, 20:24) самое ...   Sep 3 2013, 17:46
|- - psL   Цитата(Tarbal @ Aug 31 2013, 21:11) имея ...   Sep 2 2013, 16:48
- - Tarbal   Интересно стало: есть ли здесь кто-нибудь кто писа...   Sep 4 2013, 17:26
|- - sasamy   Цитата(Tarbal @ Sep 4 2013, 21:26) Интере...   Sep 5 2013, 06:58
- - vshemm   Есть, писали Comedi самый старый фреймворк, для ...   Sep 5 2013, 07:30
|- - sasamy   Цитата(vshemm @ Sep 5 2013, 11:30) Comedi...   Sep 5 2013, 11:11
- - Tarbal   Теперь такая проблема. У меня ЦПУ Freescale Cortex...   Sep 5 2013, 12:26
|- - vshemm   Цитата(Tarbal @ Sep 5 2013, 16:26) Теперь...   Sep 5 2013, 13:00
|- - Tarbal   Цитата(vshemm @ Sep 5 2013, 17:00) Так, к...   Sep 5 2013, 13:29
|- - vshemm   Цитата(Tarbal @ Sep 5 2013, 17:29) И чем ...   Sep 5 2013, 14:32
- - Tarbal   Моя проблема в том, что в ссылке, что вы дали под ...   Sep 5 2013, 15:01
|- - vshemm   Цитата(Tarbal @ Sep 5 2013, 19:01) Моя пр...   Sep 5 2013, 15:25
||- - Tarbal   TigerShark если у вас будут вопросы по реализации ...   Sep 5 2013, 19:08
|- - sasamy   Цитата(Tarbal @ Sep 5 2013, 19:01) Кстати...   Sep 6 2013, 07:49
- - Tarbal   Вопрос знатокам. В данный момент я делаю драйвер e...   Sep 6 2013, 11:04
- - vshemm   Цитата(Tarbal @ Sep 6 2013, 15:04) Вопрос...   Sep 7 2013, 17:27
- - Tarbal   Цитата(vshemm @ Sep 7 2013, 21:27) Выбор ...   Sep 8 2013, 21:11
- - sasamy   Цитата(Tarbal @ Sep 9 2013, 01:11) Kак сд...   Sep 9 2013, 05:44
- - Tarbal   Цитата(sasamy @ Sep 9 2013, 09:44) Ваш во...   Sep 9 2013, 11:50


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 01:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01552 секунд с 7
ELECTRONIX ©2004-2016