Podłączyłem pamięć 32 kB (odpowiednik 62256) do ATmegi 128 i zacząłem ją sprawdzać.
Najpierw zapisałem ją całą swoimi danymi, a potem sprawdzałem, czy w każdej komórce pamięci jest to, co być powinno -- czyli bajt, który przed chwilą zapisałem.
Alokowanie wygląda w ten sposób:
#v+ #define TAB_LENGTH 0x7FFF u8 tab[TAB_LENGTH];
[...] for (i = 0; i < TAB_LENGTH; i++) { tab[i] = 0xAA; } #v-
Dane zgadzają się poza kilkoma adresami. Są to pola od tab[0x0FF7] do tab[0x0FFF]. W przełożeniu na adres pamięci m128 byłoby to 0x20F7 -
0x20ff (dodaję 0x1100 -- początek pamięci XMEM).
Pytanie dlaczego??
Dodam, że linkuję z flagami LDFLAGS = -Wl,-Tdata,0x801100 więc chyba powinno być ok. A może coś przeoczyłem?
Jeszcze taka ciekawostka: podczas testów okazało się, że avr-libc nie chce alokować bloków pamięci większych niż 0x7FFF (32 kB). A gdybym miał pamięć 64 kB, to jak to obejść?
ATmega128 z szybkim zegarem może być zbyt szybka dla standardowej pamięci CMOS Ram . Sprawdź czy na wolniejszym taktowaniu się nie poprawi. O ile pamiętam można dokładać wait-state przy pomocy bitów konfiguracyjnych.
Użytkownik "voice" snipped-for-privacy@komu.dzis napisał w wiadomości news: snipped-for-privacy@komu.dzis...
Pamietaj, ze pierwsze 0x1100 bajtow pamieci zewnetrznej pokrywa sie z pamiecia wewnetrzna, i procesor odwoluje sie do wewnetrznej. Na stronie atmela bylo, jak to obejsc, tak aby nie tracic tych bajtow.
Pisałem, że linkuję z flagami LDFLAGS = -Wl,-Tdata,0x801100. Ja to rozumiem tak, że sterta i sekcje danych .bss oraz .data są umieszczane w przestrzeni 0x1100 - 0xFFFF, a stos od 0x1100 w dół.
Czyli jeśli jest tak, jak rozumiem, do moja tablica z danymi powinna zostać umieszczona cała w pamięci zewnętrznej i procesor odwołując się do dowolnego bajtu tablicy odwołuje się właśnie do XMEM.
Może jednak coś pomieszałem i w ogóle źle zrozumiałem [1]? Proszę zatem o nakierowanie mnie na dobrą drogę :)
pisałeś o avr-libc, nie avr-gcc i mnie to zmyliło.
nie wiem czy to nadinterpretacja standardu C, ale chyba autorzy avr-gcc zbyt dosłownie wzięli sobie do serca, że indeksy tablic są typu int (ze znakiem). przy deklaracji > 32767 jest błąd, ale przy odwoływaniu się do elementów jest już dobrze. taki kawałek kodu:
generuje kod odwołujący się do tablica3[0x3fff]. trzeba tylko pamiętać, że kompilator zmienne może ułożyć dowolnie w pamięci i dobrze jest sprawdzić, czy na przykład ostatni kawałek tablicy nie wylądował przed pierwszym.
Fri, 10 Sep 2004 09:02:07 +0200, na pl.misc.elektronika, voice napisał(a):
Tak właśnie ma być - powinno działać. Sprawdź może jeszcze te wątpliwe adresy wchodząc bezpośrednio przez wskaźnik. Dla porównania kawałek testu jaki robiłem dla Atmega8515 : <>
// główny moduł projektu #define _MAIN_MOD_ 1 // pliki dołączone ( include ) : #include <avr\eeprom.h>
#include <avr\io.h>
#include <avr\interrupt.h>
#include <avr\signal.h>
#include <stdlib.h>
#include "projdat.h" // dane :
char Delay_counter = -10;
char *Ptab100;
#define LED PB0 // led włączony pomiędzy VCC i PB0 #define TOGGLE_LED PORTB ^= _BV(LED) #define LED_DELAY 2 #define HEAP_START RAMEND+1 #define HEAP_END 0x7fff+RAMEND+1 // w ten sposób wykorzystujemy całą kostkę ram - A15 jest // nieczynny i adresy od 0x8000 są fizycznie traktowane jak od 0
// funkcje : bool CheckRam(void) { bool chkcell; chkcell=true;
uint i,k; k=(uint)HEAP_END+1;
for (i=HEAP_START;i<k;i++) { *((uchar*)i)=0xa5; }
for (i=HEAP_START;i<k;i++) { if (*((uchar*)i) != 0xa5) { chkcell = false; break; } }
for (i=HEAP_START;i<k;i++) { *((uchar*)i)=0x5a; }
for (i=HEAP_START;i<k;i++) { if (*((uchar*)i) != 0x5a) { chkcell = false; break; } } return chkcell; }
void InitExtRam(void) { //ponieważ .data i .bss pozostały w wewnętrznej ram // wystarczy inicjalizacja w programie głównym - bez // wchodzenia w init1 DDRE |= _BV(PE0); // na przystosowanej płytce od 652 // PE0 pozostał połączony z CS ramu i musi byc ustawiony na Low MCUCR |= _BV(SRE); // włączenie interfejsu // na razie nie robimy rozdziału na sektory // i nie wprowadzamy dodatkowych wait-state'ów // przy 8 MHz zwykły 74HC573 powinien jeszcze wystarczyć SFIOR |= _BV(XMBK) | _BV(XMM0); // włączamy podtrzymywanie magistrali danych i wyłączamy najwyższy (A15) // pin adresowania - na płytce nie jest używany }
void InitHeap(void) { // sterta na całą pojemność zewnętrznego ramu 62256 (32k) __malloc_heap_start=(char*)HEAP_START; __malloc_heap_end=(char*)HEAP_END; } //==================== // funkcja main() int main(void) { // inicjalizacja OSCCAL=eeprom_read_byte((uchar*)E2END); // calibration for internal 8 MHz InitHeap(); InitExtRam();
DDRB |= _BV(LED);
if(CheckRam()) PORTB |=_BV(LED);
Ptab100 = malloc(100);
*Ptab100 = 10;
*(Ptab100 + 99) = 20;
InitT0(); sei();
// pętla główna while (1) { if (MS100FLAG) { MS100FLAG=false; if (++Delay_counter ==LED_DELAY) { Delay_counter=0; if (*(Ptab100 + 99) == 20) TOGGLE_LED; } } } } </> Tutaj linkowanie już z domyślnymi zwykłymi ustawieniami pamięci.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.