24.06.2014 Настройка и ресурсы Xilinx ZYNQ ZC702
Ustinov (обсуждение | вклад) |
Ustinov (обсуждение | вклад) (→Функции чтения и записи в регистры) |
||
Строка 162: | Строка 162: | ||
== Функции чтения и записи в регистры == | == Функции чтения и записи в регистры == | ||
+ | Литература: [[Медиа:Ug585-Zynq-7000-TRM.pdf|Техническое справочное руководство]], [[Медиа:Xtp185-zc702-schematic-rev1-1.pdf|схема]]. | ||
+ | |||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
#include <stdio.h> | #include <stdio.h> | ||
Строка 171: | Строка 173: | ||
#include <signal.h> | #include <signal.h> | ||
#include <sys/mman.h> | #include <sys/mman.h> | ||
− | |||
− | |||
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \ | #define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \ | ||
Строка 179: | Строка 179: | ||
#define MAP_SIZE 4096UL | #define MAP_SIZE 4096UL | ||
#define MAP_MASK (MAP_SIZE - 1) | #define MAP_MASK (MAP_SIZE - 1) | ||
− | #define BASE_ADDRESS | + | #define BASE_ADDRESS 0xF8000000 |
#define SET_AS_GPIO 0x1200 | #define SET_AS_GPIO 0x1200 | ||
#define SET_UNLOCK 0xDF0D | #define SET_UNLOCK 0xDF0D | ||
− | #define SLCR_UNLOCK | + | #define SLCR_UNLOCK 0x8 |
#define MIO_PIN_8 0x720 | #define MIO_PIN_8 0x720 | ||
#define MIO_PIN_10 0x728 | #define MIO_PIN_10 0x728 | ||
+ | |||
+ | /*Чение регистров по адресу*/ | ||
+ | void register_read(unsigned long addr) | ||
+ | { | ||
+ | int fd; | ||
+ | void *map_base, *virt_addr; | ||
+ | unsigned long read_result; | ||
+ | if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL; | ||
+ | fflush(stdout); | ||
+ | /* Map one page */ | ||
+ | map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDRESS & ~MAP_MASK); | ||
+ | if(map_base == (void *) -1) FATAL; | ||
+ | fflush(stdout); | ||
+ | virt_addr = map_base + ((BASE_ADDRESS + addr) & MAP_MASK); | ||
+ | read_result = *((unsigned long *) virt_addr); | ||
+ | printf("0x%08X r: 0x%X\n", addr, read_result); | ||
+ | fflush(stdout); | ||
+ | } | ||
+ | |||
+ | /*Запись в регистр по адресу*/ | ||
+ | void register_wright(unsigned long addr, unsigned long writeval) | ||
+ | { | ||
+ | int fd; | ||
+ | void *map_base, *virt_addr; | ||
+ | unsigned long read_result; | ||
+ | if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL; | ||
+ | // printf("/dev/mem opened.\n"); | ||
+ | fflush(stdout); | ||
+ | /* Map one page */ | ||
+ | map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDRESS & ~MAP_MASK); | ||
+ | if(map_base == (void *) -1) FATAL; | ||
+ | // printf("Memory mapped at address %p.\n", map_base); | ||
+ | fflush(stdout); | ||
+ | virt_addr = map_base + ((BASE_ADDRESS + addr) & MAP_MASK); | ||
+ | *((unsigned long *) virt_addr) = writeval; | ||
+ | read_result = *((unsigned long *) virt_addr); | ||
+ | printf("0x%08X w: 0x%X\n", addr, read_result); | ||
+ | } | ||
+ | |||
+ | |||
+ | int main (void) | ||
+ | { | ||
+ | /*Изначально, при загрузке, MIO_PIN_8 (на нём висит диод DS12) не сконфигурирован для GPIO, исправим это.*/ | ||
+ | register_wright(SLCR_UNLOCK, SET_UNLOCK); // Необходимый анлок регистров | ||
+ | register_read(MIO_PIN_8); // Считаем начальное значение регистра | ||
+ | register_wright(MIO_PIN_8, SET_AS_GPIO); // Записываем новое значение | ||
+ | register_read(MIO_PIN_8); // Считаываем новое значение регистра | ||
+ | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Версия 13:15, 29 июля 2014
Содержание |
About
Как всегда для сохранения ценной информации, используем SRNS.ru. Полезная информация для ZYNQ не станет исключением.
Boot Modes
convert: no images defined `/tmp/transform_50b8bd09249d-1.jpg' @ error/convert.c/ConvertImageCommand/3044.
Запуск Linux с карты памяти
Готовые релизы Linux можно найти по данной ссылке. Выберем релиз 2014.2, т.к. он основа на ядре 3.14, к которому применим preempt_rt патч. Распаковываем архив:
Подготавливаем карту памяти как в этой статье. Из скачанного архива 2014.2-release.tar.xz на карту памяти копируем следующие файлы:
- boot.bin
- uImage
- devicetree.dtb
- uramdisk.image.gz
Карточку вставляем в ZYNQ, джамперы (SW16) выставляем в комбинацию 00110, что выглядит как:
На компе запускаем скрипт:
set line /dev/ttyUSB0
set FLOW none
set speed 115200
set serial 8n1
SET CARRIER-WATCH Off
connect
Включаем плату и видим загрузку Linux. Для логина используем Username & Password: root.
Прошиваем Linux в QSPI Flash
После загрузки Linux с карты памяти, примонтируем её:
Далее вводим команду:
Видим следующее:
mtd0 отведен для boot.bin
mtd1 отведен для uImage
mtd2 отведен для devicetree.dtb
mtd3 отведен для uramdisk.image.gz
Соответственно, переходим в подмантированную папку /mnt и вводим следующие команды для записи:
flashcp -v uImage /dev/mtd1
flashcp -v devicetree.dtb /dev/mtd2
flashcp -v uramdisk.image.gz /dev/mtd3
Чтобы грузиться с QSPI Flash необходимо переключить джамперы (SW16) в комбинацию 00010.
Модификация FS
- Изменения FS скачанного выше релиза.
Необходимо развернуть образ FS из "обертки" u-boot. Для этого следует пропустить первые 64 байта:
Теперь разархивируем полученный архив в папку:
gunzip -c ramdisk.image.gz | sudo sh -c 'cd ./tmp_mnt/ && cpio -i'
cd ./tmp_mnt
Далее выполняем нужные изменения и снова запечатываем в архив:
Теперь необходимо образ "завернуть" в u-boot:
Образ готов для загрузки как с SD, так и с QSPI Flash.
- Модификация стандартной FS
Качаем образ FS по-умолчанию: RamDisk. Распаковываем его:
Монтируем распакованное содержимое:
mkdir tmp_mnt/
sudo mount -o loop ramdisk.image tmp_mnt/
cd tmp_mnt/
Делаем нужные изменения. Размонтируем и запаковываем:
gzip ramdisk.image
Соответственно, для загрузки в железку данный образ должен быть "обернут" в U-Boot:
Кроме того, можно создать изначально пустой образ и затем уже заполнять его файлами, как описано выше:
mke2fs -F ramdisk.image -L "ramdisk" -b 1024 -m 0
tune2fs ramdisk.image -i 0
chmod a+rwx ramdisk.image
Установка PetaLinux SDK
Заходим тык. Качаем PetaLinux 2014.2 Installation archive for Zynq and MicroBlaze для релиза 2014.2.
Переходим в папку, куда закачали, там выполняем:
После установки запускаем скрипт:
Проверяем, сработал ли скрипт:
Выключаем отправку статистики на сервера Xilinx:
Беспарольный доступ
Настройки, аналогичны этому примеру, за исключением некоторых но. Dropbear при старте платы всегда генерирует новые ключи, потому как грузится Linux из RAM. Соответвенно, забираем их из /etc/dropbear/ себе на комп. По вышеописанной инструкции модификации FS вносим эти файлы в /etc/dropbear/ и создаем в /home/root/.ssh файл authorized_keys. В него вносим содержимое нашего открытого ключа.
Устанавливаем все права как:
Обратите внимание, что права устанавливаются именно для подмонтированной файловой системы, а не для файлов, используемых нашим компом!
chmod 700 ./home/root/.ssh
chmod 600 ./home/root/.ssh/authorized_keys
Собираем FS и грузимся со всеми нашими модификациями.
Компиляция исходников
Необходимо установить ISE, есть на сервере. Далее по окончании установки и каждый раз при открытии новой консоли необходимо устанавливать параметры среды $PATH, запуская скрипт:
После этого уже можно стандартно использовать компилятор. Для ZYNQ zc702 он называется arm-xilinx-linux-gnueabi-gcc, ну или arm-xilinx-linux-gnueabi-g++.
Функции чтения и записи в регистры
Литература: Техническое справочное руководство, схема.
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/mman.h>
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
#define BASE_ADDRESS 0xF8000000
#define SET_AS_GPIO 0x1200
#define SET_UNLOCK 0xDF0D
#define SLCR_UNLOCK 0x8
#define MIO_PIN_8 0x720
#define MIO_PIN_10 0x728
/*Чение регистров по адресу*/
void register_read(unsigned long addr)
{
int fd;
void *map_base, *virt_addr;
unsigned long read_result;
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
fflush(stdout);
/* Map one page */
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDRESS & ~MAP_MASK);
if(map_base == (void *) -1) FATAL;
fflush(stdout);
virt_addr = map_base + ((BASE_ADDRESS + addr) & MAP_MASK);
read_result = *((unsigned long *) virt_addr);
printf("0x%08X r: 0x%X\n", addr, read_result);
fflush(stdout);
}
/*Запись в регистр по адресу*/
void register_wright(unsigned long addr, unsigned long writeval)
{
int fd;
void *map_base, *virt_addr;
unsigned long read_result;
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
// printf("/dev/mem opened.\n");
fflush(stdout);
/* Map one page */
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDRESS & ~MAP_MASK);
if(map_base == (void *) -1) FATAL;
// printf("Memory mapped at address %p.\n", map_base);
fflush(stdout);
virt_addr = map_base + ((BASE_ADDRESS + addr) & MAP_MASK);
*((unsigned long *) virt_addr) = writeval;
read_result = *((unsigned long *) virt_addr);
printf("0x%08X w: 0x%X\n", addr, read_result);
}
int main (void)
{
/*Изначально, при загрузке, MIO_PIN_8 (на нём висит диод DS12) не сконфигурирован для GPIO, исправим это.*/
register_wright(SLCR_UNLOCK, SET_UNLOCK); // Необходимый анлок регистров
register_read(MIO_PIN_8); // Считаем начальное значение регистра
register_wright(MIO_PIN_8, SET_AS_GPIO); // Записываем новое значение
register_read(MIO_PIN_8); // Считаываем новое значение регистра
}
[ Хронологический вид ]Комментарии
Войдите, чтобы комментировать.