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

📄 rlink.c

📁 一个烧写FLASH的软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*************************************************************************** *   Copyright (C) 2005 by Dominic Rath                                    * *   Dominic.Rath@gmx.de                                                   * *                                                                         * *   Copyright (C) 2007,2008 貀vind Harboe                                 * *   oyvind.harboe@zylin.com                                               * *                                                                         * *   Copyright (C) 2008 Rob Brown, Lou Deluxe                              * *   rob@cobbleware.com, lou.openocd012@fixit.nospammail.net               * *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * *   This program is distributed in the hope that it will be useful,       * *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * *   GNU General Public License for more details.                          * *                                                                         * *   You should have received a copy of the GNU General Public License     * *   along with this program; if not, write to the                         * *   Free Software Foundation, Inc.,                                       * *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             * ***************************************************************************/#ifdef HAVE_CONFIG_H#include "config.h"#endif/* system includes */#include <errno.h>#include <string.h>#include <usb.h>#include <stdint.h>/* project specific includes */#include "log.h"#include "types.h"#include "jtag.h"#include "configuration.h"#include "rlink.h"#include "st7.h"#include "ep1_cmd.h"#include "dtc_cmd.h"/* This feature is made useless by running the DTC all the time.  When automatic, the LED is on whenever the DTC is running.  Otherwise, USB messages are sent to turn it on and off. */#undef AUTOMATIC_BUSY_LED/* This feature may require derating the speed due to reduced hold time. */#undef USE_HARDWARE_SHIFTER_FOR_TMS#define INTERFACE_NAME		"RLink"#define USB_IDVENDOR		(0x138e)#define USB_IDPRODUCT		(0x9000)#define USB_EP1OUT_ADDR		(0x01)#define USB_EP1OUT_SIZE		(16)#define USB_EP1IN_ADDR		(USB_EP1OUT_ADDR | 0x80)#define USB_EP1IN_SIZE		(USB_EP1OUT_SIZE)#define USB_EP2OUT_ADDR		(0x02)#define USB_EP2OUT_SIZE		(64)#define USB_EP2IN_ADDR		(USB_EP2OUT_ADDR | 0x80)#define USB_EP2IN_SIZE		(USB_EP2OUT_SIZE)#define USB_EP2BANK_SIZE	(512)#define USB_TIMEOUT_MS		(3 * 1000)#define DTC_STATUS_POLL_BYTE	(ST7_USB_BUF_EP0OUT + 0xff)/* Symbolic names for some pins */#define ST7_PA_NJTAG_TRST		ST7_PA1#define ST7_PA_NRLINK_RST		ST7_PA3#define ST7_PA_NLINE_DRIVER_ENABLE	ST7_PA5/* mask for negative-logic pins */#define ST7_PA_NUNASSERTED	(0	\	| ST7_PA_NJTAG_TRST	\	| ST7_PA_NRLINK_RST	\	| ST7_PA_NLINE_DRIVER_ENABLE	\)#define ST7_PD_NBUSY_LED		ST7_PD0#define ST7_PD_NERROR_LED		ST7_PD1#define ST7_PD_NRUN_LED			ST7_PD7#define ST7_PE_ADAPTER_SENSE_IN		ST7_PE3#define ST7_PE_ADAPTER_SENSE_OUT	ST7_PE4static usb_dev_handle *pHDev;/* * ep1 commands are up to USB_EP1OUT_SIZE bytes in length. * This function takes care of zeroing the unused bytes before sending the packet. * Any reply packet is not handled by this function. */staticintep1_generic_commandl(	usb_dev_handle	*pHDev,	size_t		length,	...) {	uint8_t		usb_buffer[USB_EP1OUT_SIZE];	uint8_t		*usb_buffer_p;	va_list		ap;	int		usb_ret;	if(length > sizeof(usb_buffer)) {		length = sizeof(usb_buffer);	}	usb_buffer_p = usb_buffer;	va_start(ap, length);	while(length > 0) {		*usb_buffer_p++ = va_arg(ap, int);		length--;	}		memset(		usb_buffer_p,		0,		sizeof(usb_buffer) - (usb_buffer_p - usb_buffer)	);	usb_ret = usb_bulk_write(		pHDev,		USB_EP1OUT_ADDR,		(char *)usb_buffer, sizeof(usb_buffer),		USB_TIMEOUT_MS	);	return(usb_ret);}#if 0staticssize_tep1_memory_read(	usb_dev_handle	*pHDev,	uint16_t	addr,	size_t		length,	uint8_t		*buffer) {	uint8_t		usb_buffer[USB_EP1OUT_SIZE];	int		usb_ret;	size_t		remain;	ssize_t		count;	usb_buffer[0] = EP1_CMD_MEMORY_READ;	memset(		usb_buffer + 4,		0,		sizeof(usb_buffer) - 4	);	remain = length;	count = 0;	while(remain) {		if(remain > sizeof(usb_buffer)) {			length = sizeof(usb_buffer);		} else {			length = remain;		}		usb_buffer[1] = addr >> 8;		usb_buffer[2] = addr;		usb_buffer[3] = length;      		usb_ret = usb_bulk_write(			pHDev, USB_EP1OUT_ADDR,			usb_buffer, sizeof(usb_buffer),			USB_TIMEOUT_MS		);		if(usb_ret < sizeof(usb_buffer)) {			break;		}				usb_ret = usb_bulk_read(			pHDev, USB_EP1IN_ADDR,			buffer, length,			USB_TIMEOUT_MS		);		if(usb_ret < length) {			break;		}				addr += length;		buffer += length;		count += length;		remain -= length;	}	return(count);}#endifstaticssize_tep1_memory_write(	usb_dev_handle	*pHDev,	uint16_t	addr,	size_t		length,	uint8_t	const	*buffer) {	uint8_t		usb_buffer[USB_EP1OUT_SIZE];	int		usb_ret;	size_t		remain;	ssize_t		count;	usb_buffer[0] = EP1_CMD_MEMORY_WRITE;	remain = length;	count = 0;	while(remain) {		if(remain > (sizeof(usb_buffer) - 4)) {			length = (sizeof(usb_buffer) - 4);		} else {			length = remain;		}		usb_buffer[1] = addr >> 8;		usb_buffer[2] = addr;		usb_buffer[3] = length;		memcpy(			usb_buffer + 4,			buffer,			length		);		memset(			usb_buffer + 4 + length,			0,			sizeof(usb_buffer) - 4 - length		);      		usb_ret = usb_bulk_write(			pHDev, USB_EP1OUT_ADDR,			(char *)usb_buffer, sizeof(usb_buffer),			USB_TIMEOUT_MS		);		if(usb_ret < sizeof(usb_buffer)) {			break;		}				addr += length;		buffer += length;		count += length;		remain -= length;	}	return(count);}#if 0staticssize_tep1_memory_writel(	usb_dev_handle	*pHDev,	uint16_t	addr,	size_t		length,	...) {	uint8_t		buffer[USB_EP1OUT_SIZE - 4];	uint8_t		*buffer_p;	va_list		ap;	size_t		remain;	if(length > sizeof(buffer)) {		length = sizeof(buffer);	}	remain = length;	buffer_p = buffer;	va_start(ap, length);	while(remain > 0) {		*buffer_p++ = va_arg(ap, int);		remain--;	}	return(ep1_memory_write(pHDev, addr, length, buffer));}#endif#define DTCLOAD_COMMENT		(0)#define DTCLOAD_ENTRY		(1)#define DTCLOAD_LOAD		(2)#define DTCLOAD_RUN			(3)#define DTCLOAD_LUT_START	(4)#define DTCLOAD_LUT			(5)#define DTC_LOAD_BUFFER		ST7_USB_BUF_EP2UIDO/* This gets set by the DTC loader */static uint8_t dtc_entry_download;/* The buffer is specially formatted to represent a valid image to load into the DTC. */staticintdtc_load_from_buffer(	usb_dev_handle	*pHDev,	const u8		*buffer,	size_t			length) {	struct header_s {		u8	type;		u8	length;	};	int				usb_err;	struct header_s	*header;	u8				lut_start = 0xc0;	dtc_entry_download = 0;	/* Stop the DTC before loading anything. */	usb_err = ep1_generic_commandl(		pHDev, 1,		EP1_CMD_DTC_STOP	);	if(usb_err < 0) return(usb_err);	while(length) {		if(length < sizeof(*header)) {			LOG_ERROR("Malformed DTC image\n");			exit(1);		}				header = (struct header_s *)buffer;		buffer += sizeof(*header);		length -= sizeof(*header);		if(length < header->length + 1) {			LOG_ERROR("Malformed DTC image\n");			exit(1);		}				switch(header->type) {			case DTCLOAD_COMMENT:				break;			case DTCLOAD_ENTRY:				/* store entry addresses somewhere */				if(!strncmp("download", (char *)buffer + 1, 8)) {					dtc_entry_download = buffer[0];				}				break;			case DTCLOAD_LOAD:   				/* Send the DTC program to ST7 RAM. */				usb_err = ep1_memory_write(					pHDev,					DTC_LOAD_BUFFER,					header->length + 1, buffer				);				if(usb_err < 0) return(usb_err);				/* Load it into the DTC. */				usb_err = ep1_generic_commandl(					pHDev, 3,					EP1_CMD_DTC_LOAD,						(DTC_LOAD_BUFFER >> 8),						DTC_LOAD_BUFFER				);				if(usb_err < 0) return(usb_err);				break;			case DTCLOAD_RUN:				usb_err = ep1_generic_commandl(					pHDev, 3,					EP1_CMD_DTC_CALL,						buffer[0],					EP1_CMD_DTC_WAIT				);				if(usb_err < 0) return(usb_err);				break;			case DTCLOAD_LUT_START:				lut_start = buffer[0];				break;					case DTCLOAD_LUT:   				usb_err = ep1_memory_write(					pHDev,					ST7_USB_BUF_EP0OUT + lut_start,					header->length + 1, buffer				);				if(usb_err < 0) return(usb_err);				break;			default:				LOG_ERROR("Invalid DTC image record type: 0x%02x\n", header->type);				exit(1);				break;		}				buffer += (header->length + 1);		length -= (header->length + 1);	}	return(0);}/* * Start the DTC running in download mode (waiting for 512 byte command packets on ep2). */staticintdtc_start_download(void) {	int	usb_err;	u8	ep2txr;	/* set up for download mode and make sure EP2 is set up to transmit */	usb_err = ep1_generic_commandl(		pHDev, 7,		 		EP1_CMD_DTC_STOP,		EP1_CMD_SET_UPLOAD,		EP1_CMD_SET_DOWNLOAD,		EP1_CMD_MEMORY_READ,	/* read EP2TXR for its data toggle */			ST7_EP2TXR >> 8,			ST7_EP2TXR,			1	);	if(usb_err < 0) return(usb_err);	/* read back ep2txr */	usb_err = usb_bulk_read(		pHDev, USB_EP1IN_ADDR,		(char *)&ep2txr, 1,		USB_TIMEOUT_MS	);	if(usb_err < 0) return(usb_err);	usb_err = ep1_generic_commandl(		pHDev, 13,		 		EP1_CMD_MEMORY_WRITE,	/* preinitialize poll byte */			DTC_STATUS_POLL_BYTE >> 8,			DTC_STATUS_POLL_BYTE,			1,			0x00,		EP1_CMD_MEMORY_WRITE,	/* set EP2IN to return data */			ST7_EP2TXR >> 8,			ST7_EP2TXR,			1,			(ep2txr & ST7_EP2TXR_DTOG_TX) | ST7_EP2TXR_STAT_VALID,		EP1_CMD_DTC_CALL,	/* start running the DTC */			dtc_entry_download,		EP1_CMD_DTC_GET_CACHED_STATUS	);	if(usb_err < 0) return(usb_err);	/* wait for completion */	usb_err = usb_bulk_read(		pHDev, USB_EP1IN_ADDR,		(char *)&ep2txr, 1,		USB_TIMEOUT_MS	);	return(usb_err);}staticintdtc_run_download(	usb_dev_handle	*pHDev,	u8	*command_buffer,	int	command_buffer_size,	u8	*reply_buffer,	int	reply_buffer_size) {	u8	ep2_buffer[USB_EP2IN_SIZE];	int	usb_err;	int	i;	LOG_DEBUG(": %d/%d\n", command_buffer_size, reply_buffer_size);	usb_err = usb_bulk_write(		pHDev,		USB_EP2OUT_ADDR,		(char *)command_buffer, USB_EP2BANK_SIZE,		USB_TIMEOUT_MS	);	if(usb_err < 0) return(usb_err);	/* Wait for DTC to finish running command buffer */	for(i = 5;;) {		usb_err = ep1_generic_commandl(			pHDev, 4,			EP1_CMD_MEMORY_READ,				DTC_STATUS_POLL_BYTE >> 8,				DTC_STATUS_POLL_BYTE,				1		);		if(usb_err < 0) return(usb_err);		usb_err = usb_bulk_read(			pHDev,			USB_EP1IN_ADDR,			(char *)ep2_buffer, 1,			USB_TIMEOUT_MS		);		if(usb_err < 0) return(usb_err);		if(ep2_buffer[0] & 0x01) break;		if(!--i) {			LOG_ERROR("%s, %d: too many retries waiting for DTC status\n",				__FILE__, __LINE__			);			return(-ETIMEDOUT);		}	}	if(!reply_buffer) reply_buffer_size = 0;	if(reply_buffer_size) {		usb_err = usb_bulk_read(			pHDev,			USB_EP2IN_ADDR,			(char *)ep2_buffer, sizeof(ep2_buffer),			USB_TIMEOUT_MS		);		if(usb_err < (int)sizeof(ep2_buffer)) {			LOG_ERROR("%s, %d: Read of endpoint 2 returned %d\n",				__FILE__, __LINE__, usb_err			);			return(usb_err);		}		memcpy(reply_buffer, ep2_buffer, reply_buffer_size);	}	return(usb_err);}/* * The dtc reply queue is a singly linked list that describes what to do with the reply packet that comes from the DTC.  Only SCAN_IN and SCAN_IO generate these entries. */typedefstruct dtc_reply_queue_entry_s {	struct dtc_reply_queue_entry_s	*next;	jtag_command_t	*cmd;	/* the command that resulted in this entry */	struct {		u8		*buffer;	/* the scan buffer */		int		size;		/* size of the scan buffer in bits */		int		offset;		/* how many bits were already done before this? */		int		length;		/* how many bits are processed in this operation? */		enum scan_type	type;		/* SCAN_IN/SCAN_OUT/SCAN_IO */	} scan;} dtc_reply_queue_entry_t;/* * The dtc_queue consists of a buffer of pending commands and a reply queue. * rlink_scan and tap_state_run add to the command buffer and maybe to the reply queue. */staticstruct {	dtc_reply_queue_entry_t	*rq_head;	dtc_reply_queue_entry_t	*rq_tail;	int			cmd_index;	int			reply_index;	u8			cmd_buffer[USB_EP2BANK_SIZE];} dtc_queue;/* * The tap state queue is for accumulating TAP state changes wiithout needlessly flushing the dtc_queue.  When it fills or is run, it adds the accumulated bytes to the dtc_queue. */staticstruct {	int	length;	u32	buffer;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -