C - Casting Verständniss Problem

Gast #5540502
Lesenswert?

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
#5540519
Lesenswert?

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 #5540523
Lesenswert?

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 #5540534
Lesenswert?

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 #5540557
Lesenswert?

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 #5540563
Lesenswert?

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 #5540569
Lesenswert?

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 #5540573
Lesenswert?

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 #5540586
Lesenswert?

>> 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 #5540593
Lesenswert?

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 #5540602
Lesenswert?

> 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 #5540605
Lesenswert?

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

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