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

Грамотная работа с EDMA

Здравствуйте!

 

Возникло сомнение, что правильно передаю данные через 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

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


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

думаю, п.4

 

попробуй поварьировать с разными размерами массива. запиши и пришли зависимость.

 

попробуй тоже самое сделать через QDMA.

 

и еще - на какой частоте тактируется SDRAM и какая толщина шины данных?

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


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

Попробуйте грамотно расположить массив во внешней памяти.

Полная скорость SDRAM достигается, если данные берутся из одной строки, тогда скорость

определяется тактовой частотой SDRAM. А вот если данные располагаются в другой строке, то тогда на активацию новой строки тратится 4-6 тактов SDRAM_CLK ( в зависимости от памяти ). Если у Вас идет частое обращение к разным строкам, то и получите малую скорость......

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


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

1) Скорее всего вы неправильно настроили.

2) Можно, EDMA_intTest(FRAGM_EDMA_TCC)) - макрос который опрашивает руками

3) настроки памяти всегда можно изменить - посмотрите при старте что то типа фукнцию init_dsp() в не производиться инициализая памяти, кеша и т.п.

4) Замер времени произведен скорее всего правильно - неправильно расмотрены результаты - к сведению - EDMA работает на частоте CPU/3.

 

Скорее всего очень плохо настроен EDMA, но без конкретных цифиръ я сказать не могу.

так что

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


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

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?

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


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

1. Если вы использовали стандартный DSP/BIOS проект то параметр

что нибудь в роде...

bios.GBL.USERINITFXN = prog.extern("c6416_init");

 

 

2. Просто приведите пример кода которым вы инициализируете EDMA

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


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

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-ми битной памятью.

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


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

задается регистрами: ECLKIN_SEL (DEVCFG.[17,16] and DEVCFG.[15,14])

проверь осцильником, какая там частота.

еще есть подозрения, что EMIF сконфигурирован на работу с 8-ми битной памятью.

 

А разве на C64xx есть Device Configuration Register? Я не смог найти. Пишут, что он только на 6713 присутствует.

EMIF сконфигурирована на 64-битную SDRAM (регистр CECTL0: 0xffffffd3)

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


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

не знаю, может быть. посмотри таблицу Device Configuration Pins (BEA[20:13, 9:7], HD5, and BEA11) в документе SPRS146

 

вообще, не уверен в правильности подсчета числа тактов. попробуй вывести сигнал на GPIO и с помощью осцильника посмотри время копирования. чтобы результат получился точнее, сделай перекачку 100-1000 блоков (можно одних и техже и в тоже место, только убери оптимизацию компилятора)

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


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

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 секунд реального времени. Соответствует.

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


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

как узнать через CCS не знаю. не приходилось. это можно узанть по схеме или положению джамперов. через ножки конфигурируется только во время сброса.

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


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

bav,

я на всякий случай еще раз акцентирую внимание на том факте, что передача в пределах внутренней памяти L2 тоже очень медленная: 76 Мбайт/сек. Может режим\частота и т.п. внешнего интерфейса тут ни при чем тогда и надо скорее внутреннюю память настраивать?

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


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

в общем, как писал выше, подозрение в не корректности подсчета тактов.

другое дело, может, 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);

.............

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


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

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

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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