msalov 0 30 мая, 2014 Опубликовано 30 мая, 2014 · Жалоба Коллеги, ещё один вопрос : Верно ли я понимаю, что значение, которое возвращает xTaskGetTickCount(); периодически сбрасывается в 0 и начинает расти заново, т.к. переполняется 32х разрядная переменная, которая считает тики , и стало быть, при использовании xTaskGetTickCount(); я должен обрабатывать этот сброс в 0 ? А все функции операционки которые работают со временем (задержка, взять симофор и т.п. ) , то же обрабатывают сброс счётчика тиков в 0 ? МП Если ваша задержка меньше разрядности счётчика, то 0 обрабатывать не нужно. Но если больше - обязательно (или разбивать на части). Пример: пусть счётчик 16-битный. Начальное значение 2, а задержка - 70000 (0x11170). Если взять просто сумму получим 0x11172, из-за переполнения получим в итоге 0x1172, что даст реальную задержку 4464 вместо 70000. Если промахнуться с разрядностью переменной, с которой будет сравниваться счётчик - можно никогда не выйти из цикла ожидания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 30 мая, 2014 Опубликовано 30 мая, 2014 · Жалоба У меня вот это работает, только если возвращаемая переменная static . А если нет, то функция возвращает 0. Как я понимаю, это потому что существование переменной прекращаеся чуть раньше чем программа вышла из функции, и возвращать оказывается нечего. char do_something(void) { chatic char result; //................. return result; } нет, не так работает си/с++. если резалт не статик, то при покидании функции переменная резалт удалится из стека, но её значение не потеряется а нормально вернётся. может у вас в одной задаче резальт считается и равен 0, в другой задаче резалт неравен нулю. в итоге, когда статик, то оба резалта не равны нулю, а одному значению. а когда не статик, то один экземпляр равен нулю. ..... вобщем это гадание на кофейной гуще. что то не так у вас. попробуйте запустить только одну задачу и проверит статик и нестатик - результат должен быть одинаковый, потом 1-ую задачу выкл, и включить вторую - проверить..... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 30 мая, 2014 Опубликовано 30 мая, 2014 · Жалоба нет, не так работает си/с++. если резалт не статик, то при покидании функции переменная резалт удалится из стека, но её значение не потеряется а нормально вернётся. может у вас в одной задаче резальт считается и равен 0, в другой задаче резалт неравен нулю. в итоге, когда статик, то оба резалта не равны нулю, а одному значению. а когда не статик, то один экземпляр равен нулю. ..... вобщем это гадание на кофейной гуще. что то не так у вас. попробуйте запустить только одну задачу и проверит статик и нестатик - результат должен быть одинаковый, потом 1-ую задачу выкл, и включить вторую - проверить..... Я даже без ОС в самом простом линейном коде наблюдаю что функция возвращает только 0 если локальная переменная в ней не static. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 30 мая, 2014 Опубликовано 30 мая, 2014 · Жалоба Я даже без ОС в самом простом линейном коде наблюдаю что функция возвращает только 0 если локальная переменная в ней не static. http://electronix.ru/forum/index.php?showt...t&p=1259306 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 30 мая, 2014 Опубликовано 30 мая, 2014 · Жалоба эта функция или прототип функции объявлен до вызова? Это функция. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 31 мая, 2014 Опубликовано 31 мая, 2014 · Жалоба %) Я знаю что это функция. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 31 мая, 2014 Опубликовано 31 мая, 2014 · Жалоба Я даже без ОС в самом простом линейном коде наблюдаю что функция возвращает только 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 без всяких статиков. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 31 мая, 2014 Опубликовано 31 мая, 2014 · Жалоба У меня вот это работает, только если возвращаемая переменная static . А если нет, то функция возвращает 0. Как я понимаю, это потому что существование переменной прекращаеся чуть раньше чем программа вышла из функции, и возвращать оказывается нечего. char do_something(void) { chatic char result; //................. return result; } Так не бывает. Тем более с переменной типа char. Она помещается в регистр, поэтому не может прекратить своё существование. Попробуйте убрать статик и назначить переменной какое-то значение по умолчанию, типа char do_something(void) { char result = 123; //................. return result; } И посмотрите, что получится. Если функция будет возвращать 123, значит вы просто забыли присвоить значение переменной result:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 8 июня, 2014 Опубликовано 8 июня, 2014 · Жалоба Так не бывает. Тем более с переменной типа char. Она помещается в регистр, поэтому не может прекратить своё существование. Спасибо. Моя проблема скорее всего была связана с изменением переменных в прерывании, директива static иногда работала как volatile. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 12 июля, 2014 Опубликовано 12 июля, 2014 · Жалоба Коллеги, доброго времени суток. Не могу до конца понять как работают программные таймеры. Что такое "очередь таймера" и в каких случаях она переполняется ? Вот например, мне нужно, что бы таймер начал считать с 0, а если уже считал то сбросился в 0 и начал с 0. BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xBlockTime ); Делает именно это или что-то другое ? Что такое xBlockTime , почему про неё сказано , что "это то время, которое задача будет заблокирована, пока команда не запишется в очередь таймера" ? Таймер можно как-нибудь просто сбросить в 0 не блокируя задачу, в которой это делается ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 35 12 июля, 2014 Опубликовано 12 июля, 2014 · Жалоба Не могу до конца понять как работают программные таймеры. Что такое "очередь таймера" и в каких случаях она переполняется ? Вот например, мне нужно, что бы таймер начал считать с 0, а если уже считал то сбросился в 0 и начал с 0. Полагаю, что термин "очередь таймера" относится не к аппаратному таймеру, как таковому, а к планировщику задач операционной системы разделенного времени. Т.е. в отсутствие операционной системы у таймеров нет никаких очередей. Судя по всему, под очередью понимается та задача/процедура, на которую таймер должен переключиться при выходе из своей процедуры прерывания. Т.е. по сути это чисто программная задача, а не аппаратная. Причем, место следующего возврата должно быть определено еще до запуска таймера, поскольку после того, как произойдет по нему прерывание, будет некогда искать того, кто стоит в очереди первым. В прерывании вообще нельзя долго находиться, а уж тем более выяснять там какие-то вопросы, которые обязаны были быть решены заранее. Изменения в самой очереди, по-видимому, происходят только тогда, когда ставится новая задача или снимается/завершается старая. Т.е. только в этот момент в порядке очередности задач могут произойти какие-то изменения, тогда как задача таймера - чистое переключение. В общем случае каких-то стандартов тут нет, т.к. авторы операционной системы вольны создать планировщик задач исключительно по своему вкусу, в том числе и вводить для его описания свои термины. Говорят, что когда-то номер/адрес следующего задания хранили прямо в самом таймере, используя его старшие разряды, которые обычно не используются. Но с тех пор и таймеры стали другими, и задачи стали сложнее, а потому нынче задачи обычно переключают по таблице, малость смахивающую на таблицу прерываний. Что-то более определенное сказать не могу, т.к. свою операционную системы вы не назвали. Хотя, судя по названию процедуры BaseType_t xTimerReset, у вас FreeRTOS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 13 июля, 2014 Опубликовано 13 июля, 2014 · Жалоба Судя по всему, под очередью понимается та задача/процедура, на которую таймер должен переключиться при выходе из своей процедуры прерывания. Т.е. по сути это чисто программная задача, а не аппаратная. Причем, место следующего возврата должно быть определено еще до запуска таймера, поскольку после того, как произойдет по нему прерывание, будет некогда искать того, кто стоит в очереди первым. В прерывании вообще нельзя долго находиться, а уж тем более выяснять там какие-то вопросы, которые обязаны были быть решены заранее.мимо :laughing: не нужны ни какие места возврата. Не могу до конца понять как работают программные таймеры.Открываем журнал КиТ №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(). Если очередь таймера полна, то задача сброса таймера блокируется, а основная задача работает. Задача сброса должна быть приоритетом выше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Про зачистку памяти..... Ту память, которую занимала прибитая задача, зачистит 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); если у задачи уже нет никакой памяти, т.е. в эту память может записаться что угодно ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Читаю все это и волосы дыбом. Тем более что и работаю с этим. Почему программист должен думать об освобождении памяти? Почему многопоточность не поддерживается средствами языка? Почему до сих пор все сидят на древних языках вроде С и С++ (он недалеко ушел от С, пусть и поддерживает ООП, но все равно с ним обрушить любую систему на ура можно. Есть ли нормальные реализации Явы или С шарп для контроллеров? Иначе это хождение по граблям будет вечным. 15 лет в теме и все одно и тоже. И памяти то уже достаточно для Явы например, и все равно. От слов «указатель» и «приведение типов» тошнит уже в век, когда объемы флеш и озу - ничто, а время на выпуск - все, это анахронизм какой то Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Читаю все это и волосы дыбом. Тем более что и работаю с этим. Почему программист должен думать об освобождении памяти? Почему многопоточность не поддерживается средствами языка? Почему до сих пор все сидят на древних языках вроде С и С++ (он недалеко ушел от С, пусть и поддерживает ООП, но все равно с ним обрушить любую систему на ура можно. Есть ли нормальные реализации Явы или С шарп для контроллеров? Иначе это хождение по граблям будет вечным. 15 лет в теме и все одно и тоже. И памяти то уже достаточно для Явы например, и все равно. От слов «указатель» и «приведение типов» тошнит уже в век, когда объемы флеш и озу - ничто, а время на выпуск - все, это анахронизм какой то Если бы озу было "ничто", то я бы вообще не делал динамическое создание/удаление задач. Если Вы знаете как надо, то скажите основные ключевые слова. Есть проц STM32L151 . Выбран как самый малопотребляющий, т.е. ни на что более мощное перейти нельзя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться