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 Dec 05 08:31:32 2013 +0000
Revision:
128:ae39e6e81531
Parent:
88:0e827d0d8017
Child:
131:4758606c9316
updated repo to work with uint64 tick.

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 128:ae39e6e81531 37 volatile pico_time 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 70:cd218dd180e5 53 pico_rand_feed((uint32_t)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 70:cd218dd180e5 127 int32_t pico_transport_receive(struct pico_frame *f, uint8_t proto)
tass 68:0847e35d08a6 128 {
tass 70:cd218dd180e5 129 int32_t 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 88:0e827d0d8017 166 int32_t 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 70:cd218dd180e5 175 int32_t 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 70:cd218dd180e5 193 return (int32_t)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 88:0e827d0d8017 198 int32_t 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 70:cd218dd180e5 255 int32_t 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 70:cd218dd180e5 317 pico_mcast_mac[4] = (uint8_t)((long_be(hdr->dst.addr) & 0x0000FF00) >> 8);
tass 70:cd218dd180e5 318 pico_mcast_mac[3] = (uint8_t)((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 70:cd218dd180e5 333 int32_t pico_ethernet_send(struct pico_frame *f)
tass 68:0847e35d08a6 334 {
tass 68:0847e35d08a6 335 const struct pico_eth *dstmac = NULL;
tass 70:cd218dd180e5 336 int32_t 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 73:dfb737147f6e 374 ret = (int32_t)f->dev->send(f->dev, f->start,(int) 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 70:cd218dd180e5 421 int32_t pico_stack_recv(struct pico_device *dev, uint8_t *buffer, uint32_t len)
tass 68:0847e35d08a6 422 {
tass 68:0847e35d08a6 423 struct pico_frame *f;
tass 70:cd218dd180e5 424 int32_t 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 70:cd218dd180e5 438 uint32_t 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 70:cd218dd180e5 450 int32_t 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 70:cd218dd180e5 457 uint32_t 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 73:dfb737147f6e 467 uint32_t expire;
tass 68:0847e35d08a6 468 void *arg;
tass 128:ae39e6e81531 469 void (*timer)(pico_time timestamp, void *arg);
tass 68:0847e35d08a6 470 };
tass 68:0847e35d08a6 471
tass 70:cd218dd180e5 472 struct pico_timer_ref
tass 70:cd218dd180e5 473 {
tass 128:ae39e6e81531 474 pico_time expire;
tass 70:cd218dd180e5 475 struct pico_timer *tmr;
tass 70:cd218dd180e5 476 };
tass 68:0847e35d08a6 477
tass 70:cd218dd180e5 478 typedef struct pico_timer_ref pico_timer_ref;
tass 68:0847e35d08a6 479
tass 70:cd218dd180e5 480 DECLARE_HEAP(pico_timer_ref, expire);
tass 70:cd218dd180e5 481
tass 70:cd218dd180e5 482 static heap_pico_timer_ref *Timers;
tass 68:0847e35d08a6 483
tass 68:0847e35d08a6 484 void pico_check_timers(void)
tass 68:0847e35d08a6 485 {
tass 70:cd218dd180e5 486 struct pico_timer *t;
tass 70:cd218dd180e5 487 struct pico_timer_ref tref_unused, *tref = heap_first(Timers);
tass 68:0847e35d08a6 488 pico_tick = PICO_TIME_MS();
tass 70:cd218dd180e5 489 while((tref) && (tref->expire < pico_tick)) {
tass 70:cd218dd180e5 490 t = tref->tmr;
tass 70:cd218dd180e5 491 if (t && t->timer)
tass 70:cd218dd180e5 492 t->timer(pico_tick, t->arg);
tass 70:cd218dd180e5 493 if (t)
tass 70:cd218dd180e5 494 pico_free(t);
tass 70:cd218dd180e5 495 t = NULL;
tass 70:cd218dd180e5 496 heap_peek(Timers, &tref_unused);
tass 70:cd218dd180e5 497 tref = heap_first(Timers);
tass 70:cd218dd180e5 498 }
tass 70:cd218dd180e5 499 }
tass 70:cd218dd180e5 500
tass 70:cd218dd180e5 501 void pico_timer_cancel(struct pico_timer *t)
tass 70:cd218dd180e5 502 {
tass 70:cd218dd180e5 503 uint32_t i;
tass 70:cd218dd180e5 504 struct pico_timer_ref *tref = Timers->top;
tass 70:cd218dd180e5 505 if (!t)
tass 70:cd218dd180e5 506 return;
tass 70:cd218dd180e5 507 for (i = 1; i <= Timers->n; i++) {
tass 70:cd218dd180e5 508 if (tref[i].tmr == t) {
tass 70:cd218dd180e5 509 Timers->top[i].tmr = NULL;
tass 70:cd218dd180e5 510 pico_free(t);
tass 70:cd218dd180e5 511 break;
tass 70:cd218dd180e5 512 }
tass 68:0847e35d08a6 513 }
tass 68:0847e35d08a6 514 }
tass 68:0847e35d08a6 515
tass 68:0847e35d08a6 516
tass 68:0847e35d08a6 517 #define PROTO_DEF_NR 11
tass 68:0847e35d08a6 518 #define PROTO_DEF_AVG_NR 4
tass 68:0847e35d08a6 519 #define PROTO_DEF_SCORE 32
tass 68:0847e35d08a6 520 #define PROTO_MIN_SCORE 32
tass 68:0847e35d08a6 521 #define PROTO_MAX_SCORE 128
tass 68:0847e35d08a6 522 #define PROTO_LAT_IND 3 /* latecy indication 0-3 (lower is better latency performance), x1, x2, x4, x8 */
tass 68:0847e35d08a6 523 #define PROTO_MAX_LOOP (PROTO_MAX_SCORE<<PROTO_LAT_IND) /* max global loop score, so per tick */
tass 68:0847e35d08a6 524
tass 68:0847e35d08a6 525 static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret)
tass 68:0847e35d08a6 526 {
tass 68:0847e35d08a6 527 int temp, i, j, sum;
tass 68:0847e35d08a6 528 int max_total = PROTO_MAX_LOOP, total = 0;
tass 68:0847e35d08a6 529
tass 68:0847e35d08a6 530 //dbg("USED SCORES> ");
tass 68:0847e35d08a6 531
tass 68:0847e35d08a6 532 for (i = 0; i < PROTO_DEF_NR; i++) {
tass 68:0847e35d08a6 533
tass 68:0847e35d08a6 534 /* if used looped score */
tass 68:0847e35d08a6 535 if (ret[i] < score[i]) {
tass 68:0847e35d08a6 536 temp = score[i] - ret[i]; /* remaining loop score */
tass 68:0847e35d08a6 537
tass 68:0847e35d08a6 538 //dbg("%3d - ",temp);
tass 68:0847e35d08a6 539
tass 68:0847e35d08a6 540 if (index[i] >= PROTO_DEF_AVG_NR)
tass 68:0847e35d08a6 541 index[i] = 0; /* reset index */
tass 68:0847e35d08a6 542 j = index[i];
tass 68:0847e35d08a6 543 avg[i][j] = temp;
tass 68:0847e35d08a6 544
tass 68:0847e35d08a6 545 index[i]++;
tass 68:0847e35d08a6 546
tass 68:0847e35d08a6 547 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 548 score[i] <<= 1;
tass 68:0847e35d08a6 549 total += score[i];
tass 68:0847e35d08a6 550 continue;
tass 68:0847e35d08a6 551 }
tass 68:0847e35d08a6 552
tass 68:0847e35d08a6 553 sum = 0;
tass 68:0847e35d08a6 554 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
tass 68:0847e35d08a6 555 sum += avg[i][j]; /* calculate sum */
tass 68:0847e35d08a6 556
tass 68:0847e35d08a6 557 sum >>= 2; /* divide by 4 to get average used score */
tass 68:0847e35d08a6 558
tass 68:0847e35d08a6 559 /* criterion to increase next loop score */
tass 68:0847e35d08a6 560 if (sum > (score[i] - (score[i]>>2)) && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total)) { /* > 3/4 */
tass 68:0847e35d08a6 561 score[i] <<= 1; /* double loop score */
tass 68:0847e35d08a6 562 total += score[i];
tass 68:0847e35d08a6 563 continue;
tass 68:0847e35d08a6 564 }
tass 68:0847e35d08a6 565
tass 68:0847e35d08a6 566 /* criterion to decrease next loop score */
tass 68:0847e35d08a6 567 if (sum < (score[i]>>2) && (score[i]>>1 >= PROTO_MIN_SCORE)) { /* < 1/4 */
tass 68:0847e35d08a6 568 score[i] >>= 1; /* half loop score */
tass 68:0847e35d08a6 569 total += score[i];
tass 68:0847e35d08a6 570 continue;
tass 68:0847e35d08a6 571 }
tass 68:0847e35d08a6 572
tass 68:0847e35d08a6 573 /* also add non-changed scores */
tass 68:0847e35d08a6 574 total += score[i];
tass 68:0847e35d08a6 575 }
tass 68:0847e35d08a6 576 else if (ret[i] == score[i]) {
tass 68:0847e35d08a6 577 /* no used loop score - gradually decrease */
tass 68:0847e35d08a6 578
tass 68:0847e35d08a6 579 // dbg("%3d - ",0);
tass 68:0847e35d08a6 580
tass 68:0847e35d08a6 581 if (index[i] >= PROTO_DEF_AVG_NR)
tass 68:0847e35d08a6 582 index[i] = 0; /* reset index */
tass 68:0847e35d08a6 583 j = index[i];
tass 68:0847e35d08a6 584 avg[i][j] = 0;
tass 68:0847e35d08a6 585
tass 68:0847e35d08a6 586 index[i]++;
tass 68:0847e35d08a6 587
tass 68:0847e35d08a6 588 sum = 0;
tass 68:0847e35d08a6 589 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
tass 68:0847e35d08a6 590 sum += avg[i][j]; /* calculate sum */
tass 68:0847e35d08a6 591
tass 68:0847e35d08a6 592 sum >>= 2; /* divide by 4 to get average used score */
tass 68:0847e35d08a6 593
tass 68:0847e35d08a6 594 if ((sum == 0) && (score[i]>>1 >= PROTO_MIN_SCORE)) {
tass 68:0847e35d08a6 595 score[i] >>= 1; /* half loop score */
tass 68:0847e35d08a6 596 total += score[i];
tass 68:0847e35d08a6 597 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
tass 68:0847e35d08a6 598 avg[i][j] = score[i];
tass 68:0847e35d08a6 599 }
tass 68:0847e35d08a6 600
tass 68:0847e35d08a6 601 }
tass 68:0847e35d08a6 602 }
tass 68:0847e35d08a6 603
tass 68:0847e35d08a6 604 //dbg("\n");
tass 68:0847e35d08a6 605
tass 68:0847e35d08a6 606 return 0;
tass 68:0847e35d08a6 607 }
tass 68:0847e35d08a6 608
tass 68:0847e35d08a6 609
tass 68:0847e35d08a6 610
tass 68:0847e35d08a6 611 /*
tass 68:0847e35d08a6 612
tass 68:0847e35d08a6 613 .
tass 68:0847e35d08a6 614 .vS.
tass 68:0847e35d08a6 615 <aoSo.
tass 68:0847e35d08a6 616 .XoS22.
tass 68:0847e35d08a6 617 .S2S22. ._... ...... ..._.
tass 68:0847e35d08a6 618 :=|2S2X2|=++; <vSX2XX2z+ |vSSSXSSs>. :iXXZUZXXe=
tass 68:0847e35d08a6 619 )2SS2SS2S2S2I =oS2S2S2S2X22;. _vuXS22S2S2S22i ._wZZXZZZXZZXZX=
tass 68:0847e35d08a6 620 )22S2S2S2S2Sl |S2S2S22S2SSSXc: .S2SS2S2S22S2SS= .]#XZZZXZXZZZZZZ:
tass 68:0847e35d08a6 621 )oSS2SS2S2Sol |2}!"""!32S22S(. uS2S2Se**12oS2e ]dXZZXX2?YYXXXZ*
tass 68:0847e35d08a6 622 .:2S2So:..-. . :]S2S2e;=X2SS2o .)oc ]XZZXZ( =nX:
tass 68:0847e35d08a6 623 .S2S22. ___s_i,.)oS2So(;2SS2So, ` 3XZZZZc, -
tass 68:0847e35d08a6 624 .S2SSo. =oXXXSSS2XoS2S2o( XS2S2XSos;. ]ZZZZXXXX|=
tass 68:0847e35d08a6 625 .S2S22. .)S2S2S22S2S2S2S2o( "X2SS2S2S2Sus,, +3XZZZZZXZZoos_
tass 68:0847e35d08a6 626 .S2S22. .]2S2SS22S222S2SS2o( ]S22S2S2S222So :3XXZZZZZZZZXXv
tass 68:0847e35d08a6 627 .S2S22. =u2SS2e"~---"{2S2So( -"12S2S2SSS2Su. "?SXXXZXZZZZXo
tass 68:0847e35d08a6 628 .S2SSo. )SS22z; :S2S2o( ={vS2S2S22v .<vXZZZZZZZ;
tass 68:0847e35d08a6 629 .S2S2S: ]oSS2c; =22S2o( -"S2SS2n ~4XXZXZ(
tass 68:0847e35d08a6 630 .2S2S2i )2S2S2[. .)XS2So( <;. .2S2S2o :<. ]XZZZX(
tass 68:0847e35d08a6 631 nX2S2S,,_s_=3oSS2SoaasuXXS2S2o( .oXoasi_aioSSS22l.]dZoaas_aadXZZXZ'
tass 68:0847e35d08a6 632 vS2SSSXXX2; )S2S2S2SoS2S2S2S2o( iS2S222XSoSS22So.)nXZZXXXZZXXZZXZo
tass 68:0847e35d08a6 633 +32S22S2Sn -+S2S2S2S2So22S2So( 12S2SS2S2SS22S}- )SXXZZZZZZZZZXX!-
tass 68:0847e35d08a6 634 .)S22222i .i2S2S2o>;:S2S2o( .<vSoSoSo2S(; :nXXXXXZXXX(
tass 68:0847e35d08a6 635 .-~~~~- --- . - - --~~~-- --^^~~-
tass 68:0847e35d08a6 636 .
tass 68:0847e35d08a6 637
tass 68:0847e35d08a6 638
tass 68:0847e35d08a6 639 ... curious about our source code? We are hiring! mailto:<recruiting@tass.be>
tass 68:0847e35d08a6 640
tass 68:0847e35d08a6 641
tass 68:0847e35d08a6 642 */
tass 68:0847e35d08a6 643
tass 68:0847e35d08a6 644 void pico_stack_tick(void)
tass 68:0847e35d08a6 645 {
tass 68:0847e35d08a6 646 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 647 static int index[PROTO_DEF_NR] = {0,0,0,0,0,0};
tass 68:0847e35d08a6 648 static int avg[PROTO_DEF_NR][PROTO_DEF_AVG_NR];
tass 68:0847e35d08a6 649 static int ret[PROTO_DEF_NR] = {0};
tass 68:0847e35d08a6 650
tass 68:0847e35d08a6 651 pico_check_timers();
tass 68:0847e35d08a6 652
tass 68:0847e35d08a6 653 //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 654
tass 68:0847e35d08a6 655 //score = pico_protocols_loop(100);
tass 68:0847e35d08a6 656
tass 68:0847e35d08a6 657 ret[0] = pico_devices_loop(score[0],PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 658 pico_rand_feed((uint32_t)ret[0]);
tass 68:0847e35d08a6 659
tass 68:0847e35d08a6 660 ret[1] = pico_protocol_datalink_loop(score[1], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 661 pico_rand_feed((uint32_t)ret[1]);
tass 68:0847e35d08a6 662
tass 68:0847e35d08a6 663 ret[2] = pico_protocol_network_loop(score[2], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 664 pico_rand_feed((uint32_t)ret[2]);
tass 68:0847e35d08a6 665
tass 68:0847e35d08a6 666 ret[3] = pico_protocol_transport_loop(score[3], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 667 pico_rand_feed((uint32_t)ret[3]);
tass 68:0847e35d08a6 668
tass 68:0847e35d08a6 669
tass 68:0847e35d08a6 670 ret[5] = score[5];
tass 68:0847e35d08a6 671 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
tass 68:0847e35d08a6 672 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
tass 68:0847e35d08a6 673 ret[5] = pico_sockets_loop(score[5]); // swapped
tass 70:cd218dd180e5 674 pico_rand_feed((uint32_t)ret[5]);
tass 68:0847e35d08a6 675 #endif
tass 68:0847e35d08a6 676 #endif
tass 68:0847e35d08a6 677
tass 68:0847e35d08a6 678 ret[4] = pico_protocol_socket_loop(score[4], PICO_LOOP_DIR_IN);
tass 70:cd218dd180e5 679 pico_rand_feed((uint32_t)ret[4]);
tass 68:0847e35d08a6 680
tass 68:0847e35d08a6 681
tass 68:0847e35d08a6 682 ret[6] = pico_protocol_socket_loop(score[6], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 683 pico_rand_feed((uint32_t)ret[6]);
tass 68:0847e35d08a6 684
tass 68:0847e35d08a6 685 ret[7] = pico_protocol_transport_loop(score[7], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 686 pico_rand_feed((uint32_t)ret[7]);
tass 68:0847e35d08a6 687
tass 68:0847e35d08a6 688 ret[8] = pico_protocol_network_loop(score[8], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 689 pico_rand_feed((uint32_t)ret[8]);
tass 68:0847e35d08a6 690
tass 68:0847e35d08a6 691 ret[9] = pico_protocol_datalink_loop(score[9], PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 692 pico_rand_feed((uint32_t)ret[9]);
tass 68:0847e35d08a6 693
tass 68:0847e35d08a6 694 ret[10] = pico_devices_loop(score[10],PICO_LOOP_DIR_OUT);
tass 70:cd218dd180e5 695 pico_rand_feed((uint32_t)ret[10]);
tass 68:0847e35d08a6 696
tass 68:0847e35d08a6 697 /* calculate new loop scores for next iteration */
tass 68:0847e35d08a6 698 calc_score(score, index,(int (*)[]) avg, ret);
tass 68:0847e35d08a6 699 }
tass 68:0847e35d08a6 700
tass 68:0847e35d08a6 701 void pico_stack_loop(void)
tass 68:0847e35d08a6 702 {
tass 68:0847e35d08a6 703 while(1) {
tass 68:0847e35d08a6 704 pico_stack_tick();
tass 68:0847e35d08a6 705 PICO_IDLE();
tass 68:0847e35d08a6 706 }
tass 68:0847e35d08a6 707 }
tass 68:0847e35d08a6 708
tass 128:ae39e6e81531 709 struct pico_timer *pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
tass 68:0847e35d08a6 710 {
tass 70:cd218dd180e5 711 struct pico_timer *t = pico_zalloc(sizeof(struct pico_timer));
tass 70:cd218dd180e5 712 struct pico_timer_ref tref;
tass 70:cd218dd180e5 713 if (!t) {
tass 70:cd218dd180e5 714 pico_err = PICO_ERR_ENOMEM;
tass 70:cd218dd180e5 715 return NULL;
tass 70:cd218dd180e5 716 }
tass 70:cd218dd180e5 717 tref.expire = PICO_TIME_MS() + expire;
tass 70:cd218dd180e5 718 t->arg = arg;
tass 70:cd218dd180e5 719 t->timer = timer;
tass 70:cd218dd180e5 720 tref.tmr = t;
tass 70:cd218dd180e5 721 heap_insert(Timers, &tref);
tass 68:0847e35d08a6 722 if (Timers->n > PICO_MAX_TIMERS) {
tass 68:0847e35d08a6 723 dbg("Warning: I have %d timers\n", Timers->n);
tass 68:0847e35d08a6 724 }
tass 70:cd218dd180e5 725 return t;
tass 68:0847e35d08a6 726 }
tass 68:0847e35d08a6 727
tass 68:0847e35d08a6 728 void pico_stack_init(void)
tass 68:0847e35d08a6 729 {
tass 68:0847e35d08a6 730
tass 68:0847e35d08a6 731 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 732 pico_protocol_init(&pico_proto_ipv4);
tass 68:0847e35d08a6 733 #endif
tass 68:0847e35d08a6 734
tass 68:0847e35d08a6 735 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 736 pico_protocol_init(&pico_proto_ipv6);
tass 68:0847e35d08a6 737 #endif
tass 68:0847e35d08a6 738
tass 68:0847e35d08a6 739 #ifdef PICO_SUPPORT_ICMP4
tass 68:0847e35d08a6 740 pico_protocol_init(&pico_proto_icmp4);
tass 68:0847e35d08a6 741 #endif
tass 68:0847e35d08a6 742
tass 68:0847e35d08a6 743 #ifdef PICO_SUPPORT_IGMP
tass 68:0847e35d08a6 744 pico_protocol_init(&pico_proto_igmp);
tass 68:0847e35d08a6 745 #endif
tass 68:0847e35d08a6 746
tass 68:0847e35d08a6 747 #ifdef PICO_SUPPORT_UDP
tass 68:0847e35d08a6 748 pico_protocol_init(&pico_proto_udp);
tass 68:0847e35d08a6 749 #endif
tass 68:0847e35d08a6 750
tass 68:0847e35d08a6 751 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 752 pico_protocol_init(&pico_proto_tcp);
tass 68:0847e35d08a6 753 #endif
tass 68:0847e35d08a6 754
tass 68:0847e35d08a6 755 #ifdef PICO_SUPPORT_DNS_CLIENT
tass 68:0847e35d08a6 756 pico_dns_client_init();
tass 68:0847e35d08a6 757 #endif
tass 68:0847e35d08a6 758
tass 68:0847e35d08a6 759 pico_rand_feed(123456);
tass 68:0847e35d08a6 760
tass 68:0847e35d08a6 761 /* Initialize timer heap */
tass 68:0847e35d08a6 762 Timers = heap_init();
tass 68:0847e35d08a6 763 pico_stack_tick();
tass 68:0847e35d08a6 764 pico_stack_tick();
tass 68:0847e35d08a6 765 pico_stack_tick();
tass 68:0847e35d08a6 766 }
tass 68:0847e35d08a6 767