| Author |
Message |
|
|
Posted: May 29, 2012 - 12:52 PM |
|

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.
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 12:57 PM |
|

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.
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 03:02 PM |
|

Joined: Dec 30, 2004
Posts: 9012
Location: Melbourne,Australia
|
|
| Is the delay_ms actually working? |
|
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 03:11 PM |
|

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.
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 04:19 PM |
|

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.
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 04:45 PM |
|


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? |
|
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 05:16 PM |
|

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.
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 05:39 PM |
|

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
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 05:39 PM |
|


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. |
|
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 05:41 PM |
|


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? |
|
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 06:37 PM |
|

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.
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 06:59 PM |
|


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". |
|
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 07:20 PM |
|

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
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 08:48 PM |
|


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. |
|
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 08:51 PM |
|

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
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 09:03 PM |
|


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. |
|
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 09:29 PM |
|

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.
|
| |
|
|
|
|
|
Posted: May 29, 2012 - 09:50 PM |
|


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. |
|
|
| |
|
|
|
|
|
Posted: May 30, 2012 - 03:59 AM |
|

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.
|
| |
|
|
|
|
|
Posted: May 30, 2012 - 05:07 AM |
|

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. |
|
|
| |
|
|
|
|
|
Posted: May 30, 2012 - 06:45 AM |
|

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.
|
| |
|
|
|
|
|
Posted: May 30, 2012 - 12:49 PM |
|


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;
}
|
|
|
| |
|
|
|
|
|
Posted: May 30, 2012 - 01:51 PM |
|

Joined: Apr 04, 2010
Posts: 185
Location: india
|
|
@jay
thankyou+++++ I will be back with results.
again thankyou+++++ |
_________________ - Will find's a Way.
|
| |
|
|
|
|
|