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

code not exiting case properly

 
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

code not exiting case properly
PostPosted: Wed Nov 08, 2006 4:12 pm     Reply with quote

I have a switch/case routine that I use frequently while debugging new code that allows me to start functions via the serial port using hyperterm. For some reason the latest code I'm working on has decided to exit one of the case selections improperly and hangs my code.

I have placed some debug statements to check how far the code progresses before hanging by turning on a led. The code in question is located below:
Code:
void execute_cmd(){
   int   loop_counter;
   
   disable_interrupts(int_rda);
   switch (bgetc()){
      case 'h': fprintf(PC,"HELP\r\n");
         fprintf(PC,"p - to print dos buffer\r\n");
         fprintf(PC,"s - to retrieve song data from SD card\r\n");
         fprintf(PC,"d - to read the directory contents from the SD card\r\n");
         break;

      case 'p': print_buf();               //manual buffer print
         break;
      case 's': get_song(0);               //manual buffer print
         
         //for (loop_counter=0; loop_counter<index; loop_counter++){
         //   fprintf(PC,"%u ",song[loop_counter]);
         //}
         //fprintf(PC,"\r\n");
         sysled = 1;
         break;
      case 'd': printf(flow_putc,"i\r");      //get DIR info
         delay_ms(5);
         print_buf();
         break;
   }
   sysled = 1;
   enable_interrupts(int_rda);
   //sysled = 1;
}


The problem is in the 's' selection. The sysled = 1 after calling get_song works, but if I comment that out the same sysled = 1 after the break does not and the code hangs (or seems to since the RDA interrupt may simply not be enabling). The other case statements fall through and execute the sysled = 1 and enable the RDA int, only the 's' option does not. I'm really confused by this.

I have also included the .lst for the resulting code and haven't found an issue yet but thought someone might be able to shed some light on this before I run out of hair.

    .................... case 's': get_song(0); //manual buffer print
    0520: BSF 03.5
    0521: CLRF 5D
    0522: BCF 03.5
    ....................
    .................... //for (loop_counter=0; loop_counter<index; loop_counter++){
    .................... // fprintf(PC,"%u ",song[loop_counter]);
    .................... //}
    .................... //fprintf(PC,"\r\n");
    .................... sysled = 1;
    *
    06A1: BSF 07.3
    .................... break;
    06A2: GOTO 6B9
    .................... case 'd': printf(flow_putc,"i\r"); //get DIR info
    06A3: MOVLW 69
    06A4: BSF 03.5
    06A5: MOVWF 61
    06A6: BCF 03.5
    06A7: CALL 483
    06A8: MOVLW 0D
    06A9: BSF 03.5
    06AA: MOVWF 61
    06AB: BCF 03.5
    06AC: CALL 483
    .................... delay_ms(5);
    06AD: MOVLW 05
    06AE: BSF 03.5
    06AF: MOVWF 60
    06B0: BCF 03.5
    06B1: CALL 2A0
    06B2: CLRF 27
    06B3: BTFSC 0B.7
    06B4: BSF 27.7
    .................... print_buf();
    06B5: CALL 24F
    06B6: BTFSC 27.7
    06B7: BSF 0B.7
    .................... break;
    06B8: GOTO 6B9
    .................... }
    .................... sysled = 1;
    06B9: BSF 07.3
    .................... enable_interrupts(int_rda);
    06BA: BSF 03.5
    06BB: BSF 0C.5
    06BC: BCF 03.5
    06BD: BCF 0A.3
    06BE: BCF 0A.4
    06BF: GOTO 72F (RETURN)



Sorry if this post is too long, but any help would be appreciated.

compiler ver = CCS PCM C Compiler, Version 3.130, 17162
using a 16f877

Thanks Dan
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 08, 2006 4:37 pm     Reply with quote

If the code hangs as soon as you enable INT_RDA interrupts, you
probably have an overrun condition in the UART receiver. Check if
this is happening by adding the ERRORS parameter to your #use rs232()
statement. (You should always add this parameter).
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Nov 08, 2006 6:02 pm     Reply with quote

Thanks for the reply, I do indeed have the errors parameter for the HW uart. I also have it specified for the SW stream that is used with the EXT interrupt on PORT B0. Any other suggestions?

Rgds,

Dan
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 08, 2006 6:27 pm     Reply with quote

Actually, the ERRORS parameter doesn't have any effect in software
UART. The compiler ignores it.

I don't understand your statement here:
Quote:

The sysled = 1 after calling get_song works, but if I comment that out
the same sysled = 1 after the break does not and the code hangs

There are three "sysled = 1" statements in your posted code.
Which one are you referring to, when you say "the same sysled = 1" ?

It seems to me that you have one of two types of problems:

1. There's a problem with the compiler, where the switch-case
statement is not being generated correctly in some instances.

2. The code is locking up for some other reason and it's not the
compiler's fault.

What happens if you comment out the call to get_song(0) ?
Does the program still lock up ?

Post the declaration statement for 'sysled'.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Nov 08, 2006 7:14 pm     Reply with quote

I never thought about what the errors would do with a soft uart, good thing the compiler ignores it then.

What I meant about the statement you questioned was that when the code reaches SYSLED=1 after returning from get_song the LED tied to that port lights up. If I comment out the SYSLED line mentioned, the same statement that would follow the BREAK statement (just before the enable_interrupts(int_rda);) doesn't light the led.

SYSLED is a bit corresponding to PORTC.3

I have a lot of the SYSLED=1 statements at various points to determine how far the code is progressing. I comment them out to see where the problem hangs.

Your idea to comment out the get_song routine is a really good idea. I'll try that in the morning as I don't have the code with me right now. Never thought to try it, getting a bit punchy looking through everything.

Thanks again for your input.

Dan
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Nov 08, 2006 10:33 pm     Reply with quote

Make sure that you are not enabling any interrupts which you do not have a handler for. The handler is declared with the #int_XXXX pragma.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

problem solved :)
PostPosted: Thu Nov 09, 2006 7:47 am     Reply with quote

OK, I finally got to the source of the problems after a good nights sleep and some good direction from PCM and mark.

After commenting out my get_song(0); function I found the hang wasn't occuring so I dug into that function. I found the hang was occuring when I enabled my INT_EXT interrupt.

I believe what was happening was that the EXT interrupt wasn't clear when I was enabling it and therefore after enabling immediately was being serviced. As a result of the interrupt happening unexpectedly, my servicing routine was hanging waiting for data from the sw uart. I modified the handler to check for kbhit and fall through otherwise and all is well. I suppose I could have cleared the interrupt before enabling but this should prevent unexpected EXT interrupts from hanging else where.

Code:
///////////////////////////////////////////////////
// Soft serial port ISR 
#int_ext
ext_isr(){
   int   temp;

   temp =0;
//not circular, just captures up to buffer size and when full prints it
   
   if (kbhit(sd)){            //added to prevent hangup
      temp  = fgetc(sd);
      cts=1;
      sd_buff[sdnext_in] = temp;
      sdnext_in ++;
      if (sdnext_in == SDBUFFER_SIZE-1)
         //sdnext_in --;      // buffer full
         print_buf();
      cts = 0;
   }
   cts=0;

}


Thanks for the help/suggestions.

Dan
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