Protocolo FAT (formato de unidad)

Electronics and Programming tutorials and projects

Protocolo FAT (formato de unidad)

fat16 protocol FAT 协议

Este artículo proporciona una descripción general de los protocolos de hardware de almacenamiento. El protocolo FAT16 o FAT permite formatear memorias de hasta dos gigas.

Protocolo FAT

En el protocolo FAT, los datos solo se clasifican y, al leer el comienzo del disco duro, se puede conocer la dirección de los datos.

La ubicación inicial de una unidad formateada con el protocolo FAT es una «instrucción de salto».

La instrucción de salto es 0xeb3c90.

Después de identificar estos tres bytes, casi puede estar seguro de haber ingresado a la unidad. Los siguientes 8 bytes especifican el sistema que formateó la unidad.

Siguientes dos bytes: 16 bits, el número de bytes en cada sector.

Siguiente byte: 8 bits, el número de sectores por clúster (sectores por clúster).

Siguientes dos bytes: 16 bits, segmentos precargados (reservados)

Siguiente byte: 8 bits, el número de tablas de asignación de archivos (fats)

Los siguientes dos bytes: 16 bits, las entradas totales del kernel (raíz)

Siguiente byte: 16 bits, la suma de partes lógicas

Siguiente byte: 8 bits, información del dispositivo de almacenamiento

Siguientes dos bytes: 16 bits, el número lógico de segmentos por grasa

Desde la dirección 0xb hasta 0x1fe está relacionada con el sesgo y el sistema operativo, el volumen de estos datos es variable.

Datos 0x1fe=0x55 y 0x1ff=0xaa, lo que se denomina rotación (desplazamiento) de datos para sincronización.

Secciones de cada grupo * bytes de cada sección = el número que ingresa al formatear la unidad (tamaño de la unidad de asignación), por lo que se encontró una relación con el exterior de la unidad.

Aquí quedará claro que el original de cualquier dato digital no se puede distinguir de ninguna manera de su copia.

Puede copiar cualquier tipo de datos digitales, a menos que el chip no lo permita, por lo que para copiar este tipo de datos protegidos, el chip debe dividirse en laboratorios avanzados y manipularse sus puertas, lo cual es casi imposible.

* byte

| | el sector

( ) grupo (cluster)

( |**…*| |**…*| |**…*| )

Los sectores tienen 512 bytes en la mayoría de los formatos. El siguiente programa lee la información básica del archivo en formato FAT16 o FAT de la tarjeta de memoria:

bool cTxos::bFileInit()
{
	if(!bSDMMCReceiveBlock(0x00000000))
	{
		strcpy(ucErrMsg,“File format 0“);

		return 0;
	}

	if(ucFileBlockData[0] != 0xeb
		|| ucFileBlockData[1] != 0x3c
		|| ucFileBlockData[2] != 0x90)//Jump instruction
	{
		strcpy(ucErrMsg,“File format J“);

		return 0;
	}

	usFileBPS = ucFileBlockData[11];
	usFileBPS |= ucFileBlockData[12] << 8;

	ucFileSPC = ucFileBlockData[13];

	usFileFRS = ucFileBlockData[14];
	usFileFRS |= ucFileBlockData[15] << 8;

	ucFileFAT = ucFileBlockData[16];

	usFileTRE = ucFileBlockData[17];
	usFileTRE |= ucFileBlockData[18] << 8;

	usFileSPF = ucFileBlockData[22];
	usFileSPF |= ucFileBlockData[23] << 8;

	if((ucFileSPC * usFileBPS) != 8192)//Block lengh
	{
		strcpy(ucErrMsg,“Block lengh is not 8192“);

		return 0;
	}

	ucFileMaxBlocksOfCals = (ucFileSPC * usFileBPS)/512;

	//root directory initialize
	if(!bOpenDir(0))
	{
		strcpy(ucErrMsg,“File format-Root dir“);

		return 0;
	}

	return 1;
}

bool cTxos::bOpenDir(unsigned short usCalusterNumber)
{
	unsigned int uiRamAddr;

	//root directory
	uiRamAddr = (usFileFRS+(usFileSPF * ucFileFAT))*usFileBPS;

	if(usCalusterNumber != 0)
		uiRamAddr += ((usCalusterNumber-2)*ucFileSPC*usFileBPS)+(usFileTRE*32);

	vDelayUS(10000);
	if(!bSDMMCReceiveBlock(uiRamAddr))
		return 0;

	for(usCalusterNumber=0; usCalusterNumber<512; usCalusterNumber++)
		ucFileDir[usCalusterNumber] = ucFileBlockData[usCalusterNumber];

	usFileEntryOffset = 0x0000; //First entry

	return 1;
}

Y en el siguiente programa se lee un archivo de tamaño ilimitado; Después de cada vez que se llenan las 256 celdas de memoria, los datos se leen nuevamente desde el principio de la tarjeta de memoria.

void cTxos::vReadDir()
{
	//File name 0x00
	ucFileName[0] = ucFileDir[usFileEntryOffset+0];//0x00:empty - 0xE5:deleted
	ucFileName[1] = ucFileDir[usFileEntryOffset+1];
	ucFileName[2] = ucFileDir[usFileEntryOffset+2];
	ucFileName[3] = ucFileDir[usFileEntryOffset+3];
	ucFileName[4] = ucFileDir[usFileEntryOffset+4];
	ucFileName[5] = ucFileDir[usFileEntryOffset+5];
	ucFileName[6] = ucFileDir[usFileEntryOffset+6];
	ucFileName[7] = ucFileDir[usFileEntryOffset+7];
	ucFileName[8] = '';

	//File type 0x08
	ucFileType[0] = ucFileDir[usFileEntryOffset+8];
	ucFileType[1] = ucFileDir[usFileEntryOffset+9];
	ucFileType[2] = ucFileDir[usFileEntryOffset+10];
	ucFileType[3] = '';

	//File first caluster 0x1A
	usFileOSR = ucFileDir[usFileEntryOffset+26];
	usFileOSR |= ucFileDir[usFileEntryOffset+27] << 8;

	usFileEntryOffset += 0x20; //Next entry

	//End of cache
	if(usFileEntryOffset == 0x200)
		usFileEntryOffset = 0x00; //First entry
}

bool cTxos::bOpenFile(unsigned short usCalusterNumber)
{
	unsigned short usX,
			usY,
			usFirstAddr = (usFileFRS*usFileBPS),
			usLastStart = usFirstAddr;

	vDelayUS(100);
	ucFileLastBlockOfCal = 0;
	ucFileLastCal = 0;
	usFileCalusters[0] = usCalusterNumber;
	usFileCalusters[255] = 0;
	usY = (usFileCalusters[0])*2;
	usFirstAddr = (usFileFRS*usFileBPS);
	usLastStart = usFirstAddr+(usY&0xfe00);

	if(!bSDMMCReceiveBlock(usLastStart))
		return 0;

	for(usX=0; usX<255;)
	{
		if(!((usFirstAddr+usY) >= usLastStart && (usFirstAddr+usY) < (usLastStart+512)))
		{ 
			usLastStart = usFirstAddr+(usY&0xfe00);

			if(!bSDMMCReceiveBlock(usLastStart))
				return 0;
		}
		usY = ucFileBlockData[(usY&0x01ff)]
			|(ucFileBlockData[(usY&0x01ff)+1]<<8);
		usX++;

		if(usY!=0xffff)
			usFileCalusters[usX] = usY;
		else
		{
			usFileCalusters[usX] = 0;

			break;
		}

		usY = (usFileCalusters[usX])*2;
	}

	return 1;
}

bool cTxos::bReadFile()
{ 
	vDelayUS(100);
	if(usFileCalusters[ucFileLastCal]==0)
		return 0;

	if(ucFileLastCal == 255)
		if(!bOpenFile(usFileCalusters[ucFileLastCal]))
			return 0;

	if(!bSDMMCReceiveBlock((( usFileFRS+(usFileSPF * ucFileFAT)+((usFileCalusters[ucFileLastCal]-2)*ucFileSPC) )*usFileBPS)+(usFileTRE*32)+(ucFileLastBlockOfCal*512)))
		return 0;

	if(ucFileLastBlockOfCal < ucFileMaxBlocksOfCals-1)
		ucFileLastBlockOfCal++;
	else
	{
		ucFileLastBlockOfCal = 0;
		ucFileLastCal++;
	}

	return 1;
}

void cTxos::vReadFileGoToAddr(unsigned int uiAddr)//512 bytes step - max 2MB offset from 0 in 8192 format
{
	ucFileLastCal = uiAddr/ucFileMaxBlocksOfCals;
	ucFileLastBlockOfCal = uiAddr%ucFileMaxBlocksOfCals;
}

La última función mueve la posición/ubicación de lectura de la memoria, el siguiente programa también muestra un ejemplo del uso de las funciones anteriores para leer imágenes en formato BMP-16bit-RGB-565:

bool cTxos::bDrawBMPFile(unsigned short usCalNumber)
{
	unsigned short usX;
	unsigned char ucY;

	if(!bOpenFile(usCalNumber))
		return 0;

	if(!bReadFile())
		return 0;

	if(ucFileBlockData[0]==0x42 && ucFileBlockData[1]==0x4d)
	{
		usCalNumber = ucFileBlockData[10]|(ucFileBlockData[11]<<8);

		for(ucY=240; ucY>0; )
		{
			ucY--;
			for(usX=0; usX<320;usX++)
			{
				if(usCalNumber == 512)
				{
					if(!bReadFile())
						return 0;

					usCalNumber = 0;
				}
				vPrintPixel(usX,ucY,ucFileBlockData[usCalNumber]|(ucFileBlockData[usCalNumber+1]<<8));
				usCalNumber+=2;
			}
		}

		return 1;
	}
	return 0;
}

***»»Proyectos de electrónica, programación y Arduino, incluidos códigos fuente, esquemas y planos de PCB para ingenieros, estudiantes y aficionados»»***

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

veinte − ocho =