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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_MCF5235_GCC/] [lwip/] [contrib/] [port/] [FreeRTOS/] [MCF5235/] [sys_arch.c] - Blame information for rev 583

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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