mikrocontroller.net

Forum: Compiler & IDEs bin zu blöd für progmem


Autor: john (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi alle,

ich bin zu blöd um strings im rom abzlegen glauube ich. ich habe
mehrere beiträge gelesen, aber irgendwie klappt das nicht. vielleicht
habe ich nur was übersehen. hier der code

const char pms01[] PROGMEM = "starting ...\0";
const char pms02[] PROGMEM = "starting VS1001\0";
const char pms03[] PROGMEM = "VS1001 OK\0";
const char pms04[] PROGMEM = "starting MMC\0";
const char pms05[] PROGMEM = "MMC OK\0";
const char pms06[] PROGMEM = "starting FAT\0";
const char pms07[] PROGMEM = "FAT OK\0";

PGM_P pgm_strings[2] PROGMEM = {
    pms01,
  pms02
};


// if c == 0x01 then a new line is added
void USART_sendpgmstring (u08 id, u08 c) {
   char buf[16];
  char *str = &buf[0];
  u08 i =0;
  strcpy_P(buf, pgm_strings[id]);
  // parse and send string until end is found
  while ((*str != (char)0) && (*str != (char)10)&& (i<16)){
     USART_send ((u08)*str++);
    i++;
   };
  if(c ==0x01) USART_newline();
}

aber über usart kommen nur hyroglyphen raus.

john

Autor: Stefan Seegel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi John!

Gleiches Problem hatte ich die Tage auch, nur mit nem LCD.
Schau mal ein paar Threads früher, da wurde genau das Problem erklärt:
http://www.mikrocontroller.net/forum/read-2-94515.html

Knackpunkt ist dass das array pgm_strings Zeiger auf Strings im Flash
sind, aber die Zeiger selber auch im Flash stehen. Du musst also
erstmal die Zeiger aus dem Flash ziehen. Wenn du dein pgm_strings[id]
zum testen mal durch pgm_strings[0] oder pgm_strings[1] ersetzt müsste
es gehen, weil dann der Compiler dann die Adresse gleich einsetzt...

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
IMHO ist es übrigens bald sinnvoller, in solchen Konstellationen die
Zeigertabelle selbst (die ja nicht sehr groß ist) als normale Variable
zu deklarieren, statt sie in den progmem zu nageln.  Das spart die
LPMs dafür.

Autor: john (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi,

erstmal danke, ich sehe jetzt was.
ich habe jetzt -->

const u08 pms01[] PROGMEM = "starting ...\0  ";
const u08 pms02[] PROGMEM = "starting VS1001";
const u08 pms03[] PROGMEM = "VS1001 OK\0     ";
const u08 pms04[] PROGMEM = "starting MMC\0  ";
.
.
.

PGM_P pgm_strings[34] PROGMEM = {
    pms01,
    pms02,
    .
    .
    .

void USART_sendpgmstring (u08 id, u08 c) {
  u08 buf[16];
  u08 *str = &buf[0];
  u08 i =0;
  strcpy_P(buf, pgm_strings[0]+(16*id));
  while ((*str != (char)0) && (*str != (char)10)&& (i<16)){
     USART_send ((u08)*str++);
    i++;
   };
  if(c ==0x01) USART_newline();
}


aber das ist ja noch nicht richtig. ich verschwende ja jetzt immer ein
paar byte, da die breite ja bei 16 byte festgelegt ist.

john

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo kommt denn die `16 * id' her?  Sieht mir so aus, als hättest Du das
Konzept von Zeigern in C nicht verstanden.


void USART_sendpgmstring (u08 id, u08 c) {
  char *buf;
  char c;

  buf = (char **)pgm_read_word(pgm_strings + id);
  while ((c = pgm_read_byte(buf)) != '\0' && c != '\n') {
     USART_send (c);
     buf++;
  };
  ...

Autor: Stefan Seegel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau, so müssts wohl gehen, weil man erst den Pointer aus dem PROGMEM
ließt und dann die Chars aus dem Progmem.
Was ich aber immer noch nicht kapiert habe: Wieso ließt man Pointer als
"Word" ? Wer/was/wo steht definiert dass ein Pointer 2 Bytes lang ist
? Ist das halt einfach so bei AVRs ?

Stefan

Autor: john (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg : Danke hat geklappt. hatte das zweite * bei (char **) vergessen,
als ich es so probiert hatte ;) danke nochmal

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wieso ließt man Pointer als "Word"? Wer/was/wo steht definiert dass
> ein Pointer 2 Bytes lang ist? Ist das halt einfach so bei AVRs?

Zumindest bei den derzeitigen AVRs sind Zeiger 16 bits breit.  Das
wird bei künftigen AVRs (ATmega256) nicht mehr notwendig der Fall
sein.  (Für den Zugriff auf den RAM sehr kleiner AVRs würden auch 8
bit breite Zeiger genügen, aber das ist erstens hier nicht das Thema
und zweitens vom AVR-GCC nicht berücksichtigt.)

Streng genommen sind die Zeiger in den ROM beim ATmega128 auch jetzt
schon 17 bits breit, wenn man sie auf Daten zeigen läßt (also für den
ELPM oder ESPM Befehl), aber nur 16 bits breit, wenn man sie auf Code
zeigen läßt (Adressen von Funktionen), da der Programmcode in 16 bit
breiten Worten zählt.  AVR-GCC kann diese Situation aber nicht
wirklich handhaben (mit Ausnahme der Makros für den Bootloader) und
behilft sich derzeit, indem maximal 64 KB konstante Daten unterstützt
werden und diese durch den Linkerscript garantiert vor dem
ausführbaren Code plaziert werden.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.