Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested

Fork of F7_Ethernet by Dieter Graef

Committer:
DieterGraef
Date:
Sun Jun 19 16:23:40 2016 +0000
Revision:
0:d26c1b55cfca
Ethernet Library for Nucleo stm32f746ZG and Disco stm32f746NG  works under arm and gcc environment

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DieterGraef 0:d26c1b55cfca 1 /**
DieterGraef 0:d26c1b55cfca 2 * @file
DieterGraef 0:d26c1b55cfca 3 * Sequential API Main thread module
DieterGraef 0:d26c1b55cfca 4 *
DieterGraef 0:d26c1b55cfca 5 */
DieterGraef 0:d26c1b55cfca 6
DieterGraef 0:d26c1b55cfca 7 /*
DieterGraef 0:d26c1b55cfca 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
DieterGraef 0:d26c1b55cfca 9 * All rights reserved.
DieterGraef 0:d26c1b55cfca 10 *
DieterGraef 0:d26c1b55cfca 11 * Redistribution and use in source and binary forms, with or without modification,
DieterGraef 0:d26c1b55cfca 12 * are permitted provided that the following conditions are met:
DieterGraef 0:d26c1b55cfca 13 *
DieterGraef 0:d26c1b55cfca 14 * 1. Redistributions of source code must retain the above copyright notice,
DieterGraef 0:d26c1b55cfca 15 * this list of conditions and the following disclaimer.
DieterGraef 0:d26c1b55cfca 16 * 2. Redistributions in binary form must reproduce the above copyright notice,
DieterGraef 0:d26c1b55cfca 17 * this list of conditions and the following disclaimer in the documentation
DieterGraef 0:d26c1b55cfca 18 * and/or other materials provided with the distribution.
DieterGraef 0:d26c1b55cfca 19 * 3. The name of the author may not be used to endorse or promote products
DieterGraef 0:d26c1b55cfca 20 * derived from this software without specific prior written permission.
DieterGraef 0:d26c1b55cfca 21 *
DieterGraef 0:d26c1b55cfca 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
DieterGraef 0:d26c1b55cfca 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
DieterGraef 0:d26c1b55cfca 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
DieterGraef 0:d26c1b55cfca 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
DieterGraef 0:d26c1b55cfca 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
DieterGraef 0:d26c1b55cfca 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
DieterGraef 0:d26c1b55cfca 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
DieterGraef 0:d26c1b55cfca 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
DieterGraef 0:d26c1b55cfca 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
DieterGraef 0:d26c1b55cfca 31 * OF SUCH DAMAGE.
DieterGraef 0:d26c1b55cfca 32 *
DieterGraef 0:d26c1b55cfca 33 * This file is part of the lwIP TCP/IP stack.
DieterGraef 0:d26c1b55cfca 34 *
DieterGraef 0:d26c1b55cfca 35 * Author: Adam Dunkels <adam@sics.se>
DieterGraef 0:d26c1b55cfca 36 *
DieterGraef 0:d26c1b55cfca 37 */
DieterGraef 0:d26c1b55cfca 38
DieterGraef 0:d26c1b55cfca 39 #include "lwip/opt.h"
DieterGraef 0:d26c1b55cfca 40
DieterGraef 0:d26c1b55cfca 41 #if !NO_SYS /* don't build if not configured for use in lwipopts.h */
DieterGraef 0:d26c1b55cfca 42
DieterGraef 0:d26c1b55cfca 43 #include "lwip/sys.h"
DieterGraef 0:d26c1b55cfca 44 #include "lwip/memp.h"
DieterGraef 0:d26c1b55cfca 45 #include "lwip/mem.h"
DieterGraef 0:d26c1b55cfca 46 #include "lwip/pbuf.h"
DieterGraef 0:d26c1b55cfca 47 #include "lwip/tcpip.h"
DieterGraef 0:d26c1b55cfca 48 #include "lwip/init.h"
DieterGraef 0:d26c1b55cfca 49 #include "netif/etharp.h"
DieterGraef 0:d26c1b55cfca 50 #include "netif/ppp_oe.h"
DieterGraef 0:d26c1b55cfca 51
DieterGraef 0:d26c1b55cfca 52 /* global variables */
DieterGraef 0:d26c1b55cfca 53 static tcpip_init_done_fn tcpip_init_done;
DieterGraef 0:d26c1b55cfca 54 static void *tcpip_init_done_arg;
DieterGraef 0:d26c1b55cfca 55 static sys_mbox_t mbox;
DieterGraef 0:d26c1b55cfca 56
DieterGraef 0:d26c1b55cfca 57 #if LWIP_TCPIP_CORE_LOCKING
DieterGraef 0:d26c1b55cfca 58 /** The global semaphore to lock the stack. */
DieterGraef 0:d26c1b55cfca 59 sys_mutex_t lock_tcpip_core;
DieterGraef 0:d26c1b55cfca 60 #endif /* LWIP_TCPIP_CORE_LOCKING */
DieterGraef 0:d26c1b55cfca 61
DieterGraef 0:d26c1b55cfca 62
DieterGraef 0:d26c1b55cfca 63 /**
DieterGraef 0:d26c1b55cfca 64 * The main lwIP thread. This thread has exclusive access to lwIP core functions
DieterGraef 0:d26c1b55cfca 65 * (unless access to them is not locked). Other threads communicate with this
DieterGraef 0:d26c1b55cfca 66 * thread using message boxes.
DieterGraef 0:d26c1b55cfca 67 *
DieterGraef 0:d26c1b55cfca 68 * It also starts all the timers to make sure they are running in the right
DieterGraef 0:d26c1b55cfca 69 * thread context.
DieterGraef 0:d26c1b55cfca 70 *
DieterGraef 0:d26c1b55cfca 71 * @param arg unused argument
DieterGraef 0:d26c1b55cfca 72 */
DieterGraef 0:d26c1b55cfca 73 static void
DieterGraef 0:d26c1b55cfca 74 tcpip_thread(void *arg)
DieterGraef 0:d26c1b55cfca 75 {
DieterGraef 0:d26c1b55cfca 76 struct tcpip_msg *msg;
DieterGraef 0:d26c1b55cfca 77 LWIP_UNUSED_ARG(arg);
DieterGraef 0:d26c1b55cfca 78
DieterGraef 0:d26c1b55cfca 79 if (tcpip_init_done != NULL) {
DieterGraef 0:d26c1b55cfca 80 tcpip_init_done(tcpip_init_done_arg);
DieterGraef 0:d26c1b55cfca 81 }
DieterGraef 0:d26c1b55cfca 82
DieterGraef 0:d26c1b55cfca 83 LOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 84 while (1) { /* MAIN Loop */
DieterGraef 0:d26c1b55cfca 85 UNLOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 86 LWIP_TCPIP_THREAD_ALIVE();
DieterGraef 0:d26c1b55cfca 87 /* wait for a message, timeouts are processed while waiting */
DieterGraef 0:d26c1b55cfca 88 sys_timeouts_mbox_fetch(&mbox, (void **)&msg);
DieterGraef 0:d26c1b55cfca 89 LOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 90 switch (msg->type) {
DieterGraef 0:d26c1b55cfca 91
DieterGraef 0:d26c1b55cfca 92 #if LWIP_NETCONN
DieterGraef 0:d26c1b55cfca 93 case TCPIP_MSG_API:
DieterGraef 0:d26c1b55cfca 94 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
DieterGraef 0:d26c1b55cfca 95 msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
DieterGraef 0:d26c1b55cfca 96 break;
DieterGraef 0:d26c1b55cfca 97 #endif /* LWIP_NETCONN */
DieterGraef 0:d26c1b55cfca 98
DieterGraef 0:d26c1b55cfca 99 #if !LWIP_TCPIP_CORE_LOCKING_INPUT
DieterGraef 0:d26c1b55cfca 100 case TCPIP_MSG_INPKT:
DieterGraef 0:d26c1b55cfca 101 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
DieterGraef 0:d26c1b55cfca 102 #if LWIP_ETHERNET
DieterGraef 0:d26c1b55cfca 103 if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
DieterGraef 0:d26c1b55cfca 104 ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
DieterGraef 0:d26c1b55cfca 105 } else
DieterGraef 0:d26c1b55cfca 106 #endif /* LWIP_ETHERNET */
DieterGraef 0:d26c1b55cfca 107 {
DieterGraef 0:d26c1b55cfca 108 ip_input(msg->msg.inp.p, msg->msg.inp.netif);
DieterGraef 0:d26c1b55cfca 109 }
DieterGraef 0:d26c1b55cfca 110 memp_free(MEMP_TCPIP_MSG_INPKT, msg);
DieterGraef 0:d26c1b55cfca 111 break;
DieterGraef 0:d26c1b55cfca 112 #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
DieterGraef 0:d26c1b55cfca 113
DieterGraef 0:d26c1b55cfca 114 #if LWIP_NETIF_API
DieterGraef 0:d26c1b55cfca 115 case TCPIP_MSG_NETIFAPI:
DieterGraef 0:d26c1b55cfca 116 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg));
DieterGraef 0:d26c1b55cfca 117 msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg));
DieterGraef 0:d26c1b55cfca 118 break;
DieterGraef 0:d26c1b55cfca 119 #endif /* LWIP_NETIF_API */
DieterGraef 0:d26c1b55cfca 120
DieterGraef 0:d26c1b55cfca 121 #if LWIP_TCPIP_TIMEOUT
DieterGraef 0:d26c1b55cfca 122 case TCPIP_MSG_TIMEOUT:
DieterGraef 0:d26c1b55cfca 123 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
DieterGraef 0:d26c1b55cfca 124 sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
DieterGraef 0:d26c1b55cfca 125 memp_free(MEMP_TCPIP_MSG_API, msg);
DieterGraef 0:d26c1b55cfca 126 break;
DieterGraef 0:d26c1b55cfca 127 case TCPIP_MSG_UNTIMEOUT:
DieterGraef 0:d26c1b55cfca 128 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
DieterGraef 0:d26c1b55cfca 129 sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
DieterGraef 0:d26c1b55cfca 130 memp_free(MEMP_TCPIP_MSG_API, msg);
DieterGraef 0:d26c1b55cfca 131 break;
DieterGraef 0:d26c1b55cfca 132 #endif /* LWIP_TCPIP_TIMEOUT */
DieterGraef 0:d26c1b55cfca 133
DieterGraef 0:d26c1b55cfca 134 case TCPIP_MSG_CALLBACK:
DieterGraef 0:d26c1b55cfca 135 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
DieterGraef 0:d26c1b55cfca 136 msg->msg.cb.function(msg->msg.cb.ctx);
DieterGraef 0:d26c1b55cfca 137 memp_free(MEMP_TCPIP_MSG_API, msg);
DieterGraef 0:d26c1b55cfca 138 break;
DieterGraef 0:d26c1b55cfca 139
DieterGraef 0:d26c1b55cfca 140 case TCPIP_MSG_CALLBACK_STATIC:
DieterGraef 0:d26c1b55cfca 141 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
DieterGraef 0:d26c1b55cfca 142 msg->msg.cb.function(msg->msg.cb.ctx);
DieterGraef 0:d26c1b55cfca 143 break;
DieterGraef 0:d26c1b55cfca 144
DieterGraef 0:d26c1b55cfca 145 default:
DieterGraef 0:d26c1b55cfca 146 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
DieterGraef 0:d26c1b55cfca 147 LWIP_ASSERT("tcpip_thread: invalid message", 0);
DieterGraef 0:d26c1b55cfca 148 break;
DieterGraef 0:d26c1b55cfca 149 }
DieterGraef 0:d26c1b55cfca 150 }
DieterGraef 0:d26c1b55cfca 151 }
DieterGraef 0:d26c1b55cfca 152
DieterGraef 0:d26c1b55cfca 153 /**
DieterGraef 0:d26c1b55cfca 154 * Pass a received packet to tcpip_thread for input processing
DieterGraef 0:d26c1b55cfca 155 *
DieterGraef 0:d26c1b55cfca 156 * @param p the received packet, p->payload pointing to the Ethernet header or
DieterGraef 0:d26c1b55cfca 157 * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
DieterGraef 0:d26c1b55cfca 158 * NETIF_FLAG_ETHERNET flags)
DieterGraef 0:d26c1b55cfca 159 * @param inp the network interface on which the packet was received
DieterGraef 0:d26c1b55cfca 160 */
DieterGraef 0:d26c1b55cfca 161 err_t
DieterGraef 0:d26c1b55cfca 162 tcpip_input(struct pbuf *p, struct netif *inp)
DieterGraef 0:d26c1b55cfca 163 {
DieterGraef 0:d26c1b55cfca 164 #if LWIP_TCPIP_CORE_LOCKING_INPUT
DieterGraef 0:d26c1b55cfca 165 err_t ret;
DieterGraef 0:d26c1b55cfca 166 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp));
DieterGraef 0:d26c1b55cfca 167 LOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 168 #if LWIP_ETHERNET
DieterGraef 0:d26c1b55cfca 169 if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
DieterGraef 0:d26c1b55cfca 170 ret = ethernet_input(p, inp);
DieterGraef 0:d26c1b55cfca 171 } else
DieterGraef 0:d26c1b55cfca 172 #endif /* LWIP_ETHERNET */
DieterGraef 0:d26c1b55cfca 173 {
DieterGraef 0:d26c1b55cfca 174 ret = ip_input(p, inp);
DieterGraef 0:d26c1b55cfca 175 }
DieterGraef 0:d26c1b55cfca 176 UNLOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 177 return ret;
DieterGraef 0:d26c1b55cfca 178 #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
DieterGraef 0:d26c1b55cfca 179 struct tcpip_msg *msg;
DieterGraef 0:d26c1b55cfca 180
DieterGraef 0:d26c1b55cfca 181 if (!sys_mbox_valid(&mbox)) {
DieterGraef 0:d26c1b55cfca 182 return ERR_VAL;
DieterGraef 0:d26c1b55cfca 183 }
DieterGraef 0:d26c1b55cfca 184 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
DieterGraef 0:d26c1b55cfca 185 if (msg == NULL) {
DieterGraef 0:d26c1b55cfca 186 return ERR_MEM;
DieterGraef 0:d26c1b55cfca 187 }
DieterGraef 0:d26c1b55cfca 188
DieterGraef 0:d26c1b55cfca 189 msg->type = TCPIP_MSG_INPKT;
DieterGraef 0:d26c1b55cfca 190 msg->msg.inp.p = p;
DieterGraef 0:d26c1b55cfca 191 msg->msg.inp.netif = inp;
DieterGraef 0:d26c1b55cfca 192 if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
DieterGraef 0:d26c1b55cfca 193 memp_free(MEMP_TCPIP_MSG_INPKT, msg);
DieterGraef 0:d26c1b55cfca 194 return ERR_MEM;
DieterGraef 0:d26c1b55cfca 195 }
DieterGraef 0:d26c1b55cfca 196 return ERR_OK;
DieterGraef 0:d26c1b55cfca 197 #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
DieterGraef 0:d26c1b55cfca 198 }
DieterGraef 0:d26c1b55cfca 199
DieterGraef 0:d26c1b55cfca 200 /**
DieterGraef 0:d26c1b55cfca 201 * Call a specific function in the thread context of
DieterGraef 0:d26c1b55cfca 202 * tcpip_thread for easy access synchronization.
DieterGraef 0:d26c1b55cfca 203 * A function called in that way may access lwIP core code
DieterGraef 0:d26c1b55cfca 204 * without fearing concurrent access.
DieterGraef 0:d26c1b55cfca 205 *
DieterGraef 0:d26c1b55cfca 206 * @param f the function to call
DieterGraef 0:d26c1b55cfca 207 * @param ctx parameter passed to f
DieterGraef 0:d26c1b55cfca 208 * @param block 1 to block until the request is posted, 0 to non-blocking mode
DieterGraef 0:d26c1b55cfca 209 * @return ERR_OK if the function was called, another err_t if not
DieterGraef 0:d26c1b55cfca 210 */
DieterGraef 0:d26c1b55cfca 211 err_t
DieterGraef 0:d26c1b55cfca 212 tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
DieterGraef 0:d26c1b55cfca 213 {
DieterGraef 0:d26c1b55cfca 214 struct tcpip_msg *msg;
DieterGraef 0:d26c1b55cfca 215
DieterGraef 0:d26c1b55cfca 216 if (sys_mbox_valid(&mbox)) {
DieterGraef 0:d26c1b55cfca 217 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
DieterGraef 0:d26c1b55cfca 218 if (msg == NULL) {
DieterGraef 0:d26c1b55cfca 219 return ERR_MEM;
DieterGraef 0:d26c1b55cfca 220 }
DieterGraef 0:d26c1b55cfca 221
DieterGraef 0:d26c1b55cfca 222 msg->type = TCPIP_MSG_CALLBACK;
DieterGraef 0:d26c1b55cfca 223 msg->msg.cb.function = function;
DieterGraef 0:d26c1b55cfca 224 msg->msg.cb.ctx = ctx;
DieterGraef 0:d26c1b55cfca 225 if (block) {
DieterGraef 0:d26c1b55cfca 226 sys_mbox_post(&mbox, msg);
DieterGraef 0:d26c1b55cfca 227 } else {
DieterGraef 0:d26c1b55cfca 228 if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
DieterGraef 0:d26c1b55cfca 229 memp_free(MEMP_TCPIP_MSG_API, msg);
DieterGraef 0:d26c1b55cfca 230 return ERR_MEM;
DieterGraef 0:d26c1b55cfca 231 }
DieterGraef 0:d26c1b55cfca 232 }
DieterGraef 0:d26c1b55cfca 233 return ERR_OK;
DieterGraef 0:d26c1b55cfca 234 }
DieterGraef 0:d26c1b55cfca 235 return ERR_VAL;
DieterGraef 0:d26c1b55cfca 236 }
DieterGraef 0:d26c1b55cfca 237
DieterGraef 0:d26c1b55cfca 238 #if LWIP_TCPIP_TIMEOUT
DieterGraef 0:d26c1b55cfca 239 /**
DieterGraef 0:d26c1b55cfca 240 * call sys_timeout in tcpip_thread
DieterGraef 0:d26c1b55cfca 241 *
DieterGraef 0:d26c1b55cfca 242 * @param msec time in milliseconds for timeout
DieterGraef 0:d26c1b55cfca 243 * @param h function to be called on timeout
DieterGraef 0:d26c1b55cfca 244 * @param arg argument to pass to timeout function h
DieterGraef 0:d26c1b55cfca 245 * @return ERR_MEM on memory error, ERR_OK otherwise
DieterGraef 0:d26c1b55cfca 246 */
DieterGraef 0:d26c1b55cfca 247 err_t
DieterGraef 0:d26c1b55cfca 248 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
DieterGraef 0:d26c1b55cfca 249 {
DieterGraef 0:d26c1b55cfca 250 struct tcpip_msg *msg;
DieterGraef 0:d26c1b55cfca 251
DieterGraef 0:d26c1b55cfca 252 if (sys_mbox_valid(&mbox)) {
DieterGraef 0:d26c1b55cfca 253 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
DieterGraef 0:d26c1b55cfca 254 if (msg == NULL) {
DieterGraef 0:d26c1b55cfca 255 return ERR_MEM;
DieterGraef 0:d26c1b55cfca 256 }
DieterGraef 0:d26c1b55cfca 257
DieterGraef 0:d26c1b55cfca 258 msg->type = TCPIP_MSG_TIMEOUT;
DieterGraef 0:d26c1b55cfca 259 msg->msg.tmo.msecs = msecs;
DieterGraef 0:d26c1b55cfca 260 msg->msg.tmo.h = h;
DieterGraef 0:d26c1b55cfca 261 msg->msg.tmo.arg = arg;
DieterGraef 0:d26c1b55cfca 262 sys_mbox_post(&mbox, msg);
DieterGraef 0:d26c1b55cfca 263 return ERR_OK;
DieterGraef 0:d26c1b55cfca 264 }
DieterGraef 0:d26c1b55cfca 265 return ERR_VAL;
DieterGraef 0:d26c1b55cfca 266 }
DieterGraef 0:d26c1b55cfca 267
DieterGraef 0:d26c1b55cfca 268 /**
DieterGraef 0:d26c1b55cfca 269 * call sys_untimeout in tcpip_thread
DieterGraef 0:d26c1b55cfca 270 *
DieterGraef 0:d26c1b55cfca 271 * @param msec time in milliseconds for timeout
DieterGraef 0:d26c1b55cfca 272 * @param h function to be called on timeout
DieterGraef 0:d26c1b55cfca 273 * @param arg argument to pass to timeout function h
DieterGraef 0:d26c1b55cfca 274 * @return ERR_MEM on memory error, ERR_OK otherwise
DieterGraef 0:d26c1b55cfca 275 */
DieterGraef 0:d26c1b55cfca 276 err_t
DieterGraef 0:d26c1b55cfca 277 tcpip_untimeout(sys_timeout_handler h, void *arg)
DieterGraef 0:d26c1b55cfca 278 {
DieterGraef 0:d26c1b55cfca 279 struct tcpip_msg *msg;
DieterGraef 0:d26c1b55cfca 280
DieterGraef 0:d26c1b55cfca 281 if (sys_mbox_valid(&mbox)) {
DieterGraef 0:d26c1b55cfca 282 msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
DieterGraef 0:d26c1b55cfca 283 if (msg == NULL) {
DieterGraef 0:d26c1b55cfca 284 return ERR_MEM;
DieterGraef 0:d26c1b55cfca 285 }
DieterGraef 0:d26c1b55cfca 286
DieterGraef 0:d26c1b55cfca 287 msg->type = TCPIP_MSG_UNTIMEOUT;
DieterGraef 0:d26c1b55cfca 288 msg->msg.tmo.h = h;
DieterGraef 0:d26c1b55cfca 289 msg->msg.tmo.arg = arg;
DieterGraef 0:d26c1b55cfca 290 sys_mbox_post(&mbox, msg);
DieterGraef 0:d26c1b55cfca 291 return ERR_OK;
DieterGraef 0:d26c1b55cfca 292 }
DieterGraef 0:d26c1b55cfca 293 return ERR_VAL;
DieterGraef 0:d26c1b55cfca 294 }
DieterGraef 0:d26c1b55cfca 295 #endif /* LWIP_TCPIP_TIMEOUT */
DieterGraef 0:d26c1b55cfca 296
DieterGraef 0:d26c1b55cfca 297 #if LWIP_NETCONN
DieterGraef 0:d26c1b55cfca 298 /**
DieterGraef 0:d26c1b55cfca 299 * Call the lower part of a netconn_* function
DieterGraef 0:d26c1b55cfca 300 * This function is then running in the thread context
DieterGraef 0:d26c1b55cfca 301 * of tcpip_thread and has exclusive access to lwIP core code.
DieterGraef 0:d26c1b55cfca 302 *
DieterGraef 0:d26c1b55cfca 303 * @param apimsg a struct containing the function to call and its parameters
DieterGraef 0:d26c1b55cfca 304 * @return ERR_OK if the function was called, another err_t if not
DieterGraef 0:d26c1b55cfca 305 */
DieterGraef 0:d26c1b55cfca 306 err_t
DieterGraef 0:d26c1b55cfca 307 tcpip_apimsg(struct api_msg *apimsg)
DieterGraef 0:d26c1b55cfca 308 {
DieterGraef 0:d26c1b55cfca 309 struct tcpip_msg msg;
DieterGraef 0:d26c1b55cfca 310 #ifdef LWIP_DEBUG
DieterGraef 0:d26c1b55cfca 311 /* catch functions that don't set err */
DieterGraef 0:d26c1b55cfca 312 apimsg->msg.err = ERR_VAL;
DieterGraef 0:d26c1b55cfca 313 #endif
DieterGraef 0:d26c1b55cfca 314
DieterGraef 0:d26c1b55cfca 315 if (sys_mbox_valid(&mbox)) {
DieterGraef 0:d26c1b55cfca 316 msg.type = TCPIP_MSG_API;
DieterGraef 0:d26c1b55cfca 317 msg.msg.apimsg = apimsg;
DieterGraef 0:d26c1b55cfca 318 sys_mbox_post(&mbox, &msg);
DieterGraef 0:d26c1b55cfca 319 sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0);
DieterGraef 0:d26c1b55cfca 320 return apimsg->msg.err;
DieterGraef 0:d26c1b55cfca 321 }
DieterGraef 0:d26c1b55cfca 322 return ERR_VAL;
DieterGraef 0:d26c1b55cfca 323 }
DieterGraef 0:d26c1b55cfca 324
DieterGraef 0:d26c1b55cfca 325 #if LWIP_TCPIP_CORE_LOCKING
DieterGraef 0:d26c1b55cfca 326 /**
DieterGraef 0:d26c1b55cfca 327 * Call the lower part of a netconn_* function
DieterGraef 0:d26c1b55cfca 328 * This function has exclusive access to lwIP core code by locking it
DieterGraef 0:d26c1b55cfca 329 * before the function is called.
DieterGraef 0:d26c1b55cfca 330 *
DieterGraef 0:d26c1b55cfca 331 * @param apimsg a struct containing the function to call and its parameters
DieterGraef 0:d26c1b55cfca 332 * @return ERR_OK (only for compatibility fo tcpip_apimsg())
DieterGraef 0:d26c1b55cfca 333 */
DieterGraef 0:d26c1b55cfca 334 err_t
DieterGraef 0:d26c1b55cfca 335 tcpip_apimsg_lock(struct api_msg *apimsg)
DieterGraef 0:d26c1b55cfca 336 {
DieterGraef 0:d26c1b55cfca 337 #ifdef LWIP_DEBUG
DieterGraef 0:d26c1b55cfca 338 /* catch functions that don't set err */
DieterGraef 0:d26c1b55cfca 339 apimsg->msg.err = ERR_VAL;
DieterGraef 0:d26c1b55cfca 340 #endif
DieterGraef 0:d26c1b55cfca 341
DieterGraef 0:d26c1b55cfca 342 LOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 343 apimsg->function(&(apimsg->msg));
DieterGraef 0:d26c1b55cfca 344 UNLOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 345 return apimsg->msg.err;
DieterGraef 0:d26c1b55cfca 346
DieterGraef 0:d26c1b55cfca 347 }
DieterGraef 0:d26c1b55cfca 348 #endif /* LWIP_TCPIP_CORE_LOCKING */
DieterGraef 0:d26c1b55cfca 349 #endif /* LWIP_NETCONN */
DieterGraef 0:d26c1b55cfca 350
DieterGraef 0:d26c1b55cfca 351 #if LWIP_NETIF_API
DieterGraef 0:d26c1b55cfca 352 #if !LWIP_TCPIP_CORE_LOCKING
DieterGraef 0:d26c1b55cfca 353 /**
DieterGraef 0:d26c1b55cfca 354 * Much like tcpip_apimsg, but calls the lower part of a netifapi_*
DieterGraef 0:d26c1b55cfca 355 * function.
DieterGraef 0:d26c1b55cfca 356 *
DieterGraef 0:d26c1b55cfca 357 * @param netifapimsg a struct containing the function to call and its parameters
DieterGraef 0:d26c1b55cfca 358 * @return error code given back by the function that was called
DieterGraef 0:d26c1b55cfca 359 */
DieterGraef 0:d26c1b55cfca 360 err_t
DieterGraef 0:d26c1b55cfca 361 tcpip_netifapi(struct netifapi_msg* netifapimsg)
DieterGraef 0:d26c1b55cfca 362 {
DieterGraef 0:d26c1b55cfca 363 struct tcpip_msg msg;
DieterGraef 0:d26c1b55cfca 364
DieterGraef 0:d26c1b55cfca 365 if (sys_mbox_valid(&mbox)) {
DieterGraef 0:d26c1b55cfca 366 err_t err = sys_sem_new(&netifapimsg->msg.sem, 0);
DieterGraef 0:d26c1b55cfca 367 if (err != ERR_OK) {
DieterGraef 0:d26c1b55cfca 368 netifapimsg->msg.err = err;
DieterGraef 0:d26c1b55cfca 369 return err;
DieterGraef 0:d26c1b55cfca 370 }
DieterGraef 0:d26c1b55cfca 371
DieterGraef 0:d26c1b55cfca 372 msg.type = TCPIP_MSG_NETIFAPI;
DieterGraef 0:d26c1b55cfca 373 msg.msg.netifapimsg = netifapimsg;
DieterGraef 0:d26c1b55cfca 374 sys_mbox_post(&mbox, &msg);
DieterGraef 0:d26c1b55cfca 375 sys_sem_wait(&netifapimsg->msg.sem);
DieterGraef 0:d26c1b55cfca 376 sys_sem_free(&netifapimsg->msg.sem);
DieterGraef 0:d26c1b55cfca 377 return netifapimsg->msg.err;
DieterGraef 0:d26c1b55cfca 378 }
DieterGraef 0:d26c1b55cfca 379 return ERR_VAL;
DieterGraef 0:d26c1b55cfca 380 }
DieterGraef 0:d26c1b55cfca 381 #else /* !LWIP_TCPIP_CORE_LOCKING */
DieterGraef 0:d26c1b55cfca 382 /**
DieterGraef 0:d26c1b55cfca 383 * Call the lower part of a netifapi_* function
DieterGraef 0:d26c1b55cfca 384 * This function has exclusive access to lwIP core code by locking it
DieterGraef 0:d26c1b55cfca 385 * before the function is called.
DieterGraef 0:d26c1b55cfca 386 *
DieterGraef 0:d26c1b55cfca 387 * @param netifapimsg a struct containing the function to call and its parameters
DieterGraef 0:d26c1b55cfca 388 * @return ERR_OK (only for compatibility fo tcpip_netifapi())
DieterGraef 0:d26c1b55cfca 389 */
DieterGraef 0:d26c1b55cfca 390 err_t
DieterGraef 0:d26c1b55cfca 391 tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
DieterGraef 0:d26c1b55cfca 392 {
DieterGraef 0:d26c1b55cfca 393 LOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 394 netifapimsg->function(&(netifapimsg->msg));
DieterGraef 0:d26c1b55cfca 395 UNLOCK_TCPIP_CORE();
DieterGraef 0:d26c1b55cfca 396 return netifapimsg->msg.err;
DieterGraef 0:d26c1b55cfca 397 }
DieterGraef 0:d26c1b55cfca 398 #endif /* !LWIP_TCPIP_CORE_LOCKING */
DieterGraef 0:d26c1b55cfca 399 #endif /* LWIP_NETIF_API */
DieterGraef 0:d26c1b55cfca 400
DieterGraef 0:d26c1b55cfca 401 /**
DieterGraef 0:d26c1b55cfca 402 * Allocate a structure for a static callback message and initialize it.
DieterGraef 0:d26c1b55cfca 403 * This is intended to be used to send "static" messages from interrupt context.
DieterGraef 0:d26c1b55cfca 404 *
DieterGraef 0:d26c1b55cfca 405 * @param function the function to call
DieterGraef 0:d26c1b55cfca 406 * @param ctx parameter passed to function
DieterGraef 0:d26c1b55cfca 407 * @return a struct pointer to pass to tcpip_trycallback().
DieterGraef 0:d26c1b55cfca 408 */
DieterGraef 0:d26c1b55cfca 409 struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
DieterGraef 0:d26c1b55cfca 410 {
DieterGraef 0:d26c1b55cfca 411 struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
DieterGraef 0:d26c1b55cfca 412 if (msg == NULL) {
DieterGraef 0:d26c1b55cfca 413 return NULL;
DieterGraef 0:d26c1b55cfca 414 }
DieterGraef 0:d26c1b55cfca 415 msg->type = TCPIP_MSG_CALLBACK_STATIC;
DieterGraef 0:d26c1b55cfca 416 msg->msg.cb.function = function;
DieterGraef 0:d26c1b55cfca 417 msg->msg.cb.ctx = ctx;
DieterGraef 0:d26c1b55cfca 418 return (struct tcpip_callback_msg*)msg;
DieterGraef 0:d26c1b55cfca 419 }
DieterGraef 0:d26c1b55cfca 420
DieterGraef 0:d26c1b55cfca 421 /**
DieterGraef 0:d26c1b55cfca 422 * Free a callback message allocated by tcpip_callbackmsg_new().
DieterGraef 0:d26c1b55cfca 423 *
DieterGraef 0:d26c1b55cfca 424 * @param msg the message to free
DieterGraef 0:d26c1b55cfca 425 */
DieterGraef 0:d26c1b55cfca 426 void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg)
DieterGraef 0:d26c1b55cfca 427 {
DieterGraef 0:d26c1b55cfca 428 memp_free(MEMP_TCPIP_MSG_API, msg);
DieterGraef 0:d26c1b55cfca 429 }
DieterGraef 0:d26c1b55cfca 430
DieterGraef 0:d26c1b55cfca 431 /**
DieterGraef 0:d26c1b55cfca 432 * Try to post a callback-message to the tcpip_thread mbox
DieterGraef 0:d26c1b55cfca 433 * This is intended to be used to send "static" messages from interrupt context.
DieterGraef 0:d26c1b55cfca 434 *
DieterGraef 0:d26c1b55cfca 435 * @param msg pointer to the message to post
DieterGraef 0:d26c1b55cfca 436 * @return sys_mbox_trypost() return code
DieterGraef 0:d26c1b55cfca 437 */
DieterGraef 0:d26c1b55cfca 438 err_t
DieterGraef 0:d26c1b55cfca 439 tcpip_trycallback(struct tcpip_callback_msg* msg)
DieterGraef 0:d26c1b55cfca 440 {
DieterGraef 0:d26c1b55cfca 441 if (!sys_mbox_valid(&mbox)) {
DieterGraef 0:d26c1b55cfca 442 return ERR_VAL;
DieterGraef 0:d26c1b55cfca 443 }
DieterGraef 0:d26c1b55cfca 444 return sys_mbox_trypost(&mbox, msg);
DieterGraef 0:d26c1b55cfca 445 }
DieterGraef 0:d26c1b55cfca 446
DieterGraef 0:d26c1b55cfca 447 /**
DieterGraef 0:d26c1b55cfca 448 * Initialize this module:
DieterGraef 0:d26c1b55cfca 449 * - initialize all sub modules
DieterGraef 0:d26c1b55cfca 450 * - start the tcpip_thread
DieterGraef 0:d26c1b55cfca 451 *
DieterGraef 0:d26c1b55cfca 452 * @param initfunc a function to call when tcpip_thread is running and finished initializing
DieterGraef 0:d26c1b55cfca 453 * @param arg argument to pass to initfunc
DieterGraef 0:d26c1b55cfca 454 */
DieterGraef 0:d26c1b55cfca 455 void
DieterGraef 0:d26c1b55cfca 456 tcpip_init(tcpip_init_done_fn initfunc, void *arg)
DieterGraef 0:d26c1b55cfca 457 {
DieterGraef 0:d26c1b55cfca 458 lwip_init();
DieterGraef 0:d26c1b55cfca 459
DieterGraef 0:d26c1b55cfca 460 tcpip_init_done = initfunc;
DieterGraef 0:d26c1b55cfca 461 tcpip_init_done_arg = arg;
DieterGraef 0:d26c1b55cfca 462 if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
DieterGraef 0:d26c1b55cfca 463 LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
DieterGraef 0:d26c1b55cfca 464 }
DieterGraef 0:d26c1b55cfca 465 #if LWIP_TCPIP_CORE_LOCKING
DieterGraef 0:d26c1b55cfca 466 if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
DieterGraef 0:d26c1b55cfca 467 LWIP_ASSERT("failed to create lock_tcpip_core", 0);
DieterGraef 0:d26c1b55cfca 468 }
DieterGraef 0:d26c1b55cfca 469 #endif /* LWIP_TCPIP_CORE_LOCKING */
DieterGraef 0:d26c1b55cfca 470
DieterGraef 0:d26c1b55cfca 471 sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
DieterGraef 0:d26c1b55cfca 472 }
DieterGraef 0:d26c1b55cfca 473
DieterGraef 0:d26c1b55cfca 474 /**
DieterGraef 0:d26c1b55cfca 475 * Simple callback function used with tcpip_callback to free a pbuf
DieterGraef 0:d26c1b55cfca 476 * (pbuf_free has a wrong signature for tcpip_callback)
DieterGraef 0:d26c1b55cfca 477 *
DieterGraef 0:d26c1b55cfca 478 * @param p The pbuf (chain) to be dereferenced.
DieterGraef 0:d26c1b55cfca 479 */
DieterGraef 0:d26c1b55cfca 480 static void
DieterGraef 0:d26c1b55cfca 481 pbuf_free_int(void *p)
DieterGraef 0:d26c1b55cfca 482 {
DieterGraef 0:d26c1b55cfca 483 struct pbuf *q = (struct pbuf *)p;
DieterGraef 0:d26c1b55cfca 484 pbuf_free(q);
DieterGraef 0:d26c1b55cfca 485 }
DieterGraef 0:d26c1b55cfca 486
DieterGraef 0:d26c1b55cfca 487 /**
DieterGraef 0:d26c1b55cfca 488 * A simple wrapper function that allows you to free a pbuf from interrupt context.
DieterGraef 0:d26c1b55cfca 489 *
DieterGraef 0:d26c1b55cfca 490 * @param p The pbuf (chain) to be dereferenced.
DieterGraef 0:d26c1b55cfca 491 * @return ERR_OK if callback could be enqueued, an err_t if not
DieterGraef 0:d26c1b55cfca 492 */
DieterGraef 0:d26c1b55cfca 493 err_t
DieterGraef 0:d26c1b55cfca 494 pbuf_free_callback(struct pbuf *p)
DieterGraef 0:d26c1b55cfca 495 {
DieterGraef 0:d26c1b55cfca 496 return tcpip_callback_with_block(pbuf_free_int, p, 0);
DieterGraef 0:d26c1b55cfca 497 }
DieterGraef 0:d26c1b55cfca 498
DieterGraef 0:d26c1b55cfca 499 /**
DieterGraef 0:d26c1b55cfca 500 * A simple wrapper function that allows you to free heap memory from
DieterGraef 0:d26c1b55cfca 501 * interrupt context.
DieterGraef 0:d26c1b55cfca 502 *
DieterGraef 0:d26c1b55cfca 503 * @param m the heap memory to free
DieterGraef 0:d26c1b55cfca 504 * @return ERR_OK if callback could be enqueued, an err_t if not
DieterGraef 0:d26c1b55cfca 505 */
DieterGraef 0:d26c1b55cfca 506 err_t
DieterGraef 0:d26c1b55cfca 507 mem_free_callback(void *m)
DieterGraef 0:d26c1b55cfca 508 {
DieterGraef 0:d26c1b55cfca 509 return tcpip_callback_with_block(mem_free, m, 0);
DieterGraef 0:d26c1b55cfca 510 }
DieterGraef 0:d26c1b55cfca 511
DieterGraef 0:d26c1b55cfca 512 //[MS_CHANGE]
DieterGraef 0:d26c1b55cfca 513
DieterGraef 0:d26c1b55cfca 514 err_t tcpip_shutdown()
DieterGraef 0:d26c1b55cfca 515 {
DieterGraef 0:d26c1b55cfca 516 struct tcpip_msg msg;
DieterGraef 0:d26c1b55cfca 517 sys_sem_t sem;
DieterGraef 0:d26c1b55cfca 518 msg.sem = &sem;
DieterGraef 0:d26c1b55cfca 519 if (sys_mbox_valid(&mbox))
DieterGraef 0:d26c1b55cfca 520 {
DieterGraef 0:d26c1b55cfca 521 err_t err = sys_sem_new(msg.sem, 0);
DieterGraef 0:d26c1b55cfca 522 if (err != ERR_OK)
DieterGraef 0:d26c1b55cfca 523 return err;
DieterGraef 0:d26c1b55cfca 524
DieterGraef 0:d26c1b55cfca 525 msg.type = TCPIP_MSG_SHUTDOWN;
DieterGraef 0:d26c1b55cfca 526 sys_mbox_post(&mbox, &msg);
DieterGraef 0:d26c1b55cfca 527 sys_sem_wait(msg.sem);
DieterGraef 0:d26c1b55cfca 528 sys_sem_free(msg.sem);
DieterGraef 0:d26c1b55cfca 529 return ERR_OK;
DieterGraef 0:d26c1b55cfca 530 }
DieterGraef 0:d26c1b55cfca 531 return ERR_VAL;
DieterGraef 0:d26c1b55cfca 532 }
DieterGraef 0:d26c1b55cfca 533 //[END_MS_CHANGE]
DieterGraef 0:d26c1b55cfca 534
DieterGraef 0:d26c1b55cfca 535 #endif /* !NO_SYS */