OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_130/] [contrib/] [port/] [FreeRTOS/] [ColdFire/] [__sys_arch.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/*
2
 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3
 * Modifications Copyright (c) 2006 Christian Walter <wolti@sil.at>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without modification,
7
 * are permitted provided that the following conditions are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright notice,
10
 *    this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright notice,
12
 *    this list of conditions and the following disclaimer in the documentation
13
 *    and/or other materials provided with the distribution.
14
 * 3. The name of the author may not be used to endorse or promote products
15
 *    derived from this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
26
 * OF SUCH DAMAGE.
27
 *
28
 * This file is part of the lwIP TCP/IP stack.
29
 *
30
 * Author: Adam Dunkels <adam@sics.se>
31
 * Modifcations: Christian Walter <wolti@sil.at>
32
 *
33
 * $Id: __sys_arch.c 2 2011-07-17 20:13:17Z filepang@gmail.com $
34
 */
35
 
36
/* ------------------------ System includes ------------------------------- */
37
 
38
#include "stdlib.h"
39
 
40
/* ------------------------ FreeRTOS includes ----------------------------- */
41
#include "FreeRTOS.h"
42
#include "task.h"
43
#include "semphr.h"
44
 
45
/* ------------------------ lwIP includes --------------------------------- */
46
#include "lwip/debug.h"
47
#include "lwip/def.h"
48
#include "lwip/sys.h"
49
#include "lwip/mem.h"
50
#include "lwip/sio.h"
51
#include "lwip/stats.h"
52
 
53
/* ------------------------ Project includes ------------------------------ */
54
 
55
/* ------------------------ Defines --------------------------------------- */
56
/* This is the number of threads that can be started with sys_thead_new() */
57
#define SYS_MBOX_SIZE               ( 16 )
58
#define MS_TO_TICKS( ms )           \
59
    ( portTickType )( ( portTickType ) ( ms ) / portTICK_RATE_MS )
60
#define TICKS_TO_MS( ticks )        \
61
    ( unsigned long )( ( portTickType ) ( ticks ) * portTICK_RATE_MS )
62
#define THREAD_STACK_SIZE           ( 256 /*FSL:1024*/ )
63
#define THREAD_NAME                 "lwIP"
64
 
65
#define THREAD_INIT( tcb ) \
66
    do { \
67
        tcb->next = NULL; \
68
        tcb->pid = ( xTaskHandle )0; \
69
        tcb->timeouts.next = NULL; \
70
    } while( 0 )
71
 
72
/* ------------------------ Type definitions ------------------------------ */
73
typedef struct sys_tcb
74
{
75
    struct sys_tcb *next;
76
    struct sys_timeouts timeouts;
77
    xTaskHandle     pid;
78
} sys_tcb_t;
79
 
80
/* ------------------------ Prototypes ------------------------------------ */
81
 
82
/* ------------------------ Static functions ------------------------------ */
83
sys_tcb_t      *sys_thread_current( void );
84
 
85
/* ------------------------ Static variables ------------------------------ */
86
static sys_tcb_t *tasks = NULL;
87
 
88
/* ------------------------ Start implementation -------------------------- */
89
void
90
sys_init( void )
91
{
92
    LWIP_ASSERT( "sys_init: not called first", tasks == NULL );
93
    tasks = NULL;
94
}
95
 
96
/*
97
 * This optional function does a "fast" critical region protection and returns
98
 * the previous protection level. This function is only called during very short
99
 * critical regions. An embedded system which supports ISR-based drivers might
100
 * want to implement this function by disabling interrupts. Task-based systems
101
 * might want to implement this by using a mutex or disabling tasking. This
102
 * function should support recursive calls from the same task or interrupt. In
103
 * other words, sys_arch_protect() could be called while already protected. In
104
 * that case the return value indicates that it is already protected.
105
 *
106
 * sys_arch_protect() is only required if your port is supporting an operating
107
 * system.
108
 */
109
sys_prot_t
110
sys_arch_protect( void )
111
{
112
    vPortEnterCritical(  );
113
    return 1;
114
}
115
 
116
/*
117
 * This optional function does a "fast" set of critical region protection to the
118
 * value specified by pval. See the documentation for sys_arch_protect() for
119
 * more information. This function is only required if your port is supporting
120
 * an operating system.
121
 */
122
void
123
sys_arch_unprotect( sys_prot_t pval )
124
{
125
    ( void )pval;
126
    vPortExitCritical(  );
127
}
128
 
129
/*
130
 * Prints an assertion messages and aborts execution.
131
 */
132
void
133
sys_assert( const char *msg )
134
{
135
        /*FSL:only needed for debugging
136
        printf(msg);
137
        printf("\n\r");
138
        */
139
    vPortEnterCritical(  );
140
    for(;;)
141
    ;
142
}
143
 
144
void
145
sys_debug( const char *const fmt, ... )
146
{
147
        /*FSL: same implementation as printf*/
148
 
149
    /*FSL: removed due to lack of space*/
150
    //printf(fmt);
151
}
152
 
153
/* ------------------------ Start implementation ( Threads ) -------------- */
154
 
155
/*
156
 * Starts a new thread with priority "prio" that will begin its execution in the
157
 * function "thread()". The "arg" argument will be passed as an argument to the
158
 * thread() function. The argument "ssize" is the requested stack size for the
159
 * new thread. The id of the new thread is returned. Both the id and the
160
 * priority are system dependent.
161
 */
162
sys_thread_t
163
sys_thread_new(char *name, void ( *thread ) ( void *arg ), void *arg, int /*size_t*/ stacksize, int prio )
164
{
165
    sys_thread_t    thread_hdl = SYS_THREAD_NULL;
166
    int             i;
167
    sys_tcb_t      *p;
168
 
169
    /* We disable the FreeRTOS scheduler because it might be the case that the new
170
     * tasks gets scheduled inside the xTaskCreate function. To prevent this we
171
     * disable the scheduling. Note that this can happen although we have interrupts
172
     * disabled because xTaskCreate contains a call to taskYIELD( ).
173
     */
174
    vPortEnterCritical(  );
175
 
176
    p = tasks;
177
    i = 0;
178
    /* We are called the first time. Initialize it. */
179
    if( p == NULL )
180
    {
181
        p = (sys_tcb_t *)pvPortMalloc( sizeof( sys_tcb_t ) );
182
        if( p != NULL )
183
        {
184
            tasks = p;
185
        }
186
    }
187
    else
188
    {
189
        /* First task already counter. */
190
        i++;
191
        /* Cycle to the end of the list. */
192
        while( p->next != NULL )
193
        {
194
            i++;
195
            p = p->next;
196
        }
197
        p->next = (sys_tcb_t *)pvPortMalloc( sizeof( sys_tcb_t ) );
198
        p = p->next;
199
    }
200
 
201
    if( p != NULL )
202
    {
203
        /* Memory allocated. Initialize the data structure. */
204
        THREAD_INIT( p );
205
 
206
        /* Now q points to a free element in the list. */
207
        if( xTaskCreate( thread, (const signed char *const)name, stacksize, arg, prio, &p->pid ) == pdPASS )
208
        {
209
            thread_hdl = p;
210
        }
211
        else
212
        {
213
            vPortFree( p );
214
        }
215
    }
216
 
217
    vPortExitCritical(  );
218
    return thread_hdl;
219
}
220
 
221
void
222
sys_arch_thread_remove( sys_thread_t hdl )
223
{
224
    sys_tcb_t      *current = tasks, *prev;
225
    sys_tcb_t      *toremove = hdl;
226
    xTaskHandle     pid = ( xTaskHandle ) 0;
227
 
228
    LWIP_ASSERT( "sys_arch_thread_remove: assertion hdl != NULL failed!", hdl != NULL );
229
 
230
    /* If we have to remove the first task we must update the global "tasks"
231
     * variable. */
232
    vPortEnterCritical(  );
233
    if( hdl != NULL )
234
    {
235
        prev = NULL;
236
        while( ( current != NULL ) && ( current != toremove ) )
237
        {
238
            prev = current;
239
            current = current->next;
240
        }
241
        /* Found it. */
242
        if( current == toremove )
243
        {
244
            /* Not the first entry in the list. */
245
            if( prev != NULL )
246
            {
247
                prev->next = toremove->next;
248
            }
249
            else
250
            {
251
                tasks = toremove->next;
252
            }
253
            LWIP_ASSERT( "sys_arch_thread_remove: can't remove thread with timeouts!",
254
                         toremove->timeouts.next == NULL );
255
            pid = toremove->pid;
256
            THREAD_INIT( toremove );
257
            vPortFree( toremove );
258
        }
259
    }
260
    /* We are done with accessing the shared datastructure. Release the
261
     * resources.
262
     */
263
    vPortExitCritical(  );
264
    if( pid != ( xTaskHandle ) 0 )
265
    {
266
        vTaskDelete( pid );
267
        /* not reached. */
268
    }
269
}
270
 
271
/*
272
 * Returns the thread control block for the currently active task. In case
273
 * of an error the functions returns NULL.
274
 */
275
sys_thread_t
276
sys_arch_thread_current( void )
277
{
278
    sys_tcb_t      *p = tasks;
279
    xTaskHandle     pid = xTaskGetCurrentTaskHandle(  );
280
 
281
    vPortEnterCritical(  );
282
    while( ( p != NULL ) && ( p->pid != pid ) )
283
    {
284
        p = p->next;
285
    }
286
    vPortExitCritical(  );
287
    return p;
288
}
289
 
290
/*
291
 * Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
292
 * each thread has a list of timeouts which is represented as a linked
293
 * list of sys_timeout structures. The sys_timeouts structure holds a
294
 * pointer to a linked list of timeouts. This function is called by
295
 * the lwIP timeout scheduler and must not return a NULL value.
296
 *
297
 * In a single threaded sys_arch implementation, this function will
298
 * simply return a pointer to a global sys_timeouts variable stored in
299
 * the sys_arch module.
300
 */
301
struct sys_timeouts *
302
sys_arch_timeouts( void )
303
{
304
    sys_tcb_t      *ptask;
305
 
306
    ptask = sys_arch_thread_current(  );
307
    LWIP_ASSERT( "sys_arch_timeouts: ptask != NULL", ptask != NULL );
308
    return ptask != NULL ? &( ptask->timeouts ) : NULL;
309
}
310
 
311
/* ------------------------ Start implementation ( Semaphores ) ----------- */
312
 
313
/* Creates and returns a new semaphore. The "count" argument specifies
314
 * the initial state of the semaphore.
315
 */
316
sys_sem_t
317
sys_sem_new( u8_t count )
318
{
319
    xSemaphoreHandle xSemaphore;
320
 
321
    vSemaphoreCreateBinary( xSemaphore );
322
    if( xSemaphore != SYS_SEM_NULL )
323
    {
324
        if( count == 0 )
325
        {
326
            xSemaphoreTake( xSemaphore, 1 );
327
        }
328
#if SYS_STATS == 1
329
        vPortEnterCritical(  );
330
        lwip_stats.sys.sem.used++;
331
        if( lwip_stats.sys.sem.used > lwip_stats.sys.sem.max )
332
        {
333
            lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
334
        }
335
        vPortExitCritical(  );
336
#endif
337
    }
338
    else
339
    {
340
        LWIP_ASSERT( "sys_sem_new: xSemaphore == SYS_SEM_NULL", xSemaphore != SYS_SEM_NULL );
341
    }
342
 
343
    return xSemaphore;
344
}
345
 
346
/* Deallocates a semaphore */
347
void
348
sys_sem_free( sys_sem_t sem )
349
{
350
    LWIP_ASSERT( "sys_sem_free: sem != SYS_SEM_NULL", sem != SYS_SEM_NULL );
351
    if( sem != SYS_SEM_NULL )
352
    {
353
#if SYS_STATS == 1
354
        vPortEnterCritical(  );
355
        lwip_stats.sys.sem.used--;
356
        vPortExitCritical(  );
357
#endif
358
        vQueueDelete( sem );
359
    }
360
}
361
 
362
/* Signals a semaphore */
363
void
364
sys_sem_signal( sys_sem_t sem )
365
{
366
    LWIP_ASSERT( "sys_sem_signal: sem != SYS_SEM_NULL", sem != SYS_SEM_NULL );
367
    xSemaphoreGive( sem );
368
}
369
 
370
/*
371
 * Blocks the thread while waiting for the semaphore to be
372
 * signaled. If the "timeout" argument is non-zero, the thread should
373
 * only be blocked for the specified time (measured in
374
 * milliseconds).
375
 *
376
 * If the timeout argument is non-zero, the return value is the number of
377
 * milliseconds spent waiting for the semaphore to be signaled. If the
378
 * semaphore wasn't signaled within the specified time, the return value is
379
 * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
380
 * (i.e., it was already signaled), the function may return zero.
381
 *
382
 * Notice that lwIP implements a function with a similar name,
383
 * sys_sem_wait(), that uses the sys_arch_sem_wait() function.
384
 */
385
u32_t
386
sys_arch_sem_wait( sys_sem_t sem, u32_t timeout )
387
{
388
    portBASE_TYPE   xStatus;
389
    portTickType    xTicksStart, xTicksEnd, xTicksElapsed;
390
    u32_t           timespent;
391
 
392
    LWIP_ASSERT( "sys_arch_sem_wait: sem != SYS_SEM_NULL", sem != SYS_SEM_NULL );
393
    xTicksStart = xTaskGetTickCount(  );
394
    if( timeout == 0 )
395
    {
396
        do
397
        {
398
            xStatus = xSemaphoreTake( sem, MS_TO_TICKS( 100 ) );
399
        }
400
        while( xStatus != pdTRUE );
401
    }
402
    else
403
    {
404
        xStatus = xSemaphoreTake( sem, MS_TO_TICKS( timeout ) );
405
    }
406
 
407
    /* Semaphore was signaled. */
408
    if( xStatus == pdTRUE )
409
    {
410
        xTicksEnd = xTaskGetTickCount(  );
411
        xTicksElapsed = xTicksEnd - xTicksStart;
412
        timespent = TICKS_TO_MS( xTicksElapsed );
413
    }
414
    else
415
    {
416
        timespent = SYS_ARCH_TIMEOUT;
417
    }
418
    return timespent;
419
}
420
 
421
 
422
/* ------------------------ Start implementation ( Mailboxes ) ------------ */
423
 
424
/* Creates an empty mailbox. */
425
sys_mbox_t
426
sys_mbox_new( /*paolo:void*/int size )
427
{
428
    xQueueHandle    mbox;
429
 
430
    mbox = xQueueCreate( SYS_MBOX_SIZE/*size*/, sizeof( void * ) );
431
    if( mbox != SYS_MBOX_NULL )
432
    {
433
#if SYS_STATS == 1
434
        vPortEnterCritical(  );
435
        lwip_stats.sys.mbox.used++;
436
        if( lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max )
437
        {
438
            lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
439
        }
440
        vPortExitCritical(  );
441
#endif
442
    }
443
    return mbox;
444
}
445
 
446
/*
447
  Deallocates a mailbox. If there are messages still present in the
448
  mailbox when the mailbox is deallocated, it is an indication of a
449
  programming error in lwIP and the developer should be notified.
450
*/
451
void
452
sys_mbox_free( sys_mbox_t mbox )
453
{
454
    void           *msg;
455
 
456
    LWIP_ASSERT( "sys_mbox_free: mbox != SYS_MBOX_NULL", mbox != SYS_MBOX_NULL );
457
    if( mbox != SYS_MBOX_NULL )
458
    {
459
        while( uxQueueMessagesWaiting( mbox ) != 0 )
460
        {
461
            if( sys_arch_mbox_fetch( mbox, &msg, 1 ) != SYS_ARCH_TIMEOUT )
462
            {
463
                LWIP_ASSERT( "sys_mbox_free: memory leak (msg != NULL)", msg == NULL );
464
            }
465
        }
466
        vQueueDelete( mbox );
467
#if SYS_STATS == 1
468
        vPortEnterCritical(  );
469
        lwip_stats.sys.mbox.used--;
470
        vPortExitCritical(  );
471
#endif
472
    }
473
}
474
 
475
/*
476
 * This function sends a message to a mailbox. It is unusual in that no error
477
 * return is made. This is because the caller is responsible for ensuring that
478
 * the mailbox queue will not fail. The caller does this by limiting the number
479
 * of msg structures which exist for a given mailbox.
480
 */
481
void
482
sys_mbox_post( sys_mbox_t mbox, void *data )
483
{
484
    portBASE_TYPE   xQueueSent;
485
 
486
    /* Queue must not be full - Otherwise it is an error. */
487
    xQueueSent = xQueueSend( mbox, &data, 0 );
488
    LWIP_ASSERT( "sys_mbox_post: xQueueSent == pdPASS", xQueueSent == pdPASS );
489
}
490
 
491
/*FSL*/
492
/*
493
 *Try to post the "msg" to the mailbox. Returns ERR_MEM if this one
494
 *is full, else, ERR_OK if the "msg" is posted.
495
 */
496
err_t
497
sys_mbox_trypost( sys_mbox_t mbox, void *data )
498
{
499
    /* Queue must not be full - Otherwise it is an error. */
500
    if(xQueueSend( mbox, &data, 0 ) == pdPASS)
501
    {
502
        return ERR_OK;
503
    }
504
    else
505
    {
506
        return ERR_MEM;
507
    }
508
}
509
 
510
/*
511
 * Blocks the thread until a message arrives in the mailbox, but does
512
 * not block the thread longer than "timeout" milliseconds (similar to
513
 * the sys_arch_sem_wait() function). The "msg" argument is a result
514
 * parameter that is set by the function (i.e., by doing "*msg =
515
 * ptr"). The "msg" parameter maybe NULL to indicate that the message
516
 * should be dropped.
517
 *
518
 * Note that a function with a similar name, sys_mbox_fetch(), is
519
 * implemented by lwIP.
520
 */
521
u32_t
522
sys_arch_mbox_fetch( sys_mbox_t mbox, void **msg, u32_t timeout )
523
{
524
    void           *ret_msg;
525
    portBASE_TYPE   xStatus;
526
    portTickType    xTicksStart, xTicksEnd, xTicksElapsed;
527
    u32_t           timespent;
528
 
529
    LWIP_ASSERT( "sys_arch_mbox_fetch: mbox != SYS_MBOX_NULL", mbox != SYS_MBOX_NULL );
530
    xTicksStart = xTaskGetTickCount(  );
531
    if( timeout == 0 )
532
    {
533
        do
534
        {
535
            xStatus = xQueueReceive( mbox, &ret_msg, MS_TO_TICKS( 100 ) );
536
        }
537
        while( xStatus != pdTRUE );
538
    }
539
    else
540
    {
541
        xStatus = xQueueReceive( mbox, &ret_msg, MS_TO_TICKS( timeout ) );
542
    }
543
 
544
    if( xStatus == pdTRUE )
545
    {
546
        if( msg )
547
        {
548
            *msg = ret_msg;
549
        }
550
        xTicksEnd = xTaskGetTickCount(  );
551
        xTicksElapsed = xTicksEnd - xTicksStart;
552
        timespent = TICKS_TO_MS( xTicksElapsed );
553
    }
554
    else
555
    {
556
        if( msg )
557
        {
558
            *msg = NULL;
559
        }
560
        timespent = SYS_ARCH_TIMEOUT;
561
    }
562
    return timespent;
563
}
564
 
565
u32_t
566
sys_jiffies( void )
567
{
568
    portTickType    xTicks = xTaskGetTickCount(  );
569
 
570
    return ( u32_t )TICKS_TO_MS( xTicks );
571
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.