CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

USB CDC hang on print loop

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
nab



Joined: 05 Mar 2015
Posts: 3

View user's profile Send private message

USB CDC hang on print loop
PostPosted: Fri Mar 06, 2015 2:33 am     Reply with quote

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: 19499

View user's profile Send private message

PostPosted: Fri Mar 06, 2015 3:37 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Mar 06, 2015 3:59 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Mar 11, 2015 3:29 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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