init
This commit is contained in:
309
обработка данных на blackfin в АЦП подготовка.md
Normal file
309
обработка данных на blackfin в АЦП подготовка.md
Normal file
@ -0,0 +1,309 @@
|
||||
[[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`
|
||||
Работает!
|
||||
Reference in New Issue
Block a user