Ник:
Пароль:

Контакты

Cтатус Skype: starterkit.ru
тел.: (+7 3412) 478-448
тел.: +7 922 680-21-73
тел.: +7 922 680-21-74
E-mail: info@starterkit.ru
Google+
Партнеры:
otladka.com.ua - г.Киев
tixer.ru - г.Москва

Способы оплаты

User Info


Добро пожаловать,
Guest

Регистрация или входРегистрация или вход
Потеряли пароль?Потеряли пароль?

Ник:
Пароль:

ПользователейПользователей:0
Поисковых ботовПоисковых ботов:2
ГостейГостей:1

ОбновитьПодробнееВсегоВсего:3
Форум » starterkit.ru » FPGA
Конфигурация ПЛИС при помощи ARM
efreet
Добавлено 01.07.2010 23:00 Редактировалось 01.07.2010 23:16 Сообщение: 11
efreet
0

Пункты: 464
Регистрация: 08.02.2010
Хм, странно, у меня без "больше синхроимпулсов, чем количество бит в прошивке" не заливается, вернее, не проходит фаза startup (то есть не сбрасывается в 0 INIT_B и не устанавливается в 1 DONE). Причем не проходит, даже если импульсы слать, но с DIN, установленным в 0.

Насчет .bit - мой заливается, но, похоже, он действительно сгенерирован так, что не требует CRC. Как проверю - напишу. В теории CRC проверяется только для данных начиная со слова синхронизации, то есть минуя заголовок битника.

UPD Сгенерировал .bit из проекта, поставляемого с платой, проверил, чтобы была включена CRC, - битник залился.
Спуститься к концу Подняться к началу
Персональная информация
BAMB
Добавлено 17.07.2010 15:02 Сообщение: 12
BAMB
5

Пункты: 341
Регистрация: 14.07.2010
Доброго времени суток, уважаемые efreet и erma. Не могли бы вы мне объяснить исходник конфигурации ПЛИС. На сколько я понял, то для компиляции вполне хватает хедеров board.h (arm\src\flashloader\Atmel\at91lib\boards\at91sam9260-ek) и pio.h (arm\src\flashloader\Atmel\at91lib\peripherals\pio),в IAR никаких проблем с этим не возникло).
Перенес код на плату и мой arm-linux-gnu-gcc при компиляции выдает всякую непотребщину. Подскажите какие хедеры нужно использовать с GCC?(Я сним только начинаю работать).
Насколько я понимаю, для того чтобы сделать из этого драйвер нужно:
1.Создать модуль - Makefile типа такого:
EXTRA_CFLAGS = -Wall -O2
ifneq ($(KERNELRELEASE),)
obj-m := XXXXX.o
else
PWD := $(shell pwd)
ifneq ($(MAKECMDGOALS),clean)
feq ($(ARCH),)
$(error Run using make ARCH=arm CROSS_COMPILE=Путь к компилятору
KERN_DIR=путь к исходникм ядра
Missing ARCH)
endif
ifeq ($(CROSS_COMPILE),)
$(error Run using make ARCH=arm CROSS_COMPILE=Путь к компилятору
KERN_DIR=путь к исходникм ядра.
Missing CROSS_COMPILE)
endif
ifeq ($(KERN_DIR),)
$(error Run using make ARCH=arm CROSS_COMPILE=Путь к компилятору
KERN_DIR=путь к исходникм ядра.
Missing KERN_DIR)
endif
endif
default:
$(MAKE) -C $(KERN_DIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.symvers .tmp_versions
endif
2.Написать скрипт загрузки драйвера.
Поправте,если что не так
Спуститься к концу Подняться к началу
Персональная информация
leen
Добавлено 28.09.2010 09:10 Сообщение: 13
leen
0

Пункты: 623
Регистрация: 29.12.2009
Пол: Мужчина
Здравствуйте, все.
Помогите найти ошибку в процедуре конфигурации ПЛИС.
Имеется плата SK-AT91SAM9XE512-S3E с контроллером AT91SAM9260. При конфигурации в режиме slave serial вывод DONE ПЛИС не поднимается. В опциях генератора файла прошивки указано: drive DONE pin HIGH, disable internal pipe (хотя разрешена или запрещена последняя опция - не влияет). При заливке по JTAG с зажатым ресетом контроллера ПЛИС исправно запускается.
На контроллере запущен линукс с корневой ФС на microSD карте. Соединил дополнительно вывод INIT_B ПЛИС и PC11 контроллера (чтобы из дравера следить за правильностью CRC и различать когда можно дить конфигурацию).
Написал драйвер, заливающий в ПЛИС прошивку по такому алгоритму:
в инициализации драйвера (после команды insmod) выводы DIN, CCLK - выходы с записанной в них 1, PROG_B, DONE и INIT_B - выводы с открытым стоком и записанной в них 1, т.е. уровни на этих линиях задает ПЛИС.
Затем PROG_B опускается в 0 на 1 мкс (по осциллографу).
Ждем, пока INIT_B у ПЛИСС не перейдет в 1 (около 150 - 200 мкс).
Выход из инициализации драйвера.

Затем происходит запись из bin файла в ПЛИС. Производится это программой cat, копирующей побайтно из файла прошивки в драйвер.
В функции записи драйвера запись принятых данных происходит MSB first. Если файл некорректен (скажем, я дописал в него пару символов), то по окончании заливки файла вывод INIT_B ПЛИС опускается в 0. Если же файл корректный, INIT_B после окончания файла прошивки остается в 1.
При выгрузке драйвера в ПЛИС записываю еще 8 единичных бит, выполняя требование мануала UG332. Но вывод DONE не поднимается. Что я делаю не так?
Спуститься к концу Подняться к началу
Персональная информация
efreet
Добавлено 28.09.2010 11:02 Редактировалось 28.09.2010 11:17 Сообщение: 14
efreet
0

Пункты: 464
Регистрация: 08.02.2010
Судя по всему дело в том, что Startup sequence занимает больше синхроимпульсов, чем 8. Сейчас платы под рукой нет, но глянув свой код, обнаружил, что посылаю импульсы с DIN=1 до тех пор, пока DONE не выставится в 1. А уже после этого дополнительно посылаются 8 импульсов, кажется.
Спуститься к концу Подняться к началу
Персональная информация
leen
Добавлено 28.09.2010 12:24 Редактировалось 28.09.2010 12:28 Сообщение: 15
leen
0

Пункты: 623
Регистрация: 29.12.2009
Пол: Мужчина
так я тоже пробовал, DONE не выставляется даже если пару секунд посылать клюки (до 8М). При этом данные не имеют значение - 0, 1 или вперемешку.
Т.е. после окончания прошивки послать 8 или 8000000 клоков - разницы не увидел. В конце стоял цикл:
прочитать DONE и INIT,
если INIT == 1 и DONE == 0,
записать (от 8 до 1024 в разных билдах) бит (разных данных),
если записано уже много (до 8Мбит), прервать цикл,
и по новой.
а после него еще 8 бит писал.
Просто, не увидев результата и разницы, я заремил этот цикл.
Частоту менял от 200 кГц до 2 МГц. Без изменений.
Спуститься к концу Подняться к началу
Персональная информация
efreet
Добавлено 28.09.2010 13:44 Сообщение: 16
efreet
0

Пункты: 464
Регистрация: 08.02.2010
Я пишу вот так:

Код
*(int*)(mapped_base+PIO_PER) = PROG_B|DIN|CCLK|DONE;
*(int*)(mapped_base+PIO_OER) = PROG_B|DIN|CCLK;

*(int*)(mapped_base+PIO_CODR) = PROG_B;
usleep(1);
*(int*)(mapped_base+PIO_SODR) = PROG_B;
usleep(3000);
for(count=0;count<fsize;count++)
{
buf=bstr[count];
for(i=7;i>=0;i--)
{
fl=1<<i;
fl&=buf;
if(fl!=0)
{
*(int*)(mapped_base+PIO_SODR) = DIN;
}
else
{
*(int*)(mapped_base+PIO_CODR) = DIN;
}
*(int*)(mapped_base+PIO_SODR) = CCLK;
*(int*)(mapped_base+PIO_CODR) = CCLK;
}
}
*(int*)(mapped_base+PIO_SODR) = DIN;
pdsr=*(int*)(mapped_base+PIO_PDSR);
while(!(pdsr&DONE))
{
*(int*)(mapped_base+PIO_SODR) = CCLK;
*(int*)(mapped_base+PIO_CODR) = CCLK;
pdsr=*(int*)(mapped_base+PIO_PDSR);
}
*(int*)(mapped_base+PIO_PDR) = DIN;


А можно взглянуть на Ваш код?
Спуститься к концу Подняться к началу
Персональная информация
leen
Добавлено 28.09.2010 14:36 Редактировалось 28.09.2010 14:38 Сообщение: 17
leen
0

Пункты: 623
Регистрация: 29.12.2009
Пол: Мужчина
Спасибо за ответы.
Если вкратце - то же самое, завтра с работы выложу.
различие в том, что я не 3 мс жду, а поллю флаг INIT, допаянный с ПЛИС к контроллеру. Также все выводы разворачиваю на выход (кстати, здесь может и вылезти ошибка), но INIT, PROG и DONE - ставлю открытый сток и пишу 1.
Ну и совершенно неважные вещи типа с 0 до 8 или с 8 до 0 вести цикл:
Код
for (j = 0; j < 8; j++)
{
if (byte&0x80) at91_sys_write(PIO_C + PIO_SODR, DIN_PIN);
else at91_sys_write(PIO_C + PIO_CODR, DIN_PIN);
for (k = 0; k < WIDTH; k++) // замедлитель частоты заливки
at91_sys_write(PIO_C + PIO_CODR, CCLK_PIN);
for (k = 0; k < WIDTH; k++) // 1 <= WIDTH <= 1024
at91_sys_write(PIO_C + PIO_SODR, CCLK_PIN);
}

// написал по памяти.
Спуститься к концу Подняться к началу
Персональная информация
leen
Добавлено 29.09.2010 04:05 Редактировалось 29.09.2010 04:51 Сообщение: 18
leen
0

Пункты: 623
Регистрация: 29.12.2009
Пол: Мужчина
Вот мой исходник (незначимые части и инициализацию драйвера вырезал, т.к. пользовался работоспособной заготовкой):
Код

#define PROG_B_PIN AT91_PC9 // out
#define DIN_PIN AT91_PC7 // out
#define CCLK_PIN AT91_PC6 // out
#define DONE_PIN AT91_PC4 // in
#define INIT_PIN AT91_PC11 // in
//! подготовка выводов к работе
void fpga_pio_occupation(void)
{
size_t i, k;
// переключение выводов в надлежащие позиции
at91_sys_write(AT91_PIOC + PIO_PER, PROG_B_PIN | DIN_PIN | CCLK_PIN | DONE_PIN);
at91_sys_write(AT91_PIOC + PIO_MDER, PROG_B_PIN | DONE_PIN | INIT_PIN);

at91_sys_write(AT91_PIOC + PIO_SODR, PROG_B_PIN | DIN_PIN | CCLK_PIN | DONE_PIN | INIT_PIN);
at91_sys_write(AT91_PIOC + PIO_CODR, CCLK_PIN);

at91_sys_write(AT91_PIOC + PIO_OER, PROG_B_PIN | DIN_PIN | CCLK_PIN | DONE_PIN | INIT_PIN);
at91_sys_write(AT91_PIOC + PIO_PUER, PROG_B_PIN | DONE_PIN | INIT_PIN);
// генерируем не менее 0,5 мкс импульс 0 на выводе PROG_B
for (k = 0; k < 64; k++)
at91_sys_write(AT91_PIOC + PIO_CODR, PROG_B_PIN);
// ждем готовности ПЛИС (подъем вывода INIT в 1)
while (!(at91_sys_read(AT91_PIOC + PIO_PDSR) & INIT_PIN))
{
for (k = 0; k < 64; k++)
at91_sys_write(AT91_PIOC + PIO_SODR, PROG_B_PIN);
}
for (k = 0; k < 1024; k++)
at91_sys_write(AT91_PIOC + PIO_SODR, PROG_B_PIN);
}

//! запись блока в ПЛИС
void fpga_write_block(char * data, size_t len)
{
int i, j, k;
uint8_t byte;
for (i = 0; i < len; i++)
{
byte = data[i];
for (j = 0; j < 8; j++)
{
if (byte & 0x80)
{
at91_sys_write(AT91_PIOC + PIO_SODR, DIN_PIN);
//printk(KERN_NOTICE "1");
}
else
{
at91_sys_write(AT91_PIOC + PIO_CODR, DIN_PIN);
//printk(KERN_NOTICE "0");
}
byte <<= 1;
for (k = 0; k < PULSE_WIDTH; k++)
at91_sys_write(AT91_PIOC + PIO_CODR, CCLK_PIN);

for (k = 0; k < PULSE_WIDTH; k++)
at91_sys_write(AT91_PIOC + PIO_SODR, CCLK_PIN);
}
}


//! возврат выводов в прежнее состояние
void fpga_pio_deoccupation(void)
{
at91_sys_write(AT91_PIOC + PIO_ODR,
PROG_B_PIN | DIN_PIN | CCLK_PIN | DONE_PIN | INIT_PIN);
at91_sys_write(AT91_PIOC + PIO_PDR,
PROG_B_PIN | DIN_PIN | CCLK_PIN | DONE_PIN | INIT_PIN);
}
//! очистка
static void fpga_exit(void)
{
char ones[256];
for (val = 0; val < sizeof(ones); val++)
ones[val] = 0xFF;
val = 0;
while (!(at91_sys_read(AT91_PIOC + PIO_PDSR) & DONE_PIN) &&
(at91_sys_read(AT91_PIOC + PIO_PDSR) & INIT_PIN))
{
fpga_write_block(ones, sizeof(ones));
if (val++ > 1024*8)// записать не более 8*1024*256*8 бит
{
printk(KERN_ERR "fpga loader cannot load fpga\n");
break;
}
}
// выгрузка драйвера вырезана
}

Запись в ПЛИС происходит в функции записи, как уже писал - если передавать сознательно испорченный файл, INIT падает в 0 после получения CRC, если файл правильный, то пишется еще 16М бит в ожидании единицы на DONE или нуля на INIT.
При этом записывать 0, 1 или их попеременно - раззницы не увидел.
Кстати, ситуация похожа на прошивку ПЛИС JTАGом без удерживания АРМа в ресете. INIT точно так же не опускается, а DONE точно так же не поднимается.
UPD: проверил, не запирает ли кто-то вывод DONE в ноль - в драйвере переориетнировал его на вход. Не запирает.
Спуститься к концу Подняться к началу
Персональная информация
leen
Добавлено 03.10.2010 13:24 Редактировалось 05.10.2010 11:27 Сообщение: 19
leen
0

Пункты: 623
Регистрация: 29.12.2009
Пол: Мужчина
Наконец получилось загрузить ПЛИС из АРМа. Причем почему тот же код не работает из уровня ядра, не понял. Может, просмотрел ошибку. В общем, выкладываю программу под линукс, грузящую ПЛИС через GPIO. Собирается кроссплатформенно. Файл прошивки - первый аргумент командной строки. Время загрузки около 0,5 с. Просьба - потестируйте, уважаемые.
Да, еще - R45 был перемычкой, я вместо нее впаял 470 Ом (100 под рукой не было). Вряд ли это важно, тем не менее.

Attachment file: uploads/forum/forum-enIOb3nmV3-7.tgz
Спуститься к концу Подняться к началу
Персональная информация
Форум » starterkit.ru » FPGA