Arrays gleicher länge tauschen

Gast #1971255
Lesenswert?

Frage:
Ich habe 2 Arrays (arr1[11] und arr2[11]) und möchte deren Inhalte 
vertauschen. Darf ich arr1 und arr2 als Pointer interpretieren und deren 
Werte tauschen?

Hintergrund ist, dass ich mit dem einem Array gemütlich arbeiten möchte 
während Interruptroutinen mit dem zweiten Array arbeiten (nur lesen), 
wie ein Puffer.
Wenn meine Hauptroutine fertig ist mit allen Berechnungen, sollen die 
Arrays getauscht werden und die Interruproutinen arbeiten mit den 
aktualisierten werten weiter.
Also nichts anderes als ein Puffer.

also so:
1
//globale Arrays
2
uint8_t arr1[11];
3
uint8_t arr2[11];
4

5
void vertausche( void ) {
6
    uint8_t *ptr;
7

8
    cli();
9
    ptr = arr1;
10
    arr1 = arr2;
11
    arr2 = ptr;
12
    sei();
13
}
Gast #1971278
Lesenswert?

die länge ist dabei sogar egal

ich denke schon das das geht, saubere ist es eventuell wenn du einen 
zusätzlichen zeiger verwendest der auf den aktuellen wert zeigt.

uint8_t arr1[11];
uint8_t arr2[11];

uint8_t *akt_list;

    cli();
    akt_list = arr1;
    sei();
#1971284
Lesenswert?

Richard schrieb:
> Frage:
> Ich habe 2 Arrays (arr1[11] und arr2[11]) und möchte deren Inhalte
> vertauschen. Darf ich arr1 und arr2 als Pointer interpretieren und deren
> Werte tauschen?

Nein.
Ein Array ist kein Pointer.

> Hintergrund ist, dass ich mit dem einem Array gemütlich arbeiten möchte
> während Interruptroutinen mit dem zweiten Array arbeiten (nur lesen),
> wie ein Puffer.

Ah. ok.
Das kannst du anders machen.
Du kannst dir ja 2 Pointer Variablen einrichten, die auf die Arrays 
zeigen. Und wenn es Zeit ist zu wechseln, dann tauscht du die beiden 
Pointer.

1
//globale Arrays
2
uint8_t arr1[11];
3
uint8_t arr2[11];
4

5
uint8_t * actualBuffer = arr1;
6
uint8_t * backupBuffer = arr2;
7

8
void vertausche( void ) {
9
    uint8_t *ptr;
10

11
    cli();
12
    ptr = actualBuffer;
13
    actualBuffer = backupBuffer;
14
    backupBuffer = ptr;
15
    sei();
16
}

die Interrupt Routine arbeitet immer über actualBuffer während die 
Hauptroutine immer über den backupBuffer geht. Syntaxmässig ändert sich 
in der Verwendung noch nicht einmal etwas. Du kannst weiterhin zb über 
actualBuffer[i] zugreifen. Nur landet der Zugriff dann entweder in arr1 
oder arr2, je nachdem wo der Pointer hinzeigt.
Gast #1973036
Lesenswert?

Karl heinz Buchegger schrieb:
> void vertausche( void ) {
>     uint8_t *ptr;
>
>     cli();
>     ptr = actualBuffer;
>     actualBuffer = backupBuffer;
>     backupBuffer = ptr;
>     sei();
> }

Mit den cli()/sei() ist das ganz finster, das ist schlechter Stil den 
man sich nicht angewöhnen sollte. Eher so:
1
void 
2
vertausche( void ) 
3
{
4
  uint8_t *ptr;
5

6
  ATOMIC_BLOCK( ATOMIC_RESTORESTATE )
7
  {
8
    ptr = actualBuffer;
9
    actualBuffer = backupBuffer;
10
    backupBuffer = ptr;
11
  }
12
}
Gast #1974449
Lesenswert?

atomic schrieb:
> Eugenius Fragikus schrieb:
>> Mit den cli()/sei() ist das ganz finster, das...
>
> Weshalb?

Gar nicht. Da wollte nur jemand beweisen, dass er die neuen 
atomic-Macros kennt. Die sind zwar schön, und es ist meistens schön wenn 
man sie benutzt. Aber an der cli/sei Methode ist eigentlich auch nichts 
auszusetzen.
#1974670
Lesenswert?

Klaus schrieb:
> atomic schrieb:
>> Eugenius Fragikus schrieb:
>>> Mit den cli()/sei() ist das ganz finster, das...
>>
>> Weshalb?
>
> Gar nicht. Da wollte nur jemand beweisen, dass er die neuen
> atomic-Macros kennt. Die sind zwar schön, und es ist meistens schön wenn
> man sie benutzt. Aber an der cli/sei Methode ist eigentlich auch nichts
> auszusetzen.

Gleich vorweg: Ich hab das noch nicht überprüft

In der Doku zu den Makros steht, dass sie in jedem Fall sicher stellen, 
dass das Interrupt Flag wieder richtig und je nach Makroargument richtig 
gesetzt wird, wenn der Block verlassen wird.
dh. auch in diesem Fall
1
 ATOMIC_BLOCK( ATOMIC_RESTORESTATE )
2
  {
3
     ...
4

5
    return;
6
  }

machen die Makros das richtige.

Wie gesagt, ich habs noch nicht überprüft, aber für mich wär das ein 
'Vorteil' der Makros gegenüber händischem cli/sei. Ausserdem 
restaurieren die Makros auf Anforderung wieder in den vorherghenden 
Zustand, was bei Funktionen die Funktionen aufrufen kein Nachteil sein 
soll :-)
Gast #1974701
Lesenswert?

Klaus schrieb:
> atomic schrieb:
>> Eugenius Fragikus schrieb:
>>> Mit den cli()/sei() ist das ganz finster, das...
>>
>> Weshalb?
>
> Gar nicht. Da wollte nur jemand beweisen, dass er die neuen
> atomic-Macros kennt. Die sind zwar schön, und es ist meistens schön wenn
> man sie benutzt. Aber an der cli/sei Methode ist eigentlich auch nichts
> auszusetzen.

Leider falsch...

Stell dir mal vor die IRQs sind aus irgendeinem Grund disabled bevor 
cli()/sei() aufgerufen werden.. Was sind die IRQs danach?

Lies dir mal die Help der ATOMIC Macros durch.

Hier der Text der Help..
Two possible macro parameters are permitted, ATOMIC_RESTORESTATE and 
ATOMIC_FORCEON.

#define ATOMIC_FORCEON

This is a possible parameter for ATOMIC_BLOCK. When used, it will cause 
the ATOMIC_BLOCK to force the state of the SREG register on exit, 
enabling the Global Interrupt Status flag bit. This saves on flash space 
as the previous value of the SREG register does not need to be saved at 
the start of the block.

Care should be taken that ATOMIC_FORCEON is only used when it is known 
that interrupts are enabled before the block's execution or when the 
side effects of enabling global interrupts at the block's completion are 
known and understood.

#define ATOMIC_RESTORESTATE

This is a possible parameter for ATOMIC_BLOCK. When used, it will cause 
the ATOMIC_BLOCK to restore the previous state of the SREG register, 
saved before the Global Interrupt Status flag bit was disabled. The net 
effect of this is to make the ATOMIC_BLOCK's contents guaranteed atomic, 
without changing the state of the Global Interrupt Status flag when 
execution of the block completes.

Cheers
Gast #1976434
Lesenswert?

Mark Brandis schrieb:
> Ich wusste gar nicht, dass es dieses Makro für jede Architektur gibt,
> auf der ein GCC verfügbar ist... ;-)

Ich hab das - vllt fälschlich - von den cli()/sei() Funktionen 
abgeleitet, dass es hier um die avr-gcc geht. Folgende "Schreibweise" 
wird gängiger sein, hier ein Beispiel für den icc430:

1
__istate_t s = __get_interrupt_state(); 
2
__disable_interrupt(); 
3
 
4
  /* Do something */ 
5
 
6
__set_interrupt_state( s );

Klaus schrieb:
> Aber an der cli/sei Methode ist eigentlich auch nichts
> auszusetzen.

Machen kann man das, aber wie ich bereits schrieb: Ich bin der Meinung, 
dass man sich das nicht angewöhnen sollte.
Gast #1976447
Lesenswert?

Karl heinz Buchegger schrieb:
> In der Doku zu den Makros steht, dass sie in jedem Fall sicher stellen,
> dass das Interrupt Flag wieder richtig und je nach Makroargument richtig
> gesetzt wird, wenn der Block verlassen wird.
> dh. auch in diesem Fall
>
>  ATOMIC_BLOCK( ATOMIC_RESTORESTATE )
>   {
>      ...
>
>     return;
>   }
>
> machen die Makros das richtige.

Wusste ich gar nicht, das ist natürlich praktisch bei verschachtelten 
Strukturen - solchen Komfort hat man leider nicht überall. :^)

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