Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
vvyogi
PostPosted: May 29, 2012 - 12:52 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

Dear freaks,
I was testing for the nested interrupts using the code below.
I have two interrupt sources viz. Timer0 overflow and USART_RXC event.
Inside the Usart receive ISR, I disable the receive interrupt, do enable global interrupt's and intentionally use the delay of 1500 ms.
And as i expected when i send a char to the UART the correcponding RXC interrupt executes and the Timer0 interrupt fires without trouble.

But when i press multiple keys ie ' sdsddsd '
then i expect that the first char received by the UART will trigger the ISR,
After that i am disabling the RXCIE interrupt, and the other char's should just get lost(except one which is in the receive buffer as it is a two byte buffer), but interestingly the char's appear to queue and ISR is fired as many times as many chars i press.

Can someone explain why this is happening ???

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 29, 2012 - 12:57 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

sorry guy's, I could not send the whole text in one go, I got bad server request error so i am sending the code as attachment..
It has never occured before !

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
Kartman
PostPosted: May 29, 2012 - 03:02 PM
Raving lunatic


Joined: Dec 30, 2004
Posts: 9012
Location: Melbourne,Australia

Is the delay_ms actually working?
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: May 29, 2012 - 03:11 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 13961
Location: Vancouver, BC

Quote:
I got bad server request
Because you have a % in your code.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 29, 2012 - 04:19 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

Quote:
Is the delay_ms actually working?

yes. I have checked it. I'm sending the whole code in case you wish to check it @ ur end.

@koshchi
I didn't knew that. thank you. I'll make sure i don't upload a text with % in it.
Code:
#include<stdio.h>
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>


int put_char(char c, FILE *stream);
FILE myfile = FDEV_SETUP_STREAM(put_char,NULL,_FDEV_SETUP_WRITE);


int main(void){
      
      stdout = &myfile;
      //                        This is UART initialization
      UCSRA = 0;
      UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
      UCSRC = (1<<URSEL)|(3<<UCSZ0);
      UBRRH = 0;
      UBRRL = 35;
      DDRA = (1 << PA6);
      PORTA = 0x00;
      TCCR0 = 0x05;
      TIMSK = (1 << TOIE0);
      printf("STARTED\r");
      uint16_t value = 0;
      sei();
      while(1)
      {
         _delay_ms(50);
         value++;
         printf("value = (percent)d\r",value);
         
      }
   }
   
   
int put_char(char c, FILE *stream){
      while(!(UCSRA & (1<<UDRE)))
      ;
      UDR  = c;
      return 0;
      }
ISR(USART_RXC_vect){
      UCSRB &= ~(1<<RXCIE);
      sei();
      
      char ch;
      ch = UDR;      
      printf("\t char (percent)c",ch);
      printf("IN RXC");
      _delay_ms(500);
      _delay_ms(500);      
      _delay_ms(500);
      
      UCSRB |= (1<<RXCIE);
      }
ISR(TIMER0_OVF_vect){
      
      PORTA ^= (1<<PA6);
      
      
      }

PS: Instead of entering 'sdssdsdsd' i entered '123456789' and the queued char's were 1 2 3 & 9.
so my inference was wrong. The char's are not being queued.. some are getting lossed (viz 45678) but 9 is appearing. I am still trying to find out how ?

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 29, 2012 - 04:45 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 26115
Location: Wisconsin USA

Quote:

but 9 is appearing. I am still trying to find out how ?

Quote:

_delay_ms(500);
_delay_ms(500);
_delay_ms(500);

UCSRB |= (1<<RXCIE);


It is still in the buffer after your delays.

I have no idea what the purpose of this thought exercise is. If it were me, I'd "soft discard" unwanted characters. Anyway, revisit your datasheet. Doesn't it say something about flushing the buffers when RXEN is manipulated?
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 29, 2012 - 05:16 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

Quote:
I have no idea what the purpose of this thought exercise is

Ahh.. the initial purpose was to write a nested interrupt code. I have a application where i'm using nRF24l01+
[url](http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=119604)[/url]

along with UART communication.

The nRF working involves INT0_interrupt action. And i'm also doing UART network monitoring..
The priority for the UART is higher than nRF..
when nRF is operational there are chances that UART may need processing, and its possible that my code might be inside INT0_interrupt at that instant... I wanted to ditch that situation...
I have written a code for UART, when nRF operation is not involved that code work's super smooth, but when i incorporate the nRF code part... things get messy.

So my simple approach is to put all the network related code inside the USART_RXC interrupt..(previously cliff labelled a similar code of mine as "atrocious")..
but i can't see other solution.
The problem i posted in this thread came along the way and my curiocity to find the reason drove me here..
anyways

Quote:


_delay_ms(500);
_delay_ms(500);
_delay_ms(500);

UCSRB |= (1<<RXCIE);


It is still in the buffer after your delays.

I'm not manipulating RXEN
In that code after my isr is complete i re-enable the RXCIE Interrupt. What's wrong with it ?

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: May 29, 2012 - 05:39 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 13961
Location: Vancouver, BC

Why is your INT0 interrupt so long? ISRs should always be kept short.

Quote:
What's wrong with it ?
You are not clearing the global interrupt flag and you are not clearing the RCX interrupt flag.

_________________
Regards,
Steve A.

The Board helps those that help themselves.


Last edited by Koshchi on May 29, 2012 - 05:41 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 29, 2012 - 05:39 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 26115
Location: Wisconsin USA

Quote:

when nRF is operational there are chances that UART may need processing, and its possible that my code might be inside INT0_interrupt at that instant... I wanted to ditch that situation...

??? Why worry about it? Keep your ISRs skinny. You've got 2+ character times to catch up to the USART. Roughly a millisecond at usual comms speeds; an eternity.

See what a tangled web you are weaving trying to nest interrupts? The overhead for your interlocks and the like is probably greater than grabbing the USART character ans stuffing it into the receive buffer.
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 29, 2012 - 05:41 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 26115
Location: Wisconsin USA

Quote:

I'm not manipulating RXEN
In that code after my isr is complete i re-enable the RXCIE Interrupt. What's wrong with it ?


there isn't anything "wrong" as far as the way the AVR is operating. >>You<< have chosen to write the sequence shown; >>you<< have asked why you get the symptom. I told you. What part of that is confusing?
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 29, 2012 - 06:37 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

Oh don't get me wrong,
This is my current INT0 ISR code
Code:
ISR(INT0_vect){
    uint8_t status;   
    // If still in transmitting mode then finish transmission
    if (PTX) {
   
        // Read MiRF status
        mirf_CSN_lo;                                // Pull down chip select
        status = spi_fast_shift(NOP);               // Read status register
        mirf_CSN_hi;                                // Pull up chip select
      
      
        mirf_CE_lo;                             // Deactivate transreceiver
        RX_POWERUP;                             // Power up in receiving mode
        mirf_CE_hi;                             // Listening for pakets
        PTX = 0;                                // Set to receiving mode
      
        // Reset status register for further interaction
        mirf_config_register(STATUS,(1<<TX_DS)|(1<<MAX_RT)); // Reset status register
      hl_ack = 1;
    }
   else if(mirf_data_ready())
   {
         fl_data = 1;
         mirf_config_register(STATUS,(1<<RX_DR)); // Reset status register
   }   
   
}


and this is my rxc isr code
Code:
ISR(USART_RXC_vect)
   {
      
      char temp;      
      temp = UDR;      
         
      receive_buffer[r_index++] = temp;//
      
      if( temp == '$')
         {   
            r_index = 0;
         }   
      else if (temp == EOP )
         {
            trans_mode();
            receive_buffer[r_index] = '\0';
            Received_packet = YES;
            r_index = 0;
            
         }
      
   }


and this is main
Code:
int main(void)
   {
   Usart_Init();
   Port_Init();
   Variable_Init();
   Timer0_Init();
   TWI_init(48,0,0);
   
   recv_mode();// MPCM receiver select
   sei();
   
   
      while(1)
      {   
         nRF_poll_store_response(); //Task one
         
         if(Received_packet == YES) // Task Two
            {
            serve((char*)receive_buffer);
            Received_packet = 0;
            
            }
      }
   
   return 0;
   }


In This approach the problem is when TASK_ONE is being Done. And uC receives a packet, then it first finishes task at hand... but its required that the response be quick... So i thought of using the whole response code inside the ISR...
What you guy's suggest ??
I think i have started a new thread here unknowingly !

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 29, 2012 - 06:59 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 26115
Location: Wisconsin USA

Quote:

but its required that the response be quick...

Quote:

What you guy's suggest ??

Define what "quick" is.
Instrument your app, get some numbers, and tell us why it isn't "quick" enough.

I fail to see why you have to do stuff based on an interrupt trigger.

I don't know about your radio. The last time I worked with one it took some milliseconds to become "receive ready".
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 29, 2012 - 07:20 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

Quote:
Define what "quick" is.

In the context of my application "quick" would be response within 100ms.

the
Code:
nRF_poll_store_response();
is lengthy takes about 250ms to 300ms(And the best part it sometimes hangs)

In the application the frequency of UART communication will be quite less.. I want to give the UART a higher priority that nRF_code.

Is there a way to do so without making my code "atrocious"..

_________________
- Will find's a Way.


Last edited by vvyogi on May 29, 2012 - 08:49 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
jayjay1974
PostPosted: May 29, 2012 - 08:48 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 5727
Location: The Netherlands

Is that some external library function? I guess it's a blocking function, maybe wasting loads of CPU time.
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 29, 2012 - 08:51 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

yes that is a blocking function.. the details of it are here http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=119604
A short summary of what nRF_poll_store_response() is
Code:
mirf_set_TADDR((uint8_t *)T_add);//set's the target device address
mirf_set_RADDR((uint8_t *)T_add);// seems illogical but it is necessary to get the radio ack.
hl_ack = 0;
mirf_send((uint8_t *)"Hello !.",8);//send 8 bytes
//wait for a status response either success or failure
while(!hl_ack)// hl_ack is set by the INT0 interrupt
;
mirf_set_RADDR((uint8_t *)My_add);//change back my original address
flag = 0;
_delay_ms(50);
//wait 50ms for response from the target
if(flag){
 do some entries in eeprom
 }
//-done here


This above code makes the uC miss the timelines for response to uart packet.

_________________
- Will find's a Way.


Last edited by vvyogi on May 29, 2012 - 09:07 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
jayjay1974
PostPosted: May 29, 2012 - 09:03 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 5727
Location: The Netherlands

I don't see anything wrong with the RXISR function; except there is no protection against buffer overflows. GPS receiver by any chance?

You should break up the nRF_ function so it does its work little piece by little piece. I looked for it, but cannot find the source of it in any of the links you mentioned.
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 29, 2012 - 09:29 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

@jay
you are right i have not taken care of buffer overflow, that i will do..

the actual nRF function is as i mentioned above and uses this library
[url] http://www.tinkerer.eu/AVRLib/nRF24L01[/url]
along with this one
http://www.tinkerer.eu/AVRLib/SPI

and the function is

Code:
void nRF_poll_store_data(void)
   {
         mirf_set_TADDR((uint8_t *)T_add);//setting target address same as my address.
         mirf_set_RADDR((uint8_t *)T_add);// as said in datasheed it is necessary for receiving an hardware ack
         mirf_send((uint8_t *)"Hello",8);//send the packet
         hl_ack = 0;//this is flag for monitoring the firing of int0 interrupt, happens on transmission n reception o data
         fl_data = 0;//this is reception flag when a packet is there this flag goes high
         //printf("1");
         while(hl_ack == 0)//waiting till transmittion completes
         ;
         
         mirf_set_RADDR((uint8_t *)MyAdd);//immidiately set back my address to read the response from the target uC
         _delay_ms(10);   //waiting 10ms
         if(fl_data == 1)//if data arrived
            {
            
               mirf_config_register(STATUS,(1<<RX_DR));// this is the rx flag. clearing it for further reception
               
               mirf_get_data((uint8_t *)buffer); //reading the data in the buffer
               buffer[8] = '\0';
               store_block_eeprom((uint8_t *)buffer);
            }
   }

ISR(INT0_vect){
    uint8_t status;   
    // If still in transmitting mode then finish transmission
    if (PTX) {
   
        // Read MiRF status
        mirf_CSN_lo;                                // Pull down chip select
        status = spi_fast_shift(NOP);               // Read status register
        mirf_CSN_hi;                                // Pull up chip select
       
       
        mirf_CE_lo;                             // Deactivate transreceiver
        RX_POWERUP;                             // Power up in receiving mode
        mirf_CE_hi;                             // Listening for pakets
        PTX = 0;                                // Set to receiving mode
       
        // Reset status register for further interaction
        mirf_config_register(STATUS,(1<<TX_DS)|(1<<MAX_RT)); // Reset status register
      hl_ack = 1;
    }
   else if(mirf_data_ready())
   {
         fl_data = 1;
         mirf_config_register(STATUS,(1<<RX_DR)); // Reset status register
   }   
   
}

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
jayjay1974
PostPosted: May 29, 2012 - 09:50 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 5727
Location: The Netherlands

That function can easily be broken into smaller chunks by converting it into a state machine.
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 30, 2012 - 03:59 AM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

@jay can you explain that a bit in this code's context.. maybe a small-small example.. I have a little idea of state machines but i'll go read that.

PS:

i have following situation.

Code:
main(){
    TASK 1(); // This is the work uC has to do
     
       if(flag){
          Task 2();//This is conditional work
       }

TASK 1{
     task 1a;
     task 1b;
     task 1c;
       }
TASK 2{
     task 2a;
     task 2b;
     task 2c;
      }


Do you mean that i shd have each task as a state ?? and then do this
Code:
"current state+input = next state"

plz put some light into it.

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
Kartman
PostPosted: May 30, 2012 - 05:07 AM
Raving lunatic


Joined: Dec 30, 2004
Posts: 9012
Location: Melbourne,Australia

Have you read my tutorial on multitasking? It's in the tutorial section. Can't find it? Search for me and multitasking.

The general rule is (and you can break it if you fully understand te consequences) only do what is really necessary in the isr - anything that needs to wait or takes too long, then pull it out of the isr. Consider polling your RF chip in a timer isr and maybe use a state machine. It is probably ok doing one or two spi transactions in the isr (depending on the spi speed) and if you need to wait for something to happen,set your state to do this on the next tick.
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 30, 2012 - 06:45 AM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

Quote:
Have you read my tutorial on multitasking? It's in the tutorial section.

Aye aye sir.

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
jayjay1974
PostPosted: May 30, 2012 - 12:49 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 5727
Location: The Netherlands

It would roughly look like this:

Code:

void nRF_poll_store_data(void)
{
 static uint8_t state,delay_counter;

 switch(state)
  {
  case 0:if (need_to_send)
         {
           mirf_set_TADDR((uint8_t *)T_add);
           mirf_set_RADDR((uint8_t *)T_add);
           mirf_send((uint8_t *)"Hello",8);
           hl_ack = 0;
           fl_data = 0;
           need_to_send=0;
           state=1;
         }
 
         break;

  case 1:if  (hl_ack == 1)
          {
          mirf_set_RADDR((uint8_t *)MyAdd);

          delay_counter=10;

          state=2;
          }
         break;

   case 2:delay_counter-=1;
     if (delay_counter==0)
          {
            state=3;
          }
          break;

   case 3:if (fl_data == 1)//if data arrived
          {           
             mirf_config_register(STATUS,(1<<RX_DR));
             mirf_get_data((uint8_t *)buffer);
             buffer[8] = '\0';
             store_block_eeprom((uint8_t *)buffer);

        state=0;
          }
          break;
   }
 
 View user's profile Send private message  
Reply with quote Back to top
vvyogi
PostPosted: May 30, 2012 - 01:51 PM
Hangaround


Joined: Apr 04, 2010
Posts: 185
Location: india

@jay
thankyou+++++ I will be back with results.
again thankyou+++++

_________________
- Will find's a Way.
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits