INTEL (Altera) USB Byte Blaster en STM32

A menudo, si un dispositivo tiene lógica programable, también está presente un procesador / microcontrolador.





En algún momento me cansé de cablear el conector JTAG en las placas, ocupa mucho espacio en la placa y, de hecho, solo es necesario para el desarrollo. En el dispositivo final, es completamente innecesario.





Muy a menudo uso SignalTap II Logic Analyzer para comprobar la veracidad de la implementación del código Verilog, o en general "para ver cómo se están ejecutando los señalizadores", la cosa es cómoda e intuitiva, creo que muchos lo reconocerán inmediatamente por la imagen:





JTAG?





CPLD .





.





STM32F103RCT6 USB Byte Blaster. CPLD EPM3064.





, :





PC12->TDI





PC13->TMS





PC14->TCK





PC15->TDO





USB , :





USB Descriptor
/* USB Standard Device Descriptor */
const BYTE USB_DeviceDescriptor[] = {
  USB_DEVICE_DESC_SIZE,              /* bLength */
  USB_DEVICE_DESCRIPTOR_TYPE,        /* bDescriptorType */
  WBVAL(0x0110), /* 1.10 */          /* bcdUSB */
    0x00,                   // Class Code
    0x00,                   // Subclass code
    0x00,                   // Protocol code
    USB_MAX_PACKET0,          // Max packet size for EP0, see usbcfg.h
  WBVAL(0x09FB),                     /* idVendor */
  WBVAL(0x6001),                     /* idProduct */
  WBVAL(0x0400), /* 1.00 */          /* bcdDevice */
    0x01,                   // Manufacturer string index
    0x02,                   // Product string index
    0x03,                   // Device serial number string index
    0x01                    // Number of possible configurations	
};

/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const BYTE USB_ConfigDescriptor[] = {
    /* Configuration Descriptor */
  USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
/* Configuration 1 */
  WBVAL(                            /* wTotalLength */
    (1*USB_CONFIGUARTION_DESC_SIZE) +
    (1*USB_INTERFACE_DESC_SIZE) +
    (2*USB_ENDPOINT_DESC_SIZE)
  ),
    1,                      // Number of interfaces in this cfg
    1,                      // Index value of this configuration
    0,                      // Configuration string index
  USB_CONFIG_SELF_POWERED, /*|*/       /* bmAttributes */
  USB_CONFIG_POWER_MA(80),          /* bMaxPower */

    /* Interface Descriptor */
  USB_INTERFACE_DESC_SIZE,           /* bLength */
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
/* Interface 0, Alternate Setting 0, MSC Class */
  0x00,                              /* bInterfaceNumber */
  0x00,                              /* bAlternateSetting */
  0x02,                              /* bNumEndpoints */
    0xFF,                   // Class code
    0xFF,                   // Subclass code
    0xFF,                   // Protocol code
    0,                      // Interface string index
    
    /* Endpoint Descriptor */
/* Bulk In Endpoint */
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  USB_ENDPOINT_IN(BLST_EP_IN & 0x0F),                /* bEndpointAddress */
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
  WBVAL(BLST_MAX_PACKET),                     /* wMaxPacketSize */
    10,                         //Interval
    
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  USB_ENDPOINT_OUT(BLST_EP_OUT & 0x0F),               /* bEndpointAddress */
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
  WBVAL(BLST_MAX_PACKET),                     /* wMaxPacketSize */
    10                          //Interval	
/* Terminator */
  ,0                                  /* bLength */
};

//Language code string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={
sizeof(sd000),USB_STRING_DESCRIPTOR_TYPE,{0x0409}};

//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[6];}sd001={
sizeof(sd001),USB_STRING_DESCRIPTOR_TYPE,
{'A','l','t','e','r','a'}};

//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[11];}sd002={
sizeof(sd002),USB_STRING_DESCRIPTOR_TYPE,
{'U','S','B','-','B','l','a','s','t','e','r'}};

//Serial string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[8];}sd003={
sizeof(sd003),USB_STRING_DESCRIPTOR_TYPE,
{'0','0','0','0','0','0','0','0'}};

//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]=
{
    (ROM BYTE *)&USB_ConfigDescriptor
};
//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]=
{
    (ROM BYTE *)&sd000,
    (ROM BYTE *)&sd001,
    (ROM BYTE *)&sd002,
    (ROM BYTE *)&sd003
};

/* USB String Descriptor (optional) */
const BYTE *USB_StringDescriptor = (const BYTE *)USB_SD_Ptr;
      
      







"" Byte Blaster'a:





blaster.c
BYTE fifo_wp,fifo_rp;
BYTE InFIFO[256];

BYTE nCS = 0;

DWORD PacketPos = 0;
BYTE InPacket[64];
BYTE OutPacket[128];
BYTE ep1_ready = 1;

void EP2CallBack(void)
{
	ProcBlasterData();
}

void ProcBlasterData(void)
{
	int bufptr = 0;
	static BYTE jtag_byte = 0, read = 0, aser_byte = 0;
	DWORD recv_byte;
	BYTE acc0, acc1;
	
	recv_byte = USB_ReadEP(BLST_EP_OUT, OutPacket);

	bufptr = 0;
	
	if(!recv_byte) return;
	LED_RD_ON();
	
	do
	{
		if (jtag_byte)
		{
			if (!read)
			{
				do
				{

					acc0 = OutPacket[bufptr++];
					JTAG_Write(acc0);
					jtag_byte--;
					recv_byte--;
				} while (jtag_byte && recv_byte);
			}
			else
			{
				do
				{

					acc0 = OutPacket[bufptr++];
					acc1 = JTAG_RW(acc0);
					enqueue(acc1);
					jtag_byte--;
					recv_byte--;
				} while (jtag_byte&&recv_byte);
			}

		}
		else if (aser_byte)
		{
			if (!read)
			{

				do
				{

					acc0 = OutPacket[bufptr++];
					JTAG_Write(acc0);
					aser_byte--;
					recv_byte--;
				} while (aser_byte&&recv_byte);
			}
			else
			{
				do {
					acc0 = OutPacket[bufptr++];
					acc1 = ASer_RW(acc0);
					enqueue(acc1);
					aser_byte--;
					recv_byte--;
				} while (aser_byte&&recv_byte);
			}
		}
		else
		{
			do
			{
				acc0 = OutPacket[bufptr++];
				_bitcopy(bitmask(acc0, 6), read);
				if (bitmask(acc0, 7))
				{		//EnterSerialMode
					LTCK(0);		//bug fix
					
					if (nCS & 0x8) 
					{	//nCS=1:JTAG
						jtag_byte = acc0 & 0x3F;
					}
					else 
					{		//nCS=0:ActiveSerial
						aser_byte = acc0 & 0x3F;
					}
					/* Always JTAG Made */
					recv_byte--;
					break;
				}
				else
				{			//BitBangMode
					OUTP(acc0);
					if (read) {
						acc1 = 0;
						if (PADO) acc1 |= 0x02;
						if (PTDO) acc1 |= 0x01;
						enqueue(acc1);
					}
					recv_byte--;
				}
			} while (recv_byte);
		}
	} while (recv_byte);

	/* Disable RD LED */
	LED_RD_OFF();
	return;
}

void EP1CallBack(void)
{
	ep1_ready = 1;

	return;
}

void OUTP(BYTE b)
{
	unsigned int uiPortState = GPIOC->ODR;
	/* 	TCK - 0
			TMS - 1
			nCE - 2
			nCS - 3
	x - 5,6
			TDI - 4,7
	*/
	if(b & (1 << 3)) /* nCS */
		nCS = 0x08;
	else
		nCS = 0;
	
	if(b & (1 << 0)) /* TCK */
		uiPortState |= (1 << 14);
	else
		uiPortState &= ~(1 << 14);

	if(b & (1 << 1)) /* TMS */
		uiPortState |= (1 << 13);
	else
		uiPortState &= ~(1 << 13);

	if(b & (1 << 4)) /* TDI */
		uiPortState |= (1 << 12);
	else
		uiPortState &= ~(1 << 12);
	
	GPIOC->ODR = uiPortState;
	
//	Nop();
	
	return;
}

void JTAG_Write(BYTE a) 
{
	int i;
	
	for(i = 0;i < 8;i ++)
	{
		bitcopy(a & (0x01 << i),LTDI);
		tck();
	}
}

BYTE JTAG_RW(BYTE a)
{
	BYTE bRet=0;
	int i = 0;
	
	for(i = 0;i < 8;i++)
	{
		bitcopy(a & (0x01 << i),LTDI);
		if(PTDO) bRet |= (0x01 << i);
		tck();
	}
	
	return bRet;
}

BYTE ASer_RW(BYTE a) {
	BYTE bRet=0;
	int i = 0;
	
	for(i = 0;i < 8;i++)
	{
		bitcopy(a & (0x01 << 1),LTDI);
		if(PADO) bRet|= (0x01 << 1);
		tck();
	}		
	
	return bRet;
}

extern USB_EP_DATA EP0Data;
BYTE bBuffer[10];

void USB_EP0BlasterReq(USB_SETUP_PACKET *SetupPacket)
{
	BYTE bIndex;

	if (SetupPacket->bmRequestType.BM.Dir == 0)
	{	//0utput
		//Responce by sending zero-length packet
		//I don't know if this way is right, but working:)
		USB_WriteEP(0x80, NULL, 0);
		return;
	}

	if (SetupPacket->bRequest == 0x90)
	{
		bIndex = (SetupPacket->wIndex.WB.L << 1) & 0x7E;
		bBuffer[0] = eeprom_read(bIndex);
		bBuffer[1] = eeprom_read(bIndex + 1);
	}
	else
	{
		bBuffer[0] = 0x36;
		bBuffer[1] = 0x83;
	}

	EP0Data.pData = bBuffer;
	EP0Data.Count = 2;
	//		USB_WriteEP(0x80, bBuffer, 2);

	return;
}

      
      







. , main() .





:





main.c
  while (1) 
	{
		if(USB_Configuration)
		{
			if(ep1_ready)
			{
				acc0 = fifo_used();
				if (62 <= acc0) 
				{		//send full packet to host
					LED_WR_ON();
					ep1_ready = 0;
					dequeue(&InPacket[2], 62);
					USB_WriteEP(BLST_EP_IN, InPacket, 64);
					ChargeTimer_ms(10);
				}
				else if(acc0 || IsTimerArrived())
				{
					if(acc0)
						LED_WR_ON();
					else						
						LED_WR_OFF();
					ep1_ready = 0;
					if(acc0)
						dequeue(&InPacket[2], acc0);
					USB_WriteEP(BLST_EP_IN, InPacket, acc0 + 2);
					ChargeTimer_ms(10);
				}
			}
		}
  } // end while
      
      







, :





Y conectamos nuestro dispositivo a USB.





Y eso ciertamente no significa nada. Debido a que la instalación se lleva a cabo solo sobre la base del descriptor del dispositivo, ahora verifiquemos si este es realmente un Byte Blaster "real".





Nosotros elegimos:





E inicie el depurador de cadena JTAG:





¡¡¡Trabajos!!! Podemos escribir CPLD directamente a bordo de nuestro dispositivo.





Por cierto, si conecta esta implementación a FPGA, estará disponible la grabación en FPGA y SignalTap II. Eso es todo lo que quería decir.









¡Gracias por la atención! ¡Buena suerte en los negocios y buen humor!








All Articles