Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Управление периферией HPS из под OS
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
R6L-025
Доброго времени суток!
Недавно начал ковырять альтеровский SoC, в связи с чем возник довольно глупый вопрос - как правильно работать с периферией HPS из под OS (linux)?
Например пробовал поднять контроллер SPI. Пробовал из под userspace вручную управлять его регистрами - ничего хорошего не получилось.
Правильно ли я понимаю что самый корректный способ в данном случае работа с драйвером? Или есть иные решения?
И поможет ли чем альтеровская HWLIB при работе из под OS? Как я понял она больше рассчитана на работу с baremetal, да и в сорцах альтеровских драйверов я не встречал упоминаний о ней.
Jury093
Цитата(R6L-025 @ Aug 29 2016, 09:01) *
Недавно начал ковырять альтеровский SoC, в связи с чем возник довольно глупый вопрос - как правильно работать с периферией HPS из под OS (linux)?
Например пробовал поднять контроллер SPI. Пробовал из под userspace вручную управлять его регистрами - ничего хорошего не получилось.

а вы работу узла SPI в прелоадере разрешили?
если разрешили, то через обычный mmap все должно работать, т.к. через драйвер линукса работает, но с заморочным CS
R6L-025
to Jury093
Извиняюсь, немного недопонял, что Вы подразумеваете под "разрешением работы узла в прелоадере"? Я пытался адаптировать example для SPI отсюда:
https://www.altera.com/support/support-reso...amples/soc.html
Но этот пример ориентирован под baremetall. В нем используется последовательность функций из HWLIB для инициализации контроллера SPI, контрллера прерываний и пр., но под OS это по идее и не нужно. (я скопипастил оттуда ту часть которая отвечает только за работу SPI, выдрал часть кода из HWLIB, подправил так, чтоб работало с виртуальными а не физическими адресами, но в итоге получил частоту SCLK вместо 2 МГц около 100, и почему то принятые данные всегда были в нулях rolleyes.gif ).
Собственно сам вопрос больше не о том как конкретно с SPI работать, а как вообще считается корректно работать с подобной периферией.
Jury093
Цитата(R6L-025 @ Aug 29 2016, 14:26) *
Извиняюсь, немного недопонял, что Вы подразумеваете под "разрешением работы узла в прелоадере"? Я пытался адаптировать example для SPI отсюда:

видимо я неудачно выразился.. под прелоадером имеется в виду u-boot, который состоит из двух этапов - прелоадер и собственно u-boot
а начальная конфигурация узлов в т.ч. и SPI производится из оболочки Qsys из-под Quartus
т.о. Qsys формирует хидеры с настройками, на основе которых u-boot настраивает периферию HPS

Цитата
Собственно сам вопрос больше не о том как конкретно с SPI работать, а как вообще считается корректно работать с подобной периферией.

в линуксе? желательно по законам линукса, конечно.. со спецификой embedded
если совсем прямой путь - в Qsys включили SPI, в ядре разрешили SPI и свой чип, в dts прописали SPI и свой чип, далее после перезагрузки, если все корректно и правильно, то получили канал или устройство в /dev, далее софт для пользователя..
если хочется экстрима/нестандарта, то на любом этапе после u-boot перехватываете и самостоятельно пишете всё, что касается обмена с SPI ну и сервис в сторону пользователя..
R6L-025
Да, в Qsys все описано, в ядре поддержка SPI включена, он даже видится в /dev. Если с драйвером работать то осталось только разобраться как им рулить. Было интересно как вообще управление железом делается. По видимому да, самое логичное наитивными для OS путями - через драйвер)
Jury093
Цитата(R6L-025 @ Aug 30 2016, 09:08) *
Да, в Qsys все описано, в ядре поддержка SPI включена, он даже видится в /dev. Если с драйвером работать то осталось только разобраться как им рулить.

SPI не может "видится" в /dev, обычно он представлен устройством на канале или /dev/spidevX.X
смотрите в исходниках драйвера - чем он занимается и что создает в системе

Цитата
Было интересно как вообще управление железом делается. По видимому да, самое логичное наитивными для OS путями - через драйвер)

поищите в разделе OS->linux треды, там где-то выкладывались названия литературы - устройство линукса, линукс для чайников, линукс и драйверы..
возможно на местном фтп они есть или в сети

напрямую к железу HPS можно обратиться примерно так (прописав адреса HPS и имея права на доступ)
Код
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
{
printf("Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}
printf("/dev/mem opened.\n");
mapped_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, MAP_BASE & ~MAP_MASK);
if (mapped_base == (void *) -1)
{
printf("Memory mapping error.\n");
exit(EXIT_FAILURE);
}
mapped_base+=(MAP_BASE & MAP_MASK);
printf("Target address mapped 0x%08x-->0x%08x\n",(int) MAP_BASE,(int)mapped_base);
// -----------------------------------------------------------------------
printf("GPIOH_DIR=%08X\n", GPIOH_DIR);

но это чисто почитать/пописать в регистры, задействовать, например, прерывания или DMA уже не получится - такие вещи делают через драйвер..
R6L-025
Цитата
SPI не может "видится" в /dev, обычно он представлен устройством на канале или /dev/spidevX.X

Я и подразумевал, что он представлен как устройство в /dev каталоге.
В целом понятно, спасибо! sm.gif
R6L-025
Да, спасибо, сейчас в этом и копаюсь. Собственно, чтение/запись через отображение на память получилось, хочу попробовать простые модули пособирать
R6L-025
Возвращаясь к этой теме - заметил не понятную для меня особенность.
Использую DE-0 SoC Nano. Конфигурирую ядро наподобие описания здесь https://rocketboards.org/foswiki/view/Docum...xBeginnerSGuide , с версией ядра 4.1 (как там и указано).
В этом случае у меня работает FPGA manager, но не работает Ethernet, если использовать ядро 4.4 - то все наоборот. При этом SPI не запускается вообще. Если использовать скомпиленный example от Terasic все работает хорошо.
Пытался сравнивать содержание файла .config версий ядра 4.1 и 4.4 - особых отличий не нашел.
Кто нибудь сталкивался с подобным поведением? Можете скинуть рабочий .config с произвольной версией?


P.S. при конфигурации сети использовал дефолтные настройки
bugdesigner
Цитата(R6L-025 @ Oct 28 2016, 16:11) *
Кто нибудь сталкивался с подобным поведением? Можете скинуть рабочий .config с произвольной версией?

Я использую ядро 4.1.22-ltsi+ отсюда: https://github.com/altera-opensource/linux-socfpga.git
Нажмите для просмотра прикрепленного файла
Собирал все (ядро и модуль) кросс-компилятором arm-none-eabi-gcc версии 4.8.4 на Debian 8.1.
По поводу fpga manager не могу ничего сказать, я его не использую, тк мой проект использует DMA через fpga2sdram и поэтому битстрим загружается бутлоадером u-boot.
С ethernet проблем не обнаружено.
Что касается SPI. Я "завернул" сигналы SPI0 master в FPGA, чтоб потом вывести их на разъем DE0-Nanao. Такой метод дополнительно позволяет получить контроль над 4 выводами SS.
Я не использовал драйверов SPI из ядра, а написал свой модуль - так мне удобней. Сейчас у меня через SPI управляется 3 устройства - 2 DAC и DDS. DAC получает 16-битные команды, а DDS 32-битные.
Вот пример кода для 32 бит
CODE

static void __iomem *SPI0;
// ---8<---- from module init
request_mem_region(SPIM0_ADDR, SPIM0_LEN, DRV_NAME);
SPI0 = ioremap(SPIM0_ADDR, SPIM0_LEN);
// ---8<----

// initialize SPI0
iowrite32(0, SPI0+SPIM_SPIENR_OFF); // Disable SPI0
iowrite32(0x1CF, SPI0+SPIM_CTRLR0_OFF); // TxOnly, scpol=1 scph=1 length=16 bit
iowrite32(0, SPI0+SPIM_CTRLR1_OFF);
iowrite32(0, SPI0+SPIM_SER_OFF); // Disable All SS
iowrite32(100, SPI0+SPIM_BAUDR_OFF); // set baudrate
iowrite32(1, SPI0+SPIM_SPIENR_OFF); // Enable SPI0
// sending data
iowrite16((value >> 16) & 0xFFFF, SPI0+SPIM_DR_OFF);
iowrite16(value & 0xFFFF, SPI0+SPIM_DR_OFF);

iowrite32(2, SPI0+SPIM_SER_OFF); // Enable SS1
udelay(5);
while(ioread32(SPI0+SPIM_SR_OFF) & 1); //wait for busy==0
iowrite32(0, SPI0+SPIM_SER_OFF); // Disable All SS


Используемые константы.
CODE
// SPIMx registers
#define SPIM0_ADDR 0xFFF00000
#define SPIM0_LEN 0x1000
#define SPIM1_ADDR 0xFFF01000
#define SPIM1_LEN 0x1000
//
#define SPIM_CTRLR0_OFF 0x00
#define SPIM_CTRLR1_OFF 0x04
#define SPIM_SPIENR_OFF 0x08
#define SPIM_MWCR_OFF 0x0C
#define SPIM_SER_OFF 0x10
#define SPIM_BAUDR_OFF 0x14
#define SPIM_TXFTLR_OFF 0x18
#define SPIM_RXFTLR_OFF 0x1C
#define SPIM_TXFLR_OFF 0x20
#define SPIM_RXFLR_OFF 0x24
#define SPIM_SR_OFF 0x28
#define SPIM_IMR_OFF 0x2C
#define SPIM_ISR_OFF 0x30
#define SPIM_RISR_OFF 0x34
#define SPIM_TXOICR_OFF 0x38
#define SPIM_RXOICR_OFF 0x3C
#define SPIM_RXUICR_OFF 0x40
#define SPIM_ICR_OFF 0x48
#define SPIM_DMACR_OFF 0x4C
#define SPIM_DMATDLR_OFF 0x50
#define SPIM_DMARDLR_OFF 0x54
#define SPIM_DR_OFF 0x60

Подробно о регистрах и режимах написано в документе Cyclone V HPS TRM.
Если есть какие-либр вопросы - пишите.

Важный момент: при любом изменении в настройках HPS (которые вы делаете в Qsys) нужно пересобирать preloader! Те запускать bsp-editor, потом make. Иначе перефирия может работать некорректно или совсем не работать.
R6L-025
bugdesigner, спасибо! Попробую собрать с Вашей конфигурацией. У меня, собственно, тоже используется u-boot для заливание битстрима, хотя хотелось бы прикрутить к проекту возможность перепрошивки из под OS.
Отдельное спасибо за код модуля. Попробую реализовать, если с встроенным не выйдет. Если честно, пока в kernel space ничего не писал, поэтому хотелось встроенный поднять.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.