Мьютекс, захваченный одним потоком и выпущенный другой платой CMSIS и FreeRTOS STM

У нас возникла проблема с мьютексом в CMSIS и FreeRTOS на плате STM32F407.

Есть два потока, которые могут получить доступ к аппаратному радио через UART. Мы используем мьютекс, чтобы гарантировать, что только один поток может разговаривать с радио одновременно.

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

  • Поток 1 успешно захватывает мьютекс с помощью osMutexWait (radioAccessMutex, 400)

  • Поток 2 успешно освобождает тот же мьютекс с помощью osMutexRelease (radioAccessMutex)

Насколько я понимаю, мьютекс может быть освобожден только потоком, который в настоящее время удерживает мьютекс.

Возвращаемое значение от обоих вызовов мьютекса - osOK. Рекурсивные мьютексы отключены в файле конфигурации. Оба потока имеют одинаковый приоритет.

Возможно актуальная информация: CMSIS v. 1.02 FreeRTOS v. 8.2.1

Код для вывода SWO:

void SWO_write(char* output)
{
    for(int i = 0; i < strlen(output); i++)
    {
      ITM_SendChar(output[i]);
    }
}

Этот код вызывается каждый раз, когда мьютекс захватывается или освобождается сразу после успешного вызова. Результатом вызова передается строка с завершающим нулем.


person David K.    schedule 13.02.2018    source источник
comment
Я считаю, что osMutexWait () и osMutexRelease () не являются функциями FreeRTOS. Вы используете CMSIS RTOS?   -  person kkrambo    schedule 14.02.2018
comment
Зачем Thread 2 даже пытаться освободить мьютекс, не получив его предварительно?   -  person kkrambo    schedule 14.02.2018
comment
Я использую CMSIS с FreeRTOS. Это хороший вопрос, и это часть того, что мы пытаемся отладить. Освобождение мьютекса зависит от сообщения, поступающего в очередь. Мы проверили, что сообщение попадает в очередь только один раз, но каким-то образом дважды запускает функцию выпуска.   -  person David K.    schedule 14.02.2018
comment
CMSIS имеет компонент RTOS, который включает osMutexWait () и osMutexRelease (). Я понимаю, что вы будете использовать компоненты CMSIS, отличные от RTOS, с FreeRTOS. Но я не понимаю, зачем вам использовать CMSIS RTOS с FreeRTOS. Если вы используете FreeRTOS, возможно, вам нужны xSemaphoreTake () и xSemaphoreGive ().   -  person kkrambo    schedule 14.02.2018
comment
Возможно, я неправильно понимаю вариант использования CMSIS. Я думал, что это просто оболочка вокруг выбранной вами ОСРВ, позволяющая при необходимости отключать ОСРВ. Я попробую использовать прямые вызовы FreeRTOS и сообщу, если что-нибудь изменится.   -  person David K.    schedule 14.02.2018
comment
Возможно, вы правы, что ваша реализация CMSIS RTOS является оболочкой для FreeRTOS. Я, наверное, неправильно понял. Я согласен с вашим пониманием мьютекса - только поток владельца должен иметь возможность освободить его.   -  person kkrambo    schedule 14.02.2018
comment
Вероятно, было бы лучше вообще избежать проблемы, имея третий поток, который обслуживает UART, и два существующих потока отправляют ему данные, а не имеют прямой и конкурирующий доступ к UART. Тогда мьютекс вообще не требуется, и поведение будет более детерминированным, и его будет легче отлаживать.   -  person Clifford    schedule 14.02.2018
comment
Имеет ли выпускающий поток более низкий приоритет, чем получающий поток? Может случиться так, что все работает правильно, но вытеснение предотвращает печать потока с более низким приоритетом до печати потока с более высоким приоритетом.   -  person D Krueger    schedule 14.02.2018
comment
FWIW, глядя на онлайн-документацию FreeRTOS и CMSIS, неясно, что мьютекс может быть выпущен только потоком, которому он принадлежит. Вам, вероятно, придется покопаться в исходном коде ядра и посмотреть, действительно ли он проверяет идентификатор потока владельца или нет. Я лично предполагаю, что это не так.   -  person Russ Schultz    schedule 14.02.2018
comment
@RussSchultz; Семантика мьютекса требует владения потоком, иначе это просто двоичный семафор. CMSIS-RTOS документации отсутствует на все непонятно по этому поводу.   -  person Clifford    schedule 14.02.2018
comment
Я с @DKrueger ... ваш метод отладки подозрительный. Бритва Оккама предполагает, что механизм мьютекса, на который опирались тысячи проектов в течение ряда лет, с большей вероятностью будет правильным, чем механизм отладки, который вы только что изобрели. Ваши инструменты отладки и то, что вы используете, должны быть привязаны к критическому разделу, чтобы гарантировать, что нет вытеснения, вызывающего неупорядоченный вывод.   -  person Clifford    schedule 14.02.2018
comment
Возможно, вам нужно показать код, который вы используете для демонстрации этого поведения - так мы сможем увидеть, насколько ваш метод отладки ошибочен, потому что в действительности он вряд ли будет таким, как вы описали.   -  person Clifford    schedule 14.02.2018
comment
Всем спасибо за все комментарии. Оба потока имеют одинаковый приоритет, но определенно возможно, что наш метод отладки ошибочен. Я добавил функцию, которую мы используем для вывода SWO, в исходный вопрос. Я просто пытался придумать способ определить, что происходит, без увеличения задержки. Я согласен, что маловероятно, что механизм мьютекса ошибочен, но мы уже обнаружили одну подтвержденную ошибку в нашей версии CMSIS в этом проекте, поэтому мы начали искать именно с этого места. В любом случае, мы попробуем эти предложения и обновим, если что-то сработает.   -  person David K.    schedule 14.02.2018
comment
@clifford Я согласен, что это классическая семантика. Это не означает, что ОСРВ реализует это правильно. При проверке кода RTX (старая версия и новая) выясняется, что он проверяет право собственности на мьютекс и возвращает ошибку, если не владелец. FreeRTOS, похоже, НЕ возвращает ошибку для случаев с нерекурсивными мьютексами (по крайней мере, насколько я хотел посмотреть на код). Нерекурсивные мьютексы ПОЯВЛЯЮТСЯ обработанными как семафоры, но есть много #define косвенного обращения и абстракции объектов как очередей, которые могут скрывать от меня проверку на владение.   -  person Russ Schultz    schedule 14.02.2018
comment
@RussSchultz: Независимо от семантики FreeRTOS, требуемая семантика CMSIS-RTOS ясна, и уровень абстракции должен адаптировать базовую RTOS для соответствия. FreeRTOS во многих отношениях необычен с точки зрения его реализации, но спецификация CMSIS-RTOS является фасадным слоем, предназначенным для обеспечения общей и согласованной семантики и API. Лично я бы избегал как FreeRTOS, так и CMSIS-RTOS, но это уже другая проблема.   -  person Clifford    schedule 14.02.2018
comment
@CLIFFORD Я не согласен, что семантика ясна в документации CMSIS-RTOS. Хотя в нем говорится, что мьютексы вводят право собственности, и владелец может рекурсивно получать, в нем не говорится о том, что не владелец не может освободить. Возвращаемые значения osMutexRelease() не включают «не владелец» в качестве потенциальной ошибки (реализация RTX просто возвращает osError, что на самом деле не указано в качестве возможного возвращаемого значения в документации). Мы все предполагаем, что только владельцы могут выпускать мьютексы, потому что это общепринятая семантика мьютексов, но ...   -  person Russ Schultz    schedule 14.02.2018
comment
Я добавил новый мьютекс, чтобы проверить, может ли один поток захватить его, а другой освободить. Я проверил значения в отладчике, и оказалось, что CMSIS / FreeRTOS допускает такое поведение. Вызов в потоке 1 для захвата мьютекса завершается успешно, и вызов в потоке 2 для освобождения мьютекса также завершается успешно, оба с osOK. Казалось бы, от этого не остерегаются. Эти два местоположения - единственные области, где когда-либо изменяется мьютекс.   -  person David K.    schedule 14.02.2018


Ответы (2)


Конфигурация CMSIS и FreeRTOS, которую мы используем, позволяет одному потоку освобождать мьютекс, который был захвачен другим потоком.

Я добавил новый мьютекс, чтобы проверить, может ли один поток захватить его, а другой освободить. Я проверил значения каждого вызова в отладчике, и оба возвращают osOK. CMSIS / FreeRTOS допускает такое поведение. Эти два местоположения - единственные области, где когда-либо изменяется мьютекс.

person David K.    schedule 15.02.2018

CMSIS не требует, чтобы поток, который получает мьютекс, был таким же, как тот, который его освобождает. Из документации CMSIS-RTOS osMutexRelease:

osStatus osMutexRelease (osMutexId mutex_id)

Освободите мьютекс, полученный с помощью osMutexWait. Другие потоки, которые в настоящее время ожидают того же мьютекса, теперь будут переведены в состояние ГОТОВ.

Коды состояния и ошибок

  • osOK: мьютекс был освобожден правильно.
  • osErrorResource: ранее мьютекс не получался.
  • osErrorParameter: неверный параметр mutex_id.
  • osErrorISR: osMutexRelease нельзя вызывать из подпрограмм обслуживания прерываний.

Обратите внимание, что нет кода ошибки для условия, когда разные потоки получают и освобождают мьютекс.

Наличие одного и того же потока для получения и выпуска мьютекса - это хорошая идея, но это не обеспечивается CMSIS.

person D Krueger    schedule 15.02.2018
comment
Большое спасибо за ответ. Интересно, что это не прописано в документации, но должно предполагаться из-за отсутствия конкретного кода ошибки. В любом случае я рад видеть некоторые доказательства, подтверждающие наши результаты. Спасибо еще раз! - person David K.; 16.02.2018