two USART ISR definitions

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi everyone!

I'm making a .c & .h files for a little project that are gonna controle the USART.
I've declared the two Interrupt Service Routine (rx and tx) on the .c file, and I get this error

Quote:

../uart.c:35: error: redefinition of 'ISR'

../uart.c:22: error: previous definition of 'ISR' was here

I understand what it means but I can't understand why is happening. If I only declare one of them I don't get any error. Maybe is it because is not the main file.c of the project and it's on a lib??

ISR(USART_RX_vect)
{
	*(pBin+counter)=UDR0;
	counter++;

	if(UDR0==0x04)	counter=0;

	
}

ISR(USART_TX_vect)
{
	counter++;
	if(txEnd==0)
	{
		UDR0=*(pBout+counter);
		if(*(pBout+counter)==0x04) txEnd=1;

	}
	else
	{
		counter=0;
		CLEARBIT(PORTD,2); 
	}
	
}

Could you help me please!

Thanks in advance!! :D :D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It could be that the name (USART_TX_vect or USART_RX_vect ) is undefined or spelled differently in the lib file. Or the TX vector is not differenciated between the UDRE vector and the TX_completed vector.

Are you using the same variable named 'counter' for the offset into both the pBin and pBout buffer? Or are they different variables with the same name? Why are you using the sentinal value 0x04 that is received from external computer to initialize the receive_buffer offset?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you including at the top of the file? If not, you are defining two functions, both called ISR that take a single int as a parameter and return an int.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks both!!

Koshchi:
Thanks. I had the #include commented and I didn't notice it until you mentioned it. Thank you very much.
Clearly I'm still a newbie...I feel a bit ashamed.

Simonetta:
The var "counter" it's the same for both ISR because it's a half duplex communication.
I'm using the 0x04 because it's the end of the data frame that I'm using. This way the "counter" it's 0 for the next communication . It's not a good idea??

Thanks one more time!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The variables that are used in different interrupts should have slightly different names, even if they are doing the same thing.

The counter variable will need to be a global variable with a 'volatile' keyword in its definition. Otherwise it gets recreated each time that the interrupt routine is entered and deleted each time that the interrupt routine returns to main code. If they have exactly the same name then the same variable will be used for both the Tx and Rx interrupt and it will mess up the count.

Granted it may work OK even if the variable has the same name and if the same variable is used for both routines, but I suggest using a variable called RxCounter for the RX interrupt and one called TxCounter for the TX interrupt. But the first time that the RX receives 0x04 then it will set the variable counter to 0. If the TX routine is retransmitting received data then it will send pBout[1] instead of pBout[counter].

Also, you may want to have the counter increment after the TX==0 test otherwise the TX routine will never send the first element of the pBout buffer, which is pBout[0] or *(pBout+counter) when counter ==0. But the test never sees the counter equal to 0 because counter is immediately incremented upon entry to the interrupt routine.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The counter variable will need to be a global variable with a 'volatile' keyword in its definition.
I disagree with respect to volatile. If the variable is used only in the ISR, it most certainly does not need to be volatile. And even when the same variable is used in both ISRs, then volatile is not needed since no other code can be run while the ISR is running.

And for a variable that is used only within a single ISR (but needs to retain its value between calls), a local static variable would be better.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
And even when the same variable is used in both ISRs, then volatile is not needed since no other code can be run while the ISR is running.
That is true in the usual case of when the ISR is written not to be interruptable. In the rare case where nested interrupts are allowed it may be necessary to define a variable as volatile even if it used only by two ISRs.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The variables that are used in different interrupts should have slightly different names, even if they are doing the same thing.

Would that even apply to 'i' used in a for() loop?
Quote:

The counter variable will need to be a global variable with a 'volatile' keyword in its definition. Otherwise it gets recreated each time that the interrupt routine is entered and deleted each time that the interrupt routine returns to main code. If they have exactly the same name then the same variable will be used for both the Tx and Rx interrupt and it will mess up the count.

You are confusing two concepts there. For both ISR()s to "see" the same variable it would need to have global context so is located in .data or .bss in which case it is not "created/destroyed" when the ISR is entered/exited. Only stack frame automatic locals are created/destroyed in this way but the very nature of their locality means that one ISR() cannot "see" the other whether you made it 'volatile' or not.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The original poster's ISR code increments the variable 'counter' each time that the interrupt happens. This variable has to be preserved somehow in order to maintain its value in between interrupts.
It is my impression that this is done by using the keyword 'volatile'.

The main reason that I hate C language so much is that there is an exception to every simple rule because the programmers who made the language in the first place always wanted a way for themselves to get around the restrictions that a well-structured language imposes. Hence they made C a low-level language with high-level data structures. Assembler is a much simpler and direct language to work with because there is never any question about the scope of any variable. If a value is in a memory location it stays there until the user changes it.
I recognize that on the register/op_code level C and assembler are the same thing with different syntaxes. C is taught to students because it is easy for beginners to learn (once the compiler is set up for them) to do simple things. It also is very flexible for experts in the language who understand how it works on a register/op-code level. But for everyone else in the middle levels, C is a raging nightmare. Mid-level AVR programmers just trying to get a non-trivial but not extensive project functioning spend far more time debugging C code than they would if the code were written in assembler and following a well-structured formal algorythm or flow-chart.

One characteristic about AVRfreaks is that whenever a beginner asks a straight-forward question about a homework project that they have goofed up in C, and someone gives a straightforward answer to that specific project in C, then another (quote unquote)more advanced user will jump in saying that the suggested approach is wrong and cites some highly-advanced technical trivia to 'prove' it. This is a defect of both the language and the compiler writers' mentality. I call it "Programmer's disease" and caution people entering technical fields to recognize it and avoid it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
It is my impression that this is done by using the keyword 'volatile'.
Your impression is incorrect. The volatile attribute simply tells the compiler that the associated variable can change at any time due to action outside of the function being processed by the compiler. Due to this possible "volatility", the compiler must not rely on values of the variable that it may hold in registers, i.e., it must reload the variable each time it is used. Further, the attribute tells the compiler that, regardless of what it may conclude about the usefulness of a read or write it must generate code to perform each and every access implied by the code (assuming that the code sequence is reachable, of course).

It sounds like you may be confusing the effect of volatile with that of static. The static attribute tells the compiler two things: 1) the variable must not be visible outside the function or module containing its definition, and 2) storage for the variable must be statically allocated. For variables that are defined outside of any function, only the first effect is important since the second one would apply anyway. For variables defined inside a function, both effects are important because normally, a variable defined inside a function is dynamically allocated (i.e. on the stack) and only lives as long as the function is executing.

For further study:
http://en.wikipedia.org/wiki/Vol...
http://en.wikipedia.org/wiki/Sta...

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The main reason that I hate C language so much is that there is an exception to every simple rule because the programmers who made the language in the first place always wanted a way for themselves to get around the restrictions that a well-structured language imposes.

I don't understand Chinese - so it must be a stupid language?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The main reason that I hate C language so much is that there is an exception to every simple rule
Please show me one single rule in C that has an exception.

Regards,
Steve A.

The Board helps those that help themselves.