|
|
View previous topic :: View next topic |
Author |
Message |
nab
Joined: 05 Mar 2015 Posts: 3
|
USB CDC hang on print loop |
Posted: Fri Mar 06, 2015 2:33 am |
|
|
Hi,
I'm trying to port some code from a pic18f4550 project to a new version made on a pic18f25k50. The port seems to be working, but I have troubles getting the USB serial output to work reliably. When putting a stream of data out, it ends up hanging quickly.
I tried to narrow it down, and to simplify, I took one of the examples and modified it.
I took ex_usb_serial2.c, modified the defines in ex_usb_common.h to match the 25k50 and my board pinout for the LED.
Code: |
#if defined(USB_NANO_PIC18F25K50)
#include <18F25K50.h>
#use delay(crystal=16MHz, clock=48MHz, USB_FULL)
#fuses NOWDT
//leds ordered from bottom to top
#DEFINE LED1 PIN_A0 //green
#define LED2 PIN_B0
#define LED3 PIN_B0
#define LEDS_OFF() LED_OFF(LED1); LED_OFF(LED2); LED_OFF(LED3)
#define BUTTON_PRESSED() !input(PIN_A1)
//see section below labeled USB_CABLE_IS_ATTACHED
// #define PIN_USB_SENSE PIN_B2
#define __NO_UART__
#define HW_ADC_CONFIG ADC_CLOCK_INTERNAL
#define HW_ADC_CHANNEL 0 //PIN_A0
#define HW_ADC_PORTS sAN0
#define HW_INIT() setup_adc_ports(HW_ADC_PORTS)
#endif
|
I modified ex_usb_serial2.c main to match my issue:
Code: |
void main(void)
{
int i = 0;
HW_INIT();
LEDS_OFF();
uart_printf(uart_putc, "\r\n\nCCS USB Serial2 Example");
#if defined(__PCH__)
uart_printf(uart_putc, "\r\nPCH: v");
uart_printf(uart_putc, __PCH__);
#elif defined(__PCD__)
uart_printf(uart_putc, "\r\nPCD: v");
uart_printf(uart_putc, __PCD__);
#else
uart_printf(uart_putc, "\r\n\PCM: v");
uart_printf(uart_putc, __PCM__);
#endif
#if defined(LEDS_RED)
LEDS_RED();
#elif defined(LED1)
LED_ON(LED1);
#endif
// init USB (non-blocking)
// usb_task() need to be called in your loop to finish USB initialization.
usb_init_cs();
for(;;)
{
// service low level USB operations.
usb_task();
// special debugging routines for this program.
usb_debug_task();
// blink the LED at 1hz
led_blink_task();
if (usb_enumerated())
{
if (usb_cdc_kbhit())
{
// application specific routine that handles incoming CDC (virtual
// com port) commands for reading/writing EEPROM.
// handle_incoming_cdc();
while(1)
{
usb_task();
delay_us(1000);
printf(usb_cdc_putc, "i: %d\r\n", i);
i++;
}
}
}
}
}
|
I then connect it to my PC, open the serial connection to it with putty, press a key and it starts dumping text.
If I add a delay bigger than 1000 us, it quickly hangs. With lower delays, it works. As I'm using USB interrupts, I didn't think adding a delay would be any issues, I expected it to actually make it work better, avoiding to fill buffers. I'm also not sure I actually need to call usb_task() in my case.
I tried checking usb_cdc_putready() in my loop and call usb_task() as long as I don't have enough free buffer, but this didn't fix it.
Am I misunderstanding something? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Fri Mar 06, 2015 3:37 am |
|
|
usb_task, must be called periodically, if usb_init_cs is used. It handles the possibilities of the USB disconnecting, and the basic 'tidy' functions. If you use usb_init, instead of usb_init_cs, you do not need to call usb_task regularly (provided you use interrupts), but then the code will hang, if a disconnect takes place.
This is described in the notes in usb.h:
"//// usb_task() - If usb_init_cs() was used to initiate the USB ////
//// peripheral, usb_task() should then be called periodically"
Note 'should be called periodically'.
A few times a second is usually OK.
This is where a timer comes in. My main code always loops at good speed, checking the 'housekeeping' tasks. If I want to delay for a second, then this is done by a tick on a timer interrupt, with the next function being called when this expires, and the main loop keeping executing.
Your code as posted, also never retrieves the received character, so will eventually overflow the USB receive buffer. |
|
|
nab
Joined: 05 Mar 2015 Posts: 3
|
|
Posted: Fri Mar 06, 2015 3:59 am |
|
|
That's one of the thing I'm not sure to understand: if I use usb_init() instead of usb_init_cs() and use interrupts and not USB_ISR_POLLING, do I need to call usb_task() anyway to do the housekeeping ?
It doesn't seem to change behaviour if I replace usb_init_cs() with usb_init() and start it with USB connected (which is also what the original code I ported was doing).
And I'm not sending chars back, just trying to dump a string. So I didn't think the input buffer would overflow.
Just to be sure, I added this to poll the input buffer in my loop:
Code: |
if (usb_cdc_kbhit())
{
char c = usb_cdc_getc();
printf(usb_cdc_putc, "r\r\n");
}
|
Thanks for your answer, still learning about PIC and USB! |
|
|
nab
Joined: 05 Mar 2015 Posts: 3
|
|
Posted: Wed Mar 11, 2015 3:29 am |
|
|
Looking at the communication with Microsoft Message Analyser, it looks like it gets a stall handshake and gets stuck there. Putting a breakpoint in usb_isr_stall() confirms that. Any hint on how to find out what provokes that?
From what I understand, the device sends that when it gets and internal error and requests the host to take some action (probably resetting the line). Haven't found out where this problem occurs, any pointers are welcome. |
|
|
|
|
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
|