Змінюй хід війни! Допомагай ЗСУ!

Мягкий Real-Time в Windows XP

  • Автор теми Автор теми Neurox
  • Дата створення Дата створення
и все же реальный реалтайм только в реальных RTOS, тобишь QNX, VxWorkx и т.д.
красота qnx заключается в том, что ты вообще можешь собрать систему впринципе без планировщика задач, только одну твою прогу (ну с дровами конечно), которая будет работать в максимальном приоритете. тогда правда не будет многозадачности как таковой. в любом случае qnx дает гарантированный отклик, будь то 1мс, или 500нс... счет идет на наносекунды. при условии что можно задействовать Adaptive Partition, который позволяет гарантированно отдавать заданное %-е время процессора/памяти и прочих ресурсов конкретной программе, про работе в многозадачном режиме. ничего сложного в qnx нет, тем более если есть опыт написания под лины. впрочем достаточно знать с++, сокеты, ну и как работать с gcc. единственный минус, что qnx не бесплатна, и в конце концов на готовый продукт придётся покупать лицензию. хотя базовая лицензия на самый минимум порядка 50-7- баксов, что не так уж много.
 
Пардон. Мой первый вариант не катит. Написал, потестил (самому интересно стало).
Даже привязанный к одному ядру поток TIME_CRITICAL в процессе REALTIME_CLASS_PRIORITY проскакивает интервалы в 1 мс.
И ваще, с виндой дело плохо. ((

PS: Спс BFG-9000, напомнил про Affinity (привязку к ядру).
 
у меня получилось сделать псевдореальайм под винды в аналогичной задаче, только у меня карт ввода/вывода 3 и комп чистый двухпроцессорный был. Причем делалось это в Делфи, ибо для всех карт под него были библиотеки. Делалось это на таймере, в основе которого был счетчик циклов проца (таймер не мой, сторонний номпонент). Точность времени квантования 1 мс плюс/минус 50 мкс. Вышибается только потоковыми файловыми операциями, а если комп не трогать, вообще работает идеально. На однопроцессорной машине не работало, была та же проблема - пропускал такты
 
Всем привет)
Наконец-то я добрался до работающего приложения))
Защита магистрерской младшего брата на подходе и пора было закончить эти пляски с бубном)

Итак что получилось:

1.Первоначальные требования по производительности оказались значительно завышены.
2.Целевой алгоритм оказался детерминированным- Т.е он работает независимо от предидущего состояния системы, пропуск отсчетов между блоками по 20 точек совершенно не критичен)
3.Основной модуль--консольное приложение. модуль конфигурации - диалоговое окно . связь по PIPE.

Не судите строго быдлокод — очень спешил..))


Идея с половинками буфера нагло скопипизжена из документации для работы с платой L-Card L783M

Сбор данных идет в отдельном потоке.

Настройки АЦП :
частота дискретизации 400кГц.
считывается блоками по 7 значений(7 каналов ввода.)
интервал между считывания блоков 1 мс.
после считывания 20 блоков--происходит запуск обработчика данных через флаг.
С++ код
PHP:
 ULONG WINAPI ServiceThread(PVOID /*Context*/)
{
   
   ULONG halfbuffer = IrqStep*pages/2;             // Собираем половинками кольцевого буфера
   ULONG fl2,fl1 = fl2 = (*sync<=halfbuffer)? 0:1; // Настроили флаги
   short  *tmp1;
   
   //Процедура копирования половинок бушера в рабочий массив
   while(1)
   {
	   
      while(fl2==fl1) fl2=(*sync<=halfbuffer)? 0:1; // Ждем заполнения половинки буфера
      //tmp=fdata+(halfbuffer*i);                    // Настраиваем указатель в файле
      tmp1=data+(halfbuffer*fl1);                  // Настраиваем указатель в кольцевом буфере
      memcpy(data1,tmp1,halfbuffer*sizeof(USHORT));// Записываем данные в файл
      fl1=(*sync<=halfbuffer)? 0:1;                // Обновляем флаг
	  HalfBuffer=true;
      Sleep(10);
   }
   complete=1;
   // Мы завершили сбор данных
  return 0;// Вышли (надо реализовать выход по команде с пользовательской консоли)
}

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



В main() кроме потока сбора данные запускается 3 потока связи с внешним миром:

PHP:
//Запускаем поток чтения конфигурации
// защиты в пользовательскую консоль
hThread_config_read=CreateThread(0,0x2000,ThreadWaitConfigReadConnect,0,0,&Tid2);
//cout<<"pipe test write"<<endl;
//Запускаем поток записи конфигурации защиты из пользовательской консоли
hThread_config_write=CreateThread(0,0x2000,ThreadWaitConfigWriteConnect,0,0,&Tid2);
//Запускаем поток данных для пользовательской консоли и OPC сервера
hThread_data=CreateThread(0,0x2000,ThreadWaitDataConnect,0,0,&Tid2);

Пример одного из сторожевых потоков для PIPE

PHP:
DWORD WINAPI ThreadWaitDataConnect(LPVOID nParam)
{       float nData[8];
	DWORD dwBytesRead;

	hNamedPipe_data = CreateNamedPipe ( "\\\\.\\pipe\\pipe_data",PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_WAIT,
	10, // максимальное количество экземпляров канала 
	0, // размер выходного буфера по умолчанию 
	0, // размер входного буфера по умолчанию 
	INFINITE, // клиент ждет связь бесконечно долго 
	NULL // защита по умолчанию 
	); 

	
	
	/////////////////////////////
	if (hNamedPipe_data == INVALID_HANDLE_VALUE) 
	{ 
		cout<<"NVALID_HANDLE_VALUE"<<endl;
	} 
	///////////////////////////
	while(1)
	{
		if(!ConnectNamedPipe( hNamedPipe_data, NULL )) 
	{  
     //cout<<"error"<<endl;
	}
//...................................................................
///
//Заполняем nData
///
//...................................................................
	if(WriteFile(hNamedPipe_data, &nData,sizeof(nData),&dwBytesRead,NULL))
	{
		//cout<<"read ok"<<endl;

	}
	DisconnectNamedPipe(hNamedPipe_data);
	FlagConnect_data=FALSE;
	}
	return 0;
}

Поток основного расчетного алгоритма:

PHP:
DWORD WINAPI ThreadMainAlgoritm(LPVOID nParam)
{
	while(1)
	{
	if(HalfBuffer==true)
	{
	//Выполняется заполнение массивов и преобразование из кода АЦП в вольты(float)
	for(int i=0;i<=19;i++)
	{
		Ia1[i]=5.0*data[i*7]/2000.0;
		Ib1[i]=5.0*data[i*7+1]/2000.0;
		Ic1[i]=5.0*data[i*7+2]/2000.0;
		Ua1[i]=5.0*data[i*7+3]/2000.0;
		Ub1[i]=5.0*data[i*7+4]/2000.0;
		Uc1[i]=5.0*data[i*7+5]/2000.0;
		F[i]=10*data[i*7+6]/2000.0;
		//cout<<Ia1[i]<<endl;
	}
	//попробуем вызвать основную функцию расчета температуры ротора...
	F4();
	HalfBuffer=false;
	}
	}
	return 0;
}

Оболочка пользователя интереса совершенно не представляет --там стандартная работа с MFC.



BFG-9000, Sefiroth огромное спасибо за информацию, пригодится в других проектах)

кстати та задача которая мной решалась , в свете новых требований по производительности прекрасно заработает на ATmega 8))

Там в расчетной функции F4() только фильтр Фурье для расчета действующих значений токов и напряжений и функция с чисто алгебраическими вычислениями для расчета температуры ротора.

Кому интересно, могу расказать как написать СВОЙ!! OPC сервер)

На базе взломанного Fastwel Uni OPC )))))))
 
Останнє редагування:
Хорошая статья про многопоточность в винде
⚠ Тільки зареєстровані користувачі бачать весь контент та не бачать рекламу.


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



Бльо, я так надеялся что кто-то скажет-"cool source bro!!"

P.S. тяпниццо)))
 
Останнє редагування:
Назад
Зверху Знизу