|
|
  |
Несколько вопросов начинающего |
|
|
|
May 30 2014, 05:35
|
Знающий
   
Группа: Свой
Сообщений: 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. Если промахнуться с разрядностью переменной, с которой будет сравниваться счётчик - можно никогда не выйти из цикла ожидания.
|
|
|
|
|
May 30 2014, 05:59
|

Профессионал
    
Группа: Свой
Сообщений: 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-ую задачу выкл, и включить вторую - проверить.....
|
|
|
|
|
May 30 2014, 06:43
|

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

|
Цитата(juvf @ May 30 2014, 14:09)  нет, не так работает си/с++. если резалт не статик, то при покидании функции переменная резалт удалится из стека, но её значение не потеряется а нормально вернётся. может у вас в одной задаче резальт считается и равен 0, в другой задаче резалт неравен нулю. в итоге, когда статик, то оба резалта не равны нулю, а одному значению. а когда не статик, то один экземпляр равен нулю. ..... вобщем это гадание на кофейной гуще. что то не так у вас. попробуйте запустить только одну задачу и проверит статик и нестатик - результат должен быть одинаковый, потом 1-ую задачу выкл, и включить вторую - проверить..... Я даже без ОС в самом простом линейном коде наблюдаю что функция возвращает только 0 если локальная переменная в ней не static.
--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
|
|
|
|
|
May 31 2014, 06:38
|

Профессионал
    
Группа: Свой
Сообщений: 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 без всяких статиков.
|
|
|
|
|
May 31 2014, 08:25
|

фанат дивана
     
Группа: Свой
Сообщений: 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:)
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 12 2014, 00:58
|

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

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

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

|
Цитата(MiklPolikov @ Jul 12 2014, 04:58)  Не могу до конца понять как работают программные таймеры. Что такое "очередь таймера" и в каких случаях она переполняется ? Вот например, мне нужно, что бы таймер начал считать с 0, а если уже считал то сбросился в 0 и начал с 0. Полагаю, что термин "очередь таймера" относится не к аппаратному таймеру, как таковому, а к планировщику задач операционной системы разделенного времени. Т.е. в отсутствие операционной системы у таймеров нет никаких очередей. Судя по всему, под очередью понимается та задача/процедура, на которую таймер должен переключиться при выходе из своей процедуры прерывания. Т.е. по сути это чисто программная задача, а не аппаратная. Причем, место следующего возврата должно быть определено еще до запуска таймера, поскольку после того, как произойдет по нему прерывание, будет некогда искать того, кто стоит в очереди первым. В прерывании вообще нельзя долго находиться, а уж тем более выяснять там какие-то вопросы, которые обязаны были быть решены заранее. Изменения в самой очереди, по-видимому, происходят только тогда, когда ставится новая задача или снимается/завершается старая. Т.е. только в этот момент в порядке очередности задач могут произойти какие-то изменения, тогда как задача таймера - чистое переключение. В общем случае каких-то стандартов тут нет, т.к. авторы операционной системы вольны создать планировщик задач исключительно по своему вкусу, в том числе и вводить для его описания свои термины. Говорят, что когда-то номер/адрес следующего задания хранили прямо в самом таймере, используя его старшие разряды, которые обычно не используются. Но с тех пор и таймеры стали другими, и задачи стали сложнее, а потому нынче задачи обычно переключают по таблице, малость смахивающую на таблицу прерываний. Что-то более определенное сказать не могу, т.к. свою операционную системы вы не назвали. Хотя, судя по названию процедуры BaseType_t xTimerReset, у вас FreeRTOS.
|
|
|
|
|
Jul 13 2014, 11:16
|

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

|
Цитата(Xenia @ Jul 12 2014, 19:32)  Судя по всему, под очередью понимается та задача/процедура, на которую таймер должен переключиться при выходе из своей процедуры прерывания. Т.е. по сути это чисто программная задача, а не аппаратная. Причем, место следующего возврата должно быть определено еще до запуска таймера, поскольку после того, как произойдет по нему прерывание, будет некогда искать того, кто стоит в очереди первым. В прерывании вообще нельзя долго находиться, а уж тем более выяснять там какие-то вопросы, которые обязаны были быть решены заранее. мимо не нужны ни какие места возврата. Цитата Не могу до конца понять как работают программные таймеры. Открываем журнал КиТ №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(). Если очередь таймера полна, то задача сброса таймера блокируется, а основная задача работает. Задача сброса должна быть приоритетом выше.
|
|
|
|
|
Jul 17 2014, 13:17
|

Гуру
     
Группа: Свой
Сообщений: 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); если у задачи уже нет никакой памяти, т.е. в эту память может записаться что угодно ?
--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
|
|
|
|
|
Jul 17 2014, 16:46
|

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

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