C - Casting Verständniss Problem

Gast #5540502
Was mache ich falsch? Bin gerade fast am heulen kopf gegen wand
1
void foo( void *dest )
2
{
3
  DMA.CH0.DESTADDR0 = (uint8_t)(((uint32_t) dest) & 0xFF);
4
  DMA.CH0.DESTADDR1 = (uint8_t)(((uint32_t) dest >> 8) & 0xFF);
5
  DMA.CH0.DESTADDR2 = (uint8_t)(((uint32_t) dest >> 16) & 0xFF);
6
}
Wenn ich versuche das zu kompilieren, kommt immer ein warning. 
Wahrscheinlich zu Recht..
1
Severity  Code  Description  Project  File  Line
2
Warning    cast from pointer to integer of different size [-Wpointer-to-int-cast]  XMEGA DMA  c:\users\marcus\Documents\Atmel Studio\7.0\XMEGA DMA\XMEGA DMA\main.c  14
Das sieht doch eher so aus, als würde bewusst mit den Adressen 
gearbeitet, auf die "dest" zeigt.
Eventuell liegt es einfach daran, dass Zeiger (soweit ich weiß, bitte 
berichtigt mich sonst) normalerweise die Breite der Systemarchitektur 
aufweisen und die kleiner als 32 Bit ist.

Gruß
Sam
Gast
Jim M. schrieb:
> Xmega hat IIRC nur 16-bittige Pointer..?
>
> Versuche mal die uint32_t durch uintptr_t zu ersetzen.

Das sieht schon besser aus.
1
{
2
  DMA.CH0.DESTADDR0 = (uint8_t)((uintptr_t) dest) & 0xFF;
3
  DMA.CH0.DESTADDR1 = (uint8_t)((uintptr_t) dest >> 8) & 0xFF;
4
  DMA.CH0.DESTADDR2 = (uint8_t)((uintptr_t) dest >> 16UL) & 0xFF;
5
}

Wenn der XMEGA nur 16 Bittige Zeiger hat, wieso gibt es dann das 
Register "DESTADDR2" ?
Es kommt jedoch jetzt immer noch eine Warnung. Ist ja auch verständlich. 
Er meckert das dass schieben überläuft..
Gast
Tobias B. schrieb:
> Auf was für einem System entwickelst du? 32 oder 64 bit?
>
> Kannst du mal ausgeben was die Größe des void Pointers ist?
> sizeof(void*)
> Evtl. liegt da der Hund begraben.

Das ist für nen XMEGA, schreibe den Source in C. Kann die Größe jetzt 
leider nicht ausgeben. Mein Rechner ist jedoch ein 64 Bit. Aber das 
sollte damit doch nichts zu tun haben?
Gast
Dein Problem ist, dass du DMA-Adressen und C-Pointer mischt. Bei einigen 
CPU-Architekturen sind die nicht identisch. Die XMEGA haben (bei deinem 
Compiler) 16-Bit C-Pointer aber 24-Bit DMA-Adressen. Mach dir eine 
Hilfsfunktion, die von C-Ptr nach DMA-Adresse umwandelt - im trivialen 
Fall ist das ein Cast, bei einigen Architekturen ist aber mehr nötig 
(Adressoffsets, etc) ...
1
typedef uint32_t dmaaddr_t;
2
#define cptr2dma(cptr) ((dmaaddr_t)(uintptr_t)(cptr))
3

4
...
5
{
6
  dmaaddr_t addr = cptr2dma(dest);
7

8
  DMA.CH0.DESTADDR0 = addr;
9
  DMA.CH0.DESTADDR1 = addr >> 8;
10
  DMA.CH0.DESTADDR2 = addr >> 16;
11
}
Gast
foobar schrieb:
> Dein Problem ist, dass du DMA-Adressen und C-Pointer mischt. Bei
> einigen
> CPU-Architekturen sind die nicht identisch. Die XMEGA haben (bei deinem
> Compiler) 16-Bit C-Pointer aber 24-Bit DMA-Adressen. Mach dir eine
> Hilfsfunktion, die von C-Ptr nach DMA-Adresse umwandelt - im trivialen
> Fall ist das ein Cast, bei einigen Architekturen ist aber mehr nötig
> (Adressoffsets, etc) ...
> typedef uint32_t dmaaddr_t;
> #define cptr2dma(cptr) ((dmaaddr_t)(uintptr_t)(cptr))
>
> ...
> {
>   dmaaddr_t addr = cptr2dma(dest);
>
>   DMA.CH0.DESTADDR0 = addr;
>   DMA.CH0.DESTADDR1 = addr >> 8;
>   DMA.CH0.DESTADDR2 = addr >> 16;
> }

Ich habe mir das hier abgesehen..
/*
 * DMAController.cpp
 *
 *  Created on: 16.01.2013
 *      Author: Nicolas Göddel
 *
 * 
https://www.mikrocontroller.net/articles/Speicherdirektzugriff_(DMA)_mit_dem_ATxmega#DMAController.cpp
 */
Gast
Hi Marcus,

bist noch nicht viel weiter gekommen. Weshalb aber ein neuer Thread?

Vielleicht solltest Du beschreiben was du machen willst.

Grüsse,
René
Gast
René H. schrieb:
> Hi Marcus,
>
> bist noch nicht viel weiter gekommen. Weshalb aber ein neuer Thread?
>
> Vielleicht solltest Du beschreiben was du machen willst.
>
> Grüsse,
> René

Hi Rene,

ich versuche ( einen Post über deinen (link) ) die C++ Bibliothek in C 
zu schreiben.
Gast
foobar schrieb:
> typedef uint32_t dmaaddr_t;
> #define cptr2dma(cptr) ((dmaaddr_t)(uintptr_t)(cptr))
>
> ...
> {
>   dmaaddr_t addr = cptr2dma(dest);
>
>   DMA.CH0.DESTADDR0 = addr;
>   DMA.CH0.DESTADDR1 = addr >> 8;
>   DMA.CH0.DESTADDR2 = addr >> 16;
> }

Das sieht gut aus. Keine Warnings mehr.
Und jetzt steht dort auch die Adresse der Variablen drin oder deren 
Inhalt?
Gast
Marcus schrieb:
> foobar schrieb:
>> typedef uint32_t dmaaddr_t;
>> #define cptr2dma(cptr) ((dmaaddr_t)(uintptr_t)(cptr))
>>
>> ...
>> {
>>   dmaaddr_t addr = cptr2dma(dest);
>>
>>   DMA.CH0.DESTADDR0 = addr;
>>   DMA.CH0.DESTADDR1 = addr >> 8;
>>   DMA.CH0.DESTADDR2 = addr >> 16;
>> }
>
> Das sieht gut aus. Keine Warnings mehr.
> Und jetzt steht dort auch die Adresse der Variablen drin oder deren
> Inhalt?

Die Adresse.

Grüsse,
René
Gast
>> Das sieht gut aus. Keine Warnings mehr.
>> Und jetzt steht dort auch die Adresse der Variablen drin oder deren
>> Inhalt?
>
> Die Adresse.
>
> Grüsse,
> René

Das mit dem Makro ist echt ne klasse Idee ;) Besten dank!
Gast
Habe das gerade mal auf dem Rechner ausprobiert.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4
#include <stdbool.h>
5

6
typedef uint32_t dmaaddr_t;
7
#define CPTR2DMA(cptr) ((dmaaddr_t)(uintptr_t)(cptr))
8

9
void foo( void *dest )
10
{
11
  printf( "%d\r\n" , CPTR2DMA( dest ) & 0xFF );
12
  printf( "%d\r\n" , ( CPTR2DMA( dest ) >> 8 ) & 0xFF );
13
        printf( "%d\r\n" , ( CPTR2DMA( dest ) >> 16 ) & 0xFF );
14
        printf( "%d\r\n" , ( CPTR2DMA( dest ) >> 32 ) & 0xFF );
15
}
16

17

18
int main(int argc, char *argv[]) 
19
{
20
  uint32_t test;
21
  
22
  foo( &test );
23
  
24
  printf( "Adresse: %d" , &test );
25
  
26
  return 0;
27
}

Wenn ich mit "printf" die ganze Adresse ausgeben möchte, kommt für mich 
eine richtige Adresse raus.

Wenn ich jedoch die Variable der Funktion "foo()" übergebe und das 
zerlege, kommt was ganz anderes raus?!
Gast
> Wenn ich jedoch die Variable der Funktion "foo()" übergebe und
> das zerlege, kommt was ganz anderes raus?!

Der letzte Shift ist falsch (muss >>24 sein, nicht >>32). Und mit %x 
statt %d fällt das Vergleichen leichter ...
Gast
foobar schrieb:
>> Wenn ich jedoch die Variable der Funktion "foo()" übergebe und
>> das zerlege, kommt was ganz anderes raus?!
>
> Der letzte Shift ist falsch (muss >>24 sein, nicht >>32). Und mit %x
> statt %d fällt das Vergleichen leichter ...

Klasse!
1
void foo( void *dest )
2
{
3
  dmaaddr_t addr = CPTR2DMA( dest );
4
  
5
  printf( "%x\r\n" , (addr & 0x000000FF) >> 0  );
6
  printf( "%x\r\n" , (addr & 0x0000FF00) >> 8  );
7
  printf( "%x\r\n" , (addr & 0x00FF0000) >> 16 );
8
  printf( "%x\r\n" , (addr & 0xFF000000) >> 24 );
9
}
10

11

12
int main(int argc, char *argv[]) 
13
{
14
  uint32_t test;
15
  
16
  foo( &test );
17
  
18
  printf( "Adresse: %x" , &test );
19
  
20
  return 0;
21
}
Jetzt haut es hin ;)

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 8 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.