MCU User Forum
  F340_USB problems

Post New Topic  Post A Reply
profile | register | preferences | faq | search

UBBFriend: Email This Page to Someone! next newest topic | next oldest topic
Author Topic:   F340_USB problems
vvjoy
New Member
posted August 17, 2010 07:03 AM     Click Here to See the Profile for vvjoy   Click Here to Email vvjoy     Edit/Delete Message
hello, I am not good at english, so I doubt if I can discrib my questions clearly.

Problems: I want trans some data into PC using F340's USB0. So, I edit the files under the folder D:\SiLabs\MCU\Examples\C8051F34x\USB_Interrupt\Firmware.

As a slave device, when USB0 doesnot receive any command from the PC, is it must keep idle state? But using BusHound, I find data trans on the usb data bus. why? How to edit the firmware, so the usb can work at: when pc command it to trans in the data, it trans, or it just do nothing.

Where I changed, I flaged with /////////,anyone help me , tanks a lot.

I edit two files: F34x_USB_ISR.c and F34x_USB_Main.c as following:

F34x_USB_Main.c:
///////////////////////////////////

#include
#include "F34x_USB_Register.h"
#include "F34x_USB_Main.h"
#include "F34x_USB_Descriptor.h"

//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F32x
//-----------------------------------------------------------------------------

sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter

//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------

sbit Led1 = P2^2; // LED='1' means ON
sbit Led2 = P2^3;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
bit DAT_RDY_FLAG = 0; // = 1 Data is already written to the IN_PACKET
// = 0 Data is not written to the IN_PACKET, or has send to the EP1's FIFO

BYTE DAT_WR_STATE = 0; //It is sued to desiding which part of the DAT_TEST send to IN_PACKET
////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define Sw1 0x01 // These are the port2 bits for Sw1
#define Sw2 0x02 // and Sw2 on the development board
BYTE Switch1State = 0; // Indicate status of switch
BYTE Switch2State = 0; // starting at 0 == off

BYTE Toggle1 = 0; // Variable to make sure each button
BYTE Toggle2 = 0; // press and release toggles switch

BYTE Potentiometer = 0x00; // Last read potentiometer value
BYTE Temperature = 0x00; // Last read temperature sensor value

idata BYTE Out_Packet[64]; // Last packet received from host
idata BYTE In_Packet[64]; // Next packet to sent to host

xdata unsigned char DAT_TEST[512];

code const BYTE TEMP_ADD = 112; // This constant is added to Temperature
//-----------------------------------------------------------------------------
// Main Routine
//-----------------------------------------------------------------------------
void main(void)
{
// unsigned int i;
int length = 37;
int i,j;

PCA0MD &= ~0x40; // Disable Watchdog timer

OSCILLATOR_Init(); // Initialize oscillator
PORT_Init(); // Initialize crossbar and GPIO
USB0_Init(); // Initialize USB0
Timer2_Init(); // Initialize Timer2
ADC0_Init(); // Initialize ADC0

for(i=0;i<512;i++)
{
DAT_TEST[i] = i;
}

while (1)
{
if(!DAT_RDY_FLAG)
{
In_Packet[0] = 0xBB; //开始
In_Packet[1] = m_btNo; //计数位
//In_Packet[2] = 0x02; //帧控制字
In_Packet[2] = DAT_WR_STATE;
In_Packet[3] = length; //帧长度

switch(DAT_WR_STATE)
{
case 0:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j];
}
DAT_RDY_FLAG = 1;
break;
case 1:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+32];
}
DAT_RDY_FLAG = 1;
break;
case 2:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+64];
}
DAT_RDY_FLAG = 1;
break;
case 3:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+96];
}
DAT_RDY_FLAG = 1;
break;
case 4:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+128];
}
DAT_RDY_FLAG = 1;
break;
case 5:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+160];
}
DAT_RDY_FLAG = 1;
break;
case 6:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+192];
}
DAT_RDY_FLAG = 1;
break;
case 7:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+224];
}
DAT_RDY_FLAG = 1;
break;
case 8:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+256];
}
DAT_RDY_FLAG = 1;
break;
case 9:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+288];
}
DAT_RDY_FLAG = 1;
break;
case 10:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+320];
}
DAT_RDY_FLAG = 1;
break;
case 11:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+352];
}
DAT_RDY_FLAG = 1;
break;
case 12:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+384];
}
DAT_RDY_FLAG = 1;
break;
case 13:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+416];
}
DAT_RDY_FLAG = 1;
break;
case 14:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+448];
}
DAT_RDY_FLAG = 1;
break;
case 15:
for(j=0;j<32;j++)
{
In_Packet[4+j] = DAT_TEST[j+480];
}
DAT_RDY_FLAG = 1;
break;
default: break;
}
In_Packet[36] = 0xEE; //结束
m_btNo++;
m_btNo = m_btNo&0xFF;
}
}
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Initialize the system clock and USB clock
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init(void)
{
#ifdef _USB_LOW_SPEED_

OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency and enable
// missing clock detector

CLKSEL = SYS_INT_OSC; // Select System clock
CLKSEL |= USB_INT_OSC_DIV_2; // Select USB clock
#else
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency and enable
// missing clock detector

CLKMUL = 0x00; // Select internal oscillator as
// input to clock multiplier

CLKMUL |= 0x80; // Enable clock multiplier
Delay(); // Delay for clock multiplier to begin
CLKMUL |= 0xC0; // Initialize the clock multiplier
Delay(); // Delay for clock multiplier to begin

while(!(CLKMUL & 0x20)); // Wait for multiplier to lock
CLKSEL = SYS_INT_OSC; // Select system clock
CLKSEL |= USB_4X_CLOCK; // Select USB clock
#endif /* _USB_LOW_SPEED_ */
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This function configures the crossbar and GPIO ports.
//
// P2.2 digital push-pull LED
// P2.3 digital push-pull LED
// P2.5 analog Potentiometer
//-----------------------------------------------------------------------------
void PORT_Init(void)
{
P2MDIN = 0xDF; // P2.5 set as analog input

P0MDOUT |= 0x0F; // P0 pins 0-3 set high impedance
P1MDOUT |= 0x0F; // P1 pins 0-3 set high impedance
P2MDOUT |= 0x0C; // P2 pins 0,1 set high impedance

P2SKIP = 0x20; // P2.5 skipped by crossbar

XBR0 = 0x00;
XBR1 = 0x40; // Enable Crossbar
}

//-----------------------------------------------------------------------------
// USB0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// - Initialize USB0
// - Enable USB0 interrupts
// - Enable USB0 transceiver
// - Enable USB0 with suspend detection
//-----------------------------------------------------------------------------
void USB0_Init(void)
{
BYTE Count;

// Set initial values of In_Packet and Out_Packet to zero
// Initialize here as opposed to above main() to prevent WDT reset
for (Count = 0; Count < 64; Count++)
{
Out_Packet[Count] = 0;
In_Packet[Count] = 0;
}

POLL_WRITE_BYTE(POWER, 0x08); // Force Asynchronous USB Reset
POLL_WRITE_BYTE(IN1IE, 0x07); // Enable Endpoint 0-2 in interrupts
POLL_WRITE_BYTE(OUT1IE, 0x07); // Enable Endpoint 0-2 out interrupts
POLL_WRITE_BYTE(CMIE, 0x07); // Enable Reset,Resume,Suspend interrupts
#ifdef _USB_LOW_SPEED_
USB0XCN = 0xC0; // Enable transceiver; select low speed
POLL_WRITE_BYTE(CLKREC, 0xA0); // Enable clock recovery; single-step mode
// disabled; low speed mode enabled
#else
USB0XCN = 0xE0; // Enable transceiver; select full speed
POLL_WRITE_BYTE(CLKREC, 0x80); // Enable clock recovery, single-step mode
// disabled
#endif // _USB_LOW_SPEED_

EIE1 |= 0x02; // Enable USB0 Interrupts
EA = 1; // Global Interrupt enable
// Enable USB0 by clearing the USB
// Inhibit bit
POLL_WRITE_BYTE(POWER, 0x01); // and enable suspend detection
}

//-----------------------------------------------------------------------------
// Timer2_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Timer 2 reload, used to check if switch pressed on overflow and
// used for ADC continuous conversion
//-----------------------------------------------------------------------------

void Timer2_Init(void)
{
TMR2CN = 0x00; // Stop Timer2; Clear TF2;

CKCON &= ~0xF0; // Timer2 clocked based on T2XCLK;
TMR2RL = 0; // Initialize reload value
TMR2 = 0xffff; // Set to reload immediately

ET2 = 1; // Enable Timer2 interrupts
TR2 = 1; // Start Timer2
}

//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configures ADC for single ended continuous conversion or Timer2
//-----------------------------------------------------------------------------

void ADC0_Init(void)
{
REF0CN = 0x0E; // Enable voltage reference VREF
AMX0P = 0x1E; // Positive input starts as temp sensor
AMX0N = 0x1F; // Single ended mode(neginput = gnd)

ADC0CF = 0xF8; // SAR Period 0x1F, Right adjusted

ADC0CN = 0xC2; // Continuous converion on timer 2
// overflow; low power tracking mode on

EIE1 |= 0x08; // Enable conversion complete interrupt
}

//-----------------------------------------------------------------------------
// Timer2_ISR
//-----------------------------------------------------------------------------
//
// Called when timer 2 overflows, check to see if switch is pressed,
// then watch for release.
//
//-----------------------------------------------------------------------------

void Timer2_ISR(void) interrupt 5
{
if (!(P2 & Sw1)) // Check for switch #1 pressed
{
if (Toggle1 == 0) // Toggle is used to debounce switch
{ // so that one press and release will
Switch1State = ~Switch1State; // toggle the state of the switch sent
Toggle1 = 1; // to the host
}
}
else Toggle1 = 0; // Reset toggle variable

if (!(P2 & Sw2)) // Same as above, but Switch2
{
if (Toggle2 == 0)
{
Switch2State = ~Switch2State;
Toggle2 = 1;
}
}
else Toggle2 = 0;

TF2H = 0; // Clear Timer2 interrupt flag
}

//-----------------------------------------------------------------------------
// ADC0_ConvComplete_ISR
//-----------------------------------------------------------------------------
//
// Called after a conversion of the ADC has finished
// Updates the appropriate variable for potentiometer or temperature sensor
// Switches the ADC multiplexor value to switch between the potentiometer
// and temp sensor
//
//-----------------------------------------------------------------------------

void ADC0_ConvComplete_ISR(void) interrupt 10
{
if (AMX0P == 0x1E) // This switches the AMUX between
{ // the temperature sensor and the
Temperature = ADC0L; // potentiometer pin after conversion
Temperature += TEMP_ADD; // Add offset to Temperature
AMX0P = 0x04; // switch to potentiometer
ADC0CF = 0xFC; // Place ADC0 in left-adjusted mode
}
else
{
Potentiometer = ADC0H;
AMX0P = 0x1E; // switch to temperature sensor
ADC0CF = 0xF8; // place ADC0 in right-adjusted mode
}

AD0INT = 0;
}

//-----------------------------------------------------------------------------
// Delay
//-----------------------------------------------------------------------------
//
// Used for a small pause, approximately 80 us in Full Speed,
// and 1 ms when clock is configured for Low Speed
//
//-----------------------------------------------------------------------------

void Delay(void)
{
int x;
for(x = 0;x < 500;x)
x++;
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

F34x_USB_ISR.c
///////////////////////////////////
#include "c8051F340.h"
#include "F34x_USB_Register.h"
#include "F34x_USB_Main.h"
#include "F34x_USB_Descriptor.h"

//-----------------------------------------------------------------------------
// Global Externs
//-----------------------------------------------------------------------------

extern idata BYTE OUT_PACKET[];
extern idata BYTE IN_PACKET[];

extern BYTE DAT_WR_STATE;
extern bit DAT_RDY_FLAG;

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

BYTE USB_State; // Holds the current USB State
// def. in F32x_USB_Main.h

setup_buffer Setup; // Buffer for current device request

unsigned int DataSize; // Size of data to return
unsigned int DataSent; // Amount of data sent so far
BYTE* DataPtr; // Pointer to data to return

// Holds the status for each endpoint
BYTE Ep_Status[3] = {EP_IDLE, EP_IDLE, EP_IDLE};


//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// USB0_ISR
//-----------------------------------------------------------------------------
//
// Called after any USB type interrupt, this handler determines which type
// of interrupt occurred, and calls the specific routine to handle it.
//
//-----------------------------------------------------------------------------
void USB0_ISR(void) interrupt 8 // Top-level USB ISR
{
BYTE bCommon, bIn, bOut;
POLL_READ_BYTE(CMINT, bCommon); // Read all interrupt registers
POLL_READ_BYTE(IN1INT, bIn); // this read also clears the register
POLL_READ_BYTE(OUT1INT, bOut);
{
if (bCommon & rbRSUINT) // Handle Resume interrupt
{
Usb_Resume();
}
if (bCommon & rbRSTINT) // Handle Reset interrupt
{
Usb_Reset();
}
if (bIn & rbEP0) // Handle Setup packet received
{ // or packet transmitted if Endpoint 0
Handle_Setup(); // is transmit mode
}
if (bIn & rbIN1) // Handle In Packet sent, put new data
{
// if(DAT_RDY_FLAG) // on endpoint 1 fifo
// {
Handle_In1();
// DAT_RDY_FLAG = 0;
// }
}
if (bOut & rbOUT2) // Handle Out packet received, take data
{ // off endpoint 2 fifo
Handle_Out2();
}
if (bCommon & rbSUSINT) // Handle Suspend interrupt
{
Usb_Suspend();
}
}
}

//-----------------------------------------------------------------------------
// Support Routines for ISR
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Usb_Reset
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// - Set state to default
// - Clear Usb Inhibit bit
//
//-----------------------------------------------------------------------------

void Usb_Reset(void)
{
USB_State = DEV_DEFAULT; // Set device state to default

POLL_WRITE_BYTE(POWER, 0x01); // Clear usb inhibit bit to enable USB
// suspend detection

Ep_Status[0] = EP_IDLE; // Set default Endpoint Status
Ep_Status[1] = EP_HALT;
Ep_Status[2] = EP_HALT;
}

//-----------------------------------------------------------------------------
// Handle_Setup
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// - Decode Incoming Setup requests
// - Load data packets on fifo while in transmit mode
//
//-----------------------------------------------------------------------------

void Handle_Setup(void)
{
BYTE ControlReg,TempReg; // Temporary storage for EP control
// register

POLL_WRITE_BYTE(INDEX, 0); // Set Index to Endpoint Zero
POLL_READ_BYTE(E0CSR, ControlReg); // Read control register

if (Ep_Status[0] == EP_ADDRESS) // Handle Status Phase of Set Address
// command
{
POLL_WRITE_BYTE(FADDR, Setup.wValue.c[LSB]);
Ep_Status[0] = EP_IDLE;
}

if (ControlReg & rbSTSTL) // If last packet was a sent stall, reset
{ // STSTL bit and return EP0 to idle state
POLL_WRITE_BYTE(E0CSR, 0);
Ep_Status[0] = EP_IDLE;
return;
}

if (ControlReg & rbSUEND) // If last setup transaction was ended
{ // prematurely then set
POLL_WRITE_BYTE(E0CSR, rbDATAEND);
POLL_WRITE_BYTE(E0CSR, rbSSUEND); // Serviced Setup End bit and return EP0
Ep_Status[0] = EP_IDLE; // to idle state
}

if (Ep_Status[0] == EP_IDLE) // If Endpoint 0 is in idle mode
{
if (ControlReg & rbOPRDY) // Make sure that EP 0 has an Out Packet ready from host
{ // although if EP0 is idle, this should always be the case
Fifo_Read(FIFO_EP0, 8, (BYTE *)&Setup);
// Get Setup Packet off of Fifo, it is currently Big-Endian

// Compiler Specific - these next three statements swap the
// bytes of the setup packet words to Big Endian so they
// can be compared to other 16-bit values elsewhere properly
Setup.wValue.i = Setup.wValue.c[MSB] + 256*Setup.wValue.c[LSB];
Setup.wIndex.i = Setup.wIndex.c[MSB] + 256*Setup.wIndex.c[LSB];
Setup.wLength.i = Setup.wLength.c[MSB] + 256*Setup.wLength.c[LSB];


switch(Setup.bRequest) // Call correct subroutine to handle each kind of
{ // standard request
case GET_STATUS:
Get_Status();
break;
case CLEAR_FEATURE:
Clear_Feature();
break;
case SET_FEATURE:
Set_Feature();
break;
case SET_ADDRESS:
Set_Address();
break;
case GET_DESCRIPTOR:
Get_Descriptor();
break;
case GET_CONFIGURATION:
Get_Configuration();
break;
case SET_CONFIGURATION:
Set_Configuration();
break;
case GET_INTERFACE:
Get_Interface();
break;
case SET_INTERFACE:
Set_Interface();
break;
default:
Force_Stall(); // Send stall to host if invalid request
break;
}
}
}

if (Ep_Status[0] == EP_TX) // See if the endpoint has data to transmit to host
{
if (!(ControlReg & rbINPRDY)) // Make sure you don't overwrite last packet
{
// Endpoint 0 transmit mode

POLL_READ_BYTE(E0CSR, ControlReg);
// Read control register

if ((!(ControlReg & rbSUEND)) || (!(ControlReg & rbOPRDY)))
// Check to see if Setup End or Out Packet received, if so
// do not put any new data on FIFO
{
TempReg = rbINPRDY; // Add In Packet ready flag to E0CSR bitmask

// Break Data into multiple packets if larger than Max Packet
if (DataSize >= EP0_PACKET_SIZE)
{
Fifo_Write(FIFO_EP0, EP0_PACKET_SIZE, (BYTE *)DataPtr);// Put Data on Fifo
DataPtr += EP0_PACKET_SIZE; // Advance data pointer
DataSize -= EP0_PACKET_SIZE; // Decrement data size
DataSent += EP0_PACKET_SIZE; // Increment data sent counter
}
else // If data is less than Max Packet size or zero
{
Fifo_Write(FIFO_EP0, DataSize, (BYTE *)DataPtr); // Put Data on Fifo
TempReg |= rbDATAEND; // Add Data End bit to bitmask
Ep_Status[0] = EP_IDLE; // Return EP 0 to idle state
}
if (DataSent == Setup.wLength.i)
// This case exists when the host requests an even multiple of
// your endpoint zero max packet size, and you need to exit
// transmit mode without sending a zero length packet
{
TempReg |= rbDATAEND; // Add Data End bit to mask
Ep_Status[0] = EP_IDLE; // and return Endpoint 0 to an idle state
}
POLL_WRITE_BYTE(E0CSR, TempReg); // Write mask to E0CSR
}
}
}
}

//-----------------------------------------------------------------------------
// Handle_In1
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine loads the current value from In_Packet on the Endpoint 1 fifo,
// after an interrupt is received from the last packet being transmitted
//
//-----------------------------------------------------------------------------

void Handle_In1()
{
BYTE ControlReg;

POLL_WRITE_BYTE(INDEX, 1); // Set index to endpoint 1 registers
POLL_READ_BYTE(EINCSR1, ControlReg); // Read contol register for EP 1

if (Ep_Status[1] == EP_HALT) // If endpoint is currently halted,
// send a stall
{
POLL_WRITE_BYTE(EINCSR1, rbInSDSTL);
}

else // Otherwise send last updated
// data to host
{
if (ControlReg & rbInSTSTL) // Clear sent stall if last packet
// returned a stall
{
POLL_WRITE_BYTE(EINCSR1, rbInCLRDT);
}

if (ControlReg & rbInUNDRUN) // Clear underrun bit if it was set
{
POLL_WRITE_BYTE(EINCSR1, 0x00);
}

// Put new data on Fifo
Fifo_Write(FIFO_EP1, EP1_PACKET_SIZE, (BYTE *)IN_PACKET);
////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
DAT_RDY_FLAG = 0; //*********************************//
if(DAT_WR_STATE == 15) //这里的几段是我添加的。
{
DAT_WR_STATE = 0; //DAT_RDY_FLAG = 1 数据准备好,但没有写入端点FIFO
} //DAT_RDY_FLAG = 0 数据没有准备好,或者已经写入端点FIFO
else //********************
{ //DAT_WR_STATE 的值决定要将实验数组DAT_TSET中的那一部分写入IN_PACKET
DAT_WR_STATE ++; //*********************************//
}
//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
POLL_WRITE_BYTE(EINCSR1, rbInINPRDY);

// Set In Packet ready bit, indicating
} // fresh data on Fifo 1
}

//-----------------------------------------------------------------------------
// Handle_Out2
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Take the received packet from the host off the fifo and put it into
// the Out_Packet array
//
//-----------------------------------------------------------------------------

void Handle_Out2()
{
BYTE Count = 0;
BYTE ControlReg;

POLL_WRITE_BYTE(INDEX, 2); // Set index to endpoint 2 registers
POLL_READ_BYTE(EOUTCSR1, ControlReg);

if (Ep_Status[2] == EP_HALT) // If endpoint is halted, send a stall
{
POLL_WRITE_BYTE(EOUTCSR1, rbOutSDSTL);
}

else // Otherwise read packet from host
{
if (ControlReg & rbOutSTSTL) // Clear sent stall bit if last packet
// was a stall
{
POLL_WRITE_BYTE(EOUTCSR1, rbOutCLRDT);
}

POLL_READ_BYTE(EOUTCNTL, Count);
if (Count != EP2_PACKET_SIZE) // If host did not send correct packet
// size, flush buffer
{
POLL_WRITE_BYTE(EOUTCNTL, rbOutFLUSH);
}
else // Otherwise get the data packet
{
Fifo_Read(FIFO_EP2, EP2_PACKET_SIZE, (BYTE*)OUT_PACKET);
}
POLL_WRITE_BYTE(EOUTCSR1, 0); // Clear Out Packet ready bit
}
}

//-----------------------------------------------------------------------------
// Usb_Suspend
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Enter suspend mode after suspend signalling is present on the bus
//
//-----------------------------------------------------------------------------

void Usb_Suspend(void)
{
// Put the device in a low power configuration

P0MDIN = 0x00; // Port 0 configured as analog input
P1MDIN = 0x00; // Port 1 configured as analog input
P2MDIN = 0x00; // Port 2 configured as analog input
P3MDIN = 0x00; // Port 3 configured as analog input

ADC0CN &= ~0x80; // Disable ADC0
REF0CN = 0x00; // Disable voltage reference

OSCICN |= 0x20; // Put oscillator

// When the device receives a non-idle USB event, it will resume execution
// on the instruction that follows OSCICN |= 0x20.

// Re-enable everything that was disabled when going into Suspend

P0MDIN = 0xFF; // Port 0 configured as digital pins
P1MDIN = 0x7F; // Port 1 pin 7 set as digital pin
P2MDIN = 0xFF; // Port 2 configured as digital pins
P3MDIN = 0xFF; // Port 3 configured as digital pins

REF0CN = 0x0E; // Enable voltage reference VREF
ADC0CN |= 0x80; // Re-enable ADC0
}

//-----------------------------------------------------------------------------
// Usb_Resume
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Resume normal USB operation
//
//-----------------------------------------------------------------------------

void Usb_Resume(void)
{
volatile int k;

k++;

// Add code for resume
}

//-----------------------------------------------------------------------------
// Fifo_Read
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) BYTE addr : target address
// 2) unsigned int uNumBytes : number of bytes to unload
// 3) BYTE * pData : read data destination
//
// Read from the selected endpoint FIFO
//
//-----------------------------------------------------------------------------

void Fifo_Read(BYTE addr, unsigned int uNumBytes, BYTE * pData)
{
int i;

if (uNumBytes) // Check if >0 bytes requested,
{
USB0ADR = (addr); // Set address
USB0ADR |= 0xC0; // Set auto-read and initiate
// first read

// Unload from the selected FIFO
for(i=0;i {
while(USB0ADR & 0x80); // Wait for BUSY->'0' (data ready)
pData[i] = USB0DAT; // Copy data byte
}

USB0ADR = 0; // Clear auto-read

while(USB0ADR & 0x80); // Wait for BUSY->'0' (data ready)
pData[i] = USB0DAT; // Copy data byte
}
}

//-----------------------------------------------------------------------------
// Fifo_Write
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) BYTE addr : target address
// 2) unsigned int uNumBytes : number of bytes to unload
// 3) BYTE * pData : location of source data
//
// Write to the selected endpoint FIFO
//
//-----------------------------------------------------------------------------

void Fifo_Write(BYTE addr, unsigned int uNumBytes, BYTE * pData)
{
int i;

// If >0 bytes requested,
if (uNumBytes)
{
while(USB0ADR & 0x80); // Wait for BUSY->'0'
// (register available)
USB0ADR = (addr); // Set address (mask out bits7-6)

// Write to the selected FIFO
for(i=0;i {
USB0DAT = pData[i];
while(USB0ADR & 0x80); // Wait for BUSY->'0' (data ready)
}

//DAT_RDY_FLAG = 0;
}
}

//-----------------------------------------------------------------------------
// Force_Stall
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Force a procedural stall to be sent to the host
//
//-----------------------------------------------------------------------------

void Force_Stall(void)
{
POLL_WRITE_BYTE(INDEX, 0);
POLL_WRITE_BYTE(E0CSR, rbSDSTL); // Set the send stall bit
Ep_Status[0] = EP_STALL; // Put the endpoint in stall status
}

//-----------------------------------------------------------------------------
// End Of File
//-

[This message has been edited by vvjoy (edited August 17, 2010).]

[This message has been edited by vvjoy (edited August 17, 2010).]

[This message has been edited by vvjoy (edited August 17, 2010).]

IP: Logged

Tsuneo
Member
posted August 26, 2010 02:00 AM     Click Here to See the Profile for Tsuneo   Click Here to Email Tsuneo     Edit/Delete Message
I don't recommend USB_Interrupt example for newly designed devices. The PC device driver has a couple of problems.
HID is better than USB_Interrupt. The functions of HID is a superset of USB_Interrupt. HID works with OS built-in class driver. You don't need to install PC device driver for HID.

HID examples are placed in this folder.
C:\SiLabs\MCU\Examples\C8051F34x\USB_HID\BlinkyExample

Also, this appnote gives you some introduction for HID.

AN249: Human Interface Device (HID) Tutorials
https://www.silabs.com/Support%20Documents/TechnicalDocs/AN249.pdf

This example always sends IN transactions, too.
But the control flow is much simpler than USB_Interrupt.
In this example, a packet is sent from the device, when SendPacket() is called. It is placed in the main loop.


F3xx_USB0_Main.c

void main(void)
{

System_Init ();
Usb_Init ();

EA = 1;

while (1)
{
if (BLINK_SELECTORUPDATE)
{
BLINK_SELECTORUPDATE = 0;
SendPacket (IN_BLINK_SELECTORID); // <------
}
}
}


Modify it, so that SendPacket() is called just when your firmware requires.

Tsuneo

[This message has been edited by Tsuneo (edited August 26, 2010).]

IP: Logged

All times are CT (US)

next newest topic | next oldest topic

Administrative Options: Close Topic | Archive/Move | Delete Topic
Post New Topic  Post A Reply
Hop to:

Contact Us | MCU User Forum

Have you seen our MCU Knowledge Base?


Ultimate Bulletin Board 5.47b