реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Грамотная работа с EDMA, SDRAM --EDMA--> L2
lamateur
сообщение Dec 5 2008, 05:30
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
bav
сообщение Dec 5 2008, 12:06
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 693
Регистрация: 21-06-05
Из: Санкт-Петербург
Пользователь №: 6 184



думаю, п.4

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

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

и еще - на какой частоте тактируется SDRAM и какая толщина шины данных?
Go to the top of the page
 
+Quote Post
bve
сообщение Dec 5 2008, 12:26
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 316
Регистрация: 20-02-05
Из: Ленинградская обл.
Пользователь №: 2 765



Попробуйте грамотно расположить массив во внешней памяти.
Полная скорость SDRAM достигается, если данные берутся из одной строки, тогда скорость
определяется тактовой частотой SDRAM. А вот если данные располагаются в другой строке, то тогда на активацию новой строки тратится 4-6 тактов SDRAM_CLK ( в зависимости от памяти ). Если у Вас идет частое обращение к разным строкам, то и получите малую скорость......
Go to the top of the page
 
+Quote Post
rokhan
сообщение Dec 8 2008, 15:31
Сообщение #4


Участник
*

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



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

Скорее всего очень плохо настроен EDMA, но без конкретных цифиръ я сказать не могу.
так что
Go to the top of the page
 
+Quote Post
lamateur
сообщение Dec 9 2008, 07:58
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 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?
Go to the top of the page
 
+Quote Post
rokhan
сообщение Dec 9 2008, 09:30
Сообщение #6


Участник
*

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



1. Если вы использовали стандартный DSP/BIOS проект то параметр
что нибудь в роде...
bios.GBL.USERINITFXN = prog.extern("c6416_init");


2. Просто приведите пример кода которым вы инициализируете EDMA
Go to the top of the page
 
+Quote Post
bav
сообщение Dec 9 2008, 10:42
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 693
Регистрация: 21-06-05
Из: Санкт-Петербург
Пользователь №: 6 184



Цитата
3) Память представляет из себя две спаренные 32-битные SDARM по 8 МБайт. Таким образом, общая полоса на 64 бит. Тактируется, если я правильно разобрался, с частотой ECLKOUT1, которая соответствует входной частоте EMIF: ECLKIN, а уже последняя в свою очередь либо внешняя, либо CPU/4, либо CPU/6. А вот где это задается - хоть убей - не нашел. Нашел только в комментах GEL-файла, что EMIF работает на 120MHz, наверное это и есть та самая ECLKIN.

убивать не будем smile.gif
задается регистрами: ECLKIN_SEL (DEVCFG.[17,16] and DEVCFG.[15,14])
проверь осцильником, какая там частота.
еще есть подозрения, что EMIF сконфигурирован на работу с 8-ми битной памятью.
Go to the top of the page
 
+Quote Post
lamateur
сообщение Dec 9 2008, 13:24
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 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)
Go to the top of the page
 
+Quote Post
bav
сообщение Dec 9 2008, 13:32
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 693
Регистрация: 21-06-05
Из: Санкт-Петербург
Пользователь №: 6 184



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

вообще, не уверен в правильности подсчета числа тактов. попробуй вывести сигнал на GPIO и с помощью осцильника посмотри время копирования. чтобы результат получился точнее, сделай перекачку 100-1000 блоков (можно одних и техже и в тоже место, только убери оптимизацию компилятора)
Go to the top of the page
 
+Quote Post
lamateur
сообщение Dec 10 2008, 08:35
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 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 секунд реального времени. Соответствует.
Go to the top of the page
 
+Quote Post
bav
сообщение Dec 10 2008, 09:41
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 693
Регистрация: 21-06-05
Из: Санкт-Петербург
Пользователь №: 6 184



как узнать через CCS не знаю. не приходилось. это можно узанть по схеме или положению джамперов. через ножки конфигурируется только во время сброса.
Go to the top of the page
 
+Quote Post
lamateur
сообщение Dec 10 2008, 10:29
Сообщение #12


Участник
*

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



bav,
я на всякий случай еще раз акцентирую внимание на том факте, что передача в пределах внутренней памяти L2 тоже очень медленная: 76 Мбайт/сек. Может режим\частота и т.п. внешнего интерфейса тут ни при чем тогда и надо скорее внутреннюю память настраивать?
Go to the top of the page
 
+Quote Post
bav
сообщение Dec 10 2008, 10:50
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 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);

.............
Go to the top of the page
 
+Quote Post
rokhan
сообщение Dec 10 2008, 13:31
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 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 раз smile.gif

Это с ходу что можно сказать.

Забыл предупредить для работы с 64 битами нужно иметь выравненые указатели на 64битаsmile.gif

Сообщение отредактировал rokhan - Dec 10 2008, 13:34
Go to the top of the page
 
+Quote Post
lamateur
сообщение Dec 10 2008, 13:50
Сообщение #15


Участник
*

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



rokhan,
Крутой документ этот spraa02! Буду разжевывать! Спасибо!
Go to the top of the page
 
+Quote Post
lamateur
сообщение Dec 11 2008, 09:00
Сообщение #16


Участник
*

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



Теперь, когда переделал, еще раз спасибо!
Наверное, не уместно говорить, что самому приходило в голову увеличить размер элемента, но не верилось, что EDMA сам не догадывается использовать шину целиком! )

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

Всем большое спасибо за участие в решение проблемы!
Go to the top of the page
 
+Quote Post
lamateur
сообщение Mar 3 2009, 08:19
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 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;
}
}
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th July 2025 - 14:49
Рейтинг@Mail.ru


Страница сгенерированна за 0.01537 секунд с 7
ELECTRONIX ©2004-2016