Files
RadioPhotonic-generator-docs/обработка данных на blackfin в АЦП подготовка.md
2025-09-18 17:11:38 +03:00

25 KiB
Raw Permalink Blame History

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

Этапы создания ПО:

  • прием чисел от ПК, умножение на константу (задаваемую отдельной функцией)
  • прием данных от АЦП, пересылка на ПК
  • 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=size2, xcnt=min(256, size2), 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

альтернатива: установка 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/

альтернатива: 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 Работает!