Exception13 0 28 июля, 2008 Опубликовано 28 июля, 2008 · Жалоба Разбираюсь потихоньку с uClinux на BF537 (STAMP). Никак не въеду каким образом воспользоваться существующими в uClinux драйверами SPI. Интерфейс тривиальный, но как с ним работать из под uC - не ясно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Exception13 0 30 июля, 2008 Опубликовано 30 июля, 2008 · Жалоба Ну неужели никто SPI не заводил под uClinux'oм ? Тут вроде спецы есть кто Blackfin'oм занимаются. А то получается что linux запустили и все, радуемся :)... Подскажите пожалуйста, как вы это делали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MIkler 0 31 июля, 2008 Опубликовано 31 июля, 2008 · Жалоба В своё время написал свои, пользовался Даташитом и драйверами которые лежали в uC может сейчас стало получше с драйверами но тогда было мрачно :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Exception13 0 1 августа, 2008 Опубликовано 1 августа, 2008 · Жалоба Уважаемый Mihail Gluhowchenko писал вам в личку, но видимо письмо не дошло... Вобщем, мне пока удалось сделать драйвер символьного устройства SPI, который работает по прерываниям. Сделал очередь FIFO как на отправку так и на прием данных. Долго маялся с прерываниями пытаясь понять как правильно использовать SPIN блокировку. Ну, да ладно, вот только частота следования пакетов данных меня не радует, всего то 340 КГц получилась, и это при максимальном битрейте. Т.е. там между посылками получается разрыв раза в 3 превышающий длительность передачи 8 бит данных. Вот и хотелось бы посмотреть как работает встроенный в uClinux драйвер SPI, только как им правильно воспользоваться я не знаю... Если вы такое делали, поделитесь пожалуйста или подскажите как надо оформить соответствующие секции драйвера: init, exit, ioctl, read, write... С уважением, Александр... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MIkler 0 4 августа, 2008 Опубликовано 4 августа, 2008 · Жалоба Уважаемый Mihail Gluhowchenko писал вам в личку, но видимо письмо не дошло... Вобщем, мне пока удалось сделать драйвер символьного устройства SPI, который работает по прерываниям. Сделал очередь FIFO как на отправку так и на прием данных. Долго маялся с прерываниями пытаясь понять как правильно использовать SPIN блокировку. Ну, да ладно, вот только частота следования пакетов данных меня не радует, всего то 340 КГц получилась, и это при максимальном битрейте. Т.е. там между посылками получается разрыв раза в 3 превышающий длительность передачи 8 бит данных. Вот и хотелось бы посмотреть как работает встроенный в uClinux драйвер SPI, только как им правильно воспользоваться я не знаю... Если вы такое делали, поделитесь пожалуйста или подскажите как надо оформить соответствующие секции драйвера: init, exit, ioctl, read, write... С уважением, Александр... Задача у меня была рассовывать пакетики небольшого размера по контроллерам. Неставил вообще задачу оптимизации. Рекомендовал бы вам посмотреть в сторону DMA а именно сделать из них буфер дескрипторов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Exception13 0 5 августа, 2008 Опубликовано 5 августа, 2008 · Жалоба Рекомендовал бы вам посмотреть в сторону DMA а именно сделать из них буфер дескрипторов. Да, пожалуй к этому все и идет... У меня задача - плисину прогружать Virtex4, ну и потом с ней дальше общаться. Я просто не хочу изобретать велосипед, а нучиться "кататься" на том что уже есть. Если вы пользовали встроенные драйвера SPI, подскажите пожалуйста как вы это делалли ? Исходы ваших драйверов остались у вас ? Подскажите пожалуйста как надо оформить соответствующие секции своего драйвера: init, exit, ioctl, read, write... с использованием SPI драйверов поставляющихся в пакете uClinux. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MIkler 0 6 августа, 2008 Опубликовано 6 августа, 2008 · Жалоба На lkml.org информация про неплохой драйвер для 537-го. гугл вам в помощь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MIkler 0 18 августа, 2008 Опубликовано 18 августа, 2008 · Жалоба Ну и как успехи? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kekek 0 18 августа, 2008 Опубликовано 18 августа, 2008 · Жалоба Разбираюсь потихоньку с uClinux на BF537 (STAMP). Никак не въеду каким образом воспользоваться существующими в uClinux драйверами SPI. Интерфейс тривиальный, но как с ним работать из под uC - не ясно. Пытался приспособить встроенный драйвер для непрерывного чтения с АЦП. Плюнул и написал свой через ДМА. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Exception13 0 18 августа, 2008 Опубликовано 18 августа, 2008 · Жалоба Пытался приспособить встроенный драйвер для непрерывного чтения с АЦП. Плюнул и написал свой через ДМА. А можно хоть одним глазком взглянуть на реализацию. Я вот со своим драйвером все парюсь никак его корректно работать заставить не могу. Сейчас пока без DMA, реализована очередь и отправка новых данных по прерыванию. Вобщем то пока что не весело запихиваю 8 байт в очердь, наружу выплевывается только 6, да и данные там совсем не те что я отправляю. Вставлял дебаговый printk... в прерывание - он мне четко говорит то что 8 байт были отправлены. Код драйвера выложу завтра... Просто я только начинаю разрабатывать драйвера, до этого никогда ничего подобного под Linux писать не приходилось, и то как корректно обрабатывать прерывания я толком не знаю, в основном опираюсь на другие исходы... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kekek 0 21 августа, 2008 Опубликовано 21 августа, 2008 (изменено) · Жалоба А можно хоть одним глазком взглянуть на реализацию. Это тоже мой первый драйвер, есть недостатки, но он работает. За основу взял драйвер из более старой версии uClinux, немного переделал его под свои нужды. В новых версиях uClinux уже совсем другой драйвер, который имеет мало общего со старым. #include <linux/kernel.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/wait.h> #include <linux/poll.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/blackfin.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <linux/spi/spi.h> /* definitions */ #define SPI_BUF_LEN 1404 #define SPI_REGSIZE 16 #define SPI_MAJOR 252 /* experiential */ #define SPI0_MINOR 0 #define SPI_DEVNAME "spi" #define SPI_INT0NAME "spiint0" /* Should be less than 19 chars. */ #define BFIN_SPI_DEBUG 1 #ifdef BFIN_SPI_DEBUG #define PRINTK(args...) printk(args) #else #define PRINTK(args...) #endif typedef struct Spi_Device_t { int opened; int nonblock; int master; int bdrate; int channel; /* only valid in master mode */ int polar; int phase; int outenable; int irqnum; int byteorder; /* 0: MSB first; 1: LSB first; */ int recvopt; /* 0: Discard packet if Rxbuffer is full; 1: Flush Rxbuffer if it is full; */ uint8_t *bufptr; uint8_t *rxbuf; uint64_t count; uint64_t count_read; dma_addr_t addr; wait_queue_head_t* rx_wq; }spi_device_t; /* Globals */ /* We must declare queue structure by the following macro. * firstly declare 'wait_queue_head_t' and then 'init_waitqueue_head' * doesn't work in 2.4.7 kernel / redhat 7.2 */ static DECLARE_WAIT_QUEUE_HEAD(spirxq0); static spi_device_t spiinfo; #define DEFINE_SPI_REG(reg, off) \ static inline u16 read_##reg(void) \ { return *(volatile unsigned short*)(SPI0_REGBASE + off); } \ static inline void write_##reg(u16 v) \ {*(volatile unsigned short*)(SPI0_REGBASE + off) = v;\ __builtin_bfin_ssync();} DEFINE_SPI_REG(CTRL, 0x00) DEFINE_SPI_REG(FLAG, 0x04) DEFINE_SPI_REG(STAT, 0x08) DEFINE_SPI_REG(TDBR, 0x0C) DEFINE_SPI_REG(RDBR, 0x10) DEFINE_SPI_REG(BAUD, 0x14) DEFINE_SPI_REG(SHAW, 0x18) #define START_STATE ((void*)0) #define RUNNING_STATE ((void*)1) #define DONE_STATE ((void*)2) #define ERROR_STATE ((void*)-1) static irqreturn_t spi_adc_dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { clear_dma_irqstat(CH_SPI); spiinfo.count++; spiinfo.recvopt = 1; wake_up_interruptible(&spirxq0); return IRQ_HANDLED; } static ssize_t spi_adc_read(struct file *filp, char *buf, size_t count, loff_t *pos) { int ierr; /* Wait for data available */ if (spiinfo.count - spiinfo.count_read <= 1) { ierr = wait_event_interruptible(spirxq0, spiinfo.recvopt); if (ierr) /* waiting is broken by a signal */ return ierr; } else if (spiinfo.count - spiinfo.count_read > 30) { printk("spi_adc_read: %d\n", (uint32_t) (spiinfo.count - spiinfo.count_read)); return -EINVAL; } spiinfo.recvopt = 0; spiinfo.bufptr = spiinfo.rxbuf + SPI_BUF_LEN * ( spiinfo.count_read & 0x1F ); memmove(buf, spiinfo.bufptr, SPI_BUF_LEN); spiinfo.count_read++; return SPI_BUF_LEN; } static int spi_adc_ioctl(struct inode *inode, struct file *filp, uint cmd, unsigned long arg) { switch (cmd) { case CMD_SPI_SET_BAUDRATE: write_BAUD((uint16_t) arg); break; default: return -EINVAL; } return 0; } static int spi_adc_open(struct inode *inode, struct file *filp) { char intname[20]; int minor = MINOR (inode->i_rdev); /* SPI 0 ? */ if(minor != SPI0_MINOR) return -ENXIO; if(spiinfo.opened) return -EMFILE; /* Clear configuration information */ memset(&spiinfo, 0, sizeof(spi_device_t)); if(filp->f_flags & O_NONBLOCK) spiinfo.nonblock = 1; spiinfo.rx_wq = &spirxq0; spiinfo.opened = 1; spiinfo.phase = 1; spiinfo.recvopt = 0; spiinfo.bdrate = SPI_DEFAULT_BARD; spiinfo.count = 0; spiinfo.count_read = 0; strcpy(intname, SPI_INT0NAME); spiinfo.irqnum = SPI0_IRQ_NUM; write_STAT(BIT_STAT_CLR); disable_dma(CH_SPI); clear_dma_irqstat(CH_SPI); spiinfo.rxbuf = dma_alloc_coherent(NULL, SPI_BUF_LEN << 5, &spiinfo.addr, GFP_DMA); spiinfo.bufptr = NULL; bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x7c00); __builtin_bfin_ssync(); bfin_write_PORTF_FER(bfin_read_PORTF_FER() & 0xFFBF); __builtin_bfin_ssync(); bfin_write_PORTFIO_DIR(bfin_read_PORTFIO_DIR() | 0x0040); __builtin_bfin_ssync(); /*bfin_write_PORTG_FER(bfin_read_PORTG_FER() & 0xFFCF); __builtin_bfin_ssync(); bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | 0x0030); __builtin_bfin_ssync(); bfin_write_PORTGIO_SET(bfin_read_PORTGIO() | 0x0030); __builtin_bfin_ssync();*/ write_BAUD(256); write_FLAG(0xFD02); write_CTRL(0x0000); set_dma_start_addr(CH_SPI, (unsigned long) spiinfo.rxbuf); set_dma_x_count(CH_SPI, SPI_BUF_LEN); set_dma_x_modify(CH_SPI, 1); set_dma_y_count(CH_SPI, 32); set_dma_y_modify(CH_SPI, 1); dma_enable_irq(CH_SPI); set_dma_config(CH_SPI, WNR | WDSIZE_8 | DI_EN | DMAFLOW_AUTO | DI_SEL | DMA2D); enable_dma(CH_SPI); write_CTRL(CFG_SPI_DMAREAD | (CFG_SPI_ENABLE << 14)); bfin_write_PORTFIO_SET(bfin_read_PORTFIO() | 0x0040); __builtin_bfin_ssync(); return 0; } static int spi_adc_release (struct inode *inode, struct file *filp) { write_CTRL(0x0000); bfin_write_PORTFIO_CLEAR(bfin_read_PORTFIO() | 0x0040); __builtin_bfin_ssync(); /*bfin_write_PORTGIO_CLEAR(bfin_read_PORTGIO() | 0x0030); __builtin_bfin_ssync();*/ write_STAT(BIT_STAT_CLR); disable_dma(CH_SPI); dma_disable_irq(CH_SPI); clear_dma_irqstat(CH_SPI); dma_free_coherent(NULL, SPI_BUF_LEN << 5, spiinfo.rxbuf, spiinfo.addr); spiinfo.opened = 0; return 0; } static struct file_operations spi_fops = { owner: THIS_MODULE, read: spi_adc_read, ioctl: spi_adc_ioctl, open: spi_adc_open, release: spi_adc_release, }; #ifdef MODULE int init_module(void) #else int __init spi_init(void) #endif /* MODULE */ { int result; printk("spi0: INIT\n"); result = register_chrdev(SPI_MAJOR, "spi", &spi_fops); if (result < 0) { printk(KERN_WARNING "spi0: can't get minor %d\n", SPI_MAJOR); return result; } if(request_dma(CH_SPI, "BF53x_SPI_DMA") < 0) { PRINTK("Unable to request BlackFin SPI DMA channel\n"); return -ENODEV; } set_dma_callback(CH_SPI, (void*)spi_adc_dma_irq_handler, &spiinfo); dma_disable_irq(CH_SPI); return 0; } #ifdef MODULE void cleanup_module(void) #else void spi_uninit(void) #endif /* MODULE */ { unregister_chrdev(SPI_MAJOR, SPI_DEVNAME); printk("<1>Goodbye spi \n"); } module_init(spi_init); module_exit(spi_uninit); Изменено 21 августа, 2008 пользователем Kekek Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Exception13 0 22 августа, 2008 Опубликовано 22 августа, 2008 · Жалоба Большое спасибо, буду разбираться. Вот то, что у меня сейчас получилось. Драйвер SPI для режима master/slave, поддерживается передача данных как 8, так и 16 битными словами. bfin_spi.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться