⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 write_idblock.c

📁 用于Rabbit写Flash设备ID的程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 + -