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

BratherLU

Свой
  • Постов

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

  • Посещение

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


  1. ld #0x00,a rpt *(_fir_ord) rptz действительно не принимает indirect addressing только константы на входе - (сорри спутал с rpt)
  2. mvdk *(_p_buff_length-1),brc сорри Вас запутал и сам заплутал mvdk *(_p_buff_length-1),brc - такая штука загрузит в брс значение из ячейки с абсолютным адресом (_p_buff_length-1). Поэтому - по адресу _p_buff_length должно лежать сразу нужное значение (на единицу меньше), если хотите использовать mvdk *(_p_buff_length),brc По поводу циркулярной адрессации и rptz грабли таки rptz a,_fir_ord-1 , если _fir_ord - адрес внешней константы (в сях), то компилер реально считает, что число повторений следующей инструкции лежит по адресу _fir_ord-1 и выполняет инструкцию это число раз +1 - ничего общего с Вашей задумкой я думаю => два способа вызова rptz (Mnemonic insruction Set) 1 rptz a,#_fir_ord-1 повторит след инструкция _fir_ord раз, где _fir_ord - константа объявленная в этом же асме или еще где во внешнем асме чере .set 2 rptz a,*(_fir_ord) в этом случае повторит след инструкция число раз +1 лежащих по адрес _fir_ord .
  3. В Conventions описано как праввильно делать вызов асм функций из С, как передать параметры через стэк, и какие регистры использует компилятор для своих нужд (какие регистры требуют сохранения на стэке), а какие можно свободно использовать без сохранения контекста Код смотрел бегло - то что бросилось в глаза и написал Да еще при использовании циклической адрессации в mvdd необходимо использовать ar0 для модификации адресных регистров типа mvdd *ar2+,ar3+0% Тогда будет работать mvdm *(_p_buff_length)-1,brc заменить на mvdk *(_p_buff_length-1),brc По поводу округления - ссылку не смотрел. Отвечу опираясь на эррату - здесь округление до соответствующего 2-чного разряда (младшего значащего в формате Q15 (15 - бит дробная часть 1 бит -3нак)), а не десятичного. Дорустим: (АH:AL)=0x00008000 = 0.000015259(=0x8000*(1/0x80000000)) в формате Q31. Добавляем (единицу сдвинутую на 15)-> AH:AL+0x8000=> (АH:AL)=0x00008000 =0.000015259(q31) + 0x00008000 =0.000015259(q31) (АH:AL)=0x00010000 = 0.000030517578125(Q31)=0x0001(Q15) То есть берем старшую часть аккумулятора, а младшую отбрасываем в итоге получается верный 16-битный округленный до ближайшего большего результат в формате (Q15) =0x0001 (PS точка находится между msb msb-1 результата как для Q31 так и для Q15)
  4. 1 - В mvdd можно использовать только регистры ar2,ar3,ar4,ar5 2 - rnd не стоит использовать т к она работает неправильно читайте эррату на процессор заменить на ADD #1,15,src[,dst] 3 - Загляните в хелп CCS в разделы Register Conventions и Function Conventions
  5. в *.с в верху #include "*.h" //Забыли наверно сделать :)
  6. Если не риалтайм и с периферией не работаете - не вижу смысла заморачиваться с DMA, тока если пощупать что за зверь. Хотя всей специфики задачи не представляю - может где и можно прикрутить... По поводу DMA memory map c5402(без букв) - spru302а.pdf + sprs079e.pdf(datasheet)
  7. Если у Вас камень с5402 (без букв) - то номер не пройдет у него ДМА не поддерживает работу с внешней памятью, насколько я знаю. Если у Вас камень с5402А то такое, думаю, можно реализовать, но такую связку мне самому поднимать не приходилось.
  8. А процессор у Вас как зовут?
  9. Да Если память данных отображена на память программ Так. Если не собираетесь модифицировать код во время выполнения программы и будете использовать только внутреннюю память процессора для кода и данных. Не ошибаетесь по умалчанию она находится в ROM по 0xff80 Насыщение по умолчанию отклучено. Управляют им два бита sst в регистре pmst и ovm в регистре st1 Да
  10. Возможно я неправильно выразился - затирается часть кода уже во время выполнения программы (запись в массивы) Из-за того что память данных отображена на программную память Линкер не причем, он размещает секции кода и данных на тех страницах памяти которые указаны в .cmd, но он ничего не знает о состоянии регистров управления CPU (PMST, ST0, ST1 для с54x)(для него Page 0 и Page 1 - физически разные участки) Программно ввести процессор в нужный режим после ресета = сконфигурировать карту памяти, задать расположение таблицы векторов прерываний, насыщение результата аривфметических операций... - обязанность разработчика.
  11. Одним словом Вы скорее всего затираете часть кода во время записи данных в Ваши Массивы
  12. 1 - Внимательно посмотрите datasheet на tms5402 а именно раздел Memory Map В Том диапазоне адресов, что Вы указали для EPROG и DATA в .cmd файле у 5402 есть непрерывный участок размером только 0x4000 слов, как для программной памяти так и для памяти данных Полный объем внутреенней оперативной памяти для с5402 (16 кСлов = 0x4000)) Так что если симулятор стерпел, то при загрузке в реальную железку CCS скорее всего изругается :) 2 - если в регистре pmst MP/MC=0 и OVLY=1 то диапазон 0x0000 0x4000 Это Физичиски Одна и Таже Оперативная Память
  13. По первому вопросу - Простое умножение коэффициентов и последующее округление или усечение результата до целого может исковеркать АЧХ до неузнаваемости. Умножать коэффициенты принято не на 10^..., а на 2^.... чтобы получить целочисленные значения Загляните вот сюда -> http://www.analog.spb.ru/pub_dsp.htm один из путей решения примерно такой -> %-------------------------------------------------------------------------- function out=Create_IIR() [bn,an] = butter(2,0.125,'low'); Hq=qfilt('df2',{bn,an},... 'CoefficientFormat', quantizer('fixed', 'round', 'saturate', [16 15]),... 'InputFormat', quantizer('fixed', 'round', 'saturate', [16 15]),... 'OutputFormat', quantizer('fixed', 'round', 'saturate', [16 15]),... 'MultiplicandFormat', quantizer('fixed', 'round', 'saturate', [16 15]),... 'ProductFormat', quantizer('fixed', 'round', 'saturate', [32 30]),... 'SumFormat', quantizer('fixed', 'round', 'saturate', [32 30])); Hq=normalize(Hq) figure; freqz(Hq.ReferenceCoefficients{1},Hq.ReferenceCoefficients{2},1024,8000); figure; freqz(Hq.QuantizedCoefficients{1},Hq.QuantizedCoefficients{2},1024,8000); %-------------------------------------------------------------------------- fp=fopen('d:\iir.h','w'); fprintf(fp,'const short IIR_Coefs_DF2[]=\n{\n'); %... % выводим массив kоэффициентов в том виде как нам надо %... fprintf(fp,'//- Numerator coefs \n'); for i=length(Hq.QuantizedCoefficients{1}):-1:1 temp=num2hex(Hq.CoefficientFormat,Hq.QuantizedCoefficients{1}(i)); fprintf(fp,' 0x'); fprintf(fp,temp); fprintf(fp,', // B%x- Numerator coefs \n',i-1); end fprintf(fp,'//- Denumerator coefs \n'); for i=length(Hq.QuantizedCoefficients{2}):-1:1 temp=num2hex(Hq.CoefficientFormat,Hq.QuantizedCoefficients{2}(i)); fprintf(fp,' 0x'); fprintf(fp,temp); fprintf(fp,', // B%x- Numerator coefs \n',i-1); end fprintf(fp,'};\n\n'); fclose(fp) out=Hq; %---------------------------------------------------------------------- Ключевые слова для поиска в хелпе матлаба - qfilt,quantizer,normalize %------------------------------------------------------------------------ По Второму - Действительно перегрузку аккумуляторов надо предотвращать предварительно масштабируя сигнал, и используя насыщенную арифметику. Я Бы порекомендовал предварительно написать функцию фильтра в матлабе и помоделировать, заодно увидите, где и насколько возможна перегрузка во внутренних состояниях. Таким образом сможете определить как надо масштабировать по входу и по выходу чтобы достичь нужного результата.
  14. По-моему проще надо быть - и работать с еепром (читать/писать) только в одной нитке, а фон это или прерывание - это на усмотрение разработчика :)
  15. Да тут вообще все ок должно быть, только в прерываниях к еепром обращаться не надо и фсе...
  16. А, ну если с этой стороны на проблему смотреть то да, сделать, как Владимир предложил, либо завести FIFO и писать в него в фоне, а выгребать из него в прерывании (от EEPROM), конечно тормознее получится...
  17. Я бы просто запретил прерывания на время обращения к еепром в фоне для начала...
  18. Да нет, проблем на стыке быть не должно. Нужно сохранить контекст фильтра после обработки предыдущего кадра. Под контекстом фильтра имею ввиду -> линию задержки и указатель внутри этой линии задержки а сам вызов фильтра можно оформить примерно так void ExampleFIR(unsigned short xFrameLen, short **pBuffer, short *pIn, short *pOut); xFrameLen - длина входного/выходного кадра pBuffer - указатель на ячейку где будет храниться указатель внутри линии задержки (передача параметра по ссылке в С) pIn - указатель на входной кадр pOut - указатель на выходной кадр Или загляните в хелп для DSPLIB там тоже разрисованы некоторые особенности реализации алгоритма Еще рекомендую ознакомиться -> spra556b.pdf (A Multichannel/Algorithm Implementation on the TMS320C6000 DSP) семейство другое но общие принципы реализации алгоритмов одинаковы и не только для фильтров... По поводу размещения данных в конкретных областях памяти - посмотрите в хелпе директивы компилятора #pragma CODE_SECTION и #pragma DATA_SECTION
  19. Нет не ошибаетесь - конечно надо брать весь 32-х битный результат, просто в конкретной реализации Вы сами решите как отмасштабировать результат и какую часть соханить а какая не имеет значерния Согласен в примере dst a,*ar5+ выглядело бы более правильно
  20. Попробую обойтись без кодов 0 Предварительно buffer конечно стоит обнулить 1 Циклическая адрессация для кэффициентов используетс чтобы не переинициализировать заново указатель на коэффициенты - просто после расчета одного выходного отсчета указатель автоматически вернется в начало массива коэффициентов и можно сразу щитать следующую выходную выборку (я не стал в примере этого делать а явно грузил указатель на коэффициенты перед каждой итерацией) 2 Данные в buffer подгружаются последовательно один за другим - крутить надо указатель в циклическом буфере (массиве buffer) допустим coeff[4] - in[10] buffer[4] инициализируем алгоритм - обнуляем все елементы buffer[4] Начали фильтровать подгружаем отсчет buffer[0]=in[0] => buffer = in[0] 0x00 0x00 0x00 фильтруем ... buffer coeffs acc=in[0] *c[0] <-ar4 acc+=0*c[3] acc+=0*c[2] acc+=0*c[1] Сохраняем результат подгружаем отсчет buffer[1]=in[1] => buffer = in[0] in[1] 0x00 0x00 фильтруем ... buffer coeffs acc=in[0] *c[1] acc+=in[1] *c[0] <-ar4 acc+=0*c[3] acc+=0*c[2] Сохраняем результат подгружаем отсчет buffer[2]=in[2] => buffer = in[0] in[1] in[2] 0x00 фильтруем ... buffer coeffs acc=in[0] *c[2] acc+=in[1] *c[1] acc+=in[2] *c[0] <-ar4 acc+=0*c[3] Сохраняем результат подгружаем отсчет... buffer[3]=in[3] => buffer = in[0] in[1] in[2] in[3] фильтруем ... buffer coeffs acc=in[0] *c[3] acc+=in[1] *c[2] acc+=in[2] *c[1] acc+=in[3] *c[0] <-ar4 Сохраняем результат подгружаем отсчет... buffer[0]=in[4] => buffer = in[0] in[1] in[2] in[3] фильтруем ... buffer acc=in[4] *c[0] <-ar4 acc+=in[1] *c[3] acc+=in[2] *c[2] acc+=in[3] *c[1] Сохраняем результат подгружаем отсчет... buffer[0]=in[4] => buffer = in[4] in[5] in[2] in[3] фильтруем ... buffer coeffs acc=in[4] *c[1] acc+=in[5] *c[0] <-ar4 acc+=in[2] *c[3] acc+=in[3] *c[2] Сохраняем результат Как интерпретировать результат целиком зависит от Вас sth a,... в данном контексте можно перевести как "resault=acc > > 16" масштабирование на выходе одним словом
  21. Вот как-то так можно пользоваться циклическими буферами Только как Пример реализация в лоб FIR фильтра c использованием циклической адрессации фильтрует 150 входных отсчетов ar2 - указатель на входной массив выборок ar3 - указатель на массив коэффициентов ar4 - указатель внутри циклического буфера (линии задержки) ar5 - указатель на выходной массив выборок ;// ... xN .set 100 xSamplesNum .set 150 _ExampleFir stm #xN,BK ;задаем размер циклического буфера (лини задержки) stm #InBuff,ar2 ;Массив входных выборок stm #OutBuff,ar5 ;Массив выходных выборок mvdk *(buffer),ar4 ;инициализируем указатель внутри циклического буфера линии задержки ; (стартовый адрес буфера должен быть выровнен в памяти по границе 128 для BK=100) stm #xSamplesNum-1,brc ;инициализируем счетчик входных отсчетов stm #-1,ar0 nop nop ;(не оптимально - но наглядно) rptb fir_loop_end-1 stm #coeff,ar3 ; инициализируем указатель на коэффициенты фильтра mvdd *ar2+,*ar4 ; Помещаем очередной отсчет в линию задержки rptz a,#xN-1 mac *ar3+,*ar4+0%,a ; Собственно FIR для одного входного отсчета sth a,*ar5+ ; Сохраняем выходной отсчет mar *ar4-0% ; Модифицируем указатель внутри линии задержки fir_loop_end mvkd ar4,*(buffer) ; сохраняем указатель циклического буфера для следующего цикла обработки ;// ...
  22. по реализации фильтров на c54x (подробно - spru173.pdf) BK - регистр процессора в нем хранится размер циклического буфера в с54х циклический буфер необходимо выравнивать по одресам кратным степеням двойки (подробно - spru131F.pdf (Circular Address Modifications)) *ar4+0% - означет обращение к ячейке памяти по адресу находящемуся во вспомогательном регистре ar4 +0 означает что после обращения адресный регистр (ar4) увеличится на значение лежащее в индексном регистре ar0 % - означает что используется циклическая aдресная ариффметика пример: до инструкции al = 0x7fff bk = 0x0010 ar0 = 2 ar4 = 0x400f *(0x400f) = 0x0000; ... stl a,*ar4+0% 1 такт после инструкции al = 0x7fff bk = 0x0010 ar0 = 2 *(0x400f) = 0x7fff ar4 = 0x4001
  23. Вот еще -> http://www.koders.com/c/fidFB061A3A59F844A...0EEA2DDD87.aspx
  24. Извините за бред в пред ид посте - не видел доку f281x и их карту памяти в глаза Щас глаза открылись :-) На Вашем месте Поступил бы так - часть кода разместил бы в M0 (M1,L0,L1), То есть часть кода из .text перенес в другую секцию и разместил эту секцию в M0(M1,L0,L1) (вроде как отображены в программную страницу) если, конечно, хватает места под стэк и данные
×
×
  • Создать...