Перейти к содержанию
    

Несколько вопросов начинающего

Если бы я знал «как надо» то не сидел бы тут… увы я знаю только как не надо. Сколько у меня было этих «плавающих» указателей, сколько геммора с потоками (не надо говорить, что все просто, одна инверсия приоритетов чего стоит. В итоге над основной идеей подумать времени мало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ключевые слова malloc, free и их реализация в порте FreeRTOS для нужного процессора. http://microsin.ru/content/view/1308/44/

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кому они ключевые ? Да хоть new, хоть malloc - суть одна - любой залетевший дятел разрушит все. Посмотрите примеры программ на Java - там нет этого дебилизма. С++ позволит даже такое *(int *)0x40001234 = 0; На Яве вам никто не позволит пользоваться указателями, оных и нету, и никто не позволит приводить типы с уменьшением точности. С++ - это очень старый язык, он неплох для своих лет, но уже 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 байт, а куча не используется.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Более того ни кто не знает - нужно ли эту память зачищать?

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ps если у вас сценарий, как в последнем моём примере, то зачем вам вообще динамика? пишите в статике, будет вам автоматическая зачистка
void myTask(void *context)

 

Видимо я плохо объяснил.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Видимо я плохо объяснил.

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

хороший вопрос. теоретически можно 100 раз создать задачу и 100 раз удалить, и при этом не разу не попав в idle.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

хороший вопрос. теоретически можно 100 раз создать задачу и 100 раз удалить, и при этом не разу не попав в idle.

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Пользуйте BASIC и не будете так нервничать :)

 

Программист менее всего должен думать КОГДА освободить память. По-сути в нормальной серьезной программе с асинхронными обработчиками он даже и не может этого знать.

Вот к чему мир катится, программисты превращаются в кодеров, которым не надо будет думать :) и программы с миганием светодиодов для микроконтроллеров будут весить под несколько гигабайт :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Такой вопрос :

 

Система виснет, потому что какая-то задача берёт семафор, и не отдаёт.

Какие есть способы узнать, где именно семафор не отдан ?

Неужели никаких простых нет, и "всё плохо" ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

заведи глобальную переменную 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(....);

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тут был мой вопрос, ответ на который я сразу же сам нашёл :laughing:

Изменено пользователем ohmjke

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всем доброго времени суток.

Есть такая проблема - если в кратце - то при пеердаче структуры в очереди теряются элементы.

Если по-конкретнне то есть вот такая структура:

    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МГц.

Почему так?

Изменено пользователем Halfback

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

проблема оказалась в определении очереди (привет 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));
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...