Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как из обработчика прерывания(вынесен в отдельный файл) вызвать xTaskResumeFromISR
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Neo_Matrix
Такая проблема:
Есть файл main.c в нем имеется задача РТОС, которая объявлена как void vDeleteSTR(void const * argument); сама функция такая
Код
void vDeleteUart(void const * argument)
{
//Здесь удаляем строку
vTaskSuspend(NULL); // Здесь засыпаем, пока прерывание не разбудит...
}

Сам обработчик прерывания вынесен в отдельный файл допустим irq.c
Код
void USART3_IRQHandler(void)
{
xTaskResumeFromISR(vDeleteUart);// Пробовал писать так
}

Но чего и следовало ожидать, vDeleteUart не объявлена в irq.c, соответственно при компиляции ошибка. Как правильно сделать?
extern void vDeleteSTR(void const * argument); - пробовал - не работает.
Спасибо всем.
x893
void vDeleteUart(void const * argument);
zltigo
QUOTE (Neo_Matrix @ Feb 25 2016, 17:58) *
Такая проблема:

Как бы помягче.... Вы хоть в документацию одним глазом загляните ЧТО нужно указывать xTaskResumeFromISR(). И это СОВЕРШЕННО не адрес функции, а Handle.
Neo_Matrix
В первом сообщении закралась ошибка, vDeleteUart необходимо заменить на vDeleteSTR. Немного промахнулся с копи-пастом.
zltigo
Хорошо, как тогда его использовать? С "мейна" все работает хорошо, как хэндл использовать в "библиотечном" файле?
Просто написать в начале irq.c
Код
BaseType_t vDeleteSTR;
или
TaskHandle_t vDeleteSTR;
Както так?
zltigo
QUOTE (Neo_Matrix @ Feb 25 2016, 22:50) *
как хэндл использовать в "библиотечном" файле?

Как и любую переменую. Что за проблема?
Neo_Matrix
Хорошо допустим есть main.c c с содержимым:
Код
#include "irq.h"
void vDeleteSTR(void const * argument);

int main(void)
osThreadDef(DeleteSTR, vDeleteSTR, osPriorityIdle, 0, 1024);
DeleteSTRHandle = osThreadCreate(osThread(DeleteSTR), NULL);
osKernelStart();
while(1){}

void vDeleteSTR(void const * argument)
{
//Здесь удаляем строку
vTaskSuspend(NULL); // Здесь засыпаем, пока прерывание не разбудит...
}


Есть файл irq.c c содержимым:

Код
void USART3_IRQHandler(void)
{
xTaskResumeFromISR(vDeleteSTR);// Пробовал писать так
}


Как правильно разбудить задачу vDeleteSTR с прерывания, обработчик которого вынесен в отдельный .с файл ?
Если можно примером кода.
x893
И описание и пример кода
http://www.freertos.org/taskresumefromisr.html
Neo_Matrix
x893
Спасибо, но если бы все было в одном main.c все сработало бы.Я не могу понять как в данном случае объявить ХЭНДЛ в стороннем файле, если extern применить не ясно как(для меня). В моем случае получается multiply defined vDeleteSTR.
x893
В другом файле написать

extern TaskHandle_t xHandle;
Код
void vAnExampleISR( void )
{
BaseType_t xYieldRequired;

     // Resume the suspended task.
     xYieldRequired = xTaskResumeFromISR( xHandle );

     if( xYieldRequired == pdTRUE )
     {
         // We should switch context so the ISR returns to a different task.
         // NOTE:  How this is done depends on the port you are using.  Check
         // the documentation and examples for your port.
         portYIELD_FROM_ISR();
     }
}
zltigo
QUOTE (Neo_Matrix @ Feb 26 2016, 00:19) *
Спасибо, но если бы все было в одном main.c все сработало бы.

Разумется нет. Совсем нет. Сам вызов принципиально неправилен и не рабоспособен. Документация!
Ruslan1
Цитата(zltigo @ Feb 26 2016, 08:51) *
Разумется нет. Совсем нет. Сам вызов принципиально неправилен и не рабоспособен. Документация!

Угу. И нехотение читать что там за "ошибка при компиляции". А многие еще и варнинги отключают и не понимают что с ними вообще делать, типа "скомпилировалось- значит в исходнике все нормально"
Neo_Matrix
Цитата
В другом файле написатьextern TaskHandle_t xHandle;

Все теперь понял. Это и был основной вопрос, спасибо!

Относительно гневных комментариев: Сам вызов буду осуществлять через cmsis_os, Весь код приведен только как пример(кстати если его записать только в мейне, то все будет работать(возможно не долго)).
Между прочим код компилится без варнингов и без ошибок, если все сгрузить в мейн.
jcxz
Цитата(Neo_Matrix @ Feb 26 2016, 14:18) *
Относительно гневных комментариев: Сам вызов буду осуществлять через cmsis_os, Весь код приведен только как пример(кстати если его записать только в мейне, то все будет работать(возможно не долго)).
Между прочим код компилится без варнингов и без ошибок, если все сгрузить в мейн.

Чтобы сообщить задаче ОС о некоем событии в ISR, используются средства синхронизации ОС. Как то: мэйлбоксы, семафоры, мьютексы и т.п. Читайте описание на свою ОС.
Например: задача ждёт в функции ожидания мэйлбокса -> ISR отправляет сообщение в сей мэйлбокс -> задача просыпается, выполняет работу, опять выходит на функцию ожидания мэйлбокса. И так в цикле.
Так стандартно строятся все задачи - обработчики неких событий от периферии (от ISR).
Neo_Matrix
Цитата(jcxz @ Feb 26 2016, 10:38) *
Чтобы сообщить задаче ОС о некоем событии в ISR, используются средства синхронизации ОС. Как то: мэйлбоксы, семафоры, мьютексы и т.п. Читайте описание на свою ОС.
Например: задача ждёт в функции ожидания мэйлбокса -> ISR отправляет сообщение в сей мэйлбокс -> задача просыпается, выполняет работу, опять выходит на функцию ожидания мэйлбокса. И так в цикле.
Так стандартно строятся все задачи - обработчики неких событий от периферии (от ISR).

Не понял к чему это сказано, вопрос был несколько иным...
Какое отличие между тем, что задача ожидает очередь или семафор от применения засыпания в конце задачи и дальнейшим пробуждением из прерывания. То что очередь может передать данные - не в счет.
jcxz
Цитата(Neo_Matrix @ Feb 26 2016, 14:55) *
Не понял к чему это сказано, вопрос был несколько иным...
Какое отличие между тем, что задача ожидает очередь или семафор от применения засыпания в конце задачи и дальнейшим пробуждением из прерывания. То что очередь может передать данные - не в счет.

Вопрос вроде был "Как правильно разбудить задачу vDeleteSTR с прерывания" если я не ошибаюсь.
Обычно простое засыпание (без привязки к средствам синхронизации ОС) задачи ОС - это засыпание на N тактов сис.таймера. Задача конечно проснётся и обнаружит событие, но не сразу после его его возникновения, как если бы ждала мэйлбокса. Данные не обязательно передавать через мэйлбокс - достаточно факта вызова функции MailboxPost() в ISR.
zltigo
QUOTE (Neo_Matrix @ Feb 26 2016, 10:18) *
Между прочим код компилится без варнингов и без ошибок, если все сгрузить в мейн.

Между прочим, он должен РАБОТАТЬ, а не только компилится с подавленным варнингами. Работать пробуждение написаное Вам НЕ будет ни при каком раскладе.


Neo_Matrix
Цитата(jcxz @ Feb 26 2016, 11:04) *
Вопрос вроде был "Как правильно разбудить задачу vDeleteSTR с прерывания" если я не ошибаюсь.
Обычно простое засыпание (без привязки к средствам синхронизации ОС) задачи ОС - это засыпание на N тактов сис.таймера. Задача конечно проснётся и обнаружит событие, но не сразу после его его возникновения, как если бы ждала мэйлбокса. Данные не обязательно передавать через мэйлбокс - достаточно факта вызова функции MailboxPost() в ISR.

Да, возможно я не очень точно описал мою проблему. Проблема была в объявлении ХЕНДЛА в отдельном файле не main.c. Собственно уже решено, всем спасибо.

Цитата(zltigo @ Feb 26 2016, 12:03) *
Между прочим, он должен РАБОТАТЬ, а не только компилится с подавленным варнингами. Работать пробуждение написаное Вам НЕ будет ни при каком раскладе.

Спорить не хочу, но это работает на Дискавери 4. Варнинги у меня не подавлены. С чего Вы вообще взяли, что подавлены варнинги?
В любом случае x893 уже дал ответ на поставленный вопрос. Да и выше было сказано о примере кода, а не о конечном варианте.
zltigo
QUOTE (Neo_Matrix @ Feb 26 2016, 12:14) *
Спорить не хочу, но это работает на Дискавери 4.

Если работает, то что то другое. Без вариантов.
QUOTE
Варнинги у меня не подавлены. С чего Вы вообще взяли, что подавлены варнинги?

C этим вообще просто - подсовывание при вызове адреса функции вместо хандлера процесса есть 100% причина ругаться.
esaulenka
Цитата(Neo_Matrix @ Feb 25 2016, 18:58) *
Но чего и следовало ожидать, vDeleteUart не объявлена в irq.c, соответственно при компиляции ошибка. Как правильно сделать?


Для решения этой задачи надо объявить хэндлер (который присваивается в CreateTask() глобальным. Заодно осознать, что хэндлер - это просто переменная (пусть и "хитрого" типа). Как использовать переменную в двух модулях одновременно, написано во всех букварях (первая же ссылка - http://www.c-cpp.ru/books/extern ).

А "как правильно" написано в статьях Курница (гуглится "Курниц FreeRTOS"). Очень рекомендую.
Ещё очень рекомендую инструкцию от scmRTOS - просто и понятно расписаны все принципы микро-операционки.

Цитата(zltigo @ Feb 26 2016, 15:40) *
C этим вообще просто - подсовывание при вызове адреса функции вместо хандлера процесса есть 100% причина ругаться.

Вот кстати необязательно. Авторы FreeRTOS очень любят указатели на void. Соответственно, можно наворотить всякой фигни, и оно успешно соберётся. Работать, конечно же, это не станет.
zltigo
QUOTE (esaulenka @ Feb 29 2016, 09:31) *
Вот кстати необязательно. Авторы FreeRTOS очень любят указатели на void. Соответственно, можно наворотить всякой фигни, и оно успешно соберётся. Работать, конечно же, это не станет.

В данном случае все совершенно однозначно - даже вместо:
* void
подсунуть что-то типа функции:
void (*)(void)
без реальных издевательств нереально.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.