Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Petalinux. Kernel module.
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
doom13
Приветствую.
Пытаюсь сделать модуль ядра для управления AXI GPIO. По мануалу сгенерил шаблон модуля и вношу в него свои изменения. Отлаживаю работу модуля в QEMU. При загрузке модуля (insmod) выполняется функция инициализации (printk в консоль выводит сообщение) в ней происходит вызов platform_driver_register(&axi_gpio_platform_driver), которая должна "пнуть" вызов axi_gpio_probe(), но вызов axi_gpio_probe() почему-то не происходит (сообщение printk в консоль о выполнении axi_gpio_probe() не выводятся). При этом platform_driver_register(&axi_gpio_platform_driver) возвращает 0.
В чём может быть проблема?

Спасибо.
nill
platform_driver_register() всего лишь регистрирует драйвер в системе, далее система должна определить присутствие устройства и после этого вызвать axi_gpio_probe(). У Вас это устройство определено в device tree? Вы передали device tree в qemu при старте системы?
doom13
Цитата(nill @ Apr 7 2016, 11:07) *
platform_driver_register() всего лишь регистрирует драйвер в системе, далее система должна определить присутствие устройства и после этого вызвать axi_gpio_probe(). У Вас это устройство определено в device tree? Вы передали device tree в qemu при старте системы?

Изменяю свой модуль. В консоли выполяю команды:
Код
petalinux-build
petalinux-boot --qemu --kernel

Этого достаточно?
В консоль выдаёт следующее:
CODE

--------------------------------------------------------------------
Xilinx QEMU Dec 10 2015 13:38:20.
--------------------------------------------------------------------
INFO: TCP PORT is free
INFO: Starting microblaze QEMU
INFO: qemu-system-microblazeel -L /opt/pkg/petalinux-v2015.4-final/etc/qemu -M microblaze-fdt-plnx -m 256 -serial mon:stdio -serial /dev/null -display none -kernel /home/andrei/work/htg_v7_g3/petalinux/peta_test/images/linux/image.elf -gdb tcp::9000 -dtb /tmp/tmp.BX8ZjB61fs -tftp /tftpboot
--------------------------------------------------------------------
Xilinx QEMU Dec 10 2015 13:38:20.
--------------------------------------------------------------------
Ramdisk addr 0x00000000,
FDT at 0x40b11668
Linux version 4.0.0 (andrei@andrei-pc) (gcc version 4.9.2 (crosstool-NG 1.20.0) ) #150 Thu Apr 7 15:23:02 MSK 2016
setup_cpuinfo: initialising
setup_cpuinfo: No PVR support. Using static CPU info from FDT
wt_msr_noirq
setup_memory: max_mapnr: 0x40000
setup_memory: min_low_pfn: 0x40000
setup_memory: max_low_pfn: 0x70000
setup_memory: max_pfn: 0x80000
Zone ranges:
DMA [mem 0x0000000040000000-0x000000006fffffff]
Normal empty
HighMem [mem 0x0000000070000000-0x000000007fffffff]
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000040000000-0x000000007fffffff]
Initmem setup node 0 [mem 0x0000000040000000-0x000000007fffffff]
On node 0 totalpages: 262144
free_area_init_node: node 0, pgdat c03d3004, node_mem_map c1000000
DMA zone: 1536 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 196608 pages, LIFO batch:31
HighMem zone: 65536 pages, LIFO batch:15
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260608
Kernel command line: console=ttyUL0,115200 earlyprintk
PID hash table entries: 4096 (order: 2, 16384 bytes)
Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
Memory: 1027408K/1048576K available (2965K kernel code, 95K rwdata, 816K rodata, 6856K init, 545K bss, 21168K reserved, 0K cma-reserved, 262144K highmem)
Kernel virtual memory layout:
* 0xfffea000..0xfffff000 : fixmap
* 0xff800000..0xffc00000 : highmem PTEs
* 0xff800000..0xff800000 : early ioremap
* 0xf0000000..0xff800000 : vmalloc & ioremap
NR_IRQS:33
/amba_pl/interrupt-controller@10002000: num_irq=2, edge=0x2
/amba_pl/timer@10000000: irq=1
xilinx_timer_set_mode: shutdown
xilinx_timer_set_mode: periodic
sched_clock: 32 bits at 150MHz, resolution 6ns, wraps every 28633115641ns
Calibrating delay loop... 749.56 BogoMIPS (lpj=3747840)
pid_max: default: 4096 minimum: 301
Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
devtmpfs: initialized
NET: Registered protocol family 16
Switched to clocksource xilinx_clocksource
NET: Registered protocol family 2
TCP established hash table entries: 8192 (order: 3, 32768 bytes)
TCP bind hash table entries: 8192 (order: 5, 163840 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP: reno registered
UDP hash table entries: 512 (order: 2, 24576 bytes)
UDP-Lite hash table entries: 512 (order: 2, 24576 bytes)
NET: Registered protocol family 1
Skipping unavailable RESET gpio -2 (reset)
futex hash table entries: 16 (order: -4, 448 bytes)
romfs: ROMFS MTD © 2007 Red Hat, Inc.
bounce: pool size: 64 pages
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
10001000.serial: ttyUL0 at MMIO 0x10001000 (irq = 2, base_baud = 0) is a uartlite
console [ttyUL0] enabled
brd: module loaded
i2c /dev entries driver
TCP: cubic registered
NET: Registered protocol family 17
Key type encrypted registered
Freeing unused kernel memory: 6856K (c03d4000 - c0a86000)
INIT: version 2.88 booting
Creating /dev/flash/* device nodes
random: dd urandom read with 10 bits of entropy available
Starting internet superserver: inetd.
update-rc.d: /etc/init.d/run-postinsts exists during rc.d purge (continuing)
Removing any system startup links for run-postinsts ...
/etc/rcS.d/S99run-postinsts
INIT: Entering runlevel: 5
Configuring network interfaces... ifconfig: SIOCGIFFLAGS: No such device
login[290]: root login on 'console'
-sh: can't access tty; job control turned off
root@peta_test:~#
root@peta_test:~#
root@peta_test:~#
root@peta_test:~#


Попробовал так
Код
petalinux-boot --qemu --image images/linux/image.elf --dtb images/linux/system.dtb

, не помогло.
doom13
Уточню.
Нашёл исходный код platform_driver_register(), добавил туда printk. Всё чётко, никаких ошибок не выдаёт и возвращает 0.
CODE

int __platform_driver_register(struct platform_driver *drv,
struct module *owner)
{

printk(KERN_ERR "In __platform_driver_register() function\n");
printk(KERN_ERR "drv->probe = %p\n", drv->probe); // не ноль
printk(KERN_ERR "drv->remove = %p\n", drv->remove); // не ноль
printk(KERN_ERR "drv->shutdown = %p\n", drv->shutdown); // не ноль

drv->driver.owner = owner;
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;

return driver_register(&drv->driver);
}

int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;

BUG_ON(!drv->bus->p);

printk(KERN_ERR "In driver_register() function TP# 1\n");

if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
//printk(KERN_WARNING "Driver '%s' needs updating - please use "
// "bus_type methods\n", drv->name);
printk(KERN_ERR "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);

printk(KERN_ERR "In driver_register() function TP# 2\n");

other = driver_find(drv->name, drv->bus);
if (other) {
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}

printk(KERN_ERR "In driver_register() function TP# 3\n");

ret = bus_add_driver(drv);
if (ret)
return ret;

printk(KERN_ERR "In driver_register() function TP# 4\n");

ret = driver_add_groups(drv, drv->groups);
if (ret) {
bus_remove_driver(drv);
return ret;
}

printk(KERN_ERR "In driver_register() function TP# 5\n");

kobject_uevent(&drv->p->kobj, KOBJ_ADD);

printk(KERN_ERR "In driver_register() function TP# 6\n");
printk(KERN_ERR "ret = %d\n", ret);

return ret; // тут ret равен 0
}
nill
Цитата(doom13 @ Apr 7 2016, 14:58) *
Этого достаточно?

Device tree передаётся qemu параметром -dtb и этот параметр есть в строке запуска, так что должно быть достаточно. Другое дело - проследить, чтоб передавался нужный файл. А вообще, содержимое device tree можно посмотреть в /proc/device-tree. Вы добавили своё устройство в device tree? Я думаю, что проблема именно в этом месте.

Для загрузки платформенного драйвера, который Вы решили сделать, необходимо выполнить несколько условий:
1. Добавить устройство в device tree. Ключевым параметром здесь является compatible = "name" и именно по имени name ядро решает, какой драйвер соответствует данному устройству.
2. Заполнить структуру of_device_id и указать в ней имя драйвера. Оно должно соответствовать name в device tree.
3. Заполнить струкруру platform_driver и в её поле driver.of_match_table указать Вашу of_device_id.
4. Передать структуру platform_driver макросу module_platform_driver().
Если всё сделать правильно, то ядро само вызовет функцию probe() после загрузки драйвера.

Покажите код Вашего драйвера (если он не слишком длинный).
doom13
Цитата(nill @ Apr 8 2016, 09:53) *
А вообще, содержимое device tree можно посмотреть в /proc/device-tree. Вы добавили своё устройство в device tree? Я думаю, что проблема именно в этом месте.

Подскажите, как это проверить. Вот что попробовал, какая-то ерунда получается:
Код
root@peta_test:~# cat /proc/device-tree
cat: read error: Is a directory
root@peta_test:~#
root@peta_test:~# cd /proc/device-tree/
root@peta_test:/sys/firmware/devicetree/base#
root@peta_test:/sys/firmware/devicetree/base#



Из хелпа QEMU
Цитата
QEMU available options:
--dtb DTB force use of a particular device tree file.
if not specified, QEMU uses
<PROJECT>/images/linux/system.dtb

, получается использует device-tree из папки проекта
nill
Вам же говорят, что это каталог rolleyes.gif Зайдите внутрь, там всё дерево разложено по каталогам и файлам.
doom13
Цитата(nill @ Apr 8 2016, 09:53) *
Покажите код Вашего драйвера (если он не слишком длинный).

Там просто стандартный шаблон, который сгенерировала команда petalinux-create -t modules --name axi_gpio0 --enable:
CODE

/* axi_gpio0.c - The simplest kernel module.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/interrupt.h>

#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>

/* Standard module information, edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Xilinx corp.");
MODULE_DESCRIPTION ("axi_gpio0 - loadable module for axi_gpio control");

#define DRIVER_NAME "axi_gpio0"


int test_value = 0;


struct axi_gpio0_local {
int irq;
unsigned long mem_start;
unsigned long mem_end;
void __iomem *base_addr;
};

static irqreturn_t axi_gpio0_irq(int irq, void *lp)
{
printk("axi_gpio0 interrupt\n");
return IRQ_HANDLED;
}

static int axi_gpio0_probe(struct platform_device *pdev)
{
struct resource *r_irq; /* Interrupt resources */
struct resource *r_mem; /* IO mem resources */
struct device *dev = &pdev->dev;
struct axi_gpio0_local *lp = NULL;

int rc = 0;
int counter = 0;

test_value = 111;

printk("<1>Hello module world.\n");
printk(KERN_ERR "In probe() function\n");

dev_info(dev, "Device Tree Probing\n");

test_value = 222;

/*
// Get iospace for the device
r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r_mem) {
dev_err(dev, "invalid address\n");
return -ENODEV;
}

lp = (struct axi_gpio0_local *) kmalloc(sizeof(struct axi_gpio0_local), GFP_KERNEL);
if (!lp) {
dev_err(dev, "Cound not allocate axi_gpio0 device\n");
return -ENOMEM;
}

dev_set_drvdata(dev, lp);

lp->mem_start = r_mem->start;
lp->mem_end = r_mem->end;

printk("lp->mem_start = %x\n", lp->mem_start);
printk("lp->mem_end = %x\n", lp->mem_end);

if (!request_mem_region(lp->mem_start,
lp->mem_end - lp->mem_start + 1,
DRIVER_NAME)) {
dev_err(dev, "Couldn't lock memory region at %p\n",
(void *)lp->mem_start);
rc = -EBUSY;
goto error1;
}

lp->base_addr = ioremap(lp->mem_start, lp->mem_end - lp->mem_start + 1);
if (!lp->base_addr) {
dev_err(dev, "axi_gpio0: Could not allocate iomem\n");
rc = -EIO;
goto error2;
}

// Get IRQ for the device
r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!r_irq) {
dev_info(dev, "no IRQ found\n");
dev_info(dev, "axi_gpio0 at 0x%08x mapped to 0x%08x\n",
(unsigned int __force)lp->mem_start,
(unsigned int __force)lp->base_addr);
return 0;
}
lp->irq = r_irq->start;

rc = request_irq(lp->irq, &axi_gpio0_irq, 0, DRIVER_NAME, lp);
if (rc) {
dev_err(dev, "testmodule: Could not allocate interrupt %d.\n",
lp->irq);
goto error3;
}

dev_info(dev,"axi_gpio0 at 0x%08x mapped to 0x%08x, irq=%d\n",
(unsigned int __force)lp->mem_start,
(unsigned int __force)lp->base_addr,
lp->irq);

return 0;
error3:
free_irq(lp->irq, lp);
error2:
release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
error1:
kfree(lp);
dev_set_drvdata(dev, NULL);
*/
return rc;
}

static int axi_gpio0_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct axi_gpio0_local *lp = dev_get_drvdata(dev);
free_irq(lp->irq, lp);
release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
kfree(lp);
dev_set_drvdata(dev, NULL);

test_value = 333;

return 0;
}

//#ifdef CONFIG_OF
static struct of_device_id axi_gpio0_of_match[] = {
{ .compatible = "vendor,axi_gpio0", },
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(of, axi_gpio0_of_match);
//#else
//# define axi_gpio0_of_match
//#endif


static struct platform_driver axi_gpio0_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = axi_gpio0_of_match,
},
.probe = axi_gpio0_probe,
.remove = axi_gpio0_remove,
};


static int __init axi_gpio0_init(void)
{
int result = 12;

printk(KERN_INFO "Hello module world.\n");
printk(KERN_INFO "Hello module world.\n");
printk(KERN_INFO "In init() function 10:14.\n");
//dev_info(dev, "<1>Hello module world.\n");
//printk("<1>Module parameters were (0x%08x) and \"%s\"\n", myint,
// mystr);

printk(KERN_INFO "result = %d\n", result);
//test_counter();

printk(KERN_ERR "axi_gpio0_driver.probe = %p\n", axi_gpio0_driver.probe);
printk(KERN_ERR "axi_gpio0_probe = %p\n", axi_gpio0_probe);

result = platform_driver_register(&axi_gpio0_driver);
printk(KERN_INFO "result = %d\n", result);
printk(KERN_INFO "test_value = %d\n", test_value);


return result;
}


static void __exit axi_gpio0_exit(void)
{
platform_driver_unregister(&axi_gpio0_driver);
printk(KERN_INFO "Goodbye module world.\n");
printk(KERN_INFO "test_value = %d\n", test_value);
}

module_init(axi_gpio0_init);
module_exit(axi_gpio0_exit);

, в теле axi_gpio0_probe() только printk, хочу увидеть что оно в неё заходит.

Цитата(nill @ Apr 8 2016, 10:36) *
Вам же говорят, что это каталог rolleyes.gif Зайдите внутрь, там всё дерево разложено по каталогам и файлам.

Ссори, не то закопипастил в посте выше, исправил, не даёт зайти в каталог, переходит сразу в каталог /sys/firmware/devicetree/base (или так и надо?).
nill
axi_gpio0_init(void) и axi_gpio0_exit(void) можно выбросить вместе с module_init/module_exit и использовать вместо них макрос module_platform_driver(axi_gpio0_driver). Это не обязательно, но чаще делают именно так - код получается немного проще. В device tree должно быть строка .compatible = "vendor,axi_gpio0". Я бы заменил её на что-нибудь уникальное во избежание накладок.

Цитата(doom13 @ Apr 8 2016, 13:39) *
... не даёт зайти в каталог, переходит сразу в каталог /sys/firmware/devicetree/base (или так и надо?).

Тут ничего не могу сказать, поскольку не работал с petalinux и не знаю, как они там всё устроили. Похоже, что /proc/device-tree - это симлинк, но сути это не меняет. Ищите в /sys, ести Вас туда выводят.
doom13
Цитата(nill @ Apr 8 2016, 10:57) *
axi_gpio0_init(void) и axi_gpio0_exit(void) можно выбросить вместе с module_init/module_exit и использовать вместо них макрос module_platform_driver(axi_gpio0_driver). Это не обязательно, но чаще делают именно так - код получается немного проще.

Спасибо, учту в будущем.
Цитата(nill @ Apr 8 2016, 10:57) *
В device tree должно быть строка .compatible = "vendor,axi_gpio0". Я бы заменил её на что-нибудь уникальное во избежание накладок.

Тут поменял на my_gpio_driver, но всё как и ранее, в probe не заходит.

Цитата(nill @ Apr 8 2016, 10:57) *
Тут ничего не могу сказать, поскольку не работал с petalinux и не знаю, как они там всё устроили. Похоже, что /proc/device-tree - это симлинк, но сути это не меняет. Ищите в /sys, ести Вас туда выводят.

Вот, что есть в /sys/firmware/devicetree/base:
CODE

[ hexdump renice
[[ hostname reset
addgroup httpd rm
adduser hwclock rmdir
ar id rmmod
ash ifconfig route
awk ifdown run-parts
basename ifup run-postinsts
bootlogd inetd runlevel
busybox init runlevel.sysvinit
busybox.nosuid init.sysvinit sed
busybox.suid insmod seq
cat ip setconsole
chattr kill sh
chgrp killall sha1sum
chmod killall5 sha256sum
chown klogd sha3sum
chroot last sha512sum
chvt last.sysvinit shuf
clear lastb shutdown
cmp ldconfig shutdown.sysvinit
cp less sleep
cpio ln sort
cut loadfont start-stop-daemon
date loadkmap stat
dc logger strings
dd login stty
deallocvt logname su
delgroup logread sulogin
deluser losetup swapoff
depmod ls swapon
devmem lsmod switch_root
df md5sum sync
diff mdev sysctl
dirname mesg syslogd
dmesg mesg.sysvinit tail
dnsdomainname microcom tar
du mkdir tee
dumpkmap mkdosfs telinit
dumpleases mkfifo telnet
echo mkfs.vfat telnetd
egrep mknod test
env mkswap tftp
expr mktemp time
false modprobe top
fatattr more touch
fbset mount tr
fdisk mountpoint traceroute
fgrep mountpoint.sysvinit true
find mtd_debug tty
flash_erase mtdinfo udhcpc
flash_eraseall mv udhcpd
flash_lock nanddump umount
flash_otp_dump nandtest uname
flash_otp_info nandwrite uniq
flash_otp_lock netstat unlink
flash_otp_write nice unzip
flash_unlock nohup update-alternatives
flashcp nslookup update-rc.d
flock od upgrade-firmware
free openvt uptime
fsck passwd users
fstab-decode patch usleep
fstrim peek utmpdump
ftpd pidof utmpdump.sysvinit
ftpget pidof.sysvinit vi
ftpput ping vlock
fuser ping6 wall
fwupgrade pivot_root wall.sysvinit
gdbserver poke watch
getopt poweroff watchdog
getty poweroff.sysvinit wc
grep printf wget
groups ps which
gunzip pwd who
gzip rdate whoami
halt readlink xargs
halt.sysvinit realpath yes
hd reboot zcat
head reboot.sysvinit

nill
Это имя дожно быть одинаковым в драйвере и device tree. Вы его изменили в device tree? Нашли эту строку в /proc/device-tree (или где она там...)?

В /sys/... что-то не то, device tree выгдядит по-другому.
doom13
Цитата(nill @ Apr 8 2016, 11:08) *
Это имя дожно быть одинаковым в драйвере и device tree. Вы его изменили в device tree? Нашли эту строку в /proc/device-tree (или где она там...)?

Это имя .compatible = "my_gpio_driver", которое задаётся для компатибле???
Цитата(nill @ Apr 8 2016, 11:08) *
В /sys/... что-то не то, device tree выгдядит по-другому

Это похоже
Код
root@peta_test:/sys/firmware/devicetree/base# ls -al
-r--r--r--    1 root     root             4 Jan  1 00:15 #address-cells
-r--r--r--    1 root     root             4 Jan  1 00:15 #size-cells
drwxr-xr-x    8 root     root             0 Jan  1 00:04 .
drwxr-xr-x    3 root     root             0 Jan  1 00:04 ..
drwxr-xr-x    2 root     root             0 Jan  1 00:05 aliases
drwxr-xr-x    8 root     root             0 Jan  1 00:05 amba_pl
drwxr-xr-x    2 root     root             0 Jan  1 00:15 chosen
drwxr-xr-x    4 root     root             0 Jan  1 00:15 clocks
-r--r--r--    1 root     root            16 Jan  1 00:15 compatible
drwxr-xr-x    3 root     root             0 Jan  1 00:15 cpus
drwxr-xr-x    2 root     root             0 Jan  1 00:15 memory
-r--r--r--    1 root     root            10 Jan  1 00:15 model
-r--r--r--    1 root     root             1 Jan  1 00:15 name
root@peta_test:/sys/firmware/devicetree/base#

????
nill
^ Да, это оно.
Так, кажется я начал о чём-то догадываться... biggrin.gif
Вам необходимо отредактивать исходник device tree, а не то что находится в /proc/device-tree. Этот файл нужен для контроля уже загруженного device tree и изменить его не получится. Вам нужно найти и отредактировать файл с расширением dts, из него в процессе сборки компилируется dtb. Как и где это сделать - не знаю, вам придётся разобраться с сиcтемой сборки.
doom13
Цитата(nill @ Apr 8 2016, 11:20) *
Так, кажется я начал о чём-то догадываться... biggrin.gif
Вам необходимо отредактивать исходник device tree, а не то что находится в /proc/device-tree. Этот файл нужен для контроля уже загруженного device tree и изменить его не получится. Вам нужно найти и отредактировать файл с расширением dts, из него в процессе сборки компилируется dtb. Как и где это сделать - не знаю, вам придётся разобраться с сиcтемой сборки.

Тут счас подумаю, а пока, что скажете об этом:
Код
root@peta_test:/sys/firmware/devicetree/base/amba_pl#
root@peta_test:/sys/firmware/devicetree/base/amba_pl# ls -al
-r--r--r--    1 root     root             4 Jan  1 00:24 #address-cells
-r--r--r--    1 root     root             4 Jan  1 00:24 #size-cells
drwxr-xr-x    8 root     root             0 Jan  1 00:05 .
drwxr-xr-x    8 root     root             0 Jan  1 00:04 ..
-r--r--r--    1 root     root            11 Jan  1 00:24 compatible
drwxr-xr-x    2 root     root             0 Jan  1 00:24 gpio@10003000
drwxr-xr-x    2 root     root             0 Jan  1 00:24 interrupt-controller@10002000
-r--r--r--    1 root     root             4 Jan  1 00:24 linux,phandle
drwxr-xr-x    2 root     root             0 Jan  1 00:24 memory-controller@40000000
-r--r--r--    1 root     root             8 Jan  1 00:24 name
-r--r--r--    1 root     root             4 Jan  1 00:24 phandle
-r--r--r--    1 root     root             0 Jan  1 00:24 ranges
drwxr-xr-x    2 root     root             0 Jan  1 00:24 serial@10001000
drwxr-xr-x    2 root     root             0 Jan  1 00:24 serial@20000000
drwxr-xr-x    2 root     root             0 Jan  1 00:24 timer@10000000
root@peta_test:/sys/firmware/devicetree/base/amba_pl#

Memory map для системы на рисунке. Т.е. тут есть timer@10000000, serial@10001000, interrupt-controller@10002000, gpio@10003000, memory-controller@40000000.
nill
axi_gpio_0 определён в карте памяти, посмотрите в gpio@10003000 - может это оно и есть. И прикрепите сюда Ваш dtb, я завтра гляну, если Вы сами к тому моменту не разберётесь.
doom13
Цитата(nill @ Apr 8 2016, 11:41) *
axi_gpio_0 определён в карте памяти, посмотрите в gpio@10003000 - может это оно и есть.

Так и есть - это необходимый AXI GPIO. Только что с этим делать? sad.gif
Цитата(nill @ Apr 8 2016, 11:41) *
И прикрепите сюда Ваш dtb, я завтра гляну, если Вы сами к тому моменту не разберётесь.

В папке проекта Petalinux есть папка /subsystems/linux/configs/device-tree/, в ней файлы pl.dtsi, system-conf.dtsi, system-top.dts, как понимаю, на их основании собирает device tree /images/linux/system.dtb, которое и заливается в QEMU. Файлы прикрепил.
nill
В файле pl.dtsi есть секция axi_gpio_0: gpio@10003000. Вам нужно использовать значение compatible = "xlnx,xps-gpio-1.00.a" в своём драйвере. Вы могли найти это значение и в /sys/firmware/devicetree/base/amba_pl/gpio@10003000/compatible.
doom13
Цитата(nill @ Apr 9 2016, 09:02) *
В файле pl.dtsi есть секция axi_gpio_0: gpio@10003000. Вам нужно использовать значение compatible = "xlnx,xps-gpio-1.00.a" в своём драйвере. Вы могли найти это значение и в /sys/firmware/devicetree/base/amba_pl/gpio@10003000/compatible.

Т.е. для кода модуля (сообщение #8 выше) надо изменить
Код
static struct of_device_id axi_gpio0_of_match[] = {
    { .compatible = "vendor,axi_gpio0", },
    { /* end of list */ },
};

на
Код
static struct of_device_id axi_gpio0_of_match[] = {
    { .compatible = "xlnx,xps-gpio-1.00.a", },
    { /* end of list */ },
};

и всё должно заработать? Это я пробовал, но функция probe() всё равно не вызывалась (axi_gpio0_probe() в моём случае).
Спасибо, попробую ещё раз перепроверить.
nill
Других идей у меня, к сожалению, нет. Возможно, что в ядре не включена поддержка device tree и тогда драйвер будет привязываться к устройству по имени DRIVER_NAME (в коде модуля), но это маловероятный вариант. Проверьте параметр CONFIG_OF в конфигурации ядра.
doom13
Приветствую.
Перепроверил всё ещё раз. При загрузке модуля axi_gpio0_probe() не выполняется???
Код драйвера (совет использовать module_platform_driver(axi_gpio0_driver) пока не учтён):
CODE

/* axi_gpio0.c - The simplest kernel module.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/interrupt.h>

#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>

/* Standard module information, edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Xilinx corp.");
MODULE_DESCRIPTION ("axi_gpio0 - loadable module for axi_gpio control");

#define DRIVER_NAME "axi_gpio0"


int test_value = 0;


struct axi_gpio0_local {
int irq;
unsigned long mem_start;
unsigned long mem_end;
void __iomem *base_addr;
};

static irqreturn_t axi_gpio0_irq(int irq, void *lp)
{
printk("axi_gpio0 interrupt\n");
return IRQ_HANDLED;
}

static int axi_gpio0_probe(struct platform_device *pdev)
{
struct resource *r_irq; /* Interrupt resources */
struct resource *r_mem; /* IO mem resources */
struct device *dev = &pdev->dev;
struct axi_gpio0_local *lp = NULL;

int rc = 0;
int counter = 0;

test_value = 111;

printk("<1>Hello module world.\n");
printk(KERN_ERR "In probe() function\n");

dev_info(dev, "Device Tree Probing\n");

test_value = 222;

return rc;
}

static int axi_gpio0_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct axi_gpio0_local *lp = dev_get_drvdata(dev);
free_irq(lp->irq, lp);
release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
kfree(lp);
dev_set_drvdata(dev, NULL);

test_value = 333;

return 0;
}

//#ifdef CONFIG_OF
static struct of_device_id axi_gpio0_of_match[] = {
{ .compatible = "xlnx,xps-gpio-1.00.a", },
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(of, axi_gpio0_of_match);
//#else
//# define axi_gpio0_of_match
//#endif


static struct platform_driver axi_gpio0_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = axi_gpio0_of_match,
},
.probe = axi_gpio0_probe,
.remove = axi_gpio0_remove,
};


static int __init axi_gpio0_init(void)
{
int result = 12;

printk(KERN_INFO "Ver - 09:01 11.03.2016\n");

printk(KERN_INFO "Hello module world.\n");
printk(KERN_INFO "Hello module world.\n");
printk(KERN_INFO ".compatible = xlnx,xps-gpio-1.00.a\n");

printk(KERN_INFO "result = %d\n", result);
//test_counter();

printk(KERN_ERR "axi_gpio0_driver.probe = %p\n", axi_gpio0_driver.probe);
printk(KERN_ERR "axi_gpio0_probe = %p\n", axi_gpio0_probe);

result = platform_driver_register(&axi_gpio0_driver);
printk(KERN_INFO "result = %d\n", result);
printk(KERN_INFO "test_value = %d\n", test_value);


return result;
}


static void __exit axi_gpio0_exit(void)
{
platform_driver_unregister(&axi_gpio0_driver);
printk(KERN_INFO "Goodbye module world.\n");
printk(KERN_INFO "test_value = %d\n", test_value);
}

module_init(axi_gpio0_init);
module_exit(axi_gpio0_exit);


1) Сборка ядра:
CODE

andrei@andrei-pc:~/work/htg_v7_g3/petalinux/peta_test$ petalinux-build
INFO: Checking component...
INFO: Generating make files and build linux
INFO: Generating make files for the subcomponents of linux
INFO: Building linux
[INFO ] pre-build linux/rootfs/axi_gpio0
[INFO ] pre-build linux/rootfs/autologin
[INFO ] pre-build linux/rootfs/fwupgrade
[INFO ] pre-build linux/rootfs/peekpoke
[INFO ] build linux/kernel
[INFO ] generate linux/u-boot configuration files
[INFO ] update linux/u-boot source
[INFO ] build linux/u-boot
[INFO ] build fs-boot
[INFO ] build kernel in-tree modules
[INFO ] modules linux/kernel
[INFO ] build linux/rootfs/axi_gpio0
[INFO ] modules linux/kernel
[INFO ] build linux/rootfs/autologin
[INFO ] build linux/rootfs/fwupgrade
[INFO ] build linux/rootfs/peekpoke
[INFO ] post-build linux/rootfs/axi_gpio0
[INFO ] post-build linux/rootfs/autologin
[INFO ] post-build linux/rootfs/fwupgrade
[INFO ] post-build linux/rootfs/peekpoke
[INFO ] pre-install linux/rootfs/axi_gpio0
[INFO ] pre-install linux/rootfs/autologin
[INFO ] pre-install linux/rootfs/fwupgrade
[INFO ] pre-install linux/rootfs/peekpoke
[INFO ] install system.dtb
[INFO ] install linux/kernel
[INFO ] generate linux/u-boot configuration files
[INFO ] update linux/u-boot source
[INFO ] build linux/u-boot
[INFO ] install linux/u-boot
[INFO ] install sys_init
[INFO ] install kernel in-tree modules
[INFO ] modules_install linux/kernel
[INFO ] install linux/rootfs/axi_gpio0
[INFO ] modules_install linux/kernel
[INFO ] install linux/rootfs/autologin
[INFO ] install linux/rootfs/fwupgrade
[INFO ] install linux/rootfs/peekpoke
[INFO ] post-install linux/rootfs/axi_gpio0
[INFO ] post-install linux/rootfs/autologin
[INFO ] post-install linux/rootfs/fwupgrade
[INFO ] post-install linux/rootfs/peekpoke
[INFO ] package rootfs.cpio to /home/andrei/work/htg_v7_g3/petalinux/peta_test/images/linux
[INFO ] Update and install vmlinux image
[INFO ] vmlinux linux/kernel
[INFO ] install linux/kernel
[INFO ] package simpleImage.mb
[INFO ] simpleImage.mb linux/kernel
[INFO ] install linux/kernel
[INFO ] Package HDF bitstream
webtalk failed:PetaLinux statistics:extra lines detected:notsent_nofile!
webtalk failed:Failed to get PetaLinux usage statistics!
andrei@andrei-pc:~/work/htg_v7_g3/petalinux/peta_test$
andrei@andrei-pc:~/work/htg_v7_g3/petalinux/peta_test$


2) Загрузка ядра в QEMU
CODE

andrei@andrei-pc:~/work/htg_v7_g3/petalinux/peta_test$ petalinux-boot --qemu --kernelqemu_cmd=qemu-system-microblazeel
--------------------------------------------------------------------
Xilinx QEMU Dec 10 2015 13:38:20.
--------------------------------------------------------------------
INFO: TCP PORT is free
INFO: Starting microblaze QEMU
INFO: qemu-system-microblazeel -L /opt/pkg/petalinux-v2015.4-final/etc/qemu -M microblaze-fdt-plnx -m 256 -serial mon:stdio -serial /dev/null -display none -kernel /home/andrei/work/htg_v7_g3/petalinux/peta_test/images/linux/image.elf -gdb tcp::9000 -dtb /tmp/tmp.ggssIoMAoO -tftp /tftpboot
--------------------------------------------------------------------
Xilinx QEMU Dec 10 2015 13:38:20.
--------------------------------------------------------------------
Ramdisk addr 0x00000000,
FDT at 0x40b11668
Linux version 4.0.0 (andrei@andrei-pc) (gcc version 4.9.2 (crosstool-NG 1.20.0) ) #170 Mon Apr 11 09:02:31 MSK 2016
setup_cpuinfo: initialising
setup_cpuinfo: No PVR support. Using static CPU info from FDT
wt_msr_noirq
setup_memory: max_mapnr: 0x40000
setup_memory: min_low_pfn: 0x40000
setup_memory: max_low_pfn: 0x70000
setup_memory: max_pfn: 0x80000
Zone ranges:
DMA [mem 0x0000000040000000-0x000000006fffffff]
Normal empty
HighMem [mem 0x0000000070000000-0x000000007fffffff]
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000040000000-0x000000007fffffff]
Initmem setup node 0 [mem 0x0000000040000000-0x000000007fffffff]
On node 0 totalpages: 262144
free_area_init_node: node 0, pgdat c03d3004, node_mem_map c1000000
DMA zone: 1536 pages used for memmap
DMA zone: 0 pages reserved
DMA zone: 196608 pages, LIFO batch:31
HighMem zone: 65536 pages, LIFO batch:15
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260608
Kernel command line: console=ttyUL0,115200 earlyprintk
PID hash table entries: 4096 (order: 2, 16384 bytes)
Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
Memory: 1027408K/1048576K available (2965K kernel code, 95K rwdata, 816K rodata, 6856K init, 545K bss, 21168K reserved, 0K cma-reserved, 262144K highmem)
Kernel virtual memory layout:
* 0xfffea000..0xfffff000 : fixmap
* 0xff800000..0xffc00000 : highmem PTEs
* 0xff800000..0xff800000 : early ioremap
* 0xf0000000..0xff800000 : vmalloc & ioremap
NR_IRQS:33
/amba_pl/interrupt-controller@10002000: num_irq=2, edge=0x2
/amba_pl/timer@10000000: irq=1
xilinx_timer_set_mode: shutdown
xilinx_timer_set_mode: periodic
sched_clock: 32 bits at 150MHz, resolution 6ns, wraps every 28633115641ns
Calibrating delay loop... 723.76 BogoMIPS (lpj=3618816)
pid_max: default: 4096 minimum: 301
Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
devtmpfs: initialized
NET: Registered protocol family 16
Switched to clocksource xilinx_clocksource
NET: Registered protocol family 2
TCP established hash table entries: 8192 (order: 3, 32768 bytes)
TCP bind hash table entries: 8192 (order: 5, 163840 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP: reno registered
UDP hash table entries: 512 (order: 2, 24576 bytes)
UDP-Lite hash table entries: 512 (order: 2, 24576 bytes)
NET: Registered protocol family 1
Skipping unavailable RESET gpio -2 (reset)
futex hash table entries: 16 (order: -4, 448 bytes)
romfs: ROMFS MTD © 2007 Red Hat, Inc.
bounce: pool size: 64 pages
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
10001000.serial: ttyUL0 at MMIO 0x10001000 (irq = 2, base_baud = 0) is a uartlite
console [ttyUL0] enabled
brd: module loaded
i2c /dev entries driver
TCP: cubic registered
NET: Registered protocol family 17
Key type encrypted registered
Freeing unused kernel memory: 6856K (c03d4000 - c0a86000)
INIT: version 2.88 booting
Creating /dev/flash/* device nodes
random: dd urandom read with 9 bits of entropy available
Starting internet superserver: inetd.
update-rc.d: /etc/init.d/run-postinsts exists during rc.d purge (continuing)
Removing any system startup links for run-postinsts ...
/etc/rcS.d/S99run-postinsts
INIT: Entering runlevel: 5
Configuring network interfaces... ifconfig: SIOCGIFFLAGS: No such device
login[290]: root login on 'console'
-sh: can't access tty; job control turned off
root@peta_test:~#
root@peta_test:~#
root@peta_test:~#
root@peta_test:~#


3)Загрузка модуля ядра (axi_gpio0)
CODE

root@peta_test:~#
root@peta_test:~#
root@peta_test:~#
root@peta_test:~#
root@peta_test:~# cd /lib/modules/4.0.0/extra/
root@peta_test:/lib/modules/4.0.0/extra#
root@peta_test:/lib/modules/4.0.0/extra#
root@peta_test:/lib/modules/4.0.0/extra#
root@peta_test:/lib/modules/4.0.0/extra# insmod axi_gpio0.ko
Ver - 09:01 11.03.2016
Hello module world.
Hello module world.
.compatible = xlnx,xps-gpio-1.00.a
result = 12
axi_gpio0_driver.probe = f00dc000
axi_gpio0_probe = f00dc000
result = 0
test_value = 0
root@peta_test:/lib/modules/4.0.0/extra#
root@peta_test:/lib/modules/4.0.0/extra#
root@peta_test:/lib/modules/4.0.0/extra#


4) Хотим посмотреть device tree
CODE

root@peta_test:/lib/modules/4.0.0/extra# cd /proc/device-tree/
root@peta_test:/sys/firmware/devicetree/base#
root@peta_test:/sys/firmware/devicetree/base# ls -al
-r--r--r-- 1 root root 4 Jan 1 00:01 #address-cells
-r--r--r-- 1 root root 4 Jan 1 00:01 #size-cells
drwxr-xr-x 8 root root 0 Jan 1 00:01 .
drwxr-xr-x 3 root root 0 Jan 1 00:01 ..
drwxr-xr-x 2 root root 0 Jan 1 00:01 aliases
drwxr-xr-x 8 root root 0 Jan 1 00:01 amba_pl
drwxr-xr-x 2 root root 0 Jan 1 00:01 chosen
drwxr-xr-x 4 root root 0 Jan 1 00:01 clocks
-r--r--r-- 1 root root 16 Jan 1 00:01 compatible
drwxr-xr-x 3 root root 0 Jan 1 00:01 cpus
drwxr-xr-x 2 root root 0 Jan 1 00:01 memory
-r--r--r-- 1 root root 10 Jan 1 00:01 model
-r--r--r-- 1 root root 1 Jan 1 00:01 name
root@peta_test:/sys/firmware/devicetree/base#


5) Содержимое директории amba_pl:
CODE

root@peta_test:/sys/firmware/devicetree/base# cd amba_pl/
root@peta_test:/sys/firmware/devicetree/base/amba_pl#
root@peta_test:/sys/firmware/devicetree/base/amba_pl#
root@peta_test:/sys/firmware/devicetree/base/amba_pl# ls -al
-r--r--r-- 1 root root 4 Jan 1 00:01 #address-cells
-r--r--r-- 1 root root 4 Jan 1 00:01 #size-cells
drwxr-xr-x 8 root root 0 Jan 1 00:01 .
drwxr-xr-x 8 root root 0 Jan 1 00:01 ..
-r--r--r-- 1 root root 11 Jan 1 00:01 compatible
drwxr-xr-x 2 root root 0 Jan 1 00:01 gpio@10003000
drwxr-xr-x 2 root root 0 Jan 1 00:01 interrupt-controller@10002000
-r--r--r-- 1 root root 4 Jan 1 00:01 linux,phandle
drwxr-xr-x 2 root root 0 Jan 1 00:01 memory-controller@40000000
-r--r--r-- 1 root root 8 Jan 1 00:01 name
-r--r--r-- 1 root root 4 Jan 1 00:01 phandle
-r--r--r-- 1 root root 0 Jan 1 00:01 ranges
drwxr-xr-x 2 root root 0 Jan 1 00:01 serial@10001000
drwxr-xr-x 2 root root 0 Jan 1 00:01 serial@20000000
drwxr-xr-x 2 root root 0 Jan 1 00:01 timer@10000000
root@peta_test:/sys/firmware/devicetree/base/amba_pl#


6) Содержимое gpio@10003000:
CODE

root@peta_test:/sys/firmware/devicetree/base/amba_pl#
root@peta_test:/sys/firmware/devicetree/base/amba_pl# cd gpio@10003000/
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000#
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000#
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000# ls -al
-r--r--r-- 1 root root 4 Jan 1 00:02 #gpio-cells
drwxr-xr-x 2 root root 0 Jan 1 00:01 .
drwxr-xr-x 8 root root 0 Jan 1 00:01 ..
-r--r--r-- 1 root root 12 Jan 1 00:02 compatible
-r--r--r-- 1 root root 0 Jan 1 00:02 gpio-controller
-r--r--r-- 1 root root 5 Jan 1 00:02 name
-r--r--r-- 1 root root 8 Jan 1 00:02 reg
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,all-inputs
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,all-inputs-2
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,all-outputs
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,all-outputs-2
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,dout-default
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,dout-default-2
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,gpio-width
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,gpio2-width
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,interrupt-present
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,is-dual
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,tri-default
-r--r--r-- 1 root root 4 Jan 1 00:02 xlnx,tri-default-2
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000#


7) Содержимое compatible в директории gpio@10003000:
CODE

root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000#
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000#
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000# cat compatible
invalidated
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000#
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000#


Почему показало "invalidated" вместо "xlnx,xps-gpio-1.00.a", что содержится в конфигурационных файлах для device tree (цеплял выше)?

Цитата(nill @ Apr 10 2016, 09:58) *
Проверьте параметр CONFIG_OF в конфигурации ядра.

CONFIG_OF=y
nill
Цитата(doom13 @ Apr 11 2016, 14:31) *
Код
root@peta_test:/sys/firmware/devicetree/base/amba_pl/gpio@10003000# cat compatible
invalidated

А вот и проблемное место. Эта строка означает, что данное устройство не поддерживается в qemu, поэтому эмулятор заменил параметр и тем самым предотвратил дальнейшую загрузку драйвера. У Вас два выхода:
1. Если необходимо работать именно с этим GPIO, то придётся перейти на реальное железо.
2. Если хочется просто поэкспериментировать с драйвером, то можно найти какое-нибудь поддерживаемое в эмуляторе устройство и добавить его. Или вручную отредактировать device tree и добавить секцию с именем, которое заведомо неизвестно qemu и которая содержит только парамерт compatible. Правда, я не уверен, что это сработает - нужно проверять.
doom13
nill, cпасибо.
Попробую поэкспериментировать с железом, платы не было, поэтому проводил эксперименты с QEMU.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.