Полезные инструкции

Даже если вы не пишете на языке ассемблера, просматривайте иногда инструкции ядра: среди них можно отыскать интересные. При этом не все эти инструкции доступны напрямую синтаксисом Си, но их можно вызывать как intrinsic-функции (эти обертки содержаться в библиотеке CMSIS). Такие функции могут быть полезны при обработке данных и заменять целые участки кода. Рассмотрим реализацию алгоритма изменения порядка следования битов справа налево на языке Си.

// Bit Twiddling Hacks, https://graphics.stanford.edu/~seander/bithacks.html
uint32_t swap_word(uint32_t word) {
    // swap odd and even bits
    word = ((word >> 1) & 0x55555555) | ((word & 0x55555555) << 1);
    // swap consecutive pairs
    word = ((word >> 2) & 0x33333333) | ((word & 0x33333333) << 2);
    // swap nibbles ...
    word = ((word >> 4) & 0x0F0F0F0F) | ((word & 0x0F0F0F0F) << 4);
    // swap bytes
    word = ((word >> 8) & 0x00FF00FF) | ((word & 0x00FF00FF) << 8);
    // swap 2-byte long pairs
    word = ( word >> 16             ) | ( word               << 16);
    return word;
}

Здесь выполняется много операций — компилятор создаст целую портянку ассемблер-команд. Когда потребуется перевернуть сотни или тысячи чисел, выполнение займет изрядное количество времени. В действительности достаточно воспользоваться одной инструкцией процессора, имеющейся в ядре Cortex-M3, которая обернута в функцию __RBIT в файле core_cmInstr.h:

a = __RBIT(a);

Список подобных инструкций можно найти в документации ARM.


Изменено:

Эффективный код для Cortex-M: 3 комментария

  1. >Вопрос 48. Какой тип целочисленной переменной лучше всего СПОЛЬЗОВАТЬ в микроконтроллере PIC24 и почему?

  2. Здравствуйте.
    Мучаю STM32F030F4P6 и изучаю вашу книгу.
    Замерял сегодня скорость выполнения вышеприведённых циклов на разных оптимизациях кода O1 O2 O3.
    И у меня получилось что цикл
    for (i = 0; i < 1000000; i++) {} выполняется на любой оптимизации за 4800 микросекунд
    цикл for ( i = 1000000; i != 0; i—){} выполняется за 4800 микросек. только на оптимизации O1 . При оптимизации O2 и O3 он выполняется за 10800 микросекунд.
    цикл
    n = 1000000;
    do {
    // code here
    } while (—n != 0); на любой оптимизации выполняется за 10800 микросекунд

    может это связано с компиляцией и оптимизацией именно для данного чипа.
    но лучше я буду писать for (i = 0; i < 1000000; i++){}

  3. Взял осциллограф и всё перепроверил. Оказалось что у меня таймер переполнялся.
    Думаю что мои коменты публиковать не нужно )

Добавить комментарий

Ваш адрес email не будет опубликован.