source: svn/newcon3bcm2_21bu/nexus/base/src/ucos_ii/nexus_base_os.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 19.1 KB
Line 
1/***************************************************************************
2*     (c)2008-2011 Broadcom Corporation
3
4*  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5*  and may only be used, duplicated, modified or distributed pursuant to the terms and
6*  conditions of a separate, written license agreement executed between you and Broadcom
7*  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8*  no license (express or implied), right to use, or waiver of any kind with respect to the
9*  Software, and Broadcom expressly reserves all rights in and to the Software and all
10*  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11*  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12*  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE. 
13*   
14*  Except as expressly set forth in the Authorized License,
15*   
16*  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17*  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18*  and to use this information only in connection with your use of Broadcom integrated circuit products.
19*   
20*  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21*  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22*  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23*  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24*  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25*  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26*  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27*  USE OR PERFORMANCE OF THE SOFTWARE.
28
29*  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30*  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31*  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32*  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33*  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34*  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35*  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36*  ANY LIMITED REMEDY.
37*
38* $brcm_Workfile: nexus_base_os.c $
39* $brcm_Revision: 8 $
40* $brcm_Date: 8/29/11 12:19p $
41*
42* API Description:
43*
44* Revision History:
45*
46* $brcm_Log: /nexus/base/src/ucos_ii/nexus_base_os.c $
47*
48* 8   8/29/11 12:19p agin
49* SWNOOS-481:  Add additional task priorities for UCOS Diags only.
50*
51* 7   7/11/11 3:34p agin
52* SWNOOS-466:  Don't need to zero out pSettings->driverModuleInit and
53*  pSettings->driverModuleUninit.
54*
55* 6   7/10/11 4:13p agin
56* SWNOOS-466:  Initialize driverModuleInit and driverModuleUninit.
57*
58* 5   5/21/11 11:40a agin
59* SWNOOS-461:  Add NEXUS_P_Base_StrCmp.
60*
61* 4   3/31/11 7:08a agin
62* SWNOOS-450:  Support GHS for 97125 again.
63*
64* 3   11/11/10 5:10p vsilyaev
65* SW7405-4995: Use BKNI_Memcmp to preinitialize structure used in
66*  GetDefaultSettings
67*
68* 2   9/15/10 3:41p jtna
69* SW7420-1004: added BERR_StoreError and NEXUS_GetLastError_Os
70*
71* 1   7/20/10 6:26p jfisher
72* SW7572-30:  Add ucos_ii support.
73*
74* 1   7/20/10 2:08p jfisher
75* SW7572-30:  Add ucos_ii support.
76*
77* 8   7/13/09 1:22p cnovak
78* PR56705: Adjust the ucos task priorities which we assign to the Nexus
79*  module priorities.
80*
81* 7   3/4/09 10:46a agadre
82* PR51817:Update ucos task priorities
83*
84* 6   8/6/08 4:02p cnovak
85* PR45469: Default thread priorities setup for uCOS.
86*
87* 5   8/5/08 1:50p cnovak
88* PR43697: Setup default uCOS task priorities for each Nexus scheduler
89*  thread.
90*
91* 4   7/31/08 12:17p cnovak
92* PR43697: Minor tweaking.
93*
94* 3   7/22/08 11:59a cnovak
95* PR43697: Enable call to MIPS cache flush. Fix bug in environment
96*  get/set routines.
97*
98* 2   6/19/08 6:13p cnovak
99* PR43697: Fix Time_Add implementation.
100*
101* 1   6/17/08 2:36p cnovak
102* PR43697: Add uCOS to Nexus.
103*
104***************************************************************************/
105#include "nexus_base.h"
106#include "nexus_base_priv.h"
107
108#include "bos.h"
109#include "ministd.h"
110#include "cache_util.h"
111
112BDBG_MODULE(nexus_base_os);
113
114
115/****************************************************************************
116        Defines
117****************************************************************************/
118/* We're porting the 256-task version of uCOS. If we move to a new version,
119   it will likely require a different port, or a bit of refactoring at least.
120*/
121#define UCOS_MAX_TASKS          (256)
122#define UCOS_TASK_STACKSIZE_C   (2048 * sizeof(unsigned int))
123#define UCOS_OS_TICK_RATE_MS    (1000/ g_ticks_per_second)    /* How many ms in an OS tick? <<< JPF -the value is really ms per tick */
124#define MAX_ENV_ENTRIES         (64)
125
126/****************************************************************************
127        Map the NEXUS scheduler priorities into a default set of uCOS tasks
128        Per NDS, the 256-task version of uCOS has the following assignments:
129       
130        NDS-UK           0-7, 56-71, 88-95, 128-175, 192-215, 224-231, 248-255
131        NDS-TI           24-31, 40-47, 96-111, 216-223, 240-247
132        DRIVERS (HDI+CA) 8-23, 32-39, 48-55, 72-87, 112-127, 176-191, 232-239
133           
134        We use the highest driver task (8) for the ISR task. We also need to
135        pick one for main. Since NEXUS uses many fewer tasks then the old HDI4
136        driver implementation, we don't need to worry about running out - I hope.
137       
138        These task priorities are relative to Nexus, not the system. DO NOT put
139        the idle task at the lowest uCOS task or else modules like frontend, which
140        uses idle, will not function correctly.
141****************************************************************************/
142const NEXUS_ModulePriority ucosPriorityMap[NEXUS_ModulePriority_eMax] = {
143#ifdef UCOS_DIAGS
144        3,              /* NEXUS_ModulePriority_eIdle */
145        2,              /* NEXUS_ModulePriority_eLow */
146        1,              /* NEXUS_ModulePriority_eDefault */
147        0,              /* NEXUS_ModulePriority_eHigh */
148        6,              /* NEXUS_ModulePriority_eIdleActiveStandby */
149        5,              /* NEXUS_ModulePriority_eLowActiveStandby */
150        4               /* NEXUS_ModulePriority_eHighActiveStandby */
151#else
152        55,     /* NEXUS_ModulePriority_eIdle */
153        54,     /* NEXUS_ModulePriority_eLow */
154        2,     /* NEXUS_ModulePriority_eDefault */
155        1,     /* NEXUS_ModulePriority_eHigh */
156#endif
157};
158
159static int s_priority_index = 54;
160/****************************************************************************
161        Structures
162****************************************************************************/
163BDBG_OBJECT_ID(NEXUS_Thread);
164
165typedef struct NEXUS_Thread {
166    BDBG_OBJECT(NEXUS_Thread)
167    int task; /* task id of the new thread */
168    char name[16];
169    void (*pThreadFunc)(void *);
170    void *pContext;
171        b_task_t handle;
172    NEXUS_ThreadSettings settings;
173    NEXUS_P_ThreadInfo info;
174    unsigned * stack;
175} NEXUS_Thread;
176
177typedef struct NEXUS_OsEnv {
178    unsigned count;
179    struct {
180        const char *key;
181        const char *value;
182    } env[MAX_ENV_ENTRIES];
183} NEXUS_OsEnv;
184
185/****************************************************************************
186        Static variables
187****************************************************************************/
188/* This module is a singleton. We can only have 1 */
189static bool bModuleInitialized = false;
190static NEXUS_Thread * aTaskObjectList[UCOS_MAX_TASKS];
191static NEXUS_OsEnv NEXUS_P_OsEnv = {
192    0,
193    {{ NULL, NULL }}
194};
195
196typedef void (* UCOS_TaskFunction )(void *pv_param);
197
198/****************************************************************************
199****************************************************************************/
200BERR_Code
201NEXUS_P_Base_Os_Init(void)
202{
203    BERR_Code rc = BERR_SUCCESS;
204   
205    if (bModuleInitialized == true) {
206        rc = BERR_TRACE(BERR_LEAKED_RESOURCE);
207        return rc;
208    }
209
210    /* Initialize our task list */
211    BKNI_Memset(aTaskObjectList, 0x00, sizeof(aTaskObjectList));
212
213    bModuleInitialized = true;
214
215    return rc;
216}
217
218/****************************************************************************
219****************************************************************************/
220void 
221NEXUS_P_Base_Os_Uninit(void)
222{
223    bModuleInitialized = false;
224}
225
226/****************************************************************************
227    Return the current timestamp. NEXUS_Time is an abstract data type as
228    far as NEXUS is concerned.
229****************************************************************************/
230void 
231NEXUS_Time_Get(NEXUS_Time *time)
232{
233    long osTicks;
234
235    BDBG_ASSERT(time);
236   
237    osTicks = bos_getticks();
238    time->osTicks = osTicks;
239
240    return;
241}
242
243/****************************************************************************
244    Return time difference in ms
245****************************************************************************/
246long 
247NEXUS_Time_Diff(const NEXUS_Time *future, const NEXUS_Time *past)
248{
249    long tickDiff;
250    NEXUS_Time tempTime;
251   
252    BDBG_ASSERT(future);
253    BDBG_ASSERT(past);
254
255    /* Check for wrap condition */
256    if (past->osTicks > future->osTicks) {
257        /* Get max tick value */
258        tempTime.osTicks = -1;
259        tickDiff = (tempTime.osTicks - past->osTicks) + future->osTicks;
260    } else {
261        tickDiff = future->osTicks - past->osTicks;
262    }
263   
264    return (tickDiff * UCOS_OS_TICK_RATE_MS);
265}
266
267/****************************************************************************
268****************************************************************************/
269void 
270NEXUS_Time_Add(NEXUS_Time *time, long delta_ms)
271{
272    BDBG_ASSERT(time);
273   
274    time->osTicks += (delta_ms / UCOS_OS_TICK_RATE_MS);
275   
276    return;
277}
278
279/****************************************************************************
280****************************************************************************/
281void 
282NEXUS_FlushCache(const void *pvAddr, size_t ulNumBytes)
283{
284    flush_dcache((unsigned long)pvAddr, (unsigned long)((unsigned char*)pvAddr + ulNumBytes));
285}
286
287/****************************************************************************
288****************************************************************************/
289const char *
290NEXUS_GetEnv(const char *name)
291{
292    unsigned i;
293   
294    for (i=0;i<NEXUS_P_OsEnv.count;i++) {
295        if (! NEXUS_P_Base_StrCmp(NEXUS_P_OsEnv.env[i].key, name)) {
296            BDBG_MSG(("GetEnv: %s=%s", NEXUS_P_OsEnv.env[i].key, NEXUS_P_OsEnv.env[i].value));
297            return NEXUS_P_OsEnv.env[i].value;
298        }
299    }
300    BDBG_MSG(("GetEnv: %s", name));
301   
302    return NULL;
303}
304
305/****************************************************************************
306****************************************************************************/
307void 
308NEXUS_SetEnv(const char *name, const char *value)
309{
310    unsigned i;
311
312    BDBG_MSG(("SetEnv: %s=%s", name, value));
313
314    /* if already there, replace old with new */
315    for (i=0;i<NEXUS_P_OsEnv.count;i++) {
316        if (! NEXUS_P_Base_StrCmp(NEXUS_P_OsEnv.env[i].key, name)) {
317            NEXUS_P_OsEnv.env[i].value = value;
318            return;
319        }
320    }
321    /* not already there -- add it (save new key.value pair) */
322    if (i<sizeof(NEXUS_P_OsEnv.env)/sizeof(*NEXUS_P_OsEnv.env)) {
323        NEXUS_P_OsEnv.env[i].key = name;
324        NEXUS_P_OsEnv.env[i].value = value;
325        NEXUS_P_OsEnv.count = i+1;
326    }
327    return;
328}
329
330/****************************************************************************
331****************************************************************************/
332static int my_atoi(const char *s)
333{
334        int i=0;
335
336        while ((*s >= '0') && (*s <='9'))
337                i = i*10 + *(s++) - '0';
338
339        return i;
340}
341int 
342NEXUS_atoi(const char *str)
343{
344    return my_atoi(str);
345}
346
347/****************************************************************************
348****************************************************************************/
349void 
350NEXUS_Thread_GetDefaultSettings(NEXUS_ThreadSettings *pSettings)
351{
352    BDBG_ASSERT(pSettings);
353    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
354    pSettings->priority = ucosPriorityMap[NEXUS_ModulePriority_eDefault];
355    pSettings->stackSize = UCOS_TASK_STACKSIZE_C;
356    return;
357}
358
359BERR_Code BERR_StoreError_tagged(const char *file, unsigned lineno, const char *error, BERR_Code rc)
360{
361    /* not yet implemented */
362    if (rc) {
363        BKNI_Printf("!!!Error %s(%#x) at %s:%d\n", error, rc, file, lineno); /* mimic original BERR_TRACE behavior */
364    }
365    return rc;
366}
367
368void NEXUS_GetLastError_Os(BERR_Code *code)
369{
370    /* not yet implemented */
371    *code = 0;
372    return;
373}
374
375/****************************************************************************
376    This private function is called from the new kernel thread. From here
377    we call the real task function.
378****************************************************************************/
379static int 
380NEXUS_P_ThreadEntry(void *data)
381{
382        unsigned taskId;
383    NEXUS_ThreadHandle thread = (NEXUS_ThreadHandle)data;
384
385    BDBG_MSG(("NEXUS_P_ThreadEntry"));
386   
387        /* Get the current task ID (priority) and use it to find our task object */
388        taskId = thread->task;
389        if (taskId >= UCOS_MAX_TASKS) {
390            BKNI_Printf("Invalid task [%d]!!\n", taskId);
391            BKNI_Fail();
392                return -1;
393        }
394
395        thread = aTaskObjectList[taskId];
396
397    if (!thread) {
398            BKNI_Printf("Invalid task called [%d]!!\n", taskId);
399            BKNI_Fail();
400        return -1;
401    }
402
403    BDBG_MSG(("NEXUS_P_ThreadEntry: task handle %p", thread));
404
405    if (((unsigned long)thread->pThreadFunc & 0xe0000000) != 0x80000000) {
406        BKNI_Printf("trying to execute task at 0x%.8lx\n", (unsigned long)thread->pThreadFunc);
407        BKNI_Fail();
408    }
409
410        /* Call the original task */
411    (*thread->pThreadFunc)(thread->pContext);
412
413    BKNI_Printf("Task terminated!!\n");
414
415    return 0;
416}
417
418/****************************************************************************
419****************************************************************************/
420NEXUS_P_ThreadInfo *
421NEXUS_P_ThreadInfo_Get(void)
422{
423        /* Not sure what this is supposed to do */
424    return NULL;
425}
426
427/****************************************************************************
428****************************************************************************/
429void
430NEXUS_Base_GetDefaultSettings(NEXUS_Base_Settings *pSettings)
431{
432    unsigned i;
433
434    BDBG_ASSERT(pSettings);
435    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
436    for(i=0;i<sizeof(pSettings->threadSettings)/sizeof(pSettings->threadSettings[0]);i++) {
437        NEXUS_Thread_GetDefaultSettings(&pSettings->threadSettings[i]);
438        /* Map the scheduler's priority to an real uCOS priority */
439        pSettings->threadSettings[i].priority = ucosPriorityMap[i];
440    }
441    return;
442}
443
444/****************************************************************************
445****************************************************************************/
446NEXUS_ThreadHandle
447NEXUS_Thread_Create(const char *pThreadName, void (*pThreadFunc)(void *), void *pContext, const NEXUS_ThreadSettings *pSettings)
448{
449    BERR_Code mrc;
450    NEXUS_ThreadHandle hThread;
451    int priority, stackSize;
452        unsigned *p_task_stack;
453        b_task_params params;
454
455    BDBG_ASSERT(pThreadName);
456    BDBG_ASSERT(pThreadFunc);
457
458    BDBG_MSG(("NEXUS_Thread_Create"));
459#if 0
460    /* Use locals so we can change them witout changing the settings they provided */
461        priority = -1;
462        stackSize = -1;
463       
464        /* If we get a NULL pointer, use our default settings */
465    if (pSettings) {
466            priority = pSettings->priority;
467            stackSize = pSettings->stackSize;
468    }
469
470    /* If they used -1 then use these defaults */
471    if (priority <= 0) priority = ucosPriorityMap[NEXUS_ModulePriority_eDefault] + s_priority_index++;
472#else
473        priority = s_priority_index++;
474#endif
475    if (stackSize < 0) stackSize = UCOS_TASK_STACKSIZE_C;
476
477    BDBG_MSG(("Thread Pri: %d Stack: %d", priority, stackSize));
478
479        if (priority >= UCOS_MAX_TASKS) {
480                BKNI_Printf("BKNI_AddTask: priority 0x%.8lx invalid\n", priority) ;
481                return NULL;
482        }
483
484    /* We allocate the task stack for uCOS. After we've successfully allocated
485       the memory, keep a pointer to the "stack"
486    */
487    hThread = BKNI_Malloc(sizeof(*hThread) + stackSize);
488    if (!hThread) {
489        mrc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
490        return NULL;
491    }
492    BKNI_Memset(hThread, 0, sizeof(*hThread) + stackSize);
493
494        p_task_stack = (unsigned *)((char *)hThread + sizeof(*hThread));
495   
496    BDBG_MSG(("NEXUS_Thread_Create: task=%p, stack=%p", hThread, p_task_stack));
497
498#ifdef __MON_STACK_USAGE__
499        BKNI_Memset((char *)p_task_stack, 0x55, stackSize);
500        task_stack_tbl[priority] = ( char * )p_task_stack;
501#endif
502
503    BDBG_OBJECT_INIT(hThread, NEXUS_Thread);
504    hThread->task = priority;
505    hThread->stack = p_task_stack;
506    strcpy(hThread->name, (const char *) pThreadName);
507    hThread->pThreadFunc = pThreadFunc;
508    hThread->pContext = pContext;
509    hThread->settings.priority = priority;
510    hThread->settings.stackSize = stackSize;
511    NEXUS_P_ThreadInfo_Init(&(hThread->info));
512    hThread->info.pThreadName = hThread->name;
513
514        aTaskObjectList[priority] = hThread;
515
516        /* NDS wants us to call OSAddTask, not OSTaskCreate. OSAddTask doesn't
517           let us pass in a user-defined parameter, so we'll need to store the
518           parameter and pass it in from our shim
519        */
520
521        params.name = hThread->name;
522        params.priority = priority;
523        params.stack = p_task_stack;
524        params.stack_size = stackSize/sizeof(unsigned int);
525        hThread->task = priority;
526        if (bos_start_task(&(hThread->handle),&params,(b_task_func)NEXUS_P_ThreadEntry,hThread) != b_ok)
527        {
528        aTaskObjectList[priority] = NULL;
529                BKNI_Free(hThread);
530        BKNI_Printf("Error creating uC/OS task [%d]\n", priority);
531        return NULL;
532        }
533
534    return hThread;
535}
536
537/****************************************************************************
538    Wait for the task to exit. If the task function has already returned, it
539    returns the saved return code. This functions releases all resources
540    associated with the NEXUS_Thread, and that object can't be used any more.
541
542    We do not force the task to exit -- this is the user's responsibility.
543    However NEXUS_Thread_Destroy might interrupt any blocked kernel interface
544    functions.
545****************************************************************************/
546void 
547NEXUS_Thread_Destroy(NEXUS_ThreadHandle thread)
548{
549    BDBG_MSG(("NEXUS_Thread_Destroy"));
550
551    BDBG_OBJECT_ASSERT(thread, NEXUS_Thread);
552
553    if (thread->task) {
554        if (thread->task) {
555            BDBG_WRN(("NEXUS_Thread_Destroy: %#lx killing (%s:%u)", (unsigned long)thread, thread->name, thread->task));
556
557            bos_stop_task(thread->handle);
558        }
559    }
560
561    BDBG_OBJECT_DESTROY(thread, NEXUS_Thread);
562    BKNI_Free(thread);
563   
564    return;
565}
566
567#ifdef GHS
568int
569strcasecmp(const char *s1, const char *s2)
570{
571    int i;
572    for (i=0;s1[i] && s2[i];i++) {
573        char c1 = tolower((int)s1[i]);
574        char c2 = tolower((int)s2[i]);
575        if (c1 < c2) return -1;
576        if (c1 > c2) return 1;
577    }
578    /* if one string is longer than the other then they don't compare */
579    if (s1[i]) return 1; /*s1 longer than s2*/
580    if (s2[i]) return -1;/*s2 longer than s1*/
581    return 0;
582}
583#endif
584
585int
586NEXUS_P_Base_StrCmp(const char *str1, const char *str2)
587{
588    int ch1, ch2, diff;
589
590    for(;;) {
591        ch1 = *str1++;
592        ch2 = *str2++;
593        diff = ch1 - ch2;
594        if (diff) {
595            return diff;
596        } else if (ch1=='\0') {
597            return 0;
598        }
599    }
600}
Note: See TracBrowser for help on using the repository browser.