Jump to content

    
Sign in to follow this  
R6L-025

Управление периферией HPS из под OS

Recommended Posts

Доброго времени суток!

Недавно начал ковырять альтеровский SoC, в связи с чем возник довольно глупый вопрос - как правильно работать с периферией HPS из под OS (linux)?

Например пробовал поднять контроллер SPI. Пробовал из под userspace вручную управлять его регистрами - ничего хорошего не получилось.

Правильно ли я понимаю что самый корректный способ в данном случае работа с драйвером? Или есть иные решения?

И поможет ли чем альтеровская HWLIB при работе из под OS? Как я понял она больше рассчитана на работу с baremetal, да и в сорцах альтеровских драйверов я не встречал упоминаний о ней.

Share this post


Link to post
Share on other sites
Недавно начал ковырять альтеровский SoC, в связи с чем возник довольно глупый вопрос - как правильно работать с периферией HPS из под OS (linux)?

Например пробовал поднять контроллер SPI. Пробовал из под userspace вручную управлять его регистрами - ничего хорошего не получилось.

а вы работу узла SPI в прелоадере разрешили?

если разрешили, то через обычный mmap все должно работать, т.к. через драйвер линукса работает, но с заморочным CS

Share this post


Link to post
Share on other sites

to Jury093

Извиняюсь, немного недопонял, что Вы подразумеваете под "разрешением работы узла в прелоадере"? Я пытался адаптировать example для SPI отсюда:

https://www.altera.com/support/support-reso...amples/soc.html

Но этот пример ориентирован под baremetall. В нем используется последовательность функций из HWLIB для инициализации контроллера SPI, контрллера прерываний и пр., но под OS это по идее и не нужно. (я скопипастил оттуда ту часть которая отвечает только за работу SPI, выдрал часть кода из HWLIB, подправил так, чтоб работало с виртуальными а не физическими адресами, но в итоге получил частоту SCLK вместо 2 МГц около 100, и почему то принятые данные всегда были в нулях :rolleyes: ).

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

Share this post


Link to post
Share on other sites
Извиняюсь, немного недопонял, что Вы подразумеваете под "разрешением работы узла в прелоадере"? Я пытался адаптировать example для SPI отсюда:

видимо я неудачно выразился.. под прелоадером имеется в виду u-boot, который состоит из двух этапов - прелоадер и собственно u-boot

а начальная конфигурация узлов в т.ч. и SPI производится из оболочки Qsys из-под Quartus

т.о. Qsys формирует хидеры с настройками, на основе которых u-boot настраивает периферию HPS

 

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

в линуксе? желательно по законам линукса, конечно.. со спецификой embedded

если совсем прямой путь - в Qsys включили SPI, в ядре разрешили SPI и свой чип, в dts прописали SPI и свой чип, далее после перезагрузки, если все корректно и правильно, то получили канал или устройство в /dev, далее софт для пользователя..

если хочется экстрима/нестандарта, то на любом этапе после u-boot перехватываете и самостоятельно пишете всё, что касается обмена с SPI ну и сервис в сторону пользователя..

 

Share this post


Link to post
Share on other sites

Да, в Qsys все описано, в ядре поддержка SPI включена, он даже видится в /dev. Если с драйвером работать то осталось только разобраться как им рулить. Было интересно как вообще управление железом делается. По видимому да, самое логичное наитивными для OS путями - через драйвер)

Share this post


Link to post
Share on other sites
Да, в 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 уже не получится - такие вещи делают через драйвер..

Share this post


Link to post
Share on other sites
SPI не может "видится" в /dev, обычно он представлен устройством на канале или /dev/spidevX.X

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

В целом понятно, спасибо! :)

Share this post


Link to post
Share on other sites

Да, спасибо, сейчас в этом и копаюсь. Собственно, чтение/запись через отображение на память получилось, хочу попробовать простые модули пособирать

Share this post


Link to post
Share on other sites

Возвращаясь к этой теме - заметил не понятную для меня особенность.

Использую 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. при конфигурации сети использовал дефолтные настройки

Share this post


Link to post
Share on other sites
Кто нибудь сталкивался с подобным поведением? Можете скинуть рабочий .config с произвольной версией?

Я использую ядро 4.1.22-ltsi+ отсюда: https://github.com/altera-opensource/linux-socfpga.git

config.txt

Собирал все (ядро и модуль) кросс-компилятором 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 бит

	
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

Используемые константы.

// 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. Иначе перефирия может работать некорректно или совсем не работать.

 

Share this post


Link to post
Share on other sites

bugdesigner, спасибо! Попробую собрать с Вашей конфигурацией. У меня, собственно, тоже используется u-boot для заливание битстрима, хотя хотелось бы прикрутить к проекту возможность перепрошивки из под OS.

Отдельное спасибо за код модуля. Попробую реализовать, если с встроенным не выйдет. Если честно, пока в kernel space ничего не писал, поэтому хотелось встроенный поднять.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this