Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 - Атомарная операция в обработчике прерывания.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Alt.F4
Здравствуйте.

Настроено две группы прерываний, в группе с наименьшим приоритетом есть прерывание, в котором надо осуществить атомарно одну операцию. Я так понимаю, надо перед ней поставить disable_irq и после нее enable_irq, но в AVR такое действие приводило к вложенным прерываниям.
Подскажите, пожалуйста, не сможет ли глобальное разрешение прерываний в обработчике привести к ситуации, что данное прерывание будет прервано другим из одной и той же группы приоритетов?
Спасибо.
SSerge
Нет, не приведёт.
У AVR просто бит I выполнял две функции - (1) запрет/разрешение прерываний и (2) приоритет исполняемого кода.
У ARM эти функции разделены, disable_irq и enable_irq управляют только битом в регистре PRIMASK (запрет/разрешение), а текущий приоритет вычисляется довольно хитрым способом, описанном в ARMv7-M Architecture Reference Manual, на основе BASEPRI, PRIMASK, FAULTMASK и приоритетов всех активных обработчиков, т.е. тех, что начали исполняться, но были прерваны более приоритетным запросом.
Смотреть "Execution priority and priority boosting" в упомянутом мануале.
kan35
Перед выполнением атомарных операций с GPIO в прерывании в STM32 выключать прерывания не нужно. Спасибо, что есть регистры BRR, BSRR. При работе через библиотеку они так же используются:
Код
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  
  GPIOx->BSRR = GPIO_Pin;
}

...
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  
  GPIOx->BRR = GPIO_Pin;
}

Если нужно работать атомарно с любым битом в любом регистре, включая RAM, то можно еще дальше пойти, используя атомарные возможности Cortex-M3-4, но если используется M0, то этой возможности уже не будет.
Alt.F4
SSerge, спасибо!
kan35, да, я в курсе атомарного bitbanding'a, но у меня в прерывании надо в один буфер срочно толкнуть байт, поэтому одним тактом там не обойдется.

Спасибо большое за разъяснение вопроса! Буду использовать в обработчике disable_irq и enable_irq.
jcxz
Цитата(SSerge @ Jan 8 2015, 15:47) *
У ARM эти функции разделены, disable_irq и enable_irq управляют только битом в регистре PRIMASK (запрет/разрешение), а текущий приоритет вычисляется довольно хитрым способом, описанном в ARMv7-M

Не путайте новичка!
То что Вы пишете относится например к Cortex-M, но никак не ко всем ARM.
И ТС кстати не указал какое у него ядро.
Alt.F4
jcxz, у меня как раз Cortex-M3, сейчас насилую отладочную плату с STM32 на борту.

А к чему приведет глобальное разрешение прерываний в обработчике в других ARM'ах?
Спасибо.
jcxz
Цитата(Alt.F4 @ Jan 9 2015, 00:31) *
А к чему приведет глобальное разрешение прерываний в обработчике в других ARM'ах?

В "других" ARMах нет глобального разрешения wink.gif
В разных ядрах ARM по-разному построена система прерываний. В ARM7/9 (и вроде Cortex-A) например, есть только два прерывания, которые разрешаются/запрещаются независимо друг от друга.
kan35
Цитата(Alt.F4 @ Jan 8 2015, 19:06) *
SSerge, спасибо!
kan35, да, я в курсе атомарного bitbanding'a, но у меня в прерывании надо в один буфер срочно толкнуть байт, поэтому одним тактом там не обойдется.

Спасибо большое за разъяснение вопроса! Буду использовать в обработчике disable_irq и enable_irq.

Но все таки... Если писать байт в RAM, то атомарность итак будет, или в Cortex-M работа идет только со словами и полусловами? Люди, кто знает его ассемблер - подскажите.
jcxz
8-, 16-, 32-бит операции записи как и операции чтения всех этих размерностей в Cortex-M атомарны.
ELEKTROS
Ну а если вложенные прерывания не использовать вовсе . Я думал вложенные прерывания на то и нужны чтобы перебивать всякое действие в аварийных ситуациях или я чего то не догоняю.
SSerge
Цитата(Alt.F4 @ Jan 8 2015, 23:06) *
...
но у меня в прерывании надо в один буфер срочно толкнуть байт, поэтому одним тактом там не обойдется.

А Вы знаете, что работу с FIFO-буфером можно реализовать вообще без блокировок?
Alt.F4
Цитата
А Вы знаете, что работу с FIFO-буфером можно реализовать вообще без блокировок?
Подскажите, пожалуйста, как это можно реализовать?
Спасибо.
SSerge
Цитата(Alt.F4 @ Jan 12 2015, 21:37) *
Подскажите, пожалуйста, как это можно реализовать?
Спасибо.

Как ни странно - легко и без затей.
Фокус в том, что если поразбираться, то окажется что каждая функция меняет только один указатель/индекс, а второй только читает. Поэтому при "внезапном" изменении значения этого второго индекса ничего страшного не происходит.
Единственное, что требуется - чтобы операции чтения и записи индексов были атомарны, по этой причине на 8-битниках индексы придётся сделать тоже uint8_t, но там и этого будет достаточно.
CODE
typedef struct
{
uint32_t PushIndx;
uint32_t PopIndx;
uint8_t Buffer[UART_FIFO_SIZE];
} UartFifo_t;

inline static bool FifoPush( UartFifo_t* Fifo, uint8_t Data)
{
// calculate next push index
uint32_t IndxTmp = Fifo->PushIndx + 1;
if( IndxTmp == UART_FIFO_SIZE )
IndxTmp = 0;

if (IndxTmp == Fifo->PopIndx) // Check FIFO state
return(false); // The FIFO is full

Fifo->Buffer[Fifo->PushIndx] = Data; // Push the data

Fifo->PushIndx = IndxTmp; // Updating the push's index
return(true);
}

static bool FifoPop( UartFifo_t *Fifo, uint8_t *pData)
{
if (Fifo->PushIndx == Fifo->PopIndx) // Check FIFO state
return(false);// The FIFO is empty

*pData = Fifo->Buffer[Fifo->PopIndx]; // Pop the data

// Calculate the next pop index
uint32_t IndxTmp = Fifo->PopIndx + 1;
if( IndxTmp == UART_FIFO_SIZE )
IndxTmp = 0;
Fifo->PopIndx = IndxTmp; // Updating of the pop's index
return(true);
}
Alt.F4
SSerge, это подходит для буферов, где запись и чтение происходит по строгой очереди, у меня в буфере хранятся указатели на функции, и освобождение ячеек в нем происходит в произвольном порядке, таким образом чтобы в него записать, надо сперва найти свободную ячейку. И момент когда мы ее нашли и хотим сделать запись должен быть атомарным.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.