repstosw 18 22 октября, 2023 Опубликовано 22 октября, 2023 (изменено) · Жалоба HiFi4 DSP не сбрасывается вместе с CPU 0/1 при нажатии кнопки RESET. Результат непредсказуем: после сброса DSP либо улетает в экспешн, либо работает. Запись в регистр DSP_ALT_RESET_VEC_REG не приводит к положительному результату. Вопрос: как остановить DSP? Код для запуска DSP в спойлере: Spoiler void sunxi_dsp_init(const void *img_addr,u32 img_size) { sram_remap_set(1); //set system boot use local ram dsp_freq_default_set(); //clock gating u32 reg_val=readl_dsp(CCU_BASE+CCMU_DSP_BGR_REG); reg_val|=(1<<BIT_DSP0_CFG_GATING); writel_dsp(reg_val,CCU_BASE+CCMU_DSP_BGR_REG); //reset reg_val=readl_dsp(CCU_BASE+CCMU_DSP_BGR_REG); reg_val|=(1<<BIT_DSP0_CFG_RST); reg_val|=(1<<BIT_DSP0_DBG_RST); writel_dsp(reg_val,CCU_BASE+CCMU_DSP_BGR_REG); writel_dsp(DSP0_START_ADDRESS,DSP0_CFG_BASE+DSP_ALT_RESET_VEC_REG); reg_val=readl_dsp(DSP0_CFG_BASE+DSP_CTRL_REG0); reg_val|=(1<<BIT_START_VEC_SEL); writel_dsp(reg_val,DSP0_CFG_BASE+DSP_CTRL_REG0); sunxi_dsp_set_runstall(1); //set runstall //set dsp clken reg_val=readl_dsp(DSP0_CFG_BASE+DSP_CTRL_REG0); reg_val|=(1<<BIT_DSP_CLKEN); writel_dsp(reg_val,DSP0_CFG_BASE+DSP_CTRL_REG0); //de-assert dsp0 reg_val=readl_dsp(CCU_BASE+CCMU_DSP_BGR_REG); reg_val|=(1<<BIT_DSP0_RST); writel_dsp(reg_val,CCU_BASE+CCMU_DSP_BGR_REG); load_image(img_addr,img_size); //load image to ram sram_remap_set(0); //set dsp use local ram sunxi_dsp_set_runstall(0); //clear runstall } Изменено 22 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 22 октября, 2023 Опубликовано 22 октября, 2023 (изменено) · Жалоба 3 hours ago, repstosw said: HiFi4 DSP не сбрасывается вместе с CPU 0/1 при нажатии кнопки RESET. Результат непредсказуем: после сброса DSP либо улетает в экспешн, либо работает. Вопрос решён. Проблема была в повторной инициализации регионов кеширования, которая приводила к эксепшену. В функции _cache_config : https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/master/arch/board-init.c#L11 Для повторных вызовов (при нажатии кнопки RESET на плате с T113-s3) нужно сделать инвалидацию кешей: #include "hal.h" static void _cache_config(void) { //для корректной работы DSP после сброса T113-s3 xthal_icache_all_invalidate(); xthal_dcache_all_invalidate(); /* 0x0~0x20000000-1 is non-cacheable */ xthal_set_region_attribute((void *)0x00000000, 0x20000000, XCHAL_CA_WRITEBACK,0); xthal_set_region_attribute((void *)0x00000000, 0x20000000, XCHAL_CA_BYPASS, 0); //... По-хорошему, после сброса надо запрещать кеширование и отключать предвыборку(prefetch) и сбрасывать конвеер. Чтобы потом снова разрешать всё. Вариант-минимум выше работает. Изменено 22 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 22 октября, 2023 Опубликовано 22 октября, 2023 (изменено) · Жалоба 45 минут назад, repstosw сказал: при нажатии кнопки RESET на плате с T113-s3) нужно сделать инвалидацию кешей: Да уж, странно, после повторного перезапуска оно понятно, как перевод управления из бутлоадера в осн. программу, но после аппаратного сброса... Такое впечатление, что аппаратный сброс != сброс ДСП))) Изменено 22 октября, 2023 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 22 октября, 2023 Опубликовано 22 октября, 2023 · Жалоба 53 minutes ago, mantech said: Да уж, странно, после повторного перезапуска оно понятно, как перевод управления из бутлоадера в осн. программу, но после аппаратного сброса... Такое впечатление, что аппаратный сброс != сброс ДСП))) Так в асмовском стартап-коде для Cortex A7 также запрещаются кеши и проводятся инвалидации. Entry: MRC p15, 0, r0, c1, c0, 0 @ Read CP15 System Control register BIC r0, r0, #(0x1 << 12) @ Clear I bit 12 to disable I Cache BIC r0, r0, #(0x1 << 2) @ Clear C bit 2 to disable D Cache BIC r0, r0, #0x1 @ Clear M bit 0 to disable MMU BIC r0, r0, #(0x1 << 11) @ Clear Z bit 11 to disable branch prediction MCR p15, 0, r0, c1, c0, 0 @ Write value back to CP15 System Control register MOV r0,#0 MCR p15, 0, r0, c8, c7, 0 @ I-TLB and D-TLB invalidation MCR p15, 0, r0, c7, c5, 6 @ BPIALL - Invalidate entire branch predictor array Вопрос в том, как это правильно сделать для DSP и желательно - с особой педантичностью, чтобы в любых случаях положительный результат был 100%. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 23 октября, 2023 Опубликовано 23 октября, 2023 · Жалоба Запустил спинлоки: https://electronix.ru/forum/topic/173928-mnogoyadernost-parallelnost-rabotaet-no-posle-sbrosa/?do=findComment&comment=1883076 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 24 октября, 2023 Опубликовано 24 октября, 2023 (изменено) · Жалоба Как-то понадобилось мне сделать задержки через DSP-таймер. В board_init.c есть такая функция: uint64_t xbsp_get_ccount(void). Задержку решил сделать так: u64 t=xbsp_get_ccount(); while(xbsp_get_ccount()-t<60000); //100 us wait (600 MHz timer) Не работает xbsp_get_ccount(): https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/master/arch/board-init.c#L130 Если использовать 32-битный таймер без учёта переполнения, то он переполнится через 7,15 секунд, что неприемлемо. 64 бита уже дадут переполнение через 355 839 cуток. Сделал так: Spoiler u32 Timer_Get(void) { u32 ccount; __asm__ __volatile__ ("rsr.ccount %0" : "=r"(ccount)); return ccount; } u64 Timer_Get64(void) //get 64 bit timer value { static u32 oldlo=0; //old LSW timer value static u32 oldhi=0; //MSW of 64 bit timer u32 curlo; u32 curhi; u64 tmr64; curlo=Timer_Get(); //get the 32 bit counter/timer value curhi=oldhi; //get the upper 32 bits of the 64 bit counter/timer if(curlo<oldlo)curhi++; //detect rollover oldhi=curhi; oldlo=curlo; tmr64=curhi; tmr64<<=32; tmr64|=curlo; return tmr64; } Изменено 24 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 180 24 октября, 2023 Опубликовано 24 октября, 2023 · Жалоба 5 часов назад, repstosw сказал: Как-то понадобилось мне сделать задержки через DSP-таймер. В board_init.c есть такая функция: uint64_t xbsp_get_ccount(void). Задержку решил сделать так: И Ваш, и чей-то приведенный пример будут работать криво, если функцию будут юзать из нескольких потоков или из потока и ISR, т.к. она не потокобезопасна🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 24 октября, 2023 Опубликовано 24 октября, 2023 · Жалоба 16 hours ago, Arlleex said: И Ваш, и чей-то приведенный пример будут работать криво, если функцию будут юзать из нескольких потоков или из потока и ISR, т.к. она не потокобезопасна🙂 Согласен. Есть ли какие-нибудь идеи как сделать функцию реентабельной? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 180 25 октября, 2023 Опубликовано 25 октября, 2023 · Жалоба 6 часов назад, repstosw сказал: Согласен. Есть ли какие-нибудь идеи как сделать функцию реентабельной? Критическая секция? Или: сделать таймер все-таки 32-битным, а статическое 32-битное раширение (для 64-битного результата) создавать "по месту" в коде. Хрень редьки не слаще - Вам все равно придется вызывать свою xbsp_get_ccount() чаще, чем раз в 7,15 секунд, иначе даже в однопоточном варианте эта функция сломается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 25 октября, 2023 Опубликовано 25 октября, 2023 · Жалоба 1 час назад, Arlleex сказал: чаще, чем раз в 7,15 секунд, Честно не представляю, для чего нужна задержка больше 7 сек??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 0 25 октября, 2023 Опубликовано 25 октября, 2023 · Жалоба On 10/25/2023 at 9:54 AM, mantech said: Честно не представляю, для чего нужна задержка больше 7 сек? я ещё меньше понимаю зачем такие задержки в ISR 🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 180 25 октября, 2023 Опубликовано 25 октября, 2023 · Жалоба 27 минут назад, sasamy сказал: я ещё меньше понимаю зачем такие задержки в ISR 🙂 Я акцентирую внимание не на задержках в ISR, разумеется, а на возможность вызова функции получения timestamp в ISR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 0 25 октября, 2023 Опубликовано 25 октября, 2023 (изменено) · Жалоба On 10/24/2023 at 3:11 AM, repstosw said: Не работает xbsp_get_ccount(): https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/master/arch/board-init.c#L130 она не работает из-за макроса XTHAL_GET_CCOUNT() https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/164696d952116d20100daefd7a475d2ede828eb0/arch/board-init.c#L133 https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/164696d952116d20100daefd7a475d2ede828eb0/include/xtensa/core-macros.h#L346 если вместо него использовать xthal_get_ccount() должно быть нормально хотя тут помоему ошибка https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/164696d952116d20100daefd7a475d2ede828eb0/arch/board-init.c#L137 в общем нафик она нужна вообще 🙂 Изменено 25 октября, 2023 пользователем sasamy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 25 октября, 2023 Опубликовано 25 октября, 2023 · Жалоба 1 час назад, Arlleex сказал: Я акцентирую внимание не на задержках в ISR, разумеется, а на возможность вызова функции получения timestamp в ISR. При желании - можно сделать на двух сцепленных аппаратно 32-битных таймерах. С простой процедурой чтения 64-битного значения, состоящей из 3 чтений счётчиков и одного сравнения с возвратом (циклическим). PS: Хотя конечно тратить аппаратные таймеры на такую ерунду это как то... по-ламерски что-ли.... Но в то же время: в некоторых МК аппаратных таймеров - "хоть попой ешь". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 25 октября, 2023 Опубликовано 25 октября, 2023 (изменено) · Жалоба 1 hour ago, sasamy said: если вместо него использовать xthal_get_ccount() должно быть нормально хотя тут помоему ошибка https://github.com/YuzukiHD/FreeRTOS-HIFI4-DSP/blob/164696d952116d20100daefd7a475d2ede828eb0/arch/board-init.c#L137 в общем нафик она нужна вообще 🙂 1. пробовал - эффекта положительного не дало 2. да. Ошибка в алгоритме 3. того же мнения 🙂 22 minutes ago, jcxz said: Но в то же время: в некоторых МК аппаратных таймеров - "хоть попой ешь". Там есть прерывание по достижению конкретного значения. Можно инкрементировать переменную в обработчике. Но это более ресурсоёмко, по сравнению с чтением одного волатильного регистра. Делителя к сожалению нет, так как это счётчик тактов ядра. Использую AVS периферийный таймеры от T113-s3 с делителями. Они тоже 32-битные, но с правильно установленными делителями там переполнение наступит не скоро. P.S. Кстати, вопрос всем. Кто-нибудь пробовал вместо прерываний IRQ задействовать FIQ ? Так называемые быстрые прерывания. Можно ли GIC400 запапить на FIQ? Изменено 25 октября, 2023 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться