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

 
 
> Несколько вопросов начинающего
MiklPolikov
сообщение Nov 16 2013, 13:09
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Помогите пожалуйста побыстрее разобраться что к чему.

Вопрос 1:
Есть задача, управляющая миганием светодиода. Мигать он может с разными частотами и разным цветом. Что бы он мигал задача всё время "крутится",
а частота мигания регулируется при помощи vTaskDelay.
Мигание светодиода должно зависеть от результатов выполнения других задач. Как правильнее всего реализовать передачу данных из нескольких разных задач в эту одну ?
Пришло в голову : сделать очередь, в которую все задачи управляющие миганием будут записывать данные по мере их появления. В задаче мигания проверять наличие в очереди непрочитанного элемента. И только если он есть читать, иначе задача заблокируется и светодиод перестанет мигать совсем.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
7 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 99)
AlexMad
сообщение Nov 16 2013, 17:13
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 262
Регистрация: 18-02-05
Из: SPb
Пользователь №: 2 743



А нельзя просто, по результату полученного сообщения менять частоту мигания?
То есть, пришло сообщение от одной задачи, мигаем пять раз в секунду, от другой - десять.
Не говоря о том, что в теле самого сообщения Вы можете указать частоту мигания, или другой аргумент, по которому задача мигалки будет что-то решать для себя.
И отсюда можно начинать говорить об алгоритмизации взаимодействия потоков и пользователя.
Go to the top of the page
 
+Quote Post
Lagman
сообщение Nov 16 2013, 19:06
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(MiklPolikov @ Nov 16 2013, 17:09) *
В задаче мигания проверять наличие в очереди непрочитанного элемента. И только если он есть читать, иначе задача заблокируется и светодиод перестанет мигать совсем.

Можно при получении из очереди выставить xTicksToWait и ждать он будет не больше этого количества тиков.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 16 2013, 19:16
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(Lagman @ Nov 16 2013, 23:06) *
Можно при получении из очереди выставить xTicksToWait и ждать он будет не больше этого количества тиков.

Большое спасибо !



--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 16 2013, 21:35
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Вопрос 2 :

Есть USB библиотека. К ней я обращаюсь при помощи всего трёх функций USB_INIT(), USB_RECEIVE(char *p_data), USB_TRANSMIT(char *p_data);
Переписывать всю библиотеку под операционку разумеется желания нет.
Как правильнее всего применить эту библиотеку в проекте, где я решил использовать freeRTOS ? Будет ли правильно просто вставить эти функции в какие-то задачи, чтоб они там вызывались ?
Мой вопрос не "будет ли работать ?" а "как вообще это надо сделать по всем правилам ?"


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 17 2013, 23:54
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Вопрос 3:

Почему 2 задачи работают, а если запускаю 3 то не работает ничего ?
Использую heap_2

Где взять файл Errors.h , в котором должны быть коды ошибок возвращаемые xTaskCreate ?

Код
#define configUSE_PREEMPTION        1
#define configUSE_IDLE_HOOK            0
#define configUSE_TICK_HOOK            0
#define configCPU_CLOCK_HZ            ( ( unsigned long ) 16000000 )    
#define configTICK_RATE_HZ            ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES        ( ( unsigned portBASE_TYPE ) 5 )
#define configMINIMAL_STACK_SIZE    ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17*128) )  
#define configMAX_TASK_NAME_LEN        ( 16 )
#define configUSE_TRACE_FACILITY    0
#define configUSE_16_BIT_TICKS        0
#define configIDLE_SHOULD_YIELD        1


/////////


void Task1 (void *pvParameters)
{
    static char x;
   while(1)
     {
      x++;
     }
}

void Task2 (void *pvParameters)
{
    static char x;
   while(1)
     {
      x++;
     }
}

void Task3 (void *pvParameters)
{
    static char x;
   while(1)
     {
      x++;
     }
}


int main()
{
    xTaskCreate(Task1,(signed char*)"Task1", configMINIMAL_STACK_SIZE,        NULL, tskIDLE_PRIORITY + 1, NULL);
      xTaskCreate(Task2,(signed char*)"Task2", configMINIMAL_STACK_SIZE,        NULL, tskIDLE_PRIORITY + 1, NULL);
     xTaskCreate(Task3,(signed char*)"Task3", configMINIMAL_STACK_SIZE,        NULL, tskIDLE_PRIORITY + 1, NULL);
        vTaskStartScheduler();

}


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 18 2013, 02:02
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Вопрос 4:

Почему в файле FreeRtosConfig.h нету параметров configUSE_STATS_FORMATTING_FUNCTIONS и configCHECK_FOR_STACK_OVERFLOW ?
configUSE_STATS_FORMATTING_FUNCTIONS вписал туда руками что бы начать использовать отладочную функцию vTaskList


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение Nov 18 2013, 19:32
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(MiklPolikov @ Nov 17 2013, 01:35) *
Вопрос 2 :

Есть USB библиотека. К ней я обращаюсь при помощи всего трёх функций USB_INIT(), USB_RECEIVE(char *p_data), USB_TRANSMIT(char *p_data);
Переписывать всю библиотеку под операционку разумеется желания нет.
Как правильнее всего применить эту библиотеку в проекте, где я решил использовать freeRTOS ? Будет ли правильно просто вставить эти функции в какие-то задачи, чтоб они там вызывались ?
Мой вопрос не "будет ли работать ?" а "как вообще это надо сделать по всем правилам ?"

Можно прям так и использовать, только преимуществ от rtos вы не получите. Обрамляете вызовы своих функций (порт USB наверно один) в семафоры или мутексы, чтобы не было двойных вызов (хотя в вытесняющем режиме этого может и не произойти) и обращений к одному железу.

В №3 надо попробовать увеличить configTOTAL_HEAP_SIZE.
В №4 http://microsin.ru/content/view/1309/44/ по умолчанию никому не надо.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 18 2013, 20:41
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(Lagman @ Nov 18 2013, 23:32) *
Можно прям так и использовать, только преимуществ от rtos вы не получите. Обрамляете вызовы своих функций (порт USB наверно один) в семафоры или мутексы, чтобы не было двойных вызов (хотя в вытесняющем режиме этого может и не произойти) и обращений к одному железу.

Спасибо. Преимущества получу. У меня же не одна USB задача , и работа с USB занимает малую часть все логики программы.

С вопросом 3 разобрался сам. Не хватает размера кучи. #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 ) означает стек глубиной 128 4х байтных слов, т.к. процессор 32х разрядный. А #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17*128) ) означает размер кучи всего 17 * 128 = 2176 байт. Т.е. хватит на 4 задачи, 2 из которых это задача таймера(точно не знаю, по-моему она создаётся после запуска шедуллера и сразу удаляется) и задача бездействия.

Вопрос 5:
Я правильно понимаю, что при создании каждой задачи правильнее указывать какой-то определённый размер стека, который на самом деле нужен, а не одно и то же значение configMINIMAL_STACK_SIZE ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение Nov 18 2013, 21:28
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(MiklPolikov @ Nov 19 2013, 00:41) *
Спасибо. Преимущества получу. У меня же не одна USB задача , и работа с USB занимает малую часть все логики программы.

Вопрос 5:
Я правильно понимаю, что при создании каждой задачи правильнее указывать какой-то определённый размер стека, который на самом деле нужен, а не одно и то же значение configMINIMAL_STACK_SIZE ?

Высокоприоритетные задачи не дадут выполняться менее приоритетным, и когда высокоприоритетные "простаивают" (без оптимизации) ожидание в цикле то все остальные тоже ждут, а если оптимизировать и сказать например vTaskDelay то выполняться будет менее приоритетная задача.

http://microsin.net/programming/ARM/freertos-part1.html
Цитата
Каждая задача имеет собственное уникальное хранилище состояния, выделенное ядром при создании задачи. Значение параметра usStackDepth говорит ядру, какой величины стек необходимо создать.

Значение usStackDepth указывает количество слов, которое можно сохранить в стеке, а не количество байт. Например, если стек имеет ширину 32 бита, и переданное значение usStackDepth равно 100, то под стек будет выделено 400 байт (100 * 4 байт). Глубина стека, умноженная на его ширину, не должна превышать максимальное значение, которое может содержать переменная типа size_t.

Размер стека, используемого для задачи ожидания (idle task, об этой задаче подробнее говорится далее), задается константой configMINIMAL_STACK_SIZE. Значение, назначенное этой константе в демо-приложении FreeRTOS (для определенной архитектуры микроконтроллера) может быть использовано как минимально рекомендованное для любой задачи. Если Ваша программа использует пространство в стеке, то нужно указать для константы configMINIMAL_STACK_SIZE увеличенное значение.

Нет простого способа узнать, какого размера стек нужен для задачи. Этот размер можно вычислить, но в большинстве случаев можно просто назначить подходящее значение, подобранное опытным путем, либо взятое приблизительно. Подобрать правильный размер стека важно, чтобы обеспечить адекватное использование RAM без ненужных затрат. Часть 6 содержит информацию о том, как запросить размер стека, используемого задачей.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Nov 21 2013, 11:47
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



6 ) Вопрос по структуре программы :

Допустим есть задача v_Start_File_Write_Task, которая начинает запись файла на SD карту. Эта задача запускает какие-то ещё задачи, а те в свою очередь возможно запускают ещё задачи.
Как остановить запись файла и удалить все связанные с этим задачи ? Сделать задачу v_Stop_File_Write_Task в которой все связанные с файловой системой задачи будут удалятся ?
Более изящного пути нет ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Nov 21 2013, 16:49
Сообщение #12


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MiklPolikov @ Nov 21 2013, 15:47) *
...Более изящного пути нет ?


не знаю как на счёт изяществ, но... в серверном мире(как пример) просматриваются следующие модели:
1) когда логика отрабатывает по запросам пользователя. Этот вариант смахивает на Ваш. У Вас пользователь = это обращение к карточке.
2) когда есть поток(и) обрабатывающие запросы от любых пользователей к определённым ресурсам.
3) смешенная.

1 вариант не плохо применять в разрезе секьюрности(можно потоку(ам) наследовать уровень доступа самого залогиневшегося пользователя).
минусы - вы тратите доп. ресурсы на подъём и порождения необходимых дочерних потоков, если такие требуются. слабая диспетчеризация
доступа к ресурсам и т.п..

2 вариант просче масштабировать от нагрузке. можно это делать на автоматике даже. при этом можно время подготовки выделяемых
ресурсов убрать в фоновый режим.
минус - вы должны не забывать об уровне прав и отношений в системе пользователя к устройствам и операциям.

возвращаясь к вопросу.
кмк можно породить необходимое кол-во потоков для обработки ваших нужд, и передавать в поток конкретную очередь команд обращений
к данному девайсу. При этом, если задач нет - потоки ожидают на семафорах(либо других элементах синхронизации). При поступлении задачи -
необходимый(ые) потоки просыпаются, делают работу и опять уходят на ожидание.

ЗЫ
Пример:
на одной из серверных осей(НЕ форточки), разграничение доступа к БД было на уровне потоков. Доступ к БД, по условию задачи, возможен
был только со стороны сервера. Обращение к БД было инкапсулировано в один поток. Код обращения к БД резко сократился - механизмы
транзакций(сервер считался защищён с точки зрения отказов железа) и блокировки не использовались. Быстродействие повысилось. Т.к. читала
и писала одна и та-же "правая рука", то целостность базы была обеспечена априори. Т.е. на лету можно было делать бэкапы в фоновом режиме,
заливку данных, сжатие данных, печать любых отчётов за 0 минут 0 секунд.

Сообщение отредактировал kolobok0 - Nov 21 2013, 16:57
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Dec 9 2013, 03:15
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Ещё вопрос, №7

Правильно ли я понимаю, что любой переход задачи в блокированное состояние, будь то вызов vTaskDelay() , попытка взять симофор, взять элемент из пустой очереди и т.п. эквивалентен форсированному переключению контекста ?
Иными словами, Если у меня во всех задачах либо форсированное переключение контекста, либо какие угодно переводы задачи в блокированное состояние, то я могу быть уверен в том что моя программа "крутится" с максимально возможной скоростью при данной частоте процессора, и системный квант времени фактически ни на что не влияет ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Dec 9 2013, 22:23
Сообщение #14


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MiklPolikov @ Dec 9 2013, 07:15) *
...что любой переход задачи...Если у меня во всех задачах либо форсированное
переключение ..либо ..переводы задачи в блокированное состояние..уверен в том что .."крутится" с максимально возможной скоростью при данной
частоте процессора, и системный квант времени .. ни на что не влияет ?


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

я так понимаешь, что не было попытки заглянуть внутрь оси и разобраться sm.gif самое лучшее именно та ки поступить...
по поводу максимально возможного - тут всё верно, но немножко оговорочка: теоретически можно поставить колом и даннй механизм,
который будет конечно же дышать, но будет бОльшее выполнение кол-во кода при одном и том же конечном функционале. Но думаю
1) накладные расходы (по сравнению с полезным выполнением, будут минимальны)
2) вопрос спускается к устройству оси. И если Вы ей "доверяете" - то оставте это дело ей. Если нет - переписывайте, либо изучайте вопрос
уже более глубже(сравнивая оси, выбирая и корректируя на более оптимальный олгаритм шедуллер и иже).
3) ИМХО - достаточно при написании кода относится к оси почти как к НЕ вытесняющей. Т.е. помнить о шедуллере и писать код
менее "жадным" к выполнению. Т.е. там где нет необходимости постоянно поллить - перейти на прерывания (идеально чтоб всё было
на прерываниях. от аппаратуры и при передачи самих данных.)

По поводу таймера:
Рекомендую посчитать в тактах МК время кванта тиканья системного таймера. если у Вас всё по умолчанию, тиканье с частотой 1ms
и частота ядра 168Мгц, то на один квант приходится около 168000 тактов МК. Что более чем достаточно для многих задач, с
"бесконечными циклами выполняющихся за 10 секунд" sm.gif т.е. вероятность того, что Вы получите прерывание потока именно таким
способом сводится к минимуму, по большому счёту... хотя зависит от задач sm.gif

Сообщение отредактировал kolobok0 - Dec 9 2013, 22:26
Go to the top of the page
 
+Quote Post
juvf
сообщение Dec 11 2013, 04:28
Сообщение #15


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Dec 9 2013, 09:15) *
Правильно ли я понимаю, что любой переход задачи в блокированное состояние, будь то вызов vTaskDelay() , попытка взять симофор, взять элемент из пустой очереди и т.п. эквивалентен форсированному переключению контекста ?

Нет ни какого форсированного переключения контекста. Есть переключение контекста. При вызове vTaskDelay() ( или попытка взять семафор, взять элемент из пустой очереди и т.п.) планировщик проверит нет ли менее приоритетных задач, готовых к выполнению. Если есть, то будет обычное переключение контекста на др. задачу. Если нет задач, готовых к выполнению, то произойдет переключение контекста на пустую(фоновую) задачу (idle task). Пустую задачу можно определить самому.

Цитата
то я могу быть уверен в том что моя программа "крутится" с максимально возможной скоростью при данной частоте процессора, и системный квант времени фактически ни на что не влияет ?
Системный квант влияет... чем меньше квант, тем чаще вызывается планировщик.

я так понял что вы беспокоитесь о том, что переключение контекста может происходить только при взове планировщика во время системного кванта. Да... во FreeRTOS так и делается.

Допустим системный квант будет 1 раз в сек. При вызове vTaskDelay() переключение контекста произойдет сразуже, не дожидпясь ситемного тика (конца секунды). При попытке захватить семафор.... если семафор занят.... то сразу будет вызван планировщик, т.е. сразу произойдет переключение контекста. Т.е. если пренебречь временем обработки прерывания системного кванта, то системный квант времени фактически ни на что не влияет.

НО! Есть маленький нюанс: Допустим у вас 2 полезные задачи. обе заблокированны. одна ждёт семафор1, другая семафор2. Выполняется idle задача. Если семафор1 выдается в прерывании по приходу, например байта по УАРТ, то в обработчике прерывания УАРТ нужно руками прописывать переключение контекста. см. portEND_SWITCHING_ISR(). Если этого не сделать, то по приходу байта будет выдан семафор, но переключения контекста с задачи idle на задачу 1 не произойдет. Переключение контекста случится по системному тику (в конце секунды). Вот в таком случает системный квант будет влиять на скорость работы программы.

ps почитайте http://kit-e.ru/assets/listalka/Kurniz/Kurniz.pdf там все азы и буки по фриртос да и вообще по ртос, всё разжованно и по полочкам.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Dec 21 2013, 17:32
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Объясните, как подружить FREERTOS и STM32F030 ?

Взял FreeRTOSConfig.h , который компилировался с STM32L151 .
Не компилируется. ругается на ассемблерные вставки в port.c " error: A1874E: Specified register list cannot be loaded or stored in target instruction set" и другие подобные ошибки.
Взял FreeRTOSConfig.h из демо проекта STM32F05 IAR. У меня keil . Не компилируется. Да и этот файл сильно отличается от моего , наверно потому что он для Iar.

Направьте меня пожалуйста в нужную сторону.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Dec 21 2013, 22:16
Сообщение #17


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MiklPolikov @ Dec 21 2013, 21:32) *
...ругается на ассемблерные вставки в port.c...


а разве для кейла нет уже адаптированой фриртос? я барахтаюсь на иаре, но вроде как под кейло был порт? На худой случай - переписать азм файл.
Там ничего страшного нет. Оригинальный пример + немного инфы по командам вашего камня и будет вам победа...

За одно и поучитесь и ошики подправите во фриртос - они там немного существуют...
Go to the top of the page
 
+Quote Post
juvf
сообщение Dec 22 2013, 07:10
Сообщение #18


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Dec 21 2013, 22:32) *
Взял FreeRTOSConfig.h из демо проекта STM32F05 IAR. У меня keil . Не компилируется. Да и этот файл сильно отличается от моего , наверно потому что он для Iar.

Направьте меня пожалуйста в нужную сторону.

а от куда взял port.c? Для кортексаМ0 с кейлом порт нужно брать от сюда FreeRTOS\Source\portable\RVDS\ARM_CM0
а FreeRTOSConfig.h ... может этот подойдёт FreeRTOS\Demo\CORTEX_M0_Infineon_XMC1000_IAR_Keil_GCC\FreeRTOSConfig.h
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Dec 22 2013, 13:49
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



juvf , спасибо, получилось. Моя проблема была в том что в версии 7.4.0 скаченной несколько месяцев назад вообще не было папки ARM_CM0


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Dec 23 2013, 10:38
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Вопрос про удаление задач.
Как это организовать правильно, или правильно ли я вообще подхожу к созданию алгоритма ?

Есть 3 задачи v_Task1, Vtask2, Vtask3.
В любой момент времени может потребоваться создать любую задачу , или может потребоваться любую удалить.
Если задача создаётся, то нужно во-первых быть уверенным что она уже не создана(а что будет если создать заново той же самой командой ?), а во-вторых удалить две другие задачи.

Делаю так :
В начале задачи v_Task1 пишу

Код
if(v_Task2_Handle!=NULL)
      vTaskDelete(&v_Task2_Handle);
if(v_Task3_Handle!=NULL)
      vTaskDelete(&v_Task3_Handle);


аналогично в остальных задачах.

Но вот беда : если переключение контекста произойдёт после проверки условия v_Task2_Handle ! = NULL , задача v_Task2 где-то удалится, а потом программа вернётся в Task1 и снова попытается удалить уже удалённую задачу, то Task1 удалит сама себя, т.к. v_Task2_Handle уже == NUL

Задачи хочу именно удалять для экономии стека. да и запускать их надо каждый раз с начала.

Вопрос: как это сделать по-человечески ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Dec 23 2013, 11:00
Сообщение #21


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Dec 23 2013, 16:38) *
Но вот беда : если переключение контекста произойдёт после проверки условия v_Task2_Handle ! = NULL , задача v_Task2 где-то удалится, а потом программа вернётся в Task1 и снова попытается удалить уже удалённую задачу, то Task1 удалит сама себя, т.к. v_Task2_Handle уже == NUL

Дак а критические секции? Остановка планировщика?

см taskCRITICAL_ENTER(), taskCRITICAL_EXIT(), vTaskSuspendAll(), xTaskResumeAll();
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Dec 23 2013, 16:00
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



juvf, спасибо !

У меня ещё вопрос .
В документации пишут, что vTaskDelay не освобождает память. занятую задачей память нужно освободить как-то вручную, до вызова vTaskDelay.
За примером отсылают к death.c
https://code.google.com/p/freertos-atmega32...ull/death.c?r=2
Смотрю на код, и не понимаю, где там освобождается память ? По-моему просто вызывается vTaskDelay.
И вообще, как можно освободить память задачи, которая ещё не удалена ? Ведь если не удалена, значит ещё работает .



--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Dec 23 2013, 17:33
Сообщение #23


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



не путай vTaskDelay и vTaskDelete.

vTaskDelay - не удаляет задачу, а задерживает.

Про зачистку памяти.....
Цитата
Замечание: idle задача ответственна за освобождение выделенной памяти задач, которые были удалены. Поэтому важно, чтобы idle задача имела микроконтроллерное время на работу, если ваше приложение делает какие-нибудь вызовы vTaskDelete (). Память, выделенная коду задачи автоматически не освобождается, и должна быть освобождена прежде, чем задача будет удалена.


Ту память, которую занимала прибитая задача, зачистит idle. А ту память которую выделили задаче до создания задачи, нужно руками зачищать.

например death.c
Код
void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority )
{
unsigned portBASE_TYPE *puxPriority;

        /* Create the Creator tasks - passing in as a parameter the priority at which
        the suicidal tasks should be created. */
        puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );
        *puxPriority = uxPriority;

        xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );

        /* Record the number of tasks that are running now so we know if any of the
        suicidal tasks have failed to be killed. */
        uxTasksRunningAtStart = uxTaskGetNumberOfTasks();
}

Если задача vCreateTasks сама себя удалит, или её удалит кто-то другой, то память, веделенная вызовом pvPortMalloc не освободится. Нужно позаботится об её освобождении. Поэтому в задаче vCreateTasks делается ручная зачистка

Код
unsigned portBASE_TYPE uxPriority; //создается новая переменная на стеке
...

        uxPriority = *( unsigned portBASE_TYPE * ) pvParameters; //копируется данные из динамической выделенной памяти pvParameters в uxPriority
        vPortFree( pvParameters ); //удаляется динамически выделенная память.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Dec 24 2013, 02:29
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



juvf, огромное спасибо !!!

Наблюдения :
Разбирался с переполнением стека. vApplicationStackOverflowHook иногда работает, иногда нет.
А если вставить вот такую функцию-заглушку перед каждым созданием новой задачи, она даст 100% верный результат.
vTaskDelay(1); нужен для того что бы запустить Idle Task которая память освободит если этого ещё не случилось после удаления задач.
В худшем случае программа просто зацыклится внутри этой функции, и я буду точно знать в какой момент память кончилась.


Код
//функция- костыль
//////////////////////////////////////
void CHECK_FREE_MEMORY(void)
{
    xxx=xPortGetFreeHeapSize();
    while(xxx<256)
    {
        xxx=xPortGetFreeHeapSize();
        vTaskDelay(1);
    }    
}


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Dec 24 2013, 03:20
Сообщение #25


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Dec 24 2013, 07:29) *
vApplicationStackOverflowHook иногда работает, иногда нет.

У vApplicationStackOverflowHook есть два режима. см КОМПОНЕНТЫ И ТЕХНОЛОГИИ • № 11 '2011, стр 104, "Контроль переполнения стерка". Пробуй Метод контроля переполнения стека № 2.

Ну и как я понял проблема в том, что не хватает памяти в общем стеке для создания новой задачи. А vApplicationStackOverflowHook контролирует переполнение стека не общего, а стека задачи самой задачей.

Цитата
А если вставить вот такую функцию-заглушку перед каждым созданием новой задачи, она даст 100% верный результат.

ээээ..... не совсем понятно что делает заглушка? Проверяет есть ли 256 байт или 256*size_t байт доступно в общем стеке? Не нашол описание на xPortGetFreeHeapSize().
какую модель памяти используешь?
на оф сайте
Цитата
The xPortGetFreeHeapSize() API function returns the total amount of heap space that remains unallocated (allowing the configTOTAL_HEAP_SIZE setting to be optimised), but does not provided information on how the unallocated memory is fragmented into smaller blocks.
Т.е. у тебя может быть в общей куче 500 байт свободно, 50 блоков по 10 байт. ни одну новую задачу создать не возможно. Память фрагментирована. Твой костыль тут не поможет.

Поможет возвращяемое значение xTaskCreate()
Цитата
Возвращает:
pdPASS - если задача успешно создана и добавлена в список готовых, иначе возвращает код ошибки, определенный в файле errors. h
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 6 2014, 00:32
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Стало любопытно, каким образом память становится фрагментирована на куски по 10 байт ? После того как была удалена задача со стеком 60 байт, и создана новая задача со стеком 50 , стек которой заполнил освободившуюся "дырку"?
А она потом сама автоматически дефрагментируется ? Возможно для этого необходимо уходить в задачу idle , так же как и для освобождение памяти после удаления задачи ?


Цитата(juvf @ Dec 24 2013, 07:20) *
Т.е. у тебя может быть в общей куче 500 байт свободно, 50 блоков по 10 байт. ни одну новую задачу создать не возможно. Память фрагментирована. Твой костыль тут не поможет.



--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Jan 6 2014, 06:57
Сообщение #27


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Jan 6 2014, 05:32) *
Стало любопытно, каким образом память становится фрагментирована на куски по 10 байт ? После того как была удалена задача со стеком 60 байт, и создана новая задача со стеком 50 , стек которой заполнил освободившуюся "дырку"?
Да

Цитата
А она потом сама автоматически дефрагментируется ?
Нет

Дружище..... тебя уже не раз отсылали к статьям Курниц. Там же ответы на все твои вопросы. На русском разжовано и с картинками выложенно.
По поводу фрагментации памяти см КиТ №5 2011 стр 99. Там не совсем свежее описание, нет модели 4, но 1-3 модели описанны хорошо.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 6 2014, 08:12
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(juvf @ Jan 6 2014, 10:57) *
Дружище..... тебя уже не раз отсылали к статьям Курниц. Там же ответы на все твои вопросы. На русском разжовано и с картинками выложенно.
По поводу фрагментации памяти см КиТ №5 2011 стр 99. Там не совсем свежее описание, нет модели 4, но 1-3 модели описанны хорошо.

Конечно же я их прочитал. И не только их. Ну всего же не запомнишь...


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 6 2014, 14:44
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



У меня новый вопрос.
Правильно ли я отдаю симафор из прерывания и переключаю в нём контекст ?
Такая проблема : работает, но через 5 минут(точной привязки ко времени нет) начинает работать неправильно. Остальные задачи начинают тормозить, будто бы задача забирающая симафор
vRTC_Read_Time_Task начала использовать всё машинное время. Второй день не могу даже точно понять что происходит .
Заранее спасибо !!!

Код
////////////////////////////читаем время из RTC сразу после выдачи симафора из ежесекундного прерывания//////////////////////////////////////
void vRTC_Read_Time_Task (void * pvParameters)
{    
  while(1)
  {
        xSemaphoreTake( x_RTC_Second_Change, portMAX_DELAY );
    /*
        .....................
     */
  }


///////прерывание RTC  ALARM  1 раз в секунду////////////////////////////////////////////////
void RTC_Alarm_IRQHandler(void)
{
     portBASE_TYPE pxHigherPriorityTaskWoken;
    
      EXTI->PR|=(1<<17);
      RTC->ISR&=~RTC_ISR_ALRAF;    //сбрасываем флаги прерывания
    
      xSemaphoreGiveFromISR(x_RTC_Second_Change,&pxHigherPriorityTaskWoken);
      if(pxHigherPriorityTaskWoken==pdTRUE)
            taskYIELD(); //переключаем контекст
}


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Jan 6 2014, 17:55
Сообщение #30


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MiklPolikov @ Jan 6 2014, 18:44) *
...Правильно ли я отдаю симафор из прерывания и переключаю в нём контекст ?...


в коде подвоха не видно.
привидите пример создания этого семафора, ну и обратите на это внимание собственно sm.gif
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 6 2014, 21:06
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(kolobok0 @ Jan 6 2014, 21:55) *
в коде подвоха не видно.
привидите пример создания этого семафора, ну и обратите на это внимание собственно sm.gif


Код
xSemaphoreHandle x_RTC_Second_Change;    //глобальная переменная
/*
.......
*/
vSemaphoreCreateBinary( x_RTC_Second_Change );  //в самом начале программы, до инициализации прерываний и создания задач


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Jan 6 2014, 23:04
Сообщение #32


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MiklPolikov @ Jan 7 2014, 01:06) *
Код
..vSemaphoreCreateBinary( x_RTC_Second_Change );...


вот тут есть инфа о различиях и правильном применении семафоров.
семафоры
обратите внимание на другие способы создания семафоров(и способы работы с ними - рисунки 30 и 31), например xSemaphoreCreateCounting

если интенсив у Вас большой - то возможно это Ваш случай.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 7 2014, 00:38
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(kolobok0 @ Jan 7 2014, 03:04) *
вот тут есть инфа о различиях и правильном применении семафоров.
семафоры
обратите внимание на другие способы создания семафоров(и способы работы с ними - рисунки 30 и 31), например xSemaphoreCreateCounting

если интенсив у Вас большой - то возможно это Ваш случай.

Знаю про другие способы создания симафора. Но это не даёт ответа на вопрос, из-за чего именно происходит глюк. И увеличение частоты выдающего симафор прерывания в 1000 раз не учащает появление глюка.

Изучил глюк получше :
Во время глюка иногда попадаю в HardFault_Handler, иногда просто операционка начинает работать не так.
В HardFault_Handler под отладкой вижу, что одна задача как будто вызвала саму себя, хотя код в задачах самый простой и линейный, никакой рекурсии.
Глюк происходит, только если в задаче есть строчка xSemaphoreTake( x_RTC_Second_Change, portMAX_DELAY );
Т.е. будто бы проблема связана с тем что контекст захотел переключится после выдачи симафора в прерывании.
При этом переключаю я контекст taskYIELD() в конце прерывания или не переключаю ни на что не влияет.
Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Jan 7 2014, 08:19
Сообщение #34


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Jan 6 2014, 20:44) *
Код
///////прерывание RTC  ALARM  1 раз в секунду////////////////////////////////////////////////
void RTC_Alarm_IRQHandler(void)
{
     portBASE_TYPE pxHigherPriorityTaskWoken;
    
      EXTI->PR|=(1<<17);
      RTC->ISR&=~RTC_ISR_ALRAF;    //сбрасываем флаги прерывания
    
      xSemaphoreGiveFromISR(x_RTC_Second_Change,&pxHigherPriorityTaskWoken);
      if(pxHigherPriorityTaskWoken==pdTRUE)
            taskYIELD(); //переключаем контекст
}


Какой камень? А вроде не правильное переключение контекста, у меня чото не задружило переключение taskYIELD() для NIOS и для STM32. Так
Код
void USART1_IRQHandler(void)
{
    static uint8_t byte;
    [b]static [/b]portBASE_TYPE xHigherPriorityTaskWoken;
    xHigherPriorityTaskWoken = pdFALSE;
    if(USART1_SR_bit.RXNE == 1)
    { //
        byte = USART1_DR;
        xQueueSendToBackFromISR(uart485Queue, &byte, &xHigherPriorityTaskWoken);
    }
    [b]portEND_SWITCHING_ISR(xHigherPriorityTaskWoken == pdTRUE);[/b]
}

лучше xHigherPriorityTaskWoken сделать статиком
ну и определи configASSERT, может косяк выскочит из-за конфига ртос
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 7 2014, 20:05
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(juvf @ Jan 7 2014, 12:19) *
Какой камень? А вроде не правильное переключение контекста, у меня чото не задружило переключение taskYIELD() для NIOS и для STM32. Так
лучше xHigherPriorityTaskWoken сделать статиком
ну и определи configASSERT, может косяк выскочит из-за конфига ртос


STM32L151
Сделал xHigherPriorityTaskWoken статиком
Заменил taskYIELD(); на portYIELD_FROM_ISR(xHigherPriorityTaskWoken == pdTRUE); (это то же самое что у Вас portEND_SWITCHING_ISR )
Сделал через очередь xQueueSendFromISR
Ничего не изменилось.

Что такое configASSERT не понимаю. Объясните пожалуйста в двух словах. Прочитал про него на сайте Freertos, вижу как определён.
А что он делает-то и как его "определить" ?
#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

И ещё : где взять 100% правильный файл FreeRtosConfig.h для STM32L151 Keil FreeRTOS V7.6.0 ?
В разных примерах есть "вроде бы подходящие" файлы, и с ними до сих пор работало.
Ну а какой точно нужен ? Может в этом дело ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Jan 9 2014, 03:22
Сообщение #36


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Jan 8 2014, 02:05) *
Что такое configASSERT не понимаю. Объясните пожалуйста в двух словах. Прочитал про него на сайте Freertos, вижу как определён.
А что он делает-то и как его "определить" ?
#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

configASSERT - это проверка правильности настройки фрииртос. этот дефайн отнимает немного процесорного времени и нужен только для начального дебага(проверки) ртос. Когда гдето ртос начинает глючить, есть вероятность что не правильно что-то заданно.
например у меня было
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
создал задачу с приоритетом 5. вроде работало, но иногда сбоило. определил configASSERT в FreeRtosConfig.h
Код
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for(;; ); }

сразу при создании задачи застрял в одном месте ртос с коментами типа "попытка создать задачу с приоритетом >= 5". оказалось что configMAX_PRIORITIES должен быть на 1 выше самого высокого приоритета задачи.

Потом во фрииртос сложная замута с приоритетами задач и прерываний. В стм32 ещё приоритеты прерываний в обратном порядке. Чтобы ртос коректно крутилась нужно правильно назначить configKERNEL_INTERRUPT_PRIORITY и configMAX_SYSCALL_INTERRUPT_PRIORITY..... для stm32 это вообще квест.... попробую объяснить. В демках так
Код
/* This is the raw value as per the Cortex-M3 NVIC.  Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY         255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     191 /* equivalent to 0xb0, or priority 11. */


/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15.  This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting.  Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY    15

configKERNEL_INTERRUPT_PRIORITY - с этим всё понятно. ядру низший приоритет.
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */ - вот это загадка. 191 в хексе = 0xbf. для моего stm32 в назначении приоритета учавствует только старшая тетрада. поэтому bf equivalent to 0xb0. 0 отбрасываем.... приоритет 0хb, или 11.
Так вот.... если вы используете прерывания, пишете обработчики прерывания, и если в обработчике прерывания нет API, то прерывание может быть с любым приоритетом. А если из обработчика прерывания есть вызов API, то источник прерывания должен быть с приоритетом не выше configMAX_SYSCALL_INTERRUPT_PRIORITY, в моем случае не выше 11. Т.е. у вас приоритет для RTC_Alarm_IRQHandler должен быть равен или ниже configMAX_SYSCALL_INTERRUPT_PRIORITY.
0 - вроде как высший приоритет в стм32. т.е. если configMAX_SYSCALL_INTERRUPT_PRIORITY=191, то приоритет RTC_Alarm_IRQHandler должен быть от 15 до 11 включительно.

configASSERT также проверит приоритеты прерываний.

В моем компиляторе нет макросов __FILE__, __LINE__, да и выводить не куда. поэтому у меня вечный вайл for( ;; );

Цитата
И ещё : где взять 100% правильный файл FreeRtosConfig.h для STM32L151 Keil FreeRTOS V7.6.0 ?
Ну так а чего там может быть правильно и неправильно. разберись с каждой строчкой и сделай свой. Не сложно вроде.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 11 2014, 09:09
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



juvf, огромное спасибо, сделал приоритет прерывания от RTC 12 и проблема исчезла !!!

Что делает это configMAX_SYSCALL_INTERRUPT_PRIORITY так и не могу понять.
Как понимаю из документации, прерывания выше этого приоритета используются самой операционкой, поэтому они и должны быть выше всех остальных.
Но почему их так много, 11 ?
Ведь операционка использует всего 3 прерывания, вот эти
#define xPortSysTickHandler SysTick_Handler
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение Jan 11 2014, 11:55
Сообщение #38


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(MiklPolikov @ Jan 11 2014, 13:09) *
juvf, огромное спасибо, сделал приоритет прерывания от RTC 12 и проблема исчезла !!!

Что делает это configMAX_SYSCALL_INTERRUPT_PRIORITY так и не могу понять.
Как понимаю из документации, прерывания выше этого приоритета используются самой операционкой, поэтому они и должны быть выше всех остальных.
Но почему их так много, 11 ?
Ведь операционка использует всего 3 прерывания, вот эти
#define xPortSysTickHandler SysTick_Handler
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler

В СТМ какие прерывания более приоритетны? И 11 это не значит их количество, это приоритет прерывания.
http://microsin.net/programming/ARM/freertos-part3.html ищите пункт 3.5 и ниже.
так же читайте про приоритеты прерываний для вашего процессора.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 11 2014, 12:15
Сообщение #39


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(Lagman @ Jan 11 2014, 15:55) *
В СТМ какие прерывания более приоритетны? И 11 это не значит их количество, это приоритет прерывания.
http://microsin.net/programming/ARM/freertos-part3.html ищите пункт 3.5 и ниже.
так же читайте про приоритеты прерываний для вашего процессора.


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



--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение Jan 11 2014, 12:27
Сообщение #40


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(MiklPolikov @ Jan 11 2014, 16:15) *
Понимаю что 11 это не количество прерываний а приоритет. Но ведь выходит, что операционка резервирует для своих нужд все приоритеты выше 11, т.е. 11 разных приоритетов ,
и возникает вопрос почему так много, если реально используется меньше прерываний.

никто ничего не резервирует, просто приоритеты от 11 до 15 могут использовать функционал freertos, а которые выше приоритетом от 0 до 10 уже не могут и не могут быть прерваны тиком freertos.

ну и наверно в cortex m3 может быть много прерываний с одинаковым приоритетом, ведь векторов прерываний не 15.
Go to the top of the page
 
+Quote Post
juvf
сообщение Jan 11 2014, 20:48
Сообщение #41


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



На сколько я понял.... ос использует приоритеты ниже 11, т.е. 15-11. Да же не ос, а в обработчика прерываний есть апи ос.
Например сработал твой rtc, в обработчике вызвал функционал ртос. Сработал какой нить уарт с прерыванием 11.
Прервал функционал ртос и вызвал другую апи. Обе апи из обоих оработчиков могут использовать одни и реже ресурсы. Поэтому ртос должна как-то это разрулить. Потом обработчик уарта был прерван прерыванием таймера с приоритетом 7. Ртос знает, что там нет вызова апи, и что не одна переменная ртосины не изменится, поэтому ртосу не надо защищаться от совместного использования ресурсов ос.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 13 2014, 08:52
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Ещё один вопрос :
Почему в задачу vApplicationStackOverflowHook вместо указателя на название задачи стек которой переполнился передаётся 0 ?
Раньше работало, и я мог увидеть название задачи. Вопрос : что могло изменится ?
Заранее спасибо !
Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Jan 13 2014, 10:56
Сообщение #43


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Jan 13 2014, 14:52) *
Ещё один вопрос :
Почему в задачу vApplicationStackOverflowHook вместо указателя на название задачи стек которой переполнился передаётся 0 ?
Раньше работало, и я мог увидеть название задачи. Вопрос : что могло изменится ?
Заранее спасибо !

Не знаю. Смотри указатель xTaskHandle xTask в vApplicationStackOverflowHook на какую задачу указывает. Как создавал задачу? прописал ли имена задач, задал ли xTaskHandle?
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 13 2014, 11:57
Сообщение #44


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(juvf @ Jan 13 2014, 14:56) *
Не знаю. Смотри указатель xTaskHandle xTask в vApplicationStackOverflowHook на какую задачу указывает. Как создавал задачу? прописал ли имена задач, задал ли xTaskHandle?

Разобрался. Это Keil не хочет показывать значение локальной переменной, если она определена но не используется. Раньше этой проблемы с pcTaskName почему-то не было.
Сделал глобальную переменную, которой присваиваю pcTaskName.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 4 2014, 20:46
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Вопрос по организации алгоритма :

Допустим начала работать задача А(была создана, была разблокирована), и пока она работает должны заблокироваться задачи Б, С, Д. Когда задача А завершила работу, Б С Д должны разблокироваться. Как это принято делать так, что бы было наименее путано ? Сделать очередь из одного элемента, из которой задачи Б С Д читают этот элемент без удаления, а задача А его либо удаляет либо возвращает ?
Нет ли способа проверять внутри задачи Д чему равен хэндлер задачи А, так что бы когда он не NULL задача Д блокировалась бы, а когда снова стал NULL разблокировалась бы?


Спасибо.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Feb 5 2014, 02:25
Сообщение #46


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



для этого существуют эвэнты. в v8.0 наконецто их добавили. задачи Б, С, Д блокируй в ожидании установки флага (эвента). Задачи Б, С, Д могут ждать одного флага, а можно для каждой задачи сделать отдельный флаг в группе флагов.

А с проверкой хэндлера..... дак это прийдется в задачах Б, С, Д с какимто периодом проверять хендлер. С таким же успехом можно завести глобальную переменную и проверять её в Б, С, Д и не заморачиваться с хендлером.
Go to the top of the page
 
+Quote Post
Timma
сообщение Feb 5 2014, 13:16
Сообщение #47


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 26-11-07
Пользователь №: 32 693



Цитата(MiklPolikov @ Feb 5 2014, 00:46) *
Вопрос по организации алгоритма :

Допустим начала работать задача А(была создана, была разблокирована), и пока она работает должны заблокироваться задачи Б, С, Д. Когда задача А завершила работу, Б С Д должны разблокироваться. Как это принято делать так, что бы было наименее путано ? Сделать очередь из одного элемента, из которой задачи Б С Д читают этот элемент без удаления, а задача А его либо удаляет либо возвращает ?
Нет ли способа проверять внутри задачи Д чему равен хэндлер задачи А, так что бы когда он не NULL задача Д блокировалась бы, а когда снова стал NULL разблокировалась бы?


Спасибо.

Может просто сделать приоритет А выше других?
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 12 2014, 19:37
Сообщение #48


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Ещё вопрос:

Как я понял , для того что бы использовать флаги событий нужно добавить в FreeRTOSConfig.h следующие строки, без них не компилируется.
Из каких соображений нужно выбирать то, что я отметил //// ?

Рассуждаю так :
configTIMER_TASK_PRIORITY 0 самый верхний приоритет для того что бы всё что с этим будет связано обрабатывалось быстрее моих задач, так будет работать гарантированно однозначно.
configTIMER_QUEUE_LENGTH 1 маленькая длинна очереди т.к. приоритет всё равно самый верхний, очередь не должна переполнится

Заранее спасибо за ответ !

Цитата
#define INCLUDE_xEventGroupSetBitFromISR 1
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 0 ////
#define configTIMER_QUEUE_LENGTH 1 ////
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE ////
#define INCLUDE_xTimerPendFunctionCallFromISR 1


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Feb 14 2014, 02:42
Сообщение #49


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Я работал с флагами (эвентами) в др ртос. В ФрииРТОС пока не доводилось, не разбирался. С чем их есть во фри - не знаю. laughing.gif
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 14 2014, 07:21
Сообщение #50


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Настроил как написал выше, и вроде бы всё хорошо.

Ещё один вопрос, мучает уже давно :
Почему в примерах в объявлениях семафоров , мьютиксов и т.п. нет директивы volatile, и почему без неё работает когда семафор выдаётся в прерывании ?
Заранее спасибо за объяснение !

Код
/*volatile*/  xSemaphoreHandle    x_RTC_Second_Change;  //разве тут не нужен volatile ?

//.....

xSemaphoreGiveFromISR(x_RTC_Second_Change,&xHigherPriorityTaskWoken);


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Feb 15 2014, 10:02
Сообщение #51


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



И ещё вопрос по флагам событий :
Я верно понимаю, что xEventGroupWaitBits работает только по факту наличия флага, сделать так чтоб работало по моменту выставления способа не предусмотрено ? Иными словами : пользователь жмёт кнопку, при этом выставляются и снимаются флаги "кнопка была нажата" "кнопка была отпущена". В задаче нужно чтоб программа проходила строку xEventGroupWaitBits после нажатия, а при следующем попадании на неё же ждала следующего отпускания + нажатия. Сбрасывать флаги нельзя, т.к. они используются в других функциях.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Feb 15 2014, 14:19
Сообщение #52


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(MiklPolikov @ Feb 14 2014, 11:21) *
Код
/*volatile*/  xSemaphoreHandle    x_RTC_Second_Change;  //разве тут не нужен volatile ?
//.....
xSemaphoreGiveFromISR(x_RTC_Second_Change,&xHigherPriorityTaskWoken);

Не нужен volatile, потому что xSemaphoreHandle - это указатель и он в прерывании не изменяется.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Apr 24 2014, 14:41
Сообщение #53


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Ещё один вопрос, по архитектуре кода :

Перевожу свои старые коды без ОС на FreeRTOS. К примеру есть функция, инициализирующая SD карту, в ней в каких-то циклах ожидание чего-то.
Как теперь с этим поступить наиболее правильно ?
а) Вставить в функцию команды переключения контекста. Функция будет вызываться в задаче, но выполняться будет не быстро, т.к. функция чего-то ждёт внутри себя.
С одной стороны контекст будет переключатся, т.е. система в целом работать правильно, но с другой та задача, которая функцию вызвала, будет останавливаться на этой функции на большое время, что на мой взгляд криво.
б) Сделать из функции отдельную задачу. Создавать её когда надо проинициализировать карту, когда инициализация прошла удалять, а о том что инициализация прошла узнавать через эвенты или симафоры.

Заранее спасибо.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
DASM
сообщение Apr 24 2014, 16:08
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Б
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 24 2014, 18:54
Сообщение #55


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MiklPolikov @ Apr 24 2014, 18:41) *
...есть функция, инициализирующая SD карту...


в) всю работу с карточкой убрать в нитку. обслуживать запросы можно и синхронно и асинхронно - в зависимости от дальнейшей надобности.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Apr 24 2014, 19:25
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(kolobok0 @ Apr 24 2014, 22:54) *
в) всю работу с карточкой убрать в нитку. обслуживать запросы можно и синхронно и асинхронно - в зависимости от дальнейшей надобности.


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


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 25 2014, 18:08
Сообщение #57


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MiklPolikov @ Apr 24 2014, 23:25) *
Объясните пожалуйста на пальцах, что значит "убрать в нитку" и "обслуживать запросы синхронно и асинхронно" ?
..один линейный код в одной задаче ?...


если юзаете ось, то во фриртосе есть понятие поток. вам ничего не мешает отдельно поток завести на ваши медленно играющие проблемы.
асинхронно (по отношению к этому потоку) вы сможете вызывать необходимые вам функции (рядом с потоком лежащие и реализующие
синхонизацию).
Вам никто не мешает порождать, посылать запрос, ждать, по возврату управления удалять объект синхронизации. это есть
синхронное обращение. как пример см. стэки изернет, синхроные натификэшены во всяких форточках и иже...

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

про линейный код нифига не понял.
как пример разжовывания на пальцах(да и пользительно под форточками) - почитайте толковую книгу
"WINDOWS для профессионалов" автор Джеффри Рихтер

там есть и асинхронный пласт и синхронный...возможно не по теме но как консерватория - вполне...
Go to the top of the page
 
+Quote Post
juvf
сообщение Apr 26 2014, 04:18
Сообщение #58


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(kolobok0 @ Apr 25 2014, 00:54) *
в) всю работу с карточкой убрать в нитку. обслуживать запросы можно и синхронно и асинхронно - в зависимости от дальнейшей надобности.

на сколько я понял вопрос в другом. Какая разница что в какой нитке? Допустим есть отдельняя нитка в которой ведется работа с SD Картой. есть функция, инициализирующая SD карту, в ней в каких-то циклах ожидание чего-то.
Как теперь с этим поступить наиболее правильно?
Когда идет инициализация, то процессор простаивает. как правильно организовать работу, чтобы во время ожиданий процессор не простаивал?

если сделать так
while(waitForSdCard);

то процессор будет стоять в этом месте (ну если конечно более приоритетные задачи не прервыт эту задачу).

самое простое сделать ожидание через vTaskDelay();

Код
for(int i = 0; i<100; i++)
{
   if(waitForSdCard)
   {
   //дождались... дальше пишем код
   }
   vTaskDelay(10);
}
//сюда попадем, если недождались. исключение


Если то событие, которое ожидаем, может сегенрировать прерыванеи, то можно сделать двоичный симафор (или эвэнт). из прерывания выдавать симафор. тогда

Цитата
if(xSemaphoreTake(smSdCardReady, 1000) == pdPASS)//ждём симафор
{ //дождались... дальше пишем код

}
else
{
//сюда попадем, если недождались. исключение
}


Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Apr 29 2014, 10:22
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Ещё один вопрос:

Требуется экономить потребляемый ток.
Раньше, без ОС, в тех местах кода, где надо чего-то ждать,я использовал какой-то из спящих режимов, а дождавшись вновь увеличивал частоту.
Сейчас всё ожидание, очевидно, будет в задаче Idle. В ней я могу снизить тактовую частоту. А вот как её обратно повысить ? Я ведь не знаю ни когда это потребуется, ни где программа окажется когда выйдет из IDLE . Как быть ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 29 2014, 20:36
Сообщение #60


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(juvf @ Apr 26 2014, 08:18) *
...Когда идет инициализация, то процессор простаивает. как правильно организовать работу...


Вы вот прочитали но не поняли скорее всего, что я написал выше.
Окейно. по другому..
откуда это у Вас?

"Когда идет инициализация, то процессор простаивает"

я бы сказал заблуждение... Или логику так построили? Ну а кто мешает по другому, религия если только???

вот у меня паралельно идёт инициализация(читай подъём или инициализация) железа...uSD, Ehernet, ADC, стэки, оси, MODBAUS,
запуск ниток, изернет клиенты-сервера, wifi (и прочий звериниц), всё это делается параллельно
(ну есть конечно же последовательные действия), но они не создают узких мест для общей картины а больше, как это лучше
сказать - по общей готовности все подождут самого отстающего...
ну и принимается решения для подключения или отключения функционала блоков или логики...
Go to the top of the page
 
+Quote Post
Lagman
сообщение Apr 30 2014, 11:27
Сообщение #61


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



http://www.freertos.org/low-power-tickless-rtos.html
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Apr 30 2014, 12:56
Сообщение #62


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(Lagman @ Apr 30 2014, 15:27) *

Это то что нужно ! Огромное спасибо !!!

Кое-что непонятно, поясните пожалуйста :
Тут
http://www.freertos.org/low-power-tickless-rtos.html
сказано, что функция portSUPPRESS_TICKS_AND_SLEEP( xIdleTime ) не определена, пользователю предлагается написать её самому , приведён пример возможного кода.
А я вижу в FreeRTOS V8.0.0 что эта функция уже есть написанная, и в ней вызываются функции
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
которые я должен написать сам.
Вопрос : почему в описании по ссылке сказано, что portSUPPRESS_TICKS_AND_SLEEP нужно писать самому ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение Apr 30 2014, 18:08
Сообщение #63


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Я сильно не вникал т.к. не использую режимы энергосбережения, но из написанного на оф.сайте я понял, что если для процессора есть пример с энергосбережением то можно его использовать или написать свою ф-ю.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение May 4 2014, 18:54
Сообщение #64


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Может кто подскажет :
Есть задача, которая создаёт несколько других задач, и после этого становится не нужна.
Если в конце задачи в бесконечном цикле vTaskDelay то всё хорошо. А если задача сама себя удаляет vTaskDelete(NULL); , то программа оказывается в Hardfault_Handler. Почему так происходит ? Задачи создаю с проверкой Task_Handle==NULL и запрещением переключения контекста на время проверки и создания.
Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение May 6 2014, 16:53
Сообщение #65


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Разобрался, дело было в недостаточном стеке задачи. В vApplicationStackOverflowHook программа не попадала, сразу HardFault.

Ещё один вопрос :
Как сохранить неизменной частоту системных тиков при изменении тактовой частоты процессора ? Никаких готовых инструментов не нашёл. Нужно перенастраивать таймер вручную ? А после этого операционка его обратно не перенастроит сама зачем-нибудь ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение May 7 2014, 07:43
Сообщение #66


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



2MiklPolikov
по существу не скажу. такого опыта не имею.
ps: я смотрю на вопросы... и любопытстов всё больше и больше.... динамическое создание задач, самоудаление задач, налету изменение системного тика....
Что за проект? Что вы делаете?
Go to the top of the page
 
+Quote Post
kostyan
сообщение May 7 2014, 12:04
Сообщение #67


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 8-11-05
Пользователь №: 10 577



2MiklPolikov, фриртос - это операционка с открытым кодом.

Открыл свой проект, нашел в FreeRTOSConfig.h:
#define configCPU_CLOCK_HZ ( SystemCoreClock )

Сделал поиск по configCPU_CLOCK_HZ в проекте.

Нашел что юзается дефайн в "__weak void vPortSetupTimerInterrupt( void )". Сделал иерархию вызова функции: portBASE_TYPE xPortStartScheduler( void ) <- void vTaskStartScheduler( void )

Следовательно, дефолтные настройки системного таймера применяются ровно один раз в проекте. Если вы хотите менять частоту процессора - то в том же коде перенастаивайте таймер системного тика, и будет вам счастье. Пост писал, гораздо дольше чем залез в код и нашел ответы на ваши вопросы.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение May 7 2014, 12:13
Сообщение #68


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(juvf @ May 7 2014, 11:43) *
2MiklPolikov
по существу не скажу. такого опыта не имею.
ps: я смотрю на вопросы... и любопытстов всё больше и больше.... динамическое создание задач, самоудаление задач, налету изменение системного тика....
Что за проект? Что вы делаете?


Например разрабатываю диктофоны, которые производят Телесистемы в Зеленограде.
И другие проекты подобного характера. Иными словами, я делаю "гаджеты".

Цитата(kostyan @ May 7 2014, 16:04) *
2MiklPolikov, фриртос - это операционка с открытым кодом.

Открыл свой проект, нашел в FreeRTOSConfig.h:
#define configCPU_CLOCK_HZ ( SystemCoreClock )

Сделал поиск по configCPU_CLOCK_HZ в проекте.

Нашел что юзается дефайн в "__weak void vPortSetupTimerInterrupt( void )". Сделал иерархию вызова функции: portBASE_TYPE xPortStartScheduler( void ) <- void vTaskStartScheduler( void )

Следовательно, дефолтные настройки системного таймера применяются ровно один раз в проекте. Если вы хотите менять частоту процессора - то в том же коде перенастаивайте таймер системного тика, и будет вам счастье. Пост писал, гораздо дольше чем залез в код и нашел ответы на ваши вопросы.


Да, я то же это находил.
Но подумал, вдруг есть неочевидные для меня тонкости.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение May 27 2014, 09:01
Сообщение #69


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Коллеги, ещё один вопрос :

Верно ли я понимаю, что значение, которое возвращает xTaskGetTickCount(); периодически сбрасывается в 0 и начинает расти заново, т.к. переполняется 32х разрядная переменная, которая считает тики , и стало быть, при использовании xTaskGetTickCount(); я должен обрабатывать этот сброс в 0 ?
А все функции операционки которые работают со временем (задержка, взять симофор и т.п. ) , то же обрабатывают сброс счётчика тиков в 0 ?

МП


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение May 28 2014, 00:41
Сообщение #70


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ May 27 2014, 19:11) *
переполняется 32х разрядная переменная

32-х битная или 16
Код
#if( configUSE_16_BIT_TICKS == 1 )
    typedef uint16_t TickType_t;
    #define portMAX_DELAY 0xffff
#else
    typedef uint32_t TickType_t;
    #define portMAX_DELAY 0xffffffffUL
#endif


Цитата
стало быть, при использовании xTaskGetTickCount(); я должен обрабатывать этот сброс в 0 ?
а зачем?

Цитата
А все функции операционки которые работают со временем (задержка, взять симофор и т.п. ) , то же обрабатывают сброс счётчика тиков в 0 ?
ээээ.... а это зачем?
зарядили симофор на 100. в счетчик симофора 100. каждый тик из счетчика симофора вычитаем 1. как 0 стал - обработали. вобще счетчик тика тут не причем. (код ос не смотрел, но я бы так сделал)

допустим typedef uint16_t TickType_t;. текущее значение 0xfffe. зафиксировали. прошло 100 тиков. счетчик стал 0х0062. Для вычисления периода времени из нового значения вычитаем старое, т.е. 0х0062 - 0xfffe, для типов uint16_t разница равно 100 dec.

Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение May 29 2014, 15:40
Сообщение #71


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



juvf, спасибо !
Я всегда работал со временем другим способом, и в нём приходилось проверять, не начался ли счёт с 0

И ещё вопрос. Правильно ли я понимаю работу ОС в целом ? :

В устройстве две SD карты. Задача инициализации написана одна, она создаётся в двух экземплярах, в задачу передаётся параметр № карты.
Задача вызывает какие-то функции с локальными переменными, те то же вызывают функции и т.д.
Правильно ли я понимаю, что при переключении контекста все эти локальные переменные сохраняются в стеке задачи, т.е. физически копируются из одной области памяти в другую ?
Если локальные переменные в функциях определены как static, это не влияет на сохранение в стеке ?
Получается, что на переписывание контекста в стек и обратно уходит много времени, и стало быть надо стремится сокращать количество локальных переменных ? Все большие массивы нужно определять как глобальные переменные, и работать с ними как с ресурсом ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение May 30 2014, 00:37
Сообщение #72


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



я думаю что ос работает не так. есть две задачи. у каждой свой стек. локальные переменные создаются и удаляются в стеке задачи не во время переключения, а во время работы задачи, по мере необходимости.есть указатель на вершину стека. при переключении контекста локальные переменные в каждой задаче ни куда не копируются. копируется только указатель на вершину стека. Т.е. кагбэ ос переключается на др стек. Поэтому от размера стека задачи и от кол-ва локальных переменных время переключение контекста не зависит.
Go to the top of the page
 
+Quote Post
Newegor
сообщение May 30 2014, 02:50
Сообщение #73


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 2-03-06
Из: Минск
Пользователь №: 14 879



Цитата(MiklPolikov @ May 29 2014, 22:50) *
juvf, спасибо !
Я всегда работал со временем другим способом, и в нём приходилось проверять, не начался ли счёт с 0

И ещё вопрос. Правильно ли я понимаю работу ОС в целом ? :

В устройстве две SD карты. Задача инициализации написана одна, она создаётся в двух экземплярах, в задачу передаётся параметр № карты.
Задача вызывает какие-то функции с локальными переменными, те то же вызывают функции и т.д.
Правильно ли я понимаю, что при переключении контекста все эти локальные переменные сохраняются в стеке задачи, т.е. физически копируются из одной области памяти в другую ?
Если локальные переменные в функциях определены как static, это не влияет на сохранение в стеке ?
Получается, что на переписывание контекста в стек и обратно уходит много времени, и стало быть надо стремится сокращать количество локальных переменных ? Все большие массивы нужно определять как глобальные переменные, и работать с ними как с ресурсом ?

По поводу переписывания контекства juvf Вам уже ответил. Контекст не переписывается, а переключается.
А вот использование static, без понимания, я бы не рекомендовал. При создании такой переменной ее экземпляр будет один и тот же на все задачи. И это может привести к печальным последствиям, если это не учитывать.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение May 30 2014, 04:13
Сообщение #74


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(Newegor @ May 30 2014, 11:00) *
А вот использование static, без понимания, я бы не рекомендовал. При создании такой переменной ее экземпляр будет один и тот же на все задачи.


Newegor, спасибо за информацию про static !

У меня вот это работает, только если возвращаемая переменная static . А если нет, то функция возвращает 0. Как я понимаю, это потому что существование переменной прекращаеся чуть раньше чем программа вышла из функции, и возвращать оказывается нечего.

Код
char do_something(void)
{
       chatic char result;

        //.................
  
       return result;
}


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение May 30 2014, 05:19
Сообщение #75


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



эта функция или прототип функции объявлен до вызова?
Go to the top of the page
 
+Quote Post
msalov
сообщение May 30 2014, 05:35
Сообщение #76


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Цитата(MiklPolikov @ May 27 2014, 16:11) *
Коллеги, ещё один вопрос :

Верно ли я понимаю, что значение, которое возвращает xTaskGetTickCount(); периодически сбрасывается в 0 и начинает расти заново, т.к. переполняется 32х разрядная переменная, которая считает тики , и стало быть, при использовании xTaskGetTickCount(); я должен обрабатывать этот сброс в 0 ?
А все функции операционки которые работают со временем (задержка, взять симофор и т.п. ) , то же обрабатывают сброс счётчика тиков в 0 ?

МП


Если ваша задержка меньше разрядности счётчика, то 0 обрабатывать не нужно. Но если больше - обязательно (или разбивать на части).

Пример: пусть счётчик 16-битный. Начальное значение 2, а задержка - 70000 (0x11170). Если взять просто сумму получим 0x11172, из-за переполнения получим в итоге 0x1172, что даст реальную задержку 4464 вместо 70000. Если промахнуться с разрядностью переменной, с которой будет сравниваться счётчик - можно никогда не выйти из цикла ожидания.
Go to the top of the page
 
+Quote Post
juvf
сообщение May 30 2014, 05:59
Сообщение #77


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ May 30 2014, 14:23) *
У меня вот это работает, только если возвращаемая переменная static . А если нет, то функция возвращает 0. Как я понимаю, это потому что существование переменной прекращаеся чуть раньше чем программа вышла из функции, и возвращать оказывается нечего.

Код
char do_something(void)
{
       chatic char result;

        //.................
  
       return result;
}

нет, не так работает си/с++. если резалт не статик, то при покидании функции переменная резалт удалится из стека, но её значение не потеряется а нормально вернётся. может у вас в одной задаче резальт считается и равен 0, в другой задаче резалт неравен нулю. в итоге, когда статик, то оба резалта не равны нулю, а одному значению. а когда не статик, то один экземпляр равен нулю. ..... вобщем это гадание на кофейной гуще. что то не так у вас. попробуйте запустить только одну задачу и проверит статик и нестатик - результат должен быть одинаковый, потом 1-ую задачу выкл, и включить вторую - проверить.....
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение May 30 2014, 06:43
Сообщение #78


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(juvf @ May 30 2014, 14:09) *
нет, не так работает си/с++. если резалт не статик, то при покидании функции переменная резалт удалится из стека, но её значение не потеряется а нормально вернётся. может у вас в одной задаче резальт считается и равен 0, в другой задаче резалт неравен нулю. в итоге, когда статик, то оба резалта не равны нулю, а одному значению. а когда не статик, то один экземпляр равен нулю. ..... вобщем это гадание на кофейной гуще. что то не так у вас. попробуйте запустить только одну задачу и проверит статик и нестатик - результат должен быть одинаковый, потом 1-ую задачу выкл, и включить вторую - проверить.....


Я даже без ОС в самом простом линейном коде наблюдаю что функция возвращает только 0 если локальная переменная в ней не static.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение May 30 2014, 07:18
Сообщение #79


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(MiklPolikov @ May 30 2014, 14:53) *
Я даже без ОС в самом простом линейном коде наблюдаю что функция возвращает только 0 если локальная переменная в ней не static.

http://electronix.ru/forum/index.php?showt...t&p=1259306
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение May 30 2014, 12:01
Сообщение #80


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(Lagman @ May 30 2014, 13:29) *
эта функция или прототип функции объявлен до вызова?


Это функция.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение May 31 2014, 06:21
Сообщение #81


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



%)
Я знаю что это функция.
Go to the top of the page
 
+Quote Post
juvf
сообщение May 31 2014, 06:38
Сообщение #82


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ May 30 2014, 16:53) *
Я даже без ОС в самом простом линейном коде наблюдаю что функция возвращает только 0 если локальная переменная в ней не static.

даже не чего подсказат. си/с++ не так работает. отправлять вас читать книжки "Учимся писать на СИ" как-то неприлично. может компилятор кривой, может вы что-то путаете.

Как же вообще у вас FreeRTOS работает? например функция создания задач

Код
signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions )
{
signed  xReturn;
...
return  xReturn;
}
ни каких статиков. и др функции возвращающие не void без всяких статиков.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 31 2014, 08:25
Сообщение #83


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(MiklPolikov @ May 30 2014, 14:23) *
У меня вот это работает, только если возвращаемая переменная static . А если нет, то функция возвращает 0. Как я понимаю, это потому что существование переменной прекращаеся чуть раньше чем программа вышла из функции, и возвращать оказывается нечего.
Код
char do_something(void)
{
       chatic char result;

        //.................
  
       return result;
}

Так не бывает. Тем более с переменной типа char. Она помещается в регистр, поэтому не может прекратить своё существование.
Попробуйте убрать статик и назначить переменной какое-то значение по умолчанию, типа
Код
char do_something(void)
{
       char result = 123;

        //.................
  
       return result;
}

И посмотрите, что получится. Если функция будет возвращать 123, значит вы просто забыли присвоить значение переменной result:)


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jun 8 2014, 09:16
Сообщение #84


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(AHTOXA @ May 31 2014, 16:35) *
Так не бывает. Тем более с переменной типа char. Она помещается в регистр, поэтому не может прекратить своё существование.


Спасибо. Моя проблема скорее всего была связана с изменением переменных в прерывании, директива static иногда работала как volatile.



--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jul 12 2014, 00:58
Сообщение #85


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Коллеги, доброго времени суток.

Не могу до конца понять как работают программные таймеры.
Что такое "очередь таймера" и в каких случаях она переполняется ?
Вот например, мне нужно, что бы таймер начал считать с 0, а если уже считал то сбросился в 0 и начал с 0.
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xBlockTime );
Делает именно это или что-то другое ?
Что такое xBlockTime , почему про неё сказано , что "это то время, которое задача будет заблокирована, пока команда не запишется в очередь таймера" ? Таймер можно как-нибудь просто сбросить в 0 не блокируя задачу, в которой это делается ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jul 12 2014, 13:32
Сообщение #86


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(MiklPolikov @ Jul 12 2014, 04:58) *
Не могу до конца понять как работают программные таймеры.
Что такое "очередь таймера" и в каких случаях она переполняется ?
Вот например, мне нужно, что бы таймер начал считать с 0, а если уже считал то сбросился в 0 и начал с 0.


Полагаю, что термин "очередь таймера" относится не к аппаратному таймеру, как таковому, а к планировщику задач операционной системы разделенного времени. Т.е. в отсутствие операционной системы у таймеров нет никаких очередей.

Судя по всему, под очередью понимается та задача/процедура, на которую таймер должен переключиться при выходе из своей процедуры прерывания. Т.е. по сути это чисто программная задача, а не аппаратная. Причем, место следующего возврата должно быть определено еще до запуска таймера, поскольку после того, как произойдет по нему прерывание, будет некогда искать того, кто стоит в очереди первым. В прерывании вообще нельзя долго находиться, а уж тем более выяснять там какие-то вопросы, которые обязаны были быть решены заранее.

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

В общем случае каких-то стандартов тут нет, т.к. авторы операционной системы вольны создать планировщик задач исключительно по своему вкусу, в том числе и вводить для его описания свои термины. Говорят, что когда-то номер/адрес следующего задания хранили прямо в самом таймере, используя его старшие разряды, которые обычно не используются. Но с тех пор и таймеры стали другими, и задачи стали сложнее, а потому нынче задачи обычно переключают по таблице, малость смахивающую на таблицу прерываний. Что-то более определенное сказать не могу, т.к. свою операционную системы вы не назвали. Хотя, судя по названию процедуры BaseType_t xTimerReset, у вас FreeRTOS.
Go to the top of the page
 
+Quote Post
juvf
сообщение Jul 13 2014, 11:16
Сообщение #87


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(Xenia @ Jul 12 2014, 19:32) *
Судя по всему, под очередью понимается та задача/процедура, на которую таймер должен переключиться при выходе из своей процедуры прерывания. Т.е. по сути это чисто программная задача, а не аппаратная. Причем, место следующего возврата должно быть определено еще до запуска таймера, поскольку после того, как произойдет по нему прерывание, будет некогда искать того, кто стоит в очереди первым. В прерывании вообще нельзя долго находиться, а уж тем более выяснять там какие-то вопросы, которые обязаны были быть решены заранее.
мимо laughing.gif
не нужны ни какие места возврата.

Цитата
Не могу до конца понять как работают программные таймеры.
Открываем журнал КиТ №10 2011, страница 93. Читаем....

Цитата
Что такое "очередь таймера" и в каких случаях она переполняется ?

Очередь команд таймеров
Для совершения операций запуска, оста-
нова, сброса, изменения периода и удале-
ния таймеров во FreeRTOS предоставляется
набор API-функций, которые могут вызы-
ваться из задач и обработчиков прерываний,
а также из функций таймеров. Вызов этих
API-функций не воздействует напрямую
на задачу обслуживания таймеров. Вместо
этого он приводит к записи команды в оче-
редь, которую в дальнейшем мы будем на-
зывать очередью команд таймеров. Задача
обслуживания таймеров считывает команды
из очереди и выполняет их.

....
conf igTIMER_QUEUE_LENGTH. Размер
очереди команд — устанавливает макси-
мальное число невыполненных команд,
которые могут храниться в очереди, пре-
жде чем задача обслуживания таймеров их
выполнит.



Цитата
Что такое xBlockTime
смотрим там же...
xBlockTime — определяет время тайм-
аута — максимальное время нахождения
вызывающей xTimerChangePeriod() задачи
в блокированном состоянии, если очередь
команд полностью заполнена и нет воз-
можности поместить в нее команду об из-
менении периода таймера.

У вас очередь 5 команд. вызвали из других задач 5 разных команд. Потом из текущей вызываем xTimerChangePeriod(). Что должно произойти? Функция xTimerChangePeriod должна поместить в очередь таймера новую команду изменения периода, но очередь заполнина. Что делать? Текущая задача переходит в блокированное состояние на время xBlockTime или до тех пор, пока в очереди не появиться свободное место.


Цитата
Вот например, мне нужно, что бы таймер начал считать с 0, а если уже считал то сбросился в 0 и начал с 0.
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xBlockTime );
Делает именно это или что-то другое ?
там же, в ките, всёже на русском и могучем...
Сброс таймера
Сброс таймера осуществляется с помощью
API-функции xTimerReset(). Ее прототип:
portBASE_TYPE xTimerReset( xTimerHandle xTimer, portTickType
xBlockTime );
...
Операция сброса может применяться как
к активному таймеру, так и к находящему-
ся в пассивном состоянии. В случае если
таймер находился в пассивном состоянии,
вызов xTimerReset() будет эквивалентен вы-
зову xTimerStart(), то есть таймер будет за-
пущен. Если таймер уже отсчитывал время
в момент вызова xTimerReset() (то есть на-
ходился в активном состоянии), то вызов
xTimerReset() приведет к тому, что таймер
заново начнет отсчет времени с момента вы-
зова xTimerReset().



Цитата
Таймер можно как-нибудь просто сбросить в 0 не блокируя задачу, в которой это делается ?

Скорее нельзя. ..... ээээ.... напрямую нет, или да.... вобщем сброс таймера - это запись команды сброса таймера в очередь таймеров. Если у вас 1 таймер... пара мест вызова API для таймера, в которые вы попадаете раз в год и очередь таймера 100 команд, то с вероятностью близкой к 1.0 ваша задача не будет блокирована вызовом xTimerReset(). Если у вас 100 таймеров, 1000 мест вызова API для таймеров... и/или вы ограниченны в длине очереди команд таймера, то можно сделать какойнить финт... типа: сделать задачу сброса таймера. эта задача будет ждать флага/эвента. Основная задача выставляет флаг/запускает эвент сброса таймера и работает дальше, а задача сброса таймера вызывает xTimerReset(). Если очередь таймера полна, то задача сброса таймера блокируется, а основная задача работает. Задача сброса должна быть приоритетом выше.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jul 17 2014, 13:17
Сообщение #88


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(juvf @ Dec 23 2013, 21:33) *
Про зачистку памяти.....

Ту память, которую занимала прибитая задача, зачистит idle. А ту память которую выделили задаче до создания задачи, нужно руками зачищать.

например death.c
Код
void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority )
{
unsigned portBASE_TYPE *puxPriority;

        /* Create the Creator tasks - passing in as a parameter the priority at which
        the suicidal tasks should be created. */
        puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );
        *puxPriority = uxPriority;

        xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );

        /* Record the number of tasks that are running now so we know if any of the
        suicidal tasks have failed to be killed. */
        uxTasksRunningAtStart = uxTaskGetNumberOfTasks();
}

Если задача vCreateTasks сама себя удалит, или её удалит кто-то другой, то память, веделенная вызовом pvPortMalloc не освободится. Нужно позаботится об её освобождении. Поэтому в задаче vCreateTasks делается ручная зачистка

Код
unsigned portBASE_TYPE uxPriority; //создается новая переменная на стеке
...

        uxPriority = *( unsigned portBASE_TYPE * ) pvParameters; //копируется данные из динамической выделенной памяти pvParameters в uxPriority
        vPortFree( pvParameters ); //удаляется динамически выделенная память.


Помогите пожалуйста разобраться с vPortFree.
Вот допустим, я удаляю задачу.
Что делать дальше ? Нужно передать в vPortFree в качестве параметра хендлер этой задачи, и тогда память, которую занимала задача, освободится ?
А если задача удаляет саму себя, перед этим присваивая значение NULL хэндлеру ?
Можно ли перед этим, прямо внутри задачи, запустить vPortFree ?
И как после этого задача продолжит работать , т.е. выполнит два последних действия
v_Task_Handle=NULL;
vTaskDelete(NULL);
если у задачи уже нет никакой памяти, т.е. в эту память может записаться что угодно ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
DASM
сообщение Jul 17 2014, 16:10
Сообщение #89


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Читаю все это и волосы дыбом. Тем более что и работаю с этим. Почему программист должен думать об освобождении памяти? Почему многопоточность не поддерживается средствами языка? Почему до сих пор все сидят на древних языках вроде С и С++ (он недалеко ушел от С, пусть и поддерживает ООП, но все равно с ним обрушить любую систему на ура можно. Есть ли нормальные реализации Явы или С шарп для контроллеров? Иначе это хождение по граблям будет вечным. 15 лет в теме и все одно и тоже. И памяти то уже достаточно для Явы например, и все равно. От слов «указатель» и «приведение типов» тошнит уже в век, когда объемы флеш и озу - ничто, а время на выпуск - все, это анахронизм какой то
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jul 17 2014, 16:46
Сообщение #90


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(DASM @ Jul 17 2014, 20:10) *
Читаю все это и волосы дыбом. Тем более что и работаю с этим. Почему программист должен думать об освобождении памяти? Почему многопоточность не поддерживается средствами языка? Почему до сих пор все сидят на древних языках вроде С и С++ (он недалеко ушел от С, пусть и поддерживает ООП, но все равно с ним обрушить любую систему на ура можно. Есть ли нормальные реализации Явы или С шарп для контроллеров? Иначе это хождение по граблям будет вечным. 15 лет в теме и все одно и тоже. И памяти то уже достаточно для Явы например, и все равно. От слов «указатель» и «приведение типов» тошнит уже в век, когда объемы флеш и озу - ничто, а время на выпуск - все, это анахронизм какой то


Если бы озу было "ничто", то я бы вообще не делал динамическое создание/удаление задач.
Если Вы знаете как надо, то скажите основные ключевые слова.
Есть проц STM32L151 . Выбран как самый малопотребляющий, т.е. ни на что более мощное перейти нельзя.


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
DASM
сообщение Jul 17 2014, 17:13
Сообщение #91


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Если бы я знал «как надо» то не сидел бы тут… увы я знаю только как не надо. Сколько у меня было этих «плавающих» указателей, сколько геммора с потоками (не надо говорить, что все просто, одна инверсия приоритетов чего стоит. В итоге над основной идеей подумать времени мало.
Go to the top of the page
 
+Quote Post
Lagman
сообщение Jul 17 2014, 19:11
Сообщение #92


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



ключевые слова malloc, free и их реализация в порте FreeRTOS для нужного процессора. http://microsin.ru/content/view/1308/44/
Go to the top of the page
 
+Quote Post
DASM
сообщение Jul 17 2014, 19:26
Сообщение #93


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Кому они ключевые ? Да хоть new, хоть malloc - суть одна - любой залетевший дятел разрушит все. Посмотрите примеры программ на Java - там нет этого дебилизма. С++ позволит даже такое *(int *)0x40001234 = 0; На Яве вам никто не позволит пользоваться указателями, оных и нету, и никто не позволит приводить типы с уменьшением точности. С++ - это очень старый язык, он неплох для своих лет, но уже 2014 на дворе. Тот же ассемблер завуалированный.
Go to the top of the page
 
+Quote Post
juvf
сообщение Jul 17 2014, 19:30
Сообщение #94


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Jul 17 2014, 19:17) *
Помогите пожалуйста разобраться с vPortFree.
Вот допустим, я удаляю задачу.
Что делать дальше ?
Во первых вы должны понимать что такое динамическое выделение памяти и для чего оно нужно. как работает стек и куча. В 2-х словах не объяснить.

Цитата
Нужно передать в vPortFree в качестве параметра хендлер этой задачи
ненужно.

вы знаете как работают функции malloc() и free()? Для чего они нужны? Как работают операторы new и delete? Если знаете, то не должно возникнуть вопросов по vPortFree. vPortFree - работает аналогично. Если не знаете или плохо знаете, лучше не заморачивайтесь и работайте на стеке, т.е. без vPortFree pvPortMalloc, иначе выстрел в ногу гарантирован. Зачем вам динамическая память? Если нужны динамические задачи - делайте динамические задачи. Но зачем в динамических задачах использовать динамическую память?

Цитата
Можно ли перед этим, прямо внутри задачи, запустить vPortFree ?
И как после этого задача продолжит работать , т.е. выполнит два последних действия
v_Task_Handle=NULL;
vTaskDelete(NULL);


Ещё раз....
1) выделяем в КУЧЕ 100 байт
void *p = pvPortMalloc( 100 );

2)создадим задачу и передаем в неё в качестве параметра указатель на выделенный блок памяти в куче.
xTaskCreate( myTask, "Leningrad", 30, p, 5, NULL ); - создали задачу myTask, присвоили ей имя Leningrad, размер стека 30( байт или чего-то там, см доки, для стм32 вроде 30*4), приоритет задачи 5. Вот здесь выделяется для нужд задачи 120 байт (30*4) - это стек задачи. Это от дельная память от блока в 100 байт.

3)внутри задачи удаляем задачу vTaskDelete(). Задача остановиться и прекратит работать. Но 120 байт стека и 100 байт в куче не освободятся.

4)Происходит вызов idle. idle высвобождает 120 байт стека задачи.

Но 100 байт выделеных с помощью pvPortMalloc ни кто не зачистит. Более того ни кто не знает - нужно ли эту память зачищать? может далее по алгоримту ваша программа будет работать так

5)создадим другую задачу и передадим в неё в качестве параметра указатель на выделенный блок памяти в куче. В этом блоке нужная информация
xTaskCreate( yourTask, "Moskow", 50, p, 4, NULL ); и более того может быть 100 байт использоваться сразу в 10 задачах. одну задачу удалили- но остальные задачи пользуют эту память.

Если у вас блок в 100 байт использует всего 1 задача и после удаления эти данные ненужны, то руками удалите pvPortFree(). Если удаляете внутри задачи, то перед vTaskDelete()
Код
//полезный код задачи использующий эти 100 байт
pvPortFree(*vParam);//высвобождение памяти выделенной в куче, но не высвобождение памяти стека, т.е. 120 байт продлолжают использоваться
//возможно ещё какойто полезный код, но здесь уже нельзя использовать эти 100 байт
vTaskDelete(NULL);
}
ну вот как-то так.

ps если у вас сценарий, как в последнем моём примере, то зачем вам вообще динамика? пишите в статике, будет вам автоматическая зачистка
Код
void myTask(void *context)
{
uint8_t array[100]; //выделение 100 байт на СТЕКЕ задачи
//полезный код
vTaskDelete(NULL);
}
//создаем задачу
xTaskCreate( myTask, "Leningrad", 30 + 25, 0, 5, NULL );// создали задачу и выделили под стек на 100 байт больше
При таком написании поле удаления задачи idle автоматически зачистит стек задачи? т.е. 120+100 байт, а куча не используется.
Go to the top of the page
 
+Quote Post
DASM
сообщение Jul 17 2014, 19:39
Сообщение #95


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Цитата(juvf @ Jul 17 2014, 23:30) *
Более того ни кто не знает - нужно ли эту память зачищать?

Если на нее никто не ссылается - сборщик мусора освободит ее. Если среда выполнения поддерживает это. Программист менее всего должен думать КОГДА освободить память. По-сути в нормальной серьезной программе с асинхронными обработчиками он даже и не может этого знать. Отсюда все эти Unhandled exception - а в области MCU - просто hard fault (и то если это Кортекс итп, а обычно просто крик в форуме "виснет, помогите"
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jul 17 2014, 19:47
Сообщение #96


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(juvf @ Jul 17 2014, 23:30) *
ps если у вас сценарий, как в последнем моём примере, то зачем вам вообще динамика? пишите в статике, будет вам автоматическая зачистка[code]void myTask(void *context)


Видимо я плохо объяснил.
Речь не о памяти, занятой при выполнении задачи. Речь о стеке самой задачи. После удаления задачи память освобождается не сразу, а только в задаче idle . Если я сразу после удаления создаю новую задачу , а программа между этими двумя действиями не попадает в Idle task , то памяти может не хватить. Вопрос : как освободить память менее криво, чем вызывать между удалением и созданием vTaskDeleay ? Ну неужели не предусмотрено простого способа ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
juvf
сообщение Jul 17 2014, 20:09
Сообщение #97


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(MiklPolikov @ Jul 18 2014, 01:47) *
Видимо я плохо объяснил.
Речь не о памяти, занятой при выполнении задачи. Речь о стеке самой задачи. После удаления задачи память освобождается не сразу, а только в задаче idle . Если я сразу после удаления создаю новую задачу , а программа между этими двумя действиями не попадает в Idle task , то памяти может не хватить. Вопрос : как освободить память менее криво, чем вызывать между удалением и созданием vTaskDeleay? Ну неужели не предусмотрено простого способа ?

хороший вопрос. теоретически можно 100 раз создать задачу и 100 раз удалить, и при этом не разу не попав в idle.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jul 17 2014, 20:12
Сообщение #98


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(juvf @ Jul 18 2014, 00:09) *
хороший вопрос. теоретически можно 100 раз создать задачу и 100 раз удалить, и при этом не разу не попав в idle.

Вы начали меня понимать !


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
Lagman
сообщение Jul 17 2014, 20:36
Сообщение #99


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(DASM @ Jul 17 2014, 23:26) *
Кому они ключевые ? Да хоть new, хоть malloc - суть одна - любой залетевший дятел разрушит все. Посмотрите примеры программ на Java - там нет этого дебилизма. С++ позволит даже такое *(int *)0x40001234 = 0; На Яве вам никто не позволит пользоваться указателями, оных и нету, и никто не позволит приводить типы с уменьшением точности. С++ - это очень старый язык, он неплох для своих лет, но уже 2014 на дворе. Тот же ассемблер завуалированный.

Пользуйте BASIC и не будете так нервничать sm.gif

Цитата(DASM @ Jul 17 2014, 23:39) *
Программист менее всего должен думать КОГДА освободить память. По-сути в нормальной серьезной программе с асинхронными обработчиками он даже и не может этого знать.

Вот к чему мир катится, программисты превращаются в кодеров, которым не надо будет думать sm.gif и программы с миганием светодиодов для микроконтроллеров будут весить под несколько гигабайт sm.gif
Go to the top of the page
 
+Quote Post
juvf
сообщение Jul 17 2014, 20:40
Сообщение #100


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(DASM @ Jul 18 2014, 01:39) *
Если на нее никто не ссылается - сборщик мусора освободит ее. Если среда выполнения поддерживает это. Программист менее всего должен думать КОГДА освободить память. По-сути в нормальной серьезной программе с асинхронными обработчиками он даже и не может этого знать. Отсюда все эти Unhandled exception - а в области MCU - просто hard fault (и то если это Кортекс итп, а обычно просто крик в форуме "виснет, помогите"

в мэтро может и не должен знать. а в реалтайм - не то что должен - ОБЯЗАН знать. Прогер должен занать, что вот в этом месте код исполняется 100 тактов, и что никакие сборщики мусора его не прервут.

так то это очередной вброс говна в вентилятор на тему c++ vs java. а ветка про FreeRTOS. Предлагаю дальнейшее обсуждение языков для мк перенести в более подходящее место и не засорять эту тему.
Go to the top of the page
 
+Quote Post

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

 


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


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