AB&T / Mbed OS EasyCAT_LAB

Dependencies:   SOEM SPI_STMPE610 SPI_TFT_ILI9341 TFT_fonts

Committer:
sulymarco
Date:
Tue Jun 11 10:19:08 2019 +0000
Revision:
0:7077d8f28b3e
Added SPI speed parameter

Who changed what in which revision?

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