Forum: Mikrocontroller und Digitale Elektronik AVR, Devices über 64k FLASH erkennen?


von Rudolph R. (rudolph)


Lesenswert?

Gibt es einen Weg automatisch zu erkennen ob der Code für einen AVR mit 
<=64k FLASH oder >64k FLASH compiliert wird?

Testen auf _AVR31_, _AVR51__ und __AVR6_ fällt mir jetzt dazu ein.
Ich bin aber nicht sicher damit alles zu erwischen.
Und käme ein _AVR7_ dazu würde das ja nicht mehr funktionieren.

Ich will je nach Target automatisch pgm_read_byte_near() und 
pgm_read_byte_far() umschalten lassen.

von c-hater (Gast)


Lesenswert?

Rudolph R. schrieb:

> Gibt es einen Weg automatisch zu erkennen ob der Code für einen AVR mit
> <=64k FLASH oder >64k FLASH compiliert wird?
1
.IFDEF RAMPZ
2
...
3
.ENDIF

Ähnlich für die Unterscheidung <=128k vs. >128k:
1
.IFDEF EIND
2
...
3
.ENDIF

von Rudolph R. (rudolph)


Lesenswert?

Danke!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

c-hater schrieb:
> .IFDEF RAMPZ

Es gibt Devices, die RAMPZ für RAM-Zugriff verwenden. Daher sollte 
besser auf z.B. ELPM getestet werden:
1
#if defined __AVR_HAVE_ELPM__

https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html#AVR-Built-in-Macros

Und avr-libc hat Makros wie FLASHEND:
1
$ echo | avr-gcc -xc - -E -dM -mmcu=atmega128 -include avr/io.h | sort | grep 'END\b'
2
#define E2END 0x0FFF
3
#define FLASHEND 0x1FFFF
4
#define RAMEND 0x10FF
5
#define XRAMEND 0xFFFF
-->
1
#include <avr/io.h>
2
#if FLASHEND < 0x10000

von c-hater (Gast)


Lesenswert?

Johann L. schrieb:

> c-hater schrieb:
>> .IFDEF RAMPZ
>
> Es gibt Devices, die RAMPZ für RAM-Zugriff verwenden.

Und weniger als 64k Flash haben? Kannst du Beispiele nennen?

von c-hater (Gast)


Lesenswert?

c-hater schrieb:

> Und weniger als 64k Flash haben? Kannst du Beispiele nennen?

Nein, das kann er natürlich nicht.

Deswegen ist sein Einwurf genau nur als eins zu werten: Eine Sache, die 
eine völlig unnötige Abhängigkeit zum gcc schafft. Also eigentlich das 
typische Microsoft-Konzept: wir schaffen unnötige Abhängigkeiten, damit 
du Dummdödel von Programmierer allein schon aus Faulheit auch in Zukunft 
als "Multiplikator" für unseren Schmutz agierst.

Leute, laßt euch nicht von solchen Typen verarschen und an die Kandare 
nehmen. Denkt beim Programmieren auch immer über die Wirkungen der 
verwendeten Infrastruktur nach. Die für auch selber und die für eure 
Kunden.

Das beste Konzept ist immer eine Minimierung der Abhängigkeiten.

Hier ist das wirklich mal sehr einfach möglich. Also: Tut besser nicht, 
was Lilith rät...

(Wer sich mit der Bibel nicht so auskennt: Lilith ist das Werkzeug des 
Teufels, die ultimative Verführerin. Ich selber bin zwar Atheist, halte 
das aber im konkreten Fall für ein schönes poetisches Bild für den 
Sachverhalt). Man könnte auch einfach sagen: nimm' von niemandem einen 
Rat an, dessen Intentionen du nicht hinterfragt hast...

von Stefan F. (Gast)


Lesenswert?

Die gcc ist allerdings kein "Schmutz" vor deren Abhängigkeit man sich 
fürchten muss. Schon gar nicht ist die Bestandteil eines Imperiums, dass 
die Welt knechten will.

Die gcc ist ein Community Open-Source Projekt.

von c-hater (Gast)


Lesenswert?

Stefan U. schrieb:

> Die gcc ist allerdings kein "Schmutz" vor deren Abhängigkeit man sich
> fürchten muss. Schon gar nicht ist die Bestandteil eines Imperiums, dass
> die Welt knechten will.
>
> Die gcc ist ein Community Open-Source Projekt.

Mit vielen Verfechtern, deren Methoden denen der religiösen Eifererer 
diverser Kirchen kaum noch nachstehen und auch nicht denen der 
kommerziellen Konkurrenz...

Genau das ist ja das Schlimme...

von Stefan F. (Gast)


Lesenswert?

Du bist mir ja einer ...
Dann geh' doch zu Apple!

von c-hater (Gast)


Lesenswert?

Stefan U. schrieb:

> Du bist mir ja einer ...
> Dann geh' doch zu Apple!

Was hat Apple damit zu tun? Mal abgesehen davon, dass die (auf Grund der 
überwiegend geistig minderbemittelten Nutzerschaft) noch sehr viel 
erfolgreicher damit sind, unnötige Abhängigkeiten als "Standard" zu 
setzen. Das ist, wovon Microsoft träumt und offensichtlich auch viele 
gcc-Verfechter...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

c-hater schrieb:
> c-hater schrieb:
>
>> Und weniger als 64k Flash haben? Kannst du Beispiele nennen?
>
> Nein, das kann er natürlich nicht.
>
> Deswegen ist sein Einwurf genau nur als eins zu werten: Eine Sache, die
> eine völlig unnötige Abhängigkeit zum gcc schafft.

Also eine "Antwort, die eine Abhängigkeit schafft".  soso. ROFL.

Es ist eine Antwort auf die Frage des OT, abhängig von der Flashgröße 
(bedingt) zu compilieren, unter Verwendung einer zugegeben unbekannten 
Toolchain.

Die Frage habe ich also für eine Toolchain beantwortet, für die ich die 
Antwort sicher weiß, und zwar — wie vom OT gewünscht — unanhängig vom 
konkreten Devices, sei es ein existierendes oder ein zukünftiges.

von S. Landolt (Gast)


Lesenswert?

Und in der .inc-Datei von Atmel steht dann für den ATmega128 für 
FLASHEND der Wort-Wert mit 0xffff. Das ist schon etwas befremdlich.

von Stefan F. (Gast)


Lesenswert?

Der Programmspeicher ist 16bit breit. Die Adresse 0x0000 zeigt auf das 
erste Wort. Die Adresse 0x0001 zeigt auf das zweite Wort. Wort, nicht 
Byte. Beim RAM ist das anders, das wird Byteweise adressiert.

von S. Landolt (Gast)


Lesenswert?

Durchaus klar und altbekannt.
Was ich mit 'befremdlich' meinte, war, dass gcc FLASHEND umdefiniert.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> Was ich mit 'befremdlich' meinte, war, dass gcc FLASHEND umdefiniert.

Adressen wie char* in C sind immer Byte-Adressen. Übrigens kommt das 
define aus den Geadern der avr-libc, welche auch mit Assembler zusammen 
funktionieren.

von Conny G. (conny_g)


Lesenswert?

c-hater schrieb:
> Stefan U. schrieb:
>
>> Du bist mir ja einer ...
>> Dann geh' doch zu Apple!
>
> Was hat Apple damit zu tun? Mal abgesehen davon, dass die (auf Grund der
> überwiegend geistig minderbemittelten Nutzerschaft) noch sehr viel
> erfolgreicher damit sind, unnötige Abhängigkeiten als "Standard" zu
> setzen. Das ist, wovon Microsoft träumt und offensichtlich auch viele
> gcc-Verfechter...

Du wäscht bestimmt auch mit Waschnüssen statt Waschmittel und verwendest 
Abspülwasser für die Toilette? :-)

von Rudolph R. (rudolph)


Lesenswert?

Schon krass wie das hier immer wieder aus dem Ruder läuft.

Johann L. schrieb:
> Es gibt Devices, die RAMPZ für RAM-Zugriff verwenden. Daher sollte
> besser auf z.B. ELPM getestet werden:

Das geht zwar schon schwer in Richtung Dinge die mich überhaupt nicht 
interessieren, weil sich da gefälligst der Compiler drum kümmern soll.

Aber ich bin ja neugierig.

In www.atmel.com/images/Atmel-0856-AVR-Instruction-Set-Manual.pdf findet 
sich erstmal das hier:

---
RAMPX, RAMPY, and RAMPZ
Registers concatenated with the X-, Y-, and Z-registers enabling 
indirect addressing of the whole data
space on MCUs with more than 64KB data space, and constant data fetch on 
MCUs with more than 64KB program space.
---

Nur, es gibt doch gar keine AVR mit mit mehr als 64kB Daten?
Und versagen würde der Test auf RAMPZ doch nur auf Devices mit 64k FLASH 
und >64k SRAM?

Vielleicht ist die Beschreibung auch nicht mehr aktuell und es gibt 
Devices bei denen der Speicher anders organisiert ist, so mehr in einem 
Adress-Raum hintereinander anstatt parallel mit getrennten Adressen?

Klingt jetzt irgendwie nicht so schlau, wenn man ein Device hat mit z.B. 
64k FLASH und ein paar k SRAM die hinter dem FLASH liegen, dann würde 
das doch erheblich Overhead erzeugen FLASH und SRAM auf die gleiche Art 
und Weise anzusprechen.
Wenn das insgesamt unter 64k bleibt sieht die Sache ja wieder anders 
aus.

Welche Devices sind das konkret die RAMPZ für den RAM-Zugriff verwenden?

von spess53 (Gast)


Lesenswert?

Hi

>Welche Devices sind das konkret die RAMPZ für den RAM-Zugriff verwenden?

RAMPZ wird auch für den byteweisen Zugriff auf den Flash, via 
Assemblerinstruktion 'LPM', verwendet.

MfG Spess

von Horst M. (horst)


Lesenswert?

Rudolph R. schrieb:
> Welche Devices sind das konkret die RAMPZ für den RAM-Zugriff verwenden?

XMEGA64A1U und XMEGA128A1U mittels EBI.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

spess53 schrieb:
> RAMPZ wird auch für den byteweisen Zugriff auf den Flash, via
> Assemblerinstruktion 'LPM', verwendet.

Via ELPM bzw. ELPMx; wobei die Unterstützung letzterer die Unterstützung 
ersterer impliziert.

von Rudolph R. (rudolph)


Lesenswert?

spess53 schrieb:
> RAMPZ wird auch für den byteweisen Zugriff auf den Flash, via
> Assemblerinstruktion 'LPM', verwendet.

LPM verwendet RAMPZ doch gar nicht, sondern ELPM macht das?

Horst M. schrieb:
> XMEGA64A1U und XMEGA128A1U mittels EBI.

Naja, XMega unterstütze ich soweit ohnehin nicht, das wäre dann wieder 
ein eigener Pfad.

Was mir aber gerade beim rumprobieren aufgefallen ist, das vorhandensein 
von RAMPZ ist in der Tat kein Hinweis auf ein Device >64k.
1
#if defined(RAMPZ) /* we have an AVR with more than 64kB FLASH memory */
2
#error !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Während das zum Beispiel für Mega328 und Mega644 durch läuft, gibt es 
mit dem Mega1284 einen Fehler, also wie gewünscht.
Aber Mega4808, Mega4809 haben nur 48kB und das gibt einen Fehler.

Noch interessanter finde ich, AT90CAN32, AT90CAN64 und AT90CAN128 sind 
offenbar alle gleich, die haben alle drei das RAMPZ Register.
Aber ELPM hat nur AT90CAN128.
Ein pgm_read_byte_far() wird mit dem 90CAN32 auch anstandlos übersetzt, 
nur ist das ja nicht notwendig.

Okay, streng genommen könnte man auch auf Devices >64k FLASH ein 
pgm_read_byte_near() verwenden solange alles in die unteren 64k passt.
Aber das lässt sich eher nicht automatisch einfangen. :-)

Also wofür auch immer übrhaupt mindestens 90CAN32, 90CAN64, Mega4808 und 
Mega4809 ein RAMPZ Register haben, die sind unter 64k und damit führt 
der Test darauf nicht zum gewünschten Ergebnis.

Ich habe jetzt sicher nicht alle Megas durchprobiert,
1
#if defined (__AVR_HAVE_ELPM__)
2
#error !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

macht aber gar nichts auf 90CAN32, 90CAN64, Mega4808 und diversen 
anderen.

Also dann so, danke.

Dass das jetzt nur für den GCC funktioniert kümmert mich auch wenig, 
einen anderen Compiler nutze ich da sowieso nicht.

Und der Block fängt so an:
1
#ifndef ARDUINO
2
  #if defined (__GNUC__)
3
    #if  defined (__AVR__)

Andere Targets unter anderen Compilern sind da gar kein Problem, man 
muss das nur entsprechend dazu eintragen.

Die XMega müssten unter "__AVR_XMEGA__" laufen, oder?
Aber mit den Dingern werde ich mich jetzt sowieso nicht mehr 
beschäftigen.
Eher kommt da ein SAME51 dazu.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rudolph R. schrieb:
> Dass das jetzt nur für den GCC funktioniert kümmert mich auch wenig,
> einen anderen Compiler nutze ich da sowieso nicht.

Gibt ja noch FLASHEND, das ist sogar noch näherliegend als ELPM weil es 
sich direkt auf die Flashgröße bezieht und nicht auf den 
Instruktionssatz.

ATmega4808/9 kennt die aktuelle Release nicht.  Da braucht's dann nen 
eigenen specs für, z.B. von Atmel.

> Die XMega müssten unter "__AVR_XMEGA__" laufen, oder?

Ja, siehe

http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html#AVR-Built-in-Macros

Wobei inzwischen einige der Makros nicht mehr built-in sind sondern via 
specs qua Kommandozeile -D definiert werden.

: Bearbeitet durch User
von Rudolph R. (rudolph)


Lesenswert?

Johann L. schrieb:
> Gibt ja noch FLASHEND, das ist sogar noch näherliegend als ELPM weil es
> sich direkt auf die Flashgröße bezieht und nicht auf den
> Instruktionssatz.

Nur reicht FLASHEND dafür ja nicht unbedingt.

Ich habe gerade in die Unterlagen von dieser neuen "megaAVR 0-series" 
geschaut und die haben als feature "The Flash memory is mapped into the 
data space".
Ist jetzt dafür soweit kein Problem aber starten bei 0x4000 und haben 
mit 48k das FLASHEND bei 0xffff.
Wer weiss was denen noch so einfällt, mit mehr als 48k läuft das ja aus 
dem 16Bit Adress-Raum und FLASHEND wäre entsprechend jenseits 0xffff.
Klingt jetzt nicht besonders sinnvoll, okay.
Aber man müsste auch noch prüfen ob FLASHSTART überhaupt definiert ist 
und falls ja ob FLASHEND - FLASHSTART größer 0xffff ist.

Also irgendwann ist ja auch mal Schluss, ich lasse das jetzt mit ELPM 
erstmal so. :-)

> ATmega4808/9 kennt die aktuelle Release nicht.  Da braucht's dann nen
> eigenen specs für, z.B. von Atmel.

Na, irgendwas wurde wohl gemacht für "AVR 8-bit GCC Toolchain 3.6.1", 
die lassen sich ja auswählen und für compilieren.
Aber scheinbar haben die gar kein RAMPZ, ich wundere mich schon warum 
das denen angedichtet wird.
Wenigstens kein ELPM.

von spess53 (Gast)


Lesenswert?

Hi

>Wer weiss was denen noch so einfällt, mit mehr als 48k läuft das ja aus
>dem 16Bit Adress-Raum und FLASHEND wäre entsprechend jenseits 0xffff.
>Klingt jetzt nicht besonders sinnvoll, okay.

Nö. Der Flash kann mehr als 48 k haben:

megaAVR® 0-Series Manual(S.19):

>The Flash memory can be read with the
>LPM instruction. For the LPM instruction, the Flash start address is 0x0000.

MfG Spess

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rudolph R. schrieb:
> Ich habe gerade in die Unterlagen von dieser neuen "megaAVR 0-series"
> geschaut und die haben als feature "The Flash memory is mapped into the
> data space".

Die momentan unterstützten Devices mit diesem Feature (avrtiny, 
avrxmega3) haben alle einen Flash-Start bei 0x0, allerdings ist der 
Flash auch im RAM Adressraum zu sehen, und zwar ab einem bestimmten 
Offset: 0x4000 für avrtiny und 0x8000 für avrxmega3.

Das funktioniert ähnlich wie mit SRAM vs. I/O, welche einen Offset haben 
(der auch 0 sein darf) und die mit LDx/STx vs. IN/OUT zugegriffen 
werden.

Bei RAM vs. Flash ist der Offset __AVR_PM_BASE_ADDRESS__, wobei hier ein 
Offset von 0 bedeutet, dass Flash nicht im RAM-Space sichtbar ist. Der 
Zugriff erfolgt per LDx vs. LPM.

__AVR_PM_BASE_ADDRESS__ braucht einen normalerweise nicht zu 
interessieren; der Offset wird von den Tools automatisch addiert:
1
// foo.c
2
const int C, *volatile pC;
3
const __flash int F, *volatile pF;
4
5
int main (void)
6
{
7
    pC = &C;
8
    pF = &F;
9
}
1
$ avr-gcc-8 foo.c -mmcu=attiny816  -Os -save-temps -fno-common -Wl,-Map,foo.map
1
; foo.s
2
main:
3
  ldi r24,lo8(C)
4
  ldi r25,hi8(C)
5
  sts pC,r24
6
  sts pC+1,r25
7
  ldi r24,lo8(F)
8
  ldi r25,hi8(F)
9
  sts pF,r24
10
  sts pF+1,r25
11
  ...
12
.global  F
13
  .section  .progmem.data,"a",@progbits
14
  ...
15
.global  C
16
  .section  .rodata
17
  ...
1
# foo.map
2
Address of section .data set to 0x803e00
3
...
4
                0x00008000                __RODATA_PM_OFFSET__ = DEFINED (__RODATA_PM_OFFSET__)?__RODATA_PM_OFFSET__:0x8000
5
...
6
.text           0x00000000       0x7a
7
...
8
 *(.progmem.*)
9
 .progmem.data  0x00000034        0x2 foo.o
10
                0x00000034                F
11
...
12
.rodata         0x0000807a        0x2 load address 0x0000007a
13
 *(.rodata)
14
 .rodata        0x0000807a        0x2 foo.o
15
                0x0000807a                C
16
...
17
.data           0x00803e00        0x0 load address 0x0000007c
18
...
1
$ avr-objdump -dr a.out > foo.lst
2
3
00000058 <main>:
4
  58:  8a e7         ldi  r24, 0x7A  ; 122
5
  5a:  90 e8         ldi  r25, 0x80  ; 128
6
  5c:  80 93 02 3e   sts  0x3E02, r24  ; 0x803e02 <pC>
7
  60:  90 93 03 3e   sts  0x3E03, r25  ; 0x803e03 <pC+0x1>
8
  64:  84 e3         ldi  r24, 0x34  ; 52
9
  66:  90 e0         ldi  r25, 0x00  ; 0
10
  68:  80 93 00 3e   sts  0x3E00, r24  ; 0x803e00 <_edata>
11
  6c:  90 93 01 3e   sts  0x3E01, r25  ; 0x803e01 <_edata+0x1>
12
  ...

> Ist jetzt dafür soweit kein Problem aber starten bei 0x4000 und haben
> mit 48k das FLASHEND bei 0xffff.

FLASHEND sollte bei 0xbfff sein.

> Wer weiss was denen noch so einfällt, mit mehr als 48k läuft das ja aus
> dem 16Bit Adress-Raum und FLASHEND wäre entsprechend jenseits 0xffff.

Wenn es wirklich mal solche Devices gibt, d.h. 
FLASHEND + __AVR_PM_BASE_ADDRESS__ > 0xffff, dann wäre ein Teil des 
Flash nicht mehr im RAM-Space sichtbar.

Die von dir genannten neuen 0-Devices sind noch nicht von den GNU-Tools 
unterstützt, evt. müsste nen neuer Multilib-Zweig her; zum Testen geht 
aber wohl auch avrxmega3 mit -Wl,--defsym,__RODATA_PM_OFFSET__=0x4000.

>> ATmega4808/9 kennt die aktuelle Release nicht.  Da braucht's dann nen
>> eigenen specs für, z.B. von Atmel.

specs sind Text, das geht auch von Hand; z.B. ableiten von 
specs-attiny1616, und die Multilib müsste auch passen.  Die meiste 
Arbeit ist dann io.h, was ja auch in crt*.o verwendet wird.

: Bearbeitet durch User
von Rudolph R. (rudolph)


Lesenswert?

Diese "0-Series" nutze ich selber sowieso nicht, ist mir nur beim 
Durchklicken durch diverse Devices und Compilieren dafür aufgefallen.

Solange es keinen AVR mit CAN-FD gibt, vorzugsweise zwei Kanäle, werde 
ich mich von den AVR gezwungenermassen auch langsam abwenden müssen.

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.