Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: иструкции cortex-m3 DMB/DSB/ISB/LDREX/CLREX/TBB
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
klen
здравствуйте.
к сожалению С/C++ компиллеры не могут использовать все иструкции ядра, поскольку язык программирования (с/c++) - всетаки язык формального описания и не позволяет разработчику выразить на нем все свои желания, о которых о части позаботились разработчики ядра процессора.

в свете сказанного очевидно что без применения асма в 'узких местах" - новый процессор тановится таким же ''старым" и мы получаем дядю Васю забивающего магнитофоном гвозди.

осознание вышескзанного заставило наконецто залесть в мануал и потратить время на изучение СM3 - результат печальный.
ниже приведен список команд - названи красивые и заманчивые, но мне непонятно как они работают, тоесть для чего они нужны.
последняя вроде понятно как работет но непонятно кудаее можно прикрутить с максимальной пользой, в какихто алгоритмах же она заменит кучу кода - вопрос в каких.
первые три особо загадочные, на них у меня большие надежды.
просьба уже разобравшихся пролить свет. зарание спасибо.

Data memory barrier DMB <c>
Data synchronization barrier DSB <c>
Instruction synchronization barrier
ISB <c>
Send event SEV <c>
Load register exclusive calculates an address from a base register value and an immediate offset, loads a word from memory, writes it to a register
LDREX<c> <Rt>,[<Rn>{,#<imm>}]
STREX <c> <Rd>,<Rt>,[<Rn>{,#<imm>}]
Clear exclusive clears the local record of the executing processor that an address has had a request for an exclusive access.
CLREX <c>
Table branch byte TBB [<Rn>, <Rm>]
Table branch halfword TBH [<Rn>, <Rm>, LSL #1]



Return number of leading zeros in register value
CLZ.W <Rd>, <Rn>
AHTOXA
Цитата(klen @ May 16 2010, 15:47) *
последняя вроде понятно как работет но непонятно кудаее можно прикрутить с максимальной пользой, в какихто алгоритмах же она заменит кучу кода - вопрос в каких.

Например, в scmRTOS clz используется в ф-ии GetHighPriority() - для получения наиболее приоритетного процесса из битовой маски готовых к выполнению процессов.
Вот: OS_Target.h

tbb вроде видел в листинге, используется при больших case.
Про остальные не знаюsmile.gif
bseyur
Неплохое описание инструкций есть в юзер-мануалах на соответствующие чипы от NXP. Не смотрели их?
klen
2_AHTOXA
насчет CLZ я примерно так и предполагал

2_bseyur
URL в студию
zltigo
Цитата(bseyur @ May 16 2010, 14:02) *
Неплохое описание инструкций есть в юзер-мануалах на соответствующие чипы от NXP. Не смотрели их?

На ну? Есть оригинальная документация от ARM. Другую рожать никто не будет. Если непонятно, то надо искать просто научно-популярные
растолковывающие книжки. А из них никто еще лучше, чем Joseph Yiu не написал и не напишет.

Цитата(klen @ May 16 2010, 12:47) *
первые три особо загадочные, на них у меня большие надежды.

Чем же они загадочны?
DMB - будет требовать завершения текущих обращений к памяти до следующего обращения к памяти
DSB - тоже самое, но до следующей инструкции
ISB - пока pipeline не освободится.
Ну как надежды? Оправдались?
klen
Цитата(zltigo @ May 16 2010, 16:09) *
На ну? Есть оригинальная документация от ARM. Другую рожать никто не будет. Если непонятно, то надо искать просто научно-популярные
растолковывающие книжки. А из них никто еще лучше, чем Joseph Yiu не написал и не напишет.


Чем же они загадочны?
DMB - будет требовать завершения текущих обращений к памяти до следующего обращения к памяти
DSB - тоже самое, но до следующей инструкции
ISB - пока pipeline не освободится.
Ну как надежды? Оправдались?

biggrin.gif
а черт его знает, пока непонятно, а в каких случаях это может пригодится?
а можете привести ситуации когда без них становится нехорошо, что бы понятно стало а то както туго, инструкции есть а вставить куда не придумаю, значит непонимаю назначение.
спасибо

глянул книжку Joseph Yiu по диагонали - супер. аж перевести захотелось для таких как я, только времени на это нет. магазинам Нада не киты продавать а покупать лицензию на книгу переводить и продвать сначала ее, тогда китов наверно больше можно былобы продать. я бы так бизныс построил. я уверен что большинство программеров включая меня используют кортекс как armv4, да компиляторы тоже подкосили многих - зачем напрягатся - и так скомпилил и работает
bseyur
Цитата(zltigo @ May 16 2010, 19:09) *
На ну? Есть оригинальная документация от ARM. Другую рожать никто не будет. Если непонятно, то надо искать просто научно-популярные
растолковывающие книжки. А из них никто еще лучше, чем Joseph Yiu не написал и не напишет.

Ну как же. Глава 34. Где в оригинальной документации ARM столь доходчиво приведено описание ядра М3? rolleyes.gif
zltigo
Цитата(klen @ May 16 2010, 16:16) *
глянул книжку Joseph Yiu по диагонали - супер. аж перевести захотелось....

Надеюсь, второе издение? Оно лучше первого.
igorsk
TBB/TBH применяются нормальными компиляторами для реализации оператора switch. Большинство остальных инструкций используются для многопоточной синхронизации - семафоры, мьютексы, критические секции и т.п.
klen
Цитата(igorsk @ May 16 2010, 19:18) *
TBB/TBH применяются нормальными компиляторами для реализации оператора switch. Большинство остальных инструкций используются для многопоточной синхронизации - семафоры, мьютексы, критические секции и т.п.

вот я так и думал а что если синхронизация задач ускорить получится в FreeRTOS, только мне пока непонятно как это сделать

да, действительно gcc генерит tbb для выбора ветки в switch/case если ключи case идут подряд или с малыми дырками, иначе компилер решает что размер таблицы неприемлем и начинает генерить условный выбор ветки

НУ ВОТ!, я разобрасля с tbb теперь знаю как писать switch чтоб он быстро работал - ранее я избегал этой конструкции как класса, их у мен небыло вообще. лично для меня польза от этой ветки форума уже очевидна. спасибо.

едем дальше...
KRS
при помощи
LDREX/STREX - реализуюется синхронизация, причем можно сразу довольно высокого уровня, не только простой мьютекс, но и conditional variable, семафоры и т.п.

Всякие барьеры - вроде пока не пригодятся, на существюющих coretx-m3. Это задел под многоядерность и кеши, которых пока и нет.
zltigo
Цитата(KRS @ May 16 2010, 22:35) *
Всякие барьеры - вроде пока не пригодятся, на существюющих coretx-m3.

Ну ISB везде годится. Память тоже на внешней шине и ws-тов на ней может быть много. А кэши и ядра это уже другие кортексы.
KRS
Цитата(zltigo @ May 16 2010, 23:44) *
Ну ISB везде годится.

Вот только интересен пример использования (зачем это на существующих чипах может понадобится)
zltigo
Цитата(KRS @ May 16 2010, 22:49) *
Вот только интересен пример использования (зачем это на существующих чипах может понадобится)

Гарантированное приведение программы в однозначное состояние дабы с этого момента можно, например, было точно знать количество тактов. И не знаю, как там дела у M3 обстоят дела с отслеживанием модификации кода пред командой, но те-же AMD486 в свое время славно на этом лажались - приходилось JUMP фиктивный вставлять.
klen
Цитата(KRS @ May 16 2010, 23:35) *
при помощи
LDREX/STREX - реализуюется синхронизация, причем можно сразу довольно высокого уровня, не только простой мьютекс, но и conditional variable, семафоры и т.п.

и как это архитектурно должно выглядеть? в FreeRTOS семафоры реализованы ка и все на очередях - избыточно и не очень быстро. тут ченить усовершенствовать можно?
собственно опятже вопрос что такое эксклюзивное чтение и запись применительно к этим командам
KRS
Есть статья
ARM Synchronization Primitives Development Article
http://infocenter.arm.com/help/topic/com.a..._primitives.pdf

У Cortex-M3 глобального монитора нет, адреса по которым делаются LDREX/STREX он не сечет. Флаг один на все, поэтому барьеры никаике ставить не надо. Но все отлично работает.
brag
Я вот только не пойму, как эти 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 мютекс sm.gif)
Aleksandr Baranov
Вот пример программного сброса, использующий DSB:

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

}
}


brag
толку там от DSB, если и так в вечном цикле виснем?
akimych
Вот мне тоже интересно, так уж ли в этом коде необходимо 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 */
}
brag
не нужен стопудово. у меня хендмейд ось и все пахает отлично. DSB/DMB может на STM32 понадобится только при работе с DMA и то в редких случаях, MPU там нету.

а здесь, на пример, без isb глюканет
Код
аsm volatile(" mrs r0,CONTROL; orr r0,2; msr CONTROL,r0; ISB" : : :"r0");
blablabla();
brag
a SWP хорошая была инструкция, зря похерили. теперь думай башка, как сделать lock-free Queue с кучей райтеров и одним ридером...
Genadi Zawidowski
Цитата(brag @ May 15 2011, 01:26) *
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;
}
brag
Цитата
В каком это смысле? Значит ли это, что следующий код не делает того, что должен?

этот код работать на 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 не успевало включаться и команда сброса не отрабатывалась. Теперь работает.
Надеюсь, поможет кому-нибудь не наступить на грабли.
KRS
Цитата(Сергей Борщ @ Jan 22 2014, 22:44) *
Если я правильно предполагаю, тактирование блока CRC не успевало включаться и команда сброса не отрабатывалась. Теперь работает.

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

Сергей Борщ
Цитата(KRS @ Jan 22 2014, 20:55) *
интересно, а с DMB будет работать?
Работает.
vlad_new
Цитата(Сергей Борщ @ Jan 23 2014, 04:28) *
Работает.

А может дело не в инструкции, а в задержке. Может и с __nop() будет работать?
KRS
Цитата(vlad_new @ Jan 23 2014, 12:27) *
А может дело не в инструкции, а в задержке. Может и с __nop() будет работать?

может не хватить! потому что текст на С, там и так скорее всего есть 1 -2 инструкции между записями (константу хотя бы загрузить)
Сергей Борщ
Цитата(vlad_new @ Jan 23 2014, 10:27) *
А может дело не в инструкции, а в задержке. Может и с __nop() будет работать?
Конечно дело в задержке. Но чем nop() лучше специально заточенной инструкции, которая занимает ровно столько же места и выполняется не быстрее и не дольше чем нужно?
Golikov A.
а там статусного флага в регистре нет, который надо подождать?
просто задержка - не есть верно. Должен быть либо статус, либо в описании должно быть сколько ждать в тактах, секундах и т.д.

не строго как-то просто барьер воткнуть... ИМХО
Genadi Zawidowski
Что-то мне подсказывает, что вот это
Цитата
computation done in 4 AHB clock cycles (HCLK)

надо относить и к тому, когда CRC калькулятор будет готов принять данные не только после записи очередного байта, но и к тому, когда он будет готов после RESET.
BioWolf2000
Наткнулся на интересный баг в STM32F767. Эзернет работает, но иногда в Wireshark проскакивают пакеты TCP DUP ACK и Retransmission. Ложится передача на 0.3с, что для моего устройства с модбас критично.

Проблема устраняется редактированием файла stm32f7xx_hal_eth.c
В функции HAL_StatusTypeDef HAL_ETH_TransmitFrame(ETH_HandleTypeDef *heth, uint32_t FrameLength)
перед

Код
/* When Tx Buffer unavailable flag is set: clear it and resume transmission */
  if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET)
  {
    /* Clear TBUS ETHERNET DMA flag */
    (heth->Instance)->DMASR = ETH_DMASR_TBUS;
    /* Resume DMA transmission*/
    (heth->Instance)->DMATPDR = 0;
  }


вставляем инструкцию __DSB();
Подозрение, что не успевают обновляться данные в DMASR и получаем ложную ошибку
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.