Перейти к содержанию
    

иструкции cortex-m3 DMB/DSB/ISB/LDREX/CLREX/TBB

Есть статья

ARM Synchronization Primitives Development Article

http://infocenter.arm.com/help/topic/com.a..._primitives.pdf

 

У Cortex-M3 глобального монитора нет, адреса по которым делаются LDREX/STREX он не сечет. Флаг один на все, поэтому барьеры никаике ставить не надо. Но все отлично работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я вот только не пойму, как эти LDREX/STREX юзать на практике...

Допустим,тот же пример из того же DHT0008A

   LDR r1, =locked
1: LDREX r2, [r0]
   CMP r2, r1; Test if mutex is locked or unlocked
   BEQ %f2; If locked - wait for it to be released, from 2
   STREXNE r2, r1, [r0]; Not locked, attempt to lock it
   CMPNE r2, #1; Check if Store-Exclusive failed
   BEQ %b1; Failed - retry from 1
; Lock acquired
   DMB; Required before accessing protected resource
   BX lr
2; Take appropriate action while waiting for mutex to become unlocked
   WAIT_FOR_UPDATE
   B %b1; Retry from 1

Допустим,

1. тред1 выполнил LDREX r2, [r0] (r0=mutex1)

2. тред3 выполнил LDREX r2, [r0] (r0=mutex2), допустим даже отработал до конца(тк время отведенное ему довольно много, по сравнению с размером данной фунцкии), т.е взял mutex2, и что-то там еще делал

3. тред1 продолжнил выполнятся, дошел до STREXNE r2, r1, [r0] (r0=mutex1) и приплыли (из arm_architecture_v7m_reference):

The result of executing a Store-Exclusive instruction to an address that is different from that used in the preceding Load-Exclusive instruction is unpredictable.

Получается LDREX...STREX надо пихать в критическую секцию или выполнять в SVC-обработчике, так зачем они тогда нужны ? ну разве что в приложении только 1 мютекс :))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот пример программного сброса, использующий DSB:

 

void SoftRestart( void )
{
NVIC_GenerateSystemReset();
 __DSB(); 
 while(1)
 {

 }
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот мне тоже интересно, так уж ли в этом коде необходимо DSB.

Но core_cm3.h от STM32 библиотеки оно тоже есть.

static __INLINE void NVIC_SystemReset(void)
{
  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      | 
                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | 
                 SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */
  __DSB();                                                     /* Ensure completion of memory access */              
  while(1);                                                    /* wait until reset */
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

не нужен стопудово. у меня хендмейд ось и все пахает отлично. DSB/DMB может на STM32 понадобится только при работе с DMA и то в редких случаях, MPU там нету.

 

а здесь, на пример, без isb глюканет

аsm volatile(" mrs r0,CONTROL; orr r0,2; msr CONTROL,r0; ISB" : : :"r0");
blablabla();

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

a SWP хорошая была инструкция, зря похерили. теперь думай башка, как сделать lock-free Queue с кучей райтеров и одним ридером...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

a SWP хорошая была инструкция, зря похерили. теперь думай башка, как сделать lock-free Queue с кучей райтеров и одним ридером...

 

В каком это смысле? Значит ли это, что следующий код не делает того, что должен?

 

// Contributed by Bo Granlund.
static unsigned long interlockedexchange(
    volatile unsigned long * oldval,
    unsigned long newval)
{
    long result;
      asm volatile (
               "\n\t"
               "swp     %0,%2,[%1] \n\t"
               ""
               : "=&r"(result)
               : "r"(oldval), "r"(newval)
               : "memory");
  return result;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В каком это смысле? Значит ли это, что следующий код не делает того, что должен?

этот код работать на Cortex-M3 не будет, тк там нету инструкции SWP

LDREX/STREX толку очень мало, тк флаг сбрасывается при возникновении любого исключения (во избежание напорки на to,что я выше цитировал с документа). Те, если выполнилась Ldrex и возникло исключение, то STREX всегда вылетает с ошибкой и нужно делать повтор - производительность хуже, чем просто запретить прерывания на короткий участок. а с SWP такого небыло, и ее похерили. причины они изложили,почему так сделали(можно почитать в документе DHT0008A), но могли бы и оставить...

А еще лучше - сделать, чтобы флаг не сбрасывался при возникновении исключения, и чтобы STREX нормально возвращала ошибку, если адрес не совпадает с предшествующей LDREX. Тогда и красивый lock-free код получится в ядре операционки...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Встряхну тему.

 

Только что напоролся на интересную штуку. Код считает CRC:

#include    <stm32f10x.h>
config_t::crc_t config_storage::calculate_crc(config_t const & from, uint32_t const * end)
{
    config_t::crc_t Result;

    RCC->AHBENR |= (1 * RCC_AHBENR_CRCEN);      // enable CRC clock
    CRC->CR = CRC_CR_RESET;

    auto pSrc = (uint32_t const *)&from;
    do
        CRC->DR = *pSrc;
    while(++pSrc < end);

    Result = CRC->DR;

    RCC->AHBENR &= ~(1 * RCC_AHBENR_CRCEN);     // disable CRC clock

    return Result;
}

При пошаговой отладке все отлично. А при работе без точек останова при каждом проходе получается разный результат. Долго ломал голову, пока не сделал так:

    RCC->AHBENR |= (1 * RCC_AHBENR_CRCEN);      // enable CRC clock
    __DSB();
    CRC->CR = CRC_CR_RESET;

Если я правильно предполагаю, тактирование блока CRC не успевало включаться и команда сброса не отрабатывалась. Теперь работает.

Надеюсь, поможет кому-нибудь не наступить на грабли.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если я правильно предполагаю, тактирование блока CRC не успевало включаться и команда сброса не отрабатывалась. Теперь работает.

интересно, а с DMB будет работать?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Работает.

А может дело не в инструкции, а в задержке. Может и с __nop() будет работать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А может дело не в инструкции, а в задержке. Может и с __nop() будет работать?

может не хватить! потому что текст на С, там и так скорее всего есть 1 -2 инструкции между записями (константу хотя бы загрузить)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А может дело не в инструкции, а в задержке. Может и с __nop() будет работать?
Конечно дело в задержке. Но чем nop() лучше специально заточенной инструкции, которая занимает ровно столько же места и выполняется не быстрее и не дольше чем нужно?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...