sys_arch.c 11.9 KB
Newer Older
1 2 3 4 5 6 7
#include <rtthread.h>

#include "lwip/sys.h"
#include "lwip/opt.h"
#include "lwip/stats.h"
#include "lwip/err.h"
#include "arch/sys_arch.h"
8
#include "lwip/debug.h"
9 10 11
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "netif/ethernetif.h"
12
#include "lwip/sio.h"
13 14 15

#include <string.h>

16 17
static err_t netif_device_init(struct netif *netif)
{
18
    struct eth_device *ethif;
19

20 21 22 23
    ethif = (struct eth_device *)netif->state;
    if (ethif != RT_NULL)
    {
        rt_device_t device;
24

25 26 27 28 29 30
        /* get device object */
        device = (rt_device_t) ethif;
        if (rt_device_init(device) != RT_EOK)
        {
            return ERR_IF;
        }
31

32 33
        /* copy device flags to netif flags */
        netif->flags = ethif->flags;
34

35 36
        return ERR_OK;
    }
37

38
    return ERR_IF;
39 40 41
}

static void tcpip_init_done_callback(void *arg)
42
{
43 44 45 46 47 48
    rt_device_t device;
    struct eth_device *ethif;
    struct ip_addr ipaddr, netmask, gw;
    struct rt_list_node* node;
    struct rt_object* object;
    struct rt_object_information *information;
49

50
    extern struct rt_object_information rt_object_container[];
51

52
    LWIP_ASSERT("invalid arg.\n",arg);
53

54 55 56
    IP4_ADDR(&gw, 0,0,0,0);
    IP4_ADDR(&ipaddr, 0,0,0,0);
    IP4_ADDR(&netmask, 0,0,0,0);
57

58 59
    /* enter critical */
    rt_enter_critical();
60

61 62 63 64 65 66 67 68 69 70 71
    /* for each network interfaces */
    information = &rt_object_container[RT_Object_Class_Device];
    for (node = information->object_list.next;
         node != &(information->object_list);
         node = node->next)
    {
        object = rt_list_entry(node, struct rt_object, list);
        device = (rt_device_t)object;
        if (device->type == RT_Device_Class_NetIf)
        {
            ethif = (struct eth_device *)device;
72

73 74
            /* leave critical */
            rt_exit_critical();
75

76 77
            netif_add(ethif->netif, &ipaddr, &netmask, &gw,
                      ethif, netif_device_init, tcpip_input);
78

79 80
            if (netif_default == RT_NULL)
                netif_set_default(ethif->netif);
81 82

#if LWIP_DHCP
83 84 85 86 87 88
            if (ethif->flags & NETIF_FLAG_DHCP)
            {
                /* if this interface uses DHCP, start the DHCP client */
                dhcp_start(ethif->netif);
            }
            else
89
#endif
90 91 92 93
            {
                /* set interface up */
                netif_set_up(ethif->netif);
            }
94 95

#ifdef LWIP_NETIF_LINK_CALLBACK
96
            netif_set_link_up(ethif->netif);
97 98
#endif

99 100 101 102
            /* enter critical */
            rt_enter_critical();
        }
    }
103

104 105 106
    /* leave critical */
    rt_exit_critical();
    rt_sem_release((rt_sem_t)arg);
107 108
}

109 110 111 112 113
/**
 * LwIP system initialization
 */
void lwip_system_init(void)
{
114 115
    rt_err_t rc;
    struct rt_semaphore done_sem;
116

117 118
    /* set default netif to NULL */
    netif_default = RT_NULL;
119

120
    rc = rt_sem_init(&done_sem, "done", 0, RT_IPC_FLAG_FIFO);
121

122 123 124
    if (rc != RT_EOK)
    {
        LWIP_ASSERT("Failed to create semaphore", 0);
125

126 127
        return;
    }
128

129
    tcpip_init(tcpip_init_done_callback, (void *)&done_sem);
130

131 132 133 134 135 136 137 138 139 140
    /* waiting for initialization done */
    if (rt_sem_take(&done_sem, RT_WAITING_FOREVER) != RT_EOK)
    {
        rt_sem_detach(&done_sem);

        return;
    }
    rt_sem_detach(&done_sem);

    /* set default ip address */
141
#if !LWIP_DHCP
142 143 144
    if (netif_default != RT_NULL)
    {
        struct ip_addr ipaddr, netmask, gw;
145

146 147 148
        IP4_ADDR(&ipaddr, RT_LWIP_IPADDR0, RT_LWIP_IPADDR1, RT_LWIP_IPADDR2, RT_LWIP_IPADDR3);
        IP4_ADDR(&gw, RT_LWIP_GWADDR0, RT_LWIP_GWADDR1, RT_LWIP_GWADDR2, RT_LWIP_GWADDR3);
        IP4_ADDR(&netmask, RT_LWIP_MSKADDR0, RT_LWIP_MSKADDR1, RT_LWIP_MSKADDR2, RT_LWIP_MSKADDR3);
149

150 151
        netifapi_netif_set_addr(netif_default, &ipaddr, &netmask, &gw);
    }
152 153 154 155 156
#endif
}

void sys_init(void)
{
157
    /* nothing on RT-Thread porting */
158 159 160 161
}

void lwip_sys_init(void)
{
162
    lwip_system_init();
163
}
164 165 166

err_t sys_sem_new(sys_sem_t *sem, u8_t count)
{
167 168 169
    static unsigned short counter = 0;
    char tname[RT_NAME_MAX];
    sys_sem_t tmpsem;
170

171
    RT_DEBUG_NOT_IN_INTERRUPT;
172

173 174
    rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter);
    counter ++;
175

176 177 178 179 180 181
    tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO);
    if (tmpsem == RT_NULL)
        return ERR_MEM;
    else
    {
        *sem = tmpsem;
182

183 184 185
        return ERR_OK;
    }
}
186 187 188

void sys_sem_free(sys_sem_t *sem)
{
189 190
    RT_DEBUG_NOT_IN_INTERRUPT;
    rt_sem_delete(*sem);
191 192 193 194
}

void sys_sem_signal(sys_sem_t *sem)
{
195
    rt_sem_release(*sem);
196 197 198 199
}

u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
{
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
    rt_err_t ret;
    s32_t t;
    u32_t tick;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* get the begin tick */
    tick = rt_tick_get();
    if (timeout == 0)
        t = RT_WAITING_FOREVER;
    else
    {
        /* convert msecond to os tick */
        if (timeout < (1000/RT_TICK_PER_SECOND))
            t = 1;
        else
            t = timeout / (1000/RT_TICK_PER_SECOND);
    }

    ret = rt_sem_take(*sem, t);

    if (ret == -RT_ETIMEOUT)
        return SYS_ARCH_TIMEOUT;
    else
    {
        if (ret == RT_EOK)
            ret = 1;
    }

    /* get elapse msecond */
    tick = rt_tick_get() - tick;

    /* convert tick to msecond */
    tick = tick * (1000 / RT_TICK_PER_SECOND);
    if (tick == 0)
        tick = 1;

    return tick;
238 239 240
}

#ifndef sys_sem_valid
241 242 243
/** Check if a semaphore is valid/allocated:
 *  return 1 for valid, 0 for invalid
 */
244 245
int sys_sem_valid(sys_sem_t *sem)
{
246
    return (int)(*sem);
247 248
}
#endif
249

250
#ifndef sys_sem_set_invalid
251 252
/** Set a semaphore invalid so that sys_sem_valid returns 0
 */
253 254
void sys_sem_set_invalid(sys_sem_t *sem)
{
255
    *sem = RT_NULL;
256 257 258
}
#endif

M
mbbill@gmail.com 已提交
259
/* ====================== Mutex ====================== */
260

M
mbbill@gmail.com 已提交
261 262
/** Create a new mutex
 * @param mutex pointer to the mutex to create
263 264
 * @return a new mutex
 */
M
mbbill@gmail.com 已提交
265 266
err_t sys_mutex_new(sys_mutex_t *mutex)
{
267 268 269 270 271
    static unsigned short counter = 0;
    char tname[RT_NAME_MAX];
    sys_mutex_t tmpmutex;

    RT_DEBUG_NOT_IN_INTERRUPT;
M
mbbill@gmail.com 已提交
272

273 274
    rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MUTEX_NAME, counter);
    counter ++;
275

276 277 278 279 280 281
    tmpmutex = rt_mutex_create(tname, RT_IPC_FLAG_FIFO);
    if (tmpmutex == RT_NULL)
        return ERR_MEM;
    else
    {
        *mutex = tmpmutex;
M
mbbill@gmail.com 已提交
282

283 284
        return ERR_OK;
    }
M
mbbill@gmail.com 已提交
285 286 287
}

/** Lock a mutex
288 289
 * @param mutex the mutex to lock
 */
M
mbbill@gmail.com 已提交
290 291
void sys_mutex_lock(sys_mutex_t *mutex)
{
292 293
    RT_DEBUG_NOT_IN_INTERRUPT;
    rt_mutex_take(*mutex, RT_WAITING_FOREVER);
M
mbbill@gmail.com 已提交
294

295
    return;
M
mbbill@gmail.com 已提交
296 297 298
}

/** Unlock a mutex
299 300
 * @param mutex the mutex to unlock
 */
M
mbbill@gmail.com 已提交
301 302
void sys_mutex_unlock(sys_mutex_t *mutex)
{
303
    rt_mutex_release(*mutex);
M
mbbill@gmail.com 已提交
304 305 306
}

/** Delete a semaphore
307 308
 * @param mutex the mutex to delete
 */
M
mbbill@gmail.com 已提交
309 310
void sys_mutex_free(sys_mutex_t *mutex)
{
311
    RT_DEBUG_NOT_IN_INTERRUPT;
312

313
    rt_mutex_delete(*mutex);
M
mbbill@gmail.com 已提交
314 315 316
}

#ifndef sys_mutex_valid
317 318 319
/** Check if a mutex is valid/allocated:
 *  return 1 for valid, 0 for invalid
 */
M
mbbill@gmail.com 已提交
320 321
int sys_mutex_valid(sys_mutex_t *mutex)
{
322
    return (int)(*mutex);
M
mbbill@gmail.com 已提交
323 324 325 326
}
#endif

#ifndef sys_mutex_set_invalid
327 328
/** Set a mutex invalid so that sys_mutex_valid returns 0
 */
M
mbbill@gmail.com 已提交
329 330
void sys_mutex_set_invalid(sys_mutex_t *mutex)
{
331
    *mutex = RT_NULL;
M
mbbill@gmail.com 已提交
332 333
}
#endif
334 335 336 337 338

/* ====================== Mailbox ====================== */

err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{
339 340 341 342 343
    static unsigned short counter = 0;
    char tname[RT_NAME_MAX];
    sys_mbox_t tmpmbox;

    RT_DEBUG_NOT_IN_INTERRUPT;
344

345 346
    rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MBOX_NAME, counter);
    counter ++;
347

348 349 350 351
    tmpmbox = rt_mb_create(tname, size, RT_IPC_FLAG_FIFO);
    if (tmpmbox != RT_NULL)
    {
        *mbox = tmpmbox;
352

353 354
        return ERR_OK;
    }
355

356
    return ERR_MEM;
357 358 359 360
}

void sys_mbox_free(sys_mbox_t *mbox)
{
361
    RT_DEBUG_NOT_IN_INTERRUPT;
362

363
    rt_mb_delete(*mbox);
364

365
    return;
366 367
}

M
mbbill@gmail.com 已提交
368 369 370
/** Post a message to an mbox - may not fail
 * -> blocks if full, only used from tasks not from ISR
 * @param mbox mbox to posts the message
371 372
 * @param msg message to post (ATTENTION: can be NULL)
 */
373 374
void sys_mbox_post(sys_mbox_t *mbox, void *msg)
{
375
    RT_DEBUG_NOT_IN_INTERRUPT;
376

377
    rt_mb_send_wait(*mbox, (rt_uint32_t)msg, RT_WAITING_FOREVER);
378

379
    return;
380 381 382 383
}

err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
{
384 385
    if (rt_mb_send(*mbox, (rt_uint32_t)msg) == RT_EOK)
        return ERR_OK;
386

387
    return ERR_MEM;
388 389
}

M
mbbill@gmail.com 已提交
390 391 392 393 394 395
/** Wait for a new message to arrive in the mbox
 * @param mbox mbox to get a message from
 * @param msg pointer where the message is stored
 * @param timeout maximum time (in milliseconds) to wait for a message
 * @return time (in milliseconds) waited for a message, may be 0 if not waited
           or SYS_ARCH_TIMEOUT on timeout
396 397
 *         The returned time has to be accurate to prevent timer jitter!
 */
398 399
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
{
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
    rt_err_t ret;
    s32_t t;
    u32_t tick;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* get the begin tick */
    tick = rt_tick_get();

    if(timeout == 0)
        t = RT_WAITING_FOREVER;
    else
    {
        /* convirt msecond to os tick */
        if (timeout < (1000/RT_TICK_PER_SECOND))
            t = 1;
        else
            t = timeout / (1000/RT_TICK_PER_SECOND);
    }

    ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, t);

    if(ret == -RT_ETIMEOUT)
        return SYS_ARCH_TIMEOUT;
    else
    {
        LWIP_ASSERT("rt_mb_recv returned with error!", ret == RT_EOK);
    }

    /* get elapse msecond */
    tick = rt_tick_get() - tick;

    /* convert tick to msecond */
    tick = tick * (1000 / RT_TICK_PER_SECOND);
    if (tick == 0)
        tick = 1;

    return tick;
438 439
}

M
mbbill@gmail.com 已提交
440 441 442 443 444
/** Wait for a new message to arrive in the mbox
 * @param mbox mbox to get a message from
 * @param msg pointer where the message is stored
 * @param timeout maximum time (in milliseconds) to wait for a message
 * @return 0 (milliseconds) if a message has been received
445 446
 *         or SYS_MBOX_EMPTY if the mailbox is empty
 */
447 448
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
{
449
    int ret;
450

451
    ret = rt_mb_recv(*mbox, (rt_uint32_t *)msg, 0);
452

453 454 455 456 457 458 459
    if(ret == -RT_ETIMEOUT)
        return SYS_ARCH_TIMEOUT;
    else
    {
        if (ret == RT_EOK) 
            ret = 1;
    }
460

461
    return ret;
462 463 464
}

#ifndef sys_mbox_valid
465 466 467
/** Check if an mbox is valid/allocated:
 *  return 1 for valid, 0 for invalid
 */
468 469
int sys_mbox_valid(sys_mbox_t *mbox)
{
470
    return (int)(*mbox);
471 472
}
#endif
473

474
#ifndef sys_mbox_set_invalid
475 476
/** Set an mbox invalid so that sys_mbox_valid returns 0
 */
477 478
void sys_mbox_set_invalid(sys_mbox_t *mbox)
{
479
    *mbox = RT_NULL;
480 481 482 483 484
}
#endif

/* ====================== System ====================== */

485 486 487 488 489
sys_thread_t sys_thread_new(const char    *name,
                            lwip_thread_fn thread,
                            void          *arg,
                            int            stacksize,
                            int            prio)
490
{
491
    rt_thread_t t;
492

493
    RT_DEBUG_NOT_IN_INTERRUPT;
494

495 496 497
    /* create thread */
    t = rt_thread_create(name, thread, arg, stacksize, prio, 20);
    RT_ASSERT(t != RT_NULL);
498

499 500
    /* startup thread */
    rt_thread_startup(t);
501

502
    return t;
503 504 505 506
}

sys_prot_t sys_arch_protect(void)
{
507
    rt_base_t level;
508

509 510 511 512
    /* disable interrupt */
    level = rt_hw_interrupt_disable();

    return level;
513 514 515 516
}

void sys_arch_unprotect(sys_prot_t pval)
{
517 518 519 520 521
    /* enable interrupt */
    rt_hw_interrupt_enable(pval);

    return;
}
522

523 524 525 526 527 528 529 530 531 532 533 534 535 536
void sys_arch_assert(const char *file, int line)
{
    rt_kprintf("\nAssertion: %d in %s, thread %s\n",
               line, file, rt_thread_self()->name);
    RT_ASSERT(0);
}

u32_t sys_jiffies(void)
{
    return rt_tick_get();
}

u32_t sio_read(sio_fd_t fd, u8_t *buf, u32_t size)
{
D
dzzxzz@gmail.com 已提交
537
    u32_t len;
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557

    RT_ASSERT(fd != RT_NULL);

    len = rt_device_read((rt_device_t)fd, 0, buf, size);
    if (len <= 0)
        return 0;

    return len;
}

u32_t sio_write(sio_fd_t fd, u8_t *buf, u32_t size)
{
    RT_ASSERT(fd != RT_NULL);

    return rt_device_write((rt_device_t)fd, 0, buf, size);
}

void sio_read_abort(sio_fd_t fd)
{
    rt_kprintf("read_abort\n");
558 559
}

560
void ppp_trace(int level, const char *format, ...)
561
{
562 563 564 565 566 567 568 569
    va_list args;
    rt_size_t length;
    static char rt_log_buf[RT_CONSOLEBUF_SIZE];

    va_start(args, format);
    length = rt_vsprintf(rt_log_buf, format, args);
    rt_device_write((rt_device_t)rt_console_get_device(), 0, rt_log_buf, length);
    va_end(args);
570
}