FreeCalypso > hg > freecalypso-sw
view gsm-fw/gpf/osl/contrib/os_tim_ir.c @ 923:10b4bed10192
gsm-fw/L1: fix for the DSP patch corruption bug
The L1 code we got from the LoCosto fw contains a feature for DSP CPU load
measurement.  This feature is a LoCosto-ism, i.e., not applicable to earlier
DBB chips (Calypso) with their respective earlier DSP ROMs.  Most of the
code dealing with that feature is conditionalized as #if (DSP >= 38),
but one spot was missed, and the MCU code was writing into an API word
dealing with this feature.  In TCS211 this DSP API word happens to be
used by the DSP code patch, hence that write was corrupting the patched
DSP code.
| author | Mychaela Falconia <falcon@ivan.Harhan.ORG> | 
|---|---|
| date | Mon, 19 Oct 2015 17:13:56 +0000 | 
| parents | 536c53d3356c | 
| children | 
line wrap: on
 line source
/* * This C module is a reconstruction based on the disassembly of * os_tim.obj in frame_na7_db_ir.lib from the Leonardo package. */ /* set of included headers from COFF symtab: */ #include <stdio.h> #include "gpfconf.h" /* FreeCalypso addition */ #include "../../nucleus/nucleus.h" #include "typedefs.h" #include "os.h" #include "gdi.h" #include "os_types.h" #include "os_glob.h" extern unsigned os_time_to_tick_multiplier; extern unsigned os_tick_to_time_multiplier; extern T_OS_TIMER_ENTRY TimerTable[]; extern T_OS_TIMER_TABLE_ENTRY *p_list[]; extern int volatile t_list_access; extern unsigned t_start_ticks; extern T_OS_TIMER_TABLE_ENTRY * volatile t_running; extern int used_timers; extern int next_t_handle; extern NU_SEMAPHORE TimSemCB; extern NU_TIMER os_timer_cb; extern int max_used_timers; void os_Timeout(UNSIGNED t_handle); void timer_error(int err) { err = 0; } static int os_remove_timer_from_list(T_OS_TIMER_TABLE_ENTRY *timer) { OS_TICK c_ticks; if (timer != t_running) { if (timer->next != t_running) timer->next->r_ticks += timer->r_ticks; } else { c_ticks = NU_Retrieve_Clock(); if (timer->next == timer) { t_running = 0; } else { timer->next->r_ticks = t_start_ticks + timer->r_ticks + timer->next->r_ticks - c_ticks; t_running = timer->next; } NU_Control_Timer(&os_timer_cb, NU_DISABLE_TIMER); if (t_running != NULL) { t_start_ticks = c_ticks; if (t_running->r_ticks != 0) NU_Reset_Timer(&os_timer_cb, os_Timeout, t_running->r_ticks, 0, NU_ENABLE_TIMER); } } if (timer->next != timer) { timer->prev->next = timer->next; timer->next->prev = timer->prev; } timer->next = NULL; timer->prev = NULL; timer->status = 1; return 1; } static unsigned os_add_timer_to_list(T_OS_TIMER_TABLE_ENTRY *timer, OS_TICK ticks) { T_OS_TIMER_TABLE_ENTRY *t_list; OS_TICK c_ticks, r1_ticks, return_ticks; if (ticks == 0) ticks = 1; c_ticks = NU_Retrieve_Clock(); t_list = t_running; if (t_list != NULL) { if (t_running->r_ticks >= c_ticks - t_start_ticks) { r1_ticks = t_running->r_ticks - c_ticks + t_start_ticks; t_running->r_ticks = r1_ticks; } else { r1_ticks = 0; t_running->r_ticks = 0; } t_start_ticks = c_ticks; return_ticks = 0; while (ticks >= r1_ticks) { ticks -= r1_ticks; t_list = t_list->next; if (t_list == t_running) goto out; r1_ticks = t_list->r_ticks; } t_list->r_ticks -= ticks; if (t_list == t_running) { t_running = timer; t_start_ticks = c_ticks; NU_Control_Timer(&os_timer_cb, NU_DISABLE_TIMER); return_ticks = ticks; } out: timer->next = t_list; timer->prev = t_list->prev; t_list->prev->next = timer; t_list->prev = timer; timer->r_ticks = ticks; } else { timer->next = timer; timer->prev = timer; timer->r_ticks = ticks; t_start_ticks = c_ticks; t_running = timer; return_ticks = ticks; } timer->status = 2; return return_ticks; } GLOBAL LONG os_StartTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle, USHORT Index, OS_TIME InitialTime, OS_TIME RescheduleTime) { T_OS_TIMER_TABLE_ENTRY *timer; OS_TICK ticks; USHORT status; STATUS sts; t_list_access = 1; timer = &TimerTable[TimerHandle].entry; if (TimerHandle > MaxSimultaneousTimer || timer->status == 0) { t_list_access = 0; return OS_ERROR; } sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); /* FIXME: not sure about this if (sts != NU_SUCCESS) os_MyHandle(sts); */ status = timer->status; if (status == 2) status = os_remove_timer_from_list(timer); timer->t_handle = TimerHandle; timer->task_handle = os_MyHandle(); timer->entity_handle = TaskHandle; timer->t_index = Index; timer->p_ticks = TIME_TO_SYSTEM_TICKS(RescheduleTime); ticks = os_add_timer_to_list(timer, TIME_TO_SYSTEM_TICKS(InitialTime)); if (ticks) NU_Reset_Timer(&os_timer_cb, os_Timeout, ticks, 0, NU_ENABLE_TIMER); if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); t_list_access = 0; return OS_OK; } /* FIXME: t_handle is unused?! */ void os_Timeout(UNSIGNED t_handle) { UNSIGNED s_ticks; OS_HANDLE task_handle; OS_HANDLE e_handle; int t_index, i, done; T_OS_TIMER_TABLE_ENTRY **t_r4; T_OS_TIMER_TABLE_ENTRY *timer; void (*timeout_func) (OS_HANDLE, OS_HANDLE, USHORT); OS_TIME InitialTime; if (t_list_access) { t_start_ticks++; NU_Reset_Timer(&os_timer_cb, os_Timeout, 1, 0, NU_ENABLE_TIMER); return; } t_list_access = 1; timer = t_running; if (t_running) { s_ticks = 0; done = 0; i = 0; do { timeout_func = timer->TimeoutProc; if (timer->p_ticks) p_list[i++] = timer; task_handle = timer->task_handle; e_handle = timer->entity_handle; t_index = timer->t_index; timer->status = 1; if (timer->next == timer) { t_running = NULL; done = 1; } else { timer->prev->next = timer->next; timer->next->prev = timer->prev; if (timer->next->r_ticks) { t_running = timer->next; s_ticks = timer->r_ticks; done = 1; } else timer = timer->next; } /* FIXME: IND$CALL() ? */ } while (!done); if (s_ticks) { t_start_ticks = NU_Retrieve_Clock(); NU_Reset_Timer(&os_timer_cb, os_Timeout, s_ticks, 0, NU_ENABLE_TIMER); } } for (t_r4 = p_list; *t_r4; t_r4++) { timer = *t_r4; InitialTime = SYSTEM_TICKS_TO_TIME(timer->p_ticks); os_StartTimer(timer->entity_handle, timer->t_handle, timer->t_index, InitialTime, InitialTime); *t_r4 = NULL; } t_list_access = 0; return; } /* FIXME: TaskHandle is unused?! */ GLOBAL LONG os_StopTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle) { T_OS_TIMER_ENTRY *timer_e; STATUS sts; t_list_access = 1; timer_e = &TimerTable[TimerHandle]; if (TimerHandle > MaxSimultaneousTimer || timer_e->entry.status == 0) { t_list_access = 0; return OS_ERROR; } sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); if (timer_e->entry.status == 2) os_remove_timer_from_list(&timer_e->entry); if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); t_list_access = 0; return OS_OK; } GLOBAL LONG os_IncrementTick(OS_TICK ticks) { return OS_OK; } /* FIXME: TaskHandle is unused?! */ GLOBAL LONG os_DestroyTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle) { STATUS sts; T_OS_TIMER_ENTRY *timer_e; t_list_access = 1; sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); timer_e = &TimerTable[TimerHandle]; if (TimerHandle > MaxSimultaneousTimer || timer_e->entry.status == 0) { if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); t_list_access = 0; return OS_ERROR; } timer_e->next_t_handle = next_t_handle; timer_e->entry.status = 0; used_timers--; t_list_access = 0; if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); return OS_OK; } /* FIXME: TaskHandle and MemPoolHandle are unused?! */ GLOBAL LONG os_CreateTimer(OS_HANDLE TaskHandle, void (*TimeoutProc) (OS_HANDLE, OS_HANDLE, USHORT), OS_HANDLE *TimerHandle, OS_HANDLE MemPoolHandle) { STATUS sts; OS_HANDLE orig_next_t_handle; T_OS_TIMER_ENTRY *timer_e; t_list_access = 1; sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); orig_next_t_handle = next_t_handle; if (next_t_handle == 0) { /* INVALID_HANDLE */ if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); t_list_access = 0; return OS_ERROR; } timer_e = &TimerTable[next_t_handle]; timer_e->entry.status = 1; timer_e->entry.TimeoutProc = TimeoutProc; *TimerHandle = orig_next_t_handle; next_t_handle = timer_e->next_t_handle; used_timers++; if (max_used_timers < used_timers) max_used_timers = used_timers; if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); t_list_access = 0; return OS_OK; }
