Быстрая тригонометрия: математический ускоритель CORDIC в микроконтроллерах STM32G4
14 сентября 2020
Александр Калачев (г. Барнаул)
Модуль математического ускорителя вычисления тригонометрических, логарифмических и гиперболических функций CORDIC, встроенный компанией STMicroelectronics в микроконтроллеры новой серии STM32G4, незаменим в задачах, связанных с управлением двигателями, навигационными системами, системами управления движением узлов и агрегатов, в задачах управления и контроля электроснабжения, а также при обработке сигналов и в системах искусственного интеллекта.
Современные задачи управления часто требуют значительного объема вычислений. Наиболее распространенные из них – управление двигателями, обработка изображений, некоторые приложения искусственного интеллекта, графический пользовательский интерфейс, навигация, системы управления движением, цифровая обработка сигналов. При этом сложность и объем вычислений постоянно возрастают по мере роста требований к скорости, точности и адаптивности систем управления и повышения сложности прикладных задач.
Большой объем вычислений так или иначе касается расчета трансцендентных функций – тригонометрических, показательных, логарифмических и прочих. Даже при наличии математических библиотек и аппаратных модулей вычислений с плавающей точкой расчеты трансцендентных функций занимают значительное время при стопроцентной загрузке центрального процессора. В системах управления, обязанных одновременно отслеживать множество параметров и событий, где требуется обеспечить предсказуемое и, желательно, минимальное время реакции системы на событие, необходимо или сокращать время вычислений, жертвуя точностью, или проводить жесткую оптимизацию кода математических библиотек или отдельных функций.
CORDIC – старый, но не бесполезный алгоритм
На выручку приходит алгоритм из времен, когда «компьютеры были большими и медленными, а программы маленькими и быстрыми» – CORDIC (Coordinate Rotation Digital Computer) – итерационный алгоритм последовательного приближения для вычисления сложных функций простыми операциями. Данный метод был предложен в 1956-м году Джеком Волдером для вычисления тригонометрических функций и операций преобразования координат (отсюда и название алгоритма). Благодаря тому, что алгоритм использует только простые операции сложения и сдвига в комбинации с предварительно вычисленными табличными значениями, он подходит для применения даже в системах с относительно небольшими вычислительными ресурсами, а также для аппаратной реализации [1].
Еще одним достоинством CORDIC является то, что с его помощью можно вести вычисления в целочисленном формате, или в формате с фиксированной точкой.
CORDIC является достаточно быстрым алгоритмом, количество итераций совпадает с разрядностью результата: при желании вычисления результата могут вестись как с 8-, так и с 32-битной точностью. Алгоритм широко использовался в первых вычислительных системах, более того, он применялся в математическом сопроцессоре 8*87 для вычисления тригонометрических функций, экспонент и логарифмов.
Несмотря на свою простоту в плане базовых операций, таких как сложение и сдвиг, CORDIC позволяет вычислять:
- тригонометрические функции – sin(), cos(), atan(), atan2();
- гиперболические функции – sinh(), cosh(), atanh();
- показательные функции – sqrt(), exp(), ln() (полный список доступных функций можно посмотреть в [2]).
Работу метода последовательного приближения можно рассмотреть на примере задачи угадывания числа из заданного диапазона (или поиска корня уравнения в заданном интервале):
0) предполагаем, что число – середина диапазона – будет нулевым приближением, а само значение середины диапазона будет текущим шагом приближения;
1) сравниваем нулевое приближение с искомым числом. Если равенства нет – продолжаем по шагам ниже;
2) уменьшаем шаг приближения вполовину;
3) если искомое число больше – прибавляем к нулевому приближению число текущего значения шага (если искомое число меньше – то отнимаем), получаем первое приближение;
4) сравниваем первое приближение с искомым числом, если равенство не достигнуто – повторяем с пункта 2 до достижения равенства.
Например, задано число 77, диапазон 0…100, дополнительное условие – все операции только с целыми числами. Получаем:
- нулевым приближением в данном случае будет 50, текущий шаг приближения – также 50;
- 50 ≠ 77, придется подбирать дальше;
- уменьшаем шаг 50/2 = 25;
- 50 < 77, значит, значение шага надо прибавить: 50 + 25 = 75;
- 75 ≠ 77, уменьшаем шаг еще вполовину: 25/2 = 12 (помним, что операции ведем в целых числах);
- следующее приближение будет 75 + 12 = 87;
- 87 ≠ 77, уменьшаем шаг: 12/2 = 6;
- 87 > 77, значение шага нужно отнять: 87 – 6 = 81;
- 81 ≠ 77, уменьшаем шаг: 6/2 = 3;
- 81 > 77, отнимаем шаг: 81 – 3 = 78;
- 78 ≠ 77, уменьшаем шаг: 3/2 = 1;
- 78 > 77, отнимаем шаг: 78 – 1 = 77;
- 77 = 77 – равенство достигнуто!
Итоговая последовательность вычислений по подбору числа выглядит так:
50 + 25 + 12 – 6 – 3 – 1 = 77
CORDIC при вычислениях действует по тому же принципу.
Для демонстрации принципа работы алгоритма приводят канонический пример с определением угла наклона вектора с заданными координатами X и Y относительно оси 0X путем последовательности вращений вектора на определенные углы по или против часовой стрелки до достижения нулевого угла. Итоговая сумма углов поворота в результате даст приближенное значение исходного угла (точность будет зависеть от заданной разрядности); по сути, это типовая операция перехода из декартовой системы координат (X, Y) в полярную (угол, модуль).
Изменения координат вектора на каждом шаге математически выглядят как:
- при повороте против часовой стрелки:
- Xnew = X – Y × TAN(Angle);
- Ynew = Y + X × TAN(Angle);
- Angle = Angle[next_step].
- при повороте по часовой стрелке:
- Xnew = X + Y × TAN(Angle);
- Ynew = Y – X × TAN(Angle);
- Angle = Angle[next_step].
Оригинальный и хитрый ход – чтобы избавиться от операции умножения, углы выбираются таким образом, чтобы их тангенсы были отрицательными степенями двойки (2-n, где n – номер итерации). В данном случае умножение просто заменится на сдвиг (сдвиг влево, поскольку числа меньше единицы).
В итоге действия на каждой итерации будут следующими.
- Формируем таблицу углов:
- AngTable = 45; 26,565; 14,036; 7,125; 3,576; 1,790; 0,895; 0,448.
- Начальные значения углов и итерации:
- SumAngle = 0;
- LoopNum = 0.
И на каждом шаге:
- Если результирующий Y положителен:
- Xnew = X + (Y >> LoopNum);
- Ynew = Y – (X >> LoopNum);
- SumAngle = SumAngle + AngTable[LoopNum];
- LoopNum = LoopNum + 1.
- Если Y отрицательный:
- Xnew = X – (Y >> LoopNum);
- Ynew = Y + (X >> LoopNum);
- SumAngle = SumAngle – AngTable[LoopNum];
- LoopNum = LoopNum + 1.
Итерации прекращаются, когда значение Y станет нулевым. Разрешение по углам будет зависеть от выбранного коэффициента масштабирования.
И наоборот, для случая векторов единичной длины при известном угле практически аналогично можно найти значение пары sin() и cos(). В общем случае, при смене системы координат возможно вычисление аналогичными способами показательных и гиперболических функций.
Унифицированный алгоритм CORDIC использует три регистра – X, Y для координат, Z для угла [5]. Из операций задействуются только сложения и сдвиги (вместо деления/умножения), масштабирующий коэффициент (Fn) добавляется в самом конце по завершении всех итераций:
- Xn + 1 Fn = [Xn – M S Yn/2n];
- Yn + 1 Fn = [S Xn/2n + Yn];
- Zn + 1 = Zn – S A
Коэффициент M, элементарный угол An и масштабирующий коэффициент Fn определяются в зависимости от используемой системы координат CORDIC:
- полярная – An = atan(1/2n), n от 0, M = +1, Fn = sqrt(1 + 1/22n);
- линейная – An = 1/2n, n от 0, M = 0, Fn = sqrt(1);
- гиперболическая – An = atanh(1/2n), n от 1, M = -1, Fn = sqrt(1 — 1/22n).
Множитель S определяется режимом работы алгоритма CORDIC:
- вращение – угол Z сводится к 0 — S = + 1, если Z ≥ 0 и S = -1, если Z < 0;
- векторизация – компонент Y сводится к 0 — S = +1, если Y ≤ 0 и S = -1, если Y > 0.
Угол в регистре Z должен быть меньше угла сходимости, который является суммой углов An на каждой итерации. В случае гиперболической системы координат для получения сходимости необходимо повторить следующие итерации: 4, 13, 40,… k, … 3k + 1 (рисунок 1):
- полярная – A = Σ An = 1,7432866 radians (99,9deg), n = 0, 1, 2, 3, 4, 5, … N;
- линейная – A = Σ An = 2, n = 0, 1, 2, 3, 4, 5, … N;
- гиперболическая – A = Σ An = 1,1181730 radians (64deg), n = 1, 2, 3, 4, 4, 5, …

Рис. 1. Микроповороты в алгоритме CORDIC в полярной, линейной и гиперболической системах координат
Из-за особенностей алгоритма в ходе работы CORDIC всегда вычисляется пара значений.
По сравнению с другими математическими библиотеками программная реализация CORDIC для 32-разрядных контроллеров занимает всего около 1 кбайт (для ядер ARM Cortex-M0, M4) [1] при сравнимой производительности вычислений на контроллерах с модулем вычислений с плавающей точкой.
CORDIC в STM32G4
Как уже упоминалось выше, CORDIC крайне нетребователен к аппаратным ресурсам. Как минимум, из-за отсутствия в нем операций умножения он достаточно привлекателен для аппаратной реализации – аппаратные умножители довольно затратны при реализации «в кремнии» из-за сложности схемы, оптимизации топологии, большой занимаемой площади, дополнительного энергопотребления. а в случае с CORDIC выполняются всего лишь элементарные сдвиги, сложение, и задействованы несколько регистров памяти. В серии STM32G4 компания STMicroelectronics сделала подарок разработчикам, разместив в микроконтроллерах аппаратный модуль-ускоритель, реализующий алгоритм CORDIC, дополнительно к ускорителям ART и FMAC [3, 4].
Серия STM32G4 относится к классу микроконтроллеров со смешанными сигналами. Главное их преимущество заключается в том, что разработчик может с их помощью заменить множество отдельных микросхем (ЦАП, АЦП, ОУ, компараторов, ИОН и прочих), и они могут работать как с аналоговыми сигналами, так и с цифровыми.
Как и оригинальный алгоритм, CORDIC-ускоритель (CORDIC-сопроцессор) в STM32G4 производит вычисления в формате с фиксированной точкой и, с позиции программиста, прост для применения [5, 6]:
- результаты вычислений просто отображаются в регистрах результатов, отображаемых в пространство памяти микроконтроллера;
- режимы прерываний и прямого доступа к памяти также доступны;
- поддерживаются режимы потоковых операций.
Сопроцессор CORDIC обеспечивает аппаратное ускорение трансцендентных математических функций, обычно используемых для управления двигателями, обработки сигналов и многих других задачах.
Сопроцессор ускоряет расчет данных функций по сравнению с их программной реализацией, что в итоге позволяет освободить вычислительные ресурсы центрального процессора для выполнения сопутствующих задач.
Блок CORDIC является подчиненным устройством на шине AHB, инициирующим состояние ожидания, когда Cortex-M4 запрашивает результат до завершения операции. Еще один небольшой подарок программистам – нет необходимости в специализированном драйвере ввода/вывода для данного сопроцессора. В случае задействования режима генерации прерывания ядро Cortex-M4 получает возможность обрабатывать другую информацию, пока сопроцессор находится в процессе вычислений. В этом случае запрос прерывания от блока CORDIC указывает, что результат доступен (рисунок 2).

Рис. 2. Взаимодействие CORDIC-сопроцессора с основной системой STM32G4
Сопроцессор поддерживает режим прямого доступа к памяти и режим конвейерной обработки – принимает следующие аргументы в процессе вычисления текущих значений.
Поддерживается вычисление следующих функций:
- косинус;
- синус;
- фаза;
- модуль вектора;
- арктангенс;
- гиперболический синус;
- гиперболический косинус;
- гиперболический арктангенс;
- натуральный логарифм;
- квадратный корень.
Безусловно, существует ряд ограничений, связанных с тем, что CORDIC-ускоритель – это все-таки узел целочисленных вычислений (вычисления происходят в формате с фиксированной точкой). Однако умелое использование тригонометрических преобразований, формул приведения углов, свойств гиперболических функций и логарифмов позволяет с легкостью вычислять практически любые функции и обходить ограничения на входные параметры модуля CORDIC.
В полярном (круговом) режиме (Circular mode) CORDIC сходится для всех углов в диапазоне -π…π радиан. Использование представления с фиксированной точкой означает, что входные и выходные значения должны находиться в диапазоне от -1 до +1. Входные углы в радианах должны быть умножены на 1/π, а выходные углы должны быть умножены на π для преобразования обратно в радианы.
Модуль CORDIC при работе в зависимости от настроек использует один из форматов: q1.31 или q1.15.
В формате q1.31 числа представлены одним знаковым битом, и 31 битом для дробной части представлены двоичные разряды. В формате q1.15 – один знаковый бит и 15 бит дробной части.
Преимущество этого формата заключается в том, что два входных аргумента могут быть упакованы в одно 32-битное число, и два результата также могут быть получены в одном числе. Однако точность уменьшается до 2-15 (около 3×10-5).
Так, в формате q1.31 значение 0х80000000 будет соответствовать -1, а 0х7FFFFFFF – 1 — 2-31, в представлении q1.15 -1 – 0x8000, 1 — 2-15 – 0x7FFF.
Значение модуля вектора должно находиться в диапазоне 0…1 независимо от того, преобразуется он из полярных координат в декартовы или наоборот.
В гиперболическом режиме результат определяется только для x ≥ 1, все входы и выходы делятся на 2, чтобы оставаться в числовом диапазоне с фиксированной точкой. Следовательно, CORDIC без дополнительного масштабирования поддерживает значения x = cosh (t) в диапазоне 1…2 (то есть 0,5…1 после деления на 2), что соответствует величине гиперболического угла t в диапазоне 0…1,317.
В круговом режиме алгоритм CORDIC сходится со скоростью одного двоичного разряда за итерацию. Это означает, что для достижения 16-битной точности требуется 16 итераций. За один системный цикл процессора выполняются четыре итерации. Максимально достижимая точность ограничена количеством бит в «механизме» CORDIC (переключателях и сумматорах, а также таблице, используемой для хранения последовательных углов поворота) и, конечно, во входных и выходных регистрах. Устройство CORDIC серии STM32G4 поддерживает 16- и 32-битные входные и выходные данные (входные форматы q1.15 и q1.31, соответственно) и имеет внутреннюю разрядность в 24 бита.
Рисунок 3 демонстрирует зависимость ошибки вычислений в модуле CORDIC в полярном, или тригонометрическом, и гиперболическом режимах от количества итераций алгоритма расчетов со входными данными в 16- и 32-битных форматах [4,5].

Рис. 3. Зависимость ошибки вычислений в модуле CORDIC в полярном (а) и гиперболическом (б) режимах от количества итераций
Некоторые функции допускают применение коэффициента масштабирования SCALE. Это позволяет расширить диапазон входных функций, чтобы охватить весь диапазон значений, поддерживаемых CORDIC, без насыщения входных, выходных или внутренних регистров.
Если требуется масштабный коэффициент, он должен быть заранее программно рассчитан и записан в поле SCALE регистра CORDIC_CSR. Однако есть и нюансы – входные аргументы должны быть соответствующим образом масштабированы перед программированием масштабированных значений в регистре CORDIC_WDATA. Масштабирование также должно быть отменено для результатов, считанных из регистра CORDIC_RDATA. Помимо прочего, коэффициент масштабирования влечет за собой потерю точности из-за усечения масштабированного значения в разрядной сетке.
Формат аргументов функций и формат представлений результатов зависят от значений полей ARGSIZE и RESSIZE регистра CORDIC_CSR и от вычисляемой функции в поле FUNC того же регистра.
Вычисляемые функции могут требовать один или два входных аргумента (регистры ARG1, ARG2) и возвращать один или два результата (регистры RES1, RES2). Так, при вычислении косинуса парным ему результатом будет синус, и наоборот. Аналогичная ситуация – с функциями вычисления модуля и фазы вектора, с гиперболическими синусом и косинусом.
Функции и аргументы модуля CORDIC
Вычисления при помощи модуля CORDIC достаточно просты с программной точки зрения. Рассмотрим пример преобразования полярных координат в декартовы при помощи функции cos (таблица 1). Исходные тексты примера доступны в STM32CubeG4 MCU Package, в папке примеров проектов \Projects\NUCLEO-G474RE\Examples_LL\CORDIC\CORDIC_CosSin [5]:
1. Конфигурируется CORDIC:
LL_CORDIC_Config(CORDIC,
LL_CORDIC_FUNCTION_COSINE, /* вычисляем функцию косинус */
LL_CORDIC_PRECISION_6CYCLES, /* задаем количество итераций, в данном случае –
для максимальной точности формата q1.31 для функции косинус */
LL_CORDIC_SCALE_0, /* не требуется масштабирования*/
LL_CORDIC_NBWRITE_1, /* один входной аргумент – угол, второй будет принят за 1 */
LL_CORDIC_NBREAD_2, /* два выходных результата – косинус, затем синус */
LL_CORDIC_INSIZE_32BITS, /* q1.31 – формат входных данных */
LL_CORDIC_OUTSIZE_32BITS); /* q1.31 – формат выходных данных */
2. Записываются входные аргументы:
/* записываем угол */
LL_CORDIC_WriteData(CORDIC, ANGLE_CORDIC);
3. Считываются результаты:
/* считываем косинус */
cosOutput = (int32_t)LL_CORDIC_ReadData(CORDIC);
/* считываем синус */
sinOutput = (int32_t)LL_CORDIC_ReadData(CORDIC);
Легко заметить, что отсутствует команда ожидания результата или проверки готовности результата – первое считывание завершится, как только результат преобразования будет готов. Поскольку выходной результат был затребован в формате q1.31, для его полного считывания необходимы две операции чтения. Если бы выходные результаты были сконфигурированы в формате q1.15, достаточно было бы одного чтения – результаты разместились бы в старшей и младшей частях 32-битной переменной результата (таблицы 2…10) [5, 6].
Таблица 1. Аргументы и результаты для функции cos()
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | Угол ϑ в радианах, нормированный на 1/π |
[-1; 1] |
ARG2 | Модуль m | [0; 1] |
RES1 | m·cos(ϑ) | [-1; 1] |
RES2 | m·sin(ϑ) | [-1; 1] |
SCALE | – | 0 |
Таблица 2. Аргументы и результаты для функции sin()
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | Угол ϑ в радианах, нормированный на 1/π |
[-1; 1] |
ARG2 | Модуль m | [0; 1] |
RES1 | m·sin(ϑ) | [-1; 1] |
RES2 | m·cos(ϑ) | [-1; 1] |
SCALE | – | 0 |
Таблица 3. Аргументы и результаты для функции вычисления фазового угла
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | X-координата | [-1; 1] |
ARG2 | Y-координата | [-1; 1] |
RES1 | Фазовый угол ϑ, деленный на π | [-1; 1] |
RES2 | Модуль m | [0; 1] |
SCALE | – | 0 |
Таблица 4. Аргументы и результаты для функции вычисления модуля вектора
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | X-координата | [-1; 1] |
ARG2 | Y-координата | [-1; 1] |
RES1 | Модуль m | [0; 1] |
RES2 | Фазовый угол ϑ, деленный на π | [-1; 1] |
SCALE | – | 0 |
Таблица 5. Аргументы и результаты для функции atan()
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | x × 2-n | [-1; 1] |
ARG2 | – | – |
RES1 | 2-n·tan-1(x) в радианах, деленный на π | [-1; 1] |
RES2 | – | [-1; 1] |
SCALE | n | [0; 7] |
Таблица 6. Аргументы и результаты для функции cosh()
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | x × 2-n | [-0,559; 0,559] |
ARG2 | – | – |
RES1 | 2-n·cosh(x) | [0,5; 0,846] |
RES2 | 2-n·sinh(x) | [-0,683; 0,683] |
SCALE | n | 1 |
Таблица 7. Аргументы и результаты для функции sinh()
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | x × 2-n | [-0,559; 0,559] |
ARG2 | – | – |
RES1 | 2-n·sinh(x) | [-0,683; 0,683] |
RES2 | 2-n·cosh(x) | [0,5; 0,846] |
SCALE | n | 1 |
Гиперболические синус и косинус могут быть использованы для вычисления экспоненциальных функций (кто говорил, что школьная математика не нужна и «зачем учить эти формулы»?):
ex =cosh(x) + sinh(x);
e-x = cosh(x) — sinh(x).
Таблица 8. Аргументы и результаты для функции atanh()
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | x × 2-n | [-0,403; 0,403] |
ARG2 | – | – |
RES1 | 2-n·atanh(x) | [-0,559; 0,559] |
RES2 | – | – |
SCALE | n | 1 |
Таблица 9. Аргументы и результаты для функции ln()
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | x × 2-n | [0,054; 0,875] |
ARG2 | – | – |
RES1 | 2-n·ln(x) | [0,279; 0,137] |
RES2 | – | – |
SCALE | n | [1; 4] |
Таблица 10. Аргументы и результаты для функции √()
Параметр | Описание | Диапазон |
---|---|---|
ARG1 | x × 2-n | [0,027; 0,703] |
ARG2 | – | – |
RES1 | 2-n·√x | [0,04; 1] |
RES2 | – | – |
SCALE | n | [0; 2] |
Программное обеспечение, которое выполняет вычисления на блоке CORDIC, не должно опрашивать флаг, чтобы определить, когда этот расчет завершен. Просто инициируется запрос на чтение регистра RDATA через шину AHB. Как и любой транзакции AHB, ведомому разрешено вставлять состояния ожидания, поддерживая низкий уровень сигнала HREADY. Как только результаты доступны, блок CORDIC устанавливает HREADY, что завершает транзакцию. В течение этого времени выполнение кода на ядре Cortex-M4 приостанавливается. Этот подход к работе с CORDIC-сопроцессором называется режимом с нулевыми издержками (Zero-Overhead mode).
Запуск работы логики CORDIC начинается после записи аргументов во входные регистры, и, пока внутренняя логика проводит вычислительные итерации, возможна запись новых значений во входные регистры. Как только результаты были прочитаны из RDATA (одна или две операции чтения в зависимости от значения NRES), запускается операция с новыми входными данными. Новый набор аргументов и настроек может быть записан при условии, что нет ожидающих операций. То есть время, потраченное на ожидание завершения операции CORDIC, можно использовать для подготовки аргументов для следующей операции (рисунок 4). Таким образом, CORDIC-сопроцессор никогда не находится в режиме ожидания, а центральный процессор постоянно получает поток вычисленных результатов, что в итоге повышает общую производительность системы, сокращая или совсем исключая простои, связанные с ожиданием результатов.

Рис. 4. Потоковые операции в режиме с нулевыми издержками
Режим с нулевыми издержками особенно эффективен в случае единичных или относительно редких вычислений с использованием CORDIC.
Программист также может использовать вычисления на CORDIC-сопроцессоре в режиме с генерацией и обработкой прерываний. Для этого достаточно установить бит IEN в регистре настроек CORDIC_CSR. В этом случае по завершении вычислений будет сгенерировано прерывание, которое можно будет обработать. Такой способ, конечно, позволяет центральному процессору продолжать выполнение задачи после запуска расчетов на CORDIC, но, в целом, это происходит медленнее режима с нулевыми издержками из-за процедуры вызова обработчика прерываний, передачи результатов в основную программу и тому подобных вспомогательных действий.
В том случае, когда предстоят расчеты определенного множества значений одной и той же функции (настройки CORDIC-модуля не изменяются), предпочтительнее использовать режим прямого доступа к памяти. При прямом доступе к памяти сам CORDIC-модуль всегда работает в потоковом режиме (рисунок 5). Единственное условие – в ходе расчетов не должны меняться настройки режима работы модуля.

Рис. 5. Работа CORDIC-модуля в режиме прямого доступа к памяти
В таблице 11 представлены результаты сравнения производительности вычислений с программной библиотекой ARM Fast Math (в данной библиотеке вычисления выполняются на центральном ядре) и с модулем CORDIC в режимах с нулевыми издержками и прямого доступа к памяти.
Таблица 11. Производительность вычислений преобразования углов программным способом и способом с применением аппаратного ускорителя
Формат данных | q1.15 | ||
---|---|---|---|
Способ вычислений | ARM Fast Math arm_sin_q15() | CORDIC, режим с нулевыми издержками | CORDIC, режим DMA in/out |
Производительность вычислений, циклов/отсчет | 36 | 7 | 11 |
Загрузка процессорного ядра, % | 100 | 100 | 0 |
Максимальная абсолютная ошибка | 0,00012 | 0,00004 | 0,00004 |
Формат данных | q1.31 | ||
Способ вычислений | ARM Fast Math arm_sin_q31() | CORDIC, режим с нулевыми издержками | CORDIC, режим DMA in/out |
Производительность вычислений, циклов/отсчет | 41 | 8 | 12 |
Загрузка процессорного ядра, % | 100 | 100 | 0 |
Максимальная абсолютная ошибка | 0,00002 | 0,000002 | 0,000002 |
Суммарное сравнение производительности CORDIC при вычислении различных функций по сравнению с вычислениями с использованием программных библиотек представлено на рисунке 6. На нем хорошо видно, что аппаратный ускоритель существенно сокращает время вычисления трансцендентных функций, в ряде случаев – до нескольких десятков раз.

Рис. 6. Сравнение производительности вычислений CORDIC с программными библиотеками
Конечно, есть некоторые сомнения, что производительность в реальных задачах будет несколько ниже из-за необходимости обхода ограничений, связанных с диапазоном входных данных для CORDIC или дополнительных преобразований. Но тут следует иметь в виду, что входные данные для обработки в подавляющем большинстве случаев также целочисленные. Тем более, что микроконтроллеры серии STM32G4 позиционируются как контроллеры смешанных сигналов, и оцифрованные входные аналоговые сигналы также будут представлены в целочисленном формате, а желание обрабатывать их в формате с плавающей запятой так или иначе будет реализовано через преобразование форматов, что означает дополнительные накладные расходы.
Как попробовать?
Простейший способ попробовать работать с STM32G4 и испытать все их преимущества — использовать новую бесплатную среду разработки STM32CubeIDE в совокупности с набором библиотек и программной инфраструктуры STM32Cube.
Для серии STM32G4 предлагается программный пакет STM32CubeG4 MCU Package, содержащий специализированные программные библиотеки, а также примеры проектов и работы с отдельными модулями микроконтроллеров.
В частности, примеры в STM32CubeG4 MCU Package представлены для отладочной платы NUCLEO-G474RE [7, 8]. NUCLEO-G474RE – отладочная плата семейства STM32G4 NUCLEO на основе микроконтроллера смешанных сигналов STM32G474RE в корпусе LQFP64 (рисунок 7). Для работы с платами STM32G4 Nucleo-64 не требуется отдельный отладчик, поскольку на каждой плате семейства установлен программатор/отладчик STLINK-V3E.
Плата совместима с разъемами Arduino™ Uno V3 и также имеет коннекторы ST Morpho, что обеспечивает простой способ расширения функциональности и прототипирования с использованием широкого спектра плат расширения, предлагаемых для платформ Arduino и Nucleo.

Рис. 7. Отладочная плата NUCLEO-G474RE
Каковы же выводы?
Безусловно, преимущество наличия данного ускорителя в STM32G4 очевидны: существенно увеличивается скорость и точность вычисления тригонометрических, логарифмических и гиперболических функций. Модуль CORDIC просто незаменим в задачах, связанных с управлением двигателями (особенно с управлением бесколлекторными двигателями), навигационными системами, в том числе в системами локального позиционирования, с системами управления движением узлов, агрегатов или самих устройств. Полезен CORDIC и в задачах управления и контроля электроснабжения как переменного, так и постоянного тока, а также в широком спектре задач обработки сигналов и искусственного интеллекта.
Преимущество CORDIC в STM32G4 полностью раскрывается при работе с числами в формате q1.31, так как точность вычислений при этом составляет ~5 × 10-5.
Появление столь интересного модуля дает надежду, что это не разовая акция, а тенденция, возвращающая оригинальные и эффективные алгоритмы в современные вычислительные системы в новом качестве.
Видео
Литература
- DT0085 Design tip Coordinate rotation digital computer algorithm (CORDIC) to compute trigonometric and hyperbolic functions.
- STM32G4 Series advanced Arm®-based 32-bit MCUs.
- STM32G4 – новый флагман микроконтроллеров общего назначения.
- Разбор новых уникальных модулей FMAC и CORDIC в микроконтроллерах общего назначения STM32G4 (материалы вебинара).
- Getting started with the CORDIC accelerator using STM32CubeG4 MCU Package.
- STM32G CORDIC-coprocessor.
- NUCLEO-G474RE.
- STM32 Nucleo-64 development board with STM32G474RE MCU, supports Arduino and ST morpho connectivity.
Наши информационные каналы