-
Постов
2 694 -
Зарегистрирован
-
Победитель дней
2
Весь контент repstosw
-
Меня эта проблема достала и на UART2 - то грузится, то нет. Замерил логические уровни на бут-пинах: там где должна быть лог. "1" напряжение 1.8V вместо положеных 3-3.3V. Подтягивающие резисторы на 9,1 кОм оказались многоваты. Заменил на 1,1 кОм - теперь лог. уровень 3.1V что в норме. Глючить перестало! А я уже думал что UART'ы подпаливаются )))
-
Выкинул RESTRICT - всё заработало, но число кадров в секунду то же - 70
-
Попробовал адаптировать Ваш последний фрагмент кода под свои нужды - приёмник LCD экран, без инкремента адреса: void LCD_Picture2(float const * restrict src,int n) { float * restrict dst=(float*)0x60004000; //LCD Data Port do { _amem8((void*)dst)=_amem8((void*)src); src+=2; } while(n-=2); } Вызов: LCD_Picture2((float const*)Picture,sizeof(Picture)>>2); Не работает как надо: экран вместо картинки показывает несколько строк, залитыми серым цветом.
-
C6745 CPU vs. DMA, вопрос
repstosw опубликовал тема в Сигнальные процессоры и их программирование - DSP
Сделал замеры скорости отрисовки кадра на дисплей через DMA и с помощью CPU. Дисплей: 480x320 16 бит на точку. Интерфейс - параллельная шина 8 бит. Клок шины 91.2 МГц . Времянки для дисплея на EMIFA такие: void EMIFA_Init(void) { EMIFA_CE2CFG= (0<<31)| //Select Strobe (0 - Normal Mode) (0<<30)| //Extend Wait (0 - disabled) (0<<26)| //Write setup width 0..15 (0 - EMA_CLK/1) (1<<20)| //Write strobe width 0..63 (0 - EMA_CLK/1) (0<<17)| //Write hold width 0..7 (0 - EMA_CLK/1) (0<<13)| //Read setup width 0..15 (0 - EMA_CLK/1) (1<< 7)| //Read strobe width 0..63 (0 - EMA_CLK/1) (0<< 4)| //Read hold width 0..7 (0 - EMA_CLK/1) (0<< 2)| //Minimum Turn-Around time (min. num. of EMA_CLK cycles between reads & writes - 1) 0 ; //Asynchronous Data Bus Width (0 - 8 bit) } Тоесть всё на максимуме, кроме Write Strobe Width. Если его укоротить до 0, то изображение начинает "ехать по горизонтали". Поэтому тестировался стабильный вариант. Ядро на 456 МГц, кеширование L1P, L1D ,L2 включены. Регионы SDRAM прокешированы. Адрес картинки в SDRAM выровнен на границу 256 бит. Трансфер идёт с SDRAM в порт LCD_Data. Дополнительно выставил максимальный размер бурста: CFGCHIP0=(2<<2)|2; //PLL MMRs unlock & TC1 64 byte & TC0 64 byte (DBS) Если выставить бурст 32 байта - скорость не меняется. Но если поставить 16 - то скорость немного падает. DMA отрисовывает 74 кадра в секунду. Это выходит скорость : 320*480*2*74 = 21,68 МБайт/с. CPU отрисовывает немного меньше - 70 кадров/с. Код отрисовки - через 64-битный указатель: void LCD_Picture(u32 o,u32 n) //64 bit transfer { n>>=3; register u64 *P=(u64*)&Picture[o]; while(n--)LCD_D64=*P++; } Если отрисовывать через 32- 16- и особенно 8- битные указатели - скорость линейно падает. Оптимизация компилятора - максимальная "5" по скорости. Регион портов LCD не кеширован. Кстати, отключал кеширование в разных комбинациях - DMA работает с одинаковой скоростью и на кеширование ему начихать. Вопрос собственно вот в чём - возможно ли получить бОльшую скорость отрисовки без изменения аппаратной части ? Включить Write Buffer для порта LCD или изменить политику кеширования? Или это предел? Можно ли разогнать EMIFA до 101,3 МГц ? - с такой тактовой скорость отрисовки уже выходит чуть больше. -
Разобрался. В CMD-файле надо было добавить секцию: /* Interrupt */ .vecs > EMIFBSDRAM Или вообще выкинуть из intvecs.asm объявление секции и слинковать как обычно: ; .sect ".vecs" --- закомментировано .align 1024 _intcVectorTable: _vector0: VEC_ENTRY _c_int00 ;RESET _vector1: VEC_ENTRY _vec_dummy ;NMI _vector2: VEC_ENTRY _vec_dummy ;RSVD ... Рабочий код таймера по прерываниям: #include <c6x.h> #include "Type.h" #define TIMER_TIM12 (*(IO u32*)0x01C20010) /* Timer Counter Register 12 */ #define TIMER_TIM34 (*(IO u32*)0x01C20014) /* Timer Counter Register 34 */ #define TIMER_PRD12 (*(IO u32*)0x01C20018) /* Timer Period Register 12 */ #define TIMER_PRD34 (*(IO u32*)0x01C2001C) /* Timer Period Register 34 */ #define TIMER_TCR (*(IO u32*)0x01C20020) /* Timer Control Register */ #define TIMER_TGCR (*(IO u32*)0x01C20024) /* Timer Global Control Register */ #define TIMER_REL12 (*(IO u32*)0x01C20034) /* Timer Reload Register 12 */ #define TIMER_REL34 (*(IO u32*)0x01C20038) /* Timer Reload Register 34 */ #define TIMER_INTCTLSTAT (*(IO u32*)0x01C20044) /* Timer Interrupt Control and Status Register */ #define INTMUX1 (*(IO u32*)0x01800104) /* Interrupt mux register 1 */ extern void _intcVectorTable(void); extern volatile u32 Timer_Flag; void Timer_Delay(u32 d); void Timer_INT_Init(u32 d); void Timer_INT_Init(u32 d) { d*=24000; TIMER_TGCR=0x00000004; //reset TIMER12 TIMER_TIM12=0; //reset count TIMER_PRD12=d-1; //period TIMER_TCR=0x00000080; //continuous mode INTMUX1=4; //Event #4 T64P0_TINT12 => INTSEL4 ISTP=(u32)_intcVectorTable; //set new Vector Table for Interrupt ICR=0xFFF0; //clear all interrupts, bits 4 thru 15 IER=(1<<1)|(1<<4); //enable NMI, INT4 interrupts _enable_interrupts(); TIMER_TGCR=0x00000005; //activate TIMER12 } volatile u32 Timer_Flag=0; interrupt void Timer_INT(void) { Timer_Flag=1; } //Использование: void main(void) { L1P_Config(L1_SIZE_32K); //Enable L1P L1D L2 Cache L1D_Config(L1_SIZE_32K); L2_Config(L2_SIZE_128K); SDRAM_Cacheable(CACHEABLE_ON); //Enable SDRAM Cacheable KICK0R=0x83E70B13; //Unlock KICK1R=0x95A4F1E0; PINMUX10=0x00000080; //GP3[0] PINMUX13=0x11000000; //EMIFA PINMUX14=0x00111111; PINMUX17=0x00000100; PINMUX18=0x00101010; PSC0_lPSC_enable(0,0); //enable EDMA3 Channel Controller PSC0_lPSC_enable(0,1); //enable EDMA3 Transfer Controller 0 PSC0_lPSC_enable(0,3); //enable EMIFA PSC1_lPSC_enable(0,3); //enable GPIO EMIFA_Init(); LCD_Reset(); LCD_Init(); LCD_Clear(0x0000); Picture_Reverse(); //Swap bytes L2WB=0x01; //Flush L2 Cache (for DMA) EDMA3_Init((void*)Picture,sizeof(Picture)); //Init EDMA3 Timer_INT_Init(1000); //1s interval while(1) { register u16 x=rand()%(480-128); register u16 y=rand()%(320-128); EDMA_Wait(); LCD_Position(x,y,x+(128-1),y+(128-1)); EDMA3_Run(); while(!Timer_Flag); Timer_Flag=0; } } Вышепреведённый код рисует через DMA картинки с интервалом 1 с.
-
C6745 прерывание от таймера
repstosw опубликовал тема в Сигнальные процессоры и их программирование - DSP
Пытаюсь задействовать прерывание от таймера TIMER 1:2 у C6745, но не работает. Сам таймер настроил и он работает. Не получается вызвать обработчик его прерывания - не видит и всё! Номер эвента от Timer1:2 = 0x04 , настраиваю INTMUX1 = 4 - связываю int4 с таймером. Код ниже: extern void _Vectors(void); void Timer_INT(void) { TIMER_TGCR=0x00000004; //сброс TIMER12 TIMER_TIM12=0; //сброс счётчика TIMER_PRD12=24000000-1; //установка периода ~1 с. TIMER_TCR=0x00000080; //многократный счёт TIMER_TGCR=0x00000005; //активируем TIMER12 TIMER_INTCTLSTAT=0x00000003; //сброс флага прерывания и разрешаем прерывания INTMUX1=4; //эвент таймера 0x4 на int4 //загружаем новую таблицу векторов ISTP=(unsigned int)_Vectors; /* clear all interrupts, bits 4 thru 15 */ ICR = 0xFFF0; IER=(1<<4)|(1<<1); //enable int4 & non-maskable int /* enable interrupts, set GIE bit */ _enable_interrupts(); Delay(100); } Сам обработчик прерывания такой: interrupt void _Int4(void) { while(1); //пока безнадёжно повисаем } Таблица векторов и обработчики : ; Global symbols defined here and exported out of this file .global _Vectors .global _c_int00 .global _vector1 .global _vector2 .global _vector3 .global _vector4 .global _Int4 .global _vector5 .global _vector6 .global _vector7 .global _vector8 .global _vector9 .global _vector10 .global _vector11 .global _vector12 .global _vector13 .global _vector14 .global _vector15 ; This is a macro that instantiates one entry in the interrupt service table. VEC_ENTRY .macro addr STW B0,*--B15 MVKL addr,B0 MVKH addr,B0 B B0 LDW *B15++,B0 NOP 2 NOP NOP .endm ; This is a dummy interrupt service routine used to initialize the IST. _vec_dummy: B B3 NOP 5 ; This is the actual interrupt service table (IST). .sect ".vecs" .align 1024 _Vectors: _vector0: VEC_ENTRY _Int4 ;RESET _vector1: VEC_ENTRY _Int4 ;NMI _vector2: VEC_ENTRY _Int4 ;RSVD _vector3: VEC_ENTRY _Int4 ;RSVD _vector4: VEC_ENTRY _Int4 ;isr0 _vector5: VEC_ENTRY _Int4 ;isr1 _vector6: VEC_ENTRY _Int4 ;isr2 _vector7: VEC_ENTRY _Int4 ;isr3 _vector8: VEC_ENTRY _Int4 ;isr4 _vector9: VEC_ENTRY _Int4 ;isr5 _vector10: VEC_ENTRY _Int4 ;isr6 _vector11: VEC_ENTRY _Int4 ;isr7 _vector12: VEC_ENTRY _Int4 ;isr8 _vector13: VEC_ENTRY _Int4 ;isr9 _vector14: VEC_ENTRY _Int4 ;isr10 _vector15: VEC_ENTRY _Int4 ;isr11 Пока сделал везде _Int4 (позже исправлю). Линковщик ругается на секцию: И самое весёлое: смотрю в MAP-файл и вижу: Вот какого черта он игнорирует мою таблицу векторов и считает её что она в ROM с адреса 0x00700000 ? Прерывание естественно НЕ работает! Как можно заставить прерывание от таймера работать? -
UART0 то работает, то нет. Переключился на загрузку с UART2 - работает стабильно: более 0.5 МБ гружу в SDRAM. Настроил EMIFA и прикрутил дисплей 480x320. Всё работает. С картой памяти наверное поступлю проще - повышаю её на SPI1 (на SPI 0 висит Boot EEPROM). Видео дисплея в работе: https://www.youtube.com/watch?v=CzOtunjHsSg Исходник проекта для CCS v6 ниже: LCD_ILI9486.rar
-
Вы здОрово всё расписали, интересно было почитать! Вылезла другая проблема - с какого-то момента загрузка по UART0 перестала работать и включается очень редко. Ошибка такого плана: Но загрузка с SPI EEPROM при этом идёт! В чем может быть дело?
-
У PRUSS своё мультиплексирование пинов, не совпадающее с GPIO. Контроллируется с помощью PINMUX0..19. Только вот в C6745 там в битовых полях стоит Reserved, а в C6748 уже обозначены GP PRU. В техасовских утилитах (которые пины помогают назначить) - также. Я упустил из виду, что PRUSS - отдельные процессоры и DMA действительно становится не нужен. Нужна параллельность отрисовки в дисплей. Тоесть используя часть линий McASP можно полностью реализовать SPI ? Тогда зачем SPI сделали отдельно?
-
McASP он максимум 192 кГц и не годится. Это для звука больше. Да мне главное 4-битный режим задействовать. Надо будет читать видео-потоки с разной плотностью сжатия и отрисовывать на экране видео. Даташит говорит что целых два - PRU0 и PRU1. Но в референс мануале нет мультиплексирования GPO/GPI через PINMUX, что странно. В C6548 eсть и в утилите PINMUX тоже есть. Кое-как нашёл асм для PRUSS. Было бы здорово его задействовать для реализации интерфейса для SD карты (4 бита данные, CLK, CMD, CS) или LCD (8 бит, CS, WR, A0). Только как тогда DMA будет с этим всем работать? И какой максимально возможный SPI CLK допустим? В даташите пишут: SPI_Module_Clock/3. Только чему равен SPI_Module_Clock - не написали. Вместо SD карты ещё рассматриваю микроновскую SPI MT29F4G01ADAGDWB - на 133 МГц она лучше будет чем SD-карта на 25 МГц даже с 4 битами
-
ЗдОрово! Я даже и это успел проспать! :) Нет, не поможет. Потому что в C6745 нет вывода GPO,GPI на GPIO (в PINMUX нет таких функций.) Зато в C6748 уже есть. И всё-же есть ли способ работать с SD-картой в режиме 4 бита способом кроме как SDIO?
-
С самого сайта TI? Или в закрома лазить прийдётся? Нашёл csl-phytec-master там есть модуль для работы с MMCSD. Новая проблема: с ужасом заметил что пины для работы с SD-картой перекрывают EMIFA, которая тоже нужна. Мультиплексировать(разделять во времени) SDIO и EMIFA - не вариант. EMIFA будет в 8 битном режиме, можно только на запись, обязательно работа через DMA. На EMIFA будет LCD с 8 битной шиной. Для SD-карты нужен 4-ибитный режим. PRUSS поможет? Через него можно работать с SDIO, но так чтобы пины были переназначены на другие? Или только ногодрыгом проблема решается? И TI опять зажала PRUSS тулзы для C6745
-
Подскажите, есть ли пример работы с SDIO у TMS320C6745 ? Планирую SD карту подключить и наладить общение с ней (на первых порах - инит, чтение, запись сектора). Может даже в сторону OMAP-L137 копнуть и пусть даже ARM-ядро (C он и в Африке Си)
-
Это уже C++ с редактированием большого количества исходников :) Да, верно, ошибки 1) и 2). При исправленных, 3) не помогло - такого пункта нет в настройках. Проблема описана здесь и её решение: https://e2e.ti.com/support/tools/ccs/f/81/t/501095 Если вкратце: использовал CCS v5 с компилятором C6000 7.4.8. Штатный апдейт доводил до v. 7.4.24. Всё то же - нет опции -C99 в Dialog. Поставил 6-ю версию CCS (она также лечится путём удаления mdex.dll как и 5-я версия), которая имеет App Center, из которого удалось скачать версию компилятора 8.3.3. Переделал проект под 6-ю CSS и поставил компилятор 8.3.3. В опциях появилось C99: Теперь код такого типа компилируется без ошибок: int Test_Shlak(int n) { int m[n]; for(int i=0;i<n;i++)m[i]=m[1]; return m[3]; } Что и нужно было. Попутно поборолся с удалением неиспользуемых функций в проекте. В компиляторе поставил: В линковщике: И только тогда создаётся выходной файл без лишнего. Проверяем так: C:\CCS_DIR\ccsv6\tools\compiler\ti-cgt-c6000_8.3.3\bin\ofd6x.exe --func_info Project.out > Project.csv И смотрим Экселем полученный Project.csv - который содержит все объекты которые в бинарнике. Только тонкая оптимизация, только -C99, только хардкор! ))) P.S. А Страуструповское творение(C++) так и не умеет массивы переменной длины :)
-
Пытаюсь в CCSv5 скомпилять следующий код: int read_and_process(int n) { int vals[n]; for (int i = 0; i < n; ++i) vals[i] = vals[2*i] return vals[3*i]; } Ругается на то что размер массива переменный (VLA) и на объявление переменной внутри цыкла. Если от второго ещё можно избавиться, опустившись на уровень Страуструповщины (переключив на C++), то VLA не хочет варится. Даже при включенном Enable GCC Extentions. Есть ли способ заставить компилятор варить Variable Length Arrays ? (must have для C99) Эмуляторописатели любят GNU-шные плюшки и при портировании прийдётся править много кода (к слову Visual DSP 5.1 и Keil ARM могут это). Выход? Скачать CSS по-старше чем v.5 ?
-
Всё, я разобрался в чём дело. Когда в AISgen включена инициализация PLL и SDRAM и код грузится в SDRAM, загрузчик сам включает кеширование L1P и L1D. Это и послужило тому, что вначале подумал, что кеш инструкций не даёт выигрыша. Обнаружил это сперва принудительно записав в L1PCFG=0x0. А затем считал его значение и узнал, что загрузчик включает L1 на полную: по 32 кБ. А вот L2 остаётся выключенным - загрузчик его не трогает. И ещё он не трогает MAR192, отвечающий за кеширование адресов SDRAM. Программу раздувал так: #define REPEAT8(x) \ x; \ x; \ x; \ x; \ x; \ x; \ x; \ x; \ #define REPEAT64(x) REPEAT8(REPEAT8(x)) #define REPEAT4096(x) REPEAT64(REPEAT64(x)) void NoOp(void) { __asm("NOP"); } void main(void) { //..... while(1) { //...... REPEAT4096(NoOp()) //....... //..... } Попробовал принудительно отключать кеши и сделал замеры: L1P L1D L2 время выполнения 0 0 0 - 30 секунд 1 0 0 - 14 cекунд 0 1 0 - 12 cекунд 1 1 0 - 2 секунды 0 0 1 - 3 cекунды 1 0 1 - 3 cекунды 0 1 1 - 2 секунды 1 1 1 - 2 cекунды Удлинил тест для L2=1 и сделал второй тест: L1P L1D L2 время выполнения 0 0 1 - 52 cекунды 1 0 1 - 48 cекунды 0 1 1 - 34 секунды 1 1 1 - 34 cекунды Теперь я вижу, что L1P работает и в некоторых случаях очень сильно ускоряет работу. Есть ли способ жестко задать программе точку входа в main() или _c_int00() ? Адрес постоянно плавает. А мне надо свой загрузчик с SD-карты писать чтобы переходить на загруженную программу.
-
Всё, разобрался. Оказывается UART Boot Host каким-то чудом понимает, что если все секции слинкованы в SDRAM, то и грузит туда. Получилось запустить код в SDRAM. Попробовал включить L1P (кеш кода), так: Но вот прироста в скорости выполнения кода я не особо заметил. Диод мигает с одинаковой скоростью - что при выключенном L1P, что при включенном. А вот ОТключение L1D тормозит выполнение из SDRAM в 10 раз примерно. Что я делаю не так? (с L1P) Как можно проверить что кеш кода (L1P) включен и он приносит пользу? 32 миллиона нопов заставить делать в SDRAM ? с кешем и без
-
И кстати, техасцы назвиздели по поводу создания AIS в виде H-файла для встраивания в другие C-программы. Создаётся бинарник в любом случае! Речь об этом:
-
Как можно заставить Bootloader C6745 грузить код в SDRAM? Посмотрел CMD - но там объявлены только адреса по которым линковщик размещает секции. А вот как толкнуть AIS в SDRAM? Возможно ли это сделать AISgen-ом? Или курить описание AIS формата надо и ваять самому AIS? Или самому надо писать код копирования бинарника в сдрам?
-
Ещё задействовал L2 в качестве кеша (максимально получилось оттяпать 128кБ, при 256 кБ программа не запускается, потому что она перетирается кешем L2): L2CFG=0x3; //128 kB L2 Итого время тестов сократилось ещё на 24%. Вот бы ещё L1P для кода задействовать. И что важно перед тем как туда (на внешнюю память) прыгнуть, надо сбросить L1D (flush) чтобы конец образа программы гарантированно лег в SDRAM. Я на Блекфинах на этом моменте собаку съел )) использовал flush_data_buffer()
-
Да ладно, не язвите. Поугорали и хватит))) Я запустил DSP - и уменя сегодня праздник!!!
-
Спасибо за помощь. Вышеприведенного кода оказалось недостаточно для того чтобы закешировать SDRAM. На гитхабе в ccslearning-master было упоминание о MAR-регистрах. Поиск вывел меня на даташит: TMS320C674x DSP Megamodule Оказалось, что эти самые MAR-регистры задают регионы кеширования. И по дефолту регистры MAR192 и MAR193 (они отвечают за адреса 0xC0000000...0xC1FFFFFF, которые используются SDRAM ) с выключенным кешированием. Младший бит этих регистров был равен 0 (проверял), удалось их установить в 1 (операция привелегированная : требуется SuperVisor Mode, который как оказывается у меня был). После этого время теста на 32-битных записях уменьшилось в 3 раза! Попробовал убрать инит MAR-регистров, всё вернулось как без кеширования. Полная функция включения кеша L1D для SDRAM 32 МБ на EMIFB - выглядит так: void Enable_DCache(void) //Enable D-Cache { L1DWB=0x01; //Flush L1D L1DCFG=0x07; //Reconfigure L1D to default state (full cache) MAR192=0x00000001; //0xC0000000..0xC0FFFFFF cacheble MAR193=0x00000001; //0xC1000000..0xC1FFFFFF cacheble } Про кеширование доки слишком сложные, для моего понимания, а вот хочется максимально выжать с внешней памяти производительность на чтение-запись данных и выполнение кода. Так как внутренней памяти мне не хватит - она пойдет под стек, кучу и DMA.
-
Рефреш-тест тоже проходит нормально. Делаю 4 чтения каждой ячейки после записи. Не совсем понятно про кеширование данных. Надо включить Data Cache. Нашёл только вот это: void Enable_DCache(void) //Enable D-Cache { L1DWB=0x01; //Flush L1D L1DCFG=0x07; //Reconfigure L1D to default state (full cache) } Подозреваю, этого мало. А как политику кеша настраивать : Write Back, Write Throw ? И как закешировать к примеру, только регион SDRAM - все 32 мегабайта начиная с адреса 0xC0000000 ? Референс мануал ничего по этому поводу не пишет. Где можно подсмотреть?
-
Завидуйте молча! :)
-
Разве в AISgen можно указать стартовый адрес для кода? Картинка ниже. Может имели в виду, что CMD-файл надо править, где расписаны регионы и их адреса? Пользуясь случаем задам вопрос, как можно базовые адреса секций программы менять? RO, RW, ZI, Stack, Heap ? А на счет идеи потестить с рефрешем я понял. Просто добавить многократное чтение каждой ячейки с проверкой на обнаружения факта разрушения данных в каждой ячейки после первого чтения.