uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lpc17xx-if.c
Go to the documentation of this file.
1 #include "lwip/opt.h"
2 
3 #include "lwip/def.h"
4 #include "lwip/mem.h"
5 #include "lwip/pbuf.h"
6 #include "lwip/sys.h"
7 #include <lwip/stats.h>
8 #include <lwip/snmp.h>
9 #include "netif/etharp.h"
10 #include "netif/ppp_oe.h"
11 #include "netif/lpc17xx-if.h"
12 
13 #include <lpc17xx_emac.h>
14 #include <lpc17xx_nvic.h>
15 #include <lpc17xx_pinsel.h>
16 
17 #define IFNAME0 'e'
18 #define IFNAME1 'x'
19 
20 extern uint8_t mac_address[6];
21 
22 /* Forward declarations. */
23 static void lpc17xx_if_input(struct netif *netif);
24 static void wait_DMA_slot();
25 
33 static int
34 low_level_init(struct netif *netif)
35 {
36  EMAC_CFG_Type EMAC_Config;
37  PINSEL_CFG_Type PinCfg;
38  uint32_t delay, retry;
39 
40  /* set MAC hardware address length */
41  netif->hwaddr_len = ETHARP_HWADDR_LEN;
42 
43  /* set MAC hardware address */
44  memcpy(netif->hwaddr, mac_address, 6);
45 
46  /* maximum transfer unit */
47  netif->mtu = 1500;
48 
49  /* device capabilities */
51 
52  /* initializing lpc17xx's emac. */
53  PinCfg.Funcnum = 1;
54  PinCfg.OpenDrain = 0;
55  PinCfg.Pinmode = 0;
56  PinCfg.Portnum = 1;
57 
58  PinCfg.Pinnum = 0; PINSEL_ConfigPin(&PinCfg);
59  PinCfg.Pinnum = 1; PINSEL_ConfigPin(&PinCfg);
60  PinCfg.Pinnum = 4; PINSEL_ConfigPin(&PinCfg);
61  PinCfg.Pinnum = 8; PINSEL_ConfigPin(&PinCfg);
62  PinCfg.Pinnum = 9; PINSEL_ConfigPin(&PinCfg);
63  PinCfg.Pinnum = 10; PINSEL_ConfigPin(&PinCfg);
64  PinCfg.Pinnum = 14; PINSEL_ConfigPin(&PinCfg);
65  PinCfg.Pinnum = 15; PINSEL_ConfigPin(&PinCfg);
66  PinCfg.Pinnum = 16; PINSEL_ConfigPin(&PinCfg);
67  PinCfg.Pinnum = 17; PINSEL_ConfigPin(&PinCfg);
68  EMAC_Config.Mode = EMAC_MODE_AUTO;
69  EMAC_Config.pbEMAC_Addr = netif->hwaddr;
70  for (retry = 0; retry < 500; retry++) {
71  if (EMAC_Init(&EMAC_Config) != ERROR)
72  return 1;
73  for(delay = 0x100000; delay; delay--);
74  }
75  return 0;
76 }
77 
94 static err_t
95 low_level_output(struct netif *netif, struct pbuf *p)
96 {
97  struct pbuf *q;
98  EMAC_PACKETBUF_Type TxPack;
99 
100 #if ETH_PAD_SIZE
101  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
102 #endif
103 
104  if (EMAC_CheckTransmitIndex() == FALSE) {
105  wait_DMA_slot();
106  }
107 
108  for(q = p; q != NULL; q = q->next) {
109  /* Send the data from the pbuf to the interface, one pbuf at a
110  time. The size of the data in each pbuf is kept in the ->len
111  variable. */
112  TxPack.ulDataLen = q->len;
113  TxPack.pbDataBuf = q->payload;
114  EMAC_WritePacketBuffer(&TxPack, FALSE);
115  }
116  TxPack.ulDataLen = 0;
117  TxPack.pbDataBuf = NULL;
118  EMAC_WritePacketBuffer(&TxPack, TRUE);
120 
121 #if ETH_PAD_SIZE
122  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
123 #endif
124 
125  LINK_STATS_INC(link.xmit);
126 
127  return ERR_OK;
128 }
129 
138 static struct pbuf *
139 low_level_input(struct netif *netif)
140 {
141  struct pbuf *p, *q;
142  u16_t len;
143 
144  if (EMAC_CheckReceiveIndex() == FALSE)
145  return NULL;
146 
147  /* Obtain the size of the packet and put it into the "len"
148  variable. */
149  len = EMAC_GetReceiveDataSize() + 1;
150 
151 #if ETH_PAD_SIZE
152  len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
153 #endif
154 
155  /* We allocate a pbuf chain of pbufs from the pool. */
156  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
157 
158  if (p != NULL) {
159 
160 #if ETH_PAD_SIZE
161  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
162 #endif
163 
164  /* We iterate over the pbuf chain until we have read the entire
165  * packet into the pbuf. */
166  for(q = p; q != NULL; q = q->next) {
167  /* Read enough bytes to fill this pbuf in the chain. The
168  * available data in the pbuf is given by the q->len
169  * variable.
170  * This does not necessarily have to be a memcpy, you can also preallocate
171  * pbufs for a DMA-enabled MAC and after receiving truncate it to the
172  * actually received size. In this case, ensure the tot_len member of the
173  * pbuf is the sum of the chained pbuf len members.
174  */
175  EMAC_PACKETBUF_Type RxPack;
176  RxPack.pbDataBuf = q->payload;
177  RxPack.ulDataLen = q->len;
178  EMAC_ReadPacketBuffer(&RxPack);
179  }
180 
181 #if ETH_PAD_SIZE
182  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
183 #endif
184 
185  LINK_STATS_INC(link.recv);
186  } else {
187  LINK_STATS_INC(link.memerr);
188  LINK_STATS_INC(link.drop);
189  }
191 
192  return p;
193 }
194 
204 static void
205 lpc17xx_if_input(struct netif *netif)
206 {
207  struct eth_hdr *ethhdr;
208  struct pbuf *p;
209 
210  /* move received packet into a new pbuf */
211  p = low_level_input(netif);
212  /* no packet could be read, silently ignore this */
213  if (p == NULL) return;
214  /* points to packet payload, which starts with an Ethernet header */
215  ethhdr = p->payload;
216 
217  switch (htons(ethhdr->type)) {
218  /* IP or ARP packet? */
219  case ETHTYPE_IP:
220  case ETHTYPE_ARP:
221 #if PPPOE_SUPPORT
222  /* PPPoE packet? */
223  case ETHTYPE_PPPOEDISC:
224  case ETHTYPE_PPPOE:
225 #endif /* PPPOE_SUPPORT */
226  /* full packet send to tcpip_thread to process */
227  if (netif->input(p, netif)!=ERR_OK)
228  { LWIP_DEBUGF(NETIF_DEBUG, ("lpc17xx_if_input: IP input error\n"));
229  pbuf_free(p);
230  p = NULL;
231  }
232  break;
233 
234  default:
235  pbuf_free(p);
236  p = NULL;
237  break;
238  }
239 }
240 
253 static int lpc17xx_if_got_init = 0;
254 
255 err_t
256 lpc17xx_if_init(struct netif *netif)
257 {
258  LWIP_ASSERT("netif != NULL", (netif != NULL));
259  /* We only have one EMAC on the lpc17xx, so... */
260  if (!__sync_bool_compare_and_swap(&lpc17xx_if_got_init, 0, 1))
261  return ERR_VAL;
262 
263 #if LWIP_NETIF_HOSTNAME
264  /* Initialize interface hostname */
265  netif->hostname = "lwip";
266 #endif /* LWIP_NETIF_HOSTNAME */
267 
268  /*
269  * Initialize the snmp variables and counters inside the struct netif.
270  * The last argument should be replaced with your link speed, in units
271  * of bits per second.
272  */
274 
275  netif->state = NULL;
276  netif->name[0] = IFNAME0;
277  netif->name[1] = IFNAME1;
278  /* We directly use etharp_output() here to save a function call.
279  * You can instead declare your own function an call etharp_output()
280  * from it if you have to do some checks before sending (e.g. if link
281  * is available...) */
282  netif->output = etharp_output;
283  netif->linkoutput = low_level_output;
284 
285  /* initialize the hardware */
286  if (!low_level_init(netif)) {
287  lpc17xx_if_got_init = 0;
288  return ERR_IF;
289  }
290 
291  return ERR_OK;
292 }
293 
295 
296 static void wait_DMA_slot(void) {
297  if (lpc17xx_if_waitdma)
299  while (EMAC_CheckTransmitIndex() == FALSE);
300 }
301 
302 void lpc17xx_if_check_input(struct netif * netif) {
303  lpc17xx_if_input(netif);
304 }
305 
306 __attribute__((section(".eth_ram"))) uint8_t lwip_ram_heap[5632];
307 
308 err_t interface_init(struct netif *netif) __attribute__((weak, alias ("lpc17xx_if_init")));
309 void interface_check_input(struct netif * netif) __attribute__((weak, alias ("lpc17xx_if_check_input")));