310 lines
25 KiB
Markdown
310 lines
25 KiB
Markdown
[[ADC_software-hardware]]
|
||
|
||
|
||
Про настройку linux для работы с АЦП: [[АЦП E-502]]
|
||
|
||
Описание работы с BF: [[x502_low_level.pdf]]
|
||
# how-to
|
||
## load firmware to Blackfin DSP
|
||
При использовании штатной библиотеки x502api для загрузки прошивки с
|
||
компьютера достаточно установить связь с устройством и вызвать функцию
|
||
X502_BfLoadFirmware(), которая загружает прошивку, проверяет ее работу
|
||
с помощью команды L502_BF_CMD_CODE_GET_PARAM с параметром
|
||
L502_BF_PARAM_FIRM_VERSION (подробнее смотри раздел Командный ин-
|
||
терфейс между ПК и сигнальным процессором), передает прошивке необходимую
|
||
информацию о модуле, после чего переводит модуль в режим работы с DSP.
|
||
|
||
Загружаем .ldr
|
||
|
||
|
||
## setup ADC sampling etc. Настройка параметров сбора данных
|
||
Как и для API верхнего уровня, прошивка BlackFin может устанавливать парамет-
|
||
ры сбора данных только в момент, когда не запущен синхронный ввод-вывод. В штат-
|
||
ной прошивке, как и в API верхнего уровня, сперва задаются все параметры, после
|
||
чего вызывается специальная функция (configure()), которая их непосредственно запи-
|
||
сывает в регистры ПЛИС. Сами параметры хранятся в структуре g_set. Они могут
|
||
быть заданы как командами из программы ПК при вызове X502_Configure(), так и
|
||
изменены внутри самой прошивкой. Для изменения можно как напрямую изменять по-
|
||
ля структуры g_set, так и использовать функции из l502_param.h (params_set_lch(),
|
||
params_set_adc_freq_div() и т.д.), которые дополнительно проверяют значения пара-
|
||
метров. Сами параметры аналогичны используемым в API верхнего уровня (правда
|
||
частоты сбора необходимо устанавливать вручную с помощью делителей и межкадро-
|
||
вой задержки).
|
||
После изменения параметров из прошивки необходимо перед запуском сбора не за-
|
||
быть вызвать configure().
|
||
## алгоритм работы:
|
||
см 5.7 Командный интерфейс между ПК и сигнальным
|
||
процессором
|
||
1. записываем команду (по номеру), аргументы.
|
||
2. DSP загружает её в память, выставляет флаг "работаем"
|
||
3. DSP вызывает соответствующую функцию
|
||
4. ф-ция отрабатывает
|
||
# Realisation
|
||
Задача:
|
||
1. Запуск, настройка АЦП
|
||
2. Получение данных от АЦП
|
||
3. рассчет FFT для одного ЛЧМ. Плата генератора должна подавать сигнал о том, что ЛЧМ в процессе, чтобы разделять данные для разных ЛЧМ
|
||
4. выдача результата на ПК
|
||
## Решение:
|
||
### Программа на PC
|
||
Функционал:
|
||
- загружает прошивку в BlackFin (X502_BfLoadFirmware())
|
||
- настраивает АЦП
|
||
- отправляет в BF команду на запуск работы
|
||
- принимает данные от BF
|
||
- отправляет BF пользовательские команды для управления (задать константы, управление обработкой и т.п.)
|
||
### BlackFin software
|
||
Этапы создания ПО:
|
||
- [x] прием чисел от ПК, умножение на константу (задаваемую отдельной функцией)
|
||
- [x] прием данных от АЦП, пересылка на ПК
|
||
- [ ] FFT обработка данных АЦП, пересыл на ПК
|
||
|
||
|
||
|
||
Если l502_cmd_done() вызывается дважды -- на ПК посылабтся данные последнего вызова. По крайней мере, если вызовы происходят подряд
|
||
|
||
|
||
## hints:
|
||
Если l502_cmd_done() вызывается дважды -- на ПК посылабтся данные последнего вызова. По крайней мере, если вызовы происходят подряд
|
||
|
||
### Про потоки данных и HostDMA:
|
||
HDMA должен конфигурироваться с компа.
|
||
Если конфигурировать с BlackFin, то настройки в ПЛИС будут изменены, всё сконфигурируется, но ПК и драйвер об этом знать не будут. Решение:
|
||
Вызывать с ПК:
|
||
1. X502_StreamsEnable()
|
||
2. X502_StreamsStart()
|
||
непосредственно прием:
|
||
3. X502_GetRecvReadyCount()
|
||
4. X502_Recv()
|
||
|
||
|
||
|
||
Данные АЦП попадают в BF по интерфейсу SPORT0:
|
||
![[Pasted image 20250627192138.png]]
|
||
|
||
|
||
|
||
Реализация чтения данных АЦП:
|
||
функция usr_in_proc_data(): Функция вызывается каждый раз, когда обнаружены новые данные от АЦП/цифровых входов, пришедшие по SPORT0. By defalut -- просто отправляет данные по HDMA
|
||
Последовательность (предположительно): См главу 5.8
|
||
1. задание параметров АЦП
|
||
2. задание L502_BF_PARAM_IN_STREAM_MODE = 0x100 / Режим работы потока на ввод /
|
||
3. разрешение потоков IO BF (L502_BF_CMD_CODE_STREAM_EN)
|
||
4. запуск потоков (L502_BF_CMD_CODE_STREAM_START)
|
||
5. запуск DSP в режиме потоков L502_BF_MODE_STREAM
|
||
См главу 5.8 lowlevel_guide
|
||
|
||
## Формат данных в потоке на ввод и на вывод
|
||
Существует только один поток на ввод и один на вывод. Данные в потоке передаются в виде 32-битных слов. При этом в 32-битном слове, помимо самих данных закодировано и что это за данные (АЦП или DIN). Определить, что за данные, можно по старшему байту принятого слова.
|
||
Ниже приведена таблица для определения какому типу данных принадлежит принятое слово из потока ввода:
|
||
|
||
|
||
| Биты 31-24 | hex | Значение |
|
||
| ---------- | ------------ | ------------------------ |
|
||
| 1xxxxxxx | 0x80 -- 0xFF | Данные от АЦП |
|
||
| 00000000 | 0x00 | Данные с цифровых входов |
|
||
| 00000001 | 0x01 | Сообщения (от BF в ПК) |
|
||
| 001xxxxx | 0x20 -- 0x3F | Резерв |
|
||
| 01xxxxxx | 0x40 -- 0x7F | Пользовательские данные |
|
||
|
||
Непосредственно от ПЛИС по SPORT0 приходят только данные от АЦП и цифровых входов. Сообщения могут генерироваться в прошивке BlackFin для уведомления программы ПК о событиях. Сейчас используется только одно сообщение — сообщение о переполнении буфера. Штатная прошивка передает это сообщение при переполнении буфера SPORT0 на прием. При работе в режиме без DSP это сообщение генерируется аппаратно ПЛИС при переполнении внутреннего буфера DMA на ввод. Данные от АЦП приходят в виде расширенного 24-битного формата в дополнительном коде, так как к ним уже аппаратно применены калибровочные коэффициенты. Код L502_ADC_SCALE_CODE_MAX соответствует напряжению равному границе данного диапазона (например, +10В, +2В и т.д.).
|
||
|
||
**Данные от АЦП приходят в следующем формате:**
|
||
|
||
| 31-24 | 23-0 |
|
||
| -------- | ------------------------ |
|
||
| 11mmcccc | dddddddddddddddddddddddd |
|
||
- d — 24-битный скорректированный дополнительный код АЦП.
|
||
- с — номер канал: “0” — 1-ый или 17-ый, “15” — 16-ый или 32-ой канал (в зависимости от режима).
|
||
- m — режим измерения:
|
||
- 0 — дифференциальный
|
||
- 1 — первые 16 каналов с общей землей
|
||
- 2 — вторые 16 с общей землей
|
||
- 3 — собственный ноль
|
||
|
||
|
||
**С цифровых линий данные приходят в следующем формате:**
|
||
|
||
|
||
| 31-24 | 23-16 | 15-8 | 7-0 |
|
||
| -------- | -------- | -------- | -------- |
|
||
| 00000000 | 000000ss | dddddddd | dddddddd |
|
||
|
||
- d — значения цифровых линий
|
||
- s — значение линий DI_SYN1 (16-ый бит) и DI_SYN2 (17-ый бит)
|
||
|
||
Для слов потока на вывод схожим образом по старшем битам определяется, для
|
||
чего предназначены данные:
|
||
|
||
|
||
|
||
|
||
|
||
|
||
## random from docs:
|
||
|
||
Размещение неинициализуемоего массива (буфера). подключать файл надо перед каждым объявлением.
|
||
`#include ‘‘l502_sdram_noinit.h’’
|
||
`static volatile uint32_t f_sport_in_buf[L502_SPORT_IN_BUF_SIZE];
|
||
|
||
|
||
|
||
### HostDMA
|
||
Запись и чтение по HostDMA всегда осуществляются блоками, кратными
|
||
восьми 32-битным словам (32 байта). Таким образом при записи массива данных разме-ром, некратным размеру блока, будет испорчена часть данных за записываемой частью до границы, кратной 32-м байтам
|
||
|
||
Для прямого доступа к памяти со стороны ПК в библиотеке l502api введены функ-
|
||
ции X502_BfMemRead() и X502_BfMemWrite(). При этом реально обмен осуществляется
|
||
блоками с максимальным размером 128 32-битных слов (512 байт), т.е. при вызове функ-ции с большим размером, массив данных будет разбит на несколько блоков, которые будут последовательно записаны/прочитаны. **надо следить за использованием, для исключения чтения недообработанных данных**
|
||
|
||
Изменение состояния этих выходов (toggle) при нулевом значении на выходах PF14 или PF15 является признаком, что в памяти BlackFin есть готовый новый блок для передачи или есть место для приема очередного блока на вывод. При этом **можно сообщить о готовности нового блока до завершения предыдущего**, так как ПЛИС сохраняет количество готовых, но не завершенных запросов на обмен. Всего может быть до 31 (определено через L502_IN_HDMA_DESCR_CNT и 502_OUT_HDMA_DESCR_CNT) незавершенных запросов по каждому направлению.
|
||
|
||
**Для описания запросов на обмен используются дескрипторы**, которые хранятся в фиксированной области памяти BlackFin (g_state.hdma.in[] и g_state.hdma.out[]). Состав дескриптора описан типом t_hdma_stream_descr. После сброса автомата ПЛИС ножками PF14 и PF15, автомат ожидает дескриптор по фиксированным адресам: &g_state.in[0] (0xFF800020) для ввода и &g_state.out[0] (0xFF800420) для вывода. Адрес же каждого следующего дескриптора задается в предыдущем дескрипторе.
|
||
По **завершению** чтения или записи данных, соответствующих дескриптору, **ПЛИС**
|
||
**записывает обработанный дескриптор полностью обратно в память BlackFin** по адре-
|
||
сам &g_state.in_lb (0xFF800000) и &g_state.out_lb (0xFF800400), **меняя нек. поля**. Прошивка использует поле valid, чтобы узнать о завершении запроса.
|
||
|
||
#### Алгоритм передачи данных для потока ввода выглядит схожим образом:
|
||
|
||
- При запуске потока прошивка вызывает функцию hdma_send_start(), которая
|
||
устанавливает выход PF14 в 0 — разрешается поток на ввод
|
||
- При наличии блока данных на передачу необходимо вызвать hdma_send_req_start()
|
||
с указанием буфера с данными — функция заполняет дескриптор g_state.in[0] нужными значениями (full_size=size*2, xcnt=min(256, size*2), addr, valid=1, id) и изменяет состояние выхода PG5, чтобы сообщить ПЛИС о готовности нового запроса.
|
||
- ПЛИС по этому сигналу, когда будет свободна шина HostDMA, считывает де-
|
||
скриптор из g_state.in[0].
|
||
- При наличии места в памяти ПК на прием и свободной шине HostDMA идет чтение данных из памяти BlackFin, начиная с адреса g_state.in[0].addr, блоками размером не больше xcnt 16-битных слов с последующей записью в память ПК.
|
||
- При передаче всех full_size слов записывается считанный до этого дескриптор с измененными полями full_size и addr по адресу &g_state.in_lb.
|
||
- По завершению этой записи в обработчике hdma_isr() прошивка определяет по g_state.in_lb.valid, что записан дескриптор, устанавливает g_state.in_lb.valid в 0, вычисляет обработанный размер и вызывает hdma_send_done(). hdma_send_done() реализовано в l502_user_process.c.
|
||
- При передаче на вывод в обратно записанном дескрипторе full_size=0, что соответствует полностью обработанному дескриптору.
|
||
- По мере необходимости добавляются новые дескрипторы через dma_send_req_start().
|
||
- Дожидаться завершения предыдущего не обязательно — задания на передачу данных ставятся в очередь. Только нужно проверить, что есть место в очереди через hdma_send_req_rdy().
|
||
- При завершении потокового ввода вызывается hdma_send_stop(), которая устанавливает PF14 в 1, что приводит к сбросу автомата приема потока на ввод по HostDMA в ПЛИС.
|
||
|
||
### SPORT0 (5.9)
|
||
|
||
|
||
В отличии от остальных интерфейсов для приема-передачи потоков данных, где обмен осуществляется через дескрипторы и может быть приостановлен, пока новый дескриптор не будет поставлен в очередь, прием синхронных данных от АЦП/DIN всегда осуществляется непрерывно со скоростью ввода этих данных. Прием осуществляется 32-битными словами. При этом каждое 32-битное слово передается как два 16-битных, передаваемых параллельно — одно по первичному каналу SPORT0, второе — по вторичному. При приеме используется внешний сигнал начала кадра (RFS), который генерирует ПЛИС каждый раз при наличии нового принятого отсчета АЦП или DIN.
|
||
Сигнал RFS должен быть явно разрешен с помощью установки бита BF_RFS_EN регистра OUTSWAP_BFCTL. Для ра.
|
||
приема
|
||
Прием
|
||
используется
|
||
данных
|
||
третий
|
||
происходит
|
||
канал
|
||
постоянно
|
||
DMA
|
||
в
|
||
BlackFin
|
||
буфер
|
||
в
|
||
режимеавтобуфе-
|
||
f_sport_in_bufразмером
|
||
L502_SPORT_IN_BUF_SIZE. Сам буфер разделен на блоки, размер каждого из
|
||
которых
|
||
равен
|
||
шагу
|
||
прерывания.
|
||
Этот
|
||
шаг
|
||
может
|
||
быть
|
||
установлен
|
||
с
|
||
помощью
|
||
функции sport_in_set_step_size(). В штатной прошивке установка этого параметра
|
||
осуществляется
|
||
с
|
||
ПК
|
||
через
|
||
команду
|
||
L502_BF_CMD_CODE_SET_PARAM
|
||
с
|
||
параметром L502_BF_PARAM_IN_STEP_SIZE, но ничего не мешает изменять его
|
||
из самой прошивки пока синхронные потоки не запущены.
|
||
Для реализации приема данных с указанным шагом используется 2D режим DMA,
|
||
где размер по X равен размеру шага (умноженному на 2, т.к. используется 16-битный
|
||
77режим DMA), а по Y - количеству шагов, которое помещается в буфере на прием (долж-
|
||
но быть не меньше 3). Таким образом, если размер буфера на прием не кратен шагу,
|
||
то реально используется не весь буфер, а наибольший размер кратный шагу, но не
|
||
превышающий размер буфера.
|
||
После приема данных, размер которых соответствует шагу прерывания, будет вы-
|
||
зван обработчик isr_sport_dma_rx(), в котором обновляется размер принятых данных
|
||
в буфере и проверяется переполнение. Т.к. прерывание возникает при завершении при-
|
||
ема блока данных, когда уже начат прием следующего блока, то, чтобы не допустить
|
||
порчи данных из-за переполнения буфера, необходимо, чтобы в момент прерывания
|
||
было свободно для приема как минимум два блока. В противном случае, если к следу-
|
||
ющему прерыванию хотя бы еще один блок не освободится, то о переполнении прошивка
|
||
узнает только в момент, когда часть буфера уже была повреждена (что может приве-
|
||
сти к тому, что будут обработаны испорченные данные). Таким образом, для надежного
|
||
приема данных, если в прерывании обнаруживается, что свободно меньше двух блоков,
|
||
то это считается переполнением.
|
||
По переполнению останавливается прием по интерфейсу SPORT0 и взводится спе-
|
||
циальный флаг. После этого обрабатываются все принятые, но необработанные данные
|
||
в буфере, после чего в ПК посылается слово о том, что в данном месте было перепол-
|
||
нение.
|
||
Управление приемом по SPORT0 осуществляется из функций управления потока-
|
||
ми: при запуске синхронного ввода-вывода и разрешенных потоках на ввод выпол-
|
||
няется функция sport_rx_start(), которая настраивает DMA, сбрасывает указатели
|
||
в буфере на прием и разрешает прием по SPORT0. При останове синхронного ввода-
|
||
вывода или запрете всех потоков на ввод выполняется останов приема по SPORT0 через
|
||
sport_rx_stop().
|
||
|
||
|
||
|
||
# preparations
|
||
## установка CrossCode Embedded Studio
|
||
- source: https://www.analog.com/en/resources/evaluation-hardware-and-software/embedded-development-software/adswt-cces.html#software-relatedsoftware
|
||
- instuctions: https://download.analog.com/tools/CrossCoreEmbeddedStudio/Releases/Release_2.12.1/CrossCoreEmbeddedStudio_Installation_Guide.pdf, local: [[CrossCoreEmbeddedStudio_Installation_Guide.pdf]]
|
||
|
||
## альтернатива: установка blfn-elf-gcc
|
||
Исходники: git clone https://github.com/deanm1278/blackfin-plus-gnu.git
|
||
Сборка:
|
||
cd blackfin-plus-gnu/gcc
|
||
./contrib/download_prerequisites
|
||
cd ../buildscript/
|
||
./build.sh
|
||
Однако, возникают ошибки компиляции.
|
||
ChatGPT:
|
||
|
||
Ошибка компиляции, с которой вы столкнулись при сборке кросс-компилятора для Blackfin, связана с изменениями в компиляторе GCC, начиная с версии 8. В частности, GCC стал более строго проверять приведения типов между несовместимыми указателями на функции, что приводит к ошибкам при компиляции устаревших версий `binutils`, используемых в проекте `blackfin-plus-gnu`.
|
||
Решение:
|
||
добавить
|
||
export CFLAGS="-Wno-error=cast-function-type"
|
||
export CXXFLAGS="-Wno-error=cast-function-type"
|
||
В build.sh
|
||
|
||
|
||
|
||
#### Сборка в chroot
|
||
Создание chroot в /srv/chroot:
|
||
`sudo debootstrap --variant=buildd --arch=amd64 focal /srv/chroot/focal-amd64 http://archive.ubuntu.com/ubuntu
|
||
|
||
mounts:
|
||
sudo mount --bind /proc /srv/chroot/focal-amd64/proc
|
||
sudo mount --bind /sys /srv/chroot/focal-amd64/sys
|
||
sudo mount --bind /dev /srv/chroot/focal-amd64/dev
|
||
sudo cp /etc/resolv.conf /srv/chroot/focal-amd64/etc/
|
||
|
||
sudo mount --bind /sharedfolder /srv/chroot/shared
|
||
|
||
вход в chroot:
|
||
sudo chroot /srv/chroot/focal-amd64 /bin/bash
|
||
|
||
#### Как войти в chroot после перезагрузки
|
||
|
||
1. **Смонтируйте нужные файловые системы**, если они ещё не примонтированы:
|
||
sudo mount --bind /proc /srv/chroot/focal-amd64/proc
|
||
sudo mount --bind /sys /srv/chroot/focal-amd64/sys
|
||
sudo mount --bind /dev /srv/chroot/focal-amd64/dev
|
||
sudo cp /etc/resolv.conf /srv/chroot/focal-amd64/etc/
|
||
- Это нужно для работоспособности среды и выхода в интернет. [geeksforgeeks.org+15wiki.ubuntu.com+15stackoverflow.com+15](https://wiki.ubuntu.com/DebootstrapChroot?utm_source=chatgpt.com)
|
||
|
||
- **Войдите в chroot**:
|
||
## альтернатива: official old toolchain
|
||
https://sourceforge.net/projects/adi-toolchain/files/2014R1/2014R1-RC2/x86_64/
|
||
Скачали в Blackfin/toolchain_off
|
||
прописали в PATH:
|
||
`export PATH=/home/feda/MIPT/RadioPhotonic_Subserface_radar/BlackFin/toolchain_off/bfin-elf/bin:$PATH`
|
||
Работает!
|