KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ipmux.c
1 /*
2  * ipmux.c
3  *
4  * Created on: 8 aug. 2013
5  * Author: vincentb
6  */
7 
8 #include "drv/wb/ipmux.h"
9 #include "lm32soc/dev_soc.h"
10 #include "kernel/tm.h"
11 #include "kernel/err.h"
12 #include "util/log.h"
13 #include "errorcode.h"
14 
15 #include <stdio.h>
16 #include "util/func.h"
17 
18 LOG_DEF("IpMux");
19 
20 #define _IPM_RX_TIMEOUT_MARK 0xFFFFFFFF // value returned by read function on to
21 #define _IPM_RX_TIMEOUT 20 // tx word timeout
22 #define _IPM_TX_GRANT_TIMEOUT 100 // tx grant timeout
23 
24 
25 #define _MAC_LO(ARR) ( ( ( ARR[1] ) << 16 ) | ( ARR )[2] )
26 
27 #define _MAC_HI(ARR) ( ( ARR )[0] )
28 
29 
30 static void ipMuxCfgMod(IpMuxCfg * cfg)
31 {
32  int i;
33  uint32_t prt;
34  IPMCTRL->MAC_MOD_LO = _MAC_LO(cfg->mac);
35  IPMCTRL->MAC_MOD_HI = _MAC_HI(cfg->mac);
36  IPMCTRL->IP_MOD = cfg->ip;
37  for (i = 0; i < 4; ++i)
38  {
39  prt = IPMCTRL->UDP_PORT[i];
40  prt &= ~IPM_UDP_PORT_MOD_MASK;
41  prt|= ( cfg->prt[i] << IPM_UDP_PORT_MOD_SHIFT ) & IPM_UDP_PORT_MOD_MASK;
42  IPMCTRL->UDP_PORT[i] = prt;
43  }
44 
45 }
46 
47 static void ipMuxCfgSvr(IpMuxCfg * cfg)
48 {
49  int i;
50  uint32_t prt;
51  IPMCTRL->MAC_SVR_LO = _MAC_LO(cfg->mac);
52  IPMCTRL->MAC_SVR_HI = _MAC_HI(cfg->mac);
53  IPMCTRL->IP_SVR = cfg->ip;
54  for (i = 0; i < 4; ++i)
55  {
56  prt = IPMCTRL->UDP_PORT[i];
57  prt &= ~IPM_UDP_PORT_SVR_MASK;
58  prt|= ( cfg->prt[i] << IPM_UDP_PORT_SVR_SHIFT ) & IPM_UDP_PORT_SVR_MASK;
59  IPMCTRL->UDP_PORT[i] = prt;
60  }
61 
62 }
63 
64 
65 void ipMuxInit(IpMuxCfg * modCfg, bool flushCPU)
66 {
67  ipMuxCfgMod(modCfg);
68  if (flushCPU) ipMuxFlushCPU();
69 }
70 
71 void ipMuxCfgRemote(IpMuxCfg * svrCfg)
72 {
73  ipMuxCfgSvr(svrCfg);
74 }
75 
76 
78 {
79  return !(IPMCTRL->ACSR & IPM_ACSR_EMPTY(IPM_CH_C));
80 }
81 
82 // receive routine with time-out
83 static inline bool ipMuxWaitRx()
84 {
85  uint32_t to = timeOutInit(_IPM_RX_TIMEOUT);
86 
87  while (IPMCTRL->ACSR & IPM_ACSR_EMPTY(IPM_CH_C))
88  {
89  if (timeOut(to)) return false;
90  }
91 
92  return true;
93 }
94 
95 
96 bool ipMuxRx(void * buf, uint32_t buflen, uint32_t * rxlen)
97 {
98  uint16_t * rx = (uint16_t *)buf;
99 
100  // check for empty
101 
102  if (!ipMuxWaitRx()) {
103  *rxlen = 0;
104  return true;
105  }
106 
107  // suppose we're out of sync, we'll need to
108  // search for the IPMUX mask.
109 
110  // XXX sop not generated by IPMUX
111  bool sopFound = true;
112  // bool sopFound = false;
113 
114  uint32_t cur = 0;
115  volatile unsigned int * ptr = IPMFIFO;
116  int len = 0;
117 
118  do
119  {
120  if (len >= buflen)
121  {
122  errSet(ERROR_CTX(E_OUTOFMEMORY));
123  ipMuxFlush(IPMUX_CH_CPU, IPMUX_FLUSH_OP_TOGGLE);
124  return false;
125  }
126 
127  if (!ipMuxWaitRx()) {
128  errSet(ERROR_CTX(E_TIMEOUT));
129  ipMuxFlush(IPMUX_CH_CPU, IPMUX_FLUSH_OP_TOGGLE);
130  return false;
131  }
132 
133  cur = *ptr++;
134 // printf("Received: %08x, sop=%d, len=%d\n", cur, sopFound, len);
135 
136  if (!sopFound) {
137  if (cur & IPM_FIFO_SOP) sopFound = true;
138  else continue;
139  }
140  *rx = ( cur & IPM_FIFO_DATA_MASK ) >> IPM_FIFO_DATA_SHIFT;
141  len += 2;
142  rx++;
143 
144  } while (! (cur & IPM_FIFO_EOP));
145 
146  *rxlen = len;
147 
148  return true;
149 }
150 
151 bool ipMuxTx(void * buf, uint32_t txlen, bool done)
152 {
153 
154  IPMCTRL->ACSR |= IPM_ACSR_TX_REQ;
155  uint32_t to = timeOutInit(_IPM_TX_GRANT_TIMEOUT);
156  while (!(IPMCTRL->ACSR & IPM_ACSR_TX_GRANT))
157  {
158  if (timeOut(to)) {
159  // uint32_t reg = *((uint32_t *) (0x00020A50));
160  IPMCTRL->ACSR &= ~IPM_ACSR_TX_REQ;
161  ipMuxFlush(IPMUX_CH_CPU, IPMUX_FLUSH_OP_TOGGLE);
163  return false;
164  }
165  }
166 
167 
168  uint16_t * tx = (uint16_t *)buf;
169  int i;
170  int len = (txlen + 1) >> 1;
171 
172  uint32_t dta;
173 
174  static volatile unsigned int * ptr = IPMFIFO; // I hate statics inside functions, but
175  // its pending a better solution...
176 
177  for (i = 0; i < len; ++i) {
178  dta = *tx;
179  if ((i == (len - 1)) && done) dta |= IPM_FIFO_EOP;
180  *ptr = dta;
181  ptr++;
182  tx++;
183  }
184  if (done) {
185  ptr = IPMFIFO;
186  IPMCTRL->ACSR &= ~IPM_ACSR_TX_REQ;
187  }
188  return true;
189 }
190 
191 void ipMuxFlush(uint32_t mask, uint8_t ipmFlushOp)
192 {
193  // wait until flushable...
194 
195  while ( ( IPMPKGEN->TXSTM_INFO & IPM_TXSTM_INFO_PKT_DONE(mask) ) != IPM_TXSTM_INFO_PKT_DONE(mask))
196  {
197  }
198 
199  uint32_t acsr = IPMCTRL->ACSR;
200 
201  if (ipmFlushOp & IPMUX_FLUSH_OP_START) IPMCTRL->ACSR = acsr | IPM_ACSR_FLUSH(mask);
202  if (ipmFlushOp & IPMUX_FLUSH_OP_END) IPMCTRL->ACSR = acsr & ~IPM_ACSR_FLUSH_MASK;
203 }
204 
206 {
207  printf("IpMux dump\n");
208  printf("- ACSR : %08x\n", IPMCTRL->ACSR);
209  printf("- MAC_SVR : %04x%08x\n", IPMCTRL->MAC_SVR_HI, IPMCTRL->MAC_SVR_LO);
210  printf("- MAC_MOD : %04x%08x\n", IPMCTRL->MAC_MOD_HI, IPMCTRL->MAC_MOD_LO);
211  uint8_t * ip = (uint8_t *) &IPMCTRL->IP_SVR;
212  printf("- IP_SRV : %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
213  ip = (uint8_t *) &IPMCTRL->IP_MOD;
214  printf("- IP_MOD : %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
215  printf("- PORTS : %04x %04x %04x %04x\n",
216  IPMCTRL->UDP_PORT[0],
217  IPMCTRL->UDP_PORT[1],
218  IPMCTRL->UDP_PORT[2],
219  IPMCTRL->UDP_PORT[3]);
220 
221 }
222 
#define IPMCTRL
IPMux Control.
Definition: dev_soc.h:70
void ipMuxCfgRemote(IpMuxCfg *svrCfg)
Configure IPmux with remote settings.
Definition: ipmux.c:71
uint32_t ip
IP address.
Definition: ipmux.h:30
#define IPM_FIFO_EOP
End of packet marker.
Definition: dev_ipm.h:64
bool ipMuxTx(void *buf, uint32_t txlen, bool done)
Sends data to the IPMux&#39;s CPU interface.
Definition: ipmux.c:151
#define IPM_UDP_PORT_SVR_SHIFT
Shift for server port.
Definition: dev_ipm.h:33
#define IPM_ACSR_TX_REQ
TX request.
Definition: dev_ipm.h:39
IPMUX Driver for CLBv2.
#define IPMUX_CH_CPU
CPU channel.
Definition: ipmux.h:39
IPMux configuration structure.
Definition: ipmux.h:28
bool ipMuxRx(void *buf, uint32_t buflen, uint32_t *rxlen)
Received data from the IPMux&#39;s CPU interface.
Definition: ipmux.c:96
#define IPMPKGEN
IPMux Control.
Definition: dev_soc.h:71
void ipMuxFlush(uint32_t channelMask, uint8_t ipmFlushOp)
Flushes the IPMUX&#39;s FIFO&#39;s.
Definition: ipmux.c:191
void ipMuxDumpRegs()
Debug function to see whats inside.
Definition: ipmux.c:205
static void ipMuxFlushCPU()
Flushes the.
Definition: ipmux.h:120
bool ipMuxRxAvail()
Returns whether or not there is data available for reception.
Definition: ipmux.c:77
#define IPM_ACSR_TX_GRANT
TX grant.
Definition: dev_ipm.h:40
static uint32_t timeOutInit(uint32_t msec)
Initializes a timeout with the specified no of msecs.
Definition: tm.h:53
uint16_t mac[3]
MAC address.
Definition: ipmux.h:31
static bool timeOut(uint32_t to)
Checks whether or not the timeout has expired.
Definition: tm.h:77
Manages the global system error.
#define IPM_UDP_PORT_MOD_MASK
Mask for module port (source)
Definition: dev_ipm.h:34
Simple timer functions.
void ipMuxInit(IpMuxCfg *modCfg, bool flush)
Initializes the IPMux local (module) only.
Definition: ipmux.c:65
#define IPM_UDP_PORT_MOD_SHIFT
Shift for module port.
Definition: dev_ipm.h:35
#define E_OUTOFMEMORY
Generic error: There is no more memory.
Definition: errorcode.h:107
This module is responsible for distributing error codes.
Various useful functions.
#define E_TIMEOUT
Generic error: Timeout error.
Definition: errorcode.h:100
#define IPM_FIFO_DATA_MASK
Data mask.
Definition: dev_ipm.h:62
#define LOG_DEF(NAME,...)
Define a logger for a module.
Definition: log.h:129
uint16_t prt[4]
Port numbers.
Definition: ipmux.h:32
This file assigns all device structures to memory mapped structures.
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
#define ERROR(CODE,...)
Expands an error code to an error code with a description (if ERROR_W_DESCR is declared).
#define IPM_FIFO_SOP
Start of packet marker.
Definition: dev_ipm.h:65
Implements a generic logger facility.
#define IPM_UDP_PORT_SVR_MASK
Mask for server port (target)
Definition: dev_ipm.h:32
#define IPMFIFO
IPMux FIFO.
Definition: dev_soc.h:72
#define IPM_FIFO_DATA_SHIFT
Data shift.
Definition: dev_ipm.h:63