?? profibus.c
字號:
// otevreny handle je pozadavek zpracovavan.
//
PB->ActualHID = ReadHIDfromRB( Request );
PB_DbgPrintL2( "PB: Zpracovavani pozadavku pro HID=%d:\n",
PB->ActualHID );
PB_ProcessRequest( PB, Request );
}
else
PB_ChangeMasterState( PB, Check_Access_Time );
break;
//*************************************************************
case Check_Access_Time:
PB->LastUseTokenEntryTicks = PB->UseTokenEntryTicks;
if ( PB->RLL_Status == RLL_WaitNextCycle )
PB->RLL_Status = RLL_TestNext;
PB_ChangeMasterState( PB, Pass_Token );
break;
//*************************************************************
case Pass_Token:
//
// Pri prechodu ze stavu Check_Access_Time (tzn. master zapojen do log.
// kruhu, probiha datova vymena) vyprsi-li odpocitavadlo G je aktualizovana
// dalsi polozka v GAPu
//
if ( PB->LastState == Check_Access_Time )
{
NextToTest = GAPL_NextToTest( &PB->GAPL );
if ( NextToTest == -1 )
{
//
// mezi TS a NS nelezi zadne stanice
//
PB_SendToken( PB, PB->NS, PB->TS );
PB_ChangeMasterState( PB, Check_Token_Pass );
break;
}
if ( PB->G_CountDown <= 0 )
{
PB->G_CountDown = PB->G;
PB_SendRequestFDLStatuswithReply( PB, NextToTest );
PB_ChangeMasterState( PB, Await_Status_Resp );
break;
}
else
{
PB->G_CountDown--;
PB_SendToken( PB, PB->NS, PB->TS );
PB_ChangeMasterState( PB, Check_Token_Pass );
break;
}
}
//
// Navrat po otestovani dalsi stanice z GAPu. Je vyslan token dalsi stanici.
// NS se muze rovnat TS.
//
if ( PB->LastState == Await_Status_Resp )
{
PB_SendToken( PB, PB->NS, PB->TS ); // dalsi master ovsem nemusi token prevzit - nutno testovat
PB_ChangeMasterState( PB, Check_Token_Pass );
break;
}
//
// Studeny start logickeho kruhu. Prebirame iniciativu na sbernici a
// zaciname s vytvarenim GAPu.
//
if ( PB->LastState == Claim_Token )
{
GAPL_Clear( &PB->GAPL );
GAPL_RestartTest( &PB->GAPL );
PB_DbgPrintL3( "PB: Prebirame iniciativu na sbernici...\n" );
PB->StationStatus = Master_in_logical_ring;
PB_SendToken( PB, PB->TS, PB->TS );
PB_SendToken( PB, PB->TS, PB->TS );
PB_SendRequestFDLStatuswithReply( PB, GAPL_NextToTest( &PB->GAPL ) );
// neprepiname do Await_Status_Resp, ale pri vytvareni GAPLu zustavame
// v Pass_Token
break;
}
break;
//*************************************************************
case Check_Token_Pass:
if ( PB->NS == PB->TS )
PB_ChangeMasterState( PB, Active_Idle ); // Na sbernici neni jiny master
else
{
PB_SetTimeOut( PB, PB->tsl, TO_StartTxEmpty ); // Cekame na overeni spravneho predani tokenu
}
break;
}
// tady uz by nemelo nic byt...
// vypadavaji tu ChangeMasterState(...) z rekurze...
}
//*****************************************************************************
//** Vola se pokud je prijat znak - zajistuje vytvareni vstupniho bufferu,
//** vyhledani validnich ramcu a jejich predani k dalsimu zpracovani.
//** Fce je volana z nizsi vrstvy.
//**
//** Parametry:
//** ----------
//** ch - prijaty znak
//*****************************************************************************
void PB_RxByte( PTProfibus PB, UCHAR ch )
{
int length;
int i;
int StartIndex;
BOOLEAN TakeNextFrame;
if ( !PB )
{
DbgPrint( "PB: RxByte Error - PB pointer is NULL!" );
return;
}
/*
if ( ( PB->MasterState == Await_Data_Resp || PB->MasterState == Await_Status_Resp )
&& PB->TimeOutState == TO_Running )
PB_StopTimeOut( PB ); // casovac deaktivovan prijmem prvniho znaku
//jeste je potreba testovat spravnost ramce a pripadne generovat timeout
*/
if ( PB->InBufLen<0 || PB->InBufLen >= INBUF_SIZE )
{
DbgPrint("PB: InBuf Error - out of range!");
return;
}
PB->InBuf[PB->InBufLen] = ch;
PB->InBufLen++;
if ( PB->InBufLen >= INBUF_SIZE )
{
DbgPrint("PB: InBuf Overflow!");
PB->InBufLen = INBUF_SIZE - 1;
return;
}
do
{
TakeNextFrame = FALSE;
if ( PBFrame_FindFrame( PB->InBuf, PB->InBufLen, &length ) ) // hleda na zacatku prijatych dat ramec a v length vraci jeho delku
{
PBFrame_DecodeFrame( &PB->RxFrame,
PB->InBuf,
PB->InBufLen,
PB->TS,
PB->default_sap );
//InBuf.Delete(1,length);
if ( length <= PB->InBufLen )
for ( i = 0; i < PB->InBufLen - length; i++ )
PB->InBuf[i] = PB->InBuf[i + length]; // odstraneni zpracovaneho framu
PB->InBufLen -= length;
TakeNextFrame = TRUE;
//
// vyplneni falesnych parametru pro ShortAcknowledge (muze nekde delat neplechu)
//
if ( PB->RxFrame.FrameType == FT_ShortAcknowledge )
{
if ( PB->MasterState == Await_Data_Resp )
{
PB->RxFrame.DA = (UBYTE) PB->TS;
PB->RxFrame.SA = PB->ActualRequest->application_block.rem_add.station;
}
else
{
//
// Nejsme-li ve stavu cekani na odpoved priradime ramci SA jinou nez
// TS (ramec typu ShortAcknowldge neobsahuje zdrojovou a cilovou adresu
// a tudiz nemusi byt jasne pro koho je - stanice vi, ze je ramec pro
// ni pokud ma token a ceka na odpoved - problem muze byt pri propojeni
// mastera na sbernici).
// Hodnota TS+1 je falesna, ale hodnota mimo 0..HSA by mohla zpusobit
// chybu nekde jinde.
//
PB->RxFrame.DA = (UBYTE) PB->TS + 1;
if ( PB->RxFrame.DA > PB->HSA )
PB->RxFrame.DA = 0;
PB->RxFrame.SA = (UBYTE) PB->TS + 1;
if ( PB->RxFrame.SA > PB->HSA )
PB->RxFrame.SA = 0;
//
// Mozna by bylo jednodussi a stacilo by nastavi RxFrame.Valid na FALSE
//
}
}
//
// Format ramce je spravny - muzeme ho spracovat
//
if ( PB->RxFrame.Valid )
{
//
// Na sbernici vysila duplicitni stanice ve stavu Listen_Token
//
if ( PB->RxFrame.SA == PB->TS && PB->MasterState == Listen_Token )
{
PB->DuplicitAddressCounter++;
if ( PB->DuplicitAddressCounter >= 2 )
{
PB_DbgPrintL3( "PB: Na sbernici vysila stanice s duplicitni adresou %d!",
PB->TS );
PB_DbgPrintL3( "PB: Prechod do stavu Offline..." );
PB->DuplicitAddressCounter = 0;
PB_ChangeMasterState( PB, Offline );
return;
}
}
//
// Znovuspusteni time-outu k detekci rozpadu logickeho kruhu
// ve stavu Active_Idle
//
if ( PB->MasterState == Active_Idle )
{
PB_StopTimeOut( PB );
// Melo by nasledovat
//PB_SetTimeOut( PB, Tto, TO_StartNow );
}
//
// Na sbernici vysila duplicitni stanice ve stavu Active_Idle
//
if ( PB->RxFrame.SA == PB->TS && PB->MasterState == Active_Idle )
{
PB_DbgPrintL3( "PB: Na sbernici vysila stanice s duplicitni adresou!" );
PB_DbgPrintL3( "PB: Prechod do stavu Listen_Token..." );
PB_ChangeMasterState( PB, Listen_Token );
return;
}
//
// Prijat token
//
if ( PB->RxFrame.FrameType == FT_Token )
{
PB_ReceivedToken( PB, PB->RxFrame.DA, PB->RxFrame.SA );
return;
}
//
// Overeni spravneho odeslani Tokenu - NS stanice vysila ramec
// Pokud jako prvni ramec od NS byl Token pro nas, tak byl jiz
// zpracovan vyse.
//
if ( PB->MasterState == Check_Token_Pass && PB->RxFrame.SA == PB->NS )
{
PB_StopTimeOut( PB );
PB_ChangeMasterState( PB, Active_Idle );
//
// Zde nesmi byt return - prvni ramec, ktery NS stanice vysila
// totiz muze take byt pro nas
//
//return;
}
//
// Prijaty ramec je pro nas
//
if ( PB->RxFrame.DA == PB->TS ||
PB->RxFrame.FrameType == FT_ShortAcknowledge )
{
if ( PB->RxFrame.FrameType == FT_Reply ||
PB->RxFrame.FrameType == FT_ShortAcknowledge )
{
PB_ReceivedReply( PB ); // prisla odpoved na nas pozadavek
}
else
PB_ReceivedRequest( PB ); // prisel pozadavek z vnejsku
}
}
}
else // nenalezen zadny platny pocatek framu SDx nebo SC - odriznuti pocatku znaku v bufferu az dalsimu SDx nebo SC
{
StartIndex = PBFrame_FindStartDelimiter( PB->InBuf, PB->InBufLen );
if ( StartIndex != -1 && StartIndex != 1 )
{
StartIndex--; // dedictvi Stringu
for ( i = 0; i < PB->InBufLen - StartIndex; i++ )
PB->InBuf[i] = PB->InBuf[i + StartIndex]; // odstraneni zpracovaneho framu
PB->InBufLen -= StartIndex;
}
}
// pro jistotu
if ( PB->InBufLen >= INBUF_SIZE )
{
DbgPrint("PB: InBuf Overflow2!");
PB->InBufLen = INBUF_SIZE - 1;
return;
}
}
while ( TakeNextFrame && PB->InBufLen > 0 );
}
//*****************************************************************************
//** Vola se pokud na sbernici dochazi k predavani tokenu. Zajistuje vytvareni
//** a udrzbu LASu ve stavu Listen_Token a prijmuti tokenu pokud je pro TS
//** (This Station) - tj. pro nas.
//** V LASu pracuje pouze se stanicemi typu master.
//**
//** Parametry:
//** ----------
//** _DA - adresa stanice pro kterou je Token urcen (nemusi byt jenom pro nas,
//** tato fce zpracovava vsechny Tokeny vyslane na sbernici
//** _SA - adresa puvodce Tokenu
//*****************************************************************************
void PB_ReceivedToken( PTProfibus PB, int _DA, int _SA )
{
// DbgPrint("PB: Stanice %d prijala token (DA=%d SA=%d).", PB->TS, _DA, _SA);
switch ( PB->MasterState )
{
case Offline:
break;
//---------------------------------------
case Listen_Token:
//
// deaktivace Timeoutu pro Claim_Token pokud prisel token (melo by se mozna deaktivovat i driv [jenom od prijmu znaku?? ] )
// nekde by se ovsem mel rozebehnout dalsi time-out...
//
PB_StopTimeOut( PB );
if ( !LAS_Complete( &PB->LAS ) )
{
//
// Vytvareni LASu a detekce dvou shodnych obehu tokenu
//
if ( LAS_CreatingAdd( &PB->LAS, _SA ) )
{
// LAS complete
PB->StationStatus = Master_ready;
PB_DbgPrintL2( "PB: Dva identicke obehy tokenu - LAS completed!" );
}
}
else
{
//
// LAS hotov - ted pouze updatovani a cekani na povereni od PS
//
LAS_Update( &PB->LAS, _SA );
}
break;
//*************************************************************
case Check_Token_Pass:
case Active_Idle:
if ( _SA == PB->PS && _DA == PB->NS ) // Stanice byla nasilne vyrazena z ringu
{
PB_DbgPrintL3( "PB: Master byl nasilne vyrazen z ringu!" );
PB_ChangeMasterState( PB, Listen_Token );
break;
}
LAS_Update( &PB->LAS, _SA );
LAS_VymazStanice( &PB->LAS, _DA, _SA ); // Update LASu nejlepe vymazanim stanic mezi SA a DA - snad OK
if ( _DA == PB->TS ) // Token je pro nas
{
//DbgPrint("PB: Stanice %d prijala token (DA=%d SA=%d - PS=%d).", PB->TS, _DA, _SA, PB->PS);
if ( PB->PS != -1 && PB->PS != _SA )
{
// jeste by tu mohlo byt overeni jestli opakovani je od te same stanice
PB->IgnoreTokenCounter++;
if ( PB->IgnoreTokenCounter >= 2 )
PB->IgnoreTokenCounter = 0; // a pokracuje se dale
else
break;
}
//DbgPrint("PB: Stanice %d prijala token (DA=%d SA=%d) S3.", PB->TS, _DA, _SA);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -