Easyelectronics.ru

Электроника для всех
Текущее время: 24 янв 2021, 12:08

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 8 ] 
Автор Сообщение
 Заголовок сообщения: Растолкуйте плз, почему в данной ситуации необходим volatile
СообщениеДобавлено: 15 июл 2016, 06:21 
Старожил
Аватара пользователя

Зарегистрирован: 21 дек 2012, 13:36
Сообщения: 535
Привет, я вот делаю обработку команд, поступающих через UART. Под stm32 на С в keil c использованием FreeRTOS.
Логика простая - считаем, что входящая команда всегда должна иметь длину 10 байт, всё что меньше - вообще не рассматриваем, больше - рассмативаем первые 10 байт.
Реализовано так:
1. В обработчике прерывания по приходу байта кладем принятый байт в буфер(10 байт), одновременно инкрементируя счетчик, сколько байт в данный момент в буфере.
2. Проверяем, если принято меньше 10 - запускаем(==перезапускаем) таймер на небольшое время(5мс при скорости обмена 9600бод, неважно), и если случается такое, что он дотикал - значит передача закончилась, но пришло меньше 10 байт, и надо проигнорировать полученные данные, фактически - просто обнулить счетчик принятых байт, и ждать новых данных, для этого запускается callback функция callback_uart_receive_command_timeout(TimerHandle_t timer).
3. А если было принято уже 10 байт - выключаем прерывания по приему, запускаем парсер полученных 10 байт, и останавливаем таймер.

Код:
unsigned char uart_buf[UART_COMMAND_SIZE_BYTES];
volatile unsigned char uart_buf_current_pos = 0;

TimerHandle_t timer_uart_receive_command_timeout;
SemaphoreHandle_t semaphore_uart_command_received;

void callback_uart_receive_command_timeout(TimerHandle_t timer)
{
   uart_buf_current_pos = 0;
}

void USART2_IRQHandler(void)
{
   if(USART2->SR & USART_SR_RXNE)
   {         
      uart_buf[uart_buf_current_pos] = USART2->DR;
      uart_buf_current_pos++;
      
      if(uart_buf_current_pos == UART_COMMAND_SIZE_BYTES)
      {
         USART2->CR1 &= ~USART_CR1_RXNEIE;
         xTimerStopFromISR(timer_uart_receive_command_timeout, 0);
         xSemaphoreGive(semaphore_uart_command_received);
      }
      else
      {
         xTimerResetFromISR(timer_uart_receive_command_timeout, 0);
      }
   }
}


Как это должно работать - если шлем посылки по одному-два-три-...-девять байт, они просто игнорятся. А из посылок длиннее, либо равных 10 - берутся первые 10 байт. Прикол возник в том, что если переменную-счетчик принятых байт объявить не volatile, ее обнуление в callback фунции, видимо, не происходит, и после посылки 4 раз по 3 байта, запускается обработчик, как-будто пришла команда из 12 байт На каком-то полу-инстинктивном уровне я добавил volatile - и заработало как надо.

Читая Дихальтовский учебный курс я запомнил, что volatile "защищает переменную от посягательств оптимизатора", но вот например тут http://we.easyelectronics.ru/blog/Soft/2593.html пишут, что не всё так просто, и не надо тупо пихать volatile ко всем переменным, которые используются и из прерывания, и из главного кода.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Растолкуйте плз, почему в данной ситуации необходим volatile
СообщениеДобавлено: 15 июл 2016, 11:31 
Старожил
Аватара пользователя

Зарегистрирован: 26 янв 2010, 21:48
Сообщения: 3965
Откуда: Звенигород
В данном случае volatile говорит компилятору, что переменная может быть изменена в другом месте и ее значение нужно обязательно считывать перед использованием. Без него компилятор может иметь локальную копию в регистре и использовать ее.

_________________
От Парижа до Находки с водкой лучше, чем без водки!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Растолкуйте плз, почему в данной ситуации необходим volatile
СообщениеДобавлено: 15 июл 2016, 11:49 
Старожил

Зарегистрирован: 05 дек 2015, 16:56
Сообщения: 315
PRC писал(а):
В данном случае volatile говорит компилятору, что переменная может быть изменена в другом месте и ее значение нужно обязательно считывать перед использованием. Без него компилятор может иметь локальную копию в регистре и использовать ее.

А при чём здесь это? У него же не бесконечный цикл с проверкой флага, который взводится где-то в прерывании или в железе.
Почему в функции не работает явно указанное обнуление глобальной переменной?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Растолкуйте плз, почему в данной ситуации необходим volatile
СообщениеДобавлено: 15 июл 2016, 12:45 
Старожил

Зарегистрирован: 16 ноя 2012, 07:47
Сообщения: 2881
компилятор считает, что переменная никогда не будет изменена, т.к. нигде не вызывается функция USART2_IRQHandler. Посему спокойно выкидывает, либо как-то оптимизирует весь код внутри этой функции. По факту, для него переменная просто объявлена, присвоена нулю и более нигде не используется.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Растолкуйте плз, почему в данной ситуации необходим volatile
СообщениеДобавлено: 15 июл 2016, 15:51 
Старожил
Аватара пользователя

Зарегистрирован: 26 янв 2010, 21:48
Сообщения: 3965
Откуда: Звенигород
Gipsy писал(а):
PRC писал(а):
В данном случае volatile говорит компилятору, что переменная может быть изменена в другом месте и ее значение нужно обязательно считывать перед использованием. Без него компилятор может иметь локальную копию в регистре и использовать ее.

А при чём здесь это? У него же не бесконечный цикл с проверкой флага, который взводится где-то в прерывании или в железе.
Почему в функции не работает явно указанное обнуление глобальной переменной?

Hold уже ответил. Скорее всего дело именно в оптимизации.
Пусть ТС попробует с полностью выключенной оптимизацией посмотреть.

_________________
От Парижа до Находки с водкой лучше, чем без водки!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Растолкуйте плз, почему в данной ситуации необходим volatile
СообщениеДобавлено: 15 июл 2016, 19:40 
Старожил
Аватара пользователя

Зарегистрирован: 28 янв 2010, 20:18
Сообщения: 603
http://www.freertos.org/a00123.html

Цитата:
xSemaphoreGive( SemaphoreHandle_t xSemaphore );

...

This must not be used from an ISR. See xSemaphoreGiveFromISR() for an alternative which can be used from an ISR.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Растолкуйте плз, почему в данной ситуации необходим volatile
СообщениеДобавлено: 16 июл 2016, 00:40 
Старожил
Аватара пользователя

Зарегистрирован: 21 дек 2012, 13:36
Сообщения: 535
Цитата:
компилятор считает, что переменная никогда не будет изменена, т.к. нигде не вызывается функция USART2_IRQHandler. Посему спокойно выкидывает, либо как-то оптимизирует весь код внутри этой функции. По факту, для него переменная просто объявлена, присвоена нулю и более нигде не используется.

Спасибо, понятно)
Цитата:
This must not be used from an ISR. See xSemaphoreGiveFromISR() for an alternative which can be used from an ISR.

Блин, действительно, "зевнул фигуру" =)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Растолкуйте плз, почему в данной ситуации необходим volatile
СообщениеДобавлено: 17 июл 2016, 00:14 
Старожил
Аватара пользователя

Зарегистрирован: 28 янв 2010, 20:18
Сообщения: 603
Мне это все кажется странным, посмотреть бы выхлоп компилятора. Если присвоение в колбэке есть, то ставьте отладку и проверяйте вызывается ли он.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB