Finally got MS/TP communicating on ports/rtos32. I still need to verify that it is doing things correctly since it seems a little slow to respond to service requests. Still more work to do refactoring the state machine.

This commit is contained in:
skarg
2006-08-25 21:36:56 +00:00
parent 52ee5a5619
commit 6b18bb8935
7 changed files with 246 additions and 274 deletions
+217 -250
View File
@@ -72,7 +72,7 @@
/* least significant octet first */ /* least significant octet first */
/* (pad): (optional) at most one octet of padding: X'FF' */ /* (pad): (optional) at most one octet of padding: X'FF' */
/* The number of tokens received or used before a Poll For Master cycle */ /* The number of tokens received or used before a Poll For Master cycle */
/* is executed: 50. */ /* is executed: 50. */
const unsigned Npoll = 50; const unsigned Npoll = 50;
@@ -88,7 +88,8 @@ const uint8_t Nmin_octets = 4;
/* (Implementations may use larger values for this timeout, */ /* (Implementations may use larger values for this timeout, */
/* not to exceed 100 milliseconds.) */ /* not to exceed 100 milliseconds.) */
/* At 9600 baud, 60 bit times would be about 6.25 milliseconds */ /* At 9600 baud, 60 bit times would be about 6.25 milliseconds */
const uint16_t Tframe_abort = 1 + ((1000 * 60) / 9600); /* const uint16_t Tframe_abort = 1 + ((1000 * 60) / 9600); */
const uint16_t Tframe_abort = 100;
/* The maximum idle time a sending node may allow to elapse between octets */ /* The maximum idle time a sending node may allow to elapse between octets */
/* of a frame the node is transmitting: 20 bit times. */ /* of a frame the node is transmitting: 20 bit times. */
@@ -132,12 +133,18 @@ const uint16_t Tusage_delay = 15;
/* node must wait for a remote node to begin using a token or replying to */ /* node must wait for a remote node to begin using a token or replying to */
/* a Poll For Master frame: 20 milliseconds. (Implementations may use */ /* a Poll For Master frame: 20 milliseconds. (Implementations may use */
/* larger values for this timeout, not to exceed 100 milliseconds.) */ /* larger values for this timeout, not to exceed 100 milliseconds.) */
const uint16_t Tusage_timeout = 20; const uint16_t Tusage_timeout = 50;
/* we need to be able to increment without rolling over */ /* we need to be able to increment without rolling over */
#define INCREMENT_AND_LIMIT_UINT8(x) {if (x < 0xFF) x++;} #define INCREMENT_AND_LIMIT_UINT8(x) {if (x < 0xFF) x++;}
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;} #define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
bool MSTP_Line_Active(volatile struct mstp_port_struct_t *mstp_port)
{
return (mstp_port->EventCount > Nmin_octets);
}
unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */ unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */
unsigned buffer_len, /* amount of space available */ unsigned buffer_len, /* amount of space available */
uint8_t frame_type, /* type of frame to send - see defines */ uint8_t frame_type, /* type of frame to send - see defines */
@@ -523,7 +530,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
mstp_port->DataCRC = CRC_Calc_Data(mstp_port->DataRegister, mstp_port->DataCRC = CRC_Calc_Data(mstp_port->DataRegister,
mstp_port->DataCRC); mstp_port->DataCRC);
mstp_port->DataAvailable = false; mstp_port->DataAvailable = false;
mstp_port->Index++; /* Index now becomes the number of data octets */ mstp_port->Index++;
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA; mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;
} }
/* CRC2 */ /* CRC2 */
@@ -542,10 +549,8 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
if (mstp_port->DataCRC == 0xF0B8) { if (mstp_port->DataCRC == 0xF0B8) {
/* indicate the complete reception of a valid frame */ /* indicate the complete reception of a valid frame */
mstp_port->ReceivedValidFrame = true; mstp_port->ReceivedValidFrame = true;
/* the master node state machine will receive
/* now might be a good time to process the message or */ and validate the message */
/* copy the data to a buffer so that we can process the message */
/* wait for the start of the next frame. */ /* wait for the start of the next frame. */
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE; mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
} }
@@ -566,19 +571,7 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
return; return;
} }
void mstp_put_receive(volatile struct mstp_port_struct_t #if PRINT_ENABLED
*mstp_port)
{
if (mstp_port)
{
dlmstp_put_receive(
mstp_port->SourceAddress, /* source MS/TP address */
(uint8_t *) & mstp_port->InputBuffer[0],
mstp_port->Index);
}
}
#if PRINT_ENABLED_MASTER
char *mstp_master_state_text(int state) char *mstp_master_state_text(int state)
{ {
char *text = "unknown"; char *text = "unknown";
@@ -667,29 +660,36 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
int mtu_len = 0; int mtu_len = 0;
int frame_type = 0; int frame_type = 0;
uint8_t next_poll_station = 0; uint8_t next_poll_station = 0;
uint8_t next_poll_neighbor = 0; uint8_t next_this_station = 0;
uint8_t next_station = 0; uint8_t next_next_station = 0;
uint16_t my_timeout = 10, ns_timeout = 0;
static MSTP_MASTER_STATE master_state = MSTP_MASTER_STATE_INITIALIZE;
/* some calculations that several states need */ /* some calculations that several states need */
next_poll_station = (mstp_port->Poll_Station + 1) % next_poll_station = (mstp_port->Poll_Station + 1) %
(mstp_port->Nmax_master + 1); (mstp_port->Nmax_master + 1);
next_poll_neighbor = (mstp_port->This_Station + 1) % next_this_station = (mstp_port->This_Station + 1) %
(mstp_port->Nmax_master + 1); (mstp_port->Nmax_master + 1);
next_station = (mstp_port->Next_Station + 1) % next_next_station = (mstp_port->Next_Station + 1) %
(mstp_port->Nmax_master + 1); (mstp_port->Nmax_master + 1);
#if PRINT_ENABLED_MASTER #if PRINT_ENABLED_MASTER
fprintf(stderr,"MSTP: State=%s TS=%u NS=%u PS=%u EC=%u TC=%u Silence=%u\r\n", if (mstp_port->master_state != master_state)
mstp_master_state_text(mstp_port->master_state), {
mstp_port->This_Station, master_state = mstp_port->master_state;
mstp_port->Next_Station, fprintf(stderr,
mstp_port->Poll_Station, "MSTP: TS=%02X[%02X] NS=%02X[%02X] PS=%02X[%02X] EC=%u TC=%u ST=%u %s\r\n",
mstp_port->EventCount, mstp_port->This_Station,
mstp_port->TokenCount, next_this_station,
mstp_port->SilenceTimer); mstp_port->Next_Station,
fprintf(stderr,"MSTP: NextPollStation=%u NextPollNeighbor=%u NextStation=%u\r\n", next_next_station,
next_poll_station, mstp_port->Poll_Station,
next_poll_neighbor, next_poll_station,
next_station); mstp_port->EventCount,
mstp_port->TokenCount,
mstp_port->SilenceTimer,
mstp_master_state_text(mstp_port->master_state));
}
#endif #endif
switch (mstp_port->master_state) { switch (mstp_port->master_state) {
@@ -718,119 +718,75 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
else if (mstp_port->ReceivedInvalidFrame == true) { else if (mstp_port->ReceivedInvalidFrame == true) {
/* invalid frame was received */ /* invalid frame was received */
mstp_port->ReceivedInvalidFrame = false; mstp_port->ReceivedInvalidFrame = false;
/* wait for the next frame */ /* wait for the next frame - remain in IDLE */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
} }
else if (mstp_port->ReceivedValidFrame == true) { else if (mstp_port->ReceivedValidFrame == true) {
#if PRINT_ENABLED #if PRINT_ENABLED_MASTER
fprintf(stderr,"MSTP: ReceivedValidFrame Type=%s Dest=%02X\r\n", fprintf(stderr,
mstp_frame_type_text(mstp_port->FrameType), "MSTP: ReceivedValidFrame Src=%02X Dest=%02X DataLen=%u FC=%u Type=%s\r\n",
mstp_port->DestinationAddress); mstp_port->SourceAddress,
mstp_port->DestinationAddress,
mstp_port->DataLength,
mstp_port->FrameCount,
mstp_frame_type_text(mstp_port->FrameType));
#endif #endif
/* ReceivedUnwantedFrame - not for me */ /* destined for me! */
if (!((mstp_port->DestinationAddress == mstp_port->This_Station) if ((mstp_port->DestinationAddress ==
|| (mstp_port->DestinationAddress == mstp_port->This_Station) ||
MSTP_BROADCAST_ADDRESS))) { (mstp_port->DestinationAddress ==
/* an unexpected or unwanted frame was received. */ MSTP_BROADCAST_ADDRESS)) {
mstp_port->ReceivedValidFrame = false; switch (mstp_port->FrameType)
/* wait for the next frame */ {
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; /* ReceivedToken */
} case FRAME_TYPE_TOKEN:
/* ReceivedUnwantedFrame - broadcast TOKEN or TEST_REQUEST */ /* tokens can't be broadcast */
/* DestinationAddress is equal to 255 (broadcast) and */ if (mstp_port->DestinationAddress ==
/* FrameType has a value of Token, BACnet Data Expecting Reply, Test_Request, */ MSTP_BROADCAST_ADDRESS)
/* or a proprietary type known to this node that expects a reply */ break;
/* (such frames may not be broadcast), or */ mstp_port->ReceivedValidFrame = false;
else if ((mstp_port->DestinationAddress == mstp_port->FrameCount = 0;
MSTP_BROADCAST_ADDRESS) mstp_port->SoleMaster = false;
&& ((mstp_port->FrameType == FRAME_TYPE_TOKEN) mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
/* removed in Add-2004-135b-PR1 - see BroadcastDataNeedingReply break;
|| (mstp_port->FrameType == /* ReceivedPFM */
FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) */ case FRAME_TYPE_POLL_FOR_MASTER:
|| (mstp_port->FrameType == FRAME_TYPE_TEST_REQUEST))) { MSTP_Create_And_Send_Frame(mstp_port,
/* an unexpected or unwanted frame was received. */ FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER,
mstp_port->ReceivedValidFrame = false; mstp_port->SourceAddress, mstp_port->This_Station,
/* wait for the next frame */ NULL, 0);
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; break;
} case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
/* ReceivedUnwantedFrame - PROPRIETARY unknown to me */ /* indicate successful reception to the higher layers */
/* FrameType has a value that indicates a standard or proprietary type */ dlmstp_put_receive(
/* that is not known to this node. */ mstp_port->SourceAddress,
/* FIXME: change this if you add a proprietary type */ (uint8_t *) & mstp_port->InputBuffer[0],
else if /*( */ (mstp_port->FrameType >= mstp_port->DataLength);
FRAME_TYPE_PROPRIETARY_MIN) { /*&& */ break;
/*(FrameType <= FRAME_TYPE_PROPRIETARY_MAX)) */ case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
/* unnecessary if FrameType is uint8_t with max of 255 */ mstp_port->ReplyPostponedTimer = 0;
/* an unexpected or unwanted frame was received. */ /* indicate successful reception to the higher layers */
mstp_port->ReceivedValidFrame = false; dlmstp_put_receive(
/* wait for the next frame */ mstp_port->SourceAddress, /* source MS/TP address */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; (uint8_t *) & mstp_port->InputBuffer[0],
} mstp_port->DataLength);
/* ReceivedToken */ /* broadcast DER just remains IDLE */
else if ((mstp_port->DestinationAddress == if (mstp_port->DestinationAddress !=
mstp_port->This_Station) MSTP_BROADCAST_ADDRESS)
&& (mstp_port->FrameType == FRAME_TYPE_TOKEN)) { mstp_port->master_state =
mstp_port->ReceivedValidFrame = false; MSTP_MASTER_STATE_ANSWER_DATA_REQUEST;
mstp_port->FrameCount = 0; break;
mstp_port->SoleMaster = false; case FRAME_TYPE_TEST_REQUEST:
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; MSTP_Create_And_Send_Frame(mstp_port,
} FRAME_TYPE_TEST_RESPONSE,
/* ReceivedPFM */ mstp_port->SourceAddress, mstp_port->This_Station,
else if ((mstp_port->DestinationAddress == NULL, 0);
mstp_port->This_Station) break;
&& (mstp_port->FrameType == FRAME_TYPE_POLL_FOR_MASTER)) { case FRAME_TYPE_TEST_RESPONSE:
MSTP_Create_And_Send_Frame(mstp_port, default:
FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER, break;
mstp_port->SourceAddress, mstp_port->This_Station, }
NULL, 0); }
mstp_port->ReceivedValidFrame = false; mstp_port->ReceivedValidFrame = false;
/* wait for the next frame */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
}
/* ReceivedDataNoReply */
/* or a proprietary type known to this node that does not expect a reply */
else if (((mstp_port->DestinationAddress ==
mstp_port->This_Station)
|| (mstp_port->DestinationAddress ==
MSTP_BROADCAST_ADDRESS))
&& ((mstp_port->FrameType ==
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY) ||
/* (mstp_port->FrameType == FRAME_TYPE_PROPRIETARY_0) || */
(mstp_port->FrameType == FRAME_TYPE_TEST_RESPONSE))) {
/* indicate successful reception to the higher layers */
mstp_put_receive(mstp_port);
mstp_port->ReceivedValidFrame = false;
/* wait for the next frame */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
}
/* ReceivedDataNeedingReply */
/* or a proprietary type known to this node that expects a reply */
else if ((mstp_port->DestinationAddress ==
mstp_port->This_Station)
&& ((mstp_port->FrameType ==
FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) ||
/* (mstp_port->FrameType == FRAME_TYPE_PROPRIETARY) || */
(mstp_port->FrameType == FRAME_TYPE_TEST_REQUEST))) {
mstp_port->ReplyPostponedTimer = 0;
/* indicate successful reception to the higher layers */
/* (management entity in the case of Test_Request); */
mstp_put_receive(mstp_port);
mstp_port->ReceivedValidFrame = false;
mstp_port->master_state =
MSTP_MASTER_STATE_ANSWER_DATA_REQUEST;
}
/* BroadcastDataNeedingReply */
else if ((mstp_port->DestinationAddress ==
MSTP_BROADCAST_ADDRESS)
&& (mstp_port->FrameType ==
FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY))
{
/* indicate successful reception to the higher layers */
mstp_put_receive(mstp_port);
mstp_port->ReceivedValidFrame = false;
/* wait for the next frame */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
}
} }
break; break;
/* In the USE_TOKEN state, the node is allowed to send one or */ /* In the USE_TOKEN state, the node is allowed to send one or */
@@ -850,31 +806,31 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
mstp_port, mstp_port,
(uint8_t *) &mstp_port->TxBuffer[0], (uint8_t *) &mstp_port->TxBuffer[0],
mstp_port->TxLength); mstp_port->TxLength);
mstp_port->TxReady = false;
mstp_port->FrameCount++; mstp_port->FrameCount++;
/* SendNoWait */ switch (mstp_port->TxFrameType)
/* There is a frame awaiting transmission that */
/* is of type Test_Response, BACnet Data Not Expecting Reply, */
/* or a proprietary type that does not expect a reply, */
if ((mstp_port->TxFrameType == FRAME_TYPE_TEST_RESPONSE) ||
(mstp_port->TxFrameType == FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY) ||
((mstp_port->TxFrameType == FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) &&
(destination == MSTP_BROADCAST_ADDRESS)))
{ {
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; /* SendAndWait */
} case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
/* SendAndWait */ if (destination == MSTP_BROADCAST_ADDRESS)
/* If there is a frame awaiting transmission that is of */ mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
/* type Test_Request, BACnet Data Expecting Reply, or */ else
/* a proprietary type that expects a reply, */ mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY;
else if ((mstp_port->TxFrameType == FRAME_TYPE_TEST_REQUEST) || break;
(mstp_port->TxFrameType == FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY)) case FRAME_TYPE_TEST_REQUEST:
{ mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY;
mstp_port->master_state = MSTP_MASTER_STATE_WAIT_FOR_REPLY; break;
/* SendNoWait */
case FRAME_TYPE_TEST_RESPONSE:
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
default:
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
break;
} }
mstp_port->TxReady = false;
} }
/* In the WAIT_FOR_REPLY state, the node waits for */ break;
/* a reply from another node. */ /* In the WAIT_FOR_REPLY state, the node waits for */
/* a reply from another node. */
case MSTP_MASTER_STATE_WAIT_FOR_REPLY: case MSTP_MASTER_STATE_WAIT_FOR_REPLY:
/* ReplyTimeout */ /* ReplyTimeout */
if (mstp_port->SilenceTimer >= Treply_timeout) { if (mstp_port->SilenceTimer >= Treply_timeout) {
@@ -903,7 +859,10 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
(mstp_port->FrameType == (mstp_port->FrameType ==
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY))) { FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY))) {
/* indicate successful reception to the higher layers */ /* indicate successful reception to the higher layers */
mstp_put_receive(mstp_port); dlmstp_put_receive(
mstp_port->SourceAddress, /* source MS/TP address */
(uint8_t *) & mstp_port->InputBuffer[0],
mstp_port->DataLength);
mstp_port->ReceivedValidFrame = false; mstp_port->ReceivedValidFrame = false;
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN; mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
} }
@@ -954,81 +913,75 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* before passing the token. */ /* before passing the token. */
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
} }
/* SoleMaster */ /* Npoll changed in Errata SSPC-135-2004 */
else if ((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) && else if (mstp_port->TokenCount < (Npoll-1))
/* Npoll changed in Errata SSPC-135-2004 */ {
(mstp_port->TokenCount < (Npoll-1)) && if ((mstp_port->SoleMaster == true) &&
(mstp_port->SoleMaster == true)) { (mstp_port->Next_Station != next_this_station)) {
/* there are no other known master nodes to */ /* SoleMaster */
/* which the token may be sent (true master-slave operation). */ /* there are no other known master nodes to */
mstp_port->FrameCount = 0; /* which the token may be sent (true master-slave operation). */
mstp_port->TokenCount++; mstp_port->FrameCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN; mstp_port->TokenCount++;
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
}
else {
/* SendToken */
/* Npoll changed in Errata SSPC-135-2004 */
/* The comparison of NS and TS+1 eliminates the Poll For Master */
/* if there are no addresses between TS and NS, since there is no */
/* address at which a new master node may be found in that case. */
mstp_port->TokenCount++;
/* transmit a Token frame to NS */
MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_TOKEN,
mstp_port->Next_Station,
mstp_port->This_Station, NULL, 0);
mstp_port->RetryCount = 0;
mstp_port->EventCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
}
} }
/* SendToken */ else if (next_poll_station == mstp_port->Next_Station) {
else if (((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) && if (mstp_port->SoleMaster == true) {
/* Npoll changed in Errata SSPC-135-2004 */ /* SoleMasterRestartMaintenancePFM */
(mstp_port->TokenCount < (Npoll-1)) && mstp_port->Poll_Station = next_poll_station;
(mstp_port->SoleMaster == false)) || MSTP_Create_And_Send_Frame(mstp_port,
/* The comparison of NS and TS+1 eliminates the Poll For Master */ FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station,
/* if there are no addresses between TS and NS, since there is no */ mstp_port->This_Station, NULL, 0);
/* address at which a new master node may be found in that case. */ /* no known successor node */
(mstp_port->Next_Station == next_poll_neighbor)) { mstp_port->Next_Station = mstp_port->This_Station;
mstp_port->TokenCount++; mstp_port->RetryCount = 0;
/* transmit a Token frame to NS */ mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */
MSTP_Create_And_Send_Frame(mstp_port, /* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */
FRAME_TYPE_TOKEN, /* find a new successor to TS */
mstp_port->Next_Station, mstp_port->This_Station, NULL, 0); mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
mstp_port->RetryCount = 0; }
mstp_port->EventCount = 0; else {
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN; /* ResetMaintenancePFM */
mstp_port->Poll_Station = mstp_port->This_Station;
/* transmit a Token frame to NS */
MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_TOKEN,
mstp_port->Next_Station,
mstp_port->This_Station, NULL, 0);
mstp_port->RetryCount = 0;
mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */
mstp_port->EventCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
}
} }
/* SendMaintenancePFM */ else {
else if ((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) && /* SendMaintenancePFM */
/* Npoll changed in Errata SSPC-135-2004 */
(mstp_port->TokenCount >= (Npoll-1)) &&
(next_poll_station != mstp_port->Next_Station)) {
mstp_port->Poll_Station = next_poll_station; mstp_port->Poll_Station = next_poll_station;
MSTP_Create_And_Send_Frame(mstp_port, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station, FRAME_TYPE_POLL_FOR_MASTER,
mstp_port->Poll_Station,
mstp_port->This_Station, NULL, 0); mstp_port->This_Station, NULL, 0);
mstp_port->RetryCount = 0; mstp_port->RetryCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER; mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
} }
/* ResetMaintenancePFM */ break;
else if ((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) &&
/* Npoll changed in Errata SSPC-135-2004 */
(mstp_port->TokenCount >= (Npoll-1)) &&
(next_poll_station == mstp_port->Next_Station)
&& (mstp_port->SoleMaster == false)) {
mstp_port->Poll_Station = mstp_port->This_Station;
/* transmit a Token frame to NS */
MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_TOKEN,
mstp_port->Next_Station, mstp_port->This_Station, NULL, 0);
mstp_port->RetryCount = 0;
mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */
mstp_port->EventCount = 0;
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
}
/* SoleMasterRestartMaintenancePFM */
else if ((mstp_port->FrameCount >= mstp_port->Nmax_info_frames) &&
/* Npoll changed in Errata SSPC-135-2004 */
(mstp_port->TokenCount >= (Npoll-1)) &&
(next_poll_station == mstp_port->Next_Station)
&& (mstp_port->SoleMaster == true)) {
mstp_port->Poll_Station = next_poll_station;
MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_POLL_FOR_MASTER, mstp_port->Poll_Station,
mstp_port->This_Station, NULL, 0);
/* no known successor node */
mstp_port->Next_Station = mstp_port->This_Station;
mstp_port->RetryCount = 0;
mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */
/* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */
/* find a new successor to TS */
mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
}
/* The PASS_TOKEN state listens for a successor to begin using */ /* The PASS_TOKEN state listens for a successor to begin using */
/* the token that this node has just attempted to pass. */ /* the token that this node has just attempted to pass. */
case MSTP_MASTER_STATE_PASS_TOKEN: case MSTP_MASTER_STATE_PASS_TOKEN:
@@ -1055,7 +1008,7 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
else if ((mstp_port->SilenceTimer >= Tusage_timeout) && else if ((mstp_port->SilenceTimer >= Tusage_timeout) &&
(mstp_port->RetryCount >= Nretry_token)) { (mstp_port->RetryCount >= Nretry_token)) {
/* Assume that NS has failed. */ /* Assume that NS has failed. */
mstp_port->Poll_Station = next_station; mstp_port->Poll_Station = next_next_station;
/* Transmit a Poll For Master frame to PS. */ /* Transmit a Poll For Master frame to PS. */
MSTP_Create_And_Send_Frame(mstp_port, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_POLL_FOR_MASTER, FRAME_TYPE_POLL_FOR_MASTER,
@@ -1074,22 +1027,21 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* for that period of time. The timeout is continued to determine */ /* for that period of time. The timeout is continued to determine */
/* whether or not this node may create a token. */ /* whether or not this node may create a token. */
case MSTP_MASTER_STATE_NO_TOKEN: case MSTP_MASTER_STATE_NO_TOKEN:
my_timeout = Tno_token + (Tslot * mstp_port->This_Station);
ns_timeout = Tno_token + (Tslot * (mstp_port->This_Station + 1));
/* SawFrame */ /* SawFrame */
if ((mstp_port->SilenceTimer < if ((mstp_port->SilenceTimer < my_timeout) &&
(Tno_token + (Tslot * mstp_port->This_Station))) (mstp_port->EventCount > Nmin_octets)) {
&& (mstp_port->EventCount > Nmin_octets)) {
/* Some other node exists at a lower address. */ /* Some other node exists at a lower address. */
/* Enter the IDLE state to receive and process the incoming frame. */ /* Enter the IDLE state to receive and process the incoming frame. */
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
} }
/* GenerateToken */ /* GenerateToken */
else if ((mstp_port->SilenceTimer >= else if ((mstp_port->SilenceTimer >= my_timeout) &&
(Tno_token + (Tslot * mstp_port->This_Station))) (mstp_port->SilenceTimer < ns_timeout)) {
&& (mstp_port->SilenceTimer <
(Tno_token + (Tslot * (mstp_port->This_Station + 1))))) {
/* Assume that this node is the lowest numerical address */ /* Assume that this node is the lowest numerical address */
/* on the network and is empowered to create a token. */ /* on the network and is empowered to create a token. */
mstp_port->Poll_Station = next_poll_neighbor; mstp_port->Poll_Station = next_this_station;
/* Transmit a Poll For Master frame to PS. */ /* Transmit a Poll For Master frame to PS. */
MSTP_Create_And_Send_Frame(mstp_port, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_POLL_FOR_MASTER, FRAME_TYPE_POLL_FOR_MASTER,
@@ -1203,7 +1155,14 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* (the mechanism used to determine this is a local matter), */ /* (the mechanism used to determine this is a local matter), */
/* then call MSTP_Create_And_Send_Frame to transmit the reply frame */ /* then call MSTP_Create_And_Send_Frame to transmit the reply frame */
/* and enter the IDLE state to wait for the next frame. */ /* and enter the IDLE state to wait for the next frame. */
if ((mstp_port->FrameType == FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY) &&
(mstp_port->TxReady)) {
RS485_Send_Frame(
mstp_port,
(uint8_t *) &mstp_port->TxBuffer[0],
mstp_port->TxLength);
mstp_port->TxReady = false;
}
/* Test Request */ /* Test Request */
/* If a receiving node can successfully receive and return */ /* If a receiving node can successfully receive and return */
/* the information field, it shall do so. If it cannot receive */ /* the information field, it shall do so. If it cannot receive */
@@ -1215,17 +1174,16 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* no information field. If the receiving node cannot detect */ /* no information field. If the receiving node cannot detect */
/* the valid reception of frames with overlength information fields, */ /* the valid reception of frames with overlength information fields, */
/* then no response shall be returned. */ /* then no response shall be returned. */
if (mstp_port->FrameType == FRAME_TYPE_TEST_REQUEST) { else if (mstp_port->FrameType == FRAME_TYPE_TEST_REQUEST) {
MSTP_Create_And_Send_Frame(mstp_port, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_TEST_RESPONSE, FRAME_TYPE_TEST_RESPONSE,
mstp_port->SourceAddress, mstp_port->SourceAddress,
mstp_port->This_Station, mstp_port->This_Station,
(uint8_t *) & mstp_port->InputBuffer[0], (uint8_t *) & mstp_port->InputBuffer[0],
mstp_port->Index); mstp_port->DataLength);
} }
mstp_port->master_state = MSTP_MASTER_STATE_IDLE; mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
} }
/* */
/* DeferredReply */ /* DeferredReply */
/* If no reply will be available from the higher layers */ /* If no reply will be available from the higher layers */
/* within Treply_delay after the reception of the */ /* within Treply_delay after the reception of the */
@@ -1235,7 +1193,6 @@ void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
/* Any reply shall wait until this node receives the token. */ /* Any reply shall wait until this node receives the token. */
/* Call MSTP_Create_And_Send_Frame to transmit a Reply Postponed frame, */ /* Call MSTP_Create_And_Send_Frame to transmit a Reply Postponed frame, */
/* and enter the IDLE state. */ /* and enter the IDLE state. */
else { else {
MSTP_Create_And_Send_Frame(mstp_port, MSTP_Create_And_Send_Frame(mstp_port,
FRAME_TYPE_REPLY_POSTPONED, FRAME_TYPE_REPLY_POSTPONED,
@@ -1289,6 +1246,16 @@ void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port,
mstp_port->This_Station = this_station_mac; mstp_port->This_Station = this_station_mac;
mstp_port->Nmax_info_frames = DEFAULT_MAX_INFO_FRAMES; mstp_port->Nmax_info_frames = DEFAULT_MAX_INFO_FRAMES;
mstp_port->Nmax_master = DEFAULT_MAX_MASTER; mstp_port->Nmax_master = DEFAULT_MAX_MASTER;
/* An array of octets, used to store PDU octets prior to being transmitted. */
/* This array is only used for APDU messages */
for (i = 0; i < sizeof(mstp_port->TxBuffer); i++) {
mstp_port->TxBuffer[i] = 0;
}
mstp_port->TxLength = 0;
mstp_port->TxReady = false;
mstp_port->TxFrameType = 0;
} }
} }
+10 -7
View File
@@ -224,14 +224,17 @@ extern "C" {
*mstp_port); *mstp_port);
void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t
*mstp_port); *mstp_port);
/* returns true if line is active */
bool MSTP_Line_Active(volatile struct mstp_port_struct_t *mstp_port);
unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */ unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */
unsigned buffer_len, /* amount of space available */ unsigned buffer_len, /* amount of space available */
uint8_t frame_type, /* type of frame to send - see defines */ uint8_t frame_type, /* type of frame to send - see defines */
uint8_t destination, /* destination address */ uint8_t destination, /* destination address */
uint8_t source, /* source address */ uint8_t source, /* source address */
uint8_t * data, /* any data to be sent - may be null */ uint8_t * data, /* any data to be sent - may be null */
unsigned data_len); /* number of bytes of data (up to 501) */ unsigned data_len); /* number of bytes of data (up to 501) */
#ifdef __cplusplus #ifdef __cplusplus
+10 -9
View File
@@ -111,8 +111,9 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
void dlmstp_task(void) void dlmstp_task(void)
{ {
RS485_Check_UART_Data(&MSTP_Port); RS485_Check_UART_Data(&MSTP_Port);
MSTP_Receive_Frame_FSM(&MSTP_Port); MSTP_Receive_Frame_FSM(&MSTP_Port);
MSTP_Master_Node_FSM(&MSTP_Port); if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE)
MSTP_Master_Node_FSM(&MSTP_Port);
} }
/* called about once a millisecond */ /* called about once a millisecond */
@@ -175,17 +176,17 @@ uint16_t dlmstp_put_receive(
uint8_t * pdu, /* PDU data */ uint8_t * pdu, /* PDU data */
uint16_t pdu_len) uint16_t pdu_len)
{ {
if (Receive_Buffer.ready) if (Receive_Buffer.ready) {
{
/* FIXME: what to do when we miss a message? */ /* FIXME: what to do when we miss a message? */
pdu_len = 0; pdu_len = 0;
} } else if (pdu_len < sizeof(Receive_Buffer.pdu)) {
else
{
dlmstp_fill_bacnet_address(&Receive_Buffer.address, src); dlmstp_fill_bacnet_address(&Receive_Buffer.address, src);
Receive_Buffer.pdu_len = pdu_len; Receive_Buffer.pdu_len = pdu_len;
memmove(Receive_Buffer.pdu, pdu, sizeof(Receive_Buffer.pdu)); memmove(Receive_Buffer.pdu, pdu, pdu_len);
Receive_Buffer.ready = true; Receive_Buffer.ready = true;
} else {
/* FIXME: message too large? */
pdu_len = 0;
} }
return pdu_len; return pdu_len;
-2
View File
@@ -161,10 +161,8 @@ int main(int argc, char *argv[])
#ifdef BACDL_MSTP #ifdef BACDL_MSTP
dlmstp_task(); dlmstp_task();
#endif #endif
#if (defined(BACDL_ETHERNET) || defined(BACDL_BIP))
/* returns 0 bytes on timeout */ /* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
#endif
/* process */ /* process */
if (pdu_len) { if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len); npdu_handler(&src, &Rx_Buf[0], pdu_len);
+2 -1
View File
@@ -37,7 +37,8 @@ COMPort COM1 115200 // use COM1 with 115200 baud
VideoRAM = None // program output sent to debugger - clrscr() crashes it. VideoRAM = None // program output sent to debugger - clrscr() crashes it.
#elifdef DEBUGCOM3 #elifdef DEBUGCOM3
COMPort COM3 115200 9 // use COM3 IRQ9 115200 baud - Everex EV170 serial card COMPort COM3 115200 9 // use COM3 IRQ9 115200 baud - Everex EV170 serial card
VideoRAM = ColorText // program output sent to debugger - clrscr() crashes it. //VideoRAM = ColorText // program output sent to Graphic Card
VideoRAM = None // program output sent to debugger - clrscr() crashes it.
#else #else
COMPort COM3 115200 9 // use COM3 IRQ9 115200 baud - Everex EV170 serial card COMPort COM3 115200 9 // use COM3 IRQ9 115200 baud - Everex EV170 serial card
VideoRAM = ColorText // program output sent to Graphic Card VideoRAM = ColorText // program output sent to Graphic Card
+5 -4
View File
@@ -22,12 +22,13 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
*********************************************************************/ *********************************************************************/
#define PRINT_ENABLED_RS485 0
#include <stdint.h> #include <stdint.h>
#include <rtkernel.h> #include <rtkernel.h>
#include <rtcom.h> #include <rtcom.h>
#include <itimer.h> #include <itimer.h>
#if PRINT_ENABLED #if PRINT_ENABLED_RS485
#include <stdio.h> #include <stdio.h>
#endif #endif
#include "mstp.h" #include "mstp.h"
@@ -41,7 +42,7 @@
/* COM port number - COM1 = 0 */ /* COM port number - COM1 = 0 */
static int RS485_Port = COM2; static int RS485_Port = COM2;
/* baud rate */ /* baud rate */
static long RS485_Baud = 38400; static long RS485_Baud = 9600;
/* io base address */ /* io base address */
static long RS485_Base = 0; static long RS485_Base = 0;
/* hardware IRQ number */ /* hardware IRQ number */
@@ -111,7 +112,7 @@ static RS485_Open_Port(int port, /* COM port number - COM1 = 0 */
/* enable the 485 via the DTR pin */ /* enable the 485 via the DTR pin */
RS485_IO_ENABLE(port); RS485_IO_ENABLE(port);
RS485_RECEIVE_ENABLE(port); RS485_RECEIVE_ENABLE(port);
#if PRINT_ENABLED #if PRINT_ENABLED_RS485
fprintf(stderr,"RS485: COM%d Enabled\r\n",port+1); fprintf(stderr,"RS485: COM%d Enabled\r\n",port+1);
#endif #endif
@@ -139,7 +140,7 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
while (!(LineStatus(RS485_Port) & TX_SHIFT_EMPTY)) while (!(LineStatus(RS485_Port) & TX_SHIFT_EMPTY))
RTKScheduler(); RTKScheduler();
RS485_RECEIVE_ENABLE(RS485_Port); RS485_RECEIVE_ENABLE(RS485_Port);
#if PRINT_ENABLED #if PRINT_ENABLED_RS485
{ {
int i = 0; int i = 0;
fprintf(stderr,"RS485 Tx:"); fprintf(stderr,"RS485 Tx:");
+2 -1
View File
@@ -30,7 +30,8 @@
Locate DiskBuffer DiskIO LowMem 16k 16k // needed by disk boot code Locate DiskBuffer DiskIO LowMem 16k 16k // needed by disk boot code
NoFPU=0 // Check FPU NoFPU=0 // Check FPU
CPL = 3 // normal priveleges CPL = 3 // normal priveleges
VideoRAM ColorText // program output sent to Graphic Card // VideoRAM ColorText // program output sent to Graphic Card
VideoRAM None // program output sent to file and host
#endif #endif
FillRAM HeapMem // remap unused RAM FillRAM HeapMem // remap unused RAM