Easyelectronics.ru

Электроника для всех
Текущее время: 20 июн 2018, 10:19

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



    • JLCPCB - Платы прототипов всего за 2$ c бесплатной доставкой (при первом заказе)
    • 10 PCBs за $2 для 2 слоев, $15 для 4 слойной, $74 для 6 слойной платы.
    • Крупнейший китайский производитель прототипных плат. 290000+ клиентов & 8000+ заказов в день!
    • LCSC - Крупнейший китайский онлайн магазин радиодеталей.

Начать новую тему Ответить на тему  [ Сообщений: 13 ] 
Автор Сообщение
 Заголовок сообщения: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 18:05 
Только пришел

Зарегистрирован: 06 апр 2016, 17:36
Сообщения: 7
Всем привет.
Может кто подсказать почему при выполнении portEND_SWITCHING_ISR(xHigherPriorityTaskWoken), после выхода из обработчика прерывания TIM10_IRQHandler, программа попадает в Task2 (бесконечный цикл), вместо того чтоб попасть в обработчик xPortPendSVHandler и переключить контекст на Task1.
Код:
xSemaphoreHandle xSem1ms;   
volatile uint32_t ctim100us;   

void Tx_Init(void);
void Task1(void *pParams);
void Task2(void *pParams);

void TIM10_IRQHandler(void)
{
   static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;   
   if(TIM_GetFlagStatus(TIM10, TIM_FLAG_Update) != RESET)
   {
      TIM_ClearFlag(TIM10, TIM_FLAG_Update);
      if(ctim100us) ctim100us--;
      else
      {
         xSemaphoreGiveFromISR(xSem1ms, &xHigherPriorityTaskWoken);
         portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
      }
   }
}

int main(void)
{   
   GPIO_InitTypeDef GPIO_InitStruct;
   NVIC_InitTypeDef NVIC_InitStruct;
   
   RCC_HSICmd(ENABLE);
   while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
   RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
   RCC_HSEConfig(RCC_HSE_OFF);
  while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET);
   
   SystemCoreClockUpdate();
   SysTick_Config(SystemCoreClock/1000);//TO=1мс   
   
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
   NVIC_InitStruct.NVIC_IRQChannel = TIM10_IRQn;
   NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
   NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 14;
   NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
      NVIC_Init(&NVIC_InitStruct);
   
   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
   GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
   GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
      GPIO_Init(GPIOB, &GPIO_InitStruct);   
   
   
   xTaskCreate(Task2, "Task2-handler", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
   
   vTaskStartScheduler();
      
}

void Task2(void *pParams)
{
   vSemaphoreCreateBinary(xSem1ms);
   xTaskCreate(Task1, "Task1-handler", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
   while(1);
}

void Task1(void *pParams)
{
   xSemaphoreTake(xSem1ms, 0);
   ctim100us = 10;
   Tx_Init();
   xSemaphoreTake(xSem1ms, 10);   
   TIM_DeInit(TIM10);
   vTaskDelete(NULL);
}

void Tx_Init(void)
{
   TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
   
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);
   
   TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
   TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseInitStruct.TIM_Period = 1600-1;//100us
   TIM_TimeBaseInitStruct.TIM_Prescaler = 0;
      TIM_TimeBaseInit(TIM10, &TIM_TimeBaseInitStruct);
      TIM_ITConfig(TIM10, TIM_IT_Update, ENABLE);
      TIM_Cmd(TIM10, ENABLE);
}



Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 18:41 
Только пришел

Зарегистрирован: 14 ноя 2016, 11:48
Сообщения: 29
Задача заключается в том чтобы сразу запустить на выполнение самую высокоприоритетную из текущих задач (Task2) после получения прерывания, не дожидаясь тика шедуллера?
Попробуй сделать yeld:

Код:
{
//portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 18:45 
Только пришел

Зарегистрирован: 06 апр 2016, 17:36
Сообщения: 7
forker писал(а):
Задача заключается в том чтобы сразу запустить на выполнение самую высокоприоритетную из текущих задач (Task2) после получения прерывания, не дожидаясь тика шедуллера?
Попробуй сделать yeld:

Код:
{
//portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

Собственно это то и не работает.
без разницы, это все просто редефайны
Код:
#define portNVIC_INT_CTRL_REG      ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT      ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 18:49 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 1822
1. Вы не должны устанавливать самостоятельно SysTick, это за вас сделает RTOS при запуске планировщика, исходя из дефайна configTICK_RATE_HZ в файле FreeRTOSConfig.h. По умолчанию, RTOS использует именно SysTick для системных квантов. Из-за раннего запуска этого таймера у вас фактически запускаются часть функций планировщика задач, хотя перед этим никаких задач, включая Idle не создано, и могут возникать проблемы.

Остальной код пока еще не смотрел...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 18:52 
Только пришел

Зарегистрирован: 14 ноя 2016, 11:48
Сообщения: 29
Да согласен. Еще попробуй убрать static в
static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 19:11 
Только пришел

Зарегистрирован: 06 апр 2016, 17:36
Сообщения: 7
BusMaster писал(а):
1. Вы не должны устанавливать самостоятельно SysTick

Не помогло.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 19:16 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 1822
О'кей смотрим дальше. Семафор перед использованием должен быть в начале созданным точка А у вас он не создан. Семафор создаются в функцией создания семафора. Из-за этого задача таск-1 у вас вероятно просто пролетает от начала до конца и поскольку в конце нет бесконечного цикла то она просто выходит. А это недопустимо. Функция удаления задачи поддерживается не всеми видами памяти например менеджер памяти heap_1.c не поддерживает удаление задач. Во-вторых задачи удаляется далеко не сразу.


Последний раз редактировалось BusMaster 01 июн 2018, 19:21, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 19:19 
Только пришел

Зарегистрирован: 06 апр 2016, 17:36
Сообщения: 7
BusMaster писал(а):
О'кей смотрим дальше. Семафор перед использованием должен быть в начале созданным точка А у вас он не создан. Семафор создаются в функцией создания семафора точка

И это есть
Цитата:
...
void Task2(void *pParams)
{
vSemaphoreCreateBinary(xSem1ms);
...

Уже второй день бьюсь с этой проблемой.
Оговорка - я только недавно начал изучать STM32 и FreeRTOS.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 19:23 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 1822
Ага, пардон, увидел


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 01 июн 2018, 19:49 
Только пришел

Зарегистрирован: 06 апр 2016, 17:36
Сообщения: 7
В конечном итоге все срабатывает задача Task1 удаляется, причем разблокировка по семафору проходит, но только когда тикает очередной SysTick, но не как не по смене контекста сразу после обработки прерывания. То есть portYIELD() устанавливает PendSV, но в сам обработчик xPortPendSVHandler программа не попадает (именно по выходу из прерывания TIM10). А идет дальше в задачу Task2 из которой это самое прерывание произошло.

P.S. Много игрался, в итоге оказалось что такая фига наблюдается только в отладчике, вывел сигнал на осциллограф в нормальном режиме, по количеству тиков таймера определил что все работает нормально.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 02 июн 2018, 09:24 
Старожил

Зарегистрирован: 16 ноя 2012, 07:47
Сообщения: 2621
Вот эта строчка:
Код:
static portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

Весьма коварна - функция xSemaphoreGiveFromISR(xSem1ms, &xHigherPriorityTaskWoken) умеет выставлять только pdTRUE(можете глянуть дебри FreeRTOS), она не пишет в переменную xHigherPriorityTaskWoken значение pdFALSE, его надо установить ранее. А так как объявили переменную static, то после первого же выставленного pdTRUE, она уже никогда не станет pdFALSE. Стоит убрать static из объявления переменной.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 02 июн 2018, 13:58 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 1822
maxntf писал(а):
такая фига наблюдается только в отладчике,о.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: не работает переключение контекста в прерывании
СообщениеДобавлено: 02 июн 2018, 17:40 
Только пришел

Зарегистрирован: 06 апр 2016, 17:36
Сообщения: 7
BusMaster писал(а):
maxntf писал(а):
такая фига наблюдается только в отладчике,о.

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

Да, причем это работает так:
Если выйти командами Step или Step Over из обработчика прерываний попадаем в Task1 (то место откуда было вызвано прерывание).
А если поставить брекпоинты в задачах, и выйти из прерывания Step Out или Run тогда попадаем куда нужно, то есть в Task2 (та что с высоким приоритетом и ожидала семафора).


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

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


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

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


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

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

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