📄 write_idblock.c
字号:
if (SysIDBlock.productID) {
printf("\n\nRetain the %02X:%02X:%02X:%02X:%02X:%02X MAC address (Y/N)? ",
SysIDBlock.macAddr[0], SysIDBlock.macAddr[1], SysIDBlock.macAddr[2],
SysIDBlock.macAddr[3], SysIDBlock.macAddr[4], SysIDBlock.macAddr[5]);
ch = toupper(getchar());
if (ch != 'N') {
memcpy(tempMAC, SysIDBlock.macAddr, sizeof(tempMAC));
}
printf("\n\n");
}
#endif
//////////////////////////////////////////////////
// map MB1CR or MB3CR quadrant to flash on /CS0
// make sure A18 NOT inverted in MB1CR or MB3CR (handles bank select)
#ifdef _FLASH_
saveMB1or3CR = MB1CRShadow;
WrPortI(MB1CR, &MB1CRShadow, FLASH_WSTATES | 0x00);
_InitFlashDriver(0x01 | 0x02);
#else
#ifdef _RAM_
saveMB1or3CR = MB3CRShadow;
WrPortI(MB3CR, &MB3CRShadow, FLASH_WSTATES | 0x00);
_InitFlashDriver(0x08);
#else
#ifdef _FAST_RAM_
saveMB1or3CR = MB3CRShadow;
WrPortI(MB3CR, &MB3CRShadow, FLASH_WSTATES | 0x00);
_InitFlashDriver(0x08);
#endif
#endif
#endif
//////////////////////////////////////////////////
// set up the ID block fields
memset(&SysIDBlock, 0x00, sizeof(SysIDBlock));
#ifdef IDBLOCK_VERSION
SysIDBlock.tableVersion = IDBLOCK_VERSION;
#else // !IDBLOCK_VERSION
#if (CC_VER < 0x0726)
SysIDBlock.tableVersion = 2;
#else
SysIDBlock.tableVersion = 4;
#endif
#endif // !IDBLOCK_VERSION
#if ((NUMUSER4KBLOCKS & 1) && (CC_VER < 0x0800))
if (SysIDBlock.tableVersion >= 3) {
printf("\n\nIn this version of Dynamic C, the BIOS only supports\n");
printf("mirrored User Block (ID Block version 3 and up) sizes that\n");
printf("are a multiple of 8KB.\n\n");
printf("Recommend either editing the source to force a version 2 ID\n");
printf("Block, or define NUMUSER4KBLOCKS to be an even number.\n\n");
printf("Exiting without making any changes...\n\n");
exit(0);
}
#endif
SysIDBlock.vendorID = 1;
#if CC_VER >= 0x0705
setTimeStamp(dc_timestamp);
#else
setTimeStamp(SEC_TIMER);
#endif
SysIDBlock.idBlockSize = sizeof(SysIDBlock);
for (i=0; i<3; i++) {
SysIDBlock.marker[i*2] = 0x55;
SysIDBlock.marker[i*2+1] = 0xAA;
}
//////////////////////////////////////////////////
// board-specific data
SysIDBlock.productID = MYBOARD;
SysIDBlock.flashID = GetFlashID();
SysIDBlock.flashSize = _FLASH_SIZE_;
SysIDBlock.flashType = _FlashInfo.writeMode;
SysIDBlock.sectorSize = _FlashInfo.sectorSize;
SysIDBlock.numSectors = _FlashInfo.numSectors;
SysIDBlock.flashSpeed = 0x00; // special case, means "unknown"
#if HAS2FLASHES
// we assume that the 2nd flash (if installed) is
// identical to the first one
SysIDBlock.flash2ID = SysIDBlock.flashID;
SysIDBlock.flash2Size = _FLASH_SIZE_;
SysIDBlock.flash2Type = _FlashInfo.writeMode;
SysIDBlock.sector2Size = _FlashInfo.sectorSize;
SysIDBlock.num2Sectors = _FlashInfo.numSectors;
SysIDBlock.flash2Speed = 0x00; // special case, means "unknown"
#endif
SysIDBlock.ramID = 0x01;
SysIDBlock.ramSize = _RAM_SIZE_;
SysIDBlock.ramSpeed = 0x00; // special case, means "unknown"
SysIDBlock.cpuID = getCPUID(); // Rabbit CPU + Version
xmem2root(&div19200val, (unsigned long) divider19200, sizeof(char));
SysIDBlock.crystalFreq = div19200val * 614400ul;
// may fill serial number and product name here (future)
#if NUMUSER4KBLOCKS
if (SysIDBlock.tableVersion > 1) {
// reserve space for the User Block
SysIDBlock.userBlockSize =
SysIDBlock.userBlockLoc = (NUMUSER4KBLOCKS * 4096)
- (int) SysIDBlock.idBlockSize;
}
#endif
#if (HASETHERNET && !HASEEPROM)
// fill MAC address
memcpy(SysIDBlock.macAddr, tempMAC, sizeof(SysIDBlock.macAddr));
#endif
//////////////////////////////////////////////////
// calculate the ID block's CRC sum
SysIDBlock.idBlockCRC = 0x0000;
i = (int) (&SysIDBlock.reserved) - (int) (&SysIDBlock.tableVersion);
crc = calcCRC(0x0000, &SysIDBlock, i);
crc = calcCRC(crc, &SysIDBlock.idBlockSize, 16);
SysIDBlock.idBlockCRC = crc;
//////////////////////////////////////////////////
// write the ID Block(s) to flash
i = writeIDBlock();
if (i != 0) {
printf("\nError writing ID block (%d): \n", i);
if (i == -1) printf(" attempt to write to non-flash area\n");
else if (i == -2) printf(" source not located in root\n");
else if (i == -3) printf(" timeout during flash write\n");
else printf(" unknown error type\n");
exit(1);
} else {
printf("\nID block successfully written.\n\n");
}
//////////////////////////////////////////////////
// now try and read the ID block back...
memset(&SysIDBlock, 0x00, sizeof(SysIDBlock));
#ifdef _FLASH_
i = _readIDBlock(0x01 | 0x02);
#else
#ifdef _RAM_
i = _readIDBlock(0x08);
#else
#ifdef _FAST_RAM_
i = _readIDBlock(0x08);
#endif
#endif
#endif
//////////////////////////////////////////////////
// ...and report the information we (hope we have) found
if (i != 0) {
printf("Error %d when reading ID block.\n", i);
exit(1);
} else {
PrintSysIDBlockInfo();
PrintProductDescription(SysIDBlock.productID);
PrintFlashDescription("Flash ID", (int) SysIDBlock.flashID,
SysIDBlock.flashType);
PrintFlashDescription("Flash2 ID", (int) SysIDBlock.flash2ID,
SysIDBlock.flash2Type);
PrintFlashDescription("GetFlashID() result", GetFlashID(),
_FlashInfo.writeMode);
}
//////////////////////////////////////////////////
// restore altered MBxCR
#ifdef _FLASH_
WrPortI(MB1CR, &MB1CRShadow, saveMB1or3CR);
#else
#ifdef _RAM_
WrPortI(MB3CR, &MB3CRShadow, saveMB1or3CR);
#else
#ifdef _FAST_RAM_
WrPortI(MB3CR, &MB3CRShadow, saveMB1or3CR);
#endif
#endif
#endif
//////////////////////////////////////////////////
// Loop forever to prevent repetitive flash writes,
// in case this program is started in run mode!
printf("\n\nLooping forever to prevent repetitive flash writes.\n");
while (1);
}
/********************************************************************/
int writeIDBlock()
{
auto unsigned long physaddr;
auto int err;
#ifdef _FLASH_
physaddr = sectorToLong(_FlashInfo.numSectors) - sizeof(SysIDBlock);
#else
physaddr = ((sectorToLong(_FlashInfo.numSectors) - sizeof(SysIDBlock)) &
0x0003FFFFul) + 0x000C0000ul;
#endif
physaddr &= 0x000FFFFFul; // ensure physical address is within 1MB range
_overwrite_block_flag = 1;
err = WriteFlash(physaddr, &SysIDBlock, sizeof(SysIDBlock));
_overwrite_block_flag = 0;
#if NUMUSER4KBLOCKS
// Has a User Block, now check if mirrored . . .
if (SysIDBlock.tableVersion >= 3) {
// Mirrored ID/User Block version, might as well do it now!
physaddr -= NUMUSER4KBLOCKS * 4096ul;
_overwrite_block_flag = 1;
SysIDBlock.marker[5] = '\x00';
err = WriteFlash(physaddr, &SysIDBlock, sizeof(SysIDBlock));
SysIDBlock.marker[5] = '\xAA';
_overwrite_block_flag = 0;
}
#endif
return err;
}
/********************************************************************/
int GetFlashID()
{
static int id;
#asm
#ifdef __SEPARATE_INST_DATA__
#if __SEPARATE_INST_DATA__ && FLASH_COMPILE
ld hl, _GetFlashID
lcall _CallRAMFunction
#else
call _GetFlashID
#endif
#else
call _GetFlashID
#endif
ld (id), hl
#endasm
return id;
}
/********************************************************************/
int getCPUID()
{
static int id;
#asm
ioi ld a, (GCPU)
and 0x1F
ld (id+1), a
ioi ld a, (GREV)
and 0x1F
ld (id), a
#endasm
return id;
}
/********************************************************************/
void setTimeStamp(unsigned long timeStamp)
{
static struct tm t;
mktm(&t, timeStamp);
SysIDBlock.timestamp[0] = (t.tm_year + 1900) / 100;
SysIDBlock.timestamp[1] = t.tm_year % 100;
SysIDBlock.timestamp[2] = t.tm_mon;
SysIDBlock.timestamp[3] = t.tm_mday;
SysIDBlock.timestamp[4] = t.tm_hour;
SysIDBlock.timestamp[5] = t.tm_min;
SysIDBlock.timestamp[6] = t.tm_sec;
}
/********************************************************************/
#define CRC_POLY 0x1021 // 16-bit CRC polynomial
// (recommended by CCITT X25 standard)
/*
* CRC calculation functions
* - can be called from C (calcCRC) or assembly (_calcCRC)
* - reference: "A painless guide to CRC error detection algorithms",
* 8/19/1993, Ross N. Williams
*/
#asm
// int calcCRC(int initCRC, void *data, int blocksize);
calcCRC::
ld hl, 2
add hl, sp
ld hl, (hl)
ex de, hl ; initial CRC value
ld hl, 6 ; the "blocksize" variable
add hl, sp
ld hl, (hl)
ld b, h
ld c, l ; get data size off stack
ld hl, 4 ; the "data" variable
add hl, sp
ld hl, (hl) ; hl now contains pointer to data
;; assembly entry point
_calcCRC::
; de contains initial CRC value
; hl contains pointer to data
; bc contains number of bytes
dataloop:
push hl
ld h, (hl) ; get next byte into hl (and shift it left 8 bits)
ld l, 0x00
push bc ; save byte counter
call _byteCRC ; call CRC function from BIOS
pop bc ; restore byte counter
pop hl
inc hl
dec bc
xor a
cp b
jr nz, dataloop
cp c
jr nz, dataloop
ex de, hl ; CRC returned in hl
ret
#endasm
//////////////////////////////////////////////////////////////////////
#asm
;;
;; Calculate the CRC value for a single byte. Can be called multiple
;; times (without resetting the CRC value passed to it) to do a CRC
;; check on a larger block of data.
;;
;; data byte passed in h (l should be 0x00)
;; crc value passed, returned in de
;;
_byteCRC::
push bc
push af
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -