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

repstosw

Участник
  • Постов

    2 694
  • Зарегистрирован

  • Победитель дней

    2

Весь контент repstosw


  1. Да, хотелось бы так как при сбросе нажатием кнопки. Пара ног, которые определяют с какого носителя грузиться всегда в одном состоянии и не меняются. С какого адреса у BF532 начинается загрузчик? Попробую сделать прямой переход туда.
  2. Да. Штатный загрузчик, который по двум ногам определяет, что надо скопировать код с spi-флешки AT45DB... и передать на него управление
  3. Здравствуйте! Конфигурация: ADSP Blackfin BF532, код выполняется из SDRAM, кеширование включено. Первичная загрузка - из SPI флешки 8-битной (микросхема AT45DB....), затем переход кода в SDRAM. Нужно сбросить процессор, чтобы снова подгрузилась программа из SPI-флешки. (причем именно чтобы снова повторился цикл загрузки с SPI-флешки, ттак как старый образ программы в L1 может быть уже разрушен - стеком, буферами DMA) Вот так - НЕ работает: while(1) __asm__ ("raise 1;"); Спецы, подскажите плиз как сбросить программно?
  4. Портирую очередную программу написанную на языке C с Win32 (x86) на BlackFin (BF532). При портировании возникла проблема: C-компилятор отказывается компилировать объявление переменных внутри цикла: for(int i=0;i<10;i++) ..... Стоит сделать так - всё работает. int i; for(i=0;i<10;i++) ..... Понимаю, если по всей программе так штук 10-20... Но проблема как раз в том что в программе таких циклов огромное множество! Да и времена старой давности прошли, когда всё было строго. Есть ли у VDSP C compiler ключ какой-нибудь, чтобы понимать объявления переменных внутри цикла? Я знаю, что тот же Keil ARM C compiler поддерживает ключ -C99, при активации которого можно делать такого рода объявления и не только их! Так как? Способ переименования файлос в CPP не предлагать, нужно скомпилировать именно компилером C, а не C++ Всё, разобрался. Проблема была в том что читал протухший мануал C/C++ Compiler and Library Manual for Blackfin® Processors версии VDSP 4.0. В 5.x уже есть опция -c99 :smile3046: OFFTOP: В OpenWatcom C эта опция так и осталась недокументированной: -za99 и -aa
  5. Любой участок можно замерить теми же CYCLES, просто вплотную к оптимизации звука ещё не подошел. Кстати, отсутствие мат-сопроцессора в Блекфин меня в свое время очень разочаровало. Есть например приставка SNES, в которой плавучка просто необходима для расчета эффекта полупрозрачности и поворота на произвольный градус. Вот есть STM32 , у них есть мат-сопроцессор, но не более 300 МГц, то не радует. Есть ли камни контроллеров с тактовой от 1 ГГц с FPU и открытой архитектурой? Pi не предлагать, так как закрыта.
  6. Ещё обнаружил интересную ситуацию: Visual DSP 5.1.2 даёт рабочий код, а если собрать в VDSP 5.0, то эмулятор зависает в момент когда должен появиться звук. Если не использовать -fp-fast, то обе среды дают рабочий код. Подозреваю, что в 5.0 -fp-fast выполнен через ОПУ и не гарантирует корректной работы с эмуляцией плавучки :)))
  7. На самом деле при включенном кешировании арбитраж шины не слишком сильно душит производительность всей системы в целом. Иначе, почему память видеокарт в ПК отображена на общее адресное пространство процессора? В неё тоже можно писать и читать из нее процессором и ПК не тормозит из-за арбитража шины. Понимаю, что видео-карта сама может ворочать в своей памяти и будет быстрее, но доступ со стороны CPU сохранен. Ну и финальный вопрос: вы можете примерно предположить, во сколько раз должна подняться производительность системы, если дисплей перевешать на PPI?
  8. В своё время я поостерёгся использовать PPI + RGB-интерфейс дисплея. Показалось, что постоянная отрисовка на дисплей(формирование развертки видео-сигнала) отрицательно скажется на всей работе системы в целом. Не помню чем оттолкнула эта идея, то-ли от того что надо будет выжидать освобождения памяти или ещё чего-то... Давно это было. Вопрос про PPI был в другом: можно ли его настроить на управление контроллером S6E63D6 или тупо видео-сигнал? Хочется чтобы регенерацией экрана занимался именно S6E63D6 , а не ДМА Блекфина через PPI. И шину разгрузить хотелось бы :) Речь идет об этом девайсике: Решил "тряхнуть стариной" и портировать ещё несколько эмуляторов на него
  9. Чуть-помогло (+5 FPS), сделал -fast-fp , бинарник чуть-вырос, что свидетельствует о замене либы, что радует. Принял решение временно поиграться с загрузчиком - в нем менял времянки, увы - те что стоят оптимальны по устойчивости и быстродействию. Попытка укоротить setup, hold, write - приводит к плачевным результатам: кривая картинка на дисплее или её отсутствие. Кстати, дисплей буферизован - он подключен к шине через микросхему буфера, чтобы избежать ёмкостного шунтирования SDRAM, которая тоже висит на шине. Если дисплей привешать к PPI, то к нему можно будет обращаться как к массиву точек? Или PPI генерит свою развёртку ? Дисплей PPT9999-A003-06-Q со встроенным контроллером S6E63D6. Вот драйвер для него (тоже сам писал): /* Display PPT9999-A003-06-Q S6E63D6 Display Controller Driver */ #define OLED_Command (*(volatile u16*) 0x20000000) #define OLED_Data (*(volatile u16*) 0x20010000) const u8 Font8x8[2048]= { //тут моноширный шрифт 8x8 пикселей кодировка DOS :) } u16 OLED_Key; //Цвет прозрачности u16 OLED_Back; //Цвет фона void OLED_Register(u8 c,u16 d) { OLED_Command=c; OLED_Data=d; } void OLED_Prepare(void) { OLED_Command=0x23; //Select 18-/16-bit Data Bus Interface OLED_Register(0x03,0x0111); //16-bit Mode OLED_Register(0x10,0x0000); //IC Standby Off OLED_Register(0x05,0x0000); //Display Off OLED_Register(0x18,0x003D); //Frame Rate > 80 Hz OLED_Register(0xF8,0x000F); //VGH = +5V OLED_Register(0xF9,0x000F); //VGL = -5V OLED_Register(0x70,0x2B80); //Gamma Top/Bottom R OLED_Register(0x71,0x3600); //Gamma Top/Bottom G OLED_Register(0x72,0x3E00); //Gamma Top/Bottom B OLED_Register(0x73,0x1F19); //Gamma Top Bottom R1,2 OLED_Register(0x74,0x2214); //Gamma Top Bottom R3,4 OLED_Register(0x75,0x221B); //Gamma Top Bottom G1,2 OLED_Register(0x76,0x1E16); //Gamma Top Bottom G3,4 OLED_Register(0x77,0x241E); //Gamma Top Bottom B1,2 OLED_Register(0x78,0x2617); //Gamma Top Bottom B3,4 SimpleDelay(1000000); OLED_Register(0x05,0x0001); //Display On } void OLED_Rectangle(u16 xs,u8 ys,u16 xe,u8 ye) { OLED_Register(0x35,319-xe); OLED_Register(0x36,319-xs); OLED_Register(0x37,(ys<<8)|ye); OLED_Register(0x20,ys); OLED_Register(0x21,319-xs); OLED_Command=0x22; } void OLED_Clear(u16 Color) { register u32 i; OLED_Rectangle(0,0,319,239); for(i=0;i<320*240;i++) OLED_Data=Color; } void OLED_OutChar(u16 x,u8 y,u8 c,u16 k) { register u32 i; OLED_Rectangle(x<<3,y<<3,(x<<3)+7,(y<<3)+7); for(i=0;i<64;i++) { if(((Font8x8[(c<<3)+(i>>3)]>>(7-(i&7)))&1)) OLED_Data=k; else OLED_Data=OLED_Back; } } void OLED_OutString(u16 x,u8 y,u8* s,u16 k) { register u32 i=0; while(s[i]) { OLED_OutChar(x+i,y,s[i],k); i++; } } void OLED_OutNumber(u16 x,u8 y,u16 n,u16 k) { OLED_OutChar(x ,y,(n/100)%10+'0',k); OLED_OutChar(x+1,y,(n/ 10)%10+'0',k); OLED_OutChar(x+2,y, n %10+'0',k); } void OLED_OutSprite(u16 x,u8 y,u16 w,u8 h,const u8* s) { register u32 i; register u16 c; register u16 *S=(u16*)s; OLED_Rectangle(x,y,x+w-1,y+h-1); for(i=0;i<(w*h);i++) { if((c=S[i])!=OLED_Key) OLED_Data=c; else OLED_Data=OLED_Back; } }
  10. Не про то вопрос был. Когда я меняю параметры асинхронного банка (на котором висит дисплей) ПОВТОРНО - новые параметры не вступают в силу! В мануале написано, что не следует менять параметры контроллера шины EBIU именно AMB во время его работы (тоесть когда уже проинициализирован) - мой случай. Тогда как их менять, если по зарез надо? При нажатии на reset ведь как-то работает. Может есть какой-нибудь способ перезагрузить параметры шины? Это плохо! Весь код звуковой системы на плавучке. Эмулятор был написан для x86 на языке Cи, при перекладке кода на Blackfin, будет эмуляция FPU.
  11. Попробовал поставить частоту дискретизации 22050 Гц вместо 44100. Скорость всей эмуляции возросла до 75 FPS. Из чего можно сделать вывод, что звуковая система занимает приличный ресурс времени.
  12. Так и хочется натянуть свой опыт, да? Не выйдёт. Не мешайте говно с мёдом....... Для начала советую поразмыслить над тем, как эмуляция вашего ЧМ-модулятора относится к: 1) Capcom System QSound 2) Yamaha YM2151 3) OKI6295 Вы хотя бы один из этих чипов эмулировали ? Более на дебаты теоретиков не реагирую. ------------------ А теперь вопросы: 1) Насколько тормозной тип double для BlackFin ? Имеет ли смысл его заменить float ? 2) Каким образом можно изменить параметры растактовки шины EBIU для асинхронного банка, когда он был инициализирован ранее? Тоесть переинициализировать. После того как EBIU запущен, изменить параметры перезаписью в региcтры: EBIU_AMBCTL0 EBIU_AMBCTL1 EBIU_AMGCTL не получается!
  13. Если критические участки в программе переписывать на Ассемблере (эмуляция процессоров, эмуляция графики / звука), то производительность должна вырасти. Это выходит за рамки моей задачи, так как было нужно портировать эмулятор (автором которого я НЕ являюсь) на устройство с ADSP BF533. В целом результатом доволен, быстродействие вышло таким: 45 - 55 FPS при эмуляции CPS1 30 - 40 FPS при эмуляции CPS2. При этом показывается каждый кадр, звуковой поток не рвётся (темп плавно понижается). Система CPS слишком наворочена, так как графика/звук у неё заточены под игры(быстрые). И не надо сравнивать какой-то допотопный КР580ВМ80 в связке с убогой графикой (Спектрум небось? ) Ну и вдогонку: телефон с процессором ARM9 800 МГц воспроизводит данный эмулятор хуже (не мой порт), и КПК на 300 МГц ещё хуже! Замерял количество полных отрисовок экрана за 1 секунду (Буфер 320x224x2 из SDRAM + конвертация 16-битной палитры + вывод на дисплей) - 188 раз. Мерял этим: static __inline__ enable_cycles(void) { __asm__ __volatile__ ("R2=SYSCFG;"); __asm__ __volatile__ ("BITSET(R2,1);"); __asm__ __volatile__ ("SYSCFG=R2;"); } static __inline__ disable_cycles(void) { __asm__ __volatile__ ("R2=SYSCFG;"); __asm__ __volatile__ ("BITCLR(R2,1);"); __asm__ __volatile__ ("SYSCFG=R2;"); } static __inline__ start_cycles(void) { __asm__ __volatile__ ("R2=0;"); __asm__ __volatile__ ("CYCLES=R2;"); __asm__ __volatile__ ("CYCLES2=R2;"); } static __inline__ u64 get_cycles(void) { u32 t0,t1; __asm__ __volatile__ ("%0=cycles;%1=cycles2;":"=d"(t0),"=d"(t1)); return t0|((u64)t1<<32); } Это типа троллинг? :santa2: Полный перечень того что делается:
  14. Это FPS всего эмулятора, а не экранный FPS: while(!quit) { // эмуляция процессоров Z80, M68020 // эмуляция видео-подсистемы (4 графических слоя) // эмуляция звуковой системы (FM синтезатор + ADPCM + Wav sound*4 канала) // эмуляция системы ввода // эмуляция памяти //эмуляция ROM-set-а // отрисовка на дисплей // вывод звука // считывание клавиш } Вот это всё ВМЕСТЕ - 55 FPS !
  15. Сделал DMA по прерываниям. Буфер - 320 пикселов (одна строка) 640 байт в L1, уже сконверченная палитрой(тоже в L1). Даём DMA команду на отрисовку строки, а сами делаем дальше остальные вещи. Прерывание по окончанию пересылки строки снова запускает DMA для новой строки. И так пока экран не отрисуется весь. Код что ниже - рабочий, удаось поднять общую скорость (отрисовка экрана + вся программа) на 15 FPS !!! :rolleyes: Получается, что отрисовка экрана и работа процессора немного распараллелились. Макросы использую, потому что 100% гарантия что с-инлайнится. #define SRC_PITCH 544 #define DST_HEIGHT 224 #define SCR_WIDTH 320 #define SCR_HEIGHT 240 //0xFF800000..0xFF803FFF //L1_DATA_A #define NB (SCR_WIDTH<<1) #define L1_MEMORY 0xFF804000 #define L1_BUF (L1_MEMORY-NB) #define DMA_INIT \ { \ *pMDMA_S1_PERIPHERAL_MAP=0x0040; \ *pMDMA_S1_START_ADDR=(void*)L1_BUF; \ *pMDMA_S1_X_COUNT=(NB>>1); \ *pMDMA_S1_X_MODIFY=2; \ *pMDMA_S1_Y_COUNT=1; \ *pMDMA_S1_Y_MODIFY=0; \ *pMDMA_D1_PERIPHERAL_MAP=0x0040; \ *pMDMA_D1_START_ADDR=(void*)&OLED_Data; \ *pMDMA_D1_X_COUNT=(NB>>1); \ *pMDMA_D1_X_MODIFY=0; \ *pMDMA_D1_Y_COUNT=1; \ *pMDMA_D1_Y_MODIFY=0; \ } \ #define DMA_START \ { \ *pMDMA_S1_CONFIG=WDSIZE_16|DMAEN; \ *pMDMA_D1_CONFIG=WDSIZE_16|WNR|DMAEN|DI_EN; \ } \ #define DMA_STOP \ { \ *pMDMA_S1_CONFIG=0; \ *pMDMA_D1_CONFIG=0; \ } \ extern struct mame_display current_display; u16* src; EX_INTERRUPT_HANDLER(DMA_ISR) { static u16 y=DST_HEIGHT; *pMDMA_D1_IRQ_STATUS=1; y--; if(y) { register u16* buf=(u16*)L1_BUF; register u16 i; for(i=0;i<(NB>>1);i++)*buf++=palette_16bit_lookup[*src++]; src+=(SRC_PITCH-SCR_WIDTH); DMA_START } else { y=DST_HEIGHT; DMA_STOP } } void DMA_Init_Interrupt(void) { *pSIC_IMASK&=0xFFBFFFFF; //Disable MDMA1 interrupt *pSIC_IAR2=(*pSIC_IAR2&0xF0FFFFFF)|0x06000000; register_handler(ik_ivg13,DMA_ISR); *pSIC_IMASK|=0x00400000; //Enable MDMA1 interrupt } int win_init_window(void) { // disable win_old_scanlines if a win_blit_effect is active if (win_blit_effect != 0) win_old_scanlines = 0; DMA_Init_Interrupt(); DMA_INIT OLED_Clear(0x0000); return 0; } void dib_draw_window_DMA(void) { OLED_Rectangle(0,(SCR_HEIGHT-DST_HEIGHT)>>1,SCR_WIDTH-1,((SCR_HEIGHT+DST_HEIGHT)>>1)-1); src=(u16*)(((u32)current_display.game_bitmap->base)+17536+64); register u16* buf=(u16*)L1_BUF; register u16 i; for(i=0;i<(NB>>1);i++)*buf++=palette_16bit_lookup[*src++]; src+=(SRC_PITCH-SCR_WIDTH); DMA_START }
  16. Всё сделал как написали, работает исправно, но прироста скорости всёравно нет. Пробовал убрать dma_wait, скорость повышается, но экран отрисовывается на 1/4 и весь трясётся (что и понятно почему). Попробую не ждать, а в обработчик прерывания засунуть вывод на дисплей через DMA. Рабочий код ниже: #ifndef __DMA_H__ #define __DMA_H__ //0xFF800000..0xFF803FFF //L1_DATA_A #define NB 32 #define buf0 (0xFF803FC0-(NB<<1)) #define buf1 (0xFF803FE0- NB ) #define DMA_INIT \ { \ *pMDMA_S1_PERIPHERAL_MAP=0x0040; \ *pMDMA_S1_X_COUNT=(NB>>1); \ *pMDMA_S1_X_MODIFY=2; \ *pMDMA_S1_Y_COUNT=1; \ *pMDMA_S1_Y_MODIFY=0; \ *pMDMA_D1_PERIPHERAL_MAP=0x0040; \ *pMDMA_D1_START_ADDR=(void*)&OLED_Data; \ *pMDMA_D1_X_COUNT=(NB>>1); \ *pMDMA_D1_X_MODIFY=0; \ *pMDMA_D1_Y_COUNT=1; \ *pMDMA_D1_Y_MODIFY=0; \ } \ #define DMA_SEND(buf) \ { \ *pMDMA_S1_START_ADDR=(void*)buf; \ *pMDMA_S1_CONFIG=WDSIZE_16|DMAEN; \ *pMDMA_D1_CONFIG=WDSIZE_16|WNR|DMAEN; \ } \ #define DMA_WAIT while(*pMDMA_D1_IRQ_STATUS&DMA_RUN); #define MEMORY_COPY(dst,src) \ { \ register u16 i; \ register u32* d=(u32*)dst; \ register u32* s=(u32*)src; \ for(i=0;i<(NB>>2);i++) *d++=*s++; \ } \ #define PALETTE_CONVERT(buf) \ { \ register u16 i; \ register u16* c=(u16*)buf; \ for(i=0;i<(NB>>1);i++)*c++=palette_16bit_lookup[*c]; \ } \ #endif void dib_draw_window_DMA(void) { register u16* src=(u16*)(((u32)current_display.game_bitmap->base)+17536+64); register u16 y=DST_HEIGHT; while(y--) { register u16 x=(u16)SCR_WIDTH/(u16)NB; MEMORY_COPY(buf1,src) PALETTE_CONVERT(buf1) src+=(NB>>1); while(x--) { MEMORY_COPY(buf0,src) DMA_SEND(buf1) PALETTE_CONVERT(buf0) src+=(NB>>1); DMA_WAIT MEMORY_COPY(buf1,src) DMA_SEND(buf0) PALETTE_CONVERT(buf1) src+=(NB>>1); DMA_WAIT } src+=(SRC_PITCH-SCR_WIDTH-(NB>>1)); } }
  17. Весь цикл программы можно упрощенно представить так: while(!Quit) { эмулируем... рисуем... } Если запустить DMA и отрисовывать построчно, то всеравно прийдется ждать окончания работы DMA чтобы подсунуть ему новую линию с декодированной палитрой при передаче. В момент работы ДМА, процессор всеравно будет брать индексы из SDRAM, а это снова шина. В итоге процессор и ДМА будут рвать шину по кускам.
  18. Там очень хитрый буфер. И он "грязный", потому что по-очереди отрисовываются несколько спрайтовых плоскостей (видеосистема Capcom PlaySystem 1/2). Если преобразовывать палитру там, то боюсь всё замедлится в число раз, равное числу плоскостей. Процессор к сожалению будет конвертить палитру, а DMA так же занимать шину во время транзакций. И можно будет авансом заранее сделать не более 1 цикла эмуляции, до того как экран будет полностью не отрисован, иначе пропуск кадра будет что плохо. Проверил работу процедуры. На практике вышло чуть-лучше. Но ненамного. Вот код всей процедуры - пока не вычесал, затронут только внутренний цикл. .section/DOUBLE32 program; .extern _current_display; .extern _palette_16bit_lookup .global _dib_draw_window_asm; _dib_draw_window_asm: [--SP] = (P5:3); P1.L = _current_display+4; P1.H = _current_display+4; P1 = [P1]; P2 = 17600; P0 = 224; I0 = 0; I0.H = 8193; P1 = [P1 + 16]; P5.L = _palette_16bit_lookup; P5.H = _palette_16bit_lookup; P4 = 4; P1 = P1 + P2; [SP + 12] = P1; LOOP CycleYL LC1 = P0; CycleY: LOOP_BEGIN CycleYL; P1 = [SP + 12]; P0 = 80; P3 = [P5]; R5=P3; LOOP CycleXL LC0 = P0; CycleX: LOOP_BEGIN CycleXL; R0=W[P1 + 2] (Z) ; R0=R0<<1 || R1=W[P1 ++ P4] (Z) ; R1=R1<<1 || R2=W[P1 + 2] (Z) ; R2=R2<<1 || R3=W[P1 ++ P4] (Z) ; P0=R3 ; P0=P3+(P0<<1) ; //Preg read after write which requires 4 extra cycles R0=R0+R5 (NS) || R7.L=W[P0] ; I1=R0 ; R1=R1+R5 (NS) || R6.H=W[I1] ; //Dagreg read after write which requires 4 extra cycles I1=R1 ; R2=R2+R5 (NS) || R6.L=W[I1] ; //Dagreg read after write which requires 4 extra cycles I1=R2 ; R3=R3+R5 (NS) || R7.H=W[I1] || [I0]=R6; //Dagreg read after write which requires 4 extra cycles [I0]=R7 ; LOOP_END CycleXL; .P35L13: P0 = [SP + 12]; P1 = 1088; P1 = P0 + P1; //Preg read after write which requires 3 extra cycles [SP + 12] = P1; LOOP_END CycleYL; .P35L14: (P5:3) = [SP++]; RTS; А вот это разочаровало: //Preg read after write which requires 3 extra cycles //Dagreg read after write which requires 4 extra cycles Выходит вся оптимизация и конвеер лесом?? Пока получилось 35 - 40 FPS, в идеале должно быть 60 FPS (частота смены кадров NTSC)
  19. Процессор разогнан до 550 МГц. Шина CCLK/3=183 МГц. SDRAM работает на 183 МГц с CAS latency =2. Кеш включен (для кода и данных). Дисплей 7 тактов (setup + write + hold), в эквиваленте 183/7 = 26 МГц. Шина данных 16 бит. Обращение к 32 битам идет подряд как 2 раза по 16 бит, адрес+1. Но та как адресов у контроллера дисплея нет (точнее есть и висит он на самом старшем адресном бите), инкремент адреса не мешает. Это небольшой burst из двух коротких слов :) Сделал 14 строк ассемблера на 4 пикселя. Раньше было 11 строк на 2 пикселя. Ппришлось попарить мозг, пока вышло так (задействовал конвеер Блекфина). Пока не проверял в работе, но компилируется. Эффективность кода возросла на 36% #define PIXEL \ { \ __asm__ volatile (" R0=W[P0++] (Z);"); \ __asm__ volatile ("R0=R0<<1 || R1=W[P0++] (Z);"); \ __asm__ volatile ("R1=R1<<1 || R2=W[P0++] (Z);"); \ __asm__ volatile ("R2=R2<<1 || R3=W[P0++] (Z);"); \ __asm__ volatile ("P3=R3 ;"); \ __asm__ volatile ("P3=P5+(P3<<1) ;"); \ __asm__ volatile ("R0=R0+R5 (NS) || R1.H=W[P3] ;"); \ __asm__ volatile ("I0=R0 ;"); \ __asm__ volatile ("R1=R1+R5 (NS) || R0.L=W[I0] ;"); \ __asm__ volatile ("I1=R1 ;"); \ __asm__ volatile ("R2=R2+R5 (NS) || R0.H=W[I1] ;"); \ __asm__ volatile ("I2=R2 ;"); \ __asm__ volatile ("R3=R3+R5 (NS) || R1.L=W[I2] || [P1]=R0 ;"); \ __asm__ volatile (" [P1]=R1 ;"); \ \ } \ К сожалению объем графических данных не позволяет сделать буфер на строку во внутренней памяти + DMA. Потому что программу писал не я. Это эмуляция аркадных автоматов Capcom Play System 1/2, там палитра больше 256 цветов :) Вот это детище портировал на BF533: https://osdn.net/projects/mamespi/releases/2046 / https://www.zophar.net/mame/caname.html
  20. У Блекфина система команд такая, что особо не разбежишься. Всё очень строго, и конвеер там допускает инструкции в строго определенной последовательности. Строковых блочных команд нет вроде. Смотрел внимательно тут: http://microsin.net/programming/dsp/blackf...ence-part1.html http://microsin.net/programming/dsp/blackf...ence-part2.html Максимум получилось избавиться от 2 инструкций - вместо 11 строк кода имею 9: P1 - адрес src, P3 - адрес палитры, P5 - видео-регистр дисплея __asm__ volatile ("R0=W[P1++] (Z);"); \ __asm__ volatile ("P0=R0;"); \ __asm__ volatile ("R0=W[P1++] (Z);"); \ __asm__ volatile ("P2=R0;"); \ __asm__ volatile ("P0=P3+(P0<<1);"); \ __asm__ volatile ("P2=P3+(P2<<1);"); \ __asm__ volatile ("R1.H=W[P0];"); \ __asm__ volatile ("R1.L=W[P2];"); \ __asm__ volatile ("[P5]=R1;"); \
  21. По-разному пробовал: //#define PIXEL {OLED_Data_32=(palette_16bit_lookup[src[1]]<<16)|palette_16bit_lookup[src[0]];src+=2;} //#define PIXEL {OLED_Data_32=palette_16bit_lookup[*src++];OLED_Data_32=palette_16bit_lookup[*src++];} Выходит так: 1 LOOP_BEGIN .P38L6L; 2 R0 = W[P1 + 2] (Z); 3 P0 = R0; 4 R0 = W[P1 ++ P5] (Z); 5 P2 = R0; 6 P0 = P3 + (P0<<1); 7 R0.L = W[P0]; 8 P0 = P3 + (P2<<1); 9 R1 = R0 << 16 || R0 = W[P0] (Z); 10 R0 = R1 | R0; 11 [P4] = R0; 12 LOOP_END .P38L6L; 1 LOOP_BEGIN .P38L6L; 2 R0 = W[P1++] (Z); 3 P2 = R0; 4 P2 = P4 + (P2<<1); 5 R0 = W[P2] (Z); 6 [P5] = R0; 7 R0 = W[P1++] (Z); 8 P2 = R0; 9 P2 = P4 + (P2<<1); 10 R0 = W[P2] (Z); 11 [P5] = R0; 12 LOOP_END .P38L6L; Не особо вижу разницы, да и код на внешний вид действительно неплотный. Вот это : R1 = R0 << 16 || R0 = W[P0] (Z); - параллельное выполнение команд? LDM R0!, {R1-R8};сорри за ARM wink.gif и получит burst-чтение SDRAM Это 8 порций по 32 бита подряд за одно чтение? Есть ли такая фишка в Блекфинах? :rolleyes: :rolleyes: :rolleyes: У Intel-ловских процессоров есть подобное с mmx- и xmm- регистрами: 8 байт за раз переслать можно аналогично!
  22. Согласен, иначе следующие PIXEL при if()else... не попадут под условие. Попробую вернуть внутренний цикл и посмотреть что сделает компилятор(асм- листинг). Пробовал процедуру отрисовки скопировать в L1 Code SRAM (64K) из SDRAM. Вот так: memcpy((void*)0xFFA00000, (const void*)Draw_Screen,0x8000); //скопировал 32 килобайта (с запасом, точный размер функции в map-файле) // 0xFFA00000 - 0xFFA0FFFF Code SRAM (64K) При передаче управления туда - зависает. Передаю управление так: #define CALL(Address) (*(void(*)(void)) Address)(); //Вызов функции по её адресу CALL(0xFFA00000) Что не так? Как правильно грузить данный участок памяти кода L1 Code SRAM ? (от кеширования этот участок свободен). Есть ли #pragma в Visual DSP позволяющая сделать отдельные фуккции позиционно-независимыми? (position independent) ? Насколько оправдано размещать отдельно код процедуры отрисовки во внутренней памяти, если включено кеширование для SDRAM (I cache + D cache) ? Приложение большое - около 2 МБайт.
  23. Быстро, в смысле уменьшить время перекидывания буфера на экран. Перерисовка экрана полная. Посмотрел листинг функции на ассемблере, мой опыт не позвояет сказать насколько оптимально делает VDSP++, листинг приложил. Знающих в ассебмлере, прошу глянуть листинг - оцените насколько неоптимально или оптимально сделал компилятор свою работу? Если же слабые места будут, то буду копать ассемблер BF. asm.txt Это два пиксела по 16 бит каждый.
  24. Здравствуйте. Использую ADSP BF533 + SDRAM + OLED Display (подключен к EBIU 16 бит). Программа загружена в SDRAM, кэширование включено: для данных и программ, политика write back. Дисплей не прокеширован. Периодически нужно отрисовывать кадр на дисплей, как можно быстрее. Видеопамять дисплея - 16 бит на пиксел, адрес автоматически увеличивается на +1 пиксел после отрисовки точки. Есть буфер в котором строистя изображение - источник. Кодировка цветов через палитру. Приемником выступает сам дисплей. Палитру засунул в L1_DATA_B, чтобы ускорить доступ к ней (попиксельно идет обращение). Буфер источника находится в SDRAM (кеширована). За один присест сразу рисую 2 пиксела по 16 бит, по сути формирую 32-битное обращение к памяти дисплея: #define OLED_Data_32 (*(volatile u32*) 0x20010000) Хотя он подключен к 16-битной шине. Фрагмент кода: //u8, u16, u32 - char, short и long соответственно 1 2 4 байта UINT16* palette_16bit_lookup=(UINT16*)0xFF900000; //L1_DATA_B 16KB Тут палитра #define SRC_PITCH 544 /* Ширина источника */ #define DST_HEIGHT 224 /* Высота приемника */ #define SCR_WIDTH 320 /* Ширина дисплея */ #define SCR_HEIGHT 240 /* Высота дисплея */ #define OLED_Data_32 (*(volatile u32*) 0x20010000) /* Это регистр данных дисплея с автоинкрементом адреса, подключен к EBIU Blackfin - разрядность 16 бит */ #define PIXEL OLED_Data_32=(palette_16bit_lookup[src[1]]<<16)|palette_16bit_lookup[src[0]];src+=2; /* выводим сразу 2 пиксела(по 16 bit) на дисплей, цвет берем из палитры */ #define PIXELLAST OLED_Data_32=(palette_16bit_lookup[src[1]]<<16)|palette_16bit_lookup[src[0]];src+=(SRC_PITCH-SCR_WIDTH+2); /* последние 2 пиксела */ void Draw_Window(struct BITMAP *bitmap) //Отправка буфера на дисплей { register u16* src=(u16*)(((u32)bitmap->base)+17536+64); //Стартовый адрес источника register u32 y=DST_HEIGHT; OLED_Rectangle(0,(SCR_HEIGHT-DST_HEIGHT)>>1,SCR_WIDTH-1,((SCR_HEIGHT+DST_HEIGHT)>>1)-1); //Задаёт прямоугольную область 320x224 по центру дисплея (сам дисплей 320x240) while(y--) //цикл по Y, цикл по X развернут на 320 точек (160 слов) { PIXEL /* 159 раз */ PIXEL PIXEL /* ... */ PIXEL PIXEL PIXELLAST /* 160-й раз */ } } Цикл по X развернут макросами для ускорения. Компилировал это дело в Visual DSP++ 5.1.2 - пробовал такую оптимизацию: Speed 100, Interprocedural optimization, Frame-pointer optimization. Код работает как нужно , но подозреваю, что можно сделать быстрее! Дает ли прирост скорости 32-битное обращение к регистру данных дисплея, когда он подключен к 16-битной шине? Фактически это 2 операции подряд по 16 бит с увеличением адреса (не используются). Как можно сделать ещё быстрее? Рассмотрю любые способы: от изменения алгоритма, до системного управления процессором (кеширование, выравнивание). Пробовал изменить тайминги шины EBIU, ничего не меняется. Как можно пере-инициализировать контроллер асинхронной шины, когда он уже работает?
×
×
  • Создать...