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

SOLVED using delays with USB
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

SOLVED using delays with USB
PostPosted: Wed Jan 15, 2014 8:07 am     Reply with quote

Hi Folks,

I've been using the CCS USB drivers for a while now with the PIC18f2553 boards (Bitwhacker) from Sparkfun. Mostly using CDC terminals applications without too much trouble.

I recently started working on a project where I was using the USB as a debug terminal while the serial interface conencted to a cellular module and now I'm having a lot of problems with windows failing the USB connection. Specifically, I needed to add delays to the code while waiting for serial responses from the cell module.

I know the USB_Task() routine needs to be called frequently so I replaced delay_ms routines with
Code:

for (j=0; j<100; j++){         
    usb_task();            
    delay_ms(1);
}


I am still getting errors from windows with this. Is there a better way to implement the delays and keep windows happy?

CCS PCH C Compiler, Version 4.074, 44415

Thanks in advance.


Last edited by dan king on Sun Jan 26, 2014 7:16 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Wed Jan 15, 2014 9:19 am     Reply with quote

Run a tick.

I have delays of several thousand seconds in some parts of my code (things that happen at up to twenty four hour intervals), but everything is done using a countdown timer running from an interrupt.

My main loop sits checking the USB, a couple of serials, an I2C connection etc., all done using buffering, so nothing actually 'waits'. When I want to wait for something I load the required delay into the corresponding counter (I have one ticking at 100Hz, and one that decrements at 1Hz), and wait till it is zero.
The code in the interrupt is done as:
Code:

int16 countdown;

#int_timerx //at whatever you want the tick to be - I typically use 100Hz
void tick(void)
{
    static int8 sec_tick=99;
    if (sec_tick)
    {
        --sec_tick;
    }
    else
    {
        sec_tick=99;
        if (countdown)
            --countdown;
    }   
}

//Then in the main code:
   do
   {
      if (usb_attached())
      {
         usb_task();
         if (usb_enumerated())
         {
            if (usb_cdc_carrier.dte_present)
            {
               if (usb_cdc_oldconnected==FALSE)
               {
                  printf(usb_cdc_putc,"I/F active\n\r");  //some message
                  usb_cdc_oldconnected=TRUE;
               }
               if (usb_cdc_kbhit())
               {
                  //Need to parse USB here
                  //1) request directory of data
                  //2) request data for a day
                  //3) monitor mode (output status, and NH4)
                  tchar=usb_cdc_getc();
                  parseusb(tchar);
                  bit_clear(sys_stat,NO_HOST); //also clear host error
                  timeout=70;
               }
            }
            else
            {
               usb_cdc_oldconnected=FALSE;
            }
         }
         else
         {
            usb_cdc_oldconnected=FALSE;
         }
      }
      //Here need to look at serial tasks
      if (bkbhit(U2RX)) { //first UART2 (controller)
         tchar=bgetc(U2RX);
         stimeout=70; //have character from controller
         parseserial(tchar);
         wdog=250;
      }
      //Then half a dozen other things here talking to the other UART
      //SD card, I2C, couple of peripherals etc...
      if (countdown==0)
      {
         //perform the jobs that need to occur at the interval.
         //includes setting 'countdown' to the next time required.
      }
   }
   while (TRUE);

Now the 'parsers', are in each case state machines that walk through tables, so return quickly.

Notice the way that the enumeration is done. This unit has the connection sense pin enabled, so will detect attached/unattached, but also uses the DTE (set by the program), so it knows when the code connection is made by the host, and can send a message at this point, or do specific 'setup' jobs.

I've got some continuous data logs that run 'unbroken' for six months plus.

Best Wishes
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Jan 15, 2014 9:22 am     Reply with quote

ok, i'll modify my code to follow a similar format and let you know how I make out. Thanks for the sample.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Jan 15, 2014 12:49 pm     Reply with quote

sooo, it appears that W7 is evil. I followed the suggestion and modified my code to use a step machine and timer tick counter to ensure all routines were non-blocking and I am still having very intermittent success. W7 sometimes reports issues, press the reset on the board and sometimes it starts working, .....

I then plugged the HW into an XP machine and the code operates 100% EVERY TIME.

I'm not sure what to make of this, I'm finding some of the USB ports on the W7 machine allow me to update firmware using the USB bootloader with a Microchip custom driver, but won't run the application code using the CCS CDC driver and the other USB ports can run the CCS CDC driver but not the Microchip bootloader driver ????

I'm not sure where to go from here. If anyone has experienced this and has a solution I'd love to hear it. I so miss the simple serial days.
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Jan 15, 2014 3:42 pm     Reply with quote

Sounds like you're not the original 'administrator' on the W7 machine or only have 'some' permissions enabled.
W7 guys should know...me..I'm still in XP and it will NOT do things that W98 does.....

Good news is it's NOT PIC code at fault !!!


jay
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Jan 15, 2014 6:39 pm     Reply with quote

I've had better luck with XP than W7 but since it's a work machine I don't have a lot of say. You're correct in that I don't have full admin rights, something short of it so I'm not sure what permissions are in play here.

If anyone has any ideas, I'd love to here them. I can get by but I have to keep switching through USB ports each time I upload new code and then try to run it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Thu Jan 16, 2014 3:34 am     Reply with quote

Look at power management. If the system is putting the USB peripheral to sleep, the slave code, will need to be able to handle this, or disconnection will result. W7 does a lot more 'default' power management than WXP.
Right click on desktop, 'Personalise', 'Screen Saver', 'Power management', 'Change Power settings', 'Change Plan settings', 'Change advanced power settings', 'USB settings', and turn off 'USB selective suspend'.

On the comment the W98 allows things that XP doesn't, the answer is 'of course'. It is the difference between a protected mode OS, and something having no protection at all. While the latter is very flexible, in terms of producing reliable operation, the former is much better, but does require that drivers exist or are written for every piece of hardware, not allowing applications to directly do such accesses. However in fact provided you know what you are doing, and are prepared to bypass the OS protection to some extent, you can get just about any W98 program to run, by using 'allowio' (web search), which turns off the hardware protection for an application. Worth knowing if you are fiddling around with old stuff that does things like fiddling with the parallel ports etc....

Best Wishes
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu Jan 16, 2014 7:01 am     Reply with quote

Thanks for the suggestion but that didn't seem to help. The really odd thing is that both the Microchip USB driver and the CCS driver are struggling but on different USB ports connected to the laptop. I can initiate the USB bootloaded on one USB port and it enumerates fine but on a different USB port on the same laptop the same driver fails to start. I looked in the driver settings and both USB ports are loaded the same driver from the same windows folder location.

This same type of behavior happens with the CCS CDC driver. Some of the USB ports it's working on and some it isn't. The really odd thing is that none of the ports have both drivers working.

Thanks for the help. I know this isn't a windows support forum but this is really frustrating.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Sat Jan 18, 2014 9:05 am     Reply with quote

So a little more info as I worked with this a bit more. I have determined the issue isn't necessarily a win7 problem?? I determined this when I loaded previous usb code projects I developed and they functioned correctly with win7. I'm trying to narrow down specifics to help figure out whats going on so maybe someone will have an idea but here are some findings;
1. if I compile my current code and then load it into the micro using the USB bootloader, after a reset win7 won't recognize the device even if I press the reset. I have to physically unplug the USB connection and then it works most of the time. Something happens when switching between the USB drivers.

2. when my code has issues, the pic code is not running. I have a heartbeat LED in the TIMER code and that stops running. I am getting power to the pic though because a power LED is lit, USB powered board. A reset doesn't recover operation, requires USB to be unplugged.

3. This is the really odd one, when I have USB code loaded into the board that is acting flakey, touching the board near the programming button will lock up the IC because the heartbeat LED stops. Stable running USB code does not do this on the same board. If you look at the board layout on the sparkfun site you will see that port B is near the button, I have them configured at outputs except 1 bit being used as an input with the b pullups enabled. The button is configured as an input, schematic is located on the sparkfun site.

I will be cleaning up a simple example program to demonstrate the problem so maybe someone can review and comment but that's it for now. I'll post links to the board and schematic as well but I have to run for now.

Any thoughts and/or suggestions are welcome as I'm kind of baffled with this one.

Thanks, Dan
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Sat Jan 18, 2014 9:31 am     Reply with quote

sample code demonstrating the problem, links to come:
Code:

#include <18F2550.h>
//#include <18F2553.h>         //requires custom pic18_usb.h file to include 2553
#include <string.h>                                  // to use the string functions, strstr()
#include <stdlib.h>                                    //for using the atof function

#fuses CPUDIV1         //oscillator postscaler = PLL/2
#fuses HSPLL         //HS crystal option with PLL
#fuses PLL6            //PLL postscaler div 6 for UBW ver 2.0 with 24Mhz crystal = 4Mhz to PLL input
//#fuses PLL5            //PLL postscaler div 5 for UBW ver 1.0
#fuses USBDIV
#fuses NOWDT         //no wdt
#fuses NOPROTECT      //no code protect
#fuses NOLVP         //no Low voltage Programming
#fuses NOXINST         //no extended instructions
#fuses vregen         //usb voltage regulator enable
#fuses MCLR            //enable external reset so bootloader can be started !!!
#fuses WRTB            //disable write to boot block to protect bootloader
#fuses NOPBADEN         //configure port B as digital I/O on reset

//#device adc=10
#use delay(clock=48000000)

#use standard_io(A)
#use standard_io(B)

//change to 4800 with cell
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,stream=cell, errors)

#include <usb_cdc.h>

#byte PORTA = 0xF80
#byte PORTB = 0XF81
#BYTE PORTC = 0xF82

////////////////////////////////////////////////////
// Constants and variables
#bit   sysled = PORTC.1         //on UBW led c.0 and c.1 are onboard leds. C.2 = input button
#bit   testled = PORTC.0
#bit   button   = PORTC.2

#bit   Cell_on            = PORTB.0         //npn used to switch the cell module on
#bit    Tstat_trigger       = PORTB.1         //if tstat closes, send an sms


//////////////////////////////////////


#define    WORD unsigned long  // Data type definitions



int16    countdown;
int      heartbeat;



///////////////////////////////////////////////////////
// General prototypes //

// local prototypes
void   execute_usbcmd(char);



//========================================================
// Reserve space for the bootloader and relocate reset vector and int vectors
#build(reset=0x800,interrupt=0x808)
#org 0x000, 0x7ff{}



 
void main(){
   set_tris_c(0b10000100);
   set_tris_b(0b00000010);

   port_b_pullups(TRUE);

   sysled = 0;
   testled = 0;


      usb_init_cs();

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(global);


   //usb_cdc_putc("\r\n Cellular test program \r\n");

   while(1){

      usb_task();


      if (usb_cdc_carrier.dte_present){          //waits for usb connection to terminal
            if (usb_cdc_kbhit()) {
               execute_usbcmd(usb_cdc_getc());
             }
   
      }

   }            //close while 1
}               //close main


///////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////

#int_timer0 //at whatever you want the tick to be - I typically use 100Hz
void tick(void)
{

    static int8 sec_tick=9;


   //testled = !testled;
   set_timer0( get_timer0() + 6000);

    if (sec_tick)
    {
        --sec_tick;
    }
    else
    {
        sec_tick=9;             //countdown in 100 ms counts- 10hz
      testled = !testled;
        if (countdown)
            --countdown;

    }   
}

///////////////////////////////////////////////////
// function interprets commands received through the usb port
void execute_usbcmd(char   c){
   
   switch (c){
      case 'h': usb_cdc_putc("help usb link\n\r");   
         usb_cdc_putc("a - send AT to check for response\r\n");
         usb_cdc_putc("p - to print cellular buffer\r\n");
         usb_cdc_putc("w - what carriers are present?(long hang time, must be connected to network)\r\n");
         usb_cdc_putc("s - check for service \r\n");
         usb_cdc_putc("S - send SMS \r\n");
         usb_cdc_putc("m - sim memory status \r\n");
         usb_cdc_putc("r - read SMS location 1 \r\n");
         usb_cdc_putc("D - delete SMS loc 2\r\n");
         break;


      default: ;
   }
   
}

dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Sat Jan 18, 2014 10:14 am     Reply with quote

so I commented out all of the USB stuff and for some reason I can lock up this board by touching various areas of the I/O ports to the point that the reset button does not restore function. I know this because the heartbeat led stops toggling and won't restart without power cycling.

https://www.sparkfun.com/datasheets/DevTools/PIC/UBW_Dev-v13.pdf

The sensitivity to lockup is greater when USB powered but can also happen on DC power, though not as sensitive. I don't call having these issues before and I've used quite a few of the bit whacker boards. I can replicate the problem between several different boards so it's not isolated.

I'm wondering if the issues I'm having are related, lockup and USB failure
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Sun Jan 19, 2014 7:28 am     Reply with quote

ok, I guess the USB problems are a mystery but can anyone explain what could cause the reset function to fail? I removed all of the USB code so the final project is only the timer running with the heartbeat LED and when I touch a certain area of the board, the led stops blinking. The reset (MCLR) doesn't restore the blinking, I have to power cycle to get the board running again.

The code is identical to the code posted but with all USB code removed. I can post the code if someone would like to see it.
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jan 19, 2014 7:37 am     Reply with quote

two possibilities come to mind...
1) static electricity...'zap' is putting PIC into 'lala' land.

2) MCLR is not MCLR anymore...could be 'magically' reprogrammed to be an I/O pin ?

hth
jay
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Sun Jan 19, 2014 9:54 am     Reply with quote

ESD is always a possibility but I don't think so. Sometimes I have to keep probing an area before the lockup occurs. No real chance to "charge up". Almost feels like a floating input but the portb pullups are enabled. Very odd.

Also, the MCLR isn't an I/O pin because I can reset the chip during normal operation and the part resets.

Thanks for the suggestions though
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Jan 24, 2014 3:32 am     Reply with quote

Just one little thought came to mind about this.

You may be stopping the master clock.

On these chips, there is much less leakage than on the older chips. If the master clock gets stopped, with the oscillator input biased to an indeterminate state (touching the clock pins could do this), it won't restart on it's own, and MCLR won't start it. The chip then sits 'dead', until power is removed/applied....

You can prevent this happening, by applying a tiny 'bias' to the clock input. A large resistor (2M2R say), between OSC1, and OSC2, provides the tiny kick needed to move the input pin out of this indeterminate state.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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