📄 usb.c
字号:
/*
Open Source BDM - USB communication
/* Prominent Notice-This software was modified from TBDML software - 12/05
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
*/
#include "hidef.h"
#include "MC68HC908JB16.h"
#include "commands.h"
#include "usb.h"
#include "led.h"
#include "cmd_processing.h"
#include "main.h"
/* Data transfer format: two possibilities exist
1. Bulk transfer over EP2 (non standard for low speed devices!)
Data format: 1 byte: size (of cmd+data)
1 byte: cmd
size-1 bytes: data
Returns at least one packet with status, but possibly more data depending on command executed.
When the data is returned the command has finished.
Start of transfer of another message into EP2 will discard any data ready to be transmitted back out of EP2
Performance: ~20kB/s, roundtrip (8B IN & 8B OUT) ~ 4ms
2. Control transfer over EP0 (standard approach and the only standard option for JB8/16)
Data format:
- Setup frame: bmRequestType = 0x41 if data is to be transfered to the device
bmRequestType = 0xC1 if data is to be transfered out of the device
bRequest = cmd
wValue.lo = data0
wValue.hi = data1
wIndex.lo = data2
wIndex.hi = data3
wLength.hi = 0
wLength.lo = # of bytes in data stage
cmd, data0-3 is always transferred from host to device.
If the command parameters fit into 4 bytes, bmRequestType = 0xC1 can be used to read results of the command being transferred
If more than 4 bytes of parameters are needed, bmRequestType = 0x41 is used and data5,... is transferred in data stage
New setup frame will discard any data ready to be transmitted out of the device
Performance: ~6.7kB/s, short command (5B IN, no data out) ~3ms, ave command (5B IN, 8B OUT) ~4ms, longer cmd (5B IN, 16B OUT) ~5ms
*/
/* global and static variables, buffers, etc. */
#pragma DATA_SEG Z_RAM
/* near variables (short addressing mode) */
static unsigned far char USB_State = US_ATTACHED;
unsigned char command_buffer[105]; /* buffer for Rx and Tx of commands & results (size: 16x8byte frame + 5bytes from setup frame + 1 byte for status + 1 byte for endian byte swap = 135) */
/* data is always received starting at command_buffer+1 and transmitted starting at command_buffer+0 */
/* this is to make sure that status of the last command is preserved when receving the next command from the host */
static unsigned char *usb_dptr; /* pointer to first empty location in buffer (Rx) or to hte first char to transmit (Tx) */
static unsigned char usb_ep0_dcntT; /* data count to transmit */
static unsigned char usb_ep0_dcntR; /* data count to receive */
static unsigned char usb_ep2_dcntT; /* data count to transmit */
static unsigned char usb_ep2_dcntR; /* data count to receive */
static unsigned char usb_ep0_zeroterm=0; /* when non-zero it tells the EP0 Tx routine to terminate transfers by zero-length packet because the host has requested more data than available */
static unsigned char led_timer=0; /* counter for timing the LED flashing */
led_state_e led_state; /* led state variable (BLINK, ON, OFF) */
#pragma DATA_SEG FAR_RAM
/* far variables */
#pragma DATA_SEG DEFAULT
/* USB descriptors */
const device_descriptor DeviceDesc = {
sizeof(device_descriptor), /* size */
DT_DEVICE, /* Descriptor Type (=1) */
{0x10, 0x01}, /* USB Spec Release Number in BCD = 1.10 */
0xff, /* Device Class Code (vendor specific) */
0xff, /* Device Subclass Code (vendor specific) */
0xff, /* Device Protocol Code (vendor specific) */
8, /* Maximum Packet Size for EP0 */
{0x25, 0x04}, /* Vendor ID - it is a Freescale micro, so lets use Freescale ID :-) */
{0x00, 0x10}, /* Product ID */
{0x01, 0x00}, /* Device Release Number in BCD */
1, /* Index of String Desc for Manufacturer */
2, /* Index of String Desc for Product */
2, /* Index of String Desc for SerNo */
1 /* Number of possible Configurations */
};
/* Configuration: Control EP0, Bulk IN EP2 & Bulk OUT EP2 */
/* Bulk transfers are not allowed for low speed devices by the spec, but seem to work and much faster! */
/* There will be several transactions per frame and the throughput is very high */
/* There are 2 options: either to use Bulk EP2 or Contol EP0 (in case Bulk on EP2 does not work on the specific machine) */
const struct {
configuration_descriptor ConfigDesc;
interface_descriptor InterfaceDesc0;
endpoint_descriptor Endpoint2INDesc;
endpoint_descriptor Endpoint2OUTDesc;
} config_data = {
{ /* configuration descriptor */
sizeof(configuration_descriptor), /* size */
DT_CONFIGURATION, /* Descriptor Type (=2) */
{sizeof(config_data),0x00}, /* Total Length of Data for this Configuration */
1, /* Number of Interfaces supported by this Configuration */
1, /* Designator Value for this Configuration */
2, /* Index of String Desc for this Configuration */
0x80, /* Bus powered, no wakeup */
150 /* Max. Power Consumption in this Configuration (in 2mA steps) = 250mA current for the target if needed... */
},
{ /* interface 0 descriptor (EP0) */
sizeof(interface_descriptor), /* size */
DT_INTERFACE, /* Descriptor Type (=4) */
0, /* Number of this Interface (0..) */
0, /* Alternative for this Interface (if any) */
2, /* No of EPs used by this IF (excl. EP0) */
0xff, /* IF Class Code */
0xff, /* Interface Subclass Code */
0xff, /* IF Protocol Code */
2 /* Index of String Desc for this Interface */
},
{ /* EP2 IN descriptor */
sizeof(endpoint_descriptor), /* size */
DT_ENDPOINT, /* Descriptor Type (=5) */
0x82, /* Endpoint Address (EP2) */
0x02, /* Bulk IN endpoint */
{0x08, 0x00}, /* Max. Endpoint Packet Size */
1 /* Polling Interval in frames/microframes */
},
{ /* EP2 OUT descriptor */
sizeof(endpoint_descriptor), /* size */
DT_ENDPOINT, /* Descriptor Type (=5) */
0x02, /* Endpoint Address (EP2) */
0x02, /* Bulk OUT endpoint */
{0x08, 0x00}, /* Max. Endpoint Packet Size */
1 /* Polling Interval in frames/microframes */
}
};
const char StringDesc0[]={0x04,DT_STRING,0x08,0x04,0x00}; /* Lang ID: 0x08 0x04 = 0x0408 = English (UK) */
const char StringDesc1[]="Freescale"; /* we are using Freescale VId so it is only fair to say that this is a Freescale product :-) */
const char StringDesc2[]="Open Source BDM v0.1"; /* product version */
const char * far const StringDescTable[]={StringDesc0,StringDesc1,StringDesc2}; /* pointers to the descriptors */
/* Functions */
/* copies data from flash to the zeropage buffer */
void copydown(unsigned char count, unsigned char * far src, unsigned char * dest) {
while(count--) *(dest++) = *(src++); /* copy data while count lasts... */
}
/* Copies string from flash to the zeropage buffer */
unsigned char copystring(unsigned char index, unsigned char * dest) {
unsigned char cnt=0;
const unsigned char * far src;
if (index) {
/* unicode copy */
if (index<(sizeof(StringDescTable)/2)) { /* if the string exists, copy it */
unsigned char * dest_orig=dest;
dest+=2;
src = StringDescTable[index];
while (*src) {
*(dest++) = *(src++); /* copy byte */
*(dest++) = 0; /* unicode */
cnt+=2; /* increment count */
}
cnt+=2; /* account for the header */
*(dest_orig++) = cnt; /* create the header */
*(dest_orig) = DT_STRING;
}
} else {
/* plain copy (string 0), it has the header already */
src = StringDescTable[0];
while (*src) {
*(dest++) = *(src++); /* copy byte */
cnt++; /* inrement count */
}
}
return(cnt);
}
/* 1ms tick */
/* handles general timing functions and blinks the LED */
void usb_1ms_tick(void) {
if (led_timer) { /* led is in the middle of blinking */
led_timer--; /* decrement the counter */
if (led_timer==LED_OFF_TIME) LED_SW_OFF; /* switch the led off when the counter hits the off treshold */
} else {
if (led_state==LED_ON) {
LED_SW_ON; /* switch it on */
} else if (led_state==LED_OFF) {
LED_SW_OFF; /* switch it off */
} else if (led_state==LED_BLINK) {
LED_SW_ON; /* switch it on */
led_state=LED_ON; /* change state to permanent ON */
led_timer=LED_BLINK_PERIOD; /* blink the LED once before it settles into the ON state */
}
}
}
/* EP0 Tx */
void USB_ep0_tx(void) {
UCR0_TX0E=0; /* disable EP0 transmitter */
UIR2_TXD0FR = 1; /* clear the interrupt flag to make sure the packet transmits */
if (usb_ep0_dcntT!=0xff) {
/* transmit data from the buffer (must be in Zero Page) */
UE0D0 = *(usb_dptr++); /* copy all 8 bytes, packet might be shorter than 8 bytes */
UE0D1 = *(usb_dptr++);
UE0D2 = *(usb_dptr++);
UE0D3 = *(usb_dptr++);
UE0D4 = *(usb_dptr++);
UE0D5 = *(usb_dptr++);
UE0D6 = *(usb_dptr++);
UE0D7 = *(usb_dptr++);
if ((usb_ep0_dcntT>8)||((usb_ep0_dcntT==8)&&(usb_ep0_zeroterm))) {
UCR0 = ((UCR0^UCR0_TOSEQ_MASK)&UCR0_TOSEQ_MASK) | UCR0_TX0E_MASK | UCR0_RX0E_MASK + 8; /* enable transmission on EP0, toggle DATA0/1, length 8 (more data in buffer) */
usb_ep0_dcntT-=8;
} else {
UCR0 = ((UCR0^UCR0_TOSEQ_MASK)&UCR0_TOSEQ_MASK) | UCR0_TX0E_MASK | UCR0_RX0E_MASK + usb_ep0_dcntT; /* enable transmission on EP0, toggle DATA0/1, length according to count */
usb_ep0_dcntT = 0xff; /* no more transmission the next time */
usb_ep0_zeroterm=0; /* just finished transmission, switch zero-length termination off */
}
} else {
/* there is no data to transmit, but the interrupt occured anyway - this must be a special case or end of transmit condition */
if ((USR0_SETUP)&&(((*(setup_packet*)&UE0D0).bmRequestType&0x60)==0)) {
/* the special case is a Setup frame of standard request which was received previously, now detemine what to do */
switch ((*(setup_packet*)&UE0D0).bRequest) {
case SET_ADDRESS:
UADDR = UADDR_USBEN_MASK | (*(setup_packet*)&UE0D0).wValue.lo; /* set the new address (confirmation of reception was just transmitted) */
if ((*(setup_packet*)&UE0D0).wValue.lo) USB_State = US_ADDRESSED; else USB_State = US_DEFAULT;
case CLEAR_FEATURE:
case SET_CONFIGURATION:
case GET_CONFIGURATION:
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -