📄 idblock_recovery.c
字号:
//*****************************************************************************
// Program : idBlock_recovery.c
// Revision : 1.1 Initial Release.
// 1.2 Removed VERBOSITY_LEVEL 0
// Date : 08/02/2002
//
// Utility to convert a target controller's mirrored version 3 or 4 ID/User
// Blocks to a single version 2 ID/User Block.
//
// Mirroring of the version 3 and 4 ID/User Blocks is subject to a Dynamic C
// 7.20/7.21/7.25 bug exposed when an application calls the writeUerBlock()
// function. The GLOBAL_INIT function chain segment in writeUserBlock() may
// fail to correctly update the old "invalid" User Block image when it differs
// from the new "valid" User Block image.
//
// Symptoms may include Dynamic C target communication time outs which occur
// only on specific controllers immediately after the application has been
// loaded, incorrect controller operation, or loss of User Block data.
//
// Exit codes: 0 = Version 4 User Blocks converted to version 2 User Block,
// success.
// 10 = No System ID Block found, if sure that ID block was
// installed run Write_IDblock.c or contact Z-World.
// 20 = Unaffected System ID Block version, OK (nothing to do).
// 30 = Unknown System ID Block version, if sure that version 3
// or 4 ID block was installed. Run Write_IDblock.c or
// contact Z-World.
// 41 = Nonstandard BL21xx User Block size, run Write_IDblock.c or
// and recalibrate board or contact Z-World.
// 42 = No BL21xx calibration constants found, recalibrate or
// contact Z-World.
// 43 = Error writing BL21xx calibration constants into User
// Block, run Write_IDblock.c and recalibrate or contact
// Z-World.
// 50 = User Block A & B images both marked invalid,
// run Write_IDblock.c or contact Z-World.
// 60 = Error while copying valid User Block "B" to "A" location,
// run utility again or contact Z-World.
// 70 = Error while installing version 2 System ID Block, run
// utility again or contact Z-World.
// 80 = Old System ID Block "B" copy, not problem.
//
// Note that this utility is designed to run using the stock libraries
// provided with Dynamic C 7.20 or later. In particular, this utility calls
// the GetIDBlockSize() function, which is included only with Dynamic C 7.20
// and later.
//
// Also note that Dynamic C must run this program in debug mode in order to
// display the optional messages and to report the utility's exit code from
// the list above.
//
// Instructions:
//
// 1) If desired, set the VERBOSITY_LEVEL macro definition according to a
// value listed in its associated comments just below these instructions.
//
// 2) Ensure that Dynamic C's Compiler Options are set to compile to flash.
//
// 3) Compile idBlock_recovery.c to the target controller and run it.
//
// 4) Diagnostic messages may be presented, and the exit code will report the
// utility's final run status.
//*****************************************************************************
// Program name
#define PROGRAM_NAME "idBlock_recovery.c"
// define desired verbosity level:
// 1 == informative, 2 == chatty, 3 == please make it stop!
#define VERBOSITY_LEVEL 2
#if (CC_VER < 0x720)
#fatal "idBlock_recovery.c requires Dynamic C 7.20 or later."
#endif
// ensure running in flash!
#ifndef _FLASH_
#error "idBlock_recovery.c must run in flash!"
#endif
// check for undefined board types
#ifndef BL2100
#define BL2100 0x0B00
#endif
#ifndef BL2101
#define BL2101 0x0B06
#endif
#ifndef BL2105
#define BL2105 0x0B04
#endif
#ifndef BL2110
#define BL2110 0x0B02
#endif
#ifndef BL2111
#define BL2111 0x0B08
#endif
#ifndef BL2115
#define BL2115 0x0B05
#endif
#ifndef BL2121
#define BL2121 0x0B07
#endif
// macro definition needed for non-BL20xx/BL21xx targets
#ifndef DACHANNELS
#define DACHANNELS 4
#endif
#define MAX_DACGAIN (0.002497 * 1.2)
#define MIN_DACGAIN (0.002473 * 0.8)
#define MAX_DACOFST (4137.043400 * 1.2)
#define MIN_DACOFST (4123.284600 * 0.8)
// global constants
const char myInvalidMarker[]={"\x55\xAA\x55\xAA\x55\x00"};
const char myValidMarker[]={"\x55\xAA\x55\xAA\x55\xAA"};
// global variables
char myUBACCBuffer[0x400], myUBBCCBuffer[0x400]; // Z-World reserved size!
char *validCCBuffer;
int activeSIDBA, activeSIDBB;
int validSIDBA, validSIDBB;
int validSIDBA_CC, validSIDBB_CC;
unsigned long addrSIDBA, addrSIDBB;
unsigned long addrUBA, addrUBB;
unsigned long addrUBA_CC, addrUBB_CC;
float myDACCalib[DACHANNELS][2]; // [0]=gain,[1]=offset
SysIDBlockType mySIDBA, mySIDBB;
// local function prototypes
int CalcIDBlockCRC(SysIDBlockType *sidb);
int RecoverBL21xxCC(void);
int ReportCCInfo(char *ubccBuffer, char *ubccName);
int ReportSysIDBlockInfo(SysIDBlockType *sidb, char *sidbName);
main()
{
unsigned blockLength, copyOffset, copyLength;
int errorResult;
if (SysIDBlock.tableVersion == 0) {
#if (VERBOSITY_LEVEL >= 0)
printf("No System ID Block found.\n");
printf("Quitting without making any changes.\n\n");
printf("Recommend using write_IDblock.c to remake ID block\n");
printf("or contact Z-World for further instructions.\n");
#endif // V_L > 0
exit(10);
}
if (SysIDBlock.tableVersion < 3) {
#if (VERBOSITY_LEVEL >= 0)
printf("Unaffected System ID Block version.\n");
printf("Quitting without making any changes.\n");
#endif // V_L > 0
exit(20);
}
if (SysIDBlock.tableVersion > 4) {
#if (VERBOSITY_LEVEL >= 0)
printf("Unknown System ID Block version %d.\n", SysIDBlock.tableVersion);
printf("Quitting without making any changes.\n");
printf("Recommend using write_IDblock.c to remake ID block\n");
printf("or contact Z-World for further instructions.\n");
#endif // V_L > 0
exit(30);
}
// System ID Block A is always at top of 1st flash
addrSIDBA = (_FLASH_SIZE_ * 0x1000ul) - sizeof(SysIDBlock);
// User Block A is also always at the top of 1st flash
if (((SysIDBlock.productID & 0xFF00) == 0x0800) ||
((SysIDBlock.productID & 0xFF00) == 0x0B00))
{
// special case for BL20xx, BL21xx!
addrUBA = (_FLASH_SIZE_ * 0x1000ul) - 0x2000ul;
} else {
addrUBA = (_FLASH_SIZE_ * 0x1000ul) - (0x1000ul * GetIDBlockSize());
}
xmem2root(&mySIDBA, addrSIDBA, sizeof(SysIDBlock));
errorResult = ReportSysIDBlockInfo(&mySIDBA, "mySIDBA");
// default to active+valid System ID Block A
activeSIDBA = validSIDBA = 1;
switch (errorResult) {
case 0: // no error, active+valid
break;
case 1: // no error, just inactive
activeSIDBA = 0;
break;
case 2: // error, invalid
case 3: // also inactive
default:
activeSIDBA = validSIDBA = 0;
break;
}
// System ID Block B is always just below User Block A near top of 1st flash
if (((SysIDBlock.productID & 0xFF00) == 0x0800) ||
((SysIDBlock.productID & 0xFF00) == 0x0B00))
{
// special case for BL20xx, BL21xx!
addrSIDBB = addrSIDBA - 0x2000ul;
addrUBB = addrUBA - 0x2000ul;
} else {
addrSIDBB = addrSIDBA - (0x1000ul * GetIDBlockSize());
addrUBB = addrUBA - (0x1000ul * GetIDBlockSize());
}
xmem2root(&mySIDBB, addrSIDBB, sizeof(SysIDBlock));
errorResult = ReportSysIDBlockInfo(&mySIDBB, "mySIDBB");
// default to active+valid System ID Block B
activeSIDBB = validSIDBB = 1;
switch (errorResult) {
case 0: // no error, active+valid
break;
case 1: // no error, just inactive
activeSIDBB = 0;
break;
case 2: // error, invalid
case 3: // also inactive
default:
activeSIDBB = validSIDBB = 0;
break;
}
// check if BL21xx, if so+required+possible
// then recover calibration constants
errorResult = RecoverBL21xxCC();
if (errorResult) {
exit(40 + errorResult);
}
// ensure there's at least 1 active+valid User Block
if (!activeSIDBA && !activeSIDBB) {
#if (VERBOSITY_LEVEL >= 0)
printf("User Block A & B images both marked invalid!\n");
printf("Quitting without making any changes.\n");
printf("Recommend using write_IDblock.c to remake ID block\n");
printf("or contact Z-World for further instructions.\n");
#endif // V_L > 0
exit(50);
}
// calculate User Blocks' data size (less the ID block)
if (((SysIDBlock.productID & 0xFF00) == 0x0800) ||
((SysIDBlock.productID & 0xFF00) == 0x0B00))
{
// special case for BL20xx, BL21xx!
blockLength = 0x2000 - sizeof(SysIDBlock);
} else {
blockLength = 0x1000 * GetIDBlockSize() - sizeof(SysIDBlock);
}
// ensure System ID Block "A" copy in memory is valid
if (!activeSIDBA) {
// ID Block check from above ensures System ID Block "B" copy is valid
memcpy(&mySIDBA, &mySIDBB, sizeof(SysIDBlock));
}
// if necessary, copy valid User Block data to other User Block
copyOffset = 0;
copyLength = blockLength;
while (copyOffset < blockLength) {
if (copyLength > sizeof(myUBACCBuffer)) {
copyLength = sizeof(myUBACCBuffer);
}
// get User Block A data
xmem2root(myUBACCBuffer, addrUBA+copyOffset, copyLength);
// get User Block B data
xmem2root(myUBBCCBuffer, addrUBB+copyOffset, copyLength);
if (memcmp(myUBACCBuffer, myUBBCCBuffer, copyLength)) {
// write only segments with differences between User Blocks A & B
_overwrite_block_flag = 1;
if (activeSIDBA) {
// "A" valid, copy it to "B"
errorResult = WriteFlash(addrUBB+copyOffset, myUBACCBuffer,
copyLength);
} else {
// "B" valid, copy it to "A"
errorResult = WriteFlash(addrUBA+copyOffset, myUBBCCBuffer,
copyLength);
}
if (errorResult) {
#if (VERBOSITY_LEVEL >= 0)
printf("\nError while copying valid User Block information to other location!\n");
printf("Quitting without making additional changes.\n\n");
printf("Re-running idBlock_recovery.c may complete the User Block conversion.\n");
printf(" \"OR\" \n\n");
printf("contact Z-World for further instructions.\n");
#endif // V_L > 0
exit(60);
}
}
copyOffset += copyLength; // offset to next User Block copy segment
copyLength = blockLength - copyOffset; // remaining copy size
}
// now fix up verion 3 or 4 System ID Block "A"
// as sole version 2 ID Block
mySIDBA.tableVersion = 2;
memcpy(&mySIDBA.marker, myValidMarker, sizeof(mySIDBA.marker));
mySIDBA.idBlockCRC = CalcIDBlockCRC(&mySIDBA);
// write the converted version 2 User Block to flash
_overwrite_block_flag = 1;
errorResult = WriteFlash(addrSIDBA, &mySIDBA, sizeof(SysIDBlock));
if (errorResult) {
#if (VERBOSITY_LEVEL >= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -