I can't get out from interrupt driven serial communication
You have ser not declared as volatile. What this means is the compiler doesn't know it can be changed in an ISR.

Essentially ser is initialised to 1. In the main() function, the compiler will examine the code and see that it gets to the while(ser) loop. Now as far as it can see, ser is never changed from the moment it is initialised to the moment the while() loop is reached (because it can see that the main() function doesn't call anything that changes the value). It can also see that ser doesn't change within the while() loop.

What this means is as far as the compiler can see, the while() loop will always be entered because ser is 1, but never exited because ser is not changed anywhere that it knows the execution can reach.

It then says, well if the while() loop will never exit, then there is no point checking the value of ser, nor is there any point including any of the code after the loop (as it will never be reached). The whole loop will optimise to simply:

rjmp .-2


Which represents an infinite loop (it will jump back to itself and repeat forever).



But wait I hear you cry. ser can be changed. It's modified in the ISR. Well, ok, it is, you know that, but the compiler doesn't. It is unaware that the processor can suddenly jump to another bit of code all on its own (well, when an interrupt is triggered actually). You need to tell it that this can happen.

By declaring something as volatile, it instructs the compiler to always load from memory the value of that memory whenever it is used. This means that the compiler can't assume that it will never change, because it has been told that it specifically must check. It is no longer able to say with certainty that the value in the memory is the value it put there at the beginning.