bin zu blöd für progmem

Gast #100647
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
Gast #100648
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...
Gast #100649
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.
Gast #100650
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
Gast #100651
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++;
  };
  ...
Gast #100652
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
Gast #100654
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

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