Category: программирование

Окт 02 2015

Драйвер для Linux: первый шаг

Продолжаю эксперименты с Altera Cyclone V. На этот раз объектом эксперимента стал драйвер для той прошивки FPGA, про которую я писал ранее. Сама прошивка простейшая: она просто мигает светодиодами с частотой, которую можно задавать программно. В прошлом посте на эту тему я сделал управление частотой мигания из обычной (user-space) программы, которая получает доступ к физической памяти через функции open(«/dev/mem») и mmap().
Однако такой путь считается «hacky and unsafe». Поэтому следующим логичным шагом должно стать написание драйвера.

Tux-linux-and-ARM-multiplatform-support

Я воспользовался готовым исходником драйвера (ссылка) за авторством Howard Mao (он на самом деле не Howard, а Zhe Hao Mao). Конечно, для того, чтобы разобраться в работе кода, почитал отдельные главы книги Linux Device Drivers (есть русский перевод).

Для компиляции пришлось вытаскивать архив Arrow SocKit 13.1 GSRD Linux отсюда: http://releases.rocketboards.org/release/2013.11/gsrd/src, файл linux-socfpga-gsrd-13.1-src.bsx. Объем архива около 1.1 Гб, но сервер очень медленный, качается несколько часов. Честно говоря, я впервые увидел файл с расширением bsx, оказалось, что это самораспаковывающийся архив. Просто запускаем его и он разворачивается в указанную папку. В ней в папке sources находится файл linux-socfpga.tgz. Его тоже нужно распаковать, естественно. Это и есть как таковое ядро системы, которое нужно указывать при компиляции драйвера.

Однако всё не так просто. После компиляции записываем скомпилированный драйвер blinker.ko на SD-карту, после загрузки Linux пишем insmod blinker.ko и получаем следующее: «blinker: version magic ‘3.9.0-00161-ged01b8c SMP mod_unload ARMv7 p2v8 ‘ should be ‘3.9.0 SMP mod_unload ARMv7 p2v8’«. Не совпали волшебные номерки. Причем версия одна и та же, просто зачем-то к ней приделан какой-то добавочный номер.

Решений может быть три: 1. Скомпилировать Linux именно из этого скачанного исходника (очень неохота) или 2. Подправить номер в исходниках ядра Linux. 3. Использовать команду modprobe с ключом -f, который заставляет систему игнорировать «волшебные цифры».  Однако этот способ почему-то не заработал.
Итак, способ номер 2, подправить номер в исходнике ядра. Данный номер записан в файле /include/generated/utsrelease.h. Исправляем то, что там было, на «3.9.0», и перекомпилируем драйвер. На всякий случай смотрим hex-редактором файл blinker.ko, чтобы убедиться, что волшебные циферки такие, как нужно. Снова записываем драйвер на SD-карту, запускаем insmod, всё прошло гладко. Теперь можно проверить работу драйвера, посылая ему числа от 1 до 15 для управления частотой миганий: echo 1 > blinker — мигает быстро, echo 15 > blinker — мигает медленно. Пока всё. Немного, но путь в тысячу ли начинается с одного шага.

Эксперименты продолжаются.

Сен 23 2015

Управление FPGA из программы

Приведённый ниже код писал не я, он взят отсюда: https://zhehaomao.com/blog/fpga/2013/12/27/sockit-3.html, но я решил оставить его здесь, т.к. он пригодится для дальнейших экспериментов.

Напоминаю, что данная программа работает в ОС Linux GSRD на SoC Altera Cyclone V (ядро ARM Cortex A9). Компилятор Linaro GCC, берём здесь: http://releases.linaro.org/latest/components/toolchain/binaries/4.8/arm-linux-gnueabihf/

#include ;
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PAGE_SIZE 4096
#define LWHPS2FPGA_BRIDGE_BASE 0xff200000
#define BLINK_OFFSET 0x0

volatile unsigned char *blink_mem;
void *bridge_map;

int main(int argc, char *argv[])
{
	int fd, ret = EXIT_FAILURE;
	unsigned char value;
	off_t blink_base = LWHPS2FPGA_BRIDGE_BASE;

	if (argc < 2) {
		fprintf(stderr, "Usage: %s number\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	/* check the bounds of the value being set */
	value = atoi(argv[1]);
	if (value < 1 || value > 15) {
		fprintf(stderr, "Invalid delay setting."
				"Delay must be between 1 and 15, inclusive.\n");
		exit(EXIT_FAILURE);
	}

	/* open the memory device file */
	fd = open("/dev/mem", O_RDWR|O_SYNC);
	if (fd < 0) {
		perror("open");
		exit(EXIT_FAILURE);
	}

	/* map the LWHPS2FPGA bridge into process memory */
	bridge_map = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED,
				fd, blink_base);
	if (bridge_map == MAP_FAILED) {
		perror("mmap");
		goto cleanup;
	}

	/* get the delay_ctrl peripheral's base address */
	blink_mem = (unsigned char *) (bridge_map + BLINK_OFFSET);

	/* write the value */
	*blink_mem = value;

	if (munmap(bridge_map, PAGE_SIZE) < 0) {
		perror("munmap");
		goto cleanup;
	}

	ret = 0;

cleanup:
	close(fd);
	return ret;
}

Программа управляет частотой мигания светодиода, сам делитель частоты расположен в FPGA, частота задаётся регистром.

Read more »

Сен 11 2015

Книга Mayur Pandey, Suyog Sarda «LLVM Cookbook»

Прочитал книгу Mayur Pandey, Suyog Sarda «LLVM Cookbook», 284 стр, англ. язык.
Хорошая книга, описывает много интересных вещей об архитектуре и внутреннем устройстве инфраструктуры компиляторов LLVM.
Она дополняет другую книгу, «Getting Started with LLVM Core Libraries», про которую я уже писал. Кстати,  Getting Started with LLVM Core Libraries переведена на русский язык и сейчас есть в продаже (я читал в оригинале).

5981OS_LLVM Cookbook

Сен 05 2015

Книга Р. Лав «Разработка ядра Linux» (второе издание)

Прочитал книгу «Разработка ядра Linux», автор Р. Лав.

В книге подробно описывается внутренняя структура ядра Linux.

346326_razrabotka_yadra_linux

 

Книга, без сомнения, достойна прочтения, если вы занимаетесь разработкой модулей ядра.

Авг 25 2015

Книга Р. Лав «Linux. Системное программирование»

Прочитал книгу Р. Лав «Linux. Системное программирование».
В книге описывается ряд системных вызовов для работы с файлами, процессами, временем, сигналами и распределением памяти. Приводятся сведения о работе этих вызовов по стандарту POSIX и по их реализации в ядре Linux.

3a56606f29e71f3a51b8c5fdd1d

Авг 14 2015

Книга B. Stroustrup «A Tour of C++»

Прочитал книгу B. Stroustrup «A Tour of C++», Addison-Wesley, 2013, 180 стр, англ. язык.

51xVLzxX4vL._SX370_BO1,204,203,200_

Книга не является ни учебником по С++, ни полным справочником по С++, это именно «тур», обзор основных возможностей С++11, причем и тех, которые были в стандарте С++98, и новых. Рекомендую прочитать тем, кто знает язык, но хочет усовершенствовать эти знания.

Авг 06 2015

Книга Scott Meyers «Effective Modern C++»

Прочитал книгу Scott Meyers «Effective Modern C++», O’Reilly Media, 2014 г., 336 стр, англ. язык.

c38858a6d6b8

Замечательная книга, одна из лучших, которые я читал по С++.

Во-первых, описывается современный стандарт С++11/С++14. С введением нового стандарта в 2011 году С++ стал совершенно другим, новым языком, как это отмечает и его автор, Б. Страуструп. Книги по С++, изданные до 2011 года, сейчас читать практически не имеет смысла.

Во-вторых, у Мейерса подход к изложению гораздо более практический, чем у Страуструпа. Страуструп описывает язык с формальной точки зрения, перечисляет операторы, конструкции языка, синтаксис. Мейерс рассматривает новые возможности языка с точки зрения их применения на практике, рассматривает «подводные камни» и сложные места, предупреждает об опасностях, которые могут крыться в коде.

Следует заметить, что книга не предназначена для чтения «с нуля», она подразумевает, что читатель знает С++98. Начинающим «с нуля» могу порекомендовать книгу Шилдт «С++ Базовый курс«.

Рекомендую всем, кто любит С++.

Июл 28 2015

SoCKit Lab Instructions

Прочитал и освоил на практике воркбенч SoCKit Lab, две части, Hardware и Software.
Данная программа лабораторных работ основана на системе на кристалле (SoC) Altera Cyclone V. SoC состоит из двух процессорных ядер ARM Cortex A9 и FPGA, которые соединены мостами и могут взаимодействовать друг с другом. Первое руководство, Hardware, выполняется в Quartus II, и описывает конфигурирование и подключение периферии к процессору, а также симуляцию системы в ModelSim.
Вторая часть, Software, описывает процесс загрузки Linux, компиляцию простейшей программы (мигание светодиодом), отладку программы в ARM DS-5 Embedded Development Suite, и основы работы с SignalTap II Logic Analyzer в режиме совместной отладки программного кода и FPGA-проекта.

pic1

Июн 29 2015

Статья «Ten C++11 Features Every C++ Developer Should Use»

Прочитал статью «Ten C++11 Features Every C++ Developer Should Use», автор Marius Bancila, ссылка: http://www.codeproject.com/Articles/570638/Ten-Cplusplus-Features-Every-Cplusplus-Developer. Весьма интересно и познавательно. Я, конечно, основные моменты знал и ранее, но после прочтения познания в C++11 несколько упорядочились.
Вообще, www.codeproject.com — хороший сайт, надо почаще заглядывать.

Июн 21 2015

Генерация файлов .mif и case-конструкций

Пусть в проекте FPGA необходимо ПЗУ, в которое записана определённая информация, имеющаяся у нас в виде бинарного файла. ПЗУ, как правило, реализуются на блоках BRAM, в которые при инициализации FPGA записывается требуемое содержимое.
Файлы инициализации памяти BRAM для FPGA, могут иметь формат MIF (Memory Initialization File) или формат HEX.

DSC_0522_EDIT

Нужный модуль памяти можно сгенерировать в Quartus II с помощью MegaWizard, в ISE — с помощью Xilinx Core Generator. Кроме этого, в QuartusII возможно использование специальной директивы:

reg [7:0] mem[0:2047] /* synthesis ram_init_file = "test.mif" */;

Эта директива позволяет создать RAM, инициированную значениями из файла .MIF. Использование RAM с предустановленными значениями, это очень плохая идея, но в качестве ROM такую память использовать вполне можно. Проблема в том, что эту директиву понимает только Quartus II, никакой кроссплатформенности.

Quartus II предоставляет редактор файлов памяти, и возможность загрузки файлов .mif и .hex, Xilinx Core Generator требует загрузки файла .coe, имеющего другой формат, нежели MIF. Однако хочется иметь кроссплатформенное решение, которое не зависело бы от платформы. Таким вариантом является генерация ROM в виде case-конструкции:

always@(posedge clk)
begin
  case(in)
  ...
  11'h00d: out = 8'h99;
  11'h00e: out = 8'h81;
  11'h00f: out = 8'h7e;
  11'h010: out = 8'h7e;
  11'h011: out = 8'hff;
  11'h012: out = 8'hdb;
  11'h013: out = 8'hff;
  11'h014: out = 8'hc3;
  11'h015: out = 8'he7;
  11'h016: out = 8'hff;
  ...
  endcase
end

Полезная ссылка: различные конструкции для генерации разных типов RAM, ROM и других модулей можно найти в руководстве Altera «Recommended HDL Coding Styles»: https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/qts/qts_qii51007.pdf
Я написал две простые утилиты, которая преобразует бинарный файл в MIF и в тело конструкции case.

Read more »