/** @file DHL_SYS_Platform.c @brief ÀÌ ¸ðµâ¿¡ ´ëÇÑ °£´ÜÇÑ ¼³¸í.. ex: AudioVideo decoding/capture/output implementation Copyright 2006~2010 Digital STREAM Technology, Inc. All Rights Reserved */ #include "DHL_OSAL.h" #include "DHL_DBG.h" //#include ////#include // for memcpy /* ¸ðµç Çì´õ ÆÄÀÏÀ» Æ÷ÇÔÇÏÁö´Â ¾ÊÀ¸¸ç, compile timeÀ» ÁÙÀ̱â À§ÇØ °¢ ¸ðµâÀº ÇÊ¿äÇÑ ¸¸Å­ÀÇ Çì´õ¸¦ ¼±¾ðÇϵµ·Ï ÇÔ. */ /* DHL µð¹ö±× ¸ðµâ À̸§ Á¤ÀÇ ·ê Âü°í: DHL ¸ðµâµéÀº ¸ðµÎ * ·Î ½ÃÀÛ. API´Â ´ë¹®ÀÚ, Platform ¹× ±âŸ´Â ¼Ò¹®ÀÚ »ç¿ë. µðÆúÆ® ·¹º§Àº 0À¸·Î ¼³Á¤ÇÑ´Ù. (0: ¿¡·¯ ¸Þ½ÃÁö¸¸ Ãâ·Â) */ //DHL_MODULE("*MMM", 0); #if COMMENT ____Config____(){} #endif /* ÀÌ ¸ðµâ ³»ºÎ¿¡¼­ »ç¿ëµÇ´Â °¢Á¾ configuration Á¤ÀÇ. */ /* #define SUPPORT_FAST_SWITCHING_OPTIMIZATION 1 */ /* #define FUNC_MONITOR_TIMER_ID TIMER_ID_FUNC_MONITOR */ #if COMMENT ____Types____(){} #endif /* ÀÌ ¸ðµâ ³»ºÎ¿¡¼­ »ç¿ëµÇ´Â structure ¹× enumerations. */ #if COMMENT ____Variables____(){} #endif /* global·Î Àû¿ëµÇ´Â variable Á¤ÀÇ. °¢ function º°·Î Ư¼öÇÑ ¿ëµµÀÇ variableÀº °¢ functionX block ¿¡¼­ Á¤ÀÇ °¡´É. */ #if COMMENT _____DbgPrint_____(){} #endif #define DHL_DBG_USE_MUTEX 1 // OS_LockTask °ú °°Àº »óÅ¿¡¼­µµ debug print¸¦ ÇÏ·Á°í ÇÑ´Ù¸é // mutex¸¦ »ç¿ëÇÏÁö ¾Ê¾Æ¾ß ÇÑ´Ù. // ÀÏ´Ü caller°¡ À¯ÀÇÇØ¼­ »ç¿ëÇϱâ·Î Çϰí mutex »ç¿ëÇÔ. //------------------------------------------------------------------- // debug log function. // special prefix is inserted at the head of line, // not to be confused with other UART message.. // // µð¹ö±× ¸Þ½ÃÁö Ç¥½ÃµÇ´Â ¿¹: full option // // [APP] {tCmdExecute,130} 0320 Channel Up // [DMC] {tDmc,105} 0320 Dmc_ChangeChannelUp(uid 3) // SetTuner, AIR, 8VSB <--- driver¿¡¼­ Ãâ·ÂÇÏ´Â ¸Þ½ÃÁö // [DMC] {tDmc,105} 0323 Channel change end // [Timer] {tTimer, 200} 00324 Timer started, tid 1 period 3 // [APP] {AppGUI,120} 0324 channel // [EPG] {tEpgTask,120} 0326 epg start.. // // // °¢ ¸ðµâº°·Î PREFIX À̸§À» º¯°æÇؼ­ »ç¿ë. // ±ÛÀÚ ¼ö Á¦ÇÑÀº ¾øÀ¸³ª 3~5ÀÚ·Î ¸ÂÃçÁÖ¸é ÁÁ°ÚÀ½. // // ¿¹) [iLink] [EPG] [PNR] µîµî.. BOOL g_dhl_useMessage = TRUE; // ¾ç»ê ½ÃÁ¡¿¡´Â ÀÌ º¯¼ö¸¦ FALSE·Î Çϰí ÃâÇÏÇϸé ÁöÀúºÐÇÑ ¸Þ¼¼Áö¸¦ ¾ø¾Ù¼ö ÀÖÀ½. // ¹®Á¦°¡ ¹ß»ý½Ã UART¸¦ ÅëÇØ¼­ ÀÌ º¯¼ö¸¦ ON ½ÃŲ ÈÄ µð¹ö±ëÀ» ÇÒ ¼ö ÀÖ´Ù. BOOL g_dhl_usePrintPrefix = TRUE; // TRUEÀ̸é log message ¾Õ¿¡ [TAG]¸¦ Ãß°¡. BOOL g_dhl_printTimeTick = TRUE; // TRUEÀ̸é log message ¾Õ¿¡ time tag¸¦ Ãß°¡. // time tag´Â ¸Þ½ÃÁöµé °£ÀÇ ½Ã°£ °ü°è¸¦ Á¶»çÇÒ ¶§ Æí¸®ÇÔ. ½Ã°£ ´ÜÀ§´Â ¾Æ·¡ ÂüÁ¶. BOOL g_dhl_printTaskInfo = FALSE; // TRUEÀ̸é task ID¸¦ °°ÀÌ Ç¥½Ã. BOOL g_dhl_useOsalPrintf = FALSE; // TRUEÀ̸é DHL_OS_Printf »ç¿ë. DHL_OS_SEMA_ID g_dhl_printSema4; // Print ÇÔ¼ö ³»ºÎÀûÀ¸·Î »ç¿ëÇÏ´Â Sema4 int g_dhl_sema4InitFailCount; // Semaphore »ý¼º½Ã ¿¡·¯ ¹ß»ý Ƚ¼ö Ä«¿îÅÍ // ÀÌ Ä«¿îÅÍ °ªÀ» °ü¸®ÇÏ´Â ÀÌÀ¯´Â ½Ã½ºÅÛ ¸®¼Ò½º µîÀÇ ÀÌÀ¯·Î Semaphore »ý¼ºÀÌ ½ÇÆÐÇÒ °æ¿ì // ¸Å Print call ¸¶´Ù Semaphore »ý¼ºÀ» Àç½Ãµµ ÇÏ°Ô µÇ¸é ½Ã½ºÅÛ¿¡ ¾Ç¿µÇâÀ» ÁÙ ¼ö Àֱ⠶§¹®. // ÀÏÁ¤ Ƚ¼ö ÀÌ»ó ½ÇÆÐÇÑ´Ù¸é Semaphore ¾øÀÌ ±×³É ÁøÇàÇÑ´Ù. // BOOL g_dhl_flushBufferAlways; // true ÀÌ¸é ¸Å printf ¸¶´Ù console buffer¸¦ flush ÇÑ´Ù. // ÀÌ ¼³Á¤À» º¯°æÇÏ´Â API¸¦ ÀÌ¿ë. static int timetick(void) { // timing information. // should not greater than 9999. #if 1 return DHL_OS_GetMsCount() % 10000; #elif 1 // 10 millisec unit. uCOS specific. os ticks per second is 200. // to release cpu burden, i used hard-coded value. return ((OS_GetTickCount() / 2) % 10000); #elif 1 return ((OS_GetTickCount()*100/OS_GetTicksPerSecond()) % 10000); // // Ãâ·ÂµÉ timetickÀÇ ´ÜÀ§´Â 0.1ÃÊ·Î ÇÔ. // UINT32 typeÀ̹ǷΠx10¿¡¼­ overflow°¡ ³¯ ¼ö Àִµ¥ º° ¹®Á¦ ¾ÈµÊ. // #elif 1 return (dhl_sys_get_ms_tick() % 10000); #elif 1 return ((Demux_GetSTC()/90) % 10000); // ´ÜÀ§´Â millisec #endif } #if DHL_DBG_USE_MUTEX static void p_dbg_create_mutex() { DHL_OS_SEMA_ID mysema4 = (DHL_OS_SEMA_ID)0; if (g_dhl_printSema4 == (DHL_OS_SEMA_ID)0 && g_dhl_sema4InitFailCount < 5) // create sema4 { mysema4 = DHL_OS_CreateMutexSemaphore("DhlPrintf"); if (mysema4 == (DHL_OS_SEMA_ID)0) { DHL_OS_Printf("!! DhlPrintf Sema4 creation failed.\n"); g_dhl_sema4InitFailCount++; } else { // Semaphore »ý¼º ¼º°ø. ÀÌÁ¦ »ý¼ºµÈ sema4¸¦ g_dhl_printSema4¿¡ ¾ÈÀüÇÏ°Ô assignÇÑ´Ù. if (1) { UINT32 mask = DHL_OS_DisableInterrupts(); if (g_dhl_printSema4 == 0) { // OS_LockTask µÈ »óÅ¿¡¼­ g_dhl_printSema4¸¦ ÃʱâÈ­ ÇÑ´Ù. g_dhl_printSema4 = mysema4; mysema4 = (DHL_OS_SEMA_ID)0; } DHL_OS_RestoreInterrupts(mask); } if (mysema4) { // ÀÌ¹Ì g_dhl_printSema4°¡ ´Ù¸¥ ŽºÅ©¿¡ ÀÇÇØ »ý¼ºÀÌ µÈ °æ¿ìÀÓ. DHL_OS_Printf("!! Simultaneous DbgPrint Sema4 Creation detected %x. Safe release ours %x\n", (UINT32)g_dhl_printSema4, (UINT32)mysema4); DHL_OS_DeleteSemaphore(mysema4); mysema4 = (DHL_OS_SEMA_ID)0; } else DHL_OS_Printf("DhlPrintf Sema4 created\n"); } } } #endif // DHL_DBG_USE_MUTEX /* DbgPrintFlag options */ #define DHL_DPF_TASKNAME 0x1 #define DHL_DPF_TASKPRIO 0x2 #define DHL_DPF_TIMETICK 0x4 #define DHL_DPF_STDERR 0x100 // stderr ¿¡ Ãâ·ÂÇϵµ·Ï ÇÔ. #define DHL_DPF_FLUSH 0x200 // ¸Å printf ¸¶´Ù flush¸¦ ¼öÇà. int dhl_dbg_print_base(char *prefix, UINT32 flags, char *format, va_list ap) { int n = 0; int len_prefix, len_taskinfo, len_timetick; char *p; #if DHL_DBG_USE_MUTEX static char s_buf[4096]; // static buffer #endif char l_buf[1024]; // local buffer char *buf; static BOOL s_bFirstColumn = TRUE; char ticks[10]; #if DHL_DBG_USE_MUTEX static char taskinfo[128]; // task name is actually unlimited string.. // anyway, we can safely use static array because this function is protected by semaphore. #endif // for using static buffer, i blocked this function with sema4. BOOL bSemTakenHere = FALSE; DHL_OS_TASK_INFO info; DHL_RESULT dhr; BOOL bTaskName = (flags & DHL_DPF_TASKNAME) ? 1 : 0; BOOL bTaskPrio = (flags & DHL_DPF_TASKPRIO) ? 1 : 0; BOOL bTime = (flags & DHL_DPF_TIMETICK) ? 1 : 0; if (!g_dhl_useMessage) return 0; if (format == NULL) return 0; if (prefix == NULL) prefix = ""; len_prefix = strlen(prefix); #if DHL_DBG_USE_MUTEX if (g_dhl_printSema4 == (DHL_OS_SEMA_ID)0) p_dbg_create_mutex(); // ÇöÀç os scheduler°¡ lock »óŶó¸é mutex¸¦ lockÀÌ deadlockÀ» À¯¹ßÇÒ ¼ö ÀÖÀ½. if (DHL_OS_GetIntState()) { DHL_OS_Printf("~"); buf = l_buf; } #if 0 // »õ·Î¿î DHL OSAL ¿¡¼­´Â task lock API°¡ Á¦°ÅµÇ¾úÀ½. else if (osi_in_tasklock(NULL)) { DHL_OS_Printf("^"); buf = l_buf; } #endif else { buf = s_buf; if (g_dhl_printSema4) { DHL_OS_TakeSemaphore(g_dhl_printSema4, DHL_TIMEOUT_FOREVER); bSemTakenHere = TRUE; } } #else buf = l_buf; // use local buffer. then no mutex required. #endif if (strlen(format) > 512) DHL_OS_Printf("!! Warning! too long msg. may be overflow..\n"); p = buf; // var list¸¦ buffer¿¡ expand ½ÃŲ´Ù. if (format) n = vsnprintf(p, sizeof(p), format, ap); else strcpy(buf, "NULL"); if (g_dhl_usePrintPrefix) { // debug messageÁßÀÇ LF (LineFeed) ´ÙÀ½¿¡ "[Prefix] {Task,Priority} time_tag " ¸¦ »ðÀÔ. // // ÇöÀç Ä¿¼­°¡ column zero¿¡ ÀÖÀ» °æ¿ì¿¡¸¸ tag¸¦ »ðÀÔÇÑ´Ù. // int safty_limit = 0; p = buf; if (s_bFirstColumn) { #if DHL_DBG_USE_MUTEX if (bTaskName || bTaskPrio) { dhr = DHL_OS_GetTaskInfo(DHL_OS_GetTaskID(), &info); if (dhr != DHL_OK) snprintf(taskinfo, sizeof(taskinfo), "{? 0x%x} ", dhr); else if (bTaskName && bTaskPrio) snprintf(taskinfo, sizeof(taskinfo), "{%s,%2x} ", info.name, info.priority); else if (bTaskName) snprintf(taskinfo, sizeof(taskinfo), "{%s} ", info.name); else snprintf(taskinfo, sizeof(taskinfo),"{p%2x} ", info.priority); len_taskinfo = strlen(taskinfo); } else len_taskinfo = 0; #endif if (bTime) { snprintf(ticks, 10, "%04d ", timetick()); len_timetick = 5; } else len_timetick = 0; if (len_prefix + len_taskinfo + len_timetick > 0) memmove(p + len_prefix + len_taskinfo + len_timetick, p, strlen(p)+1); // °ø°£È®º¸. prefix + taskinfo + time_tick if (len_prefix) memcpy(p, prefix, len_prefix); // prefix »ðÀÔ. #if DHL_DBG_USE_MUTEX if (len_taskinfo) memcpy(p+len_prefix, taskinfo, len_taskinfo); // taskinfo »ðÀÔ. #endif if (len_timetick) memcpy(p+len_prefix+len_taskinfo, ticks, len_timetick); // time_tick »ðÀÔ. } while (1) { p = strchr(p, 0xA); // LF Äڵ带 ãÀ½. if (p == NULL) { break; } if (*++p == 0) { // ÀÌ LF°¡ ¸¶Áö¸· ¹®ÀÚ¶ó¸é ¿©±â¼­ Á¾·á. break; } #if DHL_DBG_USE_MUTEX if (bTaskName || bTaskPrio) { dhr = DHL_OS_GetTaskInfo(DHL_OS_GetTaskID(), &info); if (dhr != DHL_OK) snprintf(taskinfo, sizeof(taskinfo), "{? 0x%x} ", dhr); else if (bTaskName && bTaskPrio) snprintf(taskinfo, sizeof(taskinfo), "{%s,%2x} ", info.name, info.priority); else if (bTaskName) snprintf(taskinfo, sizeof(taskinfo), "{%s} ", info.name); else snprintf(taskinfo, sizeof(taskinfo), "{p%2x} ", info.priority); len_taskinfo = strlen(taskinfo); } else len_taskinfo = 0; #endif // DHL_DBG_USE_MUTEX if (bTime) { sprintf(ticks, "%04d ", timetick()); len_timetick = 5; } else len_timetick = 0; if (len_prefix + len_taskinfo + len_timetick > 0) memmove(p + len_prefix + len_taskinfo + len_timetick, p, strlen(p)+1); // °ø°£È®º¸. prefix + taskinfo + time_tick if (len_prefix) memcpy(p, prefix, len_prefix); // prefix »ðÀÔ. #if DHL_DBG_USE_MUTEX if (len_taskinfo) memcpy(p+len_prefix, taskinfo, len_taskinfo); // taskinfo »ðÀÔ. #endif if (len_timetick) memcpy(p+len_prefix+len_taskinfo, ticks, len_timetick); // time_tick »ðÀÔ. if (safty_limit++ > 10) { DHL_OS_Printf("!! Warning! too many LFs. skip remainings.\n"); break; } } p = buf; } // now print it! if (flags & DHL_DPF_FLUSH) { fprintf(1/*stderr*/, p); } else { DHL_OS_Printf(p); // in this case, message print may be deferred at arbitrary time. } if (flags & DHL_DPF_FLUSH) ; //dhl_dbg_flush_console(); if (p[strlen(p)-1] == 0xA) // ¸¶Áö¸· ±ÛÀÚ°¡ LF¶ó¸é Ä¿¼­´Â ÀÌÁ¦ ¸Ç óÀ½À¸·Î À̵¿ÇÞÀ½. s_bFirstColumn = TRUE; else s_bFirstColumn = FALSE; if (bSemTakenHere) // ÀÌ ÇÔ¼ö¿¡¼­ takeÇß´ø °æ¿ì¿¡¸¸ Sem release¸¦ ÇÑ´Ù. DHL_OS_GiveSemaphore(g_dhl_printSema4); return n; } int dhl_dbg_print(char *prefix, char *format, va_list ap) { return dhl_dbg_print_base(prefix, DHL_DPF_TIMETICK, format, ap); } #if COMMENT ____Level_Print____(){} #endif /* usage: DHL_DBG("this_module", 1); // eDBG_MODULE_LVL_Warn. means that Error(0) and Warn(1) level message is allowed to print. dprint(0, "this is error level..\n"); // this is Error level. printed. dprint(1, "this is warn level..\n"); // this is Warn level. printed. dprint(2, "this is info level..\n"); // this is Info level. NOT printed. if (dprintable(3)) // memdump msg is Verbose level. NOT printed. memdump(...); */ #define MAX_MODULE_NUM 128 static struct { char name[16]; int level; } p_module_level_table[MAX_MODULE_NUM]; static int p_module_level_idx; void DHL_DBG_SetModuleLevel(char *module_name, int level) { int i; if (!module_name) return; if (level < eDBG_MODULE_LVL_Silent) { DHL_OS_Printf("!! invalid dbg module level %d\n", level); return; } for(i=0; i=MAX_MODULE_NUM) return; strncpy(p_module_level_table[p_module_level_idx].name,module_name,15); p_module_level_table[p_module_level_idx].name[15] = 0; p_module_level_table[p_module_level_idx].level=level; p_module_level_idx++; DHL_OS_Printf("dbg module '%s' added, level %d. total %d modules\n", module_name, level, p_module_level_idx); } int DHL_DBG_GetModuleLevel(char *module_name) { int i; if (!module_name) return eDBG_MODULE_LVL_Unknown; for(i=0; i lvl %d, msg '%s' skipped\n", prefix, level, format); return 0; } dhr = DHL_OS_GetTaskInfo(DHL_OS_GetTaskID(), &tinfo); if (dhr) sprintf(prefix2, "[%s ?? 0x%x] ", prefix, dhr); else sprintf(prefix2, "[%s %d %s] ", prefix, tinfo.priority, tinfo.name); return dhl_dbg_print(prefix2, format, ap); } int DHL_DBG_KeyPrint(char *prefix, char *format, va_list ap) { DHL_OS_Printf("|%s| not implemented...\n", __FUNCTION__); return 0; } /* end of file */