Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Удаленная работа
Помощь проекту


 
Опции темы
Непрочитано 21.04.2017, 13:27  
NewWriter
Почётный гражданин KAZUS.RU
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Сообщений: 2,607
Сказал спасибо: 223
Сказали Спасибо 748 раз(а) в 516 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

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

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

Нажмите, чтобы открыть спойлер

PHP код:
/* Global variables */
/* дескрипторы задач */
xTaskHandle xMainParentTsHandle NULL,
            
xChildTs1aHandle NULL,
            
xChildTs1bHandle NULL,
            
xChildTs1cHandle NULL;
BaseType_t error;        // переменная ошибок

/* Function prototypes */
static void prvSetupHardwarevoid );
static 
void prvParentTaskvoid *pvParameters );
void prvChildTask1void *pvParameters );
/**
**===========================================================================
**
**  Abstract: main program
**
**===========================================================================
*/
int main(void)
{
    
prvSetupHardware();   // инит портов
//-----------------------------------------------
    /* Запуск главной (родительской) задачи     */
    
error xTaskCreateprvParentTask,                    // функция, реализующая задачу
                
"MainTask",                                // имя задачи для нужд отладки
                
configMINIMAL_STACK_SIZE,                // запрашиваемый размер стека для задачи
                
NULL,                                    // нет параметров, передаваемых в задачу
                
tskIDLE_PRIORITY ),                // приоритет задачи
                
&xMainParentTsHandle );                    // хэндл (дескриптор) задачи
    
if (error == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
    {
/* #error Не хватает памяти в куче для размещения задачи */ }
//----------------------------------------------
        /* Запускается планировщик задач */
        
vTaskStartScheduler();
//----------------------------------------------
      
for (;;) {}  // бесконечный цикл, в случае если не был запущен планировщик
}    /* main() */

/**
**===========================================================================
**
**  Abstract: Функции, реализующие задачи
**
**===========================================================================
*/
//.....................................................
/* Задача запускает дочерние задачи в виде эеземпляров одной
 * и той же задачи, но с разными параметрами
 */
static void prvParentTaskvoid *pvParameters )
{
    
vTaskDelay(100);            // перевод задачи в bloked на указанное время
    
BLUE_ON;                    // индикация начала работы задачи

    /* Объявляется структура передаваемых параметров */
    
struct param_t{                    // структура с типом param_t
        
uint8_t numLED;                // номер св.диода
        
uint8_t duration;            // длительность его включения
    
};

    const 
struct param_t SendParam1 = {115};    // Передаваемые параметры для каждого
    
const struct param_t SendParam2 = {250};    //   экземпляра задачи -
    
const struct param_t SendParam3 = {385};    //   номер св.диода и длительность его включения

    /* Создаются экземпляры задачи */
    //......Первый экземпляр............
    
error xTaskCreateprvChildTask1,                    // функция, реализующая задачу
                
"BlinkLED1",                            // имя задачи для нужд отладки
                
configMINIMAL_STACK_SIZE,                // запрашиваемый размер стека для задачи
                
(void *)&SendParam1,                    // передаваемые в задачу параметры при ее создании
                
tskIDLE_PRIORITY ),                // приоритет задачи
                
&xChildTs1aHandle );                    // хэндл (дескриптор) задачи
    
if (error == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
    {
/* #error Не хватает памяти в куче для размещения задачи */ }
    
//..................................
    //......Второй экземпляр............
    
error xTaskCreateprvChildTask1,                    // функция, реализующая задачу
                
"BlinkLED2",                            // имя задачи для нужд отладки
                
configMINIMAL_STACK_SIZE,                // размер стека
                
(void *)&SendParam2,                    // передаваемые в задачу параметры при ее создании
                
tskIDLE_PRIORITY ),                // приоритет задачи
                
&xChildTs1bHandle );                    // хэндл (дескриптор) задачи
    
if (error == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
    {
/* #error Не хватает памяти в куче для размещения задачи */ }
    
//..................................
    //......Третий экземпляр............
    
error xTaskCreateprvChildTask1,                    // функция, реализующая задачу
                
"BlinkLED3",                            // имя задачи для нужд отладки
                
configMINIMAL_STACK_SIZE,                // размер стека
                
(void *)&SendParam3,                    // передаваемые в задачу параметры при ее создании
                
tskIDLE_PRIORITY ),                // приоритет задачи
                
&xChildTs1cHandle );                    // хэндл (дескриптор) задачи
    
if (error == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
    {
/* #error Не хватает памяти в куче для размещения задачи */ }
    
//..................................
    
vTaskDelay(100);        // перевод задачи в bloked на указанное время
    
BLUE_OFF;                // Индикация завершения работы задачи
    
vTaskDelete(NULL);        // Удаляется эта же самая задача, она больше не существует в системе,
                            // память, выделенная для нее, будет очищена в задаче IdleTask.
                            // При этом обязательно должен использоваться файл heap_2.c или heap_4.c
                            // в папке MemMang
}
//.....................................................

/* Функция, общая для каждого создаваемого экземпляра задачи,
 * но задачи создаются отдельные и в списке задач каждый экземпляр
 * представлен отдельной задачей.
 */
void LedOn(uint8_t numLED);
void LedOff(uint8_t numLED);

void prvChildTask1void *pvParameters )
{
    
/* Объявляется структура для приема параметров */
    
struct param_t{                // структура с типом param_t
        
uint8_t numLED;            //
        
uint8_t duration;        //
    
};
    
/* принятые параметры приводятся к типу созданной структуры */
    
struct param_t *ReceiveParam;                    // объявляется указатель на структуру
    
ReceiveParam = (struct param_t*)pvParameters;    // приводится к типу созданной структуры

    /* Бесконечный цикл, реализующий работу задачи -
     * мигание светодиодами, с заданной длительностью включения */
    
for (;;)
    {
        
vTaskDelay(ReceiveParam->duration);            // задача переводится в bloked на указанное время
        
LedOn(ReceiveParam->numLED);                // вкл.св.диод, номер которого указан в параметре

        
vTaskDelay(100 ReceiveParam->duration);    // задача переводится в bloked на указанное время
        
LedOff(ReceiveParam->numLED);                // выкл.вд.диод, номер которого указан в параметре
    
}
}
//.....................................................
/* Функции, управляющие вкл/выкл св.диодов */
void LedOn(uint8_t numLED)
{    
GPIOA->BSRR << (numLED 7); }

void LedOff(uint8_t numLED)
{     
GPIOA->BRR << (numLED 7); }
/*-----------------------------------------------------------*/

/*-----------------------------------------------------------*/
/* Задача "бездействие". В настройках РТОС должен быть оперделена
 * #define configUSE_IDLE_HOOK   1 для возможности использования этой задачи
 * В переменной munRunTasc будет количество запущенных задач
 * Переменная absnumTick показывает время (в тиках) от старта планировщика.
 */
UBaseType_t munRunTasc;
void vApplicationIdleHookvoid )
{
    
GREEN_ON;        // индикация входа в Idle
    
munRunTasc uxTaskGetNumberOfTasks();    // число запущенных задач
    
absnumTick xTaskGetTickCount();        // число прошедших тиков от запуска
    
GREEN_OFF;
}
/*-----------------------------------------------------------*/ 


Видно, что в процессе работы изменяется число существующих в системе задач. Задача Idle (бездействие) - тоже отображается в списке.


Реклама:
NewWriter вне форума  
Сказали "Спасибо" NewWriter
MoonLate (22.04.2017)
Непрочитано 21.04.2017, 13:58  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 11,521
Сказал спасибо: 990
Сказали Спасибо 3,693 раз(а) в 2,037 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

Надо не забывать, что данные, расположенные по указателю, должны существовать до тех пор, пока задача их не получит и не решит, что они больше не актуальны. И тут становится ясно, для чего нужно динамически выделять память: вы декларируете указатель на структуру, просите дать вам для нее памяти, заполняете память, передаете указатель в задачу, задача его обрабатывает и освобождает память, ссылаясь на тот же самый указатель через vPortFree (если память не изменяет, как там отпускать память назад)
Easyrider83 вне форума  
Сказали "Спасибо" Easyrider83
MoonLate (22.04.2017)
Непрочитано 21.04.2017, 15:37  
NewWriter
Почётный гражданин KAZUS.RU
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Сообщений: 2,607
Сказал спасибо: 223
Сказали Спасибо 748 раз(а) в 516 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

А, да, верно... строго говоря, задачу удалять нельзя, не скопировав принятые данные, поскольку как только освободившаяся память будет занята под другую задачу, данные по тем адресам испортятся и указатели будут не актуальны.
Просто хотел показать, что задачи могут создаваться и удаляться во время работы ОС.
NewWriter вне форума  
Непрочитано 21.04.2017, 15:45  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 11,521
Сказал спасибо: 990
Сказали Спасибо 3,693 раз(а) в 2,037 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

Кстати, как раз динамическое выделение памяти больше всего крови и выпивает. При подобном подходе (правильном, кстати говоря) память быстро фрагментируется. Если у вас ее и так не много, то рано или поздно надо ждать, что heap вернет ноль и если исключение не будет обработано, получим hard fault. Честно говоря, на STM32 я смог запустить только heap_1 и heap_2. Остальные просто зависают. Не вдавался в причины, хотя видимо, пора бы уже.
Easyrider83 вне форума  
Непрочитано 21.04.2017, 16:05  
dkm
Временная регистрация
 
Регистрация: 10.04.2010
Сообщений: 86
Сказал спасибо: 7
Сказали Спасибо 17 раз(а) в 13 сообщении(ях)
dkm на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

Пока не прочитаете Курница и не вникните в каждую строчку, то лучше не приниматься. Задачи-то вы в демо запустите, светодиодиками помигаете и не более.
Вообще тема хорошая, но такое впечатление, что мало кто использует FreeRtos, хотя очень достойная и удобная вещь. Правда если что-то более менее серьезное, то заморочек.... Но без неё ещё хуже.
dkm вне форума  
Сказали "Спасибо" dkm
MoonLate (22.04.2017)
Непрочитано 21.04.2017, 16:08  
dkm
Временная регистрация
 
Регистрация: 10.04.2010
Сообщений: 86
Сказал спасибо: 7
Сказали Спасибо 17 раз(а) в 13 сообщении(ях)
dkm на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

Сообщение от Easyrider83 Посмотреть сообщение
Честно говоря, на STM32 я смог запустить только heap_1 и heap_2. Остальные просто зависают. Не вдавался в причины, хотя видимо, пора бы уже.
Стек и кучу проверить надо в настройках линковщика, работают все, хотя у меня наоборот вначале только с третьим шло
dkm вне форума  
Непрочитано 22.04.2017, 01:21  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 11,521
Сказал спасибо: 990
Сказали Спасибо 3,693 раз(а) в 2,037 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

Вот мой пример вывода сообщений на экран.
Код:
typedef struct
{
	char text[LCD_STRINGSIZE];
	LCD_CMD_TypeDef cmd;
}LCD_MSG_StructTypeDef;
Где LCD_STRINGSIZE - максимальный размер сообщения. Для 1602 это 16 или 32+1 символа
Эта функция кладет сообщение в очередь.
Код:
void LCD_Print (char * Text, LCD_CMD_TypeDef Cmd)
{
	/* Dedicate memory for message */
	LCD_MSG_StructTypeDef * MSG = pvPortMalloc(sizeof(LCD_MSG_StructTypeDef));
	
	/* If memory available */
	if (MSG)
	{
		/* Cope text to message */
		strcpy(MSG->text, Text);
		
		/* Set command to execute before */
		MSG->cmd = Cmd;
		
		/* Put message to queue */
		xQueueSend(xLCD_MSG_Queue, &MSG, NULL);
	}
}
А эта функция забирает сообщение
Код:
	/* Handle message */	
	while(1)
	{
		if (xQueueReceive(xLCD_MSG_Queue, &MSG, portMAX_DELAY) == pdPASS)
		{
			/* Execute command */
			HD44780_SPI_Cmd(&LCD, MSG->cmd);
			if (MSG->cmd == LCD_CMD_Clear)
				HD44780_SPI_Cmd(&LCD, LCD_CMD_Home);
			vTaskDelay(10);
			
			/* Print message */
			HD44780_SPI_Print(&LCD, MSG->text);
			vPortFree(MSG);
		}
	}
И освобождает память. Таким образом, мы занимаем в очереди минимум памяти - там храним только один указатель на сообщение. Сообщение ложится в память и хранится там, пока его не обработают. Очень удобно и красиво.
Easyrider83 вне форума  
Сказали "Спасибо" Easyrider83
MoonLate (22.04.2017)
Непрочитано 22.04.2017, 15:56  
MoonLate
Частый гость
 
Регистрация: 06.10.2015
Сообщений: 16
Сказал спасибо: 17
Сказали Спасибо 3 раз(а) в 2 сообщении(ях)
MoonLate на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

Огромная благодарность за примеры! Сейчас какраз разбираюсь с очередями. Радует что можно передать не только байты данных но и указатели на данные.
С созданием задач все получилось. Дело продвигается ☺
MoonLate вне форума  
Непрочитано 23.04.2017, 17:07  
hacker7
Вид на жительство
 
Регистрация: 07.01.2007
Адрес: Ленинградская обл
Сообщений: 427
Сказал спасибо: 150
Сказали Спасибо 71 раз(а) в 53 сообщении(ях)
hacker7 на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

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

1. Каждая задача програмируется как набор вариантов действий
2. На следующем входе в начало кда задачи выбирается вариант того, что нужно сделать в этот раз (в этот заход). Типа конечного автомата. На выходе - не переход на начало кода, а возврат (в диспетчер).
3. Диспетчер по очереди заходит в "начало цикла" каждой задачи.
4. Все циклы задач имеют одинаковую длину по времени выполнения. Это бывает нужно для отслеживания абсолютных временных интервалов (например, звук). Пояснение. Все ветвления (как задачи, так и ветки If внутри задач) сбалансированы по времени выполнения команд в каждом из ветвлений. Конечно, это для програмирования "в кодах".

При таком подходе не необходимы прерывания. При реализации балансировки не необходим высокоточный таймер.

Модификация техники для случаев, когда не требуется точная служба времени:
1. Каждая задача программируется как бесконечный цикл, так, как удобно, как будто нет никакого диспетчера, за исключением:
2. Как минимум один вызов диспетчера без параметров в каждом прохождении цикла задачи
и такие же вызовы во внутренних циклах, в т ч в опросах и задержках.

Диспетчер, которого вызвали, сохраняет контекст и смотрит, в какую задачу возвращать управление (не обязательно в эту)

Эта вторая техника частично используется в виндоуз, но мне представляется более разумной первая (хотя в случае, когда нужжна балансировка времени выполнния, без прогр в кодах не обойтись)
hacker7 вне форума  
Непрочитано 23.04.2017, 19:38  
NewWriter
Почётный гражданин KAZUS.RU
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Сообщений: 2,607
Сказал спасибо: 223
Сказали Спасибо 748 раз(а) в 516 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: FreeRTOS?? Разобраться с демо проектом??

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

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

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

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите разобраться с ОУ (приведение к "земле" напряжения со смещением) pittyalex Электроника - это просто 165 08.04.2015 00:55
Помогите разобраться с Контроллер Beckhoff CX1010-0021 wwwwwwww8 Микроконтроллеры, АЦП, память и т.д 9 20.05.2014 16:15
помогите разобраться в кварцах kobraxxx Информация по радиокомпонентам 9 05.01.2012 17:38
Помогите разобраться с PIC18F4550 и USB john2103 Микроконтроллеры, АЦП, память и т.д 26 02.08.2011 11:52
Как совместить Microblaze.bit с общим проектом ISE.bit? tixonia Цифровые сигнальные процессоры 1 28.12.2007 10:08


Часовой пояс GMT +4, время: 10:25.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd. Перевод: zCarot