Stránka 2 z 2
Napsal: 05 čer 2008, 17:27
od rnbw
AT91PS_PMC bude ta struktura.
Ten #define znamena, ze preprocesor kazdy vyskyt symbolu
zmeni na
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;
Napsal: 06 čer 2008, 08:39
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;
Napsal: 06 čer 2008, 08:57
od rnbw
Ano, to vyzera dobre. Bolo by vhodne prelozit kratky kod a pozriet sa na vysledok disassemblerom.
Napsal: 06 čer 2008, 09:31
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;
}
Napsal: 06 čer 2008, 10:52
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.htmlTakž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

Napsal: 06 čer 2008, 11:22
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.
Napsal: 06 čer 2008, 11:30
od piitr
Teda, předpokládám, že to AT91C_BASE_UDP -> UDP_TXVC je definováno taky tak.
Napsal: 06 čer 2008, 12:12
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.
Napsal: 06 čer 2008, 12:19
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.
Napsal: 06 čer 2008, 13:19
od piitr
Jenom pro jistotu: Je to AT91C_BASE_UDP -> UDP_TXVC taky volatile?
Napsal: 06 čer 2008, 14:04
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.
Napsal: 06 čer 2008, 15:36
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.
Napsal: 07 čer 2008, 21:50
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.
Napsal: 14 črc 2008, 22:32
od Fojtik
No jeste upresnim

- 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.