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 support@ccsinfo.com

Timer2 and relocated interrupt not working

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



Joined: 03 Nov 2004
Posts: 13

View user's profile Send private message

Timer2 and relocated interrupt not working
PostPosted: Mon Nov 13, 2006 7:27 pm     Reply with quote

Hi,

I'm trying to learn how to use interrupts from a timer here is my code

Code:

#include <18f4620.h>
#include <stdlib.h>
#fuses NOLVP, NOWDT, EC_IO, NOBROWNOUT

#ORG 0x2000, 0xFFFC default
#use delay (clock=25000000)
#use rs232 (baud=115200, xmit=PIN_E1, rcv=PIN_E0)

#define RDWR PIN_A1
#define RSEL PIN_A2
#define ENAB PIN_A0

#define row0 PIN_D7
#define row1 PIN_D6
#define row2 PIN_D5
#define row3 PIN_D4

#define col0 PIN_D3
#define col1 PIN_D2
#define col2 PIN_D1
#define col3 PIN_D0
#define col4 PIN_A3

#define BOOT PIN_C2

#build (interrupt = 0x1000)

#int_timer2
void isr_relocate()
{
   printf ("hi interrupt");
   putc (0x0D);
   putc (0x0A);
}

//variables
const int8 key_val[4][5] = {{1, 2, 3, 4, 5},
                             {6, 7, 8, 9, 10},
                             {11, 12, 13, 14, 15},
                             {16, 17, 18, 19, 20}};
int1 key_checked;
int8 row;
int8 col;



//functions
void init_disp ();
void access_disp (int1 rs, int1 rw, int8 data);
void write_disp (int8 data);
void setup_disp (int1 home, int1 cls, int1 line);
int8 scan_keypad ();
int1 key_pressed ();


void main (void)
{
   int8 data;
   int16 edata;
   int8 count;
   int8 hertz = 110;
   float vol = 1.0;
   int1 comp_flag;
   int1 phas_flag;
   int1 cueq_flag;

   int8 key_data;
   
   setup_timer_2(T2_DIV_BY_16, 128, 16);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);

   key_checked = 0;

   output_low (RDWR);
   output_low (RSEL);
   output_low (ENAB);

   edata = read_program_eeprom (0x0000FFF4);

   if (edata > 1)
   {
      write_program_eeprom (0x0000FFF4, 0x0001); //program running ok
   }

   printf ("running user code");
   putc (0x0D);
   putc (0x0A);

   init_disp ();

   setup_disp (0, 1, 0); //clear screen
   printf (write_disp, "EQ Movie");
   delay_ms (1000);
   setup_disp (1, 0, 1);
   printf (write_disp, "Volume %2.1f", vol);

   do
   {
      if (!input (BOOT))
      {
         write_program_eeprom (0x0000FFFC, 0x0001);
         delay_ms (1000);
         reset_cpu ();
      }

      if (kbhit ())
      {
         data = getc ();

         if (data == 0x30) //go back to bootloader
         {
            write_program_eeprom (0x0000FFFC, 0x0001);
            delay_ms (1000);
            reset_cpu ();
         }
      }

      if (key_pressed ())
      {
         if (key_checked == 0)
         {
            key_data = scan_keypad ();

            if (key_checked == 1)
            {
               delay_ms (500);   
            }
         }
      }
   }
   while (1);
}


The rest of the code works I'm trying to get the isr to print to tell me it's working. Thanks in advance for any help.

Tim
Ttelmah
Guest







PostPosted: Tue Nov 14, 2006 4:21 am     Reply with quote

Effectively, you do not have an ISR!.....
The build directive, tells the compiler to put the interrupt handler code at address 0x1000. The chips _hardware_, will still be vectoring to address 0x18. To use a relocated interrupt handler, _you_ need to add the code at this address, to jump to the relocatd handler. Normally such relocation is only done, where there is something like a bootloader in the bottom of memory, that includes the code to redirect the interrupt. You should not relocate the interrupt handler unless such code is present.

Best Wishes
Guest








PostPosted: Tue Nov 14, 2006 7:27 am     Reply with quote

Hi Ttelmah,

I do have a bootloader, so I searched the forums for a clue as to why the code without the #build directive was destroying my bootloader but I can't seem to find much on redirecting interrupts. I thought my interrupt handler was
Code:

#int_timer2
void isr_relocate()
{
   printf ("hi interrupt");
   putc (0x0D);
   putc (0x0A);
}


I have also tried
Code:

#int_GLOBAL
void isr_relocate()
{
   printf ("hi interrupt");
   putc (0x0D);
   putc (0x0A);
}

but this gives me a compiler error something about an unprotected call to interrupt??????

I just need a nudge in the right direction, I'm working with two unknowns here interrupts and timers. I'd like to learn more about both.
TEK66TIM



Joined: 03 Nov 2004
Posts: 13

View user's profile Send private message

PostPosted: Tue Nov 14, 2006 8:08 am     Reply with quote

Hi Ttelmah,

I thought about your post and added to my bootloader the following:
Code:

#int_GLOBAL
void relocated_interrupt
{
   goto_address (0x1000);
}

and my interrupt and timer seem to be working, thanks for the tip.
Ttelmah
Guest







PostPosted: Tue Nov 14, 2006 8:10 am     Reply with quote

The #int directive, says that what follows, is 'meant' to be the handler for a particular interrupt. However, your #build is loating this up at 1000. Your bootloader, needs to contain interrupt relocation code, so that when an interrupt occurs (and the processor jumps automatically to address 18), a jump takes place to address 1000, or your 'handler' will never get called (which is why I said you _effectively_ don't have a handler...).
The same applies to int_global (it is always present, but normally generated by the compiler). To write an int_global, _you_ need to save every register that is in use, and check which interrupt is actually occuring. You cannot call high level code like 'printf', till this is done.
Look at 'bootloader.c' (in the examples). It contains a _int_global_ handler, which then jumps to 'loader end+5'. The main program, then includes 'bootloader.h', which relocates _it's_ interrupt handler to 'loader end+5' (+9, for PCH)
So the bootloader code, needs to contain an int_global handler, forcing a jump to the relocated handler.
Your 'running' program, needs to have it's origin set above the bootloader, and it's interrupt address set to match the address used as the jump target by the bootloader int_global routine.

Best Wishes
TEK66TIM



Joined: 03 Nov 2004
Posts: 13

View user's profile Send private message

PostPosted: Tue Nov 14, 2006 8:48 am     Reply with quote

Ok,

I tried in my bootloader the
Code:

#int_GLOBAL
void relocated_interrupt
{
   goto_address (0x1000);
}
 

and the printf statement in my main code printed but I can't get the timer to work properly, I tried, in my bootloader
Code:

#int_timer2
void relocated_interrupt
{
   goto_address (0x1000);
}

and this still hoses my bootloader, I'm sorry I may just be dumb this morning, but I don't quite understand.

Do I need to relocate the global interrupt in my bootloader code to the end of my bootloader and then add the timer 2 interrupt jump to 0x1000 in my bootloader?
Ttelmah
Guest







PostPosted: Tue Nov 14, 2006 9:09 am     Reply with quote

The #int_global one is right, but you also need to force your main code up to after the loader. Look at bootloader.h. Notice that it is relocating both the interrupt code, _and_ the main routine. Your bootloader also needs to jump to the relocated 'main'.

Best Wishes
TEK66TIM



Joined: 03 Nov 2004
Posts: 13

View user's profile Send private message

PostPosted: Tue Nov 14, 2006 9:47 am     Reply with quote

The code at the top of the post is my main code and it is set to start at address 0x2000, the first four startup locations are placed at the end of the code memory along with some flags used to hand the program back to the bootloader it's big but here is my bootloader
Code:

#include <18f4620.h>
#include <stdlib.h>
#fuses NOLVP, NOWDT, EC_IO, NOBROWNOUT
#use delay (clock=25000000)
#use rs232 (baud=115200, xmit=PIN_E1, rcv=PIN_E0) // used for 452 and 4620 chip mother board

#int_timer2
void relocated_interrupt ()
{
   goto_address (0x1000);
}


//func
void read_data_frames ();
void process_data_record ();
int16 hexkey_to_int16 (int8 *ptr_data_array);
int8 hexkey_to_int8 (int8 *ptr_data_array);
void erase_eeprom ();
void check_serport ();
void flag_control ();


//var
int1 extadd_flag = 0;
int1 read_first_add_flag = 0;

int32 byte_count;
int8 data_array [264];
int8 data_h;
int8 data_hm;
int8 data_lm;
int8 data_l;
int16 temp1;
int16 bytes_to_send;
int16 total_frames;
int16 count1;
int16 count2;
int8 record_array [48];
int8 rcount = 0;


void main (void)
{
   delay_ms (2000);

   printf ("running bootloader");
   putc (0x0D);
   putc (0x0A);

   flag_control ();
}


void flag_control ()
{
   if (read_program_eeprom (0x0000FFFC) == 0x0001) // user pgm writes flag before handing back control to bootloader 3FFE
   {
      erase_eeprom ();
      check_serport ();
   }

   if (read_program_eeprom (0x0000FFE0) != 0xFFFF) // first bytes of user pgm 3FF0
   {
      if (read_program_eeprom (0x0000FFF8) == 0x0001) // bootloader writes this flag just before running user pgm 3FFC
      {
         if (read_program_eeprom (0x0000FFF4) == 0x0001) // user pgm writes this flag to show it's running ok 3FFA
         {
            delay_cycles (1);
            //goto_address (0x00003FF0); // runs user pgm
            goto_address (0x0000FFE0);
         }
         else
         {
            erase_eeprom ();
            check_serport ();
         }
      }
      else
      {
         erase_eeprom ();
         check_serport ();
      }
   }
   else
   {
      erase_eeprom ();
      check_serport ();
   }
}


void check_serport ()
{
   int8 data;
   int8 count1;
   int16 count2;

   printf ("waiting for data records");
   putc (0x0D);
   putc (0x0A);

   for (count1 = 0; count1 < 60; count1 ++)
   {
      for (count2 = 0; count2 < 0xFDE8; count2 ++)
      {
         if (kbhit())
         {
            if (getc () == 0x31)
            {
               putc (0x0D);
               putc (0x0A);
               delay_ms (100);
               do
               {
                  read_data_frames ();
               }
               while (1);
            }
         }
         delay_us (1);
      }
      putc (0x21);
   }
   putc (0x0D);
   putc (0x0A);
   printf ("resetting cpu");
   putc (0x0D);
   putc (0x0A);
   reset_cpu ();
}


void erase_eeprom ()
{
   int32 adr_cnt;

   for (adr_cnt = 0x00001000; adr_cnt <= 0x0000FFC0; adr_cnt += 64) // erases eeprom just after bootloader to end of rom
   {
      erase_program_eeprom (adr_cnt);
   }
}


void read_data_frames ()
{
   rcount = 0;
   delay_ms (200);

   putc (0x63);

   data_h = getc ();
   data_hm = getc ();
   data_lm = getc ();
   data_l = getc ();

   byte_count = make32(data_h, data_hm, data_lm, data_l);

   total_frames = byte_count / 264;
   temp1 = total_frames * 264;
   bytes_to_send = byte_count - temp1;

   printf ("byte count = %lu", byte_count);
   putc (0x0D);
   putc (0x0A);
   printf ("frame count = %lu", total_frames);
   putc (0x0D);
   putc (0x0A);
   printf ("rem bytes count = %lu", bytes_to_send);
   putc (0x0D);
   putc (0x0A);

   delay_ms (200);

   do
   {
      for (count1 = 0; count1 < total_frames; count1 ++)
      {
         putc (0x7A);

         for (count2 = 0; count2 < 264; count2 ++)
         {
            data_array [count2] = getc ();
         }
         delay_ms (100);
         for (count2 = 0; count2 < 264; count2 ++)
         {
            record_array [rcount] = data_array [count2];
            rcount ++;
            //byte_count --;

            if (record_array [rcount - 1] == 0x0A)
            {
               process_data_record ();
               rcount = 0;
            }
         }
         delay_ms (100);
      }
      delay_ms (100);

      putc (0x78);

      for (count2 = 0; count2 < bytes_to_send; count2 ++)
      {
         data_array [count2] = getc ();
      }
      delay_ms (100);
      for (count2 = 0; count2 < bytes_to_send; count2 ++)
      {
         record_array [rcount] = data_array [count2];
         rcount ++;
         //byte_count --;

         if (record_array [rcount - 1] == 0x0A)
         {
            process_data_record ();
            rcount = 0;
         }
      }
      delay_ms (100);
   }
   while (byte_count != 0);
}



void process_data_record ()
{
   int8 count;
   int8 check_sum = 0x00;
   int8 data_1 = 0x00;
   int8 data_2 = 0x00;
   int16 data_3 = 0x00;
   int8 record_type = 0x00;
   int8 check_total = 0x00;
   int8 record_length = 0x00;
   int8 data_count = 0x00;
   int16 real_check_total = 0x0000;
   int16 address = 0x0000;
   int16 ext_address;
   int32 address32 = 0x00000000;

   record_type = hexkey_to_int8 (& record_array [7]);
   check_sum = hexkey_to_int8 (& record_array [rcount - 4]);

   for (count = 1; count < rcount - 5; count += 2)
   {
      real_check_total += hexkey_to_int8 (& record_array [count]);
   }

   check_total = make8 (real_check_total, 0);
   check_total = 0x100 - check_total;

   if (check_total == check_sum)
   {
      printf ("|");
      record_length = hexkey_to_int8 (& record_array [1]);
      address = hexkey_to_int16 (& record_array [3]);

      if (record_type == 0x04) // deals with extended address records reads first ignores second, second writes to config bits
      {
         ext_address = hexkey_to_int16 (& record_array [9]);

         if (ext_address > 0x0000)
         {
            extadd_flag = 1;
         }
         else if (ext_address == 0x0000)
         {
            extadd_flag = 0;
         }
      }

      address32 = make32 (ext_address, (address));

      if (record_type == 0x01) // end of record type so time to write eeprom record
      {
         read_first_add_flag = 0;
         write_program_eeprom (0x0000FFF8, 0x0001);
         printf ("starting user code now");
         putc (0x0D);
         putc (0x0A);
         delay_cycles (1);
         //goto_address (0x00003FF0);
         goto_address (0x0000FFE0);
      }


      if (record_type == 0x00 && extadd_flag == 0)
      {

         if (address > 0x0003)
         {
            data_count = 0x09;
            for (count = 0; count < record_length; count += 0x02) // writes eeprom record by record
            {
               data_1 = hexkey_to_int8 (& record_array [data_count]);
               data_2 = hexkey_to_int8 (& record_array [data_count += 0x02]);
               data_3 = make16 (data_2, data_1);
               write_program_eeprom (address32, data_3);
               data_count += 0x02;
               address32 += 0x02;
            }
         }
         else if (address == 0x0000 && read_first_add_flag == 0) // stores first 4 instructions of downloaded code
         {
            data_1 = hexkey_to_int8 (& record_array [9]);
            data_2 = hexkey_to_int8 (& record_array [11]);
            data_3 = make16 (data_2, data_1);
            write_program_eeprom (0x0000FFE0, data_3);

            data_1 = hexkey_to_int8 (& record_array [13]);
            data_2 = hexkey_to_int8 (& record_array [15]);
            data_3 = make16 (data_2, data_1);
            write_program_eeprom (0x0000FFE2, data_3);
            read_first_add_flag = 1;
         }
      }
   }
   else
   {
      printf ("checksum not valid reset cpu");
      putc (0x0D);
      putc (0x0A);
      delay_ms (1000);
      reset_cpu ();
   }
}


int16 hexkey_to_int16 (int8 *ptr_data_array) // converts 4 ascii characters to a 16bit int
{
   int8 count;
   int16 result = 0x0000;

   for (count = 0; count < 4; count ++)
   {
      if (*ptr_data_array >= 0x41 && *ptr_data_array <= 0x46)
      {
         result = result * 0x10 + (*ptr_data_array) - 0x41 + 0x0A;
      }
      else if (*ptr_data_array >= 0x30 && *ptr_data_array <= 0x39)
      {
         result = result * 0x10 + (*ptr_data_array) - 0x30;
      }
      ptr_data_array ++;
   }
   return (result);
}


int8 hexkey_to_int8 (int8 *ptr_data_array) // converts 2 ascii characters to a 8bit int
{
   int8 count;
   int8 result = 0x00;

   for (count = 0; count < 2; count ++)
   {
      if (*ptr_data_array >= 0x41 && *ptr_data_array <= 0x46)
      {
         result = result * 0x10 + (*ptr_data_array) - 0x41 + 0x0A;
      }
      else if (*ptr_data_array >= 0x30 && *ptr_data_array <= 0x39)
      {
         result = result * 0x10 + (*ptr_data_array) - 0x30;
      }
      ptr_data_array ++;
   }
   return (result);
}

it works except for the relocating isr problem is my int_timer2 code ok?
Ttelmah
Guest







PostPosted: Tue Nov 14, 2006 10:12 am     Reply with quote

First, it needs to be #int_global, that handles the jump, not int_timer2.
Secondly, #org, does not do the relocation required. You need to relocate _everything_, including the hidden 'boot' jump. Again _look at how bootloader.h does the relocation_. Notice the 'reset=' part of the build statement.

Best Wishes
TEK66TIM



Joined: 03 Nov 2004
Posts: 13

View user's profile Send private message

PostPosted: Tue Nov 14, 2006 10:31 am     Reply with quote

I see that they also relocate the reset vector but in my bootloader I put the start-up for user code at the end of flash myself so the cpu_reset() in my user code goes back to the bootloader. My bootloader works fine and the user code enters the isr
Code:

#int_timer2
void tmr2_int()
{
   count ++;
   if (count == 2000)
   {
      printf ("hi interrupt");
      putc (0x0D);
      putc (0x0A);
      count = 0;
      clear_interrupt (int_timer2);
   }
}

and prints over and over but I can't seem to change the time between print statements if the isr was not working why does it print?
Ttelmah
Guest







PostPosted: Tue Nov 14, 2006 11:18 am     Reply with quote

The point about 'reset=', is not just that it relocates the reset vector, but that _you_ then know where the entry point to get to the main code _is_. If you just org the code, there is nothing whatsover to say how to get to the main routine. There _will_ be serial code, and timer code placed in front of this, so the behaviour will be completely indeterminate.

Best Wishes
TEK66TIM



Joined: 03 Nov 2004
Posts: 13

View user's profile Send private message

PostPosted: Tue Nov 14, 2006 11:22 am     Reply with quote

Hi Ttelmah,

I got it to work, thanks for the help.

Tim
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