SOEM EtherCAT Master library for STM Nucleo F767ZI

Dependents:   EasyCAT_LAB_simple EasyCAT_LAB_very_simple EasyCAT_LAB

  • It has been developed for the EasyCAT LAB , a complete educational and experimental EtherCAT® system, composed of one master and two slaves .

Warning

/media/uploads/EasyCAT/easycat_lab.jpg

Committer:
EasyCAT
Date:
Tue Jun 11 10:29:09 2019 +0000
Revision:
0:543d6784d4cc
SOEM EtherCAT Master Library for STM Nucleo F767ZI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
EasyCAT 0:543d6784d4cc 1 /*
EasyCAT 0:543d6784d4cc 2 * Licensed under the GNU General Public License version 2 with exceptions. See
EasyCAT 0:543d6784d4cc 3 * LICENSE file in the project root for full license information
EasyCAT 0:543d6784d4cc 4 */
EasyCAT 0:543d6784d4cc 5
EasyCAT 0:543d6784d4cc 6 /** \file
EasyCAT 0:543d6784d4cc 7 * \brief
EasyCAT 0:543d6784d4cc 8 * EtherCAT RAW socket driver.
EasyCAT 0:543d6784d4cc 9 *
EasyCAT 0:543d6784d4cc 10 * Low level interface functions to send and receive EtherCAT packets.
EasyCAT 0:543d6784d4cc 11 * EtherCAT has the property that packets are only send by the master,
EasyCAT 0:543d6784d4cc 12 * and the send packets always return in the receive buffer.
EasyCAT 0:543d6784d4cc 13 * There can be multiple packets "on the wire" before they return.
EasyCAT 0:543d6784d4cc 14 * To combine the received packets with the original send packets a buffer
EasyCAT 0:543d6784d4cc 15 * system is installed. The identifier is put in the index item of the
EasyCAT 0:543d6784d4cc 16 * EtherCAT header. The index is stored and compared when a frame is received.
EasyCAT 0:543d6784d4cc 17 * If there is a match the packet can be combined with the transmit packet
EasyCAT 0:543d6784d4cc 18 * and returned to the higher level function.
EasyCAT 0:543d6784d4cc 19 *
EasyCAT 0:543d6784d4cc 20 * The socket layer can exhibit a reversal in the packet order (rare).
EasyCAT 0:543d6784d4cc 21 * If the Tx order is A-B-C the return order could be A-C-B. The indexed buffer
EasyCAT 0:543d6784d4cc 22 * will reorder the packets automatically.
EasyCAT 0:543d6784d4cc 23 *
EasyCAT 0:543d6784d4cc 24 * The "redundant" option will configure two sockets and two NIC interfaces.
EasyCAT 0:543d6784d4cc 25 * Slaves are connected to both interfaces, one on the IN port and one on the
EasyCAT 0:543d6784d4cc 26 * OUT port. Packets are send via both interfaces. Any one of the connections
EasyCAT 0:543d6784d4cc 27 * (also an interconnect) can be removed and the slaves are still serviced with
EasyCAT 0:543d6784d4cc 28 * packets. The software layer will detect the possible failure modes and
EasyCAT 0:543d6784d4cc 29 * compensate. If needed the packets from interface A are resent through interface B.
EasyCAT 0:543d6784d4cc 30 * This layer is fully transparent for the higher layers.
EasyCAT 0:543d6784d4cc 31 */
EasyCAT 0:543d6784d4cc 32
EasyCAT 0:543d6784d4cc 33
EasyCAT 0:543d6784d4cc 34 #include "mbed.h"
EasyCAT 0:543d6784d4cc 35
EasyCAT 0:543d6784d4cc 36 #include <stdio.h>
EasyCAT 0:543d6784d4cc 37 #include <string.h>
EasyCAT 0:543d6784d4cc 38
EasyCAT 0:543d6784d4cc 39 #include "osal.h"
EasyCAT 0:543d6784d4cc 40 #include "oshw.h"
EasyCAT 0:543d6784d4cc 41
EasyCAT 0:543d6784d4cc 42 #ifndef MAX
EasyCAT 0:543d6784d4cc 43 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
EasyCAT 0:543d6784d4cc 44 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
EasyCAT 0:543d6784d4cc 45 #endif
EasyCAT 0:543d6784d4cc 46
EasyCAT 0:543d6784d4cc 47
EasyCAT 0:543d6784d4cc 48
EasyCAT 0:543d6784d4cc 49 /** Redundancy modes */
EasyCAT 0:543d6784d4cc 50 enum
EasyCAT 0:543d6784d4cc 51 {
EasyCAT 0:543d6784d4cc 52 /** No redundancy, single NIC mode */
EasyCAT 0:543d6784d4cc 53 ECT_RED_NONE,
EasyCAT 0:543d6784d4cc 54 /** Double redundant NIC connection */
EasyCAT 0:543d6784d4cc 55 ECT_RED_DOUBLE
EasyCAT 0:543d6784d4cc 56 };
EasyCAT 0:543d6784d4cc 57
EasyCAT 0:543d6784d4cc 58 /** Primary source MAC address used for EtherCAT.
EasyCAT 0:543d6784d4cc 59 * This address is not the MAC address used from the NIC.
EasyCAT 0:543d6784d4cc 60 * EtherCAT does not care about MAC addressing, but it is used here to
EasyCAT 0:543d6784d4cc 61 * differentiate the route the packet traverses through the EtherCAT
EasyCAT 0:543d6784d4cc 62 * segment. This is needed to find out the packet flow in redundant
EasyCAT 0:543d6784d4cc 63 * configurations. */
EasyCAT 0:543d6784d4cc 64 const uint16 priMAC[3] = { 0x0101, 0x0101, 0x0101 };
EasyCAT 0:543d6784d4cc 65 /** Secondary source MAC address used for EtherCAT. */
EasyCAT 0:543d6784d4cc 66 const uint16 secMAC[3] = { 0x0404, 0x0404, 0x0404 };
EasyCAT 0:543d6784d4cc 67
EasyCAT 0:543d6784d4cc 68 /** second MAC word is used for identification */
EasyCAT 0:543d6784d4cc 69 #define RX_PRIM priMAC[1]
EasyCAT 0:543d6784d4cc 70 /** second MAC word is used for identification */
EasyCAT 0:543d6784d4cc 71 #define RX_SEC secMAC[1]
EasyCAT 0:543d6784d4cc 72
EasyCAT 0:543d6784d4cc 73
EasyCAT 0:543d6784d4cc 74
EasyCAT 0:543d6784d4cc 75
EasyCAT 0:543d6784d4cc 76 //******************************************************************************
EasyCAT 0:543d6784d4cc 77 // driver used:
EasyCAT 0:543d6784d4cc 78 // \mbed-os-5.5.7\targets\TARGET_STM\TARGET_STM32F7\device\stm32f7xx_hal_eth.c
EasyCAT 0:543d6784d4cc 79 //******************************************************************************
EasyCAT 0:543d6784d4cc 80
EasyCAT 0:543d6784d4cc 81
EasyCAT 0:543d6784d4cc 82 GPIO_InitTypeDef GPIO_InitStructure;
EasyCAT 0:543d6784d4cc 83
EasyCAT 0:543d6784d4cc 84
EasyCAT 0:543d6784d4cc 85
EasyCAT 0:543d6784d4cc 86 ETH_HandleTypeDef hEth; // ethernet interface handle structure
EasyCAT 0:543d6784d4cc 87
EasyCAT 0:543d6784d4cc 88 ETH_DMADescTypeDef DMATxDescTab[ETH_TXBUFNB]; // dma tx descriptors
EasyCAT 0:543d6784d4cc 89 ETH_DMADescTypeDef DMARxDescTab[ETH_RXBUFNB]; // dma rx descriptors
EasyCAT 0:543d6784d4cc 90
EasyCAT 0:543d6784d4cc 91 uint8_t DmaTxBuff[ETH_TXBUFNB][ETH_MAX_PACKET_SIZE]; // dma tx buffers
EasyCAT 0:543d6784d4cc 92 uint8_t DmaRxBuff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE]; // dma rx buffers
EasyCAT 0:543d6784d4cc 93
EasyCAT 0:543d6784d4cc 94
EasyCAT 0:543d6784d4cc 95
EasyCAT 0:543d6784d4cc 96 HAL_StatusTypeDef HalStatus; // response from Hal functions
EasyCAT 0:543d6784d4cc 97
EasyCAT 0:543d6784d4cc 98
EasyCAT 0:543d6784d4cc 99 //------------------------------------------------------------------------------
EasyCAT 0:543d6784d4cc 100
EasyCAT 0:543d6784d4cc 101 void EthInit()
EasyCAT 0:543d6784d4cc 102 {
EasyCAT 0:543d6784d4cc 103 // HAL status codes
EasyCAT 0:543d6784d4cc 104 //
EasyCAT 0:543d6784d4cc 105 // HAL_OK = 0x00U,
EasyCAT 0:543d6784d4cc 106 // HAL_ERROR = 0x01U,
EasyCAT 0:543d6784d4cc 107 // HAL_BUSY = 0x02U,
EasyCAT 0:543d6784d4cc 108 // HAL_TIMEOUT = 0x03U
EasyCAT 0:543d6784d4cc 109
EasyCAT 0:543d6784d4cc 110
EasyCAT 0:543d6784d4cc 111 uint8_t MACAddr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; // mac address
EasyCAT 0:543d6784d4cc 112
EasyCAT 0:543d6784d4cc 113 hEth.State = HAL_ETH_STATE_RESET; // don't know if it is useful !!!
EasyCAT 0:543d6784d4cc 114
EasyCAT 0:543d6784d4cc 115 hEth.Instance = ETH;
EasyCAT 0:543d6784d4cc 116 hEth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
EasyCAT 0:543d6784d4cc 117 hEth.Init.Speed = ETH_SPEED_100M;
EasyCAT 0:543d6784d4cc 118 hEth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
EasyCAT 0:543d6784d4cc 119 hEth.Init.PhyAddress = 0x00;
EasyCAT 0:543d6784d4cc 120 hEth.Init.MACAddr = &MACAddr[0];
EasyCAT 0:543d6784d4cc 121 hEth.Init.RxMode = ETH_RXPOLLING_MODE;
EasyCAT 0:543d6784d4cc 122 hEth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
EasyCAT 0:543d6784d4cc 123 hEth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
EasyCAT 0:543d6784d4cc 124
EasyCAT 0:543d6784d4cc 125 HalStatus = HAL_ETH_Init(&hEth);
EasyCAT 0:543d6784d4cc 126 NVIC_DisableIRQ(ETH_IRQn); // we don't use interrupt
EasyCAT 0:543d6784d4cc 127 if (HalStatus != HAL_OK)
EasyCAT 0:543d6784d4cc 128 {
EasyCAT 0:543d6784d4cc 129 printf ("HAL_ETH_Init err %d\n", HalStatus);
EasyCAT 0:543d6784d4cc 130 }
EasyCAT 0:543d6784d4cc 131
EasyCAT 0:543d6784d4cc 132 HalStatus = HAL_ETH_DMATxDescListInit(&hEth, &DMATxDescTab[0], &DmaTxBuff[0][0], ETH_TXBUFNB);
EasyCAT 0:543d6784d4cc 133 if (HalStatus != HAL_OK)
EasyCAT 0:543d6784d4cc 134 {
EasyCAT 0:543d6784d4cc 135 printf ("HAL_ETH_DMATxDescListInit err %d\n", HalStatus);
EasyCAT 0:543d6784d4cc 136 }
EasyCAT 0:543d6784d4cc 137
EasyCAT 0:543d6784d4cc 138 HalStatus = HAL_ETH_DMARxDescListInit(&hEth, &DMARxDescTab[0], &DmaRxBuff[0][0], ETH_RXBUFNB);
EasyCAT 0:543d6784d4cc 139 if (HalStatus != HAL_OK)
EasyCAT 0:543d6784d4cc 140 {
EasyCAT 0:543d6784d4cc 141 printf ("HAL_ETH_DMARxDescListInit err %d\n", HalStatus);
EasyCAT 0:543d6784d4cc 142 }
EasyCAT 0:543d6784d4cc 143
EasyCAT 0:543d6784d4cc 144 HalStatus = HAL_ETH_Start(&hEth);
EasyCAT 0:543d6784d4cc 145 if (HalStatus != HAL_OK)
EasyCAT 0:543d6784d4cc 146 {
EasyCAT 0:543d6784d4cc 147 printf ("HAL_ETH_Start err %d\n", HalStatus);
EasyCAT 0:543d6784d4cc 148 }
EasyCAT 0:543d6784d4cc 149 }
EasyCAT 0:543d6784d4cc 150
EasyCAT 0:543d6784d4cc 151 //------------------------------------------------------------------------------
EasyCAT 0:543d6784d4cc 152
EasyCAT 0:543d6784d4cc 153 int EthWrPacket (uint8_t* pBuff, uint16_t Len)
EasyCAT 0:543d6784d4cc 154 {
EasyCAT 0:543d6784d4cc 155 uint8_t* pDmaBuff;
EasyCAT 0:543d6784d4cc 156
EasyCAT 0:543d6784d4cc 157 if ((hEth.TxDesc->Status & ETH_DMATXDESC_OWN) == (uint32_t)RESET)
EasyCAT 0:543d6784d4cc 158
EasyCAT 0:543d6784d4cc 159 {
EasyCAT 0:543d6784d4cc 160 pDmaBuff = (uint8_t*)(hEth.TxDesc->Buffer1Addr);
EasyCAT 0:543d6784d4cc 161
EasyCAT 0:543d6784d4cc 162 memcpy (pDmaBuff, pBuff, Len);
EasyCAT 0:543d6784d4cc 163
EasyCAT 0:543d6784d4cc 164 HalStatus = HAL_ETH_TransmitFrame(&hEth, Len);
EasyCAT 0:543d6784d4cc 165 if (HalStatus != HAL_OK)
EasyCAT 0:543d6784d4cc 166 {
EasyCAT 0:543d6784d4cc 167 printf ("HAL_ETH_TransmitFrame err %d\n", HalStatus);
EasyCAT 0:543d6784d4cc 168 return NULL;
EasyCAT 0:543d6784d4cc 169 }
EasyCAT 0:543d6784d4cc 170
EasyCAT 0:543d6784d4cc 171 return Len;
EasyCAT 0:543d6784d4cc 172 }
EasyCAT 0:543d6784d4cc 173
EasyCAT 0:543d6784d4cc 174 else
EasyCAT 0:543d6784d4cc 175 {
EasyCAT 0:543d6784d4cc 176 return NULL;
EasyCAT 0:543d6784d4cc 177 }
EasyCAT 0:543d6784d4cc 178 }
EasyCAT 0:543d6784d4cc 179
EasyCAT 0:543d6784d4cc 180 //------------------------------------------------------------------------------
EasyCAT 0:543d6784d4cc 181
EasyCAT 0:543d6784d4cc 182 int EthRdPacket(uint8_t* pBuff)
EasyCAT 0:543d6784d4cc 183 {
EasyCAT 0:543d6784d4cc 184 int Len;
EasyCAT 0:543d6784d4cc 185 uint8_t* pDmaBuff;
EasyCAT 0:543d6784d4cc 186
EasyCAT 0:543d6784d4cc 187 HalStatus = HAL_ETH_GetReceivedFrame(&hEth); // check if a packet has been received
EasyCAT 0:543d6784d4cc 188
EasyCAT 0:543d6784d4cc 189 if (HalStatus == HAL_OK) // packet received
EasyCAT 0:543d6784d4cc 190 {
EasyCAT 0:543d6784d4cc 191 Len = hEth.RxFrameInfos.length; // packet lenght
EasyCAT 0:543d6784d4cc 192 pDmaBuff = (uint8_t*)hEth.RxFrameInfos.buffer; // DMA buffer pointer
EasyCAT 0:543d6784d4cc 193
EasyCAT 0:543d6784d4cc 194 memcpy (pBuff, pDmaBuff, Len); // read the data
EasyCAT 0:543d6784d4cc 195
EasyCAT 0:543d6784d4cc 196 // release the descriptor
EasyCAT 0:543d6784d4cc 197 hEth.RxFrameInfos.FSRxDesc->Status |= ETH_DMARXDESC_OWN;
EasyCAT 0:543d6784d4cc 198 hEth.RxFrameInfos.SegCount = 0; // reset segment count
EasyCAT 0:543d6784d4cc 199
EasyCAT 0:543d6784d4cc 200 return Len; // return the number of bytes read
EasyCAT 0:543d6784d4cc 201 }
EasyCAT 0:543d6784d4cc 202
EasyCAT 0:543d6784d4cc 203 else
EasyCAT 0:543d6784d4cc 204 {
EasyCAT 0:543d6784d4cc 205 return NULL; // no packet received
EasyCAT 0:543d6784d4cc 206 }
EasyCAT 0:543d6784d4cc 207 }
EasyCAT 0:543d6784d4cc 208
EasyCAT 0:543d6784d4cc 209 //*****************************************************************************
EasyCAT 0:543d6784d4cc 210 //
EasyCAT 0:543d6784d4cc 211 //*****************************************************************************
EasyCAT 0:543d6784d4cc 212
EasyCAT 0:543d6784d4cc 213
EasyCAT 0:543d6784d4cc 214
EasyCAT 0:543d6784d4cc 215 static void ecx_clear_rxbufstat(int *rxbufstat)
EasyCAT 0:543d6784d4cc 216 {
EasyCAT 0:543d6784d4cc 217 int i;
EasyCAT 0:543d6784d4cc 218 for(i = 0; i < EC_MAXBUF; i++)
EasyCAT 0:543d6784d4cc 219 {
EasyCAT 0:543d6784d4cc 220 rxbufstat[i] = EC_BUF_EMPTY;
EasyCAT 0:543d6784d4cc 221 }
EasyCAT 0:543d6784d4cc 222 }
EasyCAT 0:543d6784d4cc 223
EasyCAT 0:543d6784d4cc 224 /** Basic setup to connect NIC to socket.
EasyCAT 0:543d6784d4cc 225 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 226 * @param[in] ifname = Name of NIC device, f.e. "eth0"
EasyCAT 0:543d6784d4cc 227 * @param[in] secondary = if >0 then use secondary stack instead of primary
EasyCAT 0:543d6784d4cc 228 * @return >0 if succeeded
EasyCAT 0:543d6784d4cc 229 */
EasyCAT 0:543d6784d4cc 230 int ecx_setupnic(ecx_portt *port, const char *ifname, int secondary)
EasyCAT 0:543d6784d4cc 231 {
EasyCAT 0:543d6784d4cc 232 int i;
EasyCAT 0:543d6784d4cc 233 int rVal;
EasyCAT 0:543d6784d4cc 234 int *psock;
EasyCAT 0:543d6784d4cc 235
EasyCAT 0:543d6784d4cc 236 EthInit();
EasyCAT 0:543d6784d4cc 237
EasyCAT 0:543d6784d4cc 238 if (rVal != 0)
EasyCAT 0:543d6784d4cc 239 return 0;
EasyCAT 0:543d6784d4cc 240
EasyCAT 0:543d6784d4cc 241 if (secondary)
EasyCAT 0:543d6784d4cc 242 {
EasyCAT 0:543d6784d4cc 243 /* secondary port struct available? */
EasyCAT 0:543d6784d4cc 244 if (port->redport)
EasyCAT 0:543d6784d4cc 245 {
EasyCAT 0:543d6784d4cc 246 /* when using secondary socket it is automatically a redundant setup */
EasyCAT 0:543d6784d4cc 247 psock = &(port->redport->sockhandle);
EasyCAT 0:543d6784d4cc 248 *psock = -1;
EasyCAT 0:543d6784d4cc 249 port->redstate = ECT_RED_DOUBLE;
EasyCAT 0:543d6784d4cc 250 port->redport->stack.sock = &(port->redport->sockhandle);
EasyCAT 0:543d6784d4cc 251 port->redport->stack.txbuf = &(port->txbuf);
EasyCAT 0:543d6784d4cc 252 port->redport->stack.txbuflength = &(port->txbuflength);
EasyCAT 0:543d6784d4cc 253 port->redport->stack.tempbuf = &(port->redport->tempinbuf);
EasyCAT 0:543d6784d4cc 254 port->redport->stack.rxbuf = &(port->redport->rxbuf);
EasyCAT 0:543d6784d4cc 255 port->redport->stack.rxbufstat = &(port->redport->rxbufstat);
EasyCAT 0:543d6784d4cc 256 port->redport->stack.rxsa = &(port->redport->rxsa);
EasyCAT 0:543d6784d4cc 257 ecx_clear_rxbufstat(&(port->redport->rxbufstat[0]));
EasyCAT 0:543d6784d4cc 258 }
EasyCAT 0:543d6784d4cc 259 else
EasyCAT 0:543d6784d4cc 260 {
EasyCAT 0:543d6784d4cc 261 /* fail */
EasyCAT 0:543d6784d4cc 262 return 0;
EasyCAT 0:543d6784d4cc 263 }
EasyCAT 0:543d6784d4cc 264 }
EasyCAT 0:543d6784d4cc 265 else
EasyCAT 0:543d6784d4cc 266 {
EasyCAT 0:543d6784d4cc 267 port->sockhandle = -1;
EasyCAT 0:543d6784d4cc 268 port->lastidx = 0;
EasyCAT 0:543d6784d4cc 269 port->redstate = ECT_RED_NONE;
EasyCAT 0:543d6784d4cc 270 port->stack.sock = &(port->sockhandle);
EasyCAT 0:543d6784d4cc 271 port->stack.txbuf = &(port->txbuf);
EasyCAT 0:543d6784d4cc 272 port->stack.txbuflength = &(port->txbuflength);
EasyCAT 0:543d6784d4cc 273 port->stack.tempbuf = &(port->tempinbuf);
EasyCAT 0:543d6784d4cc 274 port->stack.rxbuf = &(port->rxbuf);
EasyCAT 0:543d6784d4cc 275 port->stack.rxbufstat = &(port->rxbufstat);
EasyCAT 0:543d6784d4cc 276 port->stack.rxsa = &(port->rxsa);
EasyCAT 0:543d6784d4cc 277 ecx_clear_rxbufstat(&(port->rxbufstat[0]));
EasyCAT 0:543d6784d4cc 278 psock = &(port->sockhandle);
EasyCAT 0:543d6784d4cc 279 }
EasyCAT 0:543d6784d4cc 280
EasyCAT 0:543d6784d4cc 281 /* setup ethernet headers in tx buffers so we don't have to repeat it */
EasyCAT 0:543d6784d4cc 282 for (i = 0; i < EC_MAXBUF; i++)
EasyCAT 0:543d6784d4cc 283 {
EasyCAT 0:543d6784d4cc 284 ec_setupheader(&(port->txbuf[i]));
EasyCAT 0:543d6784d4cc 285 port->rxbufstat[i] = EC_BUF_EMPTY;
EasyCAT 0:543d6784d4cc 286 }
EasyCAT 0:543d6784d4cc 287 ec_setupheader(&(port->txbuf2));
EasyCAT 0:543d6784d4cc 288
EasyCAT 0:543d6784d4cc 289 return 1;
EasyCAT 0:543d6784d4cc 290 }
EasyCAT 0:543d6784d4cc 291
EasyCAT 0:543d6784d4cc 292 /** Close sockets used
EasyCAT 0:543d6784d4cc 293 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 294 * @return 0
EasyCAT 0:543d6784d4cc 295 */
EasyCAT 0:543d6784d4cc 296 int ecx_closenic(ecx_portt *port)
EasyCAT 0:543d6784d4cc 297 {
EasyCAT 0:543d6784d4cc 298 if (port->sockhandle >= 0)
EasyCAT 0:543d6784d4cc 299 {
EasyCAT 0:543d6784d4cc 300 close(port->sockhandle);
EasyCAT 0:543d6784d4cc 301 }
EasyCAT 0:543d6784d4cc 302 if ((port->redport) && (port->redport->sockhandle >= 0))
EasyCAT 0:543d6784d4cc 303 {
EasyCAT 0:543d6784d4cc 304 close(port->redport->sockhandle);
EasyCAT 0:543d6784d4cc 305 }
EasyCAT 0:543d6784d4cc 306 return 0;
EasyCAT 0:543d6784d4cc 307 }
EasyCAT 0:543d6784d4cc 308
EasyCAT 0:543d6784d4cc 309 /** Fill buffer with ethernet header structure.
EasyCAT 0:543d6784d4cc 310 * Destination MAC is always broadcast.
EasyCAT 0:543d6784d4cc 311 * Ethertype is always ETH_P_ECAT.
EasyCAT 0:543d6784d4cc 312 * @param[out] p = buffer
EasyCAT 0:543d6784d4cc 313 */
EasyCAT 0:543d6784d4cc 314
EasyCAT 0:543d6784d4cc 315 void ec_setupheader(void *p)
EasyCAT 0:543d6784d4cc 316 {
EasyCAT 0:543d6784d4cc 317 ec_etherheadert *bp;
EasyCAT 0:543d6784d4cc 318
EasyCAT 0:543d6784d4cc 319 bp = (ec_etherheadert*)p;
EasyCAT 0:543d6784d4cc 320
EasyCAT 0:543d6784d4cc 321
EasyCAT 0:543d6784d4cc 322 bp->da0 = oshw_htons(0xffff);
EasyCAT 0:543d6784d4cc 323 bp->da1 = oshw_htons(0xffff);
EasyCAT 0:543d6784d4cc 324 bp->da2 = oshw_htons(0xffff);
EasyCAT 0:543d6784d4cc 325 bp->sa0 = oshw_htons(priMAC[0]);
EasyCAT 0:543d6784d4cc 326 bp->sa1 = oshw_htons(priMAC[1]);
EasyCAT 0:543d6784d4cc 327 bp->sa2 = oshw_htons(priMAC[2]);
EasyCAT 0:543d6784d4cc 328 bp->etype = oshw_htons(ETH_P_ECAT);
EasyCAT 0:543d6784d4cc 329 }
EasyCAT 0:543d6784d4cc 330
EasyCAT 0:543d6784d4cc 331 /** Get new frame identifier index and allocate corresponding rx buffer.
EasyCAT 0:543d6784d4cc 332 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 333 * @return new index.
EasyCAT 0:543d6784d4cc 334 */
EasyCAT 0:543d6784d4cc 335 int ecx_getindex(ecx_portt *port)
EasyCAT 0:543d6784d4cc 336 {
EasyCAT 0:543d6784d4cc 337 int idx;
EasyCAT 0:543d6784d4cc 338 int cnt;
EasyCAT 0:543d6784d4cc 339
EasyCAT 0:543d6784d4cc 340 // mtx_lock (port->getindex_mutex); //******//
EasyCAT 0:543d6784d4cc 341
EasyCAT 0:543d6784d4cc 342 idx = port->lastidx + 1;
EasyCAT 0:543d6784d4cc 343 /* index can't be larger than buffer array */
EasyCAT 0:543d6784d4cc 344 if (idx >= EC_MAXBUF)
EasyCAT 0:543d6784d4cc 345 {
EasyCAT 0:543d6784d4cc 346 idx = 0;
EasyCAT 0:543d6784d4cc 347 }
EasyCAT 0:543d6784d4cc 348 cnt = 0;
EasyCAT 0:543d6784d4cc 349 /* try to find unused index */
EasyCAT 0:543d6784d4cc 350 while ((port->rxbufstat[idx] != EC_BUF_EMPTY) && (cnt < EC_MAXBUF))
EasyCAT 0:543d6784d4cc 351 {
EasyCAT 0:543d6784d4cc 352 idx++;
EasyCAT 0:543d6784d4cc 353 cnt++;
EasyCAT 0:543d6784d4cc 354 if (idx >= EC_MAXBUF)
EasyCAT 0:543d6784d4cc 355 {
EasyCAT 0:543d6784d4cc 356 idx = 0;
EasyCAT 0:543d6784d4cc 357 }
EasyCAT 0:543d6784d4cc 358 }
EasyCAT 0:543d6784d4cc 359 port->rxbufstat[idx] = EC_BUF_ALLOC;
EasyCAT 0:543d6784d4cc 360 if (port->redstate != ECT_RED_NONE)
EasyCAT 0:543d6784d4cc 361 {
EasyCAT 0:543d6784d4cc 362 port->redport->rxbufstat[idx] = EC_BUF_ALLOC;
EasyCAT 0:543d6784d4cc 363 }
EasyCAT 0:543d6784d4cc 364 port->lastidx = idx;
EasyCAT 0:543d6784d4cc 365
EasyCAT 0:543d6784d4cc 366 // mtx_unlock (port->getindex_mutex); //******//
EasyCAT 0:543d6784d4cc 367
EasyCAT 0:543d6784d4cc 368 return idx;
EasyCAT 0:543d6784d4cc 369 }
EasyCAT 0:543d6784d4cc 370
EasyCAT 0:543d6784d4cc 371 /** Set rx buffer status.
EasyCAT 0:543d6784d4cc 372 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 373 * @param[in] idx = index in buffer array
EasyCAT 0:543d6784d4cc 374 * @param[in] bufstat = status to set
EasyCAT 0:543d6784d4cc 375 */
EasyCAT 0:543d6784d4cc 376 void ecx_setbufstat(ecx_portt *port, int idx, int bufstat)
EasyCAT 0:543d6784d4cc 377 {
EasyCAT 0:543d6784d4cc 378 port->rxbufstat[idx] = bufstat;
EasyCAT 0:543d6784d4cc 379 if (port->redstate != ECT_RED_NONE)
EasyCAT 0:543d6784d4cc 380 {
EasyCAT 0:543d6784d4cc 381 port->redport->rxbufstat[idx] = bufstat;
EasyCAT 0:543d6784d4cc 382 }
EasyCAT 0:543d6784d4cc 383 }
EasyCAT 0:543d6784d4cc 384
EasyCAT 0:543d6784d4cc 385 /** Transmit buffer over socket (non blocking).
EasyCAT 0:543d6784d4cc 386 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 387 * @param[in] idx = index in tx buffer array
EasyCAT 0:543d6784d4cc 388 * @param[in] stacknumber = 0=Primary 1=Secondary stack
EasyCAT 0:543d6784d4cc 389 * @return socket send result
EasyCAT 0:543d6784d4cc 390 */
EasyCAT 0:543d6784d4cc 391 int ecx_outframe(ecx_portt *port, int idx, int stacknumber)
EasyCAT 0:543d6784d4cc 392 {
EasyCAT 0:543d6784d4cc 393 int lp, rval;
EasyCAT 0:543d6784d4cc 394 ec_stackT *stack;
EasyCAT 0:543d6784d4cc 395
EasyCAT 0:543d6784d4cc 396 if (!stacknumber)
EasyCAT 0:543d6784d4cc 397 {
EasyCAT 0:543d6784d4cc 398 stack = &(port->stack);
EasyCAT 0:543d6784d4cc 399 }
EasyCAT 0:543d6784d4cc 400 else
EasyCAT 0:543d6784d4cc 401 {
EasyCAT 0:543d6784d4cc 402 stack = &(port->redport->stack);
EasyCAT 0:543d6784d4cc 403 }
EasyCAT 0:543d6784d4cc 404 lp = (*stack->txbuflength)[idx];
EasyCAT 0:543d6784d4cc 405 (*stack->rxbufstat)[idx] = EC_BUF_TX;
EasyCAT 0:543d6784d4cc 406
EasyCAT 0:543d6784d4cc 407 rval = EthWrPacket ((*stack->txbuf)[idx], lp);
EasyCAT 0:543d6784d4cc 408
EasyCAT 0:543d6784d4cc 409 return rval;
EasyCAT 0:543d6784d4cc 410 }
EasyCAT 0:543d6784d4cc 411
EasyCAT 0:543d6784d4cc 412 /** Transmit buffer over socket (non blocking).
EasyCAT 0:543d6784d4cc 413 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 414 * @param[in] idx = index in tx buffer array
EasyCAT 0:543d6784d4cc 415 * @return socket send result
EasyCAT 0:543d6784d4cc 416 */
EasyCAT 0:543d6784d4cc 417 int ecx_outframe_red(ecx_portt *port, int idx)
EasyCAT 0:543d6784d4cc 418 {
EasyCAT 0:543d6784d4cc 419 ec_comt *datagramP;
EasyCAT 0:543d6784d4cc 420 ec_etherheadert *ehp;
EasyCAT 0:543d6784d4cc 421 int rval;
EasyCAT 0:543d6784d4cc 422
EasyCAT 0:543d6784d4cc 423 ehp = (ec_etherheadert *)&(port->txbuf[idx]);
EasyCAT 0:543d6784d4cc 424 /* rewrite MAC source address 1 to primary */
EasyCAT 0:543d6784d4cc 425 ehp->sa1 = oshw_htons(priMAC[1]);
EasyCAT 0:543d6784d4cc 426 /* transmit over primary socket*/
EasyCAT 0:543d6784d4cc 427 rval = ecx_outframe(port, idx, 0);
EasyCAT 0:543d6784d4cc 428 if (port->redstate != ECT_RED_NONE)
EasyCAT 0:543d6784d4cc 429 {
EasyCAT 0:543d6784d4cc 430 // mtx_lock (port->tx_mutex); //******//
EasyCAT 0:543d6784d4cc 431 ehp = (ec_etherheadert *)&(port->txbuf2);
EasyCAT 0:543d6784d4cc 432 /* use dummy frame for secondary socket transmit (BRD) */
EasyCAT 0:543d6784d4cc 433 datagramP = (ec_comt*)&(port->txbuf2[ETH_HEADERSIZE]);
EasyCAT 0:543d6784d4cc 434 /* write index to frame */
EasyCAT 0:543d6784d4cc 435 datagramP->index = idx;
EasyCAT 0:543d6784d4cc 436 /* rewrite MAC source address 1 to secondary */
EasyCAT 0:543d6784d4cc 437 ehp->sa1 = oshw_htons(secMAC[1]);
EasyCAT 0:543d6784d4cc 438 /* transmit over secondary socket */
EasyCAT 0:543d6784d4cc 439 //send(sockhandle2, &ec_txbuf2, ec_txbuflength2 , 0);
EasyCAT 0:543d6784d4cc 440 // OBS! redundant not ACTIVE for BFIN, just added to compile
EasyCAT 0:543d6784d4cc 441
EasyCAT 0:543d6784d4cc 442 port->redport->rxbufstat[idx] = EC_BUF_TX;
EasyCAT 0:543d6784d4cc 443
EasyCAT 0:543d6784d4cc 444 EthWrPacket((uint8_t*)&(port->txbuf2), port->txbuflength2);
EasyCAT 0:543d6784d4cc 445
EasyCAT 0:543d6784d4cc 446 // mtx_unlock (port->tx_mutex); //******//
EasyCAT 0:543d6784d4cc 447 }
EasyCAT 0:543d6784d4cc 448
EasyCAT 0:543d6784d4cc 449 return rval;
EasyCAT 0:543d6784d4cc 450 }
EasyCAT 0:543d6784d4cc 451
EasyCAT 0:543d6784d4cc 452 /** Non blocking read of socket. Put frame in temporary buffer.
EasyCAT 0:543d6784d4cc 453 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 454 * @param[in] stacknumber = 0=primary 1=secondary stack
EasyCAT 0:543d6784d4cc 455 * @return >0 if frame is available and read
EasyCAT 0:543d6784d4cc 456 */
EasyCAT 0:543d6784d4cc 457 static int ecx_recvpkt(ecx_portt *port, int stacknumber)
EasyCAT 0:543d6784d4cc 458 {
EasyCAT 0:543d6784d4cc 459 int lp, bytesrx;
EasyCAT 0:543d6784d4cc 460 ec_stackT *stack;
EasyCAT 0:543d6784d4cc 461
EasyCAT 0:543d6784d4cc 462 if (!stacknumber)
EasyCAT 0:543d6784d4cc 463 {
EasyCAT 0:543d6784d4cc 464 stack = &(port->stack);
EasyCAT 0:543d6784d4cc 465 }
EasyCAT 0:543d6784d4cc 466 else
EasyCAT 0:543d6784d4cc 467 {
EasyCAT 0:543d6784d4cc 468 stack = &(port->redport->stack);
EasyCAT 0:543d6784d4cc 469 }
EasyCAT 0:543d6784d4cc 470 lp = sizeof(port->tempinbuf);
EasyCAT 0:543d6784d4cc 471
EasyCAT 0:543d6784d4cc 472 bytesrx = EthRdPacket(*stack->tempbuf);
EasyCAT 0:543d6784d4cc 473
EasyCAT 0:543d6784d4cc 474
EasyCAT 0:543d6784d4cc 475 port->tempinbufs = bytesrx;
EasyCAT 0:543d6784d4cc 476
EasyCAT 0:543d6784d4cc 477 return (bytesrx > 0);
EasyCAT 0:543d6784d4cc 478 }
EasyCAT 0:543d6784d4cc 479
EasyCAT 0:543d6784d4cc 480 /** Non blocking receive frame function. Uses RX buffer and index to combine
EasyCAT 0:543d6784d4cc 481 * read frame with transmitted frame. To compensate for received frames that
EasyCAT 0:543d6784d4cc 482 * are out-of-order all frames are stored in their respective indexed buffer.
EasyCAT 0:543d6784d4cc 483 * If a frame was placed in the buffer previously, the function retrieves it
EasyCAT 0:543d6784d4cc 484 * from that buffer index without calling ec_recvpkt. If the requested index
EasyCAT 0:543d6784d4cc 485 * is not already in the buffer it calls ec_recvpkt to fetch it. There are
EasyCAT 0:543d6784d4cc 486 * three options now, 1 no frame read, so exit. 2 frame read but other
EasyCAT 0:543d6784d4cc 487 * than requested index, store in buffer and exit. 3 frame read with matching
EasyCAT 0:543d6784d4cc 488 * index, store in buffer, set completed flag in buffer status and exit.
EasyCAT 0:543d6784d4cc 489 *
EasyCAT 0:543d6784d4cc 490 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 491 * @param[in] idx = requested index of frame
EasyCAT 0:543d6784d4cc 492 * @param[in] stacknumber = 0=primary 1=secondary stack
EasyCAT 0:543d6784d4cc 493 * @return Workcounter if a frame is found with corresponding index, otherwise
EasyCAT 0:543d6784d4cc 494 * EC_NOFRAME or EC_OTHERFRAME.
EasyCAT 0:543d6784d4cc 495 */
EasyCAT 0:543d6784d4cc 496 int ecx_inframe(ecx_portt *port, int idx, int stacknumber)
EasyCAT 0:543d6784d4cc 497 {
EasyCAT 0:543d6784d4cc 498 uint16 l;
EasyCAT 0:543d6784d4cc 499 int rval;
EasyCAT 0:543d6784d4cc 500 uint8 idxf;
EasyCAT 0:543d6784d4cc 501 ec_etherheadert *ehp;
EasyCAT 0:543d6784d4cc 502 ec_comt *ecp;
EasyCAT 0:543d6784d4cc 503 ec_stackT *stack;
EasyCAT 0:543d6784d4cc 504 ec_bufT *rxbuf;
EasyCAT 0:543d6784d4cc 505
EasyCAT 0:543d6784d4cc 506 if (!stacknumber)
EasyCAT 0:543d6784d4cc 507 {
EasyCAT 0:543d6784d4cc 508 stack = &(port->stack);
EasyCAT 0:543d6784d4cc 509 }
EasyCAT 0:543d6784d4cc 510 else
EasyCAT 0:543d6784d4cc 511 {
EasyCAT 0:543d6784d4cc 512 stack = &(port->redport->stack);
EasyCAT 0:543d6784d4cc 513 }
EasyCAT 0:543d6784d4cc 514 rval = EC_NOFRAME;
EasyCAT 0:543d6784d4cc 515 rxbuf = &(*stack->rxbuf)[idx];
EasyCAT 0:543d6784d4cc 516 /* check if requested index is already in buffer ? */
EasyCAT 0:543d6784d4cc 517 if ((idx < EC_MAXBUF) && ( (*stack->rxbufstat)[idx] == EC_BUF_RCVD))
EasyCAT 0:543d6784d4cc 518 {
EasyCAT 0:543d6784d4cc 519 l = (*rxbuf)[0] + ((uint16)((*rxbuf)[1] & 0x0f) << 8);
EasyCAT 0:543d6784d4cc 520 /* return WKC */
EasyCAT 0:543d6784d4cc 521 rval = ((*rxbuf)[l] + ((uint16)(*rxbuf)[l + 1] << 8));
EasyCAT 0:543d6784d4cc 522 /* mark as completed */
EasyCAT 0:543d6784d4cc 523 (*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
EasyCAT 0:543d6784d4cc 524 }
EasyCAT 0:543d6784d4cc 525 else
EasyCAT 0:543d6784d4cc 526 {
EasyCAT 0:543d6784d4cc 527 // mtx_lock (port->rx_mutex); //******//
EasyCAT 0:543d6784d4cc 528 /* non blocking call to retrieve frame from socket */
EasyCAT 0:543d6784d4cc 529 if (ecx_recvpkt(port, stacknumber))
EasyCAT 0:543d6784d4cc 530 {
EasyCAT 0:543d6784d4cc 531 rval = EC_OTHERFRAME;
EasyCAT 0:543d6784d4cc 532 ehp =(ec_etherheadert*)(stack->tempbuf);
EasyCAT 0:543d6784d4cc 533 /* check if it is an EtherCAT frame */
EasyCAT 0:543d6784d4cc 534 if (ehp->etype == oshw_htons(ETH_P_ECAT))
EasyCAT 0:543d6784d4cc 535 {
EasyCAT 0:543d6784d4cc 536 ecp =(ec_comt*)(&(*stack->tempbuf)[ETH_HEADERSIZE]);
EasyCAT 0:543d6784d4cc 537 l = etohs(ecp->elength) & 0x0fff;
EasyCAT 0:543d6784d4cc 538 idxf = ecp->index;
EasyCAT 0:543d6784d4cc 539 /* found index equals requested index ? */
EasyCAT 0:543d6784d4cc 540 if (idxf == idx)
EasyCAT 0:543d6784d4cc 541 {
EasyCAT 0:543d6784d4cc 542 /* yes, put it in the buffer array (strip ethernet header) */
EasyCAT 0:543d6784d4cc 543 memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idx] - ETH_HEADERSIZE);
EasyCAT 0:543d6784d4cc 544 /* return WKC */
EasyCAT 0:543d6784d4cc 545 rval = ((*rxbuf)[l] + ((uint16)((*rxbuf)[l + 1]) << 8));
EasyCAT 0:543d6784d4cc 546 /* mark as completed */
EasyCAT 0:543d6784d4cc 547 (*stack->rxbufstat)[idx] = EC_BUF_COMPLETE;
EasyCAT 0:543d6784d4cc 548 /* store MAC source word 1 for redundant routing info */
EasyCAT 0:543d6784d4cc 549 (*stack->rxsa)[idx] = oshw_ntohs(ehp->sa1);
EasyCAT 0:543d6784d4cc 550 }
EasyCAT 0:543d6784d4cc 551 else
EasyCAT 0:543d6784d4cc 552 {
EasyCAT 0:543d6784d4cc 553 /* check if index exist and someone is waiting for it */
EasyCAT 0:543d6784d4cc 554 if (idxf < EC_MAXBUF && (*stack->rxbufstat)[idxf] == EC_BUF_TX)
EasyCAT 0:543d6784d4cc 555 {
EasyCAT 0:543d6784d4cc 556 rxbuf = &(*stack->rxbuf)[idxf];
EasyCAT 0:543d6784d4cc 557 /* put it in the buffer array (strip ethernet header) */
EasyCAT 0:543d6784d4cc 558 memcpy(rxbuf, &(*stack->tempbuf)[ETH_HEADERSIZE], (*stack->txbuflength)[idxf] - ETH_HEADERSIZE);
EasyCAT 0:543d6784d4cc 559 /* mark as received */
EasyCAT 0:543d6784d4cc 560 (*stack->rxbufstat)[idxf] = EC_BUF_RCVD;
EasyCAT 0:543d6784d4cc 561 (*stack->rxsa)[idxf] = oshw_ntohs(ehp->sa1);
EasyCAT 0:543d6784d4cc 562 }
EasyCAT 0:543d6784d4cc 563 else
EasyCAT 0:543d6784d4cc 564 {
EasyCAT 0:543d6784d4cc 565 /* strange things happened */
EasyCAT 0:543d6784d4cc 566 }
EasyCAT 0:543d6784d4cc 567 }
EasyCAT 0:543d6784d4cc 568 }
EasyCAT 0:543d6784d4cc 569 }
EasyCAT 0:543d6784d4cc 570 // mtx_unlock (port->rx_mutex); //******//
EasyCAT 0:543d6784d4cc 571
EasyCAT 0:543d6784d4cc 572 }
EasyCAT 0:543d6784d4cc 573
EasyCAT 0:543d6784d4cc 574 /* WKC if matching frame found */
EasyCAT 0:543d6784d4cc 575 return rval;
EasyCAT 0:543d6784d4cc 576 }
EasyCAT 0:543d6784d4cc 577
EasyCAT 0:543d6784d4cc 578
EasyCAT 0:543d6784d4cc 579 /** Blocking redundant receive frame function. If redundant mode is not active then
EasyCAT 0:543d6784d4cc 580 * it skips the secondary stack and redundancy functions. In redundant mode it waits
EasyCAT 0:543d6784d4cc 581 * for both (primary and secondary) frames to come in. The result goes in an decision
EasyCAT 0:543d6784d4cc 582 * tree that decides, depending on the route of the packet and its possible missing arrival,
EasyCAT 0:543d6784d4cc 583 * how to reroute the original packet to get the data in an other try.
EasyCAT 0:543d6784d4cc 584 *
EasyCAT 0:543d6784d4cc 585 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 586 * @param[in] idx = requested index of frame
EasyCAT 0:543d6784d4cc 587 * @param[in] timer = absolute timeout time
EasyCAT 0:543d6784d4cc 588 * @return Workcounter if a frame is found with corresponding index, otherwise
EasyCAT 0:543d6784d4cc 589 * EC_NOFRAME.
EasyCAT 0:543d6784d4cc 590 */
EasyCAT 0:543d6784d4cc 591 static int ecx_waitinframe_red(ecx_portt *port, int idx, osal_timert timer)
EasyCAT 0:543d6784d4cc 592 {
EasyCAT 0:543d6784d4cc 593 int wkc = EC_NOFRAME;
EasyCAT 0:543d6784d4cc 594 int wkc2 = EC_NOFRAME;
EasyCAT 0:543d6784d4cc 595 int primrx, secrx;
EasyCAT 0:543d6784d4cc 596
EasyCAT 0:543d6784d4cc 597 /* if not in redundant mode then always assume secondary is OK */
EasyCAT 0:543d6784d4cc 598 if (port->redstate == ECT_RED_NONE)
EasyCAT 0:543d6784d4cc 599 {
EasyCAT 0:543d6784d4cc 600 wkc2 = 0;
EasyCAT 0:543d6784d4cc 601 }
EasyCAT 0:543d6784d4cc 602 do
EasyCAT 0:543d6784d4cc 603 {
EasyCAT 0:543d6784d4cc 604 /* only read frame if not already in */
EasyCAT 0:543d6784d4cc 605 if (wkc <= EC_NOFRAME)
EasyCAT 0:543d6784d4cc 606 {
EasyCAT 0:543d6784d4cc 607 wkc = ecx_inframe(port, idx, 0);
EasyCAT 0:543d6784d4cc 608 }
EasyCAT 0:543d6784d4cc 609 /* only try secondary if in redundant mode */
EasyCAT 0:543d6784d4cc 610 if (port->redstate != ECT_RED_NONE)
EasyCAT 0:543d6784d4cc 611 {
EasyCAT 0:543d6784d4cc 612 /* only read frame if not already in */
EasyCAT 0:543d6784d4cc 613 if (wkc2 <= EC_NOFRAME)
EasyCAT 0:543d6784d4cc 614 wkc2 = ecx_inframe(port, idx, 1);
EasyCAT 0:543d6784d4cc 615 }
EasyCAT 0:543d6784d4cc 616 /* wait for both frames to arrive or timeout */
EasyCAT 0:543d6784d4cc 617 } while (((wkc <= EC_NOFRAME) || (wkc2 <= EC_NOFRAME)) && (osal_timer_is_expired(&timer) == FALSE));
EasyCAT 0:543d6784d4cc 618
EasyCAT 0:543d6784d4cc 619 /* only do redundant functions when in redundant mode */
EasyCAT 0:543d6784d4cc 620 if (port->redstate != ECT_RED_NONE)
EasyCAT 0:543d6784d4cc 621 {
EasyCAT 0:543d6784d4cc 622 /* primrx if the received MAC source on primary socket */
EasyCAT 0:543d6784d4cc 623 primrx = 0;
EasyCAT 0:543d6784d4cc 624 if (wkc > EC_NOFRAME)
EasyCAT 0:543d6784d4cc 625 {
EasyCAT 0:543d6784d4cc 626 primrx = port->rxsa[idx];
EasyCAT 0:543d6784d4cc 627 }
EasyCAT 0:543d6784d4cc 628 /* secrx if the received MAC source on psecondary socket */
EasyCAT 0:543d6784d4cc 629 secrx = 0;
EasyCAT 0:543d6784d4cc 630 if (wkc2 > EC_NOFRAME)
EasyCAT 0:543d6784d4cc 631 {
EasyCAT 0:543d6784d4cc 632 secrx = port->redport->rxsa[idx];
EasyCAT 0:543d6784d4cc 633 }
EasyCAT 0:543d6784d4cc 634 /* primary socket got secondary frame and secondary socket got primary frame */
EasyCAT 0:543d6784d4cc 635 /* normal situation in redundant mode */
EasyCAT 0:543d6784d4cc 636 if ( ((primrx == RX_SEC) && (secrx == RX_PRIM)) )
EasyCAT 0:543d6784d4cc 637 {
EasyCAT 0:543d6784d4cc 638 /* copy secondary buffer to primary */
EasyCAT 0:543d6784d4cc 639 memcpy(&(port->rxbuf[idx]), &(port->redport->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE);
EasyCAT 0:543d6784d4cc 640 wkc = wkc2;
EasyCAT 0:543d6784d4cc 641 }
EasyCAT 0:543d6784d4cc 642 /* primary socket got nothing or primary frame, and secondary socket got secondary frame */
EasyCAT 0:543d6784d4cc 643 /* we need to resend TX packet */
EasyCAT 0:543d6784d4cc 644 if ( ((primrx == 0) && (secrx == RX_SEC)) ||
EasyCAT 0:543d6784d4cc 645 ((primrx == RX_PRIM) && (secrx == RX_SEC)) )
EasyCAT 0:543d6784d4cc 646 {
EasyCAT 0:543d6784d4cc 647 osal_timert read_timer;
EasyCAT 0:543d6784d4cc 648
EasyCAT 0:543d6784d4cc 649 /* If both primary and secondary have partial connection retransmit the primary received
EasyCAT 0:543d6784d4cc 650 * frame over the secondary socket. The result from the secondary received frame is a combined
EasyCAT 0:543d6784d4cc 651 * frame that traversed all slaves in standard order. */
EasyCAT 0:543d6784d4cc 652 if ( (primrx == RX_PRIM) && (secrx == RX_SEC) )
EasyCAT 0:543d6784d4cc 653 {
EasyCAT 0:543d6784d4cc 654 /* copy primary rx to tx buffer */
EasyCAT 0:543d6784d4cc 655 memcpy(&(port->txbuf[idx][ETH_HEADERSIZE]), &(port->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE);
EasyCAT 0:543d6784d4cc 656 }
EasyCAT 0:543d6784d4cc 657
EasyCAT 0:543d6784d4cc 658 //osal_timer_start(&read_timer, EC_TIMEOUTRET);
EasyCAT 0:543d6784d4cc 659
EasyCAT 0:543d6784d4cc 660 osal_timer_start(&read_timer, 500);
EasyCAT 0:543d6784d4cc 661
EasyCAT 0:543d6784d4cc 662 /* resend secondary tx */
EasyCAT 0:543d6784d4cc 663 ecx_outframe(port, idx, 1);
EasyCAT 0:543d6784d4cc 664 do
EasyCAT 0:543d6784d4cc 665 {
EasyCAT 0:543d6784d4cc 666 /* retrieve frame */
EasyCAT 0:543d6784d4cc 667 wkc2 = ecx_inframe(port, idx, 1);
EasyCAT 0:543d6784d4cc 668 } while ((wkc2 <= EC_NOFRAME) && (osal_timer_is_expired(&read_timer) == FALSE));
EasyCAT 0:543d6784d4cc 669 if (wkc2 > EC_NOFRAME)
EasyCAT 0:543d6784d4cc 670 {
EasyCAT 0:543d6784d4cc 671 /* copy secondary result to primary rx buffer */
EasyCAT 0:543d6784d4cc 672 memcpy(&(port->rxbuf[idx]), &(port->redport->rxbuf[idx]), port->txbuflength[idx] - ETH_HEADERSIZE);
EasyCAT 0:543d6784d4cc 673 wkc = wkc2;
EasyCAT 0:543d6784d4cc 674 }
EasyCAT 0:543d6784d4cc 675 }
EasyCAT 0:543d6784d4cc 676 }
EasyCAT 0:543d6784d4cc 677
EasyCAT 0:543d6784d4cc 678 /* return WKC or EC_NOFRAME */
EasyCAT 0:543d6784d4cc 679 return wkc;
EasyCAT 0:543d6784d4cc 680 }
EasyCAT 0:543d6784d4cc 681
EasyCAT 0:543d6784d4cc 682 /** Blocking receive frame function. Calls ec_waitinframe_red().
EasyCAT 0:543d6784d4cc 683 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 684 * @param[in] idx = requested index of frame
EasyCAT 0:543d6784d4cc 685 * @param[in] timeout = timeout in us
EasyCAT 0:543d6784d4cc 686 * @return Workcounter if a frame is found with corresponding index, otherwise
EasyCAT 0:543d6784d4cc 687 * EC_NOFRAME.
EasyCAT 0:543d6784d4cc 688 */
EasyCAT 0:543d6784d4cc 689 int ecx_waitinframe(ecx_portt *port, int idx, int timeout)
EasyCAT 0:543d6784d4cc 690 {
EasyCAT 0:543d6784d4cc 691 int wkc;
EasyCAT 0:543d6784d4cc 692
EasyCAT 0:543d6784d4cc 693 osal_timert timer;
EasyCAT 0:543d6784d4cc 694 osal_timer_start (&timer, timeout);
EasyCAT 0:543d6784d4cc 695 wkc = ecx_waitinframe_red(port, idx, timer);
EasyCAT 0:543d6784d4cc 696
EasyCAT 0:543d6784d4cc 697 return wkc;
EasyCAT 0:543d6784d4cc 698 }
EasyCAT 0:543d6784d4cc 699
EasyCAT 0:543d6784d4cc 700 /** Blocking send and receive frame function. Used for non processdata frames.
EasyCAT 0:543d6784d4cc 701 * A datagram is build into a frame and transmitted via this function. It waits
EasyCAT 0:543d6784d4cc 702 * for an answer and returns the workcounter. The function retries if time is
EasyCAT 0:543d6784d4cc 703 * left and the result is WKC=0 or no frame received.
EasyCAT 0:543d6784d4cc 704 *
EasyCAT 0:543d6784d4cc 705 * The function calls ec_outframe_red() and ec_waitinframe_red().
EasyCAT 0:543d6784d4cc 706 *
EasyCAT 0:543d6784d4cc 707 * @param[in] port = port context struct
EasyCAT 0:543d6784d4cc 708 * @param[in] idx = index of frame
EasyCAT 0:543d6784d4cc 709 * @param[in] timeout = timeout in us
EasyCAT 0:543d6784d4cc 710 * @return Workcounter or EC_NOFRAME
EasyCAT 0:543d6784d4cc 711 */
EasyCAT 0:543d6784d4cc 712 int ecx_srconfirm(ecx_portt *port, int idx, int timeout)
EasyCAT 0:543d6784d4cc 713 {
EasyCAT 0:543d6784d4cc 714 int wkc = EC_NOFRAME;
EasyCAT 0:543d6784d4cc 715
EasyCAT 0:543d6784d4cc 716 osal_timert timer;
EasyCAT 0:543d6784d4cc 717 osal_timer_start(&timer, timeout);
EasyCAT 0:543d6784d4cc 718
EasyCAT 0:543d6784d4cc 719 do
EasyCAT 0:543d6784d4cc 720 {
EasyCAT 0:543d6784d4cc 721 osal_timert read_timer;
EasyCAT 0:543d6784d4cc 722
EasyCAT 0:543d6784d4cc 723 /* tx frame on primary and if in redundant mode a dummy on secondary */
EasyCAT 0:543d6784d4cc 724 ecx_outframe_red(port, idx);
EasyCAT 0:543d6784d4cc 725 osal_timer_start(&read_timer, MIN(timeout, EC_TIMEOUTRET));
EasyCAT 0:543d6784d4cc 726
EasyCAT 0:543d6784d4cc 727 /* get frame from primary or if in redundant mode possibly from secondary */
EasyCAT 0:543d6784d4cc 728 wkc = ecx_waitinframe_red(port, idx, read_timer);
EasyCAT 0:543d6784d4cc 729 /* wait for answer with WKC>0 or otherwise retry until timeout */
EasyCAT 0:543d6784d4cc 730 } while ((wkc <= EC_NOFRAME) && (osal_timer_is_expired(&timer) == FALSE));
EasyCAT 0:543d6784d4cc 731
EasyCAT 0:543d6784d4cc 732 return wkc;
EasyCAT 0:543d6784d4cc 733 }
EasyCAT 0:543d6784d4cc 734
EasyCAT 0:543d6784d4cc 735
EasyCAT 0:543d6784d4cc 736 #ifdef EC_VER1
EasyCAT 0:543d6784d4cc 737 int ec_setupnic(const char *ifname, int secondary)
EasyCAT 0:543d6784d4cc 738 {
EasyCAT 0:543d6784d4cc 739 return ecx_setupnic(&ecx_port, ifname, secondary);
EasyCAT 0:543d6784d4cc 740 }
EasyCAT 0:543d6784d4cc 741
EasyCAT 0:543d6784d4cc 742 int ec_closenic(void)
EasyCAT 0:543d6784d4cc 743 {
EasyCAT 0:543d6784d4cc 744 return ecx_closenic(&ecx_port);
EasyCAT 0:543d6784d4cc 745 }
EasyCAT 0:543d6784d4cc 746
EasyCAT 0:543d6784d4cc 747 int ec_getindex(void)
EasyCAT 0:543d6784d4cc 748 {
EasyCAT 0:543d6784d4cc 749 return ecx_getindex(&ecx_port);
EasyCAT 0:543d6784d4cc 750 }
EasyCAT 0:543d6784d4cc 751
EasyCAT 0:543d6784d4cc 752 void ec_setbufstat(int idx, int bufstat)
EasyCAT 0:543d6784d4cc 753 {
EasyCAT 0:543d6784d4cc 754 ecx_setbufstat(&ecx_port, idx, bufstat);
EasyCAT 0:543d6784d4cc 755 }
EasyCAT 0:543d6784d4cc 756
EasyCAT 0:543d6784d4cc 757 int ec_outframe(int idx, int stacknumber)
EasyCAT 0:543d6784d4cc 758 {
EasyCAT 0:543d6784d4cc 759 return ecx_outframe(&ecx_port, idx, stacknumber);
EasyCAT 0:543d6784d4cc 760 }
EasyCAT 0:543d6784d4cc 761
EasyCAT 0:543d6784d4cc 762 int ec_outframe_red(int idx)
EasyCAT 0:543d6784d4cc 763 {
EasyCAT 0:543d6784d4cc 764 return ecx_outframe_red(&ecx_port, idx);
EasyCAT 0:543d6784d4cc 765 }
EasyCAT 0:543d6784d4cc 766
EasyCAT 0:543d6784d4cc 767 int ec_inframe(int idx, int stacknumber)
EasyCAT 0:543d6784d4cc 768 {
EasyCAT 0:543d6784d4cc 769 return ecx_inframe(&ecx_port, idx, stacknumber);
EasyCAT 0:543d6784d4cc 770 }
EasyCAT 0:543d6784d4cc 771
EasyCAT 0:543d6784d4cc 772 int ec_waitinframe(int idx, int timeout)
EasyCAT 0:543d6784d4cc 773 {
EasyCAT 0:543d6784d4cc 774 return ecx_waitinframe(&ecx_port, idx, timeout);
EasyCAT 0:543d6784d4cc 775 }
EasyCAT 0:543d6784d4cc 776
EasyCAT 0:543d6784d4cc 777 int ec_srconfirm(int idx, int timeout)
EasyCAT 0:543d6784d4cc 778 {
EasyCAT 0:543d6784d4cc 779 return ecx_srconfirm(&ecx_port, idx, timeout);
EasyCAT 0:543d6784d4cc 780 }
EasyCAT 0:543d6784d4cc 781 #endif
EasyCAT 0:543d6784d4cc 782