Zeiger Strings ausgeben?!

OP #5107452
Lesenswert?

Moin Moin.

Wieso hängt sich der µC auf, wenn ich die Strings ausgeben will?
1
typedef struct  
2
{
3
  const char *ProjectName;
4
  const char *HardwareVersion;
5
  const char *SoftwareVersion;
6
  const char *HardwareDate;
7
  const char *SoftwareDate;
8
}DevBoard_t;
9

10
DevBoard_t  Message={
11
  
12
  .ProjectName    = "DevBoard\r\n",
13
  .HardwareVersion  = "Hardware Version 1.0\r\n",
14
  .SoftwareVersion  = "Software Version 1.0\r\n",
15
  .HardwareDate    = "Hardware from 18.04.17\r\n",
16
  .SoftwareDate    = "Software from 30.05.17\r\n",
17
};
18

19
uart_puts(Message.ProjectName);
Moderator Persönliche Seite #5107460
Lesenswert?

Jan H. schrieb:
> Wieso hängt sich der µC auf, wenn ich die Strings ausgeben will?

Vielleicht, weil die Funktion uart_puts() fehlerhaft implementiert 
wurde? Sonst gibt es auf kleinen µCs noch tausend andere Gründe, wie 
z.B. Größe des RAMs usw.

Ein
1
int main ()
2
{
3
    fputs (Message.ProjectName, stdout);
4
    return 0;
5
}

funktioniert unter Linux jedenfalls einwandfrei.

Um welchen µC handelt es sich denn? Und wie sieht der Rest des Programms 
aus?

Hängt sich der µC wirklich auf, wenn Du nur so eine kleine 
main()-Funktion hast, oder hast Du noch 30000 weitere Zeilen an Code?

Bitte ein compilierbares, reproduzierbares Beispiel angeben.
OP #5107516
Lesenswert?

1
/*************************************************************************
2
Function: uart_putc()
3
Purpose:  write byte to ringbuffer for transmitting via UART
4
Input:    byte to be transmitted
5
Returns:  none          
6
**************************************************************************/
7
void uart_putc(unsigned char data)
8
{
9
    unsigned char tmphead;
10

11
    
12
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
13
    
14
    while ( tmphead == UART_TxTail ){
15
        ;/* wait for free space in buffer */
16
    }
17
    
18
    UART_TxBuf[tmphead] = data;
19
    UART_TxHead = tmphead;
20

21
    /* enable UDRE interrupt */
22
    UART0_CONTROL    |= _BV(UART0_UDRIE);
23

24
}/* uart_putc */
1
/*************************************************************************
2
Function: uart_puts()
3
Purpose:  transmit string to UART
4
Input:    string to be transmitted
5
Returns:  none          
6
**************************************************************************/
7
void uart_puts(const char *s )
8
{
9
    while (*s) 
10
      uart_putc(*s++);
11

12
}/* uart_puts */

Diese werden verwendet..
Gast #5107561
Lesenswert?

Wahrscheinlich läuft der UART-Software-Puffer voll, wenn du den String 
ohne aktivierte Interrupts ausgibst. Dann wartet die Ausgabe bei
1
;/* wait for free space in buffer */
, weil kein Interrupt passiert, der den Puffer leert.

Gruß
Marius
Moderator Persönliche Seite #5107563
Lesenswert?

Jan H. schrieb:
> UART0_CONTROL    |= _BV(UART0_UDRIE);

Das Zeichen soll also in einer ISR ausgegeben werden. Wo ist die ISR 
dazu?

> Das passiert alles bevor sei() aufgerufen wird.

Wie soll das gehen? Ohne sei() kein Interrupt, ohne Interrupt kein 
ISR-Auffruf! Ohne ISR-Aufruf keine Ausgabe von Zeichen! Das kann so 
nicht gehen.

Pardon, aber mit so einer Salamitaktik kann man den Fehler nicht finden.

Ich wiederhole nochmal:

Bitte zeige ein compilierbares Programm mit reproduzierbarem Fehler. 
Sonst ist das ein Stochern im Dunkeln. Der Fehler kann überall sein, nur 
nicht in Deinem bisher gezeigten Code.
Moderator Persönliche Seite #5107582
Lesenswert?

Jan H. schrieb:
> Was hat denn die Ausgabe mit einem Interrupt zu tun?

Dein oben zitiertes uart_puts() gibt das Zeichen gar nicht aus. Es 
kopiert das Zeichen nur in einen Ringbuffer und aktiviert dann den 
UART-Empty-Interrupt. Dieser wird ausgelöst, wenn der UART leerläuft. 
Die ISR kopiert dann das nächste auszugebende Zeichen ins UART-Register. 
Die eigentliche Ausgabe läuft also nicht in uart_puts(), sondern in der 
ISR.

> Das habe ich noch
> nicht ganz verstanden. Wenn ein Zeichen rein kommt, weiß ich das es ein
> Interrupt gibt.

Siehe oben. Wenn der UART kein Zeichen auszugeben hat, dann löst er 
einen UDRIE-Interrupt aus. Genau diesen aktiviert Dein uart_puts():

> UART0_CONTROL |= _BV(UART0_UDRIE);

> Jetzt funktioniert es aber. Scheint wirklich der Puffer voll zu laufen.

Lass mich raten: Du hast den sei()-Aufruf nach vorne gezogen.

Achja, bitteschön. ;)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren