/** Blocking receive frame function. Calls ec_waitinframe_red(). * @param[in] idx = requested index of frame * @param[in] timeout = timeout in us * @return Workcounter if a frame is found with corresponding index, otherwise * EC_NOFRAME. */ int ecx_waitinframe(ecx_portt *port, int idx, int timeout) { int wkc; osal_timert timer; if (timeout == 0 && (port->redstate == ECT_RED_NONE)) { int loop_cnt = 0; /* Allow us to consume MAX buffer number of frames */ do { wkc = ecx_inframe(port, idx, 0); loop_cnt++; } while (wkc <= EC_NOFRAME && (loop_cnt <= EC_MAXBUF)); } else { osal_timer_start (&timer, timeout); wkc = ecx_waitinframe_red(port, idx, &timer); } return wkc; }
int ec_inframe(int idx, int stacknumber) { return ecx_inframe(&ecx_port, idx, stacknumber); }
/** Blocking redundant receive frame function. If redundant mode is not active then * it skips the secondary stack and redundancy functions. In redundant mode it waits * for both (primary and secondary) frames to come in. The result goes in an decision * tree that decides, depending on the route of the packet and its possible missing arrival, * how to reroute the original packet to get the data in an other try. * * @param[in] port = port context struct * @param[in] idx = requested index of frame * @param[in] timer = absolute timeout time * @return Workcounter if a frame is found with corresponding index, otherwise * EC_NOFRAME. */ static int ecx_waitinframe_red(ecx_portt *port, int idx, osal_timert timer) { int wkc = EC_NOFRAME; int wkc2 = EC_NOFRAME; int primrx, secrx; /* if not in redundant mode then always assume secondary is OK */ if (port->redstate == ECT_RED_NONE) { wkc2 = 0; } do { /* only read frame if not already in */ if (wkc <= EC_NOFRAME) { wkc = ecx_inframe(port, idx, 0); } /* only try secondary if in redundant mode */ if (port->redstate != ECT_RED_NONE) { /* only read frame if not already in */ if (wkc2 <= EC_NOFRAME) wkc2 = ecx_inframe(port, idx, 1); } /* wait for both frames to arrive or timeout */ } while (((wkc <= EC_NOFRAME) || (wkc2 <= EC_NOFRAME)) && (osal_timer_is_expired(&timer) == FALSE)); /* only do redundant functions when in redundant mode */ if (port->redstate != ECT_RED_NONE) { /* primrx if the reveived MAC source on primary socket */ primrx = 0; if (wkc > EC_NOFRAME) { primrx = port->rxsa[idx]; } /* secrx if the reveived MAC source on psecondary socket */ secrx = 0; if (wkc2 > EC_NOFRAME) { secrx = port->redport->rxsa[idx]; } /* primary socket got secondary frame and secondary socket got primary frame */ /* normal situation in redundant mode */ if ( ((primrx == RX_SEC) && (secrx == RX_PRIM)) ) { /* copy secondary buffer to primary */ memcpy(&(port->rxbuf[idx]), &(port->redport->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE); wkc = wkc2; } /* primary socket got nothing or primary frame, and secondary socket got secondary frame */ /* we need to resend TX packet */ if ( ((primrx == 0) && (secrx == RX_SEC)) || ((primrx == RX_PRIM) && (secrx == RX_SEC)) ) { osal_timert read_timer; /* If both primary and secondary have partial connection retransmit the primary received * frame over the secondary socket. The result from the secondary received frame is a combined * frame that traversed all slaves in standard order. */ if ( (primrx == RX_PRIM) && (secrx == RX_SEC) ) { /* copy primary rx to tx buffer */ memcpy(&(port->txbuf[idx][ETH_HEADERSIZE]), &(port->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE); } osal_timer_start(&read_timer, EC_TIMEOUTRET); /* resend secondary tx */ ecx_outframe(port, idx, 1); do { /* retrieve frame */ wkc2 = ecx_inframe(port, idx, 1); } while ((wkc2 <= EC_NOFRAME) && (osal_timer_is_expired(&read_timer) == FALSE)); if (wkc2 > EC_NOFRAME) { /* copy secondary result to primary rx buffer */ memcpy(&(port->rxbuf[idx]), &(port->redport->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE); wkc = wkc2; } } } /* return WKC or EC_NOFRAME */ return wkc; }