Архитектура микроконтроллера TMS320C33

Процессор имеет Неймановскую архитектуру (общее адресное пространство для исполняемого кода и данных), содержит 28 внутренних регистров, которые можно разбить на несколько функциональных групп:

– R0…R7extended-precision registersрегистры повышенной точности, каждый из них работает с 32-битовым целым числом или 40-битовым плавающим числом повышенной точности, которая снимает проблему накопления ошибки округления.
– AR0…AR7auxiliary registers32-битовые вспомогательные регистры, с помощью которых организуются все методы косвенной адресации.
– IR0, IR1index registers32-битовые индексные регистры вместе с ARx регистрами поддерживают косвенно-индексную адресацию.
– DPdata page pointer32-битовый регистр указатель страницы памяти, в котором используются только 8 младших разрядов. Служит для задания старшей части адреса в случае использования прямой адресации. В машинную команду, в этом случае, помещается только 16 бит из полного 24-битового адреса.
– BKblock size register32-битовый регистр, задающий размер блока для циклического типа адресации.
– SPsystem stack pointer32-битовый указатель стека.
– STstatus registerрегистр статуса, в котором хранятся флаги процессора, и биты управления внешними прерываниями – реакция на потенциал или спад.
– IECPU/DMA interrupt enable register32-битовый регистр разрешения прерываний и прямого доступа.
– IFCPU interrupt flag register32-битовый регистр флагов запроса прерываний.
– IOFflags registerрегистр ввода/вывода для сигналов XF0, XF1.
– RCrepeat counter32-битовый регистр счетчика.
– RSrepeat start register32-битовый регистр начала цикла.
– RErepeat end address register32-битовый регистр конца цикла.
– PCprogram counter32-битовый регистр счетчика команд, доступен только через команды перехода

Типы команд

Все команды процессора имеют фиксированную длину 32 бита, их можно разбить на следующие группы:

Двухоперандные

В команде присутствуют только два операнда:

операнд1 = источник, операнд2 = приемник.

Например: ADDF *AR0,R1

сложить два числа в плавающем формате, где:

операнд1=*AR0 число по адресу, хранящемуся в регистре AR0;

операнд2 = R1 второе число из регистра R1,

результат операции помещается в R1.

Трехоперандные

В команде присутствуют три операнда:

операнд1 = источник1 , операнд2 = источник2, операнд3 = приемник результата.

Например: ADDF3 *AR0,R1,R3

сложить два числа в плавающем формате, где:

источник1=*AR0 число по адресу, хранящемуся в регистре AR0;

источник2 = R1 второе число хранится в R1,

приемник = R3 результат операции в R3.

Параллельные команды

Позволяют выполнять две команды за один машинный цикл.

Каждая из этих команд может быть или двухадресной, или трехоперандной.

Например: MPYF3 *AR0,R5,R0 || ADDF3 R7,*AR1,R2

в этом случае за один машинный цикл выполняются одновременно две команды сложения и умножения с плавающими числами.

Cпециальные команды условного/безусловного перехода

Время выполнения команд условного/безусловного перехода: Bcond, BR, DBcond, CALL, CALLcond занимает четыре машинных цикла. Для обеспечения максимального быстродействия в процессоре предусмотрены специальные “задержанные” команды перехода: BcondD, BRD, DBcondD, CALLD, CALLcondD, которые выполняются за один машинный цикл, но при этом переход осуществляется через три команды после команды перехода. Использование подобных команд требует определенной адаптации алгоритма и программы, но при этом дает ощутимый эффект.

Специальные типы адресации

– двоичноинверсная адресация (bit reversed addressing) снимает временные затраты на процедуры упорядочивания в алгоритмах быстрого преобразования Фурье, Хартли.

– циклическая адресация (circular addressing) необходима для работы с циклическими буферами, которые по достижению своего конца автоматически возвращаются в начало (отпадает необходимость программного контроля конца буфера). Позволяет ускорять вычисление корреляционных, ковариационных функций, фильтрации и т.д.

Инструкции TMS320C33 для работы с плавающей арифметикой

Все перечисленные ниже команды выполняются за один машинный цикл, при выполнении программы из внутреннего ОЗУ. При выполнении программы из внешнего ОЗУ, время выполнения программы увеличивается в 1,5 — 2 раза.

ABSF src,dst вычисляет абсолютное значение плавающего числа src, т.е. dst = |src|.
ABSF src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл вычисляет модуль числа dst1 = |src2| и засылает плавающее число src3 в память dst2.
ADDF src,dst складывает два плавающих числа: dst + src –> dst.
ADDF3 src2,src1,dst складывает два плавающих числа: src2 + src1 –> dst.
ADDF3 src2,src1,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл складывает два числа dst1 = src2 + src1 и засылает плавающее число src3 в память dst2.
CMPF src,dst сравнивает два плавающих числа dst-src, не изменяя операндов, и устанавливает флаги в регистре ST.
CMPF3 src2,src1 сравнивает два плавающих числа src1-src2, не изменяя операндов, и устанавливает флаги в регистре ST.
FIX src,dst переводит плавающее число src в целое: fix(src) –> dst.
FIX src2,dst1 || STI src3,dst2 параллельная команда, которая за один машинный цикл переводит плавающее число src в целое dst1=fix(src2) и пересылает целое число src3 в память dst2.
FLOAT src,dst переводит целое число src в плавающее число: float(src) –> dst.
FLOAT src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл переводит целое число src в плавающее dst1 = float (src2) и засылает плавающее число src3 в память dst2.
LDF src,dst загружает из памяти (регистра) src плавающее число в dst: src –> dst.
LDFcond src,dst загружает из памяти (регистра) src плавающее число в dst, если выполняется условие cond: if cond is true: src –> dst.
LDF src2,dst2 || LDF src1,dst1 параллельная команда, которая за один машинный цикл выполняет две пересылки плавающих чисел: src2 –> dst2 и src1 –> dst1.
LDF src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл выполняет загрузку из памяти (регистра): src2 –> dst1 и сохраняет src3 в памяти: src3 –> dst2.
MPYF src,dst перемножает два плавающих числа: dst = src * dst.
MPYF3 src2,src1,dst перемножает два плавающих числа: dst = src1 * src2.
MPYF3 srcA,srcB,dst1 || ADDF3 srcC,srcD,dst2 параллельная команда, которая за один машинный цикл выполняет команду умножения и сложения с плавающими числами: srcA * srcB –> dst1, srcC + srcD  –> dst2.
MPYF3 src2,src1,dst || STF src3,dst2 параллельная команда, которая за один машинный цикл выполняет команду умножения плавающих чисел: src1 * src2 –> dst и сохранение src3 в памяти: src3 –> dst2.
MPYF3 srcA,srcB,dst1 ||SUBF3 srcC,srcD,dst2 параллельная команда, которая за один машинный цикл выполняет команду умножения и вычитания с плавающими числами: srcA * srcB  –> dst1, srcD — srcC –> dst2.
NEGF src,dst арифметическое отрицание: dst = -src.
NEGF src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл вычисляет обратное число: -src2 –> dst1 и сохраняет src3 в памяти: src3 –> dst2.
POPF dst переслать плавающее число со стека в регистр dst.
PUSHF dst переслать плавающее число из регистра на стек.
STF src,dst сохранение регистра src в памяти: src –> dst.
STF src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл выполняет две пересылки в память: src2 –> dst1; src3 –> dst2.
SUBF src,dst вычитает два плавающих числа: dst — src –> dst.
SUBF3 src2,src1,dst вычитает два плавающих числа: src1 — src2 –> dst.
SUBF3 src1,src2,dst1 || STF src3,dst2 параллельная команда, которая за один машинный цикл выполняет вычитание двух плавающих чисел: src2 — src1 –> dst1 и сохраняет src3 в памяти: src3 –> dst2.
SUBRF src,dst вычитание dst из src с сохранением в dst: src-dst –> dst.

TMS320C33 имеет аналогичные инструкции для целочисленной арифметики.

Формат чисел с плавающей точкой

1. Числа сокращенного формата
 биты машинной команды при непосредственной адресации
15 14 13 121110 9 8 7 6 5 4 3 2 1 0
Порядок
числа
Знак
числа
Мантисса
2. Числа обычного формата
 биты ячейки памяти
31 30 29 … 252423 22 21 20 … 7 6 5 4 3 2 1 0
Порядок
числа
Знак
числа
Мантисса
3. Числа повышенной точности
 биты регистра R0 — R7
39 38 37 … 34 333231 30 29 28 27 … 7 6 5 4 3 2 1 0
Порядок
числа
Знак
числа
Мантисса

Пример программы для TMS320C33

Одной из широко распространенных задач, которую часто приходится решать программистам и разработчикам электронной аппаратуры, это задача фильтрации сигналов. Для примера рассмотрим реализацию КИХ фильтра (фильтр с конечной импульсной характеристикой).

y(n)=h(0)*x(n)+h(1)*x(n-1)+…+h(N-1)*x(n-N+1)

При разработке программы важно добиться максимального использования параллельных команд и сократить время вычислений.

Ниже приведен текст программы фильтра:

AR0адрес буфера импульсной характеристики, указывающий на h(N-1);
AR1адрес предистории входного сигнала, указывающий на x(n-N+1);
RCхранит значение N-2, порядок фильтра-2;
BK хранит значение N, порядок фильтра.
   
MPYF3*AR0++(1),*AR1++(1)%,R0;h(N-1)*x(n-N+1) –> R0
LDF0.0,R2; 0e0 –> R2 инициализация
RPTSR C; начало цикла
MPYF3*AR0++(1),*AR1++(1)%,R0 || ADDF3 R0,R2,R2; эта команда выполняется в цикле N-1 раз
; h(N-1-i)*x(n-N+1+i)+sum
ADDFR0,R2,R0;последнее суммирование
RETS ; выход из подпрограммы.

Программа занимает шесть 32-битовых слов с временем выполнения 11 + (N-1) машинных циклов. Поскольку в данном примере используются инструкции, работающие с числами плавающего формата, нет опасности переполнений, что позволяет избежать применения дополнительных команд.

В главном цикле применена параллельная команда (MPYF3 || ADDF3), позволяющая увеличить скорость выполнения программы в два раза.