Перейти к содержанию
    

Allwinner T113-s3 уделал HiFi4 DSP. Смеяться или плакать?

6 hours ago, repstosw said:

BIT_PFAULT_ERROR

Прерывание произошло но обработчик обсыпался...
Сделай первой командой обработчика переход сам на себя. Если перестанет сообщать что fault - доходит. Если не перестанет - ошибка раньше

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

44 minutes ago, GenaSPB said:

Прерывание произошло но обработчик обсыпался...
Сделай первой командой обработчика переход сам на себя. Если перестанет сообщать что fault - доходит. Если не перестанет - ошибка раньше

Это не помогло 🙂  Проблема оказалась в том, что вектора прерываний были не в том месте. 

Вот этот товарисЧ ввёл меня в заблуждение:  https://github.com/esp-rs/xtensa-lx-rt/issues/5#issuecomment-578954586

Всё, что дальше оконных исключений - всё не то 🙂

 

Правильные смещения в таблице векторов - они идут уже не с шагом +64 :

    .org    0x17C //IntLevel2
    .org    0x19C //IntLevel3 : Timer0, Timer1
    .org    0x1BC //IntLevel4
    .org    0x1DC //IntLevel5, NMI
    .org    0x1FC //Kernel
    .org    0x21C //User
    .org    0x23C //Double

Я ещё по началу в скрипте линкера от FreeRTOS увидел  эту "кривизну" смещений.

Поймал прерывания таймеров и исключение UserException при использовании alloca( ).

Написал обработчик прерывания таймера.  Пока вызов пользовательской функции через call0 - в ассемблерном сорце.  Не получается задействовать сишный call8 - зависает.

 

Удалось из стартапа вызвать сишные функции libc_init() и cледом за ней main() с помощью call8.  Раньше был просто переход на libc_init.

Чтобы вызов второй функции main() не вешал программу  - нужно  добавить entry:

	j		XXX //обход для выравнивания

	.align 4

XXX:

	entry		a1,32

	call8		libc_init
	call8		main

//...

 

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/11/2023 at 10:47 AM, repstosw said:

Вот этот товарисЧ ввёл меня в заблуждение:  https://github.com/esp-rs/xtensa-lx-rt/issues/5#issuecomment-578954586

Всё, что дальше оконных исключений - всё не то 🙂

товарищь написал про своё ядро а они конфигурируемые, у t113 свой конфиг - в оверлее актуальные адреса для каждого процессора

https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/164696d952116d20100daefd7a475d2ede828eb0/include/xtensa/config/core-isa.h#L697

https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/releases/tag/Toolchains

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, sasamy said:

Указанные здесь оффсеты векторов совпали с моими расчётами из скрипта линкера :yes:

 

3 hours ago, repstosw said:

Пока вызов пользовательской функции через call0 - в ассемблерном сорце.  Не получается задействовать сишный call8 - зависает.

Уже задействовал. Работает.  Не работало из-за того, что в обработчике прерывания нужно понижать уровень приоритета до значения равного приоритету самого обработчика, до вызова любой пользовательской функции внутри.

Как здесь: https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/Toolchains/kernel/portable/xtensa_vectors.S#L1451

Для таймера приоритет 3:

 

	movi		a3,PS_UM|PS_WOE_ABI|PS_INTLEVEL(3)
	wsr.ps		a3
	rsync

 

3 hours ago, repstosw said:

далось из стартапа вызвать сишные функции libc_init() и cледом за ней main() с помощью call8.  Раньше был просто переход на libc_init.

Чтобы вызов второй функции main() не вешал программу  - нужно  добавить entry:

 

Теперь никакой entry не нужен.   Нужно  старт окна сделать в 1. Тогда можно будет использовать windowed-вызовы из ассемблерного сорца.

 

	movi		a3,1			//=1 - allow windowed call from assembly startup
	wsr.WINDOWSTART	a3			//Call-window start bits
      
      //...
      
   	call8		libc_init
	call8		main

 

Осталось доделать эксепшн при alloca/setjmp  и оформить это в SDK HiFi4 DSP :sun_bespectacled:

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/11/2023 at 9:23 PM, repstosw said:

Осталось доделать эксепшн при alloca/setjmp  и оформить это в SDK HiFi4 DSP :sun_bespectacled:

Доделал обработку прерываний/исключений. Итого вышло 10 исключений:

1. Прерывание таймера (1)

2. Исключения Overflow регистрового окна (3)

3. Исключения Underflow регистрового окна (3)

4. Исключение Alloca (инструкция MOVESP)  (1)

5. Исключение SetJmp (инструкция SYSCALL) (1)

6. Исключение User - просто корректный выход из исключения (1)

4,5,6 - сидят на IntLevel1. необходимо было сделать селектор (сепаратор), чтобы определять причину исключения и отдельно её обработать.

Стресс-тест на всех уровнях оптимизации не завалил программу.

 

Пришлось много возиться и курить. Считаю, что обработка исключений - самая трудная часть этого DSP. Без написания корректного кода исключений программа будет падать.

Все исключения (за исключением SetJmp) необходимы!  Самое сложное исключение - SetJmp: нужно было сделать некоторые манипуляции со стеком, регистровыми окнами, и ручками корректировать адрес возврата.

Контекст для сохранения регистров в прерываниях(там где он нужен - Timer и SetJmp) сделал в отдельной секции памяти.  Пробовал использовать стек - программа падает, если используется одновременно много прерываний (как минимум два:  Таймер + оконный Overflow/Underflow).

Поэтому чтобы не нарушать работу оконных обработчиков, прерывание таймера не использует  стек для сохранения регистров.  При этом программа не падает на любой оптимизации.

В прерывании таймера важно было правильно подтвердить его. Иначе прерывание начнёт снова выполняться сразу же после выхода - много раз.

 

В исходниках FreeRTOS обработчики написаны с учётом много-задачности.  Анализ кода может привести к взрыву мозга.

https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/master/kernel/portable/xtensa_vectors.S

 

Приходится смотреть в дургих местах как сделаны некоторые вещи:

https://chromium.googlesource.com/chromiumos/third_party/sound-open-firmware/+/5b43730e8620c60b4170231f7e9d91d2d2d89652/src/arch/xtensa/up/xtos/exc-syscall-handler.S

 

Реализовал псевдо-функцию макрос для printf, с помощью sprintf  по всем канонам стандарта (c возвращаемым значением):

#define printf(format,...)                                      \
({                                                              \
 char printf_buffer[128];                                       \
 int printf_return=sprintf(printf_buffer,format,##__VA_ARGS__); \
 UART_puts(printf_buffer);                                      \
 printf_return;                                                 \
})                                                              \

 

Этот DSP также может исполнять код из DDR T113-s3.

Тестировал на адресах: 0x41800000  , 0xC1800000 (кешируемый),  и   0x31800000 (не работает.  Возвращает Fault = 0x2).

Здесь к адресам добавлены +24 МБ (0x1800000), потому что в начале DDR программа для T113-s3.

Последний адрес скорее всего не работает из-за того что нужны кое-какие манипуляции с AHB, о чем говорит даташит:

image.thumb.png.4e6489925cde17dbec5fa8cdf1bfb874.png

Но он особо не интересен, так как первые два работают.

 

Лог запуска в UART (на ПК):

Spoiler
HiFi4 DSP...
RO Data: 0x41803073, Data Start: 0x41810080, Data End: 0x418108AC
BSS Start: 0x418108AC, BSS End: 0x41810A1C
Stack: 0x41820000, Heap Start: 0x41818000, Heap End: 0x4181C000
malloc() Test
malloc OK!
malloc String
foo 0
srand() & rand() Test:
2132416883854391803722155897918388512453687072798722520304017882391507922335899285399047465674001819
Timer Test:
ccount: 804
ccount: 747999
ccount: 1669194
ccount: 2647569
ccount: 3626769
foo 1
setjmp() & longjmp() Test:
setjmp
longjmp
setjmp
123
Loop...
!!!!!!!!!!Timer Interrupt /
!!!!!!!!!!Timer Interrupt ±
!!!!!!!!!!Timer Interrupt ­
!!!!!!!!!!Timer Interrupt ó
!!!!!!!!!!Timer Interrupt 
!!!!!!!!!!Timer Interrupt 
!!!!!!!!!!Timer Interrupt H
!!!!!!!!!!Timer Interrupt Ž
!!!!!!!!!!Timer Interrupt ¤
!!!!!!!!!!Timer Interrupt ì
!!!!!!!!!!Timer Interrupt Š
!!!!!!!!!!Timer Interrupt 
!!!!!!!!!!Timer Interrupt Ó
!!!!!!!!!!Timer Interrupt ¼
!!!!!!!!!!Timer Interrupt ò
!!!!!

 

 

Ещё мысли по поводу стандартных сишных библиотек, входящих в hifi4-dsp компилятор от FreeRTOS.  По-хорошему их надо пересобирать для BareMetal.  Потому что они ориентированы на повторную входимость и многозадачность, и содержат кучу лишних действий и доставляют проблемы с корректным запуском штатных функций.

Но исходников libc.alibm.a  я не увидел : https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/tree/master/lib

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

52 минуты назад, repstosw сказал:

В прерывании таймера важно было правильно подтвердить его. Иначе прерывание начнёт снова выполняться сразу же после выхода - много раз.

Это справедливо практически для любых таймеров и архитектур)))

53 минуты назад, repstosw сказал:

Этот DSP также может исполнять код из DDR T113-s3.

А смысл?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

29 minutes ago, mantech said:

Это справедливо практически для любых таймеров и архитектур)))

Это понятно. И ожидаемо.  А вот на счёт "как это сделать" - это и нужно было понять.

31 minutes ago, mantech said:

А смысл?

Удовлетворение собственного любопытства )) Ну или может как отдельную функцию использовать для запуска эмулятора чего-либо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/13/2023 at 1:59 PM, repstosw said:

Доделал обработку прерываний/исключений. Итого вышло 10 исключений:

1. Прерывание таймера (1)

с внешними прерываниями от периферии нет планов разобраться? без этого всё выглядит малопригодным. В freertos есть пример для msgbox но этого мало - непонятно по какому принципу мапятся прерывания от периферии, есть инит контроллера (предположил по названию - прерываний периферии)

https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/164696d952116d20100daefd7a475d2ede828eb0/arch/board-init.c#L106

описания его в мануале нет и я не заметил чтобы он использовался при установке обработчика для msgbox

https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/164696d952116d20100daefd7a475d2ede828eb0/src/msgbox.c#L37

 

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насчёт прерываний от периферии. Самое интересное прерывание,  которое может быть прицеплено к dsp ядру это прерывание по обмену с кодеками. DMAC. В данном микропроцессоре этот единственное прерывание на все 16 каналов. А с учётом того что dsp ядро единственное а cortex a7 пара, острой необходимости как-то не наблюдается. Ну интересно, но прикрутить в проект иначе как возложив на hifi4 (и только на него) всю dsp обработку (расчёты, менеджмент буферов) не получится. Usb dma я например поднял - но это то же единственное прерывание. распределять крайне неудобно. 

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

43 minutes ago, sasamy said:

с внешними прерываниями от периферии нет планов разобраться?

Внешние прерывания - это когда сигнал на ножку извне  приходит с внешнего модуля? Или под внешними понимаются любые прерывания от периферии T113-s3 ?

У меня нет мануала на периферию этого DSP. В сорцах линукса например есть такое: настроить прерывание по уровню/фронту с какого-нибудь GPIO?

Что касается периферии - так этот DSP видит всю периферию от T113-s3.  Тоесть ему особо и не нужна своя периферия.

И я думаю что у него её нет.  Всё что есть - это числомолотилка с VLIW архитектурой + SIMD + быстрая выделенная память кода/данных.

45 minutes ago, sasamy said:

В freertos есть пример для msgbox но этого мало - непонятно по какому принципу мапятся прерывания от периферии, есть инит контроллера (предположил по названию - прерываний периферии)

А что такое этот msgbox?  Буфер памяти куда флудит этот DSP для обмена сообщениями между A7 и DSP? Не совсем понятно, зачем это нужно. Всю жизнь контекст общения между двумя ядрами делал самостоятельно в удобном месте.

33 minutes ago, GenaSPB said:

Насчёт прерываний от периферии. Самое интересное прерывание,  которое может быть прицеплено к dsp ядру это прерывание по обмену с кодеками. DMAC. В данном микропроцессоре этот единственное прерывание на все 16 каналов. А с учётом того что dsp ядро единственное а cortex a7 пара, острой необходимости как-то не наблюдается. Ну интересно, но прикрутить в проект иначе как возложив на hifi4 (и только на него) всю dsp обработку не получится. Usb dma я например поднял - но это то же единственное прерывание. распределять крайне неудобно. 

Так а где смотреть как коммутировать источник прерывания на линию DSP?  Допустим у аудиокодек работает по прерываниям с ядром A7.   Как это прерывание загнать на DSP?  Ну не софтовый же поллинг делать ? 🙂 

 

Собственно я начал ковырять этот DSP, чтобы на него повешать кодер Рида-Соломона.  А декодер повешаю на второе A7 ядро.  А первое A7 ядро - главное: управление и остальное.

Кодер Рида-Соломона на A7 работает на 30 FPS.   Декодер - на 15 FPS.   Учитывая целевой FPS системы - 12..15 : нужна параллельность вычислений.

Моя тема про кодек RS здесь:

Интересно, протащит ли DSP кодирование хотя бы на уровне 15 FPS?   Мне главное чтобы параллельно шло кодирование-декодирование-главная программа.  Самое слабое звено должно давать не меньше 12-15 FPS.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/13/2023 at 6:17 PM, repstosw said:

Не совсем понятно, зачем это нужно. Всю жизнь контекст общения между двумя ядрами делал самостоятельно в удобном месте.

а потом поллингом мониторить буфер ? фигня какая-то, зачем тогда нужен этот периферийный DSP сопроцессор, с msgbox ядра друг друга аппаратно могут прерывать

On 9/13/2023 at 6:17 PM, repstosw said:

Так а где смотреть как коммутировать источник прерывания на линию DSP? 

вообще-то это я  вас и спросил

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, sasamy said:

Неплохо. :sun_bespectacled:

3 minutes ago, sasamy said:

а потом поллингом мониторить буфер ? фигня какая-то, зачем тогда нужен этот периферийный DSP сопроцессор, с msgbox ядра друг друга аппаратно могут прерывать

1.  ядро-1 делает рендеринг

2. далее ядро-1 проверяет свободно ли ядро-2 и передаёт указатель на результат рендеринга

3. ядро-2 начинает работать с результатом и делает над ним второе преобразование

4. в это время ядро-1 делает новый фрейм рендеринга

Опрос готовности ядра-2 делается ядром-1 по завершению рендеринга ядром-1.  Обычно ядро-2 к тому моменту уже свободно.  Ожидание сведено к минимуму, никто циклически не опрашивает.

Время рендеринга ядром-1  20 мс,  время второго преобразования ядром-2  15 мс.

 

PS. Но то что есть прерывания это хорошо. Возьму на заметку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/13/2023 at 6:31 PM, repstosw said:

Опрос готовности ядра-2 делается ядром-1 по завершению рендеринга ядром-1.  Обычно ядро-2 к тому моменту уже свободно.  Ожидание сведено к минимуму, никто циклически не опрашивает.

для бареметал сойдёт и так - там всё равно процессору больше нечего делать кроме поллинга 🙂  весь смысл для меня был скидывать реалтайм задачи с Linux на DSP ядро - какой толк от этого если потом надо програмно поллить буфер

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, sasamy сказал:

весь смысл для меня был скидывать реалтайм задачи с Linux на DSP ядро - какой толк от этого если потом надо програмно поллить буфер

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 9/13/2023 at 9:13 PM, mantech said:

результаты работы передаются в основной процессор. Это вполне можно делать и в шедулере

можно но не нужно, лень объяснять такие базовые вещи, поллинг неподходящая стратегия для ОС общего назначения - куча бесполезных дорогих переключений контекста (сто раз в секнду стандартного шедулера может и не хватать) и невозможность для ядра  tickless планирования

https://en.wikipedia.org/wiki/Tickless_kernel

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...