Forum: Compiler & IDEs putchar funktion soll auf Progmem umgebaut werden


von Simon (Gast)


Lesenswert?

Ich habe Folgende Function:
1
void uart_usb_send_buffer(U8 *buffer, U8 nb_data)

Diese wurde bisher mit:
1
int uart_usb_putchar(int data_to_send)
2
{
3
   uart_usb_send_buffer((U8*)&data_to_send, 1);
4
   return data_to_send;
5
}

verwendet.

Ich würde nun gerne PSTR("") damit verwenden.

Ich dachte da an soetwas hier: aber das funzt nicht :-)
1
void uart_usb_send_buffer_P(const char *data)
2
{
3
   while (pgm_read_byte(data) != 0x00)
4
     uart_usb_send_buffer(pgm_read_byte(data++));
5
}

von Stefan E. (sternst)


Lesenswert?

Das hier
1
     uart_usb_send_buffer(pgm_read_byte(data++));
 passt ja auch überhaupt nicht zu
1
void uart_usb_send_buffer(U8 *buffer, U8 nb_data)

1
void uart_usb_send_buffer_P(const char *data)
2
{
3
   U8 byte;
4
   while ((byte = pgm_read_byte(data++)) != 0x00)
5
     uart_usb_send_buffer(&byte,1);
6
}

Und für die Zukunft:
"aber das funzt nicht" ist keine hinreichende Fehlerbeschreibung. Und 
wenn (wie offensichtlich in diesem Fall) der Compiler dir den Code um 
die Ohren haut, dann schreibe zumindest die Fehlermeldungen des Compiler 
mit dazu.

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:

> Ich dachte da an soetwas hier: aber das funzt nicht :-)
>
>
1
> void uart_usb_send_buffer_P(const char *data)
2
> {
3
>    while (pgm_read_byte(data) != 0x00)
4
>      uart_usb_send_buffer(pgm_read_byte(data++));
5
> }
6
>

logisch.
Das kann nicht gehen.

Die uart_usb_send_buffer will die Adresse einer Speicherfläche haben, 
von der sie sich die Daten holt. Du hast aber keine Speicherfläche, du 
versuchst die Daten selbst in die Funktion reinzustopfen.
1
void uart_usb_send_buffer_P(const char *data)
2
{
3
  char c = pgm_read_byte(data);
4
5
  while( c != 0x00) {
6
    uart_usb_send_buffer( &c, 1 );
7
    c = pgm_read_byte(++data);
8
  }
9
}

Aber: Hast du denn keine uart_send Funktion, die einfach nur einen U8 
übernimmt? Eine
void uart_usb_send_byte(U8 buffer);

Normalerweise benutzt eine Funktion wie uart_usb_send_buffer eine 
derartige Funktion als Basis um mehrere Zeichen auszugeben.

Edit:
Dein ganzer funktionaler Aufbau scheint nicht zu stimmen.
uart_usb_putchar ist die einfachere Funktion. Die sollte sich nicht auf 
uart_usb_send_buffer stützen, sondern genau umgekehrt: 
uart_usb_send_buffer benutzt uart_usb_putchar um seine Funktionalität zu 
erledigen. Und die int in uart_usb_putchar glaub ich dir auch nicht. 
Beides zusammen ergibt eine völlig unnötige Beschäftigungstherapie für 
den µC.

von Simon (Gast)


Lesenswert?

Die sache ist das PSTR() es nicht im RAM ablegt, somit geht wenn ich
das richtig verstanden habe auch kein pointer auf den RAM.. und da liegt 
mein Problem, ich brauche irgendwie die Möglichkeit die Funktion auch 
mit PSTR verwenden zu können.




Es gibt ja noch in der unteren funktion ein
"Usb_write_byte(*buffer);"
aber ich wollte die funktionen da ansich nicht auseinander nehmen.
Gibts da keine einfacherer Möglichkeit?



Das ganze stammt aus der AVR usb lib (CDC Demo)
1
/** 
2
  * @brief This function fills the USB transmit buffer with the new data. This buffer
3
  * is sent if complete. To flush this buffer before waiting full, launch
4
  * the uart_usb_flush() function.
5
  * 
6
  * @param data_to_send 
7
  * 
8
  * @return 
9
  */
10
int uart_usb_putchar(int data_to_send)
11
{
12
   uart_usb_send_buffer((U8*)&data_to_send, 1);
13
   return data_to_send;
14
}
15
16
17
/** 
18
  * @brief This function transmits a ram buffer content to the USB.
19
  * This function is mode efficient in term of USB bandwith transfer.
20
  * 
21
  * @param U8 *buffer : the pointer to the RAM buffer to be sent 
22
  * @param data_to_send : the number of data to be sent
23
  */
24
void uart_usb_send_buffer(U8 *buffer, U8 nb_data)
25
{
26
   U8 zlp;
27
   
28
  if(!Is_device_enumerated())
29
     return;
30
   
31
   // Compute if zlp required
32
   if(nb_data%TX_EP_SIZE) 
33
   { zlp=FALSE;} 
34
   else { zlp=TRUE; }
35
   
36
   Usb_select_endpoint(TX_EP);
37
   while (nb_data)
38
   {
39
      while(Is_usb_write_enabled()==FALSE); // Wait Endpoint ready
40
      while(Is_usb_write_enabled() && nb_data)
41
      {
42
         Usb_write_byte(*buffer);
43
         buffer++;
44
         nb_data--;
45
   }
46
      Usb_ack_in_ready();
47
   }
48
   if(zlp)
49
   {
50
      while(Is_usb_write_enabled()==FALSE); // Wait Endpoint ready 
51
      Usb_ack_in_ready();
52
}
53
}

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:
> Die sache ist das PSTR() es nicht im RAM ablegt, somit geht wenn ich
> das richtig verstanden habe auch kein pointer auf den RAM.. und da liegt
> mein Problem, ich brauche irgendwie die Möglichkeit die Funktion auch
> mit PSTR verwenden zu können.

Na, ja. Hast du ja jetzt.
Stefans und mein Vorschlag sind gleichwertig.


> Es gibt ja noch in der unteren funktion ein
> "Usb_write_byte(*buffer);"
> aber ich wollte die funktionen da ansich nicht auseinander nehmen.
> Gibts da keine einfacherer Möglichkeit?

Könnte man wahrscheinlich machen. Aber da ist noch soviel drumherum zu 
machen, dass es sich wohl nicht lohnt.

Allerdings sollte man dann über die String Funktion noch mal nachdenken. 
In diesem Fall ist es dann nicht so schlau, wegen jedem Zeichen wieder 
durch die ganze Rundherum-Prozedur in uart_usb_send_buffer 
durchzulaufen.

Ich würde das zumindest soweit versuchen zu optimieren, dass aus dem 
Flash immer zb 4 Character geholt werden und diese 4 Character in einem 
aufwasch gesendet werden. Die 4 sind natürlich verhandelbar und könnten 
auch maximal zb 32 sein.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Sowas?
1
void uart_usb_send_buffer_P (const char *pstr)
2
{
3
  size_t len = strlen_P (pstr);
4
  char str[len];
5
6
  strcpy_P (str, pstr);
7
8
  uart_usb_send_buffer (str, len);
9
}

von Karl H. (kbuchegg)


Lesenswert?

Johann L. schrieb:

>   char str[len];

    char str[len+1];

von Simon (Gast)


Lesenswert?

Funzt bestens!

Vielen Dank, morgen durchdenke ich das mal in Ruhe.

Wie kommts zu der Warnung:

../uart_usb_lib.c:163: warning: pointer targets in passing argument 1 of 
'uart_usb_send_buffer' differ in signedness

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Simon schrieb:

> Wie kommts zu der Warnung:
>
> ../uart_usb_lib.c:163: warning: pointer targets in passing argument 1 of
> 'uart_usb_send_buffer' differ in signedness

Du mixt signed und unsigned pointer wild durcheinander.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.