Cortex M3 - как использовать семафоры - PullRequest
4 голосов
/ 17 января 2012

У меня есть вопрос об использовании семафоров в кортексе m3.Я нашел поток "КОРМА ARM: мьютекс с использованием битовой полосы" КОРМА ARM: мьютекс с использованием битовой полосы .Есть краткое описание проблемы, и последний ответ был бы хорош для моей проблемы - но я не уверен, как я могу реализовать это в c / c ++.

"Я никогда не использовал бит-бандингна ARM; вместо этого я склоняюсь к использованию load-exclusive / store-conditional для всех таких операций. Используйте цикл для load-exclusive старого значения, вычислите новое значение и используйте условное хранилище для его обратной записи. Loopпока условное хранилище не преуспеет (что, вероятно, будет во второй раз, если не первое). "

Я был бы очень признателен, если бы кто-то мог опубликовать краткий код, как его использовать.

Спасибо, Мартин

1 Ответ

3 голосов
/ 17 января 2012

Обратите внимание, что полоса битов доступна не во всех реализациях (в частности, она отсутствует в серии LPC1xxx от NXP).

Официальный способ реализации семафора с использованием LDREX / STREX см. В ARMРазработка примитивов синхронизации Статья .Он использует сборку ARM.

Ниже приведен простой класс, который я создал и который использует встроенные функции компилятора (не проверено!).Название, вероятно, неверно, так как на самом деле работает как мьютексВ нем также отсутствуют инструкции DMB, которые могут быть необходимы.

class Semaphore
{
  enum { SemFree, SemTaken };
  // semaphore value
  int s;  

public:
  // constructor
  Semaphore(): s(SemFree) {};

  // try to take the semaphore and return success
  // by default block until succeeded
  bool take(bool block = true)
  {
    int oldval;
#if defined(TARGET_LPC1768) // on Cortex-M3 we can use ldrex/strex
    do {
      // read the semaphore value
      oldval = __ldrex(&s);
      // loop again if it is locked and we are blocking
      // or setting it with strex failed
    }
    while ( (block && oldval == SemTaken) || __strex(SemTaken, &s) != 0 );
    if ( !block ) __clrex(); // clear exclusive lock set by ldrex
#else // on arm7 there's only swp
    do {
      // swp sets the pointed data to the given value and returns the previous one
      oldval = __swp(SemTaken, &s);
      // if blocking, loop until the previous value becomes 0
      // which would mean we have successfully taken the lock
    }
    while (block && oldval == SemTaken);
#endif
    return oldval == SemFree;
  }

  // release the semaphore
  void release()
  {
    s = SemFree;
  }
};
...