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/] [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
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without modification,
6
 * are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. The name of the author may not be used to endorse or promote products
14
 *    derived from this software without specific prior written permission.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
 * OF SUCH DAMAGE.
26
 *
27
 * This file is part of the lwIP TCP/IP stack.
28
 *
29
 * Author: Adam Dunkels <adam@sics.se>
30
 *
31
 */
32
 
33
/* lwIP includes. */
34
#include "lwip/debug.h"
35
#include "lwip/def.h"
36
#include "lwip/sys.h"
37
#include "lwip/mem.h"
38
#include "lwip/stats.h"
39
 
40
struct timeoutlist
41
{
42
        struct sys_timeouts timeouts;
43
        xTaskHandle pid;
44
};
45
 
46
/* This is the number of threads that can be started with sys_thread_new() */
47
#define SYS_THREAD_MAX 4
48
 
49
static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX];
50
static u16_t s_nextthread = 0;
51
 
52
 
53
/*-----------------------------------------------------------------------------------*/
54
//  Creates an empty mailbox.
55
sys_mbox_t sys_mbox_new(int size)
56
{
57
        xQueueHandle mbox;
58
 
59
        ( void ) size;
60
 
61
        mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) );
62
 
63
#if SYS_STATS
64
      ++lwip_stats.sys.mbox.used;
65
      if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) {
66
         lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
67
          }
68
#endif /* SYS_STATS */
69
 
70
        return mbox;
71
}
72
 
73
/*-----------------------------------------------------------------------------------*/
74
/*
75
  Deallocates a mailbox. If there are messages still present in the
76
  mailbox when the mailbox is deallocated, it is an indication of a
77
  programming error in lwIP and the developer should be notified.
78
*/
79
void sys_mbox_free(sys_mbox_t mbox)
80
{
81
        if( uxQueueMessagesWaiting( mbox ) )
82
        {
83
                /* Line for breakpoint.  Should never break here! */
84
                portNOP();
85
#if SYS_STATS
86
            lwip_stats.sys.mbox.err++;
87
#endif /* SYS_STATS */
88
 
89
                // TODO notify the user of failure.
90
        }
91
 
92
        vQueueDelete( mbox );
93
 
94
#if SYS_STATS
95
     --lwip_stats.sys.mbox.used;
96
#endif /* SYS_STATS */
97
}
98
 
99
/*-----------------------------------------------------------------------------------*/
100
//   Posts the "msg" to the mailbox.
101
void sys_mbox_post(sys_mbox_t mbox, void *data)
102
{
103
        while ( xQueueSendToBack(mbox, &data, portMAX_DELAY ) != pdTRUE ){}
104
}
105
 
106
 
107
/*-----------------------------------------------------------------------------------*/
108
//   Try to post the "msg" to the mailbox.
109
err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
110
{
111
err_t result;
112
 
113
   if ( xQueueSend( mbox, &msg, 0 ) == pdPASS )
114
   {
115
      result = ERR_OK;
116
   }
117
   else {
118
      // could not post, queue must be full
119
      result = ERR_MEM;
120
 
121
#if SYS_STATS
122
      lwip_stats.sys.mbox.err++;
123
#endif /* SYS_STATS */
124
 
125
   }
126
 
127
   return result;
128
}
129
 
130
/*-----------------------------------------------------------------------------------*/
131
/*
132
  Blocks the thread until a message arrives in the mailbox, but does
133
  not block the thread longer than "timeout" milliseconds (similar to
134
  the sys_arch_sem_wait() function). The "msg" argument is a result
135
  parameter that is set by the function (i.e., by doing "*msg =
136
  ptr"). The "msg" parameter maybe NULL to indicate that the message
137
  should be dropped.
138
 
139
  The return values are the same as for the sys_arch_sem_wait() function:
140
  Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
141
  timeout.
142
 
143
  Note that a function with a similar name, sys_mbox_fetch(), is
144
  implemented by lwIP.
145
*/
146
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
147
{
148
void *dummyptr;
149
portTickType StartTime, EndTime, Elapsed;
150
 
151
        StartTime = xTaskGetTickCount();
152
 
153
        if ( msg == NULL )
154
        {
155
                msg = &dummyptr;
156
        }
157
 
158
        if ( timeout != 0 )
159
        {
160
                if ( pdTRUE == xQueueReceive( mbox, &(*msg), timeout / portTICK_RATE_MS ) )
161
                {
162
                        EndTime = xTaskGetTickCount();
163
                        Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
164
 
165
                        return ( Elapsed );
166
                }
167
                else // timed out blocking for message
168
                {
169
                        *msg = NULL;
170
 
171
                        return SYS_ARCH_TIMEOUT;
172
                }
173
        }
174
        else // block forever for a message.
175
        {
176
                while( pdTRUE != xQueueReceive( mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary
177
                EndTime = xTaskGetTickCount();
178
                Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
179
 
180
                return ( Elapsed ); // return time blocked TODO test    
181
        }
182
}
183
 
184
/*-----------------------------------------------------------------------------------*/
185
/*
186
  Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll
187
  return with SYS_MBOX_EMPTY.  On success, 0 is returned.
188
*/
189
u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg)
190
{
191
void *dummyptr;
192
 
193
        if ( msg == NULL )
194
        {
195
                msg = &dummyptr;
196
        }
197
 
198
   if ( pdTRUE == xQueueReceive( mbox, &(*msg), 0 ) )
199
   {
200
      return ERR_OK;
201
   }
202
   else
203
   {
204
      return SYS_MBOX_EMPTY;
205
   }
206
}
207
 
208
/*-----------------------------------------------------------------------------------*/
209
//  Creates and returns a new semaphore. The "count" argument specifies
210
//  the initial state of the semaphore.
211
sys_sem_t sys_sem_new(u8_t count)
212
{
213
        xSemaphoreHandle  xSemaphore;
214
 
215
        vSemaphoreCreateBinary( xSemaphore );
216
 
217
        if( xSemaphore == NULL )
218
        {
219
 
220
#if SYS_STATS
221
      ++lwip_stats.sys.sem.err;
222
#endif /* SYS_STATS */
223
 
224
                return SYS_SEM_NULL;    // TODO need assert
225
        }
226
 
227
        if(count == 0)   // Means it can't be taken
228
        {
229
                xSemaphoreTake(xSemaphore,1);
230
        }
231
 
232
#if SYS_STATS
233
        ++lwip_stats.sys.sem.used;
234
        if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
235
                lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
236
        }
237
#endif /* SYS_STATS */
238
 
239
        return xSemaphore;
240
}
241
 
242
/*-----------------------------------------------------------------------------------*/
243
/*
244
  Blocks the thread while waiting for the semaphore to be
245
  signaled. If the "timeout" argument is non-zero, the thread should
246
  only be blocked for the specified time (measured in
247
  milliseconds).
248
 
249
  If the timeout argument is non-zero, the return value is the number of
250
  milliseconds spent waiting for the semaphore to be signaled. If the
251
  semaphore wasn't signaled within the specified time, the return value is
252
  SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
253
  (i.e., it was already signaled), the function may return zero.
254
 
255
  Notice that lwIP implements a function with a similar name,
256
  sys_sem_wait(), that uses the sys_arch_sem_wait() function.
257
*/
258
u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
259
{
260
portTickType StartTime, EndTime, Elapsed;
261
 
262
        StartTime = xTaskGetTickCount();
263
 
264
        if(     timeout != 0)
265
        {
266
                if( xSemaphoreTake( sem, timeout / portTICK_RATE_MS ) == pdTRUE )
267
                {
268
                        EndTime = xTaskGetTickCount();
269
                        Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
270
 
271
                        return (Elapsed); // return time blocked TODO test      
272
                }
273
                else
274
                {
275
                        return SYS_ARCH_TIMEOUT;
276
                }
277
        }
278
        else // must block without a timeout
279
        {
280
                while( xSemaphoreTake( sem, portMAX_DELAY ) != pdTRUE ){}
281
                EndTime = xTaskGetTickCount();
282
                Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
283
 
284
                return ( Elapsed ); // return time blocked      
285
 
286
        }
287
}
288
 
289
/*-----------------------------------------------------------------------------------*/
290
// Signals a semaphore
291
void sys_sem_signal(sys_sem_t sem)
292
{
293
        xSemaphoreGive( sem );
294
}
295
 
296
/*-----------------------------------------------------------------------------------*/
297
// Deallocates a semaphore
298
void sys_sem_free(sys_sem_t sem)
299
{
300
#if SYS_STATS
301
      --lwip_stats.sys.sem.used;
302
#endif /* SYS_STATS */
303
 
304
        vQueueDelete( sem );
305
}
306
 
307
/*-----------------------------------------------------------------------------------*/
308
// Initialize sys arch
309
void sys_init(void)
310
{
311
        int i;
312
 
313
        // Initialize the the per-thread sys_timeouts structures
314
        // make sure there are no valid pids in the list
315
        for(i = 0; i < SYS_THREAD_MAX; i++)
316
        {
317
                s_timeoutlist[i].pid = 0;
318
                s_timeoutlist[i].timeouts.next = NULL;
319
        }
320
 
321
        // keep track of how many threads have been created
322
        s_nextthread = 0;
323
}
324
 
325
/*-----------------------------------------------------------------------------------*/
326
/*
327
  Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
328
  each thread has a list of timeouts which is represented as a linked
329
  list of sys_timeout structures. The sys_timeouts structure holds a
330
  pointer to a linked list of timeouts. This function is called by
331
  the lwIP timeout scheduler and must not return a NULL value.
332
 
333
  In a single threaded sys_arch implementation, this function will
334
  simply return a pointer to a global sys_timeouts variable stored in
335
  the sys_arch module.
336
*/
337
struct sys_timeouts *sys_arch_timeouts(void)
338
{
339
int i;
340
xTaskHandle pid;
341
struct timeoutlist *tl;
342
 
343
        pid = xTaskGetCurrentTaskHandle( );
344
 
345
        for(i = 0; i < s_nextthread; i++)
346
        {
347
                tl = &(s_timeoutlist[i]);
348
                if(tl->pid == pid)
349
                {
350
                        return &(tl->timeouts);
351
                }
352
        }
353
 
354
        // Error
355
        return NULL;
356
}
357
 
358
/*-----------------------------------------------------------------------------------*/
359
/*-----------------------------------------------------------------------------------*/
360
// TODO
361
/*-----------------------------------------------------------------------------------*/
362
/*
363
  Starts a new thread with priority "prio" that will begin its execution in the
364
  function "thread()". The "arg" argument will be passed as an argument to the
365
  thread() function. The id of the new thread is returned. Both the id and
366
  the priority are system dependent.
367
*/
368
sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
369
{
370
xTaskHandle CreatedTask;
371
int result;
372
 
373
   if ( s_nextthread < SYS_THREAD_MAX )
374
   {
375
      result = xTaskCreate( thread, ( signed portCHAR * ) name, stacksize, arg, prio, &CreatedTask );
376
 
377
           // For each task created, store the task handle (pid) in the timers array.
378
           // This scheme doesn't allow for threads to be deleted
379
           s_timeoutlist[s_nextthread++].pid = CreatedTask;
380
 
381
           if(result == pdPASS)
382
           {
383
                   return CreatedTask;
384
           }
385
           else
386
           {
387
                   return NULL;
388
           }
389
   }
390
   else
391
   {
392
      return NULL;
393
   }
394
}
395
 
396
/*
397
  This optional function does a "fast" critical region protection and returns
398
  the previous protection level. This function is only called during very short
399
  critical regions. An embedded system which supports ISR-based drivers might
400
  want to implement this function by disabling interrupts. Task-based systems
401
  might want to implement this by using a mutex or disabling tasking. This
402
  function should support recursive calls from the same task or interrupt. In
403
  other words, sys_arch_protect() could be called while already protected. In
404
  that case the return value indicates that it is already protected.
405
 
406
  sys_arch_protect() is only required if your port is supporting an operating
407
  system.
408
*/
409
sys_prot_t sys_arch_protect(void)
410
{
411
        vPortEnterCritical();
412
        return 1;
413
}
414
 
415
/*
416
  This optional function does a "fast" set of critical region protection to the
417
  value specified by pval. See the documentation for sys_arch_protect() for
418
  more information. This function is only required if your port is supporting
419
  an operating system.
420
*/
421
void sys_arch_unprotect(sys_prot_t pval)
422
{
423
        ( void ) pval;
424
        vPortExitCritical();
425
}
426
 
427
/*
428
 * Prints an assertion messages and aborts execution.
429
 */
430
void sys_assert( const char *msg )
431
{
432
        ( void ) msg;
433
        /*FSL:only needed for debugging
434
        printf(msg);
435
        printf("\n\r");
436
        */
437
    vPortEnterCritical(  );
438
    for(;;)
439
    ;
440
}

powered by: WebSVN 2.1.0

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