source: svn/trunk/newcon3bcm2_21bu/dta/src/bos_ucos_ii.c

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 34.2 KB
Line 
1/***************************************************************
2**
3** Broadcom Corp. Confidential
4** Copyright 1998-2000 Broadcom Corp. All Rights Reserved.
5**
6** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED
7** SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM.
8** YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT
9** SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
10**
11** File:                bos.c
12** Description: encapsulate OS functions.
13**
14** Created: Mon Sep 25 18:12:35 PDT 2006 by Jeff Fisher
15**
16**
17**
18****************************************************************/
19
20#define BOS_C
21#include "bos.h"
22#include "ucos_ii.h"
23#include "bchp_timer.h"
24#include "bstd.h"
25#include "bchp_sun_top_ctrl.h"
26#include "bchp_xpt_fe.h"
27#include "bcm_mips.h"
28#include "bcm_mips_defs.h"
29#include "ministd.h"
30#include "bcmmemmgr.h"
31#ifdef UCOS_USB
32        #include "usbh_cfg.h"
33#endif
34
35BDBG_MODULE(bos);
36
37struct b_task_stats g_os_task_stats[OS_LOWEST_PRIO+2];
38
39extern uint32_t expt_stack; 
40#define INIT_STACK_SIZE         0x2000
41#define B_OS_STK_FILL_BYTE      0xBB
42#define B_OS_STK_FILL_INT32 0xBBBBBBBB
43extern const char *bsymtable_get_name(uint32_t addr, char *buf, size_t buf_len);
44
45void b_os_check_stack(b_task_stats *task, uint32_t pattern) __attribute__((always_inline));
46//unsigned int calc_mips_freq(void) __attribute__((always_inline));
47extern unsigned long MIPS_SetInterrupts(unsigned long new_sr);
48#define OS_DISABLE 0
49
50extern void bint_handler(void);
51b_system_globals_t g_dsp;
52b_system_globals_t *g_p_dsp = &g_dsp;
53
54
55struct b_last_ctxsw
56{
57        unsigned clock; /* value of MIPS clock when task was switched in */
58        unsigned instr;
59} g_last_ctxsw;
60
61static inline void dump(const char *name, const void *addr, size_t nelem)
62{
63        unsigned off;
64
65        printf("%s: %u bytes from %p\n", name, nelem, addr);
66        for (off=0;off<nelem;)
67        {
68                unsigned i;
69
70                printf("0x%08X: ", off+(unsigned)addr);
71                for (i=0;i<16 && off<nelem;i++,off++)
72                {
73                        printf("%02x ", ((uint8_t *)addr)[off]);
74                }
75                printf("\n");
76        }
77        printf("-----------------------------------------\n");
78        return;
79}
80
81/***************************************************************************
82 * Determine the MIPS frequency in HZ using a known timer
83 */
84#if (BCHP_CHIP==7550)
85#define TIMER_DIVISOR   1
86#define TIMER_SHIFT     9
87/* bits 32-9 of this register increment at 90000Hz by default */
88#define CLOCK_REGISTER (BCHP_XPT_FE_PARSER0_TIMESTAMP | 0xB0000000)
89#else
90#define TIMER_DIVISOR   1
91#define TIMER_SHIFT     9
92#define CLOCK_REGISTER (BCHP_XPT_FE_ATS_TS_MOD300 | 0xB0000000)
93#include "bchp_timer.h"
94#ifndef BCHP_K0_OFFSET
95#define BCHP_K0_OFFSET  (0xA0000000 | 0x10000000)
96#endif
97#ifndef WriteReg32
98#define WriteReg32(x,v) { *((volatile unsigned int*)(BCHP_K0_OFFSET + (unsigned int)(x))) = (v); }
99#endif
100#ifndef ReadReg32
101#define ReadReg32(x)    *((volatile unsigned int*)(BCHP_K0_OFFSET + (unsigned int)(x)))
102#endif
103#endif
104
105inline unsigned int calc_mips_freq(void)
106{
107#if (BCHP_CHIP==7550)
108        /* we can't use register macros since BKNI is not initialized yet */
109        volatile uint32_t * clock_ptr = (uint32_t *)CLOCK_REGISTER;
110        uint32_t clock, end_clock;
111        uint32_t count;
112       
113        clock = *clock_ptr >> TIMER_SHIFT;
114        count = bcm_read_cp0($9,0);
115        end_clock = clock + 90000/TIMER_DIVISOR;
116        do
117        {
118                clock = *clock_ptr >> TIMER_SHIFT;
119        }while (end_clock - clock);
120        count = bcm_read_cp0($9,0) - count;
121        return(count);
122#else
123        uint32_t tenth_of_a_second = 0x2932E0;  /* 27000000 */
124        uint32_t start_count,end_count,freq;
125        WriteReg32(BCHP_TIMER_TIMER0_CTRL,
126                           tenth_of_a_second | BCHP_TIMER_TIMER0_CTRL_MODE_MASK | BCHP_TIMER_TIMER0_CTRL_ENA_MASK);
127       
128        start_count = bcm_read_cp0($9,0);
129       
130        WriteReg32(BCHP_TIMER_TIMER_IS,BCHP_TIMER_TIMER_IS_TMR0TO_MASK);
131
132        do
133        {
134        }while (!(ReadReg32(BCHP_TIMER_TIMER_IS) & BCHP_TIMER_TIMER_IS_TMR0TO_MASK));
135
136        end_count = bcm_read_cp0($9,0);
137        freq = (end_count - start_count) * 10;
138        return freq;
139#endif
140}
141
142
143/******************************************************************************
144* INPUTS:    none
145* OUTPUTS:    none.
146* RETURNS:    none
147* FUNCTION: initialize ucos
148******************************************************************************/
149void bos_unhandled_handler(register_t * registers)
150{
151        g_p_dsp->b_in_interrupt = 1;
152        OSIntEnter();
153
154        gdb_handler((unsigned int*)registers, registers[ROFF_CAUSE]);
155
156        OSIntExit();
157        g_p_dsp->b_in_interrupt = 0;
158}
159
160/******************************************************************************
161* INPUTS:    none
162* OUTPUTS:    none.
163* RETURNS:    none
164* FUNCTION: initialize ucos
165******************************************************************************/
166void bos_handler(register_t * registers)
167{
168        register_t cause;
169        register_t compare;
170        register_t status;
171        uint32_t clock;
172        uint32_t exit_clock;
173        uint32_t instr_enter;
174        uint32_t instr_exit;
175        struct b_task_stats *cur_stats;
176
177        clock = bcm_read_cp0($9,0);
178        instr_enter = bcm_read_cp0($25, 2);
179
180        cur_stats = &g_os_task_stats[OSTCBCur->OSTCBPrio];
181
182        status = registers[ROFF_SR];
183        if (0 == (status & ST0_IE))
184        {
185                /* We are trying to enter critical section. Just return. */
186                return;
187        }
188
189        cause = registers[ROFF_CAUSE];
190
191        g_p_dsp->b_in_interrupt = 1;
192        OSIntEnter();
193        g_stat_isr_cnt++;
194
195        cause = (cause >> 8) & 0xFF;
196        if (cause & 0x80)
197        {                 /* timer interrupt */
198                bos_trace(eTRACE_TICK,OSPrioHighRdy,OSTCBCur->OSTCBPrio,clock);
199                /* update 64 bit clock counter */
200                if (clock <  g_running_clock.clock_low)
201                { /* overflow */
202                        g_running_clock.clock_hi++;
203                }
204                g_running_clock.clock_low = clock;
205#if 0
206                {
207                        compare = clock + OS_HW_TICKS;  /* 939391 with 375 MH frequency */
208                       
209                        __asm__("mtc0 %0, $11"::"r"(compare));
210                        //__asm__("nop");
211                }
212#else
213                __asm__("mfc0 %0, $11":"=r"(compare));
214                do
215                {
216                        compare += OS_HW_TICKS;
217                } while ((compare - clock) > OS_HW_TICKS);
218                __asm__("mtc0 %0, $11"::"r"(compare));
219                __asm__("nop");
220#endif
221                OSTimeTick();
222        }
223        if (0x4 & cause)
224        {        /* chip interrupt */
225                unsigned long status;
226                status = bcm_read_cp0($12,0);
227                bcm_write_cp0($12, 0, (status & 0xFFFFFFFCUL));
228
229                bint_handler();
230
231                bcm_write_cp0($12, 0, status);
232        }
233        if (~0x84 & cause)
234        {
235                bos_unhandled_handler(registers);           
236        }
237        OSIntExit();
238        exit_clock = bcm_read_cp0($9,0);
239        instr_exit = bcm_read_cp0($25, 2);
240        if (!(cause & 0x20))
241        {
242                g_stat_isr_time += exit_clock - clock; /* update isr time */
243                g_p_dsp->stat_isr_cnt = instr_enter - instr_exit;
244                cur_stats->clock_cnt -= exit_clock - clock;     /* adjust current task */
245                cur_stats->instr_cnt -= instr_enter - instr_exit;
246        }
247        g_p_dsp->b_in_interrupt = 0;
248}
249
250
251/******************************************************************************
252* INPUTS:    none
253* OUTPUTS:    none.
254* RETURNS:    none
255* FUNCTION: initialize ucos
256******************************************************************************/
257
258
259static const char idle[]="idle";
260static const char isr[]="ISR";
261static const char stat[]="stat";
262static const char usb_async[]="usb";
263
264void bos_init(void)
265{
266        int i;
267        unsigned int mips_freq;
268
269        mips_freq = calc_mips_freq();
270
271        memset(g_p_dsp,0,sizeof(b_system_globals_t));
272
273        g_p_dsp->b_ticks_per_second = g_ticks_per_second;
274        g_running_clock.clock_freq = mips_freq;
275        g_cycles_per_tick = (mips_freq/g_ticks_per_second);
276        OSRegisterException(0, bos_handler, NULL);
277        for (i = 1; i < 32; ++i)
278        {
279                /* Skip Syscall */
280                if (i != 8)
281                        OSRegisterException(i, bos_unhandled_handler, NULL);
282        }
283
284        /* wipe out task statistics */
285        memset(g_os_task_stats, 0, sizeof(g_os_task_stats));
286
287        /* initialize ISR pseudo task */
288        g_os_task_stats[OS_LOWEST_PRIO+1].last_time =   g_os_task_stats[OS_LOWEST_PRIO].last_time;
289        memcpy(g_os_task_stats[OS_LOWEST_PRIO+1].name, isr,  sizeof(isr));
290        g_os_task_stats[OS_LOWEST_PRIO+1].stack = &expt_stack;
291        g_os_task_stats[OS_LOWEST_PRIO+1].stack_size = INIT_STACK_SIZE/sizeof(uint32_t);
292        g_os_task_stats[OS_LOWEST_PRIO+1].stack_left = INIT_STACK_SIZE/sizeof(uint32_t);
293        g_os_task_stats[OS_LOWEST_PRIO+1].stack_fast_scan = 0;
294
295        bcm_write_cp0($25, 6, 0x80000211); /* DCACHE and Instruction/Cycle counter */
296        bcm_write_cp0($25, 4, 0x80288024);
297        bcm_write_cp0($25, 5, 0x80488044);
298
299        bcm_write_cp0($25, 0, 0)  /* PerfCount0 reset to 0 (it is a decrementing count) */
300        bcm_write_cp0($25, 1, 0)  /* PerfCount1 reset to 0 (it is a decrementing count) */
301        bcm_write_cp0($25, 2, 0)  /* PerfCount2 reset to 0 (it is a decrementing count) */
302        bcm_write_cp0($25, 3, 0)  /* PerfCount3 reset to 0 (it is a decrementing count) */
303
304        OSInit();
305
306        return;
307}
308
309
310static struct
311{
312        b_timeval last_time;
313        unsigned calib_idle_ticks;
314        unsigned calib_ms;
315        unsigned last_idle_ctr;
316        unsigned last_ctxsw_ctr;
317        unsigned last_isr_cnt;
318        unsigned last_isr_time;
319} b_os_load_data;
320
321/* returns difference between two timevals in ms */
322static unsigned
323b_os_tv_diff(const b_timeval *end, const b_timeval *begin) 
324{
325        unsigned ms;
326
327        ms = ((int)(end->tv_usec - begin->tv_usec))/1000;
328        ms += (end->tv_sec - begin->tv_sec)*1000;
329        if (ms==0)
330        {
331                ms=1;
332        }
333        return ms;
334}
335
336#ifdef CONFIG_ENABLE_EMU
337        #define B_OS_IDLE_SCALE 10
338#else
339        #define B_OS_IDLE_SCALE 1
340#endif
341
342/* this function calibrates how fast IDLE task runs */
343void
344bos_calibrate(void)
345{
346        unsigned int flags;
347#ifndef CONFIG_ENABLE_SIM
348        b_timeval start;
349        unsigned int idle_ctr;
350
351        GETTIMEOFDAY(&start);
352        idle_ctr = OSIdleCtr;
353        bos_sleep(100/B_OS_IDLE_SCALE);
354#endif
355        GETTIMEOFDAY(&b_os_load_data.last_time);
356
357        flags=bos_enter_critical();
358        b_os_load_data.last_idle_ctr = OSIdleCtr;
359        b_os_load_data.last_ctxsw_ctr = OSCtxSwCtr;
360        b_os_load_data.last_isr_time = g_stat_isr_time;
361        b_os_load_data.last_isr_cnt = g_stat_isr_cnt;
362#ifndef CONFIG_ENABLE_SIM
363        b_os_load_data.calib_idle_ticks = (b_os_load_data.last_idle_ctr - idle_ctr)*B_OS_IDLE_SCALE;    /* prescale idle_ticks, 20 */
364        b_os_load_data.calib_ms = b_os_tv_diff(&b_os_load_data.last_time, &start)*B_OS_IDLE_SCALE;              /* 96 ms */
365#else
366
367        /* These values assume the mips is running at 250MHz (i.e. STRAP_CPU_SPEED_1) */
368        b_os_load_data.calib_idle_ticks = 364;
369        b_os_load_data.calib_ms = 95;
370#endif
371        bos_exit_critical(flags);
372        BDBG_MSG(("calib_idle_ticks %u calib_ms %u\n", b_os_load_data.calib_idle_ticks, b_os_load_data.calib_ms));
373        return;
374}
375
376/******************************************************************************
377* INPUTS:    none
378* OUTPUTS:    none.
379* RETURNS:    none
380* FUNCTION: start ucos
381******************************************************************************/
382void bos_start(void)
383{
384#if 0
385        unsigned int count;
386
387        /* Ensure timer interrupt does not fire before OSStart has completed.  If it does
388           then we will see a race condition where the realExcHandler will try and dereference
389           OSTCBCur before it has been initialised. This will result in a TLB exception being
390           generated because of a NULL pointer exception. */
391        count = bcm_read_cp0($9,0);
392        count += (g_cycles_per_tick * g_ticks_per_second) / 1000;       /* 1ms wait */
393        bcm_write_cp0($11,0,count);
394#endif
395        OSStart();
396};
397
398void OSTaskCreateHook(OS_TCB *ptcb)
399{
400        struct b_task_stats *stat = &g_os_task_stats[ptcb->OSTCBPrio];
401
402        BDBG_ASSERT(ptcb->OSTCBPrio <= OS_LOWEST_PRIO);
403
404        if (ptcb->OSTCBPrio == 2)
405        {
406                printf("Stack[%03d] = 0x%08x-0x%08x %d words\n",ptcb->OSTCBPrio,stat->stack,ptcb->OSTCBStkPtr,stat->stack_size);
407        }
408
409
410        if (!stat->stack && (ptcb->OSTCBStkSize > 0))
411        {
412                stat->stack = (const uint32_t*)ptcb->OSTCBStkBottom;
413                stat->clock_cnt = 0;
414                stat->instr_cnt = 0;
415                stat->active_cnt = 0;
416                stat->stack_size = ptcb->OSTCBStkSize;
417                stat->stack_left = ptcb->OSTCBStkSize;
418                stat->stack_fast_scan = 0;
419#if (OS_TASK_STAT_STK_CHK_EN == 0)
420                memset((void*)stat->stack, B_OS_STK_FILL_BYTE,((ptcb->OSTCBStkSize - OS_FRAME_SIZE )* 4) - 4);
421#endif
422#if OS_TASK_NAME_SIZE > 1
423                strncpy(stat->name,ptcb->OSTCBTaskName,16);
424#endif
425        }
426        printf("Stack[%03d] = 0x%08x-0x%08x %d words\n",ptcb->OSTCBPrio,stat->stack,ptcb->OSTCBStkPtr,stat->stack_size);
427}
428
429
430/******************************************************************************
431 * Create a task
432 ******************************************************************************/
433bresult bos_start_task(
434                b_task_t *handle,         /* [out] new thread handle, passed to b_stop_task when finished */
435                const b_task_params *params, /* optional param structure containing Priority, task name, and stack size */
436                b_task_func func,         /* function to be called by new thread */
437                void *data                /* data passed func */
438                )
439{
440        struct b_task_stats *stat = &g_os_task_stats[params->priority];
441        stat->name[sizeof(stat->name)-1]='\0';
442        memcpy(stat->name, params->name, sizeof(stat->name)-2);
443#if (OS_TASK_STAT_STK_CHK_EN == 0)
444        memset(params->stack, B_OS_STK_FILL_BYTE, params->stack_size*sizeof(uint32_t));
445#endif
446
447        /* check to make sure no duplicate use of same task */
448#if 0//BKTEMP
449        if(NULL == stat->stack)
450                BDBG_WRN(("\n\nERR: task stack [%s] %d\n\n",stat->name, params->priority));
451#else
452        BDBG_ASSERT(NULL == stat->stack);
453#endif
454        stat->stack = (const uint32_t*)params->stack;
455        stat->stack_size = params->stack_size;
456        stat->stack_left = params->stack_size;
457        stat->clock_cnt = 0;
458        stat->instr_cnt = 0;
459        stat->active_cnt = 0;
460        stat->stack_fast_scan = 0;
461        BDBG_WRN(("TASK [%s] %d\n", stat->name, params->priority ));
462
463        *handle = params->priority;
464
465        if (OSTaskCreateExt(func,data,(OS_STK*)&params->stack[params->stack_size - 1],
466                                params->priority,params->priority,(OS_STK*)params->stack,params->stack_size,
467                                NULL,OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR) != OS_NO_ERR)
468        {
469                return berr_invalid_parameter;
470        }
471        return b_ok;
472}
473
474/******************************************************************************
475 * Stop/delete a task
476 ******************************************************************************/
477void bos_stop_task(b_task_t handle)
478{
479#if OS_TASK_DEL_EN > 0
480        INT8U err;
481        INT8U prio = (handle == OS_PRIO_SELF)?OSTCBCur->OSTCBPrio:handle;
482        memset(&g_os_task_stats[prio],0, sizeof(b_task_stats));
483        err = OSTaskDel(handle);
484        if(OS_ERR_NONE != err){
485                BDBG_ERR(("%d:%02x",__LINE__,err));
486        }
487#endif
488}
489
490/******************************************************************************
491 * create an event queue using the even pool provided.
492 ******************************************************************************/
493bresult bos_create_queue(
494                b_queue_t *handle,      /* new event queue */
495                b_event_t *events,      /* event buffer of size num_events */
496                int num_events  /* number of events in event buffer */
497                )
498{
499        /* TODO check queue size does not exceed UINT16 */
500        OS_EVENT* p_os_event = OSQCreate((void**)events,(INT16U)(num_events));
501        if (p_os_event)
502        {
503                *handle = (b_queue_t)p_os_event;
504                return b_ok;
505        }
506        *handle = (b_queue_t)NULL;
507        return berr_out_of_memory;
508}
509
510/******************************************************************************
511 * delete an event queue..
512 ******************************************************************************/
513void bos_delete_queue(
514                b_queue_t *handle        /* event queue */
515                )
516{
517#if OS_Q_DEL_EN > 0
518        INT8U           err;
519        *handle = (b_queue_t)OSQDel((OS_EVENT*)(*handle),OS_DEL_ALWAYS,&err);
520        if(OS_ERR_NONE != err){
521                BDBG_ERR(("%d:%02x",__LINE__,err));
522        }
523#endif
524}
525
526/******************************************************************************
527 * Post and event to the queue..
528 ******************************************************************************/
529bresult bos_post_event(
530                b_queue_t handle,         /* event queue */
531                b_event_t *event                  /* event to post */
532                )
533{
534        INT8U err;
535        if ((err = OSQPost((OS_EVENT*)handle,event)) != OS_NO_ERR)
536        {
537                //BKNI_Printf("OSQPost err = %d\n",err);
538
539                return berr_external_error;
540        }
541        return b_ok;
542}
543
544/******************************************************************************
545 * Wait for an event..
546 ******************************************************************************/
547b_event_t *bos_pend_event(
548                b_queue_t handle,        /* event queue */
549                int timeout_ms   /* timeout in milliseconds */
550                )
551{
552        INT8U err;
553        if (!handle)
554        {
555                volatile int *null=0;*null=*null;
556        }
557
558        if (timeout_ms == 0)
559        {
560                return(b_event_t*)OSQAccept((OS_EVENT*)handle,&err);
561        }
562        else if (timeout_ms < 0)
563        {
564                b_event_t *p_evt;
565                while ((p_evt = (b_event_t*)OSQPend((OS_EVENT*)handle,0xFFFF,&err)) == NULL)
566                {
567                        if ((err != OS_ERR_NONE) && (err != OS_ERR_TIMEOUT))
568                        {
569                                //BKNI_Printf("OSQPend err = %d\n",err);
570                                //__asm__("sdbbp");
571                                p_evt = NULL;
572
573                                break;
574                        }
575                }
576                return p_evt;
577        }
578        else if (timeout_ms < TICKS_TO_MS(1))
579        { /* set timeout as 1 tick if timeout_ms is lower than 1 tick time */
580                timeout_ms = TICKS_TO_MS(1);   
581        }
582        return(b_event_t*)OSQPend((OS_EVENT*)handle,MS_TO_TICKS(timeout_ms),&err);
583}
584
585/******************************************************************************
586 * create an event queue using the even pool provided.
587 ******************************************************************************/
588bresult bos_create_mutex(
589                b_mutex_t *handle               /* mutex reference */
590                )
591{
592        OS_EVENT* p_os_event = OSQCreate((void**)&handle->event_queue,1);
593        if (p_os_event)
594        {
595                handle->queue = (b_queue_t)p_os_event;
596                return bos_post_event(handle->queue,&(handle->event));
597        }
598        return berr_out_of_memory;
599}
600
601/******************************************************************************
602 * delete an event queue..
603 ******************************************************************************/
604void bos_delete_mutex(
605                b_mutex_t *handle        /* mutex reference */
606                )
607{
608#if OS_Q_DEL_EN > 0
609        INT8U           err;
610        OSQDel((OS_EVENT*)handle->queue,OS_DEL_ALWAYS,&err);
611        if(OS_ERR_NONE != err){
612                BDBG_ERR(("%d:%02x",__LINE__,err));
613        }
614#endif
615}
616
617/******************************************************************************
618 * Post and event to the queue..
619 ******************************************************************************/
620bresult bos_acquire_mutex(
621                b_mutex_t *handle,       /* mutex reference */
622                int timeout_ms   /* timeout in milliseconds */
623                )
624{
625        return(bos_pend_event(handle->queue,timeout_ms) != NULL) ? b_ok : berr_timeout;
626}
627
628/******************************************************************************
629 * Wait for an event..
630 ******************************************************************************/
631bresult bos_release_mutex(
632                b_mutex_t *handle        /* event queue */
633                )
634{
635        return bos_post_event(handle->queue,&handle->event);
636}
637
638/******************************************************************************
639 * Sleep for sleep_ms milliseconds..
640 ******************************************************************************/
641
642void bos_sleep(
643                unsigned int sleep_ms     /* number of milliseconds to delay */
644                )
645{
646        unsigned int ticks = MS_TO_TICKS(sleep_ms);
647        if (ticks <= 0)
648        {
649                ticks = 1;
650        }
651        OSTimeDly(ticks);
652}
653/******************************************************************************
654 * Enter critical section..
655 ******************************************************************************/
656unsigned int bos_enter_critical(void)
657{
658        unsigned int flags;
659        //OS_ENTER_CRITICAL(flags);
660        flags = MIPS_SetInterrupts(OS_DISABLE);
661        return flags;
662}
663/******************************************************************************
664 * Exit critical section..
665 ******************************************************************************/
666void bos_exit_critical(unsigned int flags)
667{
668        MIPS_SetInterrupts(flags);
669        //OS_EXIT_CRITICAL(flags);
670}
671
672/******************************************************************************
673 * Return the current OS tick count.
674 ******************************************************************************/
675
676unsigned int bos_getticks(void)
677{
678        return OSTimeGet();
679}
680
681/******************************************************************************
682 * Return the current clock.
683 ******************************************************************************/
684
685void bos_getclock(b_clock *clock)
686{
687        unsigned int flags;
688        uint32_t mips_clock;
689
690        flags = bos_enter_critical();
691        mips_clock = bcm_read_cp0($9,0);
692        /* update 64 bit clock counter */
693        if (mips_clock <  g_running_clock.clock_low)
694        { /* overflow */
695                g_running_clock.clock_hi++;
696        }
697        g_running_clock.clock_low = mips_clock;
698        clock->clock_hi = g_running_clock.clock_hi;
699        bos_exit_critical(flags);
700        clock->clock_low = mips_clock;
701        clock->clock_freq = g_running_clock.clock_freq;
702}
703
704
705void bos_getload(b_cpu_load *load)
706{
707        b_timeval now;
708        unsigned long flags;
709        unsigned idle_ctr;
710        unsigned mips_freq;
711
712        if ((b_os_load_data.calib_ms==0) || (0 == b_os_load_data.calib_idle_ticks))
713        {
714                BDBG_WRN(("calib_ms = %d, calib_idle_ticks = %d\n",b_os_load_data.calib_ms,b_os_load_data.calib_idle_ticks));
715                goto error;
716        }
717        GETTIMEOFDAY(&now);
718        flags = bos_enter_critical();
719        idle_ctr = OSIdleCtr - b_os_load_data.last_idle_ctr;
720        load->ctxsw_rate = OSCtxSwCtr - b_os_load_data.last_ctxsw_ctr;
721        load->isr = g_stat_isr_time - b_os_load_data.last_isr_time;
722        load->isr_rate = g_stat_isr_cnt - b_os_load_data.last_isr_cnt;
723        b_os_load_data.last_idle_ctr = OSIdleCtr;
724        b_os_load_data.last_ctxsw_ctr = OSCtxSwCtr;
725        b_os_load_data.last_isr_time = g_stat_isr_time;
726        b_os_load_data.last_isr_cnt = g_stat_isr_cnt;
727        load->duration = b_os_tv_diff(&now, &b_os_load_data.last_time);
728        if (load->duration==0)
729        {
730                bos_exit_critical(flags);
731                BDBG_WRN(("load->duration = %d\n",load->duration));
732                goto error;
733        }
734        b_os_load_data.last_time = now;
735        g_os_task_stats[OS_LOWEST_PRIO+1].last_time=now;
736        bos_exit_critical(flags);
737        /*
738           BDBG_MSG(("calib_idle_ticks %u calib_ms %u\n", b_os_load_data.calib_idle_ticks, b_os_load_data.calib_ms));
739           BDBG_MSG(("idle_ctr %u duration %u\n", idle_ctr, load->duration));
740         */
741        /*
742         * below we calculate this
743         *   100 * (idle_ctr/load->duration) / (b_os_load_data.calib_idle_ticks/b_os_load_data.calib_ms)
744         *  and carefully rearrange it to both prevent rounding and overflows 
745         */
746        load->ctxsw_rate = (load->ctxsw_rate*1000)/load->duration;
747        load->isr_rate = (load->isr_rate*1000)/load->duration;
748        /* ISR load is
749         *  (isr_time * 100)/(clock * (load->duration/1000))
750         * rearranged to keep it from overflowing and maintain accuracy */
751        mips_freq = g_running_clock.clock_freq/(1000*(100/10));
752        if (mips_freq==0)
753        {
754                BDBG_WRN(("g_running_clock.clock_freq = %d\n",g_running_clock.clock_freq));
755                goto error;
756        }
757        load->isr = 10*load->isr;
758        load->isr_us = load->isr/(mips_freq/10);
759        load->isr = load->isr/(mips_freq*load->duration);
760        load->idle =  ((idle_ctr/32)*((b_os_load_data.calib_ms*100*32)/load->duration))/b_os_load_data.calib_idle_ticks;
761        return;
762error:
763        load->isr = 0;
764        load->duration = 0;
765        load->idle = 0;
766        load->isr_rate = 0;
767        load->ctxsw_rate = 0;
768        return;
769}
770
771extern inline void b_os_check_stack(b_task_stats *task, uint32_t pattern)
772{
773        unsigned i;
774        unsigned left;
775        unsigned virgin;
776
777        for (virgin=0, left=i=task->stack_left;i>0;i--)
778        {
779                if (task->stack[i] != pattern)
780                {
781                        left = i;
782                        virgin = 0;
783                }
784                else
785                {
786                        virgin++;
787                        if (task->stack_fast_scan>0 && left == task->stack_left && virgin>=4)
788                        { /* if dirty marker didn't move and have seen 4 markers in a row, quit */
789                                break;
790                        }
791                }
792        }
793        if (left!=task->stack_left)
794        {
795                task->stack_fast_scan = 0; /* don't use fast scan for the next round */
796                task->stack_left = left;
797        }
798        else
799        {
800                if (task->stack_fast_scan==0)
801                {
802                        task->stack_fast_scan = 16;
803                }
804                else
805                {
806                        task->stack_fast_scan --;
807                }
808        }
809        return;
810}
811struct b_task_stats *bos_taskinfo(int priority)
812{
813        return &g_os_task_stats[priority];
814}
815
816void bos_print_taskinfo(void)
817{
818        unsigned i;
819        unsigned mips_freq = g_running_clock.clock_freq/(1000); /* prescaled frequency */
820        char *pname;
821
822        for (i=0;i<OS_LOWEST_PRIO+2;i++)
823        {
824                struct b_task_stats *stats = &g_os_task_stats[i];
825                b_timeval now;
826                unsigned ms;
827                unsigned task_ms;
828                unsigned task_cnt;
829                unsigned task_load;
830                unsigned flags;
831                unsigned stack_use;
832                unsigned issue_rate;
833                uint32_t pc=0;
834
835                if (!stats->stack)
836                {
837                        continue;
838                }
839                GETTIMEOFDAY(&now);
840                ms = b_os_tv_diff(&now, &stats->last_time);
841                /* capture and reset counters */
842                flags = bos_enter_critical();
843                if (i==OS_LOWEST_PRIO+1)
844                { /* isr pseudo task */
845                        task_cnt = g_stat_isr_cnt - b_os_load_data.last_isr_cnt;
846                        task_ms = g_stat_isr_time - b_os_load_data.last_isr_time; 
847                }
848                else
849                {
850                        task_ms = stats->clock_cnt;
851                        task_cnt = stats->active_cnt;
852                        if (OSTCBPrioTbl[i] && OSTCBPrioTbl[i]->OSTCBStkPtr)
853                        {
854                                pc = ((uint32_t *)OSTCBPrioTbl[i]->OSTCBStkPtr)[ROFF_PC/*-ROFF_NUM_REG*/];
855                        }
856                }
857                issue_rate = stats->instr_cnt;
858                if (task_cnt)
859                {
860                        stats->instr_cnt = 0;
861                        stats->clock_cnt = 0;
862                        stats->active_cnt = 0;
863                        stats->last_time = now;
864                }
865                bos_exit_critical(flags);
866                if (task_ms>1000)
867                {
868                        issue_rate /= (task_ms/1000);
869                }
870                else
871                {
872                        issue_rate = 0;
873                }
874#if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0)
875                {   OS_STK_DATA stk_data;
876                        if (OSTaskStkChk(i, &stk_data) != OS_ERR_NONE)
877                        {
878                                printf("error performing stack check for Priority %d\n",i);
879                        }
880                        else
881                        {
882                                stats->stack_size = stk_data.OSUsed/4 + stk_data.OSFree/4;
883                                stats->stack_left = stk_data.OSFree/4;
884                        }
885                }
886#else
887                b_os_check_stack(stats,B_OS_STK_FILL_INT32);
888#endif
889
890                /* normalize information  */
891                task_load = task_ms / (((mips_freq*10)/10000)*ms);
892                task_ms = task_ms/mips_freq;
893                if (stats->stack_size>0)
894                {
895                        stack_use = (100*(stats->stack_size - stats->stack_left))/stats->stack_size;
896                }
897                else
898                {
899                        stack_use = 100;
900                }
901#if OS_TASK_NAME_SIZE > 1
902                if (strlen(stats->name) > 1)
903                        pname = stats->name;
904                else
905                        pname = OSTCBPrioTbl[i]->OSTCBTaskName;
906#else
907                pname = stats->name;
908#endif
909                printf("TASK(%3u):%-16s CPU %2u.%1u%%(%5ums) RATE %2u.%1u%% CTXSW %5u(%5u/s %7uus) STACK %2u%% (%4u:%4u)\n", 
910                                i, pname, (task_load/10), (task_load%10) , task_ms, issue_rate/10, issue_rate%10, task_cnt, (task_cnt*1000)/ms, 
911                                (task_ms*1000)/(task_cnt?task_cnt:1), stack_use, (stats->stack_size-stats->stack_left), stats->stack_size); 
912        }
913        return;
914}
915
916        const void *
917bos_task_from_stack(const uint32_t *stack)
918{
919        unsigned i;
920
921        for (i=0;i<OS_LOWEST_PRIO+2;i++)
922        {
923                if ( (stack >= g_os_task_stats[i].stack && stack <= g_os_task_stats[i].stack + g_os_task_stats[i].stack_size))
924                {
925                        return g_os_task_stats[i].name;
926                }
927        }
928        return NULL;
929}
930
931void bos_check_stacks(char* str)
932{
933        unsigned i;
934        unsigned mips_freq = g_running_clock.clock_freq/(1000); /* prescaled frequency */
935#if 0
936        if (mem_validate(&g_p_dsp->sdram_heap) == 0)
937        {
938                printf("###### mem_validate failure %s\n",str);
939        }
940#endif
941        for (i=0;i<OS_LOWEST_PRIO+2;i++)
942        {
943                struct b_task_stats *stats = &g_os_task_stats[i];
944                b_timeval now;
945                unsigned ms;
946                unsigned task_ms;
947                unsigned task_cnt;
948                unsigned task_load;
949                unsigned flags;
950                unsigned stack_use;
951                unsigned issue_rate;
952                uint32_t pc=0;
953                const char *name="";
954#if defined(BCM_DEBUG)
955                char buf[24];
956#endif
957
958                if (!stats->stack)
959                {
960                        continue;
961                }
962                GETTIMEOFDAY(&now);
963                ms = b_os_tv_diff(&now, &stats->last_time);
964                /* capture and reset counters */
965                flags = bos_enter_critical();
966                if (i==OS_LOWEST_PRIO+1)
967                { /* isr pseudo task */
968                        task_cnt = g_stat_isr_cnt - b_os_load_data.last_isr_cnt;
969                        task_ms = g_stat_isr_time - b_os_load_data.last_isr_time; 
970                        stats->instr_cnt = g_stat_isr_cnt;
971                }
972                else
973                {
974                        task_ms = stats->clock_cnt;
975                        task_cnt = stats->active_cnt;
976                        if (OSTCBPrioTbl[i] && OSTCBPrioTbl[i]->OSTCBStkPtr)
977                        {
978                                pc = ((uint32_t *)OSTCBPrioTbl[i]->OSTCBStkPtr)[ROFF_PC/*-ROFF_NUM_REG*/];
979                        }
980                }
981                issue_rate = stats->instr_cnt;
982                if (task_cnt)
983                {
984                        stats->instr_cnt = 0;
985                        stats->clock_cnt = 0;
986                        stats->active_cnt = 0;
987                        stats->last_time = now;
988                }
989                bos_exit_critical(flags);
990                if (task_ms>1000)
991                {
992                        issue_rate /= (task_ms/1000);
993                }
994                else
995                {
996                        issue_rate = 0;
997                }
998#if defined(BCM_DEBUG)
999                if (pc)
1000                {
1001                        name = bsymtable_get_name(pc, buf, sizeof(buf));
1002                }
1003#endif
1004                /* check stack */
1005#if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0)
1006                {
1007                        OS_STK_DATA stk_data;
1008                        if (OSTaskStkChk(i, &stk_data) != OS_ERR_NONE)
1009                        {
1010                                printf("error performing stack check for Priority %d\n",i);
1011                        }
1012                        else
1013                        {
1014                                stats->stack_size = stk_data.OSUsed/4 + stk_data.OSFree/4;
1015                                stats->stack_left = stk_data.OSFree/4;
1016                        }
1017                }
1018#else
1019                b_os_check_stack(stats,B_OS_STK_FILL_INT32);
1020#endif
1021
1022                /* normalize information  */
1023                task_load = task_ms / ((mips_freq/100)*ms);
1024                task_ms = task_ms/mips_freq;
1025                if (stats->stack_size>0)
1026                {
1027                        stack_use = (100*(stats->stack_size - stats->stack_left))/stats->stack_size;
1028                }
1029                else
1030                {
1031                        stack_use = 100;
1032                }
1033                if (stack_use > 90)
1034                {
1035                        printf("TASK(%2u):%-12s CPU %2u%%(%4ums) RATE %2u.%1u%% CTXSW %5u(%5u/s %7uus) STACK %2u%% (%u:%u) %s@%s\n", i, stats->name, task_load, task_ms, issue_rate/10, issue_rate%10, task_cnt, (task_cnt*1000)/ms, (task_ms*1000)/(task_cnt?task_cnt:1), stack_use, (stats->stack_size-stats->stack_left), stats->stack_size, name,str); 
1036                }
1037        }
1038}
1039
1040#define RAM_SIZE_MAGIC 0xBABEBAD0
1041unsigned int bos_ram_size(void)
1042{
1043        unsigned int base;
1044        unsigned int alias;
1045        unsigned int size;
1046        unsigned int magic;
1047
1048        magic = RAM_SIZE_MAGIC;
1049
1050        base = MEM_SIZE_8M;
1051        do
1052        {
1053                alias = base << 1;
1054                *(unsigned int*)BCM_PHYS_TO_KSEG1(base - 0x100) = magic;
1055                if (magic == *(unsigned int*)BCM_PHYS_TO_KSEG1(alias - 0x100))
1056                {
1057                        size = base;
1058                        break;
1059                }
1060                base = alias;
1061                magic++;
1062        }while (1);
1063        return size;
1064}
1065
1066/*
1067   If you define PROFILE and would like to use this function, change
1068   OS_TASK_IDLE_HOOK_EN to 2 in os_cfg.h in ucos_ii directory so this
1069   function is used instead of builtin.
1070 */
1071#if (PROFILE && !OS_TASK_IDLE_HOOK_EN)
1072
1073#define OS_TASK_IDLE_CNT        4096
1074static unsigned s_addr[OS_TASK_IDLE_CNT/4 + 8];
1075
1076void OSTaskIdleHook(void)
1077{
1078        volatile unsigned *addr = s_addr;
1079        unsigned i;
1080
1081        for (i=0;i<n;i+=8)
1082        {
1083                (void)addr[i+0];
1084                (void)addr[i+1];
1085                (void)addr[i+2];
1086                (void)addr[i+3];
1087                (void)addr[i+4];
1088                (void)addr[i+5];
1089                (void)addr[i+6];
1090                (void)addr[i+7];
1091        }
1092        return;
1093}
1094#endif
1095
1096extern void bint_handler(void);
1097
1098/* update task accounting here */
1099void OSTaskSwHook(void)
1100{
1101        uint32_t count;
1102        struct b_task_stats * old;
1103        unsigned instr_cnt;
1104
1105        count = bcm_read_cp0($9,0);
1106        instr_cnt = bcm_read_cp0($25, 2);
1107        old = &g_os_task_stats[OSTCBCur->OSTCBPrio];
1108        old->clock_cnt += count - g_last_ctxsw.clock;
1109        old->instr_cnt += g_last_ctxsw.instr - instr_cnt;
1110        old->active_cnt++;
1111        g_last_ctxsw.clock = count;
1112        g_last_ctxsw.instr = instr_cnt;
1113
1114}
1115
1116#if SUPPORT_DST_PLATFORM
1117
1118b_task_stats *bos_get_task_info(b_task_t id)
1119{
1120        if(id>=OS_MAX_TASKS) return NULL;
1121       
1122        return &g_os_task_stats[id];
1123}
1124
1125void bos_print_taskinfo_ex(int level, char *(*callback)(void *, char *, int))
1126{
1127#if 0//BKTODO
1128        unsigned i;
1129        unsigned mips_freq = g_running_clock.clock_freq/(1000); /* prescaled frequency */
1130        int max_name_len = 0;
1131        char task_name[17] = {0, };
1132        // get longest task name
1133        for(i=0;i<OS_MAX_TASKS+2;i++) {
1134                int n;
1135                struct b_task_stats *stats = &g_os_task_stats[i];
1136                if(!stats->stack) continue;
1137                n = strlen(stats->name);
1138                if (max_name_len < n) max_name_len = n;
1139        }
1140       
1141        for(i=0;i<OS_MAX_TASKS+2;i++) {
1142                struct b_task_stats *stats = &g_os_task_stats[i];
1143                b_timeval now;
1144                unsigned ms;
1145                unsigned task_ms;
1146                unsigned task_cnt;
1147                unsigned task_load;
1148                unsigned flags;
1149                unsigned stack_use;
1150                unsigned issue_rate;
1151                uint32_t pc=0, r_sp=0, r_ra=0;
1152                const char *name="";
1153                char buf[24];
1154                uint32_t task_runtime;
1155                char task_runtime_buf[32];
1156
1157                if(!stats->stack) {
1158                        continue;
1159                }
1160                gettimeofday(&now);
1161                ms = b_os_tv_diff(&now, &stats->last_time);
1162                /* capture and reset counters */
1163                flags = bos_enter_critical();
1164                if(i==OS_MAX_TASKS+1) { /* isr pseudo task */
1165                        task_cnt = g_stat_isr_cnt - b_os_load_data.last_isr_cnt;
1166                        task_ms = g_stat_isr_time - b_os_load_data.last_isr_time;
1167                } else {
1168                        task_ms = stats->clock_cnt;
1169                        task_cnt = stats->active_cnt;
1170                        if(OSTCBPrioTbl[i] && OSTCBPrioTbl[i]->OSTCBStkPtr)  {
1171                                pc = ((uint32_t *)OSTCBPrioTbl[i]->OSTCBStkPtr)[ROFF_PC/*-ROFF_NUM_REG*/];
1172                                r_sp = ((uint32_t *)OSTCBPrioTbl[i]->OSTCBStkPtr)[ROFF_SP/*-ROFF_NUM_REG*/];
1173                                r_ra = ((uint32_t *)OSTCBPrioTbl[i]->OSTCBStkPtr)[ROFF_RA/*-ROFF_NUM_REG*/];
1174                        }
1175                }
1176                issue_rate = stats->instr_cnt;
1177                if (task_cnt) {
1178                        stats->instr_cnt = 0;
1179                        stats->clock_cnt = 0;
1180                        stats->active_cnt = 0;
1181                        stats->last_time = now;
1182                }
1183                bos_exit_critical(flags);
1184                if (task_ms>1000) {
1185                        issue_rate /= (task_ms/1000);
1186                } else {
1187                        issue_rate = 0;
1188                }
1189                if (pc) {
1190                        name = bsymtable_get_name(pc, buf, sizeof(buf));
1191                }
1192                /* check stack */
1193                b_os_check_stack(stats,i<OS_MAX_TASKS?B_OS_STK_FILL_INT32:0);
1194                /* normalize information  */
1195                task_load = task_ms / ((mips_freq/100)*ms);
1196                task_ms = task_ms/mips_freq;
1197                if(stats->stack_size>0) {
1198                        stack_use = (100*(stats->stack_size - stats->stack_left))/stats->stack_size;
1199                } else {
1200                        stack_use = 100;
1201                }
1202
1203                // print task name with fixed width. adapt to longest name.
1204                memset(task_name, ' ', sizeof(task_name));
1205                strncpy(task_name, stats->name, strlen(stats->name));
1206                task_name[max_name_len] = 0; // null terminator.
1207
1208                // average task run time per context switch
1209                task_runtime = (task_ms*1000)/(task_cnt?task_cnt:1);
1210                if (task_runtime >= 10000)
1211                        sprintf(task_runtime_buf, "%4ums", task_runtime/1000);
1212                else
1213                        sprintf(task_runtime_buf, "%4uus", task_runtime);
1214
1215                if (level == 1 || level == 2) {
1216                        char prefix[8] = {0, };
1217                        memset(prefix, ' ', sizeof(prefix)-1);
1218                        printf("TASK(%2u):%s CPU %2u%%(%4ums) STACK %2u%% (%u:%u) ",
1219                                i, task_name, task_load, task_ms,
1220                                stack_use, (stats->stack_size-stats->stack_left), stats->stack_size,
1221                                0);
1222                        if (level == 1 && callback && i<OS_MAX_TASKS) { // task 63,64 is not normal task.
1223                                OS_EVENT *pevent;
1224                                char outbuf[100];
1225                                flags = bos_enter_critical();
1226                                pevent = OSTCBPrioTbl[i]->OSTCBEventPtr;
1227                                bos_exit_critical(flags);
1228                                /* this 'pevent' is the event that this task is waiting..
1229                                   show more detail info about this event.
1230                                */
1231                                printf("%s\n", callback(pevent, outbuf, sizeof(outbuf)));
1232                        }
1233                        else if (level == 2 && pc && r_sp && r_ra) {
1234                                printf("\n");
1235                                stack_backtrace((unsigned int *)r_sp, (unsigned int *)pc, (unsigned int *)r_ra, prefix);
1236                        }
1237                        else
1238                                printf("\n");
1239                }
1240                else { // default
1241                        printf("TASK(%2u):%s CPU %2u%%(%4ums) RATE %2u.%1u%% CTXSW %5u(%4u/s %s) STACK %2u%% (%u:%u)\n",
1242                                i, task_name, task_load, task_ms,
1243                                issue_rate/10, issue_rate%10, // rate
1244                                task_cnt, (task_cnt*1000)/ms, task_runtime_buf, // context switch
1245                                stack_use, (stats->stack_size-stats->stack_left), stats->stack_size,
1246                                0);
1247                }
1248        }
1249
1250#if 0
1251        /* cafrii 080919, separate pending list  */
1252        if (level == 1 && callback)
1253        {
1254                OS_EVENT *pevent;
1255                //unsigned flags;
1256                printf("Pending List:\n");
1257               
1258                for(i=0;i<OS_MAX_TASKS;i++) // task 63,64 is not normal task.
1259                {
1260                        struct b_task_stats *stats = &g_os_task_stats[i];
1261                        if(!stats->stack) // no task.
1262                                continue;
1263                        //flags = bos_enter_critical();
1264                        pevent = OSTCBPrioTbl[i]->OSTCBEventPtr;
1265                        //bos_exit_critical(flags);
1266                        /* this 'pevent' is the event that this task is waiting..
1267                           show more detail info about this event.
1268                        */
1269                        callback(i, stats->name, pevent);
1270                }
1271        }
1272#endif // 0
1273#endif
1274        return;
1275}
1276
1277extern unsigned char OSLockNesting;
1278
1279INT8U OSSchedLockCount(void)
1280{
1281        return OSLockNesting;
1282}
1283
1284
1285#if 0
1286/*
1287        User can use OSUser field for their convenience.
1288*/
1289void OSSaveUserData(OS_EVENT *pevent, void *pUser)
1290{
1291        pevent->OSUser = pUser;
1292}
1293
1294void *OSGetUserData(OS_EVENT *pevent)
1295{
1296        return pevent->OSUser;
1297}
1298#endif
1299#endif
1300
Note: See TracBrowser for help on using the repository browser.