Code:
void uart_send(const char *string)
{      
   do
    {
      // ... warten bis der Sendepuffer leer ist ...
       while (!( UCSRA & (1<<UDRE)))
         ;

        UDR = (const unsigned char)*string;
    }
    while (*string++);
}
warum const char *string ? einfach nur char* string reicht doch!

wie empfängst du den string, mitm terminal ?

ausserdem ist deine while bedingung falsch, die ist post-increment, d.h. du übermittelst auf jeden fall noch das stringterminal mit, ausserdem ist fragwürdig was der compiler mit den nicht konkadenierten(hoffentlich war das richtig geschrieben) "Hallo!" "\r\n" macht, da müsste mindestens noch ein + dazwischen, oder gleich das '\r''\n' ans ende der uart_send methode verfrachten ...

zum fehler würd ich jetzt fast vermuten, dass in der schleifenbedingung versucht wird den WERT hinter dem pointer zu inkrementieren (und der ist laut deiner definition "const char* ptr" schreibgeschützt), ich würde sowas immer klammern *(ptr++) bzw. wenn cih den nachfolgenden wert prüfen will *(++ptr)