-
1. Data: 2017-02-07 22:22:43
Temat: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Pszemol <P...@P...com>
Czy mial ktos z Was do czynienia z konfiguarcją hardware polegającą na
32-bitowym procku (Arm Cortex M4) obsługującym dwie zewnętrzne pamięci
flash 16-bitowe (ST:M29W640GL)?
Wydawałoby się, że zadanie trywialne, a jednak kostki nie chcą
współpracować... :-)
Obie kostki pamięci mają wspólne sygnały Cs, Oe, We i A0..Axx a magistrala
danych po połowie 0..15 i 16..31 przydzielona odpowiednio do 0..15 każdej
kostki.
Procek ustawiony na 32bit i aby używał "address shift mode" (EMC Shift
Control bit w SCS registrze jest 0) więc "nie wie" ze sa dwi kostki w żaden
inny sposob jak tylko to, że zamiast do kasowania sektora wysylac 16-bitowo
0x00AA i 0x0055 a potem 0x0080 wysylam 32-bitowo 0x00AA00AA, 0x00550055 i
0x00800080.
I do tego problem jest ze czasem to dziala a czasem nie dziala. Jak nie
dziala to albo przy zmieniajacym sie bicie 2 jest ustawiony bit 5 (error) a
czasem juz na samym koncu przy sprawdzeniu odczytu skasowanej lokacji jest
jedna kostka skasowana a druga nieskasowana (na szynie jest np 0xFFFF0000).
Czy do takiej konfiguracji pamieci podchodzi sie jakos inaczej do
kasowania/programowania? Ktos sie podzieli doswiadczeniem?
-
2. Data: 2017-02-08 15:07:37
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: "Pszemol" <P...@P...com>
"Pszemol" <P...@P...com> wrote in message
news:o7ddno$b28$1@dont-email.me...
> Czy mial ktos z Was do czynienia z konfiguarcją hardware polegającą na
> 32-bitowym procku (Arm Cortex M4) obsługującym dwie zewnętrzne pamięci
> flash 16-bitowe (ST:M29W640GL)?
>
> Wydawałoby się, że zadanie trywialne, a jednak kostki nie chcą
> współpracować... :-)
>
> Obie kostki pamięci mają wspólne sygnały Cs, Oe, We i A0..Axx a magistrala
> danych po połowie 0..15 i 16..31 przydzielona odpowiednio do 0..15 każdej
> kostki.
>
> Procek ustawiony na 32bit i aby używał "address shift mode" (EMC Shift
> Control bit w SCS registrze jest 0) więc "nie wie" ze sa dwi kostki w
> żaden
> inny sposob jak tylko to, że zamiast do kasowania sektora wysylac
> 16-bitowo
> 0x00AA i 0x0055 a potem 0x0080 wysylam 32-bitowo 0x00AA00AA, 0x00550055 i
> 0x00800080.
>
> I do tego problem jest ze czasem to dziala a czasem nie dziala. Jak nie
> dziala to albo przy zmieniajacym sie bicie 2 jest ustawiony bit 5 (error)
> a
> czasem juz na samym koncu przy sprawdzeniu odczytu skasowanej lokacji jest
> jedna kostka skasowana a druga nieskasowana (na szynie jest np
> 0xFFFF0000).
>
> Czy do takiej konfiguracji pamieci podchodzi sie jakos inaczej do
> kasowania/programowania? Ktos sie podzieli doswiadczeniem?
A może ktoś zechce popatrzeć na kod programu i znaleźć "słabe" jego strony?
Zachęcam gorąco... :-)
// returns 1 if success
int STFlashEraseSector32(unsigned int SectorAddress)
{
U32 Status1, Status2;
volatile U32 *pSector = (volatile U32 *)(SectorAddress - (SectorAddress %
0x20000));
volatile U32 *pStatus = pSector;
// EMCSC bit in System Controls and Status register is cleared in
Flash_Init().
// It controls how addresses are output on the EMC address pins.
// For 32 bit bus the address is shifted so A2 is on A0 pin.
U32 *pA1 = (U32 *)(EXTERNAL_FLASH_LOCATION + (0x555 << 2)); //555 16bit
mode
U32 *pA2 = (U32 *)(EXTERNAL_FLASH_LOCATION + (0x2AA << 2)); //2AA 16bit
mode
// Reset
*pA1 = 0x00AA00AA;
*pA2 = 0x00550055;
*pSector = 0x00F000F0;
//
*pA1 = 0x00AA00AA;
*pA2 = 0x00550055;
*pA1 = 0x00800080; //erase
*pA1 = 0x00AA00AA;
*pA2 = 0x00550055;
*pSector = 0x00300030; //erase sector
//check toggle bit2 indicating erase operation pending
while(Status1 = *pStatus, Status2 = *pStatus, (Status1 ^ Status2) & (1 <<
2))
{
if(Status1 & (1 << 5)) // check error bit on one chip
{
LEDFRed();
return 0;
}
}
while(Status1 = *pStatus, Status2 = *pStatus, (Status1 ^ Status2) & (1 <<
(16+2)))
{
if(Status1 & (1 << (16+5))) // check error bit on second chip
{
LEDFRed();
return 0;
}
}
// Reset
// *pA1 = 0x00AA00AA;
// *pA2 = 0x00550055;
// *pSector = 0x00F000F0;
// Check the erase
if(*pSector != 0xffffffff)
{
LEDFRed();
return 0;
}
else
return 1;
}
// returns 1 if success
int STFlashWrite32(unsigned int Address, unsigned char *pSource, unsigned
int Size)
{
int Timeout;
U32 Status1, Status2;
volatile U32 *pDest = (volatile U32 *)Address;
U32 *pData = (U32 *)pSource;
// EMCSC bit in System Controls and Status register is cleared in
Flash_Init().
// It controls how addresses are output on the EMC address pins.
// For 32 bit bus the address is shifted so A2 is on A0 pin.
U32 *pA1 = (U32 *)(EXTERNAL_FLASH_LOCATION + (0x555 << 2)); //555 16bit
mode
U32 *pA2 = (U32 *)(EXTERNAL_FLASH_LOCATION + (0x2AA << 2)); //2AA 16bit
mode
if((Address & 0x01) != 0x00 || (Address & 0x02) != 0x00)
return 0;
if(((U32)pSource & 0x01) != 0x00 || ((U32)pSource & 0x02) != 0x00)
return 0;
for(unsigned int i = 0; i < Size/4; i++)
{
Timeout = 0;
// Reset
*pA1 = 0x00AA00AA;
*pA2 = 0x00550055;
*pDest = 0x00F000F0;
//
*pA1 = 0x00AA00AA;
*pA2 = 0x00550055;
*pA1 = 0x00A000A0; //program
*pDest = *pData; //data word
//check toggle bit for each chip separatelly
while(Status1 = *pDest, Status2 = *pDest, (Status1 ^ Status2) & (1 <<
6))
{
if(Status1 & (1 << 5)) // check error bit on one chip
{
LEDEYellow();
return 0;
}
if(++Timeout > 10000)
{
LEDDGreen();
return 0;
}
}
while(Status1 = *pDest, Status2 = *pDest, (Status1 ^ Status2) & (1 <<
(16+6)))
{
if(Status1 & (1 << (16+5))) // check error bit on second chip
{
LEDEYellow();
return 0;
}
if(++Timeout > 10000)
{
LEDDGreen();
return 0;
}
}
// Reset
// *pA1 = 0x00AA00AA;
// *pA2 = 0x00550055;
// *pDest = 0x00F000F0;
// check write
if(*pDest != *pData)
{
LEDDGreen();
LEDEYellow();
return 0;
}
++pDest;
++pData;
}
-
3. Data: 2017-02-08 16:00:24
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Adam Górski <gorskiamalpawpkropkapeel_@xx>
Gdybyś tak zrobił jedno miejsce przez które przechodzą wszystkie zapisy
i odczyty z printfem jakie zapisy idą do pamięci, to by pewnie było już
po problemie.
Do sprawdzenia:
1. Reprezentacja danych w pamięci. Czy aby na pewno bajty/słowa nie są
zamienione.
2. Czy w Twoim przypadku rozmiar sektora jest 0x20000 ? A może 0x40000 ?
Masz przesunięty adres.
3. Jak nie jesteś pewny to oscyloskop do łapy i sprawdź czy jest to co
Ci się wydaje.
Adam
>> Czy mial ktos z Was do czynienia z konfiguarcją hardware polegającą na
>> 32-bitowym procku (Arm Cortex M4) obsługującym dwie zewnętrzne pamięci
>> flash 16-bitowe (ST:M29W640GL)?
>>
>> Wydawałoby się, że zadanie trywialne, a jednak kostki nie chcą
>> współpracować... :-)
>>
>> Obie kostki pamięci mają wspólne sygnały Cs, Oe, We i A0..Axx a
>> magistrala
>> danych po połowie 0..15 i 16..31 przydzielona odpowiednio do 0..15 każdej
>> kostki.
>>
>> Procek ustawiony na 32bit i aby używał "address shift mode" (EMC Shift
>> Control bit w SCS registrze jest 0) więc "nie wie" ze sa dwi kostki w
>> żaden
>> inny sposob jak tylko to, że zamiast do kasowania sektora wysylac
>> 16-bitowo
>> 0x00AA i 0x0055 a potem 0x0080 wysylam 32-bitowo 0x00AA00AA, 0x00550055 i
>> 0x00800080.
>>
>> I do tego problem jest ze czasem to dziala a czasem nie dziala. Jak nie
>> dziala to albo przy zmieniajacym sie bicie 2 jest ustawiony bit 5
>> (error) a
>> czasem juz na samym koncu przy sprawdzeniu odczytu skasowanej lokacji
>> jest
>> jedna kostka skasowana a druga nieskasowana (na szynie jest np
>> 0xFFFF0000).
>>
>> Czy do takiej konfiguracji pamieci podchodzi sie jakos inaczej do
>> kasowania/programowania? Ktos sie podzieli doswiadczeniem?
>
> A może ktoś zechce popatrzeć na kod programu i znaleźć "słabe" jego strony?
> Zachęcam gorąco... :-)
>
> // returns 1 if success
> int STFlashEraseSector32(unsigned int SectorAddress)
> {
> U32 Status1, Status2;
> volatile U32 *pSector = (volatile U32 *)(SectorAddress -
> (SectorAddress % 0x20000));
> volatile U32 *pStatus = pSector;
>
> // EMCSC bit in System Controls and Status register is cleared in
> Flash_Init().
> // It controls how addresses are output on the EMC address pins.
> // For 32 bit bus the address is shifted so A2 is on A0 pin.
> U32 *pA1 = (U32 *)(EXTERNAL_FLASH_LOCATION + (0x555 << 2)); //555
> 16bit mode
> U32 *pA2 = (U32 *)(EXTERNAL_FLASH_LOCATION + (0x2AA << 2)); //2AA
> 16bit mode
>
> // Reset
> *pA1 = 0x00AA00AA;
> *pA2 = 0x00550055;
> *pSector = 0x00F000F0;
> //
> *pA1 = 0x00AA00AA;
> *pA2 = 0x00550055;
> *pA1 = 0x00800080; //erase
> *pA1 = 0x00AA00AA;
> *pA2 = 0x00550055;
> *pSector = 0x00300030; //erase sector
>
> //check toggle bit2 indicating erase operation pending
> while(Status1 = *pStatus, Status2 = *pStatus, (Status1 ^ Status2) & (1
> << 2))
> {
> if(Status1 & (1 << 5)) // check error bit on one chip
> {
> LEDFRed();
> return 0;
> }
> }
> while(Status1 = *pStatus, Status2 = *pStatus, (Status1 ^ Status2) & (1
> << (16+2)))
> {
> if(Status1 & (1 << (16+5))) // check error bit on second chip
> {
> LEDFRed();
> return 0;
> }
> }
>
> // Reset
> // *pA1 = 0x00AA00AA;
> // *pA2 = 0x00550055;
> // *pSector = 0x00F000F0;
> // Check the erase
> if(*pSector != 0xffffffff)
> {
> LEDFRed();
> return 0;
> }
> else
> return 1;
> }
>
> // returns 1 if success
> int STFlashWrite32(unsigned int Address, unsigned char *pSource,
> unsigned int Size)
> {
> int Timeout;
> U32 Status1, Status2;
> volatile U32 *pDest = (volatile U32 *)Address;
> U32 *pData = (U32 *)pSource;
>
> // EMCSC bit in System Controls and Status register is cleared in
> Flash_Init().
> // It controls how addresses are output on the EMC address pins.
> // For 32 bit bus the address is shifted so A2 is on A0 pin.
> U32 *pA1 = (U32 *)(EXTERNAL_FLASH_LOCATION + (0x555 << 2)); //555
> 16bit mode
> U32 *pA2 = (U32 *)(EXTERNAL_FLASH_LOCATION + (0x2AA << 2)); //2AA
> 16bit mode
>
> if((Address & 0x01) != 0x00 || (Address & 0x02) != 0x00)
> return 0;
> if(((U32)pSource & 0x01) != 0x00 || ((U32)pSource & 0x02) != 0x00)
> return 0;
>
> for(unsigned int i = 0; i < Size/4; i++)
> {
> Timeout = 0;
> // Reset
> *pA1 = 0x00AA00AA;
> *pA2 = 0x00550055;
> *pDest = 0x00F000F0;
> //
> *pA1 = 0x00AA00AA;
> *pA2 = 0x00550055;
> *pA1 = 0x00A000A0; //program
> *pDest = *pData; //data word
> //check toggle bit for each chip separatelly
> while(Status1 = *pDest, Status2 = *pDest, (Status1 ^ Status2) & (1
> << 6))
> {
> if(Status1 & (1 << 5)) // check error bit on one chip
> {
> LEDEYellow();
> return 0;
> }
> if(++Timeout > 10000)
> {
> LEDDGreen();
> return 0;
> }
> }
> while(Status1 = *pDest, Status2 = *pDest, (Status1 ^ Status2) & (1
> << (16+6)))
> {
> if(Status1 & (1 << (16+5))) // check error bit on second chip
> {
> LEDEYellow();
> return 0;
> }
> if(++Timeout > 10000)
> {
> LEDDGreen();
> return 0;
> }
> }
> // Reset
> // *pA1 = 0x00AA00AA;
> // *pA2 = 0x00550055;
> // *pDest = 0x00F000F0;
> // check write
> if(*pDest != *pData)
> {
> LEDDGreen();
> LEDEYellow();
> return 0;
> }
> ++pDest;
> ++pData;
> }
>
>
-
4. Data: 2017-02-08 16:33:43
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Pszemol <P...@P...com>
Adam Górski <gorskiamalpawpkropkapeel_@xx> wrote:
> Gdybyś tak zrobił jedno miejsce przez które przechodzą wszystkie zapisy
> i odczyty z printfem jakie zapisy idą do pamięci, to by pewnie było już
> po problemie.
Hmmm... Nie bardzo rozumiem ten pomysł...
Może zasugerowałbyś jakiś przykład?
W czasie programowania piszę przecież do pamięci bezpośrednio odwołując się
do wskaźników... Przy odczycie, w czasie kasowania i zapisu pamięć
przestawia jeden bit (toggle) co wskazuje na operację w toku...
> Do sprawdzenia:
> 1. Reprezentacja danych w pamięci. Czy aby na pewno bajty/słowa nie są
> zamienione.
Domyślam się że nie są zamienione, bo gdyby były to nie udawałoby się
czasem skasować i zapisać, a czasem się udaje...
> 2. Czy w Twoim przypadku rozmiar sektora jest 0x20000 ? A może 0x40000 ?
> Masz przesunięty adres.
Używam kostek M29W640GL.
To są pamięci 64Mb z 128 sektorów po 64KB/16KW każdy. Gdybym adresował
8-bitowo to sektor byłby od 0x0000 do 0xffff.
Ale tu mi trochę zadałeś klina, bo z jednej strony każda kostka pamięci ma
widzieć swój adres, ze swojego lokalnego punktu widzenia a z drugiej strony
mam procesor, który myśli że ma pamięć 32-bitową i interpretuje moje
wskazniki zgodnie ze swoim rozumieniem adresowania 32-bitowego z
przesuniętym A2 na pin A0. Muszę to jeszcze raz przetrawić...
> 3. Jak nie jesteś pewny to oscyloskop do łapy i sprawdź czy jest to co
> Ci się wydaje.
Dobre :-)
-
5. Data: 2017-02-08 16:38:11
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Pszemol <P...@P...com>
> Używam kostek M29W640GL.
> To są pamięci 64Mb z 128 sektorów po 64KB/16KW każdy.
Sorry - mialem napisac 64KB/32KW oczywiscie...
-
6. Data: 2017-02-08 17:03:16
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Adam Górski <gorskiamalpawpkropkapeel_@xx>
>> Gdybyś tak zrobił jedno miejsce przez które przechodzą wszystkie zapisy
>> i odczyty z printfem jakie zapisy idą do pamięci, to by pewnie było już
>> po problemie.
>
> Hmmm... Nie bardzo rozumiem ten pomysł...
> Może zasugerowałbyś jakiś przykład?
> W czasie programowania piszę przecież do pamięci bezpośrednio odwołując się
> do wskaźników... Przy odczycie, w czasie kasowania i zapisu pamięć
> przestawia jeden bit (toggle) co wskazuje na operację w toku...
>
Tak ale można to zrobić poprzez np. makro lub funkcje i przekierować to
co wychodzi do flasha i jednocześnie do printfa lub do bufora w ramie
tak żeby mieć rejestr z tego co wyszło i przyszło. Jedym słowem
logowanie. Tak żeby mieć pewność że sekwencja zapisu zgadza się z teorią.
>> Do sprawdzenia:
>> 1. Reprezentacja danych w pamięci. Czy aby na pewno bajty/słowa nie są
>> zamienione.
>
> Domyślam się że nie są zamienione, bo gdyby były to nie udawałoby się
> czasem skasować i zapisać, a czasem się udaje...
A nie trzeba tam gdzies czekać na bity ze status registru ?
>
>> 2. Czy w Twoim przypadku rozmiar sektora jest 0x20000 ? A może 0x40000 ?
>> Masz przesunięty adres.
>
> Używam kostek M29W640GL.
> To są pamięci 64Mb z 128 sektorów po 64KB/16KW każdy. Gdybym adresował
> 8-bitowo to sektor byłby od 0x0000 do 0xffff.
> Ale tu mi trochę zadałeś klina, bo z jednej strony każda kostka pamięci ma
> widzieć swój adres, ze swojego lokalnego punktu widzenia a z drugiej strony
> mam procesor, który myśli że ma pamięć 32-bitową i interpretuje moje
> wskazniki zgodnie ze swoim rozumieniem adresowania 32-bitowego z
> przesuniętym A2 na pin A0. Muszę to jeszcze raz przetrawić...
Tak mi się wydaje.
>> 3. Jak nie jesteś pewny to oscyloskop do łapy i sprawdź czy jest to co
>> Ci się wydaje.
> Dobre :-)
Czemu dobre ? Życie. No nie mów że dostęp do flasha jest jakiś
ekstremalnie szybki lub że nie da się tego zobaczyć. Że o debuggerach
nie wspomnę.
Adam Górski
-
7. Data: 2017-02-08 17:26:34
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Pszemol <P...@P...com>
Adam Górski <gorskiamalpawpkropkapeel_@xx> wrote:
> A nie trzeba tam gdzies czekać na bity ze status registru ?
>
Z tego pytania wnioskuję, że na funkcje zapisu i kasowania jakie tu podałem
nawet nie spojrzałeś :-)))
> Czemu dobre ? Życie. No nie mów że dostęp do flasha jest jakiś
> ekstremalnie szybki lub że nie da się tego zobaczyć. Że o debuggerach
> nie wspomnę.
Nie chodzi o szybkość, raczej o ilość potrzebnych do monitorowania wejść.
Oscyloskop, nawet 4-kanałowy niewiele pomoże. Moj analizator stanow
logicznych też tylko 16 wejsc... No i good luck aby je podłączyć pod
procesor w obudowie LQFP208 albo flasha 48-pin TSOP... Nie mam niestety
adapterów, musiałbym lutować druty do kostki :-(
-
8. Data: 2017-02-08 19:52:22
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Janusz_k <J...@o...pl>
W dniu 2017-02-08 o 15:07, Pszemol pisze:
> while(Status1 = *pStatus, Status2 = *pStatus,
--------------------^^^^---------------^^^^
Status zapisu sprawdzasz tylko z jednej pamięci, bo skąd kompilator ma
wiedzieś który "*pStatus" jest od której paMIĘCI? podstawia dwa razy to
samo. Jedna się wyrobi, druga nie i są błędy.
--
Pozdr
Janusz_k
-
9. Data: 2017-02-08 20:31:48
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Pszemol <P...@P...com>
Janusz_k <J...@o...pl> wrote:
> W dniu 2017-02-08 o 15:07, Pszemol pisze:
>> while(Status1 = *pStatus, Status2 = *pStatus,
> --------------------^^^^---------------^^^^
> Status zapisu sprawdzasz tylko z jednej pamięci, bo skąd kompilator ma
> wiedzieś który "*pStatus" jest od której paMIĘCI? podstawia dwa razy to
> samo. Jedna się wyrobi, druga nie i są błędy.
Zerknij proszę jeszcze raz na deklarację wskaźnika pStatus oraz zmiennych
Status1 i Status2.
To są obiekty 32-bitowe a więc obie kostki pamięci odpowiedzialne są za ich
zapis.
Pamietaj że jedna kostka pamięci podłączona jest do jednej połowy szyny
danych (D0..D15) a druga do drugiej połowy (D16..D31). Procesor jest
ustawiony aby wszystkie cykle robił 32-bitowe z 4-bajtowym "alignem"
adresow... (jak się to po polsku mówi?)
Dwa kolejne odczyty tego samego adresu są robione w pętli aby sprawdzić czy
pamięć jest zajęta.
Lecę więc po kolei, zakładając że kostki mogą mieć rózne potrzeby czasu na
zapis/kasowanie: najpierw w pętli jednej, czekam aż jedna kostka skończy
kasowac testujac bit D2 potem wskakuję w drugą pętle i sprawdzam czy druga
kostka też skończyła testujac bit 2+16 czyli D18 a na końcu, dla pewności,
sprawdzam czy skasowana lokacja odczytuje się 0x FFFF FFFF czyli czy obie
kostki są skasowane. I tu najczęściej się program wywala w debuggerze: test
pokazuje odczyt np 0x FFFF 0087. Czyli jedna kostka skasowana a druga ma
stara zawartosc....
-
10. Data: 2017-02-08 21:33:14
Temat: Re: programowanie i kasowanie dwu kostek flash na jednej magistrali
Od: Pszemol <P...@P...com>
Teraz na ten przykład krokuję program (breakpoint na wejsciu do funkcji
kasowania sektora) i widzę, że tak traktowany sprzęt zachowuje się ładniej
- zamiast wywalić się na kasowaniu pierwszego sektora (0x8000 0000)
przeszedł ladnie do kasowania
0x800C 0000, 0x800E 0000, 0x8010 0000 zapisujac je po kolei bez zgłaszania
błędów i po skasowaniu 0x8012 0000 wykorbił się w czasie zapisu nowych
danych:
Górna kostka, ta obsługująca bity D16..D31, zgłosiła błąd zapisu: ustawiony
bit D5 kostki (u mnie cpu widzi go jako D21) przy przestawianym wciąż bicie
D6 (u mnie D22).
I co teraz? Zaczynam kurna podejrzewać nasz hardware... Może coś jest nie
tak z jakością 3V3... Czas przynieść oscylka :-)