![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
monyno
Joined: 24 Sep 2012 Posts: 4
|
How to use USB interrupts |
Posted: Mon Sep 24, 2012 10:21 am |
|
|
Hi to all, this is my first post; please don't tell to check in other posts because I've just looked for my problem without results.
I want to read data with USB interrupt. The function void USB_isr() is defined in pic18_usb.c in this way:
Code: |
/*****************************************************************************
/* usb_handle_interrupt()
/*
/* Summary: Checks the interrupt, and acts upon event. Processing finished
/* tokens is the majority of this code, and is handled by usb.c
/*
/* NOTE: If you wish to change to a polling method (and not an interrupt
/* method), then you must call this function rapidly. If there is more
/* than 10ms latency the PC may think the USB device is stalled and
/* disable it.
/* To switch to a polling method, remove the #int_usb line above this
/* fuction. Also, goto usb_init() and remove the code that enables the
/* USB interrupt.
/******************************************************************************/
#if !defined(USB_ISR_POLLING) && !defined(USB_NO_ISR_PREPROCESSOR)
#int_usb NOCLEAR
#endif
void usb_isr(void)
{
unsigned int8 TRNAttempts;
clear_interrupt(INT_USB);
if (usb_state == USB_STATE_DETACHED) return; //should never happen, though
if (UIR)
{
debug_usb(debug_putc,"\r\n\n[%X] ",UIR);
//activity detected. (only enable after sleep)
if (UIR_ACTV && UIE_ACTV) {usb_isr_activity();}
if (UCON_SUSPND) return;
if (UIR_STALL && UIE_STALL) {usb_isr_stall();} //a stall handshake was sent
if (UIR_UERR && UIE_UERR) {usb_isr_uerr();} //error has been detected
if (UIR_URST && UIE_URST) {usb_isr_rst();} //usb reset has been detected
if (UIR_IDLE && UIE_IDLE) {usb_isr_uidle();} //idle time, we can go to sleep
if (UIR_SOF && UIE_SOF) {usb_isr_sof();}
TRNAttempts = 0;
do
{
if (UIR_TRN && UIE_TRN)
{
USTATCopy = U1STAT;
usb_clear_trn();
usb_isr_tok_dne();
}
else
break;
} while (TRNAttempts++ < 4);
}
} |
Now I want to understand where to write my code for reading from USB interrupt.
For debug for example I could read a printf("hello world") when the interrupt fires. |
|
![](templates/subSilver/images/spacer.gif) |
monyno
Joined: 24 Sep 2012 Posts: 4
|
|
Posted: Mon Sep 24, 2012 1:51 pm |
|
|
none?? I need to know it for my degree. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Mon Sep 24, 2012 2:49 pm |
|
|
You are looking at too low a level.
USB interrupts occur for dozens of reasons (not just data transfers). Every one of these low level events needs to be handled.
The interrupt code handles about a dozen separate events, and then has a state machine that handles transmitting or receiving data when it is available. USB requires all of these to be there and working.
You need to be looking only for the out token done interrupt on the endpoint being used for receiving data. usb_isr_tok_out_dne (in and out are confusing, referring to the host, not the PIC, so 'out token done' is triggered when the PIC has received data on a particular endpoint). Test the endpoint number to match what is used for your data transfer, and this then 'marks' that a data packet has arrived and is ready to be read.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
monyno
Joined: 24 Sep 2012 Posts: 4
|
|
Posted: Tue Sep 25, 2012 7:55 am |
|
|
I use endpoint 1. So for example if i want to do something( like printf hello world ) when date are on this endpoint, I have to write : printf("hello world") in the function that you've mentioned.
Can you make an example?
THANK YOU |
|
![](templates/subSilver/images/spacer.gif) |
monyno
Joined: 24 Sep 2012 Posts: 4
|
|
Posted: Tue Sep 25, 2012 7:58 am |
|
|
This is the function:
Code: |
void usb_isr_tok_dne(void)
{
unsigned int8 en;
en = USTATCopy>>3;
debug_usb(debug_putc, "T ");
debug_usb(debug_putc, "%X ", USTATCopy);
if (USTATCopy == USTAT_OUT_SETUP_E0)
{
//new out or setup token in the buffer
int8 pidKey;
debug_usb(debug_putc,"%X ", EP_BDxST_O(0));
pidKey = EP_BDxST_O(0) & 0x3C; //save PID
EP_BDxST_O(0) &= 0x43; //clear pid, prevent bdstal/pid confusion
if (pidKey == USB_PIC_PID_SETUP)
{
if ((EP_BDxST_I(0) & 0x80) != 0x00)
EP_BDxST_I(0)=0; // return the in buffer to us (dequeue any pending requests)
debug_usb(debug_putc,"(%U) ", EP_BDxCNT_O(0));
debug_display_ram(EP_BDxCNT_O(0), usb_ep0_rx_buffer);
usb_isr_tok_setup_dne();
UCON_PKTDIS=0; // UCON,PKT_DIS ; Assuming there is nothing to dequeue, clear the packet disable bit
//if setup_0_tx_size==0xFF - stall ep0 (unhandled request) (see usb_request_stall())
//if setup_0_tx_size==0xFE - get EP0OUT ready for a data packet, leave EP0IN alone (see usb_request_get_data())
//else setup_0_tx_size=size of response, get EP0OUT ready for a setup packet, mark EPOIN ready for transmit (see usb_request_send_response())
if (__setup_0_tx_size == 0xFF)
usb_flush_out(0, USB_DTS_STALL);
else
{
usb_flush_out(0, USB_DTS_TOGGLE);
if (__setup_0_tx_size != 0xFE)
usb_flush_in(0 ,__setup_0_tx_size, USB_DTS_USERX);
}
//why was this here?
//UCON_PKTDIS=0; // UCON,PKT_DIS ; Assuming there is nothing to dequeue, clear the packet disable bit
}
else if (pidKey == USB_PIC_PID_OUT)
{
usb_isr_tok_out_dne(0);
usb_flush_out(0, USB_DTS_TOGGLE);
if ((__setup_0_tx_size!=0xFE) && (__setup_0_tx_size!=0xFF))
{
usb_flush_in(0,__setup_0_tx_size,USB_DTS_DATA1); //send response (usually a 0len)
}
}
else
{
debug_usb(debug_putc, "!!! ");
}
}
else if (USTATCopy == USTAT_IN_E0)
{
//pic -> host transfer completed
EP_BDxST_I(0) = EP_BDxST_I(0) & 0x43; //clear up any BDSTAL confusion
__setup_0_tx_size = 0xFF;
usb_isr_tok_in_dne(0);
if (__setup_0_tx_size!=0xFF)
usb_flush_in(0, __setup_0_tx_size, USB_DTS_TOGGLE);
else
{
//usb_init_ep0_setup(); //REMOVED JUN/9/2009
}
}
else
{
if (!bit_test(USTATCopy, 2))
{
EP_BDxST_O(en) = EP_BDxST_O(en) & 0x43; //clear up any BDSTAL confusion
usb_isr_tok_out_dne(en);
}
else
{
EP_BDxST_I(en) = EP_BDxST_I(en) & 0x43; //clear up any BDSTAL confusion
usb_isr_tok_in_dne(en);
}
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Tue Sep 25, 2012 8:09 am |
|
|
No.
You have things the wrong way round.
Printf, is to send data from the PIC to the PC. Either use the cdc code/driver, and printf to usb_cdc_putc, or sprintf to a buffer, and use usb_puts. Interrupts are not involved as far as you are concerned in this direction. The existing driver will transfer the packet, when it receives a request from the PC. Understand that there is nothing you can do to trigger a transfer, it _has_ to wait for the PC to ask for the data. Fiddling around in the interrupt driver will gain you nothing.
The 'usb_isr_tok_out_dne' function is called from the interrupt handler, when a packet has been _received_ by the PIC. It is called with the endpoint number that the packet has come from, so you can check the number, and if the packet is for your endpoint, call code that you want to handle the packet (but with the big restriction that as always you _must_ get out of the ISR ASAP). This is what is done by the CDC code, setting the flag used by kbhit, when this happens.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|