xor.kruger 0 17 ноября, 2011 Опубликовано 17 ноября, 2011 · Жалоба Доброго времени суток! В данный момент времени приходится разбираться с программированием драйверов для периферии Microblaze (до этого имел небольшой опыт в программировании драйверов для ARM9 семейства AT91). Суть данной темы (как мне кажется :rolleyes: ) на этом форуме в том, чтобы любой желающий кому нужна и/или интересна подобная тематика (примеры, общие вопросы и рекомендации программирования драйверов с учетом аппаратных особенностей IP-COREs Microblaze) смог задать вопрос, найти готовый рабочий кусок кода и т.д. К сожалению просидев неделю в гугле, ничего подобного и полезного в таком же духе не нашел :( Как водится, начал я с мигания светодиодом. Вот пример кода драйвера который засвечивает третий светодиод в линейке: #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/of_device.h> #include <linux/of_gpio.h> static int __init kruger_driver_init(void) { struct device_node *root_dn; struct device_node *kruger_gpio; struct gpio_chip *kruger_gc; int ret; printk(KERN_ALERT "Kruger driver init...\n"); root_dn = of_find_node_by_path("/"); kruger_gpio = of_find_node_by_name(root_dn, "ledss"); if (!kruger_gpio) { printk(KERN_ALERT "LEDs not found in DTF\n"); return -ENODEV; } printk(KERN_ALERT "LEDs find\n"); kruger_gc = of_node_to_gpiochip(kruger_gpio); printk(KERN_ALERT "%s: gpio controller %s \n", root_dn->full_name, kruger_gpio->full_name); if(!kruger_gc) { printk(KERN_ALERT "gc not register\n"); ret = -ENODEV; } ret = kruger_gc->direction_output(kruger_gc, 2, 1); if (ret < 0) { printk(KERN_ALERT "LEDs output error\n"); return -ENODEV; } kruger_gc->set(kruger_gc, 2, 1); return 0; } static void __exit kruger_driver_exit(void) { printk(KERN_ALERT "Kruger driver exit\n"); } module_init(kruger_driver_init); module_exit(kruger_driver_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kruger"); MODULE_DESCRIPTION("Gpio example driver"); Кусок dts-файла, соответствующий светодиодной линейке: LEDs_8Bit: ledss@81420000 { compatible = "xlnx,xps-gpio-2.00.a", "xlnx,xps-gpio-1.00.a"; reg = < 0x81420000 0x10000 >; xlnx,all-inputs = <0x0>; xlnx,all-inputs-2 = <0x0>; xlnx,dout-default = <0x0>; xlnx,dout-default-2 = <0x0>; xlnx,family = "spartan3adsp"; xlnx,gpio-width = <0x8>; xlnx,gpio2-width = <0x20>; xlnx,interrupt-present = <0x0>; xlnx,is-dual = <0x0>; xlnx,tri-default = <0xffffffff>; xlnx,tri-default-2 = <0xffffffff>; }; Для работы с gpio я использовал структуру gpio_chip. Все подробности о ней можно узнать из комментариев в файле include/asm-generic/gpio.h Очень многое я почерпнул из исходников самого ядра, в частности, из "фирмовых" драйверов Xilinx. Так что, если есть желающие поделится примерами - прошу выкладывать ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xor.kruger 0 29 ноября, 2011 Опубликовано 29 ноября, 2011 · Жалоба Доброго времени суток, продолжая тему о драйверах для IP-CORE Microblaze, столкнулся со следующей проблемой: Решил написать драйвер который обрабатывает внешние прерывание по нажатию на кнопку. Драйвер в системе регистрируется нормально, но обработчик прерывания никак не реагирует. Код драйвера: #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/of_device.h> #include <linux/of_platform.h> #include <linux/of_gpio.h> #include <linux/of_address.h> #include <linux/of.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <asm/irq.h> static int irq; static irqreturn_t test_irq_handler(int irq, void *dev_id) { printk(KERN_ALERT "all ok!\n"); return IRQ_HANDLED; } static int __init kruger_driver_init(void) { struct device_node *root_dn; struct device_node *kruger_gpio; struct resource resource; int result; unsigned int start_addr; unsigned long *virt_addr; printk(KERN_ALERT "Kruger driver init\n"); root_dn = of_find_node_by_path("/"); kruger_gpio = of_find_node_by_name(root_dn, "gpiob"); if (!kruger_gpio) { printk(KERN_ALERT "GPIO buttons not found in DTF\n"); return -ENODEV; } result = of_address_to_resource(kruger_gpio, 0, &resource); if (result < 0) { printk(KERN_ALERT "GPIO buttons: error address to resource"); return -ENODEV; } printk(KERN_ALERT "GPIO buttons: reg. size=%d Bytes\n", (u32)resource.end-(u32)resource.start); start_addr = (unsigned int)resource.start; irq = of_irq_to_resource(kruger_gpio, 0, &resource); if (irq == NO_IRQ) { printk(KERN_ALERT "GPIO buttons: of_irq_to_resource() failed\n"); of_node_put(kruger_gpio); return -ENODEV; } printk(KERN_ALERT "GPIO buttons: irq=%d\n", irq); virt_addr = of_iomap(kruger_gpio, 0); printk(KERN_ALERT "GPIO buttons: at 0x%08X mapped to 0x%08X\n", start_addr, (u32)virt_addr); result = request_irq(irq, &test_irq_handler, IRQF_TRIGGER_MASK, "Gpio Buttons", NULL); if (result < 0) { printk(KERN_ALERT "GPIO buttons: error to request IRQ%d : %d\n", irq, result); of_node_put(kruger_gpio); return -ENODEV; } printk(KERN_ALERT "GPIO buttons module inserted successfully\n"); return 0; } static void __exit kruger_driver_exit(void) { printk(KERN_ALERT "Kruger driver exit\n"); } module_init(kruger_driver_init); module_exit(kruger_driver_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kruger"); MODULE_DESCRIPTION("Gpio example driver"); Часть DTF-файла отвечающая за кнопки: Push_Buttons: gpiob@81400000 { compatible = "xlnx,xps-gpio-2.00.a", "xlnx,xps-gpio-1.00.a"; interrupt-parent = <&xps_intc_0>; interrupts = < 1 2 >; reg = < 0x81400000 0x10000 >; xlnx,all-inputs = <0x1>; xlnx,all-inputs-2 = <0x0>; xlnx,dout-default = <0x0>; xlnx,dout-default-2 = <0x0>; xlnx,family = "spartan3adsp"; xlnx,gpio-width = <0x4>; xlnx,gpio2-width = <0x20>; xlnx,interrupt-present = <0x1>; xlnx,is-dual = <0x0>; xlnx,tri-default = <0xffffffff>; xlnx,tri-default-2 = <0xffffffff>; }; Часть лога при инициализации драйвера: [ 7.635430] Kruger driver init [ 7.637493] GPIO buttons: reg. size=65535 Bytes [ 7.642095] GPIO buttons: irq=1 [ 7.645278] GPIO buttons: at 0x81400000 mapped to 0xC80A0000 [ 7.651114] GPIO buttons module inserted successfully Вывод файла /proc/interrupt CPU0 1: 0 level Xilinx INTC Gpio Buttons 2: 546096 edge Xilinx INTC timer 4: 1193 edge Xilinx INTC uartlite Кто-то пробовал "запускать" внешние прерывания по линухом? В чем может быть проблема? ЗЫ: Задавал этот же вопрос на офф. сайте Xilinx в разделе Embedded Linux - молчат как партизаны :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
КонстантинТ 0 23 декабря, 2011 Опубликовано 23 декабря, 2011 · Жалоба Ну тогда нам ничего не остается, и мы будем молчать в тряпочку :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться