Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass
Date:
Thu Sep 19 13:26:14 2013 +0000
Revision:
68:0847e35d08a6
Child:
70:cd218dd180e5
Imported from masterbranch, again

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
tass 68:0847e35d08a6 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
tass 68:0847e35d08a6 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
tass 68:0847e35d08a6 5 .
tass 68:0847e35d08a6 6
tass 68:0847e35d08a6 7 Authors: Daniele Lacamera
tass 68:0847e35d08a6 8 *********************************************************************/
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10
tass 68:0847e35d08a6 11 #include "pico_config.h"
tass 68:0847e35d08a6 12 #include "pico_frame.h"
tass 68:0847e35d08a6 13 #include "pico_device.h"
tass 68:0847e35d08a6 14 #include "pico_protocol.h"
tass 68:0847e35d08a6 15 #include "pico_stack.h"
tass 68:0847e35d08a6 16 #include "pico_addressing.h"
tass 68:0847e35d08a6 17 #include "pico_dns_client.h"
tass 68:0847e35d08a6 18
tass 68:0847e35d08a6 19 #include "pico_eth.h"
tass 68:0847e35d08a6 20 #include "pico_arp.h"
tass 68:0847e35d08a6 21 #include "pico_ipv4.h"
tass 68:0847e35d08a6 22 #include "pico_ipv6.h"
tass 68:0847e35d08a6 23 #include "pico_icmp4.h"
tass 68:0847e35d08a6 24 #include "pico_igmp.h"
tass 68:0847e35d08a6 25 #include "pico_udp.h"
tass 68:0847e35d08a6 26 #include "pico_tcp.h"
tass 68:0847e35d08a6 27 #include "pico_socket.h"
tass 68:0847e35d08a6 28 #include "heap.h"
tass 68:0847e35d08a6 29
tass 68:0847e35d08a6 30 #define IS_LIMITED_BCAST(f) ( ((struct pico_ipv4_hdr *) f->net_hdr)->dst.addr == PICO_IP4_BCAST )
tass 68:0847e35d08a6 31
tass 68:0847e35d08a6 32 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 33 # define PICO_SIZE_MCAST 3
tass 68:0847e35d08a6 34 const uint8_t PICO_ETHADDR_MCAST[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
tass 68:0847e35d08a6 35 #endif
tass 68:0847e35d08a6 36
tass 68:0847e35d08a6 37 volatile unsigned long long pico_tick;
tass 68:0847e35d08a6 38 volatile pico_err_t pico_err;
tass 68:0847e35d08a6 39
tass 68:0847e35d08a6 40 static uint32_t _rand_seed;
tass 68:0847e35d08a6 41
tass 68:0847e35d08a6 42 void pico_rand_feed(uint32_t feed)
tass 68:0847e35d08a6 43 {
tass 68:0847e35d08a6 44 if (!feed)
tass 68:0847e35d08a6 45 return;
tass 68:0847e35d08a6 46 _rand_seed *= 1664525;
tass 68:0847e35d08a6 47 _rand_seed += 1013904223;
tass 68:0847e35d08a6 48 _rand_seed ^= ~(feed);
tass 68:0847e35d08a6 49 }
tass 68:0847e35d08a6 50
tass 68:0847e35d08a6 51 uint32_t pico_rand(void)
tass 68:0847e35d08a6 52 {
tass 68:0847e35d08a6 53 pico_rand_feed(pico_tick);
tass 68:0847e35d08a6 54 return _rand_seed;
tass 68:0847e35d08a6 55 }
tass 68:0847e35d08a6 56
tass 68:0847e35d08a6 57 /* NOTIFICATIONS: distributed notifications for stack internal errors.
tass 68:0847e35d08a6 58 */
tass 68:0847e35d08a6 59
tass 68:0847e35d08a6 60 int pico_notify_socket_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 61 {
tass 68:0847e35d08a6 62 if (0) {}
tass 68:0847e35d08a6 63 #ifdef PICO_SUPPORT_ICMP4
tass 68:0847e35d08a6 64 else if (IS_IPV4(f)) {
tass 68:0847e35d08a6 65 pico_icmp4_port_unreachable(f);
tass 68:0847e35d08a6 66 }
tass 68:0847e35d08a6 67 #endif
tass 68:0847e35d08a6 68 #ifdef PICO_SUPPORT_ICMP6
tass 68:0847e35d08a6 69 else if (IS_IPV6(f)) {
tass 68:0847e35d08a6 70 pico_icmp6_port_unreachable(f);
tass 68:0847e35d08a6 71 }
tass 68:0847e35d08a6 72 #endif
tass 68:0847e35d08a6 73
tass 68:0847e35d08a6 74 return 0;
tass 68:0847e35d08a6 75 }
tass 68:0847e35d08a6 76
tass 68:0847e35d08a6 77 int pico_notify_proto_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 78 {
tass 68:0847e35d08a6 79 if (0) {}
tass 68:0847e35d08a6 80 #ifdef PICO_SUPPORT_ICMP4
tass 68:0847e35d08a6 81 else if (IS_IPV4(f)) {
tass 68:0847e35d08a6 82 pico_icmp4_proto_unreachable(f);
tass 68:0847e35d08a6 83 }
tass 68:0847e35d08a6 84 #endif
tass 68:0847e35d08a6 85 #ifdef PICO_SUPPORT_ICMP6
tass 68:0847e35d08a6 86 else if (IS_IPV6(f)) {
tass 68:0847e35d08a6 87 pico_icmp6_proto_unreachable(f);
tass 68:0847e35d08a6 88 }
tass 68:0847e35d08a6 89 #endif
tass 68:0847e35d08a6 90 return 0;
tass 68:0847e35d08a6 91 }
tass 68:0847e35d08a6 92
tass 68:0847e35d08a6 93 int pico_notify_dest_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 94 {
tass 68:0847e35d08a6 95 if (0) {}
tass 68:0847e35d08a6 96 #ifdef PICO_SUPPORT_ICMP4
tass 68:0847e35d08a6 97 else if (IS_IPV4(f)) {
tass 68:0847e35d08a6 98 pico_icmp4_dest_unreachable(f);
tass 68:0847e35d08a6 99 }
tass 68:0847e35d08a6 100 #endif
tass 68:0847e35d08a6 101 #ifdef PICO_SUPPORT_ICMP6
tass 68:0847e35d08a6 102 else if (IS_IPV6(f)) {
tass 68:0847e35d08a6 103 pico_icmp6_dest_unreachable(f);
tass 68:0847e35d08a6 104 }
tass 68:0847e35d08a6 105 #endif
tass 68:0847e35d08a6 106 return 0;
tass 68:0847e35d08a6 107 }
tass 68:0847e35d08a6 108
tass 68:0847e35d08a6 109 int pico_notify_ttl_expired(struct pico_frame *f)
tass 68:0847e35d08a6 110 {
tass 68:0847e35d08a6 111 if (0) {}
tass 68:0847e35d08a6 112 #ifdef PICO_SUPPORT_ICMP4
tass 68:0847e35d08a6 113 else if (IS_IPV4(f)) {
tass 68:0847e35d08a6 114 pico_icmp4_ttl_expired(f);
tass 68:0847e35d08a6 115 }
tass 68:0847e35d08a6 116 #endif
tass 68:0847e35d08a6 117 #ifdef PICO_SUPPORT_ICMP6
tass 68:0847e35d08a6 118 else if (IS_IPV6(f)) {
tass 68:0847e35d08a6 119 pico_icmp6_ttl_expired(f);
tass 68:0847e35d08a6 120 }
tass 68:0847e35d08a6 121 #endif
tass 68:0847e35d08a6 122 return 0;
tass 68:0847e35d08a6 123 }
tass 68:0847e35d08a6 124
tass 68:0847e35d08a6 125
tass 68:0847e35d08a6 126 /* Transport layer */
tass 68:0847e35d08a6 127 int pico_transport_receive(struct pico_frame *f, uint8_t proto)
tass 68:0847e35d08a6 128 {
tass 68:0847e35d08a6 129 int ret = -1;
tass 68:0847e35d08a6 130 switch (proto) {
tass 68:0847e35d08a6 131
tass 68:0847e35d08a6 132 #ifdef PICO_SUPPORT_ICMP4
tass 68:0847e35d08a6 133 case PICO_PROTO_ICMP4:
tass 68:0847e35d08a6 134 ret = pico_enqueue(pico_proto_icmp4.q_in, f);
tass 68:0847e35d08a6 135 break;
tass 68:0847e35d08a6 136 #endif
tass 68:0847e35d08a6 137
tass 68:0847e35d08a6 138 #ifdef PICO_SUPPORT_IGMP
tass 68:0847e35d08a6 139 case PICO_PROTO_IGMP:
tass 68:0847e35d08a6 140 ret = pico_enqueue(pico_proto_igmp.q_in, f);
tass 68:0847e35d08a6 141 break;
tass 68:0847e35d08a6 142 #endif
tass 68:0847e35d08a6 143
tass 68:0847e35d08a6 144 #ifdef PICO_SUPPORT_UDP
tass 68:0847e35d08a6 145 case PICO_PROTO_UDP:
tass 68:0847e35d08a6 146 ret = pico_enqueue(pico_proto_udp.q_in, f);
tass 68:0847e35d08a6 147 break;
tass 68:0847e35d08a6 148 #endif
tass 68:0847e35d08a6 149
tass 68:0847e35d08a6 150 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 151 case PICO_PROTO_TCP:
tass 68:0847e35d08a6 152 ret = pico_enqueue(pico_proto_tcp.q_in, f);
tass 68:0847e35d08a6 153 break;
tass 68:0847e35d08a6 154 #endif
tass 68:0847e35d08a6 155
tass 68:0847e35d08a6 156 default:
tass 68:0847e35d08a6 157 /* Protocol not available */
tass 68:0847e35d08a6 158 dbg("pkt: no such protocol (%d)\n", proto);
tass 68:0847e35d08a6 159 pico_notify_proto_unreachable(f);
tass 68:0847e35d08a6 160 pico_frame_discard(f);
tass 68:0847e35d08a6 161 ret = -1;
tass 68:0847e35d08a6 162 }
tass 68:0847e35d08a6 163 return ret;
tass 68:0847e35d08a6 164 }
tass 68:0847e35d08a6 165
tass 68:0847e35d08a6 166 int pico_transport_send(struct pico_frame *f)
tass 68:0847e35d08a6 167 {
tass 68:0847e35d08a6 168 if (!f || !f->sock || !f->sock->proto) {
tass 68:0847e35d08a6 169 pico_frame_discard(f);
tass 68:0847e35d08a6 170 return -1;
tass 68:0847e35d08a6 171 }
tass 68:0847e35d08a6 172 return f->sock->proto->push(f->sock->net, f);
tass 68:0847e35d08a6 173 }
tass 68:0847e35d08a6 174
tass 68:0847e35d08a6 175 int pico_network_receive(struct pico_frame *f)
tass 68:0847e35d08a6 176 {
tass 68:0847e35d08a6 177 if (0) {}
tass 68:0847e35d08a6 178 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 179 else if (IS_IPV4(f)) {
tass 68:0847e35d08a6 180 pico_enqueue(pico_proto_ipv4.q_in, f);
tass 68:0847e35d08a6 181 }
tass 68:0847e35d08a6 182 #endif
tass 68:0847e35d08a6 183 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 184 else if (IS_IPV6(f)) {
tass 68:0847e35d08a6 185 pico_enqueue(pico_proto_ipv6.q_in, f);
tass 68:0847e35d08a6 186 }
tass 68:0847e35d08a6 187 #endif
tass 68:0847e35d08a6 188 else {
tass 68:0847e35d08a6 189 dbg("Network not found.\n");
tass 68:0847e35d08a6 190 pico_frame_discard(f);
tass 68:0847e35d08a6 191 return -1;
tass 68:0847e35d08a6 192 }
tass 68:0847e35d08a6 193 return f->buffer_len;
tass 68:0847e35d08a6 194 }
tass 68:0847e35d08a6 195
tass 68:0847e35d08a6 196
tass 68:0847e35d08a6 197 /* Network layer: interface towards socket for frame sending */
tass 68:0847e35d08a6 198 int pico_network_send(struct pico_frame *f)
tass 68:0847e35d08a6 199 {
tass 68:0847e35d08a6 200 if (!f || !f->sock || !f->sock->net) {
tass 68:0847e35d08a6 201 pico_frame_discard(f);
tass 68:0847e35d08a6 202 return -1;
tass 68:0847e35d08a6 203 }
tass 68:0847e35d08a6 204 return f->sock->net->push(f->sock->net, f);
tass 68:0847e35d08a6 205 }
tass 68:0847e35d08a6 206
tass 68:0847e35d08a6 207 int pico_destination_is_local(struct pico_frame *f)
tass 68:0847e35d08a6 208 {
tass 68:0847e35d08a6 209 if (0) { }
tass 68:0847e35d08a6 210 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 211 else if (IS_IPV4(f)) {
tass 68:0847e35d08a6 212 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 68:0847e35d08a6 213 if (pico_ipv4_link_find(&hdr->dst))
tass 68:0847e35d08a6 214 return 1;
tass 68:0847e35d08a6 215 }
tass 68:0847e35d08a6 216 #endif
tass 68:0847e35d08a6 217 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 218 else if (IS_IPV6(f)) {
tass 68:0847e35d08a6 219 }
tass 68:0847e35d08a6 220 #endif
tass 68:0847e35d08a6 221 return 0;
tass 68:0847e35d08a6 222 }
tass 68:0847e35d08a6 223
tass 68:0847e35d08a6 224 int pico_source_is_local(struct pico_frame *f)
tass 68:0847e35d08a6 225 {
tass 68:0847e35d08a6 226 if (0) { }
tass 68:0847e35d08a6 227 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 228 else if (IS_IPV4(f)) {
tass 68:0847e35d08a6 229 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 68:0847e35d08a6 230 if (hdr->src.addr == PICO_IPV4_INADDR_ANY)
tass 68:0847e35d08a6 231 return 1;
tass 68:0847e35d08a6 232 if (pico_ipv4_link_find(&hdr->src))
tass 68:0847e35d08a6 233 return 1;
tass 68:0847e35d08a6 234 }
tass 68:0847e35d08a6 235 #endif
tass 68:0847e35d08a6 236 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 237 else if (IS_IPV6(f)) {
tass 68:0847e35d08a6 238 /* XXX */
tass 68:0847e35d08a6 239 }
tass 68:0847e35d08a6 240 #endif
tass 68:0847e35d08a6 241 return 0;
tass 68:0847e35d08a6 242
tass 68:0847e35d08a6 243
tass 68:0847e35d08a6 244 }
tass 68:0847e35d08a6 245
tass 68:0847e35d08a6 246
tass 68:0847e35d08a6 247 /* DATALINK LEVEL: interface from network to the device
tass 68:0847e35d08a6 248 * and vice versa.
tass 68:0847e35d08a6 249 */
tass 68:0847e35d08a6 250
tass 68:0847e35d08a6 251 /* The pico_ethernet_receive() function is used by
tass 68:0847e35d08a6 252 * those devices supporting ETH in order to push packets up
tass 68:0847e35d08a6 253 * into the stack.
tass 68:0847e35d08a6 254 */
tass 68:0847e35d08a6 255 int pico_ethernet_receive(struct pico_frame *f)
tass 68:0847e35d08a6 256 {
tass 68:0847e35d08a6 257 struct pico_eth_hdr *hdr;
tass 68:0847e35d08a6 258 if (!f || !f->dev || !f->datalink_hdr)
tass 68:0847e35d08a6 259 goto discard;
tass 68:0847e35d08a6 260 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
tass 68:0847e35d08a6 261 if ( (memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) &&
tass 68:0847e35d08a6 262 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 263 (memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) &&
tass 68:0847e35d08a6 264 #endif
tass 68:0847e35d08a6 265 (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0) )
tass 68:0847e35d08a6 266 goto discard;
tass 68:0847e35d08a6 267
tass 68:0847e35d08a6 268 f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
tass 68:0847e35d08a6 269 if (hdr->proto == PICO_IDETH_ARP)
tass 68:0847e35d08a6 270 return pico_arp_receive(f);
tass 68:0847e35d08a6 271 if ((hdr->proto == PICO_IDETH_IPV4) || (hdr->proto == PICO_IDETH_IPV6))
tass 68:0847e35d08a6 272 return pico_network_receive(f);
tass 68:0847e35d08a6 273 discard:
tass 68:0847e35d08a6 274 pico_frame_discard(f);
tass 68:0847e35d08a6 275 return -1;
tass 68:0847e35d08a6 276 }
tass 68:0847e35d08a6 277
tass 68:0847e35d08a6 278 static int destination_is_bcast(struct pico_frame *f)
tass 68:0847e35d08a6 279 {
tass 68:0847e35d08a6 280 if (!f)
tass 68:0847e35d08a6 281 return 0;
tass 68:0847e35d08a6 282
tass 68:0847e35d08a6 283 if (IS_IPV6(f))
tass 68:0847e35d08a6 284 return 0;
tass 68:0847e35d08a6 285 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 286 else {
tass 68:0847e35d08a6 287 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 68:0847e35d08a6 288 return pico_ipv4_is_broadcast(hdr->dst.addr);
tass 68:0847e35d08a6 289 }
tass 68:0847e35d08a6 290 #endif
tass 68:0847e35d08a6 291 return 0;
tass 68:0847e35d08a6 292 }
tass 68:0847e35d08a6 293
tass 68:0847e35d08a6 294 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 295 static int destination_is_mcast(struct pico_frame *f)
tass 68:0847e35d08a6 296 {
tass 68:0847e35d08a6 297 if (!f)
tass 68:0847e35d08a6 298 return 0;
tass 68:0847e35d08a6 299
tass 68:0847e35d08a6 300 if (IS_IPV6(f))
tass 68:0847e35d08a6 301 return 0;
tass 68:0847e35d08a6 302 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 303 else {
tass 68:0847e35d08a6 304 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 68:0847e35d08a6 305 return pico_ipv4_is_multicast(hdr->dst.addr);
tass 68:0847e35d08a6 306 }
tass 68:0847e35d08a6 307 #endif
tass 68:0847e35d08a6 308 return 0;
tass 68:0847e35d08a6 309 }
tass 68:0847e35d08a6 310
tass 68:0847e35d08a6 311 static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac)
tass 68:0847e35d08a6 312 {
tass 68:0847e35d08a6 313 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 68:0847e35d08a6 314
tass 68:0847e35d08a6 315 /* place 23 lower bits of IP in lower 23 bits of MAC */
tass 68:0847e35d08a6 316 pico_mcast_mac[5] = (long_be(hdr->dst.addr) & 0x000000FF);
tass 68:0847e35d08a6 317 pico_mcast_mac[4] = (long_be(hdr->dst.addr) & 0x0000FF00) >> 8;
tass 68:0847e35d08a6 318 pico_mcast_mac[3] = (long_be(hdr->dst.addr) & 0x007F0000) >> 16;
tass 68:0847e35d08a6 319
tass 68:0847e35d08a6 320 return (struct pico_eth *)pico_mcast_mac;
tass 68:0847e35d08a6 321 }
tass 68:0847e35d08a6 322
tass 68:0847e35d08a6 323
tass 68:0847e35d08a6 324 #endif /* PICO_SUPPORT_MCAST */
tass 68:0847e35d08a6 325
tass 68:0847e35d08a6 326 /* This is called by dev loop in order to ensure correct ethernet addressing.
tass 68:0847e35d08a6 327 * Returns 0 if the destination is unknown, and -1 if the packet is not deliverable
tass 68:0847e35d08a6 328 * due to ethernet addressing (i.e., no arp association was possible.
tass 68:0847e35d08a6 329 *
tass 68:0847e35d08a6 330 * Only IP packets must pass by this. ARP will always use direct dev->send() function, so
tass 68:0847e35d08a6 331 * we assume IP is used.
tass 68:0847e35d08a6 332 */
tass 68:0847e35d08a6 333 int pico_ethernet_send(struct pico_frame *f)
tass 68:0847e35d08a6 334 {
tass 68:0847e35d08a6 335 const struct pico_eth *dstmac = NULL;
tass 68:0847e35d08a6 336 int ret = -1;
tass 68:0847e35d08a6 337
tass 68:0847e35d08a6 338 if (IS_IPV6(f)) {
tass 68:0847e35d08a6 339 /*TODO: Neighbor solicitation */
tass 68:0847e35d08a6 340 dstmac = NULL;
tass 68:0847e35d08a6 341 }
tass 68:0847e35d08a6 342
tass 68:0847e35d08a6 343 else if (IS_IPV4(f)) {
tass 68:0847e35d08a6 344 if (IS_BCAST(f) || destination_is_bcast(f)) {
tass 68:0847e35d08a6 345 dstmac = (const struct pico_eth *const) PICO_ETHADDR_ALL;
tass 68:0847e35d08a6 346 }
tass 68:0847e35d08a6 347 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 348 else if (destination_is_mcast(f)) {
tass 68:0847e35d08a6 349 uint8_t pico_mcast_mac[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
tass 68:0847e35d08a6 350 dstmac = pico_ethernet_mcast_translate(f, pico_mcast_mac);
tass 68:0847e35d08a6 351 }
tass 68:0847e35d08a6 352 #endif
tass 68:0847e35d08a6 353 else {
tass 68:0847e35d08a6 354 dstmac = pico_arp_get(f);
tass 68:0847e35d08a6 355 if (!dstmac)
tass 68:0847e35d08a6 356 return 0;
tass 68:0847e35d08a6 357 }
tass 68:0847e35d08a6 358 /* This sets destination and source address, then pushes the packet to the device. */
tass 68:0847e35d08a6 359 if (dstmac && (f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR)) {
tass 68:0847e35d08a6 360 struct pico_eth_hdr *hdr;
tass 68:0847e35d08a6 361 f->start -= PICO_SIZE_ETHHDR;
tass 68:0847e35d08a6 362 f->len += PICO_SIZE_ETHHDR;
tass 68:0847e35d08a6 363 f->datalink_hdr = f->start;
tass 68:0847e35d08a6 364 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
tass 68:0847e35d08a6 365 memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH);
tass 68:0847e35d08a6 366 memcpy(hdr->daddr, dstmac, PICO_SIZE_ETH);
tass 68:0847e35d08a6 367 hdr->proto = PICO_IDETH_IPV4;
tass 68:0847e35d08a6 368 if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)){
tass 68:0847e35d08a6 369 dbg("sending out packet destined for our own mac\n");
tass 68:0847e35d08a6 370 return pico_ethernet_receive(f);
tass 68:0847e35d08a6 371 }else if(IS_LIMITED_BCAST(f)){
tass 68:0847e35d08a6 372 ret = pico_device_broadcast(f);
tass 68:0847e35d08a6 373 }else {
tass 68:0847e35d08a6 374 ret = f->dev->send(f->dev, f->start, f->len);
tass 68:0847e35d08a6 375 /* Frame is discarded after this return by the caller */
tass 68:0847e35d08a6 376 }
tass 68:0847e35d08a6 377
tass 68:0847e35d08a6 378 if(!ret) pico_frame_discard(f);
tass 68:0847e35d08a6 379 return ret;
tass 68:0847e35d08a6 380 } else {
tass 68:0847e35d08a6 381 return -1;
tass 68:0847e35d08a6 382 }
tass 68:0847e35d08a6 383 } /* End IPV4 ethernet addressing */
tass 68:0847e35d08a6 384 return -1;
tass 68:0847e35d08a6 385
tass 68:0847e35d08a6 386 }
tass 68:0847e35d08a6 387
tass 68:0847e35d08a6 388 void pico_store_network_origin(void *src, struct pico_frame *f)
tass 68:0847e35d08a6 389 {
tass 68:0847e35d08a6 390 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 391 struct pico_ip4 *ip4;
tass 68:0847e35d08a6 392 #endif
tass 68:0847e35d08a6 393
tass 68:0847e35d08a6 394 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 395 struct pico_ip6 *ip6;
tass 68:0847e35d08a6 396 #endif
tass 68:0847e35d08a6 397
tass 68:0847e35d08a6 398 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 399 if (IS_IPV4(f)) {
tass 68:0847e35d08a6 400 struct pico_ipv4_hdr *hdr;
tass 68:0847e35d08a6 401 hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 68:0847e35d08a6 402 ip4 = (struct pico_ip4 *) src;
tass 68:0847e35d08a6 403 ip4->addr = hdr->src.addr;
tass 68:0847e35d08a6 404 }
tass 68:0847e35d08a6 405 #endif
tass 68:0847e35d08a6 406 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 407 if (IS_IPV6(f)) {
tass 68:0847e35d08a6 408 struct pico_ipv6_hdr *hdr;
tass 68:0847e35d08a6 409 hdr = (struct pico_ipv6_hdr *) f->net_hdr;
tass 68:0847e35d08a6 410 ip6 = (struct pico_ip6 *) src;
tass 68:0847e35d08a6 411 memcpy(ip6->addr, hdr->src.addr, PICO_SIZE_IP6);
tass 68:0847e35d08a6 412 }
tass 68:0847e35d08a6 413 #endif
tass 68:0847e35d08a6 414 }
tass 68:0847e35d08a6 415
tass 68:0847e35d08a6 416
tass 68:0847e35d08a6 417 /* LOWEST LEVEL: interface towards devices. */
tass 68:0847e35d08a6 418 /* Device driver will call this function which returns immediately.
tass 68:0847e35d08a6 419 * Incoming packet will be processed later on in the dev loop.
tass 68:0847e35d08a6 420 */
tass 68:0847e35d08a6 421 int pico_stack_recv(struct pico_device *dev, uint8_t *buffer, int len)
tass 68:0847e35d08a6 422 {
tass 68:0847e35d08a6 423 struct pico_frame *f;
tass 68:0847e35d08a6 424 int ret;
tass 68:0847e35d08a6 425 if (len <= 0)
tass 68:0847e35d08a6 426 return -1;
tass 68:0847e35d08a6 427 f = pico_frame_alloc(len);
tass 68:0847e35d08a6 428 if (!f)
tass 68:0847e35d08a6 429 return -1;
tass 68:0847e35d08a6 430
tass 68:0847e35d08a6 431 /* Association to the device that just received the frame. */
tass 68:0847e35d08a6 432 f->dev = dev;
tass 68:0847e35d08a6 433
tass 68:0847e35d08a6 434 /* Setup the start pointer, lenght. */
tass 68:0847e35d08a6 435 f->start = f->buffer;
tass 68:0847e35d08a6 436 f->len = f->buffer_len;
tass 68:0847e35d08a6 437 if (f->len > 8) {
tass 68:0847e35d08a6 438 int mid_frame = (f->buffer_len >> 2)<<1;
tass 68:0847e35d08a6 439 mid_frame -= (mid_frame % 4);
tass 68:0847e35d08a6 440 pico_rand_feed(*(uint32_t*)(f->buffer + mid_frame));
tass 68:0847e35d08a6 441 }
tass 68:0847e35d08a6 442 memcpy(f->buffer, buffer, len);
tass 68:0847e35d08a6 443 ret = pico_enqueue(dev->q_in, f);
tass 68:0847e35d08a6 444 if (ret <= 0) {
tass 68:0847e35d08a6 445 pico_frame_discard(f);
tass 68:0847e35d08a6 446 }
tass 68:0847e35d08a6 447 return ret;
tass 68:0847e35d08a6 448 }
tass 68:0847e35d08a6 449
tass 68:0847e35d08a6 450 int pico_sendto_dev(struct pico_frame *f)
tass 68:0847e35d08a6 451 {
tass 68:0847e35d08a6 452 if (!f->dev) {
tass 68:0847e35d08a6 453 pico_frame_discard(f);
tass 68:0847e35d08a6 454 return -1;
tass 68:0847e35d08a6 455 } else {
tass 68:0847e35d08a6 456 if (f->len > 8) {
tass 68:0847e35d08a6 457 int mid_frame = (f->buffer_len >> 2)<<1;
tass 68:0847e35d08a6 458 mid_frame -= (mid_frame % 4);
tass 68:0847e35d08a6 459 pico_rand_feed(*(uint32_t*)(f->buffer + mid_frame));
tass 68:0847e35d08a6 460 }
tass 68:0847e35d08a6 461 return pico_enqueue(f->dev->q_out, f);
tass 68:0847e35d08a6 462 }
tass 68:0847e35d08a6 463 }
tass 68:0847e35d08a6 464
tass 68:0847e35d08a6 465 struct pico_timer
tass 68:0847e35d08a6 466 {
tass 68:0847e35d08a6 467 unsigned long expire;
tass 68:0847e35d08a6 468 void *arg;
tass 68:0847e35d08a6 469 void (*timer)(unsigned long timestamp, void *arg);
tass 68:0847e35d08a6 470 };
tass 68:0847e35d08a6 471
tass 68:0847e35d08a6 472 typedef struct pico_timer pico_timer;
tass 68:0847e35d08a6 473
tass 68:0847e35d08a6 474 DECLARE_HEAP(pico_timer, expire);
tass 68:0847e35d08a6 475
tass 68:0847e35d08a6 476 static heap_pico_timer *Timers;
tass 68:0847e35d08a6 477
tass 68:0847e35d08a6 478 void pico_check_timers(void)
tass 68:0847e35d08a6 479 {
tass 68:0847e35d08a6 480 struct pico_timer timer;
tass 68:0847e35d08a6 481 struct pico_timer *t = heap_first(Timers);
tass 68:0847e35d08a6 482 pico_tick = PICO_TIME_MS();
tass 68:0847e35d08a6 483 while((t) && (t->expire < pico_tick)) {
tass 68:0847e35d08a6 484 t->timer(pico_tick, t->arg);
tass 68:0847e35d08a6 485 heap_peek(Timers, &timer);
tass 68:0847e35d08a6 486 t = heap_first(Timers);
tass 68:0847e35d08a6 487 }
tass 68:0847e35d08a6 488 }
tass 68:0847e35d08a6 489
tass 68:0847e35d08a6 490
tass 68:0847e35d08a6 491 #define PROTO_DEF_NR 11
tass 68:0847e35d08a6 492 #define PROTO_DEF_AVG_NR 4
tass 68:0847e35d08a6 493 #define PROTO_DEF_SCORE 32
tass 68:0847e35d08a6 494 #define PROTO_MIN_SCORE 32
tass 68:0847e35d08a6 495 #define PROTO_MAX_SCORE 128
tass 68:0847e35d08a6 496 #define PROTO_LAT_IND 3 /* latecy indication 0-3 (lower is better latency performance), x1, x2, x4, x8 */
tass 68:0847e35d08a6 497 #define PROTO_MAX_LOOP (PROTO_MAX_SCORE<<PROTO_LAT_IND) /* max global loop score, so per tick */
tass 68:0847e35d08a6 498
tass 68:0847e35d08a6 499 static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret)
tass 68:0847e35d08a6 500 {
tass 68:0847e35d08a6 501 int temp, i, j, sum;
tass 68:0847e35d08a6 502 int max_total = PROTO_MAX_LOOP, total = 0;
tass 68:0847e35d08a6 503
tass 68:0847e35d08a6 504 //dbg("USED SCORES> ");
tass 68:0847e35d08a6 505
tass 68:0847e35d08a6 506 for (i = 0; i < PROTO_DEF_NR; i++) {
tass 68:0847e35d08a6 507
tass 68:0847e35d08a6 508 /* if used looped score */
tass 68:0847e35d08a6 509 if (ret[i] < score[i]) {
tass 68:0847e35d08a6 510 temp = score[i] - ret[i]; /* remaining loop score */
tass 68:0847e35d08a6 511
tass 68:0847e35d08a6 512 //dbg("%3d - ",temp);
tass 68:0847e35d08a6 513
tass 68:0847e35d08a6 514 if (index[i] >= PROTO_DEF_AVG_NR)
tass 68:0847e35d08a6 515 index[i] = 0; /* reset index */
tass 68:0847e35d08a6 516 j = index[i];
tass 68:0847e35d08a6 517 avg[i][j] = temp;
tass 68:0847e35d08a6 518
tass 68:0847e35d08a6 519 index[i]++;
tass 68:0847e35d08a6 520
tass 68:0847e35d08a6 521 if (ret[i] == 0 && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total) ) { /* used all loop score -> increase next score directly */
tass 68:0847e35d08a6 522 score[i] <<= 1;
tass 68:0847e35d08a6 523 total += score[i];
tass 68:0847e35d08a6 524 continue;
tass 68:0847e35d08a6 525 }
tass 68:0847e35d08a6 526
tass 68:0847e35d08a6 527 sum = 0;
tass 68:0847e35d08a6 528 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
tass 68:0847e35d08a6 529 sum += avg[i][j]; /* calculate sum */
tass 68:0847e35d08a6 530
tass 68:0847e35d08a6 531 sum >>= 2; /* divide by 4 to get average used score */
tass 68:0847e35d08a6 532
tass 68:0847e35d08a6 533 /* criterion to increase next loop score */
tass 68:0847e35d08a6 534 if (sum > (score[i] - (score[i]>>2)) && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total)) { /* > 3/4 */
tass 68:0847e35d08a6 535 score[i] <<= 1; /* double loop score */
tass 68:0847e35d08a6 536 total += score[i];
tass 68:0847e35d08a6 537 continue;
tass 68:0847e35d08a6 538 }
tass 68:0847e35d08a6 539
tass 68:0847e35d08a6 540 /* criterion to decrease next loop score */
tass 68:0847e35d08a6 541 if (sum < (score[i]>>2) && (score[i]>>1 >= PROTO_MIN_SCORE)) { /* < 1/4 */
tass 68:0847e35d08a6 542 score[i] >>= 1; /* half loop score */
tass 68:0847e35d08a6 543 total += score[i];
tass 68:0847e35d08a6 544 continue;
tass 68:0847e35d08a6 545 }
tass 68:0847e35d08a6 546
tass 68:0847e35d08a6 547 /* also add non-changed scores */
tass 68:0847e35d08a6 548 total += score[i];
tass 68:0847e35d08a6 549 }
tass 68:0847e35d08a6 550 else if (ret[i] == score[i]) {
tass 68:0847e35d08a6 551 /* no used loop score - gradually decrease */
tass 68:0847e35d08a6 552
tass 68:0847e35d08a6 553 // dbg("%3d - ",0);
tass 68:0847e35d08a6 554
tass 68:0847e35d08a6 555 if (index[i] >= PROTO_DEF_AVG_NR)
tass 68:0847e35d08a6 556 index[i] = 0; /* reset index */
tass 68:0847e35d08a6 557 j = index[i];
tass 68:0847e35d08a6 558 avg[i][j] = 0;
tass 68:0847e35d08a6 559
tass 68:0847e35d08a6 560 index[i]++;
tass 68:0847e35d08a6 561
tass 68:0847e35d08a6 562 sum = 0;
tass 68:0847e35d08a6 563 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
tass 68:0847e35d08a6 564 sum += avg[i][j]; /* calculate sum */
tass 68:0847e35d08a6 565
tass 68:0847e35d08a6 566 sum >>= 2; /* divide by 4 to get average used score */
tass 68:0847e35d08a6 567
tass 68:0847e35d08a6 568 if ((sum == 0) && (score[i]>>1 >= PROTO_MIN_SCORE)) {
tass 68:0847e35d08a6 569 score[i] >>= 1; /* half loop score */
tass 68:0847e35d08a6 570 total += score[i];
tass 68:0847e35d08a6 571 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
tass 68:0847e35d08a6 572 avg[i][j] = score[i];
tass 68:0847e35d08a6 573 }
tass 68:0847e35d08a6 574
tass 68:0847e35d08a6 575 }
tass 68:0847e35d08a6 576 }
tass 68:0847e35d08a6 577
tass 68:0847e35d08a6 578 //dbg("\n");
tass 68:0847e35d08a6 579
tass 68:0847e35d08a6 580 return 0;
tass 68:0847e35d08a6 581 }
tass 68:0847e35d08a6 582
tass 68:0847e35d08a6 583
tass 68:0847e35d08a6 584
tass 68:0847e35d08a6 585 /*
tass 68:0847e35d08a6 586
tass 68:0847e35d08a6 587 .
tass 68:0847e35d08a6 588 .vS.
tass 68:0847e35d08a6 589 <aoSo.
tass 68:0847e35d08a6 590 .XoS22.
tass 68:0847e35d08a6 591 .S2S22. ._... ...... ..._.
tass 68:0847e35d08a6 592 :=|2S2X2|=++; <vSX2XX2z+ |vSSSXSSs>. :iXXZUZXXe=
tass 68:0847e35d08a6 593 )2SS2SS2S2S2I =oS2S2S2S2X22;. _vuXS22S2S2S22i ._wZZXZZZXZZXZX=
tass 68:0847e35d08a6 594 )22S2S2S2S2Sl |S2S2S22S2SSSXc: .S2SS2S2S22S2SS= .]#XZZZXZXZZZZZZ:
tass 68:0847e35d08a6 595 )oSS2SS2S2Sol |2}!"""!32S22S(. uS2S2Se**12oS2e ]dXZZXX2?YYXXXZ*
tass 68:0847e35d08a6 596 .:2S2So:..-. . :]S2S2e;=X2SS2o .)oc ]XZZXZ( =nX:
tass 68:0847e35d08a6 597 .S2S22. ___s_i,.)oS2So(;2SS2So, ` 3XZZZZc, -
tass 68:0847e35d08a6 598 .S2SSo. =oXXXSSS2XoS2S2o( XS2S2XSos;. ]ZZZZXXXX|=
tass 68:0847e35d08a6 599 .S2S22. .)S2S2S22S2S2S2S2o( "X2SS2S2S2Sus,, +3XZZZZZXZZoos_
tass 68:0847e35d08a6 600 .S2S22. .]2S2SS22S222S2SS2o( ]S22S2S2S222So :3XXZZZZZZZZXXv
tass 68:0847e35d08a6 601 .S2S22. =u2SS2e"~---"{2S2So( -"12S2S2SSS2Su. "?SXXXZXZZZZXo
tass 68:0847e35d08a6 602 .S2SSo. )SS22z; :S2S2o( ={vS2S2S22v .<vXZZZZZZZ;
tass 68:0847e35d08a6 603 .S2S2S: ]oSS2c; =22S2o( -"S2SS2n ~4XXZXZ(
tass 68:0847e35d08a6 604 .2S2S2i )2S2S2[. .)XS2So( <;. .2S2S2o :<. ]XZZZX(
tass 68:0847e35d08a6 605 nX2S2S,,_s_=3oSS2SoaasuXXS2S2o( .oXoasi_aioSSS22l.]dZoaas_aadXZZXZ'
tass 68:0847e35d08a6 606 vS2SSSXXX2; )S2S2S2SoS2S2S2S2o( iS2S222XSoSS22So.)nXZZXXXZZXXZZXZo
tass 68:0847e35d08a6 607 +32S22S2Sn -+S2S2S2S2So22S2So( 12S2SS2S2SS22S}- )SXXZZZZZZZZZXX!-
tass 68:0847e35d08a6 608 .)S22222i .i2S2S2o>;:S2S2o( .<vSoSoSo2S(; :nXXXXXZXXX(
tass 68:0847e35d08a6 609 .-~~~~- --- . - - --~~~-- --^^~~-
tass 68:0847e35d08a6 610 .
tass 68:0847e35d08a6 611
tass 68:0847e35d08a6 612
tass 68:0847e35d08a6 613 ... curious about our source code? We are hiring! mailto:<recruiting@tass.be>
tass 68:0847e35d08a6 614
tass 68:0847e35d08a6 615
tass 68:0847e35d08a6 616 */
tass 68:0847e35d08a6 617
tass 68:0847e35d08a6 618 void pico_stack_tick(void)
tass 68:0847e35d08a6 619 {
tass 68:0847e35d08a6 620 static int score[PROTO_DEF_NR] = {PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE};
tass 68:0847e35d08a6 621 static int index[PROTO_DEF_NR] = {0,0,0,0,0,0};
tass 68:0847e35d08a6 622 static int avg[PROTO_DEF_NR][PROTO_DEF_AVG_NR];
tass 68:0847e35d08a6 623 static int ret[PROTO_DEF_NR] = {0};
tass 68:0847e35d08a6 624
tass 68:0847e35d08a6 625 pico_check_timers();
tass 68:0847e35d08a6 626
tass 68:0847e35d08a6 627 //dbg("LOOP_SCORES> %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d\n",score[0],score[1],score[2],score[3],score[4],score[5],score[6],score[7],score[8],score[9],score[10]);
tass 68:0847e35d08a6 628
tass 68:0847e35d08a6 629 //score = pico_protocols_loop(100);
tass 68:0847e35d08a6 630
tass 68:0847e35d08a6 631 ret[0] = pico_devices_loop(score[0],PICO_LOOP_DIR_IN);
tass 68:0847e35d08a6 632 pico_rand_feed(ret[0]);
tass 68:0847e35d08a6 633
tass 68:0847e35d08a6 634 ret[1] = pico_protocol_datalink_loop(score[1], PICO_LOOP_DIR_IN);
tass 68:0847e35d08a6 635 pico_rand_feed(ret[1]);
tass 68:0847e35d08a6 636
tass 68:0847e35d08a6 637 ret[2] = pico_protocol_network_loop(score[2], PICO_LOOP_DIR_IN);
tass 68:0847e35d08a6 638 pico_rand_feed(ret[2]);
tass 68:0847e35d08a6 639
tass 68:0847e35d08a6 640 ret[3] = pico_protocol_transport_loop(score[3], PICO_LOOP_DIR_IN);
tass 68:0847e35d08a6 641 pico_rand_feed(ret[3]);
tass 68:0847e35d08a6 642
tass 68:0847e35d08a6 643
tass 68:0847e35d08a6 644 ret[5] = score[5];
tass 68:0847e35d08a6 645 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
tass 68:0847e35d08a6 646 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
tass 68:0847e35d08a6 647 ret[5] = pico_sockets_loop(score[5]); // swapped
tass 68:0847e35d08a6 648 pico_rand_feed(ret[5]);
tass 68:0847e35d08a6 649 #endif
tass 68:0847e35d08a6 650 #endif
tass 68:0847e35d08a6 651
tass 68:0847e35d08a6 652 ret[4] = pico_protocol_socket_loop(score[4], PICO_LOOP_DIR_IN);
tass 68:0847e35d08a6 653 pico_rand_feed(ret[4]);
tass 68:0847e35d08a6 654
tass 68:0847e35d08a6 655
tass 68:0847e35d08a6 656 ret[6] = pico_protocol_socket_loop(score[6], PICO_LOOP_DIR_OUT);
tass 68:0847e35d08a6 657 pico_rand_feed(ret[6]);
tass 68:0847e35d08a6 658
tass 68:0847e35d08a6 659 ret[7] = pico_protocol_transport_loop(score[7], PICO_LOOP_DIR_OUT);
tass 68:0847e35d08a6 660 pico_rand_feed(ret[7]);
tass 68:0847e35d08a6 661
tass 68:0847e35d08a6 662 ret[8] = pico_protocol_network_loop(score[8], PICO_LOOP_DIR_OUT);
tass 68:0847e35d08a6 663 pico_rand_feed(ret[8]);
tass 68:0847e35d08a6 664
tass 68:0847e35d08a6 665 ret[9] = pico_protocol_datalink_loop(score[9], PICO_LOOP_DIR_OUT);
tass 68:0847e35d08a6 666 pico_rand_feed(ret[9]);
tass 68:0847e35d08a6 667
tass 68:0847e35d08a6 668 ret[10] = pico_devices_loop(score[10],PICO_LOOP_DIR_OUT);
tass 68:0847e35d08a6 669 pico_rand_feed(ret[10]);
tass 68:0847e35d08a6 670
tass 68:0847e35d08a6 671 /* calculate new loop scores for next iteration */
tass 68:0847e35d08a6 672 calc_score(score, index,(int (*)[]) avg, ret);
tass 68:0847e35d08a6 673 }
tass 68:0847e35d08a6 674
tass 68:0847e35d08a6 675 void pico_stack_loop(void)
tass 68:0847e35d08a6 676 {
tass 68:0847e35d08a6 677 while(1) {
tass 68:0847e35d08a6 678 pico_stack_tick();
tass 68:0847e35d08a6 679 PICO_IDLE();
tass 68:0847e35d08a6 680 }
tass 68:0847e35d08a6 681 }
tass 68:0847e35d08a6 682
tass 68:0847e35d08a6 683 void pico_timer_add(unsigned long expire, void (*timer)(unsigned long, void *), void *arg)
tass 68:0847e35d08a6 684 {
tass 68:0847e35d08a6 685 pico_timer t;
tass 68:0847e35d08a6 686 t.expire = PICO_TIME_MS() + expire;
tass 68:0847e35d08a6 687 t.arg = arg;
tass 68:0847e35d08a6 688 t.timer = timer;
tass 68:0847e35d08a6 689 heap_insert(Timers, &t);
tass 68:0847e35d08a6 690 if (Timers->n > PICO_MAX_TIMERS) {
tass 68:0847e35d08a6 691 dbg("Warning: I have %d timers\n", Timers->n);
tass 68:0847e35d08a6 692 }
tass 68:0847e35d08a6 693 }
tass 68:0847e35d08a6 694
tass 68:0847e35d08a6 695 void pico_stack_init(void)
tass 68:0847e35d08a6 696 {
tass 68:0847e35d08a6 697
tass 68:0847e35d08a6 698 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 699 pico_protocol_init(&pico_proto_ipv4);
tass 68:0847e35d08a6 700 #endif
tass 68:0847e35d08a6 701
tass 68:0847e35d08a6 702 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 703 pico_protocol_init(&pico_proto_ipv6);
tass 68:0847e35d08a6 704 #endif
tass 68:0847e35d08a6 705
tass 68:0847e35d08a6 706 #ifdef PICO_SUPPORT_ICMP4
tass 68:0847e35d08a6 707 pico_protocol_init(&pico_proto_icmp4);
tass 68:0847e35d08a6 708 #endif
tass 68:0847e35d08a6 709
tass 68:0847e35d08a6 710 #ifdef PICO_SUPPORT_IGMP
tass 68:0847e35d08a6 711 pico_protocol_init(&pico_proto_igmp);
tass 68:0847e35d08a6 712 #endif
tass 68:0847e35d08a6 713
tass 68:0847e35d08a6 714 #ifdef PICO_SUPPORT_UDP
tass 68:0847e35d08a6 715 pico_protocol_init(&pico_proto_udp);
tass 68:0847e35d08a6 716 #endif
tass 68:0847e35d08a6 717
tass 68:0847e35d08a6 718 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 719 pico_protocol_init(&pico_proto_tcp);
tass 68:0847e35d08a6 720 #endif
tass 68:0847e35d08a6 721
tass 68:0847e35d08a6 722 #ifdef PICO_SUPPORT_DNS_CLIENT
tass 68:0847e35d08a6 723 pico_dns_client_init();
tass 68:0847e35d08a6 724 #endif
tass 68:0847e35d08a6 725
tass 68:0847e35d08a6 726 pico_rand_feed(123456);
tass 68:0847e35d08a6 727
tass 68:0847e35d08a6 728 /* Initialize timer heap */
tass 68:0847e35d08a6 729 Timers = heap_init();
tass 68:0847e35d08a6 730 pico_stack_tick();
tass 68:0847e35d08a6 731 pico_stack_tick();
tass 68:0847e35d08a6 732 pico_stack_tick();
tass 68:0847e35d08a6 733 }
tass 68:0847e35d08a6 734