INTEL (Altera) USB Byte Blaster auf STM32

Wenn ein Gerät über eine programmierbare Logik verfügt, ist häufig auch ein Prozessor / Mikrocontroller vorhanden.





Irgendwann hatte ich es satt, den JTAG-Anschluss auf den Platinen zu verdrahten, er nimmt viel Platz auf der Platine ein und wird tatsächlich nur für die Entwicklung benötigt. Im Endgerät ist dies völlig unnötig.





Sehr oft benutze ich SignalTap II Logic Analyzer, um die Richtigkeit der Implementierung des Verilog-Codes zu überprüfen, oder allgemein, um zu sehen, wie die Signalgeber laufen. Die Sache ist bequem und intuitiv. Ich denke, viele werden sie sofort am Bild erkennen:





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
      
      







, :





Und wir verbinden unser Gerät mit USB.





Und das hat bestimmt nichts zu bedeuten. Da die Installation nur auf der Grundlage des Gerätedeskriptors erfolgt, überprüfen wir nun, ob dies wirklich ein "echter" Byte Blaster ist.





Wir wählen:





Starten Sie den JTAG Chain Debugger:





Funktioniert !!! Wir können CPLD direkt an Bord unseres Geräts schreiben.





Wenn Sie diese Implementierung mit FPGA verbinden, ist übrigens eine Aufzeichnung mit FPGA und SignalTap II verfügbar. Das ist alles was ich sagen wollte.









Vielen Dank für Ihre Aufmerksamkeit! Viel Glück im Geschäft und gute Laune!








All Articles