EmbeddedRelated.com
Forums

Reset Occurs After Keyboard Interrupt on Motorola HC08

Started by Aria August 11, 2005
Hi,

I'm kind of new to programming MCUs but this must be something I missed
when I was reading about them. I am programming a MC68HC098QY4 motorola
processor with CodeWarrior and in C Language. Everything was going fine
until I discovered that after my software sets off a keyboard
interrupt, the chip resets itself. WHYYY??? Here's what I'm doing.

from the start of the main function:
-configure registars
-go into stop mode and wait for keyboard interrupt
-when interrupt comes in, blink a LED a few times then acknoledge
interrupt and clear interrupt masks (asm CLI).

now turns out, the program restarts when it comes out of the interrupt!
is this supposed to happen? how can i prevent it? I even tried finding
out what's setting offf the reset using the SRSR register but no lock!
I've enclosed my code for your review. any help would be greatly
appreciated.

thanks in advance,
Aria

**********
CODE:
**********


#include <hidef.h> /* for EnableInterrupts macro */
#include <MC68HC908QY4.h> /* include peripheral declarations */
#include <stdio.h>


#define EVER (;;)

void lightOn(int num);
void lightOff(int num);
void blink(int num);


int i;
byte cyc;
int adrval;
int zeroadr;

void main(void) {
  //EnableInterrupts; /* enable interrupts. Same as CLI command */
  /* include your code here */

  //setting CONFIG1 and CONFIG2
  CONFIG1 = 0x2B; //00101011
  CONFIG2 = 0x01; //00000001

  //setting ADSCR
  ADSCR = 0x23; //00100011 Continous ADC on AD3

  //setting ADC clock
  ADICLK = 0x80; //busclock / 16

  //enabling keyboard inputs
  KBSCR_IMASKK = 1;
  KBIER = 0x13; //00010011
  KBSCR_MODEK = 1;
  KBSCR_ACKK = 1;
  KBSCR_IMASKK = 0;

  //setting up port B
  PTB = 0x00; //initializing

  DDRB = 0xFF; //all pins on port B configured as outputs

  PTB_PTB0 = 0;

  //zeroadr = ADR; //ADR value at "zero" load.

  blink(3);
  lightOn(0);
  for (i=0;i<32000;i++) {

  }
  for (i=0;i<32000;i++) {

  }
  lightOff(0);

  //finding reset cause
  if (SRSR_LVI == 1){
    blink(1);
  }else if (SRSR_MODRST == 1){
    blink(2);
  }else if (SRSR_ILAD == 1){
    blink(3);
  }else if (SRSR_ILOP == 1){
    blink(4);
  }else if (SRSR_COP == 1){
    blink(5);
  }else if (SRSR_PIN == 1){
    blink(6);
  }else if (SRSR_POR == 1){
    blink(7);
  }else{
    lightOn(0);
    for (i=0;i<32000;i++) {

  }
  for (i=0;i<32000;i++) {

  }
  for (i=0;i<32000;i++) {

  }
  lightOff(0);
  }

  //asm WAIT;


}

interrupt 15 void KBI_ISR(void){

  asm SEI;

  if (PTA_PTA0 == 0) {
    blink(5);
  }else if (PTA_PTA1 == 0){
    blink(10);
  }else if (PTA_PTA4 == 0){
    //adrval = ADR; //clearing flag to make sure we get up-to-date
reading
    //while (!ADSCR_COCO){
      //do nothing and wait
    //}
    adrval = ADR;
    if (adrval == 155) {
      for (cyc=0;cyc<5;cyc++) {
        for (i=0;i<32000;i++) {
          lightOn(0);
        }
      }
      lightOff(0);
    }else{
      if (adrval > 150){
        blink(adrval % 150);
      }else{
        blink(1);
      }
      //blink(2);
    }
  }

  KBSCR_ACKK = 1; //acknowledging interrupt

  asm CLI;
  //asm STOP;

}

interrupt 1 void SWI_ISR(void){
  //for testing

  //asm RTI;
  asm CLI;
  asm NOP;
}

void lightOn(int num){
  switch (num){
    case 0:
      PTB_PTB0 = 1;
      break;
    case 1:
      PTB_PTB1 = 1;
      break;
    case 2:
      PTB_PTB2 = 1;
      break;
  }
}

void lightOff(int num){
  switch (num){
    case 0:
      PTB_PTB0 = 0;
      break;
    case 1:
      PTB_PTB1 = 0;
      break;
    case 2:
      PTB_PTB2 = 0;
      break;
  }
}

void blink(int num) {
  int count;
  for (count=0;count<(num*2);count++) {
    for (i=0;i<32000;i++) {
     //delay 
    }
    PTB_PTB0 = ~PTB_PTB0;
  }
}

sorry, the last line in the main() function is not supposed to be
commented out:

It should read:

asm WAIT;

AND NOT read:

//asm WAIT.


Correction: asm WAIT;   not  //asm WAIT;

"Aria" <akashefi@interchange.ubc.ca> wrote in message 
news:1123798247.131439.17540@f14g2000cwb.googlegroups.com...
> I'm kind of new to programming MCUs but this must be something I missed > when I was reading about them.
<snip>
> now turns out, the program restarts when it comes out of the interrupt! > is this supposed to happen? how can i prevent it? I even tried finding > out what's setting offf the reset using the SRSR register but no lock! > I've enclosed my code for your review. any help would be greatly > appreciated.
Hmm. I don't know your particular setup well enough to debug it for you, but I would make some general comments about your code: - Don't enable interrupts until you've completed your initialisation. Consider what would happen if an interrupt occurred at startup. - Ensure you have a valid stack before enabling interrupts (or calling any functions). (Presumably a function of your compiler & linker script.) - Do as little as possible within the interrupt. Manipulating I/O is dangerous (without some safeguards). Delay loops generally don't belong in interrupts. Where possible consider instead communicating the fact that the interrupt occurred (and any data provided uniquely by the ISR) to the top-level routine, and dealing with the event at the higher level. - You might find it convenient to break your code down into smaller chunks - for instance (once the stack is valid) putting all the initialisation into a function (or functions). - Consider putting your debug statements inside a conditional compilation clause. (This would make it easier for you and I to read the code and understand which bits are which.) - Avoid magic numbers (i.e. literal constants such as "1", "33" etc) in code. Use e.g. a #define to define them, or where appropriate, a typedef enum (for instance for your interrupt vector idents). - Consider using macros to enable/disable interrupts. The compiler may already provide a suitable set of macros. (They're just clearer than embedded assembler.) If you rewrite your code bearing all these points in mind, there's a good chance the flaw will become obvious (if it is indeed in the code - but even if it isn't, then your confidence in the code will rise). The clearer the code, the more likely it is to be correct. Hope this helps. Steve http://www.fivetrees.com
Aria wrote:

> sorry, the last line in the main() function is not supposed to be > commented out: > > It should read: > > asm WAIT; > > AND NOT read: > > //asm WAIT. > > > Correction: asm WAIT; not //asm WAIT;
Trouble is as soon as you exit the interrupt routine, main tries to carry on and simply returns. Main should never return. Ian
If you want your app to just wait for interrupts in one of the
low-power modes do the following arround the "asm WAIT" statement.

for (;;)
{
    asm WAIT
}


This will make your app to go to WAIT everytime the keyboard interrupt
returns.

Also, just to let you know, on your interrupt handlers the CPU
automatically disables global interrupts for you as soon as the
interrupt is serviced, it then re-enables them as soon as it executes
the RTI instruction (return in C).
So your asm CLI and asm SEI seem at little bit redundant.

By the way, for a beginner in C and MCU programming, you are doing very
well!

Ian Bell wrote:
> Aria wrote: > > > sorry, the last line in the main() function is not supposed to be > > commented out: > > > > It should read: > > > > asm WAIT; > > > > AND NOT read: > > > > //asm WAIT. > > > > > > Correction: asm WAIT; not //asm WAIT; > > Trouble is as soon as you exit the interrupt routine, main tries to carry on > and simply returns. Main should never return. > > Ian