реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32 - Атомарная операция в обработчике прерывания.
Alt.F4
сообщение Jan 7 2015, 22:20
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Здравствуйте.

Настроено две группы прерываний, в группе с наименьшим приоритетом есть прерывание, в котором надо осуществить атомарно одну операцию. Я так понимаю, надо перед ней поставить disable_irq и после нее enable_irq, но в AVR такое действие приводило к вложенным прерываниям.
Подскажите, пожалуйста, не сможет ли глобальное разрешение прерываний в обработчике привести к ситуации, что данное прерывание будет прервано другим из одной и той же группы приоритетов?
Спасибо.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Jan 8 2015, 09:47
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Нет, не приведёт.
У AVR просто бит I выполнял две функции - (1) запрет/разрешение прерываний и (2) приоритет исполняемого кода.
У ARM эти функции разделены, disable_irq и enable_irq управляют только битом в регистре PRIMASK (запрет/разрешение), а текущий приоритет вычисляется довольно хитрым способом, описанном в ARMv7-M Architecture Reference Manual, на основе BASEPRI, PRIMASK, FAULTMASK и приоритетов всех активных обработчиков, т.е. тех, что начали исполняться, но были прерваны более приоритетным запросом.
Смотреть "Execution priority and priority boosting" в упомянутом мануале.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
kan35
сообщение Jan 8 2015, 13:32
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Перед выполнением атомарных операций с 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, то этой возможности уже не будет.

Сообщение отредактировал kan35 - Jan 8 2015, 13:33
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jan 8 2015, 16:06
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



SSerge, спасибо!
kan35, да, я в курсе атомарного bitbanding'a, но у меня в прерывании надо в один буфер срочно толкнуть байт, поэтому одним тактом там не обойдется.

Спасибо большое за разъяснение вопроса! Буду использовать в обработчике disable_irq и enable_irq.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 8 2015, 16:51
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



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

Не путайте новичка!
То что Вы пишете относится например к Cortex-M, но никак не ко всем ARM.
И ТС кстати не указал какое у него ядро.
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jan 8 2015, 18:31
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



jcxz, у меня как раз Cortex-M3, сейчас насилую отладочную плату с STM32 на борту.

А к чему приведет глобальное разрешение прерываний в обработчике в других ARM'ах?
Спасибо.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 8 2015, 19:04
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



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

В "других" ARMах нет глобального разрешения wink.gif
В разных ядрах ARM по-разному построена система прерываний. В ARM7/9 (и вроде Cortex-A) например, есть только два прерывания, которые разрешаются/запрещаются независимо друг от друга.
Go to the top of the page
 
+Quote Post
kan35
сообщение Jan 9 2015, 19:02
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Цитата(Alt.F4 @ Jan 8 2015, 19:06) *
SSerge, спасибо!
kan35, да, я в курсе атомарного bitbanding'a, но у меня в прерывании надо в один буфер срочно толкнуть байт, поэтому одним тактом там не обойдется.

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

Но все таки... Если писать байт в RAM, то атомарность итак будет, или в Cortex-M работа идет только со словами и полусловами? Люди, кто знает его ассемблер - подскажите.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 9 2015, 19:18
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



8-, 16-, 32-бит операции записи как и операции чтения всех этих размерностей в Cortex-M атомарны.
Go to the top of the page
 
+Quote Post
ELEKTROS
сообщение Jan 9 2015, 19:21
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 294
Регистрация: 29-06-11
Пользователь №: 65 952



Ну а если вложенные прерывания не использовать вовсе . Я думал вложенные прерывания на то и нужны чтобы перебивать всякое действие в аварийных ситуациях или я чего то не догоняю.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Jan 11 2015, 18:05
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(Alt.F4 @ Jan 8 2015, 23:06) *
...
но у меня в прерывании надо в один буфер срочно толкнуть байт, поэтому одним тактом там не обойдется.

А Вы знаете, что работу с FIFO-буфером можно реализовать вообще без блокировок?


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jan 12 2015, 14:37
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Цитата
А Вы знаете, что работу с FIFO-буфером можно реализовать вообще без блокировок?
Подскажите, пожалуйста, как это можно реализовать?
Спасибо.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Jan 12 2015, 14:59
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(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);
}


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jan 13 2015, 06:28
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



SSerge, это подходит для буферов, где запись и чтение происходит по строгой очереди, у меня в буфере хранятся указатели на функции, и освобождение ячеек в нем происходит в произвольном порядке, таким образом чтобы в него записать, надо сперва найти свободную ячейку. И момент когда мы ее нашли и хотим сделать запись должен быть атомарным.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 09:22
Рейтинг@Mail.ru


Страница сгенерированна за 0.01505 секунд с 7
ELECTRONIX ©2004-2016