Hallo, ich möchte eine Peripherie- oder Speicheradresse den Xmega-DMA Adressregistern mit einer Funktion zuweisen: void InitDmaChannel(DMA_CH_t channel, register8_t *source, register8_t *destination, register16_t BlockCnt, register8_t TrigSrc, bool forever) { ... channel.SRCADDR0= (uint8_t)(((uint32_t)source)>>0); channel.SRCADDR1= (uint8_t)(((uint32_t)source)>>8); channel.SRCADDR2= (uint8_t)(((uint32_t)source)>>16); ... } ebenso... Bsp: DMA.CH0.SRCADDR0= (((uint32_t)(&Buffer))>>0*8) & 0xFF; DMA.CH0.SRCADDR1= (((uint32_t)(&Buffer))>>1*8) & 0xFF; DMA.CH0.SRCADDR2= (((uint32_t)(&Buffer))>>2*8) & 0xFF; Aber auch mit dem gefundenen Beispiel (s.o.) gibt der Compiler die Warnung aus: "cast from pointer to integer of different size" - Wie kann man das elegant schreiben, ohne dass Warnungen produziert werden? - Das mit dem "& 0xFF" kann man doch besser mit einem cast uint8_t() machen? - Sind nicht einige Klammern überflüssig? Alexxx
Vielleicht uintptr_t statt uint32_t? Soweit ich das sehen kann, sind die Zeiger auf Xmega schließlich 24 und nicht 32 Bit breit. Die intptr_t und uintptr_t sind allerdings optional und deshalb nicht notwendigerweise definiert.
Unabhängig vom Problem kommt mir das komisch vor: DMA_CH_t channel channel.SRCADDR0= ... denn damit modifizierst du einen struct Parameter, kein DMA-Register. Meinst du vielleicht DMA_CH_t *channel channel->SRCADDR0= ...
Zum Problem: Die Xmegas mögen wohl eine 24-Bit Datenadressierung beherrschen, aber ob das der GCC auch weiss? Ich vermute, dass der in alter AVR-Tradition auch bei den Xmegas Adressen nur 16-Bit breit versteht und ein Programmierer, der mehr als 64KB Datenadressen verwendet, ein Problem kriegt. Und daher vorsorglich darauf hingewiesen wird, dass ein Casten nach 32-Bit Integer einen Fehler enthalten könnte.
Für die internen Adressen (und deshalb für mich) reichen wirklich 16-Bit aus. Der Xmega kann aber 16MB externen RAM ansprechen! wie wäre es mit einem far-pointer? Alexx
Alexxx schrieb: > Der Xmega kann aber 16MB externen RAM ansprechen! > wie wäre es mit einem far-pointer? Soweit mir bekannt gibt es die im GCC nicht, d.h. nicht wirklich. GCC hat generell ziemliche Probleme, zwischen verschiedenen Sorten von Pointern (codespace, dataspace, short, near, far, ...) zu differenzieren. Man kann daher mit Attributen zwar die Platzierung statischer Daten steuern, also riesige Arrays ins Flash oder einen erweiterten Datenadressraum legen, nicht aber Pointer so steuern, dass unterschiedlicher Code raus kommt. Siehe auch die Hacks und Laufzeitfunktionen statt Dereferenzierung für Daten im Flash. Da landet man schlicht und einfach an den Grenzen des AVR-GCC.
@ A. K.: Du hast natürlich recht! @ Alle PS: die Fehlermeldung ist tatsächlich weg, wenn man... channel->SRCADDR0= (uint8_t)(((uint16_t)source)>>0); channel->SRCADDR1= (uint8_t)(((uint16_t)source)>>8); channel->SRCADDR2= 0; schreibt. Danke für eure Hilfe.
> wie wäre es mit einem far-pointer?
Der gcc kennt nur eine Sorte Pointer. Ob die nun 16, 24, oder 32Bit
gross sind das koennte man beim implementieren des Codegenerators
festlegen.
Die einfachste Loesung ist nun immer einen moeglichst grossen Pointer zu
nehmen. Leider blaeht das aber den Code deutlich auf und macht ihn
langsamer. Das will man also auch nicht.
Beim M16C wird das geloest indem nur 16Bit Pointer genutzt werden, und
fuer Spruenge auf Funktionen eine Tabelle angelegt wird die dann
ueberrall hin springen kann. Natuerlich auch nicht die beste Loesung.
Da ist es wohl ein Nachteil das der gcc hauptsaechlich fuer dicke CPUs
entwickelt wird und man Microcontoller nicht so wichtig nimmt.
Olaf
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.