Какие типы / размеры переменных являются атомарными на микроконтроллерах STM32? - PullRequest
0 голосов
/ 12 октября 2018

Вот типы данных на микроконтроллерах STM32: http://www.keil.com/support/man/docs/armcc/armcc_chr1359125009502.htm.

Эти микроконтроллеры используют 32-разрядные процессоры с ядром ARM.

Какие типы данных имеют автоматическое атомарное чтение и атомарную запись?

Я почти уверен, что все 32-битные типы данных это делают (поскольку процессор 32-битный), а все 64-битные типы данных - нет (так как для чтения или записи потребуется как минимум 2 операции процессора).64-разрядное слово), но как насчет bool (1 байт) и uint16_t / int16_t (2 байта)?

Контекст: я разделяю переменные между несколькими потоками (одно ядро), но несколько потоков или «задач», как они называются, в FreeRTOS ) на STM32 и должны знать, нужно ли мне принудительно использовать атомарный доступ путем отключения прерываний, использования мьютексов и т. д.

ОБНОВЛЕНИЕ:

Ссылаясь на этот пример кода:

volatile bool shared_bool;
volatile uint8_t shared u8;
volatile uint16_t shared_u16;
volatile uint32_t shared_u32;
volatile uint64_t shared_u64;
volatile float shared_f; // 32-bits
volatile double shared_d; // 64-bits

// Task (thread) 1
while (1)
{
    // Write to the values in this thread.
    // What I write to each variable will vary. Since other threads
    // are reading these values, I need to ensure my *writes* are atomic, or else
    // I must use a mutex to prevent another thread from reading a variable in the middle
    // of this thread's writing.
    shared_bool = true;
    shared_u8 = 129;
    shared_u16 = 10108;
    shared_u32 = 130890;
    shared_f = 1083.108;
    shared_d = 382.10830;
}

// Task (thread) 2
while (1)
{
    // Read from the values in this thread.
    // What thread 1 writes into these values can change at any time, so I need to ensure
    // my *reads* are atomic, or else I'll need to use a mutex to prevent the other 
    // thread from writing to a variable in the midst of reading
    // it in this thread.
    if (shared_bool == whatever)
    {
        // do something
    }
    if (shared_u8 == whatever)
    {
        // do something
    }
    if (shared_u16 == whatever)
    {
        // do something
    }
    if (shared_u32 == whatever)
    {
        // do something
    }
    if (shared_u64 == whatever)
    {
        // do something
    }
    if (shared_f == whatever)
    {
        // do something
    }
    if (shared_d == whatever)
    {
        // do something
    }
}

В приведенном выше коде, для каких переменных я могу сделать это без использования мьютекса? MyПодозрение следующее:

  1. volatile bool: безопасно - мьютекс не требуется
  2. volatile uint8_t: безопасно - мьютекс не требуется
  3. volatile uint16_t: безопасно - мьютекс не требуется
  4. volatile uint32_t: безопасно - мьютекс не требуется
  5. volatile uint64_t: НЕБЕЗОПАСНО - ВЫ ДОЛЖНЫ ИСПОЛЬЗОВАТЬ Критический раздел или MUTEX!
  6. volatile float: безопасно - мьютекс не требуется
  7. volatile double: НЕ БЕЗОПАСНО - ВЫ ДОЛЖНЫИСПОЛЬЗУЙТЕ Критический раздел или MUTEX!

Пример критического раздела с FreeRTOS:
- https://www.freertos.org/taskENTER_CRITICAL_taskEXIT_CRITICAL.html

// Force atomic access with these critical section atomic access guards.
taskENTER_CRITICAL();
// do the (now guaranteed to be safe) read or write here
taskEXIT_CRITICAL();

Связан, но не отвечает на мой вопрос:

Ответы [ 3 ]

0 голосов
/ 12 октября 2018

Для окончательного, окончательного ответа на этот вопрос, прыгните прямо вниз к разделу, озаглавленному « Окончательный ответ на мой вопрос ».

ОБНОВЛЕНИЕ 30 октября 2018 года: Я случайно ссылался на (слегка) неправильные документы (но в которых говорилось то же самое), поэтому я исправил их в своем ответе здесь.Подробности см. В «Заметках об изменениях 30 октября 2018 года» в нижней части этого ответа.

Я определенно не понимаю всех слов здесь, но Справочное руководство по архитектуре ARM v7-M ( Интернет-источник ; Прямая загрузка файла PDF ) (НЕ Техническое справочное руководство [TRM], поскольку оно не обсуждает атомарность) подтверждает мои предположения:

enter image description here

Итак ... Я думаю, что мои 7 предположений в нижней части моего вопроса верны.[30 октября 2018 года: Да, это правильно.Подробности см. Ниже.]


ОБНОВЛЕНИЕ 29 октября 2018 года:

Еще один маленький кусочек:

Ричард Барри, основатель FreeRTOS,Эксперт и основной разработчик заявляет в tasks.c ...

/ * Критический раздел не требуется, поскольку переменные имеют тип BaseType_t.* /

... при чтении изменяемой переменной "unsigned long" (4-байтовой) на STM32. Это означает, что он, по крайней мере, на 100% уверен, что 4-байтовые операции чтения и записи являются атомарными на STM32. Он не упоминает чтения с меньшими байтами, но для 4-байтовых операций чтения он абсолютно уверен.Я должен предположить, что 4-байтовые переменные, являющиеся собственной шириной процессора, а также выровненные по словам , имеют решающее значение для того, чтобы это было правдой.

С tasks.c, строки 2173-2178в FreeRTOS v9.0.0, например:

UBaseType_t uxTaskGetNumberOfTasks( void )
{
    /* A critical section is not required because the variables are of type
    BaseType_t. */
    return uxCurrentNumberOfTasks;
}

Он использует эту точную фразу ...

/ * Критическая секция не требуется, потому что переменные имеют типBaseType_t.* /

... в двух разных местах в этом файле.

Окончательный ответ на мой вопрос:

Более того, при более внимательном рассмотрении TRM на p141как показано на скриншоте выше, я хотел бы отметить следующие ключевые предложения:

В ARMv7-M обращения к элементарному процессору в единственном экземпляре:
• все обращения к байту.
• все обращения к полусловам в расположениях, выровненных по полусловам.
• доступ ко всем словам в расположениях, выровненных по словам.

И, для этой ссылки , верно для "базовых типов данных, реализованных в ARM C и C ++" (то есть: на STM32):

  • bool / _Bool «выровнено по байту» (выровнено по 1 байту)
  • int8_t / uint8_t «выровнено по байту»"(1-байтовое выравнивание)
  • int16_t / uint16_t" выровнено по половому слову "(2-байтовое выравнивание)
  • int32_t / uint32_t "выровнено по словам" (4-байтовое выравнивание)
  • int64_t / uint64_t "выровнено по двойному слову" (8-байтовое выравнивание)) <- NOT GUARANTEED ATOMIC </li>
  • float "выровнено по словам" (выровнено по 4 байта)
  • double "выровнено по двойному слову"(С 8-байтовым выравниванием) <- НЕ ГАРАНТИРОВАННЫЙ АТОМ </li>
  • long double «выровнен по двойному слову» (с 8-байтовым выравниванием) <- НЕ ГАРАНТИРОВАННЫЙ АТОМНЫЙ </li>
  • все указатели «выровнены по словам» (выровнены по 4 байта)

Это означает, что у меня теперь есть и я понимаю доказательства, которые мне нужны , чтобы окончательно утверждать, что все выделенные жирным шрифтом строки простовыше есть автомatic атомарный доступ для чтения и записи (но НЕ увеличивает / уменьшает конечно, что является несколькими операциями). Это окончательный ответ на мой вопрос. Единственное исключение из этой атомарности может быть в упакованных структурах, я думаю, что в этом случае эти иначе естественно выровненные типы данных могут не выравниваться естественным образом.

Также обратите внимание, что при чтении Технического справочного руководства «атомарность в единственном экземпляре», очевидно, просто означает «атомарность в одноядерном процессоре» или «атомарность в архитектуре с одним ядром».Это в отличие от «атомарности нескольких копий», которая относится к «системе многопроцессорной обработки» или архитектуре многоядерных процессоров.Википедия утверждает, что «многопроцессорность - это использование двух или более центральных процессоров (ЦП) в одной компьютерной системе» (https://en.wikipedia.org/wiki/Multiprocessing).

Моя архитектура, о которой идет речь, STM32F767ZI (сЯдро ARM Cortex-M7) - это одноядерная архитектура, поэтому, как я цитировал выше из TRM, применима, по-видимому, «атомарность одного экземпляра».

Дополнительная литература:

Примечания об изменениях 30 октября 2018 года:

  • У меня была эта ссылка: ARMv7 TRM (Техническое справочное руководство), однако это неверно в двух отношениях: 1) Это вовсе не TRM!TRM - это краткое (~ 200 страниц) техническое справочное руководство.Это, однако, «Справочное руководство по архитектуре», а не TRM.Это намного более длинный и более общий документ, поскольку справочные руководства по архитектуре имеют порядок ~ 1000 ~ 2000 страниц, как выясняется.2) Это для процессоров ARMv7-A и ARMv7-R, но руководство, которое мне нужно для рассматриваемого mcu STM32, относится к процессору ARMv7-M.
  • Вот правильная ссылка на Техническое справочное руководство по процессору ARM Cortex-M7.Онлайн: https://developer.arm.com/docs/ddi0489/latest. PDF: https://static.docs.arm.com/ddi0489/d/DDI0489D_cortex_m7_trm.pdf.
  • Правильный TRM чуть выше, на p99 (5-36) говорится: «Для получения дополнительной информации об атомарности см. Справочник по архитектуре ARM®v7-M».Руководство."Итак, вот это руководство.Ссылка для скачивания онлайн: https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs/ddi0403/latest/armv7-m-architecture-reference-manual. PDF: https://static.docs.arm.com/ddi0489/d/DDI0489D_cortex_m7_trm.pdf. Здесь обсуждается атомарность на стр. 79-80 (от A3-79 до A3-80).
0 голосов
/ 19 октября 2018

Атомная "арифметика" может обрабатываться регистрами CPU Core!

Это могут быть любые типы Один или четыре байта зависит от архитектуры и набора команд

НО модификациялюбой переменной , находящейся в памяти , выполните как минимум 3 системных шага: RMW = чтение памяти для регистрации, изменение регистра и запись в память в памяти.

Поэтому атомная модификация можетвозможно, только если вы управляете использованием регистров ЦП, это означает, что нужно использовать чистый ассемблер и не использовать компилятор C или Cpp.

Когда вы используете компилятор C \ Cpp, он помещает в память глобальную или глобальную статическую переменную, так что C \ Cpp не предоставляет никаких атомарных действий и типов

Примечание: вы можете использовать, например, «регистры FPU» для атомарной модификации (если вам это действительно нужно), но вы должны скрыться откомпилятор и ОСРВ, что архитектура имеет FPU.

0 голосов
/ 12 октября 2018

В зависимости от того, что вы подразумеваете под атомным.

Если это не простая операция загрузки или сохранения, такая как

a += 1;

, тогда все типы не являются атомарными.

Если это простая операция сохранения или загрузки, 32 бита, 16биты и 8-битные типы данных являются атомарными.Если значение в регистре должно быть нормализовано, сохраните 8 и 16 бит, и загрузка может быть не атомарной.

Если ваше оборудование поддерживает битовую полосу, тогда, если битовая полоса используется, битовые операции (установка и сброс) в областях памяти, поддерживающих битовую полосу, являются атомными

Примечание.

, если ваш кодне допускает невыровненных операций 8 и 16-битные операции могут быть не атомарными.

...