DASM 0 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Если бы я знал «как надо» то не сидел бы тут… увы я знаю только как не надо. Сколько у меня было этих «плавающих» указателей, сколько геммора с потоками (не надо говорить, что все просто, одна инверсия приоритетов чего стоит. В итоге над основной идеей подумать времени мало. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба ключевые слова malloc, free и их реализация в порте FreeRTOS для нужного процессора. http://microsin.ru/content/view/1308/44/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Кому они ключевые ? Да хоть new, хоть malloc - суть одна - любой залетевший дятел разрушит все. Посмотрите примеры программ на Java - там нет этого дебилизма. С++ позволит даже такое *(int *)0x40001234 = 0; На Яве вам никто не позволит пользоваться указателями, оных и нету, и никто не позволит приводить типы с уменьшением точности. С++ - это очень старый язык, он неплох для своих лет, но уже 2014 на дворе. Тот же ассемблер завуалированный. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Помогите пожалуйста разобраться с 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 байт, а куча не используется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Более того ни кто не знает - нужно ли эту память зачищать? Если на нее никто не ссылается - сборщик мусора освободит ее. Если среда выполнения поддерживает это. Программист менее всего должен думать КОГДА освободить память. По-сути в нормальной серьезной программе с асинхронными обработчиками он даже и не может этого знать. Отсюда все эти Unhandled exception - а в области MCU - просто hard fault (и то если это Кортекс итп, а обычно просто крик в форуме "виснет, помогите" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба ps если у вас сценарий, как в последнем моём примере, то зачем вам вообще динамика? пишите в статике, будет вам автоматическая зачистка void myTask(void *context) Видимо я плохо объяснил. Речь не о памяти, занятой при выполнении задачи. Речь о стеке самой задачи. После удаления задачи память освобождается не сразу, а только в задаче idle . Если я сразу после удаления создаю новую задачу , а программа между этими двумя действиями не попадает в Idle task , то памяти может не хватить. Вопрос : как освободить память менее криво, чем вызывать между удалением и созданием vTaskDeleay ? Ну неужели не предусмотрено простого способа ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Видимо я плохо объяснил. Речь не о памяти, занятой при выполнении задачи. Речь о стеке самой задачи. После удаления задачи память освобождается не сразу, а только в задаче idle . Если я сразу после удаления создаю новую задачу , а программа между этими двумя действиями не попадает в Idle task , то памяти может не хватить. Вопрос : как освободить память менее криво, чем вызывать между удалением и созданием vTaskDeleay? Ну неужели не предусмотрено простого способа ? хороший вопрос. теоретически можно 100 раз создать задачу и 100 раз удалить, и при этом не разу не попав в idle. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба хороший вопрос. теоретически можно 100 раз создать задачу и 100 раз удалить, и при этом не разу не попав в idle. Вы начали меня понимать ! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Кому они ключевые ? Да хоть new, хоть malloc - суть одна - любой залетевший дятел разрушит все. Посмотрите примеры программ на Java - там нет этого дебилизма. С++ позволит даже такое *(int *)0x40001234 = 0; На Яве вам никто не позволит пользоваться указателями, оных и нету, и никто не позволит приводить типы с уменьшением точности. С++ - это очень старый язык, он неплох для своих лет, но уже 2014 на дворе. Тот же ассемблер завуалированный. Пользуйте BASIC и не будете так нервничать :) Программист менее всего должен думать КОГДА освободить память. По-сути в нормальной серьезной программе с асинхронными обработчиками он даже и не может этого знать. Вот к чему мир катится, программисты превращаются в кодеров, которым не надо будет думать :) и программы с миганием светодиодов для микроконтроллеров будут весить под несколько гигабайт :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 17 июля, 2014 Опубликовано 17 июля, 2014 · Жалоба Если на нее никто не ссылается - сборщик мусора освободит ее. Если среда выполнения поддерживает это. Программист менее всего должен думать КОГДА освободить память. По-сути в нормальной серьезной программе с асинхронными обработчиками он даже и не может этого знать. Отсюда все эти Unhandled exception - а в области MCU - просто hard fault (и то если это Кортекс итп, а обычно просто крик в форуме "виснет, помогите" в мэтро может и не должен знать. а в реалтайм - не то что должен - ОБЯЗАН знать. Прогер должен занать, что вот в этом месте код исполняется 100 тактов, и что никакие сборщики мусора его не прервут. так то это очередной вброс говна в вентилятор на тему c++ vs java. а ветка про FreeRTOS. Предлагаю дальнейшее обсуждение языков для мк перенести в более подходящее место и не засорять эту тему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 31 июля, 2014 Опубликовано 31 июля, 2014 · Жалоба Такой вопрос : Система виснет, потому что какая-то задача берёт семафор, и не отдаёт. Какие есть способы узнать, где именно семафор не отдан ? Неужели никаких простых нет, и "всё плохо" ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 10 1 августа, 2014 Опубликовано 1 августа, 2014 · Жалоба ну у фриртоса вроде нет таких служебных функций. но так такое вроде на раз-два можно поймать. заведи глобальную переменную const char* govnoPlace; и далее... xSemaphoreTake(....); govnoPlace = "void myFunk();"; //полезный код govnoPlace = 0; xSemaphoreGive(....); xSemaphoreTake(....); govnoPlace = "Место, где солнце ни когда не светит"; //полезный код govnoPlace = 0; xSemaphoreGive(....); потом проверяй чему равно govnoPlace, и поймешь в каком месте семафор застревает. Можно красивее сделать, перегрузить функции xSemaphoreTake и xSemaphoreGive и внутри них сделать присвоение к глобальному указателю приоритет текущей задачи, хандлер, имя задачи. А можно к присваивать к глобальной переменной имя файла и номер строки, где произошел захват. Если есть вывод, например в файл или в RS232, то можно сделать так xSemaphoreTake(....); printf(stream, "Take semafor from %s file, line %s", __FILE__, __LINE__); //полезный код printf(stream, "Give semafor from %s file, line %s", __FILE__, __LINE__); xSemaphoreGive(....); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ohmjke 0 12 октября, 2014 Опубликовано 12 октября, 2014 (изменено) · Жалоба Тут был мой вопрос, ответ на который я сразу же сам нашёл :laughing: Изменено 12 октября, 2014 пользователем ohmjke Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 23 апреля, 2015 Опубликовано 23 апреля, 2015 (изменено) · Жалоба Всем доброго времени суток. Есть такая проблема - если в кратце - то при пеердаче структуры в очереди теряются элементы. Если по-конкретнне то есть вот такая структура: typedef struct { unsigned short int LSensor_Num; unsigned short int WLevelValueAv; unsigned short int TimeStartMeasure; unsigned short int DurationMeasureSec; } WLevelData; Очередь инициализирована так: osMessageQDef(Level2Storage_Queue, 4, WLevelData); Level2Storage_QueueHandle = osMessageCreate(osMessageQ(Level2Storage_Queue), NULL); Задачи инициализированы так: osThreadDef(TX_Task, Start_TX_Task, osPriorityNormal, 0, 128); RD_TaskHandle = osThreadCreate(osThread(TX_Task), NULL); osThreadDef(RX_Task, Start_RX_Task, osPriorityBelowNormal, 0, 128); Storage_TaskHandle = osThreadCreate(osThread(RX_Task), NULL); Есть задача где раз в 6 секунд происходит запись в очередь void Start_TX_Task(void const * argument) { portTickType xLastWakeTime; portBASE_TYPE xStatus; WLevelData WLevel = {1,111,0,60}; xLastWakeTime = xTaskGetTickCount(); /* Infinite loop */ for(;;) { xStatus = xQueueSendToBack(Level2Storage_QueueHandle,&WLevel,0); if(xStatus != pdPASS ) {} // Could not send to the queue vTaskDelayUntil(&xLastWakeTime,6000); } } Есть задача где периодически очередь считывается. void Start_RX_Task(void const * argument) { portBASE_TYPE xStatus; portTickType xLastWakeTime; WLevelData WLevel_rx; xLastWakeTime = xTaskGetTickCount(); for(;;) { if(uxQueueMessagesWaiting(Level2Storage_QueueHandle)) { xStatus=xQueueReceive(Level2Storage_QueueHandle,&WLevel_rx,0); } vTaskDelayUntil(&xLastWakeTime,130); } } И в итоге прием происходит, но последние 2 значения (TimeStartMeasure и DurationMeasureSec) в структуре WLevel_rx всегда "0". Увеличивал кучу на 10кБ. Также увеличивал глубину стека в задачах. Приоритеты менял. Не помогло. МК: STM32F407VG, клок: 168МГц. Почему так? Изменено 23 апреля, 2015 пользователем Halfback Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 23 апреля, 2015 Опубликовано 23 апреля, 2015 · Жалоба проблема оказалась в определении очереди (привет CubeMX) osMessageQDef(Level2Storage_Queue, 4, WLevelData); Level2Storage_QueueHandle = osMessageCreate(osMessageQ(Level2Storage_Queue), NULL); если заменить на классику RDLevel2Storage_QueueHandle = xQueueCreate(4,sizeof(WLevelData)); то структура передаётся без потерь. а проблема имхо кроется в #define osMessageQDef(name, queue_sz, type) \ const osMessageQDef_t os_messageQ_def_##name = \ { (queue_sz), sizeof (type) } osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) { (void) thread_id; return xQueueCreate(queue_def->queue_sz, (uint32_t) sizeof(queue_def->item_sz)); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться