_volatile_

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
rnbw
Příspěvky: 37416
Registrován: 21 bře 2006, 00:00
Bydliště: Bratislava

#16 Příspěvek od rnbw »

AT91PS_PMC bude ta struktura.

Ten #define znamena, ze preprocesor kazdy vyskyt symbolu

Kód: Vybrat vše

AT91C_BASE_PMC

zmeni na

Kód: Vybrat vše

((AT91PS_PMC) 0xFFFFFC00)

takze riadok

Kód: Vybrat vše

AT91C_BASE_PMC -> PMC_PCER = 1<<AT91C_ID_UDP;

zmeni na

Kód: Vybrat vše

((AT91PS_PMC) 0xFFFFFC00) -> PMC_PCER = 1<<AT91C_ID_UDP;
Uživatelský avatar
piitr
Příspěvky: 1003
Registrován: 19 říj 2007, 00:00
Kontaktovat uživatele:

#17 Příspěvek od piitr »

Tak jsem si to promyslel a i něco našel: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

Takže ten můj způsob 1 by šel taky, protože by překladač předpokládal, že ta adresa registru se může změnit, takže by ho četl znova, ale výsledek by nebyl optimální. Správné řešení je říci, že hodnota v tom registru se může změnit. A to jde udělat tak, že se volatile napíše do definice té struktury přímo k té položce PCM_PCER. Asi nějak takhle:

typedef struct
{
volatile int PMC_PCER;
...
} *AT91PS_PMC;
Uživatelský avatar
rnbw
Příspěvky: 37416
Registrován: 21 bře 2006, 00:00
Bydliště: Bratislava

#18 Příspěvek od rnbw »

Ano, to vyzera dobre. Bolo by vhodne prelozit kratky kod a pozriet sa na vysledok disassemblerom.
Uživatelský avatar
piitr
Příspěvky: 1003
Registrován: 19 říj 2007, 00:00
Kontaktovat uživatele:

#19 Příspěvek od piitr »

Teda, někdy je možná třeba tu strukturu použít i jinak, třeba pro kopii hodnot registrů, a tam to volatile nechci. Pak by to šlo třeba takhle:

typedef struct
{
int a;
} STRUKTURA;

#define IO ( (volatile STRUKTURA *) 0xABCDE )

void f(void)
{
STRUKTURA zaloha;
IO->a = zaloha.a;
}
Návštěvník

#20 Příspěvek od Návštěvník »

piitr píše:Tak jsem si to promyslel a i něco našel: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

Takže ten můj způsob 1 by šel taky, protože by překladač předpokládal, že ta adresa registru se může změnit, takže by ho četl znova, ale výsledek by nebyl optimální. Správné řešení je říci, že hodnota v tom registru se může změnit. A to jde udělat tak, že se volatile napíše do definice té struktury přímo k té položce PCM_PCER. Asi nějak takhle:

typedef struct
{
volatile int PMC_PCER;
...
} *AT91PS_PMC;


Přesně je to tam definováno takto:

Kód: Vybrat vše

typedef volatile unsigned int AT91_REG;// Hardware register definition

typedef struct _AT91S_PMC {
....
   AT91_REG    PMC_PCER;    // Peripheral Clock Enable Register
   AT91_REG    PMC_PCDR;    // Peripheral Clock Disable Register
....
} AT91S_PMC, *AT91PS_PMC;

Takže je to volatile a přesto to nefunguje :(
Uživatelský avatar
piitr
Příspěvky: 1003
Registrován: 19 říj 2007, 00:00
Kontaktovat uživatele:

#21 Příspěvek od piitr »

Hmm, to mi přijde dobře napsané. Alespoň podle té dokumentace.
Takže je to asi chyba překladače.
Nebo možná jede ten překladač podle nějaké starší specifikace, kde se to volatile nesmí používat tak bohatě. Možná je to blbost, ale mám dojem že to céčko se taky nějak postupně vyvíjelo a doplňovalo. Nevím. Já jsem tyhle věci vždy řešil v assembleru nebo funkcema outp() a tak.
Uživatelský avatar
piitr
Příspěvky: 1003
Registrován: 19 říj 2007, 00:00
Kontaktovat uživatele:

#22 Příspěvek od piitr »

Teda, předpokládám, že to AT91C_BASE_UDP -> UDP_TXVC je definováno taky tak.
Jak21

#23 Příspěvek od Jak21 »

AT91C_BASE_PMC -> PMC_PCER = 1<<AT91C_ID_UDP;
#define AT91C_BASE_PMC ((AT91PS_PMC) 0xFFFFFC00) // (PMC) Base Address

Takže struktura je umístěná na pevné adrese 0xfffffc00?
To je víc než 4 miliardy.
Návštěvník

#24 Příspěvek od Návštěvník »

Jak21 píše:
AT91C_BASE_PMC -> PMC_PCER = 1<<AT91C_ID_UDP;
#define AT91C_BASE_PMC ((AT91PS_PMC) 0xFFFFFC00) // (PMC) Base Address

Takže struktura je umístěná na pevné adrese 0xfffffc00?
To je víc než 4 miliardy.

ARM7 má adresní prostor 4GB a periferie jsou u AT91SAM7 na konci.
Uživatelský avatar
piitr
Příspěvky: 1003
Registrován: 19 říj 2007, 00:00
Kontaktovat uživatele:

#25 Příspěvek od piitr »

Jenom pro jistotu: Je to AT91C_BASE_UDP -> UDP_TXVC taky volatile?
Návštěvník

#26 Příspěvek od Návštěvník »

piitr píše:Jenom pro jistotu: Je to AT91C_BASE_UDP -> UDP_TXVC taky volatile?

Ano, je to stejné, všechny ty struktury jsou složené z AT91_REG a ten je volatile.
Uživatelský avatar
piitr
Příspěvky: 1003
Registrován: 19 říj 2007, 00:00
Kontaktovat uživatele:

#27 Příspěvek od piitr »

V tom případě si myslím, že to je chyba překladače. To je dost mrzuté.
Možná bych zkusil:
#define AT91C_BASE_PMC ((volatile AT91S_PMC *) 0xFFFFFC00)
Pokud to zapomíná v tom typedef nebo to nemá rád ve strukturách, tak by to mohlo pomoci.
Jinak nevím.
Jak21

#28 Příspěvek od Jak21 »

Tento problém mne zneklidňuje.
Doposud jsem si myslel, že optimizátor může vynechat část kódu, ale že by přehodil pořadí příkazů, to je podle mne nepřípustné.

Zkusil bych (jenom pro test) vložit mezi příkazy krátký delay.

Stálo by za to poslat dotaz na http://www.avrfreaks.net/index.php?name ... file=index
kde odpovídají experti na překladače.
Uživatelský avatar
Fojtik
Příspěvky: 31
Registrován: 26 led 2007, 00:00

#29 Příspěvek od Fojtik »

No jeste upresnim :wink: - volatile se pouziva nejen pro staticke promenne, ale pro veskere typy promennych.

A jeste jeden napad - vy jste resili jen jednu stranu.

Co takhle resit i tu druhou:
volatile int i = 1<<AT91C_ID_UDP;
AT91C_BASE_PMC -> PMC_PCER = i;

Tohle se zcela jiste nezoptimalizuje.
Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“