|
Грамотная работа с EDMA, SDRAM --EDMA--> L2 |
|
|
|
Dec 5 2008, 05:30
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 26-06-08
Пользователь №: 38 561

|
Здравствуйте!
Возникло сомнение, что правильно передаю данные через EDMA из внешней памяти (SDRAM) во внутреннюю (L2).
А именно, на стартер ките на базе С6416 передача 16-ти КБайт занимает примерно 54000 тиков таймера, что соотвествует примерно 0.6 мсек реального времени (720 МГц) или скорости 25 МБайт/с. По-хорошему, скорость обмена между внешней и внутренней памятью должна быть раз в 20 больше! Передачу делаю Блок-синхронизированную из 2D в 1D: транслируется квадрат байтов размера 128 на 128. Замер времени производился на участке проверки соответствующего бита CIPR-регистра. Именно этот цикл проверки и занимает 54000 тиков. Прерывание я не отправляю, поскольку далее программа работает с переданными данными и необходимо знать, что передача окончена. вот пример участка кода, на котором производится замер: EDMA_setChannel(hEdma_fragm); while (1) { if (EDMA_intTest(FRAGM_EDMA_TCC)) { EDMA_intClear(FRAGM_EDMA_TCC); break; }
Подскажите, пожалуйста, где искать ошибку. 1) Неправильно настроил канал передачи 2) Нельзя напрямую многократно опрашивать регистр CIPR 3) Существуют какие-то настройки памяти, которые надо изменить (например, через DSP/BIOS) 4) Неправильно произведен замер времени ...
Сообщение отредактировал lamateur - Dec 5 2008, 06:21
|
|
|
|
|
Dec 8 2008, 15:31
|
Участник

Группа: Участник
Сообщений: 25
Регистрация: 14-04-06
Пользователь №: 16 129

|
1) Скорее всего вы неправильно настроили. 2) Можно, EDMA_intTest(FRAGM_EDMA_TCC)) - макрос который опрашивает руками 3) настроки памяти всегда можно изменить - посмотрите при старте что то типа фукнцию init_dsp() в не производиться инициализая памяти, кеша и т.п. 4) Замер времени произведен скорее всего правильно - неправильно расмотрены результаты - к сведению - EDMA работает на частоте CPU/3.
Скорее всего очень плохо настроен EDMA, но без конкретных цифиръ я сказать не могу. так что
|
|
|
|
|
Dec 9 2008, 07:58
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 26-06-08
Пользователь №: 38 561

|
bav, 1) для других размеров массивов объем переданных в секунду данных не меняется: 256х256 (64 КБайт) ~ 215000 тиков. 128х128 (16 КБайт) ~ 54000 тиков. 128х128 (1 КБайт) = 3407 тиков. 8х8 (64 Байт) = 245 тиков.
Получается все те же 26МБайт/сек... если я правильно понял, что Вы имели ввиду.
Кстати, внутренняя передача (из одной области L2 в другую) 4КБайт занимает 11000 тиков, что соответствует 33Мбайт/сек.
2) При передачи через QDMA скорости те же самые. Делал QDMA по примеру в spra636a.pdf (EDMA: Example Application), пример Subframe Extraction (стр. 49). Кстати как раз описан мой случай - экстракции малой прямоугольной области из большей области...
3) Память представляет из себя две спаренные 32-битные SDARM по 8 МБайт. Таким образом, общая полоса на 64 бит. Тактируется, если я правильно разобрался, с частотой ECLKOUT1, которая соответствует входной частоте EMIF: ECLKIN, а уже последняя в свою очередь либо внешняя, либо CPU/4, либо CPU/6. А вот где это задается - хоть убей - не нашел. Нашел только в комментах GEL-файла, что EMIF работает на 120MHz, наверное это и есть та самая ECLKIN.
bve, Если я Вас правильно понял и правильно понял структуру памяти, в одном банке (на 16 Mbit) моей памяти: 2048 строк и 256 колонок. А массив байт 128х128 я беру из области 1024х1024, т.е. как минимум каждая новая последовательность в 128 байт будет экстрагироваться из новой строки памяти. Наглядно это показано в примере Subframe Extraction (см. выше).
rokhan, на 3) Можете пояснить, где именно должна располагаться функция типа ini_dsp() или что именно она меняет: регистры EMIF, ядра,..?
на 4) А что определяет частота работы EDMA? Могу предположить только, что частота самой передачи будет определяться "самым слабым" звеном в системе. В данном случае наименьшая частота - частота обращения к памяти через EMIF - 120MHz.
Какие цифры позволили бы вам судить о правильной настройке EDMA?
|
|
|
|
|
Dec 9 2008, 09:30
|
Участник

Группа: Участник
Сообщений: 25
Регистрация: 14-04-06
Пользователь №: 16 129

|
1. Если вы использовали стандартный DSP/BIOS проект то параметр что нибудь в роде... bios.GBL.USERINITFXN = prog.extern("c6416_init");
2. Просто приведите пример кода которым вы инициализируете EDMA
|
|
|
|
|
Dec 9 2008, 10:42
|
Знающий
   
Группа: Свой
Сообщений: 693
Регистрация: 21-06-05
Из: Санкт-Петербург
Пользователь №: 6 184

|
Цитата 3) Память представляет из себя две спаренные 32-битные SDARM по 8 МБайт. Таким образом, общая полоса на 64 бит. Тактируется, если я правильно разобрался, с частотой ECLKOUT1, которая соответствует входной частоте EMIF: ECLKIN, а уже последняя в свою очередь либо внешняя, либо CPU/4, либо CPU/6. А вот где это задается - хоть убей - не нашел. Нашел только в комментах GEL-файла, что EMIF работает на 120MHz, наверное это и есть та самая ECLKIN. убивать не будем  задается регистрами: ECLKIN_SEL (DEVCFG.[17,16] and DEVCFG.[15,14]) проверь осцильником, какая там частота. еще есть подозрения, что EMIF сконфигурирован на работу с 8-ми битной памятью.
|
|
|
|
|
Dec 9 2008, 13:24
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 26-06-08
Пользователь №: 38 561

|
Цитата(bav @ Dec 9 2008, 13:42)  задается регистрами: ECLKIN_SEL (DEVCFG.[17,16] and DEVCFG.[15,14]) проверь осцильником, какая там частота. еще есть подозрения, что EMIF сконфигурирован на работу с 8-ми битной памятью. А разве на C64xx есть Device Configuration Register? Я не смог найти. Пишут, что он только на 6713 присутствует. EMIF сконфигурирована на 64-битную SDRAM (регистр CECTL0: 0xffffffd3)
|
|
|
|
|
Dec 10 2008, 08:35
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 26-06-08
Пользователь №: 38 561

|
rokhan, Да, стандартный dsp/bios проект для dsk6416. В генерируемом cmd-файле есть такая строка: GBL_USERINITFXN = _FXN_F_nop; Извините, но пока не хватает опыта, чтоб делать какие-то выводы из этого.
Вот листинг конфигурации и передачи с замером времени. Если что-то не очевидно, я поясню.
#define FRAGM_EDMA_TCC 11
EDMA_Config cfgEdmaFragm = { EDMA_OPT_RMK( EDMA_OPT_PRI_LOW, EDMA_OPT_ESIZE_8BIT, EDMA_OPT_2DS_YES, EDMA_OPT_SUM_INC, EDMA_OPT_2DD_NO, EDMA_OPT_DUM_INC, EDMA_OPT_TCINT_YES, EDMA_OPT_TCC_OF(FRAGM_EDMA_TCC), EDMA_OPT_TCCM_OF(0), EDMA_OPT_ATCINT_NO, EDMA_OPT_ATCC_OF(0), EDMA_OPT_PDTS_DISABLE, EDMA_OPT_PDTD_DISABLE, EDMA_OPT_LINK_YES, EDMA_OPT_FS_YES ), EDMA_SRC_OF(NULL), EDMA_CNT_RMK(NULL,NULL), EDMA_DST_OF(NULL), EDMA_IDX_RMK(NULL,NULL), EDMA_RLD_RMK(0x0000,0x07E0) };
Frame =(Uint8 *)(0x80500000); hEdma_fragm = EDMA_open(EDMA_CHA_ANY,EDMA_OPEN_RESET); //пробовал так же ставить конкретный канал cfgEdmaFragm.cnt=(Uint32)((strbsize+2*delta-1)<<16) + (strbsize+2*delta); cfgEdmaFragm.idx=(Uint32)((FRAME_WIDTH-strbsize-2*delta)<<16); cfgEdmaFragm.src=(Uint32)(Frame+(32-delta)*FRAME_WIDTH +(32-delta)); cfgEdmaFragm.dst=(Uint32)(Fragm); EDMA_config(hEdma_fragm,&cfgEdmaFragm); TIMER_start(hTimer1); EDMA_setChannel(hEdma_fragm); while (1) { if (EDMA_intTest(FRAGM_EDMA_TCC)) { EDMA_intClear(FRAGM_EDMA_TCC); break; } } *tickcount1 = TIMER_getCount(hTimer1);
Кстати, я изначально в теме не правильно оценил скорость передачи... 54000 тиков - это 52 МБайт/сек. Что тоже медленно.
bav,
Спасибо за ссылку на пдф. Да, действительно, конфигурационный пин BEA[17:16] отвечает за настройку частоты. Если я правильно понял, BEA - это имя, а номера этих пинов B18 и A18. Можете подсказать, как теперь через CCStudio узнать, какой сигнал на них подается и как подать свой? Физически - это ножки процессора, да?
Осцильник я, конечно, рано или поздно возьму... ) Но я оценивал реалистичность измеряемых тиков обычным секундомером, запустив программу на 15 секунд реального времени. Соответствует.
|
|
|
|
|
Dec 10 2008, 10:29
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 26-06-08
Пользователь №: 38 561

|
bav, я на всякий случай еще раз акцентирую внимание на том факте, что передача в пределах внутренней памяти L2 тоже очень медленная: 76 Мбайт/сек. Может режим\частота и т.п. внешнего интерфейса тут ни при чем тогда и надо скорее внутреннюю память настраивать?
|
|
|
|
|
Dec 10 2008, 10:50
|
Знающий
   
Группа: Свой
Сообщений: 693
Регистрация: 21-06-05
Из: Санкт-Петербург
Пользователь №: 6 184

|
в общем, как писал выше, подозрение в не корректности подсчета тактов. другое дело, может, DMA долго инициализируется на передачу. попробуй обычное копирование с оптимизацией. скажу, что таких проблем не было. правда, DMA у меня гонял потоки по видеопортам. проводил эксперименты по работе кэша и по копированию данных во внудреннюю память с помощью QDMA, там скорости были значительно выше, чем у Вас. вот, откопал текст для таймера Timer.h Код #include "csl_timer.h"
#define CPU_FREQUENCY 720000000 #define CLOCK_SCALE 8 // не понятно, делитель стоит на 8, т. е. должен быть делитель на 8
class Timer { TIMER_Handle handle; // int overhead; int strt; int stp; int clocks;
public: Timer(); ~Timer();
int count(); void start(); void stop(); int ms(); int us(); int tic();
}; Timer.cpp Код #include "timer.h"
Timer::Timer() { handle = TIMER_open(TIMER_DEVANY, TIMER_OPEN_RESET);
TIMER_configArgs(handle, 0x000002C0, 0xFFFFFFFF, 0x00000000); //калибровка //вычисление времени срабатывания // int start_ = count(); /* called twice to avoid L1D miss.*/ // start_ = count(); // int stop_ = count(); // overhead = stop_ - start_; } //---------------------------------------- Timer::~Timer() { TIMER_close(handle); } //---------------------------------------- int Timer::count() { return TIMER_getCount(handle); } //---------------------------------------- void Timer::start() { strt = TIMER_getCount(handle); } //---------------------------------------- void Timer::stop() { stp = TIMER_getCount(handle); clocks = stp - strt;// - overhead; } //---------------------------------------- int Timer::tic() { return clocks * CLOCK_SCALE; } //---------------------------------------- int Timer::ms() { return (long)(clocks / (CPU_FREQUENCY / 1000 / CLOCK_SCALE) ); } //---------------------------------------- int Timer::us() { return (long)(clocks / (CPU_FREQUENCY / 1000000 / CLOCK_SCALE) ); } //---------------------------------------- сейчас поищу другие тексты вот, как делал копирование: Код .......
#include <csl_dat.h>
.......
DAT_open (DAT_CHAANY, DAT_PRI_HIGH, DAT_OPEN_2D); unsigned short * src_ = src.Data();//x, y); unsigned short * src__ = &src_[x - offset_block + (y - offset_block)*width]; Uint32 copy_ID1 = DAT_copy2d ( DAT_2D1D, (void*)src__, (void*)in_buf, width_o_block*sizeof(unsigned short), height_o_block, width*sizeof(unsigned short) ); DAT_wait(copy_ID1);
.............
|
|
|
|
|
Dec 10 2008, 13:31
|
Участник

Группа: Участник
Сообщений: 25
Регистрация: 14-04-06
Пользователь №: 16 129

|
1. Почитай http://focus.ti.com/lit/an/spraa02/spraa02.pdfТут всё вполне написано. рекомендации измени EDMA_OPT_PRI_LOW на EDMA_OPT_PRI_HIGH EDMA_OPT_ESIZE_8BIT на EDMA_OPT_ESIZE_32BIT тогда передача в твоём случает будет вестись словами в 64 бита. что увеличит скорость в 8 раз  Это с ходу что можно сказать. Забыл предупредить для работы с 64 битами нужно иметь выравненые указатели на 64бита
Сообщение отредактировал rokhan - Dec 10 2008, 13:34
|
|
|
|
|
Dec 10 2008, 13:50
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 26-06-08
Пользователь №: 38 561

|
rokhan, Крутой документ этот spraa02! Буду разжевывать! Спасибо!
|
|
|
|
|
Dec 11 2008, 09:00
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 26-06-08
Пользователь №: 38 561

|
Теперь, когда переделал, еще раз спасибо! Наверное, не уместно говорить, что самому приходило в голову увеличить размер элемента, но не верилось, что EDMA сам не догадывается использовать шину целиком! )
Сейчас скорость передачи примерно 1200 МБайт/сек. Из этого делаю вывод, что входная частота EMIF не меньше CPU/4=180MHz, и используется вся шина на 64 бит: теоретически это как раз 1440 МБайт/сек. В выравнивании указателей, по-моему, необходимости нет. Как сказано в spraa02, при выставке размера элемента в 32Bit, используется максимальный размер шины. Можно еще, конечно, тут ковыряться, но меня пока все устраивает.
Всем большое спасибо за участие в решение проблемы!
|
|
|
|
|
Mar 3 2009, 08:19
|
Участник

Группа: Участник
Сообщений: 28
Регистрация: 26-06-08
Пользователь №: 38 561

|
Столкнулся с проблемой, что при передаче по EDMA копируются не все фреймы...
Делал небольшой эксперимент на симуляторе процессора TMS320C6415.
Требуется скопировать данные с прореживанием из одной области внешней памяти (из адреса 0x80......) в другую (в адрес 0x80000000).
Такая задача возникает когда грузишь байтовые данные из файла, и каждый байт занимает целое слово, т.е. полезная информация идет через каждые 4 байта. (Наприм.: 255 0 0 0 119 0 0 0 67 0 0 0 и т.д., а нужно: 255 119 67).
"Полезных" байтов у меня 1024x1024, т.е. 1Мбайт. Организовываю EDMA-передачу: Frame Synchronized 1D-to-1D Transfer (SUM = 11, DUM = 01), размер элемента - 8бит. Если я правильно понимаю, теперь мне требуется 1024 синхро-сигналов, чтоб передать весь массив. Но у меня передается только 9 фреймов, т.е. 9 строк!
Вот фрагмент кода: hEdma_input = EDMA_open(EDMA_CHA_ANY,EDMA_OPEN_RESET);
cfgEdmaInput.src=...; cfgEdmaInput.dst=...; cfgEdmaInput.idx=(Uint32)(1024<<18) | 4; cfgEdmaInput.cnt=(Uint32)((1024-1)<<16) | (1024);
EDMA_config(hEdma_input,&cfgEdmaInput); for (sync=0; sync<4; sync++){ EDMA_setChannel(hEdma_input); TSK_sleep(10000);} while (1) { if (EDMA_intTest(INPUT_EDMA_TCC)) { EDMA_intClear(INPUT_EDMA_TCC); break; } }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|