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

Re: Int_Global routine for i2c doesn't work

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



Joined: 16 Jan 2008
Posts: 61

View user's profile Send private message

Re: Int_Global routine for i2c doesn't work
PostPosted: Wed Mar 06, 2013 7:16 pm     Reply with quote

Hi I am trying to use global routine for different interrupts in the same routine. But when i try following i2c clock goes low and it freezes. Collected data at slave is multiple values of same data.
Code:


#use I2C(SLAVE,sda=PIN_C4,scl=PIN_C3,address=0xB0,SLOW,FORCE_HW)


/*
*  We have two kind of interrupts: I2C and UART. I2C have a priority over UART.
*  We have a system timer which runs on the Timer Interrupt.
*/


#bit T0IE       =  0x00B.5  //! Timer0 Interrupt Enable Bit
#bit I2CE       =  0x091.3  //! I2C Interrupt Enable Bit   
#bit USART_TX_E =  0x091.4  //! UART TX Interrupt Enable Bit
#bit USART_RX_E =  0x091.5  //! UART RX Interrupt Enable Bit

#bit T0IF       =  0x00B.2  //! Timer0 Interrupt Flag Bit
#bit I2CF       =  0x011.3  //! I2C Interrupt Flag Bit   
#bit USART_TX_F =  0x011.4  //! UART TX Interrupt Flag Bit
#bit USART_RX_F =  0x011.5  //! UART RX Interrupt Flag Bit   

#BYTE TXREG = 0x19A           //Transmit char
#BYTE RCREG = 0x199           //Receive char

#define I2C_BUF_SIZE    32
#define UART_BUF_SIZE   64

/*
#define LED_ON()         output_high(PIN_E0)  //! LED On
#define LED_OFF()        output_low(PIN_E0)   //! LED Off

#define MAX_ARGC 8 

*/
unsigned int8 uart_flag=0;
int32 rx_data=0;

int32 test_flag=0;


//! Design Parameters for UART
char uart_rx_buf[UART_BUF_SIZE], *uart_ptr;

//! Design Parameters for I2C
unsigned int8 i2c_state;
unsigned int8 i2c_in_data, i2c_addr;
char i2c_rx_buf[I2C_BUF_SIZE],i2c_tx_buf[I2C_BUF_SIZE], *i2c_rxptr, *i2c_txptr;

char test,incr;



#int_global
//#INT_SSP
void default_isr(){

   if(I2CF){ //!Priority 1 Interrupt: I2C 
      clear_interrupt(INT_SSP);
      i2c_state = i2c_isr_state();     
      if((i2c_state == 0)||(i2c_state == 0x80))
         i2c_read();

      //! Slave Transmit
      if(i2c_state >= 0x80){ //! Master is Requesting Data         
         
         test = *i2c_txptr;
         i2c_write(*i2c_txptr);   //(check/test this statement for syntax correction)
         //!currently employed as '\r' but can be changed later
         //if((*i2c_txptr == '\r')||(i2c_txptr == (i2c_tx_buf+I2C_BUF_SIZE))){
            //i2c_txptr = i2c_tx_buf;
         //}   
         //i2c_txptr++;
      }

      //! Slave Receive
      else if(i2c_state>0){
         i2c_in_data = i2c_read();         
         *i2c_rxptr++ = i2c_in_data;
         
         //!currently employed as '\r' but can be changed later
         if((i2c_in_data == '\r')){
            i2c_rxptr = i2c_rx_buf;
            i2c_in_data = 0;
         }     
      }                     

     

   }

/*
   if(USART_RX_F){   //! Simple UART receiving interrupt routine
      clear_interrupt(INT_RDA);     //! Clear Interrupt     
      *uart_ptr++ = RCREG;            //! Store data in buffer and update the buffer pointer 
     
      if((RCREG == '\r')||(uart_ptr == uart_rx_buf+UART_BUF_SIZE)){ //! Reset back the pointer             
         uart_ptr = uart_rx_buf;
         uart_flag = 1;
      }
   }
   
   if(T0IF){ //!Priority 3 Interrupt: Timer   
      ;
   }
*/
}

 
void main()
{   
   char compstr[] =  "|";
   char str[20];
   char * pch; 
   char * argv[12], argc=0; 
   float value;
   int32 val;

   
   
   //! Fill out the buffer
   for(int k=0; k<8; k++)
      i2c_tx_buf[k] = 0xA1;
   
   
   uart_ptr = uart_rx_buf;    //Assign the pointer before you enable the interrupts
   i2c_rxptr = i2c_rx_buf;    //Assign the pointer before you enable the interrupts
   i2c_txptr = i2c_tx_buf;    //Assign the pointer before you enable the interrupts
   
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);
   enable_interrupts(INT_RDA);   

   
   while(1){
   };
}

In above code if I disable #int_global and enable #int_ssp line. And remove clear_interrupt(INT_SSP) line it works perfectly fine. But then it becomes interrupt routine only for i2c.

In past product code i have used the same approach for different timer and external interrupt and it successfully worked. I don't know what am I doing wrong with the i2c interrupt.

Thank you very much for the help.

nehal
_________________
nehal
Ttelmah



Joined: 11 Mar 2010
Posts: 19355

View user's profile Send private message

PostPosted: Thu Mar 07, 2013 2:23 am     Reply with quote

Start at the beginning.
If you use #INT_GLOBAL, it becomes _your_ responsibility to save _every_ register used in the interrupt routine(s). The compiler does nothing for you.
Your routine is saving nothing, so will corrupt the status register, W register, page select register, etc. etc., resulting in nothing working....

You need to go through the assembler of every routine you use in the INT_GLOBAL (including simple things like testing the flags etc.), note down every register that is affected, and start your routine with code to save all these. Then before exiting the routine, restore these. In your case this will include things like the table pointer registers.

Then you don't want to clear interrupts at the start of the routines. In the case of INT_SSP, clearing the interrupt, means that i2c_isr_state won't work correctly, since you have changed one of the bits it uses. In the case of the serial handler, the interrupt _cannot be cleared_, until the byte has been read. It'll re-set itself, since the condition that triggers the interrupt is still 'TRUE'. You must handle the interrupt event, _before_ clearing the interrupt flags. This is required by the hardware.

Then, pointer accesses are slow. You do:
Code:

         test = *i2c_txptr;
         i2c_write(*i2c_txptr);   //(check/test this statement for syntax correction)

//Instead use:
         test = *i2c_txptr;
         i2c_write(test);   //(check/test this statement for syntax correction)

You are accessing the same byte twice using pointers, and doubling the amount of work involved....

With the interrupt disable removed, then the i2c_isr_state starts to apparently work, _but_ the code still won't work for real, since as soon as you start actually doing something in the 'main' loop, this will suffer from corrupted values as register contents are destroyed. Also since you are then not clearing the interrupt, the code keeps looping to the I2C routines....

Best Wishes
nehallove



Joined: 16 Jan 2008
Posts: 61

View user's profile Send private message

PostPosted: Fri Mar 08, 2013 3:44 pm     Reply with quote

Thank you very much Ttelmah.
_________________
nehal
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