/******************************************************************* * DMW_NvRam.c * * NvRam Access API * * Copyright 2003 Digital STREAM Technology, Inc. * All Rights Reserved * * $Id: DMW_NvRam.c,v 0.42 2004 cafrii Exp $ * ********************************************************************/ #include "DMW_Platform.h" #include "DHL_OSAL.h" #include "DHL_NVM.h" #include "DHL_DBG.h" #include "DMW_Config.h" #include "DMW_Status.h" #include "DMW_DebugUtil.h" #include "dmw_nvram_priv.h" #include "DMW_Mutex.h" #include "DMW_MsgQue.h" //#include DHL_MODULE("$nvm", 0); #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) /*-------------------------------------------------------------- Configuration.. */ #define DMW_USE_MINIMIZE_FLASH_WRITE 1 /* neverdai add. 080930 ÀÌ ¸ðµå°¡ 1·Î ¼³Á¤µÇ¸é counting ¶§¹®¿¡ ºÒÇÊ¿äÇÏ°Ô flash°¡ Áö¿öÁö´Â °æ¿ì¸¦ ÃÖ´ëÇÑ ÁÙÀδÙ. cafrii 100708, ÀÌ ¸ðµå¸¦ µðÆúÆ®·Î Àû¿ëÇϵµ·Ï ÇÔ. */ #define DMW_SIZE_COUNTING_BUF 8 #define DMW_MAX_COUNTING_NUM (DMW_SIZE_COUNTING_BUF*8) /*8yte¸¦ Ãß°¡·Î counting¿¡ »ç¿ëÇÑ´Ù. µû¶ó¼­ Ç¥Çö °¡´ÉÇÑ ¼ýÀÚ´Â 8*8=64+1(65)°³°¡ µÈ´Ù.*/ /*------------------------------------------ HAL layer EEPROM / FlashRam / etc. */ enum NVRAM_DEVICE_LOCK_ENUM { NVRAM_DEVICE_LOCK_EEPROM = 0, NVRAM_DEVICE_LOCK_FLASH = 1, NVRAM_DEVICE_LOCK_FLASHBUF = 2, /* cafrii 040113 added to increase performance, we make separate lock for flash shadow buffer*/ }; #define NUM_NVRAM_DEVICE_LOCK 3 /* ÁÖÀÇ! ÀÌ °ªÀ» º¯°æÇϸé nvramMutex ÀÇ ÃʱⰪµµ ²À Ãß°¡ÇØ ÁÖµµ·Ï ÇÏÀÚ.*/ #define USE_EEPROM_INIT_AT_DMW 1 /* EEPROM device init in MW level. it is for test debugging. Actually, eeprom driver initializes when first read() or write() function are called. so, this additional init at DMW level is not required. */ #if COMMENT ____NvRamMutex________(){} #endif static DMW_MUTEX nvramMutex[NUM_NVRAM_DEVICE_LOCK] = { /* { SemID, Owner, lockCnt, FailCnt, UseOsMutex, Name, flag, traceLvl } */ { 0, 0, 0, 0, TRUE, "NvMtx1", OS_SEM_PRIO, FALSE, }, { 0, 0, 0, 0, TRUE, "NvMtx2", OS_SEM_PRIO, FALSE, }, { 0, 0, 0, 0, TRUE, "NvMtx3", OS_SEM_PRIO, FALSE, }, }; void lock_nvram_sema4(int deviceid) { if (deviceid < 0 || deviceid >= NUM_NVRAM_DEVICE_LOCK) { dprint(0, "!! lock_nvram_sema4: invalid NvRam device ID %d\n", deviceid); return; } DMW_LockMutex(&nvramMutex[deviceid]); } void unlock_nvram_sema4(int deviceid) { if (deviceid < 0 || deviceid >= NUM_NVRAM_DEVICE_LOCK) { dprint(0, "!! lock_nvram_sema4: invalid NvRam device ID %d\n", deviceid); return; } DMW_UnlockMutex(&nvramMutex[deviceid]); } /* ÁÖ¼Ò ¿µ¿ª 0x00000000 ~ 0x7fffffff : eeprom 0x80000000 ~ 0xffffffff : flash memory nvram ¿µ¿ª. */ /* eeprom °ü·Ã ÄÚµå´Â ³ªÁß¿¡ ´Ù½Ã Á¤¸® ÇÊ¿äÇÔ. ¹Ýµå½Ã SUPPORT_DMW_EEPROM Ç÷¡±×¿Í °°ÀÌ Á¶°ÇºÎ ºôµå°¡ µÇµµ·Ï ÇÏÀÚ. */ #if COMMENT ___Flash_Util_________(){} #endif /* count °ª¿¡ µû¸¥ bit map ¿¹½Ã: 0: ff ff ff ff ff ff ff ff 1: 7f ff ff ff ff ff ff ff 2: 3f ff ff ff ff ff ff ff 3: 1f ff ff ff ff ff ff ff 4: 0f ff ff ff ff ff ff ff 5: 07 ff ff ff ff ff ff ff .. 8: 00 ff ff ff ff ff ff ff 9: 00 7f ff ff ff ff ff ff .. 63: 00 00 00 00 00 00 00 01 64: 00 00 00 00 00 00 00 00 ½ÇÁ¦·Î´Â 0 °ú 64´Â Á¤»óÀûÀÎ °ªÀ¸·Î Ãë±ÞÇÏÁö ¾Ê´Â´Ù. (Ưº°ÇÑ Àǹ̷Π»ç¿ë) 1 ~ 63 »çÀÌÀÇ °ªÀÌ Á¤»óÀûÀÎ °ªÀÌ´Ù. */ static void p_set_flash_counting(int count, UINT8 *buf) { int i; int bufIdx; int bufOfs; count%=DMW_SIZE_COUNTING_BUF*8; bufIdx=count/8; bufOfs=count%8; for(i=0; i> bufOfs); // º¸±â ÁÁ°Ô MSB ºÎÅÍ clear ÇØ °¡ÀÚ. for(i=bufIdx+1; i>(i%8))) break; } /*neverdai comment*/ /*¸®ÅÏÀº 0ºÎÅÍ 64±îÁöÀÇ °ªÀ» °®°Ô µÇÁö¸¸ ½ÇÁ¦·Î 0À̳ª 64°ªÀÌ ¸®ÅϵǸé IsValidCount()¿¡¼­ À߸øµÈ °ªÀ¸·Î °£ÁֵDZ⠶§¹®¿¡ ÀÌ ÇÔ¼ö¿¡¼­ Ưº°ÇÑ ¿¡·¯ 󸮸¦ ÇÒ Çʿ䰡 ¾øÀ½*/ return i; } #if COMMENT ____Wrappter___________(){} #endif /* DHL Wrappter ÀÌ´Ù. debug message ó¸® ¸¸ Ãß°¡µÈ °ÍÀÓ. */ #define DMW_NVM_FLASH_ID 0 /* DHL¿¡¼­´Â ¿©·¯°³ÀÇ flash¸¦ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï id¸¦ ÁöÁ¤ÇÒ ¼ö ÀÖ°Ô µÇ¾î ÀÖÀ¸³ª, DMW¿¡¼­´Â ÇϳªÀÇ flash ÀåÄ¡¸¸ Áö¿øÇÑ´Ù. */ void halFlashInit(UINT32 *pAddr1, UINT32 *pAddr2, UINT32 *pSize) { *pSize = DHL_NVM_FlashNvmBlockSize(); *pAddr1 = DHL_NVM_FlashNvmBlockAddr(0); *pAddr2 = DHL_NVM_FlashNvmBlockAddr(1); } STATUS halFlashRead(UINT32 addr, UINT32 size, UINT8 *buf) { DHL_RESULT dhlResult = DHL_OK; if (buf == NULL) return statusInvalidArgument; dhlResult = DHL_NVM_FlashRead(DMW_NVM_FLASH_ID, addr, buf, size); if (dhlResult) { dprint(0, "!! %s(%x, %d, %x): ReadFlash return %d\n", __func__, addr, size, buf, dhlResult); return statusFlashError; } return statusOK; } /* Âü°í: DHLÀÇ flash write´Â ÇÊ¿äÇϸé ÀÚµ¿À¸·Î eraseÇÏ´Â ±â´ÉÀÌ Æ÷ÇԵǾî ÀÖ´Ù. */ STATUS halFlashWrite(UINT32 addr, UINT32 size, UINT8 *buf) { DHL_RESULT dhlResult = DHL_OK; if (buf == NULL) return statusInvalidArgument; dhlResult = DHL_NVM_FlashWrite(DMW_NVM_FLASH_ID, addr, buf, size); if (dhlResult) { dprint(0, "!! %s(%x, %d, %x): ProgramFlash return %d\n", __func__, addr, size, buf, dhlResult); return statusFlashError; } return statusOK; } void halFlashSync(void) { DHL_NVM_FlashSync(DMW_NVM_FLASH_ID); } #if COMMENT ____Flash_1___________(){} #endif /* Nor Flash Support Routines*/ /* Example: Spansion compatible Flash memory map bottom type device, uniform boot block size total 4M Byte ÀÌ flashÀÇ Æ¯Â¡: 1 block size = 64 K byte (can be different by vendor) 8 bit wide 400000 +------------------------------+ | Block number 70 | 64 KByte | | 3F0000 +------------------------------+ | Block number 69 | | | 3E0000 +------------------------------+ | | | ... | 020000 +------------------------------+ | Block number 8 | 64 KByte | | 010000 +==============================+ ÀÌÇÏ ¾Æ·¡ block ¸î°³´Â ÀÛÀº Å©±â·Î µÇ¾î ÀÖÀ½ | Block number 7 | 00E000 +------------------------------+ | ... | 004000 +------------------------------+ | Block number 1 | 002000 +------------------------------+ | Block number 0 | 8 KByte 000000 +------------------------------+ À§ ºí·°Áß¿¡¼­ firmware ¿ëÀ¸·Î »ç¿ëÇÏÁö ¾Ê´Â µÎ°³ ºí·°À» NvRam device 1À¸·Î ¼±ÅÃÇØ¼­ »ç¿ë. */ /*---------------------------------------*/ /* Flash User parameters..*/ typedef struct { UINT32 start_addr; /* ÀÌ UserblockÀÇ ½ÃÀÛ ÁÖ¼Ò.. Ç÷¡½Ã ¸Þ¸ð¸® Àüü ºí·° Áß¿¡¼­ NvRam ÀúÀå °ø°£ ¿ëµµ·Î »ç¿ëÇÒ block address.*/ UINT32 end_addr; /* ÀÌ ÁÖ¼Ò´Â ³Ñ¾î°¡¸é ¾ÈµÊ*/ } FlashUserBlockInfo; FlashUserBlockInfo g_flashUserBlockInfo[2]; /*----------------------------------------------------------------------------------*/ #if COMMENT ____Flash_2___________(){} #endif /******************************************************************* BlockÀÇ ¸Ç óÀ½ 32 byte´Â ID record·Î¼­ NvRam I/O API·Î´Â Á¢±Ù ºÒ°¡. ¿ÀÁ÷ halFlashXX ·çƾÀ¸·Î update°¡´ÉÇϸç, count Á¤º¸¸¦ ºñ·ÔÇÑ Áß¿äÇÑ µ¥ÀÌÅͰ¡ ±â·ÏµÈ´Ù. ID record (offset 0, 32 bytes) 0 1 2 3 4 5 6 7 8 9 A B C D E F +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 0x0000 |Magic|vr|ff| count | reserved | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 0x0010 | reserved | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | | ... | Magic : fixed. 0xCA, 0xFE vr : version. Count : flash revision count *******************************************************************/ #define FLASH_SYSTEM_VERSION 0x03 /* flash layout ¹öÀü Á¤º¸. ±¸Á¶°¡ º¯°æµÇ¸é ÀÌ °ªµµ Áõ°¡µÇ¾î¾ß ÇÔ. 8 bit ¹üÀ§ ³»¿¡¼­ Á¤ÀǵǾî¾ß ÇÔ. 0 ~ 0xff 0x03: 2010/7/8, for newby, »õ·Î¿î µðÀÚÀÎ. »ç½Ç layoutÀº º¯°æ ¾øÀ½. 0x02: 32-bit count value is used. bit-wise operation. 0x01: Ãʱâ layout. */ #define SIZE_OF_ID_RECORD 32 /* block ¸Ç ¾Õ¿¡ ID·Î »ç¿ëµÇ´Â ¿¹¾àµÈ ¿µ¿ª Å©±â*/ #define FLASH_RESERVED_SIZE SIZE_OF_ID_RECORD int FLASH_USER_AREA_SIZE; /* ½ÇÁ¦·Î user°¡ »ç¿ëÇÒ ¼ö ÀÖ´Â flash blockÀÇ Å©±â´Â ¿¹¾àµÈ ¿µ¿ªÀ» Á¦¿ÜÇÑ Å©±âÀÌ´Ù.*/ UINT8 g_NvFlashMagic[4] = { 0xca, 0xfe, FLASH_SYSTEM_VERSION, 0xff}; #define IsValidMagic(a) \ (((a)[0]==g_NvFlashMagic[0]) && ((a)[1]==g_NvFlashMagic[1]) && ((a)[2]==g_NvFlashMagic[2])) #define IsValidCount(c) (((c) >= 1) && ((c) <= DMW_MAX_COUNTING_NUM-1)) /* count °ªÀÌ À¯È¿ÇÑ ¹üÀ§ ÀÎÁö üũ. */ #define InitialCount() 0 /* nvm format ÇÒ ¶§ÀÇ count °ª */ #define StartCount() 1 /* resetÈÄ ÃÖÃÊ count °ª. 1ºÎÅÍ ½ÃÀÛÇØ¾ß flash erase¸¦ ÃÖ¼ÒÈ­ ÇÒ ¼ö ÀÖÀ½ */ #define NextCount(c) (((c) >= DMW_MAX_COUNTING_NUM-1) ? 1 : (c)+1) /* neverdai 080930 »ç¿ë °¡´ÉÇÑ °ªÀº 1¿¡¼­ºÎÅÍ DMW_MAX_COUNTING_NUM-1ÀÌ´Ù. 0xff...³ª 0x00...À» »ç¿ëÇÏ´Â °ÍÀÌ ÀûÀýÄ¡ ¾Ê´Ù°í Çϸé 0°ú DMW_MAX_COUNTING_NUM°ªÀº »ç¿ëÇÒ ¼ö ¾øÀ¸¸ç µû¶ó¼­ ½ÇÁ¦ »ç¿ë °¡´ÉÇÑ count °ªÀº 1¿¡¼­ºÎÅÍ DMW_MAX_COUNTING_NUM-1ÀÌ µÈ´Ù.*/ UINT8 *g_NvFlashBuffer; /* shadow buffer g_NvFlashBufferValid°¡ TRUEÀÎ °æ¿ì¿¡¸¸ À¯È¿ÇÏ´Ù. ¾ÕÀÇ ID_RECORD ºÎºÐ ¸¸Å­Àº ÀÌ ¹öÆÛ¿¡ Æ÷ÇÔµÇÁö ¾Ê´Â´Ù. */ BOOL g_NvFlashBufferValid = FALSE; /* TRUEÀÏ ¶§¿¡¸¸ g_NvFlashBufferÀÇ ³»¿ëÀÌ Àǹ̰¡ ÀÖ´Ù. */ BOOL g_NvFlashForceCacheDirty; /* cafrii 070402 add TRUE À̸é Ç×»ó cache°¡ dirty ÇÏ´Ù°í °¡Á¤.. Å×½ºÆ® ¿ëµµ..*/ #define NVM_VERIFY_BUF_SZ 8192 UINT8 *g_NvVerifyBuffer; /* verify¿ë ¹öÆÛ°¡ ³Ê¹« À۾Ƽ­ HAL api°¡ ³Ê¹« ºó¹øÈ÷ ½ÇÇà.. µð¹ö±ë ½Ã¿¡ ºÒÆíÇϹǷÎ, Å©±â¸¦ Ű¿î´Ù. FlashSync ¿¡¼­¸¸ »ç¿ëÇϴµ¥, ÀÌ ÀÛ¾÷Àº NwtTask¿¡¼­¸¸ ½ÇÇàµÇ¹Ç·Î, race condition °ÆÁ¤Àº ÇÏÁö ¾Ê¾Æµµ µÈ´Ù. */ /*---------------------------------------------------------------------------- FlashNvmInit Flash¸¦ NVMÀ¸·Î »ç¿ëÇϱâ À§ÇÑ ÃʱâÈ­ ÀÛ¾÷À» ÇÑ´Ù. */ void FlashNvmInit(void) { UINT32 addr1, addr2, size; halFlashInit(&addr1, &addr2, &size); DHL_ASSERT(addr1!=addr2, "flash nvm block addr invalid!"); g_flashUserBlockInfo[0].start_addr = addr1; g_flashUserBlockInfo[0].end_addr = addr1 + size; g_flashUserBlockInfo[1].start_addr = addr2; g_flashUserBlockInfo[1].end_addr = addr2 + size; dprint(0, "FlashNvmInfo: blksz 0x%x-0x%x, addr[0] 0x%x, addr[1] 0x%x\n", size, FLASH_RESERVED_SIZE, g_flashUserBlockInfo[0].start_addr, g_flashUserBlockInfo[1].start_addr); FLASH_USER_AREA_SIZE = size - FLASH_RESERVED_SIZE; if (g_NvFlashBuffer == NULL) g_NvFlashBuffer = DHL_OS_Malloc(FLASH_USER_AREA_SIZE); if (g_NvVerifyBuffer == NULL) g_NvVerifyBuffer = DHL_OS_Malloc(NVM_VERIFY_BUF_SZ); DHL_ASSERT(g_NvFlashBuffer!=NULL, "flash nvm shadow buffer null"); DHL_ASSERT(g_NvVerifyBuffer!=NULL, "flash nvm verify buffer null"); /* flash buffer¸¦ 0ÀÌ ¾Æ´Ñ 0xff ·Î ÃʱâÈ­ ÇØ ³õÀ¸¸é sync ¼Óµµ°¡ Á¶±Ý ´õ »¡¶óÁú ¼ö ÀÖ´Ù. (ÀÌ·ÐÀûÀ¸·Î..) */ memset(g_NvFlashBuffer, 0xff, FLASH_USER_AREA_SIZE); /* ÀÌ shadow buffer´Â Çѹø ÇÒ´çµÇ°í free µÇÁö ¾Ê´Â´Ù.*/ } /*---------------------------------------------------------------------------- FlashNvmGetAvailableSize »ç¿ëÀÚ°¡ »ç¿ë °¡´ÉÇÑ flash ¿µ¿ªÀÇ Å©±â ¸®ÅÏ. (¹ÙÀÌÆ® ´ÜÀ§) */ int FlashNvmGetAvailableSize() { return FLASH_USER_AREA_SIZE; } /*---------------------------------------------------------------------------- FlashInvalidFlashCache Å×½ºÆ® ¿ëµµ.. DRAM¿¡ ÀÖ´Â Buffer Cache¸¦ invalidate ½ÃŲ´Ù. Flash read/write stress test¸¦ ÇÒ ¶§ ±â·ÏÇÑ ´ÙÀ½¿¡ buffer¸¦ ÅëÇÏÁö ¾Ê°í ¹Ù·Î Àбâ À§Çؼ­ »ç¿ëÇÑ´Ù. */ void FlashNvmInvalidateCacheBuffer() { g_NvFlashBufferValid = FALSE; } /*---------------------------------------------------------------------------- _FlashSelectValidBlock µÎ°³ÀÇ block Áß¿¡¼­ ¾î¶² °ÍÀÌ °¡Àå validÇÑ °ÍÀÎÁö °áÁ¤ÇÏ´Â ÇÔ¼ö. pCount´Â validÇÑ block¿¡ ±â·ÏµÇ¾î ÀÖ´Â counter °ªÀ¸·Î ÀÌ °ªÀÌ ÇöÀç counter°¡ µÈ´Ù. valid ÇÑ blockÀ» ¸®ÅÏÇÑ´Ù. (0 ¶Ç´Â 1) validÇÑ °ÍÀÌ Çϳªµµ ¾ø´Ù¸é -1À» ¸®ÅÏÇÑ´Ù. */ int _FlashSelectValidBlock(UINT8 *pCount) { /* return block number (0 or 1) if any block is valid.*/ /* return -1 if both block is invalid..*/ UINT8 buf0[4+DMW_SIZE_COUNTING_BUF], buf1[4+DMW_SIZE_COUNTING_BUF]; int r0, r1; UINT8 cnt0, cnt1; /* counter value to be compared..*/ int lvl; /* debug level */ dprint(2, "select valid flash block:\n"); r0 = halFlashRead(g_flashUserBlockInfo[0].start_addr, 4+DMW_SIZE_COUNTING_BUF, buf0); r1 = halFlashRead(g_flashUserBlockInfo[1].start_addr, 4+DMW_SIZE_COUNTING_BUF, buf1); buf0[3] = p_get_flash_counting(&buf0[4]); buf1[3] = p_get_flash_counting(&buf1[4]); /* comment: bufn[3] is temporary space. it is not saved in flash..*/ if (r0 == 0 && IsValidMagic(buf0) && /* check magic key*/ IsValidCount(buf0[3])) /* check counter*/ cnt0 = buf0[3]; else { lvl = buf0[3] ? 2 : 0; // cnt==0 ´Â format¿¡ ÀÇÇÑ ÃʱⰪÀ̹ǷΠ¿¡·¯ »óȲÀÌ ¾Æ´Ô. dprint(lvl, "%s Block 0 not valid! r %d, magic %02x%02x%02x, cnt %d\n", !lvl ? "!!" : " ", r0, buf0[0], buf0[1], buf0[2], buf0[3]); cnt0 = 0; /* meaning "INVALID!!"*/ } if (r1 == 0 && IsValidMagic(buf1) && /* check magic key*/ IsValidCount(buf1[3])) /* check counter*/ cnt1 = buf1[3]; else { lvl = buf0[3] ? 2 : 0; // cnt==0 ´Â format¿¡ ÀÇÇÑ ÃʱⰪÀ̹ǷΠ¿¡·¯ »óȲÀÌ ¾Æ´Ô. dprint(lvl, "%s Block 1 not valid! r %d, magic %02x%02x%02x, cnt %d\n", !lvl ? "!!" : " ", r1, buf1[0], buf1[1], buf1[2], buf1[3]); cnt1 = 0; /* meaning "INVALID!!"*/ } if (cnt0 == 0 && cnt1 == 0) { /* both block is invalid!!*/ dprint(2, " no valid block!\n"); return -1; } if (cnt0 && cnt1 == 0) { /* only block 0 is valid.*/ dprint(2, "== only block 0 valid, magic %02x%02x%02x, cnt %d\n", buf0[0], buf0[1], buf0[2], cnt0); if (pCount) *pCount = cnt0; return 0; } if (cnt0 == 0 && cnt1) { /* only block 1 is valid.*/ dprint(2, "== only block 1 valid, magic %02x%02x%02x, cnt %d\n", buf1[0], buf1[1], buf1[2], cnt1); if (pCount) *pCount = cnt1; return 1; } /* both blocks are valid. compare and choose newest one.. (big value) this count value is wrapping if reached at end. so just numerical order is not important. */ dprint(2, "== block 0/1 both valid.. cnt %d/%d\n", cnt0, cnt1); dprint(2, " block 0 magic %02x%02x%02x, cnt %d\n", buf0[0], buf0[1], buf0[2], cnt0); dprint(2, " block 1 magic %02x%02x%02x, cnt %d\n", buf1[0], buf1[1], buf1[2], cnt1); if (cnt0 < cnt1) { if (cnt1 - cnt0 < DMW_MAX_COUNTING_NUM/2) { /* +-----------------------------------+ 0 cnt0 cnt1 ff*/ if (cnt1 - cnt0 > 1) dprint(0, "!! warning! cnt0 %d < cnt1 %d not adjacent! use block 1\n", cnt0, cnt1); if (pCount) *pCount = cnt1; return 1; } else { /* count 1ÀÌ ¼ýÀÚ»óÀ¸·Î´Â ´õ Å« °ªÀÌÁö¸¸ count 0°¡ ´õ ÃÖ½ÅÀÌ´Ù.*/ /*+-----------------------------------+ 0 cnt0 cnt1 ff*/ if (cnt0 != 1 || cnt1 != DMW_MAX_COUNTING_NUM-1) dprint(0, "!! warning! cnt0 %d, cnt1 %d not adjacent! use block 0\n", cnt0, cnt1); if (pCount) *pCount = cnt0; return 0; } } else /* cnt1 <= cnt0*/ { if (cnt0 - cnt1 < DMW_MAX_COUNTING_NUM/2) { /* +-----------------------------------+*/ /* 0 cnt1 cnt0 ff*/ if (cnt0 - cnt1 > 1) dprint(0, "!! warning! cnt1 %d < cnt0 %d not adjacent! use block 1\n", cnt1, cnt0); if (pCount) *pCount = cnt0; return 0; } else { /* count 0ÀÌ ¼ýÀÚ»óÀ¸·Î´Â ´õ Å« °ªÀÌÁö¸¸ count 1°¡ ´õ ÃÖ½ÅÀÌ´Ù.*/ /* +-----------------------------------+*/ /* 0 cnt1 cnt0 ff*/ if (cnt1 != 1 || cnt0 != DMW_MAX_COUNTING_NUM-1) dprint(0, "!! warning! cnt1 %d, cnt0 %d not adjacent! use block 0\n", cnt1, cnt0); if (pCount) *pCount = cnt1; return 1; } } } /***************************************************************************** _FlashReadSync Flash Read³ª Write¸¦ ÇÒ¶§ Shadow buffer ³»¿ëÀÌ ¾ÆÁ÷ invalidÇÏ¸é ¸ÕÀú flash device·ÎºÎÅÍ buffer·Î Àоî¿Í¼­ sync¸¦ ÇÑ´Ù. caller¿¡¼­ ÀÌ¹Ì shadow buffer lockÀº µÈ »óÅÂÀ̹ǷΠÀÌ ÇÔ¼ö¿¡¼­´Â flash lock¸¸ ÇÑ´Ù. *****************************************************************************/ STATUS _FlashReadSync() { int r, idx; UINT32 base; UINT8 count; lock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASH); /* flash memory*/ if (! g_NvFlashBufferValid) { /* synchronize!*/ /*dprint(2, "%s: flash shadow buffer not synchronized.. do sync now..\n", __FUNCTION__);*/ idx = _FlashSelectValidBlock(&count); if (idx != 0 && idx != 1) { /* ¾ÆÁ÷ flash ICÀÇ ³»¿ëÀÌ ÀüÇô ÃʱâÈ­°¡ µÇÁö ¾Ê¾Ò°Å³ª ¼Õ»óµÇ¾úÀ¸¹Ç·Î formatÀÌ ÇÊ¿äÇÑ °æ¿ìÀÌ´Ù.*/ dprint(0, "!! %s: both block invalid.. unformatted flash block !!!!\n", __FUNCTION__); /*memset(g_NvFlashBuffer, 0, sizeof(g_NvFlashBuffer));*/ r = statusNvRamNotFormatted; goto end_of_flash_read_sync; } /* idx is block number [0/1].. load flash content to shadow buffer. */ base = g_flashUserBlockInfo[idx].start_addr; dprint(2, " %s: block %d (%x), count 0x%x\n", __FUNCTION__, idx, base, count); r = halFlashRead(base + FLASH_RESERVED_SIZE, FLASH_USER_AREA_SIZE, g_NvFlashBuffer); if (r) { dprint(0, "!! %s: read error %d\n", __FUNCTION__, r); goto end_of_flash_read_sync; } g_NvFlashBufferValid = TRUE; } r = statusOK; end_of_flash_read_sync: unlock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASH); /*flash memory*/ return (STATUS)r; } /***************************************************************************** FlashNvmRead Flash Block ¿¡¼­ µ¥ÀÌÅÍ Àбâ. »ó´ë ÁÖ¼Ò »ç¿ë.. addr·Î »ç¿ë°¡´ÉÇÑ °ªÀÇ ¹üÀ§: 0 ~ FLASH_USER_AREA_SIZE-1 *****************************************************************************/ STATUS FlashNvmRead(UINT32 addr, UINT32 size, UINT8 *buf) { int r; lock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASHBUF); /* flash shadow buffer*/ /* flash shadow buffer integrity check*/ if (! g_NvFlashBufferValid) { /* synchronize!*/ dprint(2, "%s: flash shadow buffer not synchronized.. do sync now..\n", __FUNCTION__); r = _FlashReadSync(); if (r) goto end_of_flash_read; } /* range check*/ if (addr >= (UINT32)FLASH_USER_AREA_SIZE || size >= (UINT32)FLASH_USER_AREA_SIZE || addr + size >= (UINT32)FLASH_USER_AREA_SIZE) { dprint(0, "!! %s: limit over.. addr %u, size %u, end %u\n", __FUNCTION__, addr, size, addr+size); r = statusOutOfRange; goto end_of_flash_read; } /* actual read here! */ memcpy(buf, g_NvFlashBuffer + addr, size); r = statusOK; end_of_flash_read: unlock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASHBUF); /* flash shadow buffer*/ return (STATUS)r; } /***************************************************************************** FlashNvmWrite Flash Target Block¿¡ ±â·ÏÇϱâ. addr´Â Target Block¿¡ ´ëÇÑ »ó´ë ÁÖ¼Ò. 0 ~ FLASH_USER_AREA_SIZE-1 target blockÀº FlashOpenWrite()¿¡¼­ °áÁ¤µÈ´Ù. (ÀÌ ÇÔ¼ö¸¦ ºÎ¸£±â Àü¿¡ ²À ºÒ·¯¾ß ÇÔ) ÀÌ ÇÔ¼ö°¡ ºÒ¸®´Â ½ÃÁ¡¿¡¼­´Â ±âÁ¸ µ¥ÀÌÅÍ´Â ÀÌ¹Ì Áö¿öÁ®¼­ Á¸ÀçÇÏÁö ¾Ê´Â´Ù. ÇöÀç bufferred write ¹æ½ÄÀ̹ǷΠÀÌ ÇÔ¼ö¿¡¼­ ½ÇÁ¦·Î flash writingÀº ÇÏÁö ¾Ê´Â´Ù. *****************************************************************************/ STATUS FlashNvmWrite(UINT32 addr, UINT32 size, UINT8 *buf) { int r; lock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASHBUF); /* flash shadow buffer*/ /* flash shadow buffer integrity check*/ if (! g_NvFlashBufferValid) { /* synchronize!*/ dprint(2, "%s: flash shadow buffer not valid.. do sync now..\n", __FUNCTION__); r = _FlashReadSync(); if (r) goto end_of_flash_write; } if (addr >= (UINT32)FLASH_USER_AREA_SIZE || size >= (UINT32)FLASH_USER_AREA_SIZE || addr + size >= (UINT32)FLASH_USER_AREA_SIZE) { dprint(0, "!! %s: limit over.. addr %u, size %u, end %u\n", __FUNCTION__, addr, size, addr+size); r = statusOutOfRange; goto end_of_flash_write; } memcpy(g_NvFlashBuffer + addr, buf, size); r = statusOK; end_of_flash_write: unlock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASHBUF); /* flash shadow buffer*/ return (STATUS)r; } /***************************************************************************** FlashNvmSync Flash shadow bufferÀÇ ³»¿ë°ú flash ½ÇÁ¦ ³»¿ë°ú µ¿±âÈ­ÇÏ´Â ÇÔ¼ö pPartMapList´Â flash buffer ³»¿ë Áß¿¡¼­ ½ÇÁ¦·Î validÇÑ µ¥ÀÌÅͰ¡ Á¸ÀçÇÏ´Â ¿µ¿ªµéÀ» ¾Ë·ÁÁÖ´Â MapÀ¸·Î¼­ "¿µ¿ª" µéÀÇ array ·Î µÇ¾î ÀÖ´Ù. NULLÀ» ÁöÁ¤Çϸé Àüü ¿µ¿ªÀ» updateÇÑ´Ù. 2010/7/8, part map list´Â ´õ ÀÌ»ó »ç¿ëÇÏÁö ¾ÊÀ¸¹Ç·Î ÄÚµå Á¦°Å. *****************************************************************************/ STATUS FlashNvmSync(PartMapRange *pPartMapList) { #undef TMPBLKSZ #define TMPBLKSZ NVM_VERIFY_BUF_SZ STATUS r; int k, n, target; UINT8 count; /* flash count °ª */ UINT8 *source; UINT32 base; int size; UINT8 *tmp = g_NvVerifyBuffer; /* ±â·ÏÇÑ ´ÙÀ½¿¡ Á¦´ë·Î ±â·ÏµÇ¾ú´ÂÁö üũÇÒ¶§ »ç¿ëµÇ´Â Àӽà ¹öÆÛ*/ int this_size, offset; UINT8 header[4+DMW_SIZE_COUNTING_BUF]; // flash ¿µ¿ª Çì´õ Á¤º¸ UINT8 *pFlashShadowBuffer = NULL; // ±â·Ï ÀÛ¾÷ ¼öÇà½Ã »ç¿ëÇÏ´Â ¿øº» ¹öÆÛ º¹»çº». dprint(2, "%s\n", __FUNCTION__); if (! g_NvFlashBufferValid) { dprint(0, "!! flash shadow buffer invalid! skip!\n"); /* Çѹøµµ Read/Write¸¦ ÇÏÁö ¾ÊÀº »óÅ¿¡¼­ Sync¸¦ callÇÑ »óȲ.*/ /* ½ÇÁ¦·Î synchronize¸¦ ÇÒ data°¡ ¾øÀ¸¹Ç·Î success/fail µÑ ´Ù ÀÇ¹Ì ¾øÀ½..*/ return statusNotInitialized; } /*--------------------------------------------- Flash shadow buffer g_NvFlashBuffer µ¥ÀÌÅ͸¦ ½ÇÁ¦ Flash memory ¿¡ ±â·ÏÇÑ´Ù. shadow buffer¸¦ lockÇÏ´Â ½Ã°£À» ÃÖ¼ÒÈ­ Çϱâ À§ÇØ shadow buffer Àüü¸¦ º¹»çÇØ ³õ°í ½ÃÀÛÇÏÀÚ. definition: UINT8 g_NvFlashBuffer[FLASH_USER_AREA_SIZE];*/ pFlashShadowBuffer = (UINT8 *) DHL_OS_Malloc(sizeof(UINT8)*FLASH_USER_AREA_SIZE); if (pFlashShadowBuffer == NULL) { dprint(0, "!! flash shadow buffer duplicate err\n"); return statusOutOfMemory; } /* ÀÌÁ¦ ÀÌÈÄ ºÎÅÍ´Â ÇÔ¼ö returnÇÒ ¶§ ¸Þ¸ð¸®¸¦ ²À Free¸¦ ½ÃÄÑ¾ß ÇÔ.*/ /* duplicate with lock */ lock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASHBUF); memcpy(pFlashShadowBuffer, g_NvFlashBuffer, sizeof(UINT8)*FLASH_USER_AREA_SIZE); unlock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASHBUF); /* FlashRead/Write ¿¡¼­´Â FlashBuf¸¦ ¸ÕÀú lock ÇÑ ´ÙÀ½¿¡ Flash¸¦ lock Çϰí ÀÖ´Ù. µû¶ó¼­ FlashBuf mutex¿Í Flash mutex´Â ¼­·Î DeadLockÀÌ µÉ °¡´É¼ºÀÌ Àֱ⠶§¹®¿¡ °¡´ÉÇÏ¸é ¼­·Î ÁßÃ¸ÇØ¼­ mutex lockÀ» ÇÏÁö ¸»µµ·Ï ÇÏÀÚ. ---------------------------------------------*/ lock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASH); /* Flash shadow buffer g_NvFlashBuffer µ¥ÀÌÅ͸¦ Flash¿¡ ±â·ÏÇϱâ Àü¿¡ ½ÇÁ¦ Flash memory ³»¿ë°ú Â÷À̰¡ ÀÖ´ÂÁö üũÇÑ´Ù. ½ÇÁ¦ ³»¿ë°ú Â÷À̰¡ ¾ø´Ù¸é ±»ÀÌ ´Ù½Ã ±â·ÏÇÒ Çʿ䰡 ¾ø±â ¶§¹®. */ n = _FlashSelectValidBlock(&count); /* nÀº valid ÇÑ block ¹øÈ£. 0 or 1*/ if (n != 0 && n != 1) { /* no valid block!! compare check¸¦ ÇÒ Çʿ䰡 ¾ø´Ù. µÑ ´Ù invalid À̹ǷΠtargetÀ¸·Î´Â ¾Æ¹«°Å³ª °í¸£¸é µÈ´Ù. 0 default*/ target = 0; count = StartCount(); } else { target = (n == 0) ? 1 : 0; /* write targetÀº invalid block ¶Ç´Â µÑ Áß¿¡¼­ ¿À·¡µÈ blockÀ¸·Î Á¤ÇÑ´Ù. valid blockÀÌ 0À̸é 1À» »èÁ¦Çϰí 1ÀÌ validÇϸé 0À» »èÁ¦ÇÑ´Ù.*/ base = g_flashUserBlockInfo[n].start_addr + FLASH_RESERVED_SIZE; /* ¾ÕºÎºÐ ¿¹¾à ¿µ¿ªÀº Á¦¿ÜÇÑ´Ù.*/ size = FLASH_USER_AREA_SIZE; /* Àüü Å©±â.*/ source = pFlashShadowBuffer; /* ºñ±³ÇÒ µ¥ÀÌÅÍ Æ÷ÀÎÅÍ..*/ /*dprint(2, " compare before start synching..\n");*/ if (g_NvFlashForceCacheDirty) { dprint(0, "!! force cache dirty flag..\n"); goto start_flash_sync; } // *, /, % ¿¬»êÀÚ »ç¿ëÀ» ÃÖ¼ÒÈ­ Çϵµ·Ï ·ÎÁ÷ °³¼±. for (k=0; k= 0) { dprint(2, "!! mismatch found, offset [%u], buf %u != flash %u\n", k*TMPBLKSZ+offset, source[k*TMPBLKSZ+offset], tmp[offset]); goto start_flash_sync; } #else /* ¾îµð°¡ ¾î¶»°Ô mismatch µÇ´ÂÁö ¾Ë Çʿ䰡 ¾ø´Â °æ¿ì¿¡´Â ±×³É memcmp¸¦ */ /* »ç¿ëÇØ¼­ ½ÇÇà ¼Óµµ¸¦ ³ôÀÌÀÚ.*/ if (memcmp(&source[k], tmp, this_size)) { dprint(2, " flash cache dirty. sync now.. target %d\n", target); goto start_flash_sync; } #endif } dprint(2, " flash cache consistent. no need to sync\n"); r = statusOK; goto end_of_flash_sync; } start_flash_sync: /*--------------------------------------------- ÀÌÁ¦ ½ÇÁ¦ flash memory¿¡ ±â·ÏÇÑ´Ù. targetÀº »èÁ¦ÇÒ user blockÀÌ´Ù. 0 ¾Æ´Ï¸é 1 µÑÁß ÇϳªÀÓ. user blockÀÌ ÇѰ³ ÀÌ»óÀÇ flash blockÀ¸·Î ÀÌ·ç¾îÁ® ÀÖÀ» ¼ö ÀÖ´Ù.. º¹¼ö°³ÀÇ flash blockÀ¸·Î ÀÌ·ç¾îÁø °æ¿ì¸¦ °£ÁÖÇØ¾ß Çϸç, ÀÌ °æ¿ì invalid blockÀÎÁö ¾Æ´ÑÁöµµ Ã¼Å©ÇØ¾ß ÇÑ´Ù.*/ dprint(2, " Target block for write: %d (%x), last count: %d\n", target, g_flashUserBlockInfo[target].start_addr, count); base = g_flashUserBlockInfo[target].start_addr + FLASH_RESERVED_SIZE; /* ¾ÕºÎºÐ ¿¹¾à ¿µ¿ªÀº Á¦¿ÜÇÑ´Ù.*/ /* Áö±Ý±îÁö bufferµÈ µ¥ÀÌÅÍ ±â·Ï.*/ dprint(2, " write buffered data..\n"); if (1) /* Àüü blockÀ» ´Ù ±â·Ï..*/ { size = FLASH_USER_AREA_SIZE; /* Àüü Å©±â.*/ source = pFlashShadowBuffer; /* ±â·ÏÇÒ µ¥ÀÌÅÍ Æ÷ÀÎÅÍ..*/ dprint(2, " update entire region, addr %x size %x src %x\n", base, size, source); r = halFlashWrite(base, size, source); if (r) { dprint(0, "!! %s: halFlashWrite(%x, sz %x) err %d\n", __FUNCTION__, base, size, r); goto end_of_flash_sync; } dprint(2, " verification..\n"); for (k=0; k= 0) { dprint(0, "!! verify err! [%u] buf %u != flash %u\n", k+offset, source[k+offset], tmp[offset]); r = statusError; /* statusVerifyError..*/ goto end_of_flash_sync; } } /* end verify */ } /* write magic key and count */ /* µð¹ö±ë Å×½ºÆ® ¿ëÀ¸·Î, ±âÁ¸ µ¥ÀÌÅ͸¦ ¸ÕÀú º¸¿©ÁØ´Ù. */ halFlashRead(g_flashUserBlockInfo[target].start_addr, 4+DMW_SIZE_COUNTING_BUF, header); dprint(2, " write magic key.. (old data: %02x%02x%02x, old cnt %d)\n", header[0], header[1], header[2], p_get_flash_counting(&header[4])); /* »õ·Î¿î °ªÀ» ÁغñÇÏ°í ±â·ÏÇÑ´Ù. */ memcpy(header, g_NvFlashMagic, 4); count = NextCount(count); p_set_flash_counting(count, &header[4]); base = g_flashUserBlockInfo[target].start_addr; r = halFlashWrite(base, 4+DMW_SIZE_COUNTING_BUF, header); if (r) { dprint(0, "!! %s: halFlashWrite(magic, cnt %d) err %d\n", __FUNCTION__, count, r); } else dprint(2, "==== Block %d (%x): new count %d updated\n", target, base, count); /* 100422, nvram update ÈÄ flush ÇØÁØ´Ù */ halFlashSync(); end_of_flash_sync: if (pFlashShadowBuffer) DHL_OS_Free((void**)&pFlashShadowBuffer); unlock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASH); return (STATUS)r; } /*------------------------------------------ FlashNvmFormat */ STATUS FlashNvmFormat(void) { int r, r0; int target; UINT8 buf[4+DMW_SIZE_COUNTING_BUF]={0,0,0,0,}; UINT8 cnt = 1; UINT32 base; lock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASH); dprint(2, "%s:\n", __FUNCTION__); /* µÎ blockÀ» ¸ðµÎ »èÁ¦ÇÑ´Ù.*/ for (target=0; target<2; target++) { base = g_flashUserBlockInfo[target].start_addr; memcpy(buf, g_NvFlashMagic, 4); cnt = InitialCount(); /* ÃÖÃÊÀÇ °ªÀº ¸ðµÎ 0À¸·Î ÇÑ´Ù. ¾ÆÁ÷ Á¦´ë·Î µÈ µ¥ÀÌÅͰ¡ ±â·ÏµÇÁö ¾Ê¾ÒÀ¸¹Ç·Î invalid ÇÏ´Ù´Â Á¤º¸¸¦ ³²°ÜµÖ¾ß ÇÑ´Ù. */ p_set_flash_counting(cnt, &buf[4]); /*dprint(3, " write magic key and initial count value %d\n", cnt);*/ r = halFlashWrite(base, 4+DMW_SIZE_COUNTING_BUF, buf); if (r) { dprint(0, "!! %s: halFlashWrite(magic, cnt %d) err %d\n", __FUNCTION__, cnt, r); } else dprint(2, " Block %d (%x): new count %d updated\n", target, base, cnt); } // ´ÙÀ½¹ø¿¡ _ReadSync ¸¦ ÇÏÁö ¾Ê°í ¹Ù·Î write °¡´ÉÇϵµ·Ï.. memset(g_NvFlashBuffer, 0xff, FLASH_USER_AREA_SIZE); g_NvFlashBufferValid = TRUE; dprint(1, " Format completed\n"); unlock_nvram_sema4(NVRAM_DEVICE_LOCK_FLASH); return (STATUS)r; } STATUS FlashNvmCheckValid(void) { STATUS status; UINT8 buf[10]; /* ¸¸¾à flash cache°¡ ¼öÁ¤µÈ »óŶó¸é ºÎÁÖÀÇ·Î invalidate ÇÏ´Ù°¡´Â µ¥ÀÌÅ͸¦ ÀÒ¾î¹ö¸± °ÍÀÌ´Ù. »ç¿ë ±ÝÁö.. FlashNvmInvalidateCacheBuffer(); */ /* this cause flash read sync. reading ANY byte is ok.*/ status = FlashNvmRead(0, 1, buf); if (status) { dprint(0, "!! flash seems unformatted\n"); return status; } #if 0 /* bug! this is not needed and below code has error!*/ if (memcmp(buf, g_NvFlashMagic, 3)) { return statusNotInitialized; } #endif return statusOK; } #if COMMENT ____NvRamWorkerThread_____(){} #endif /******************************************************************* NvRam WorkerThread Main purpose of this task is background FlashSync.. ********************************************************************/ #define NWT_TASK_PRIORITY TASK_PRI_DMW_FLASH #define NWT_STACK_SIZE 8192 volatile DHL_OS_TASK_ID g_NvRam_WorkerTask; UINT32 g_NvRam_FlashSyncCount; /* ¾ÆÁ÷ test¿ëÀÓ.. caller°¡ ¾ðÁ¦ flash sync°¡ Á¾·áµÇ¾ú´ÂÁö¸¦ ¾Ë¼ö ÀÖµµ·Ï count °ªÀ» Á¦°øÇÏÀÚ.. */ BOOL g_NvRam_FlashSyncWorking; typedef enum { /* NvRam Worker Task Command*/ NWTCMD_FlashSync = 0xB0, /*NWTCMD_FlashFormat, *//*not defined..*/ /*NWTCMD_Flashxxxx, */ NWTCMD_Shutdown, } NWTCMD; /*----------------------------------------------*/ /* User Message Queue implementation*/ typedef struct { NWTCMD cmd; //UINT32 param; } NwtCmdMsg; static const char *NwtCmdName(NwtCmdMsg *msg) { if (msg->cmd == NWTCMD_FlashSync) return "sync"; if (msg->cmd == NWTCMD_Shutdown) return "shutdown"; return "?"; } static DMW_MSGQUE g_NvmMsgQue; #define SZ_USER_MSG_Q 50 //NwtCmdMsg g_NvRam_WorkerUserQ[SZ_USER_MSG_Q]; /* Mutex = { SemID, Owner, lockCnt, FailCnt, UseOsMutex, Name, flag, traceLvl }*/ static DMW_MUTEX NwtMsgQueMutex = { 0, 0, 0, 0, FALSE, "NwtMsgQ", OS_SEM_PRIO, 1, }; void NwtLockMutex(BOOL bLock) { if (bLock) DMW_LockMutex(&NwtMsgQueMutex); else DMW_UnlockMutex(&NwtMsgQueMutex); } void TestPrintUserMsgQ() { NwtLockMutex(TRUE); DMW_SYS_PrintUserMsgs(&g_NvmMsgQue, (DMW_FN_MSG_NAME)NwtCmdName); NwtLockMutex(FALSE); } static BOOL NwtIsSyncCmd(NwtCmdMsg *msg, UINT32 param) { return (msg->cmd == NWTCMD_FlashSync) ? TRUE : FALSE; } int tNvRamWorker(int arg) { NwtCmdMsg um; STATUS status; UINT32 tick; int delay = 1000/10; /*------------------------------ command message ¹Þ´Â ºÎºÐ. ------------------------------*/ label_loop_begin: status = DMW_SYS_GetUserMsg(&g_NvmMsgQue, &um, DHL_TIMEOUT_FOREVER); if (status) { DHL_OS_Delay(delay); goto label_loop_begin; } NwtLockMutex(TRUE); g_NvRam_FlashSyncWorking = TRUE; NwtLockMutex(FALSE); /*------------------------------ command message ó¸® ºÎºÐ.. ------------------------------*/ if (um.cmd == NWTCMD_FlashSync) { int i, ptr; //UINT32 count = um.param; BOOL bFutureFlashSyncFound = FALSE; dprint(2, "NWTCMD_FlashSync:\n"); /* We must not do flash sync whenever command receives. first, we should peek user msg Queue.. */ NwtLockMutex(TRUE); bFutureFlashSyncFound = DMW_SYS_CheckSpecificMsgExist(&g_NvmMsgQue, (DMW_FN_MSG_CHECK)NwtIsSyncCmd, 0); NwtLockMutex(FALSE); if (bFutureFlashSyncFound) { dprint(2, "\t!! this flash sync cmd is ignored by future FlashSync..\n"); goto label_loop_begin; } /* Now, do flash sync..*/ dprint(2, "\t--> Start flash sync (NULL)\n"); tick = DHL_OS_GetMsCount(); FlashNvmSync(NULL); NwtLockMutex(TRUE); g_NvRam_FlashSyncCount++; /* cafrii 050413 add for provide info to caller when sync end*/ g_NvRam_FlashSyncWorking = FALSE; NwtLockMutex(FALSE); dprint(2, "\t<-- End flash sync (NULL), %d ms\n", (DHL_OS_GetMsCount()-tick)); } else if (um.cmd == NWTCMD_Shutdown) { dprint(2, "NWTCMD_Shutdown:\n"); goto label_loop_end; } goto label_loop_begin; /*------------------------------ task Á¾·á.. shutdown ------------------------------*/ label_loop_end: dprint(2, "NvRam Worker task is about to shutdown..\n"); NwtLockMutex(TRUE); g_NvRam_FlashSyncWorking = FALSE; NwtLockMutex(FALSE); g_NvRam_WorkerTask = 0; DHL_OS_SelfDeleteTask(); return 0; } int NwtCreateResources() { DHL_OS_TASK_ID tid; if (g_NvRam_WorkerTask == 0) { dprint(2, "** create Nwt Task..\n"); tid = DHL_OS_CreateTask((DHL_OS_TASKFUNCTION) tNvRamWorker, "NwtTask", NWT_TASK_PRIORITY, NWT_STACK_SIZE, 0); if (tid == (DHL_OS_TASK_ID)0) { dprint(0, "!! NwtTask spawn err!\n"); return statusOutOfResource; } dprint(2, " task %x created.\n", tid); g_NvRam_WorkerTask = tid; } return statusOK; } STATUS NwtSendCommand(NWTCMD cmd, UINT32 param) { NwtCmdMsg um; STATUS status; memset(&um, 0, sizeof(NwtCmdMsg)); um.cmd = cmd; //um.param = param; NwtLockMutex(TRUE); status = DMW_SYS_AddUserMsg(&g_NvmMsgQue, &um); NwtLockMutex(FALSE); return status; } #if COMMENT ______NvRam_API_______(){} #endif /******************************************************************* NvRamInit NvRamÀ» »ç¿ëÇϱâ À§Çؼ­ ÃʱâÈ­¸¦ ÇÑ´Ù. ½ÇÁ¦·Î format, reset µîÀÇ ÀÛ¾÷À» ÇÏ´Â °ÍÀÌ ¾Æ´Ô¿¡ À¯ÀÇ. ********************************************************************/ void NvRamInit(void) { DMW_SYS_InitMsgQue(&g_NvmMsgQue, sizeof(NwtCmdMsg), SZ_USER_MSG_Q, (DMW_FN_MSG_NAME)NwtCmdName); FlashNvmInit(); /* eepromÀº µ¿Àû initÀ» Çϵµ·Ï ÀÌ¹Ì µÇ¾î ÀÖÀ¸´Ï ºÒÇÊ¿ä.*/ } /******************************************************************* NvRamGetAvailableSize ********************************************************************/ UINT32 NvRamGetAvailableSize(int device) { /*------------------- device 1 -------------------*/ if (device) /* device 1*/ return FlashNvmGetAvailableSize(); #if SUPPORT_DMW_EEPROM return EepromGetAvailableSize(); #else return 0; #endif } /******************************************************************* NvRamCheckValid ********************************************************************/ STATUS NvRamCheckValid(void) { /* eepromÀÇ °æ¿ì´Â valid check°¡ ºÒ°¡´É.*/ return FlashNvmCheckValid(); } /******************************************************************* NvRamRead NvRam µ¥ÀÌÅ͸¦ Àд´Ù. device 1ÀÇ °æ¿ì (flash) shadow buffer¿Í I/O¸¦ ¼öÇà. ********************************************************************/ STATUS NvRamRead(UINT32 address, UINT32 size, UINT8 *buf) { int err; if (NwtCreateResources()) return statusOutOfResource; if (size == 0) return statusOK; /*------------------- device 1 -------------------*/ if (address & 0x80000000) /* device 1*/ { err = FlashNvmRead(address & 0x7fffffff, size, buf); return (STATUS)err; } /*------------------- device 0 -------------------*/ #if SUPPORT_DMW_EEPROM err = EepromRead(address, size, buf); return err; #else return statusNotImpl; #endif /* SUPPORT_DMW_EEPROM*/ } /******************************************************************* NvRamWrite NvRam¿¡ µ¥ÀÌÅ͸¦ ±â·ÏÇÑ´Ù. device 1ÀÇ °æ¿ì (flash) shadow buffer¿Í I/O¸¦ ¼öÇà. ********************************************************************/ STATUS NvRamWrite(UINT32 address, UINT32 size, UINT8 *buf) { int err; if (NwtCreateResources()) return statusOutOfResource; if (size == 0) return statusOK; /*------------------- device 1 -------------------*/ if (address & 0x80000000) /* device 1*/ { err = FlashNvmWrite(address & 0x7fffffff, size, buf); return (STATUS)err; } /*------------------- device 0 -------------------*/ #if SUPPORT_DMW_EEPROM err = EepromWrite(address, size, buf); return err; #else return statusNotImpl; #endif /* SUPPORT_DMW_EEPROM*/ } /******************************************************************* NvRamSync flash ¿µ¿ªÀÇ ÁÖ¼ÒÀÏ °æ¿ì shadow buffer ³»¿ë°ú ½ÇÁ¦ device ³»¿ëÀ» ÀÏÄ¡½ÃŲ´Ù. Áï buffer->flash·Î ±â·ÏÇÔ. ********************************************************************/ STATUS NvRamSync(UINT32 addr, PartMapRange *pPartMapList) { STATUS r; if (NwtCreateResources()) return statusOutOfResource; if (addr & 0x80000000) { r = NwtSendCommand(NWTCMD_FlashSync, 0); dprint(2, "NvRamSync: deferred to NWT..\n"); return r; } #if SUPPORT_DMW_EEPROM /* device 0¿¡ ´ëÇØ¼­´Â sync °³³äÀÌ ¾ø´Ù.*/ return statusOK; #else /* eeprom ±â´É ¾øÀ½.*/ return statusNotImpl; #endif } /******************************************************************* NvRamIsSyncEnd NvRamSync ÀÛ¾÷ÀÌ Á¾·áµÇ¼­ idle »óÅÂÀ̸é TRUE¸¦ ¸®ÅÏ. ********************************************************************/ BOOL NvRamIsSyncEnd() { /* return TRUE if Sync is completed.*/ BOOL bSyncWorking; NwtLockMutex(TRUE); if (!DMW_SYS_UserMsgExist(&g_NvmMsgQue) && g_NvRam_FlashSyncWorking == FALSE) bSyncWorking = FALSE; else bSyncWorking = TRUE; NwtLockMutex(FALSE); return !bSyncWorking; } /******************************************************************* NvRamWaitForSyncEnd NvRam Sync ÀÛ¾÷ÀÌ ÁøÇàÁßÀÏ °æ¿ì Á¾·áµÉ ¶§ ±îÁö ±â´Ù¸°´Ù. ********************************************************************/ void NvRamWaitForSyncEnd() { UINT32 ms0, ms1, ms; ms0 = ms1 = DHL_OS_GetMsCount(); while (!NvRamIsSyncEnd()) { ms = DHL_OS_GetMsCount(); if (ms-ms1 > 4000) { dprint(0, "!! nvm sync too slow! %u ms elapsed?\n", ms-ms0); ms1 = ms; } DHL_OS_Delay(100); } } /******************************************************************* NvRamInvalidateCache flash shadow bufferÀÇ ³»¿ëÀ» ¹«È¿È­ ½ÃŲ´Ù. ÀÌÈÄ NvRamRead/Write¸¦ ÇÒ ¶§ ´Ù½Ã device·ÎºÎÅÍ ÀоîµéÀδÙ. ********************************************************************/ void NvRamInvalidateCache() { /*device 0:*/ /*EEPROM¿¡´Â cache°¡ ¾ø´Ù.*/ /* device 1:*/ FlashNvmInvalidateCacheBuffer(); } /******************************************************************* NvRamFormat nvm device¸¦ Æ÷¸ËÇÑ´Ù. flash nvm¿¡¸¸ ÇØ´ç. ********************************************************************/ STATUS NvRamFormat() { NvRamWaitForSyncEnd(); return FlashNvmFormat(); } /******************************************************************* NvRamShutdown ********************************************************************/ STATUS NvRamShutdown() { UINT32 tickStart; NwtSendCommand(NWTCMD_Shutdown, 0); /* shutdown µÉ ¶§±îÁö ±â´Ù·Á¾ß ÇÑ´Ù..*/ tickStart = DHL_OS_GetMsCount(); while (g_NvRam_WorkerTask && DHL_OS_GetMsCount() - tickStart < 6*1000) DHL_OS_Delay(1000/4); dprint(2, "NvRamShutdown: WorkerTask %s died\n", g_NvRam_WorkerTask ? "NOT" : ""); return g_NvRam_WorkerTask ? statusError : statusOK; } #if COMMENT ____Test___________(){} #endif void _dump_eeprom(int start, int size) { int i; UINT8 t[1]; DHL_OS_Printf("Secret Dump of EEPROM (%x~%x)\n", start, start+size); for (i=0; i d 0xbb000000 + offset */ void _dump_flash(UINT32 start, UINT32 size) { #define DUMP_CHUNK_SIZE 512 unsigned int i, k, len, r; UINT8 t[DUMP_CHUNK_SIZE]; //int oldflag = g_Trace_NvRamDebug; //g_Trace_NvRamDebug = 1; if (start & 0xf) { size += (start & 0xf); start &= ~0xf; } DHL_OS_Printf("==== Secret Dump of Flash (%x~%x) ====\n", start, start+size); for (i=0; i<(size+DUMP_CHUNK_SIZE-1)/DUMP_CHUNK_SIZE; i++) { len = min(size - DUMP_CHUNK_SIZE*i, DUMP_CHUNK_SIZE); r = halFlashRead(start+i*DUMP_CHUNK_SIZE, len, t); /* len Å©±â¸¸ Àо µÇ°í, ´Ù Àо µÇ°í..*/ /* display..*/ for (k=0; k