Programowanie skryptowe I2C SPI [PORADNIK i PRZYKŁADY]

Pytania techniczne oraz porady dotyczące programowania pamięci oraz funkcjonalności programatora.
ArT
Posts: 1020
Joined: Wed Mar 25, 2015 8:54 am
Location: Warsaw, Poland
Has thanked: 20 times
Been thanked: 96 times

Programowanie skryptowe I2C SPI [PORADNIK i PRZYKŁADY]

Postby ArT » Sat May 06, 2017 2:37 pm

Jedną z nowych funkcjonalności w wersji v1.6 jest "Programowanie Skryptowe I2C/SPI". W tym poradniku opiszę czym jest, do czego służy oraz udostępnię kilka przykładowych skryptów dla REVELPROG-IS.

Czym jest programowanie skryptowe I2C/SPI z REVELPROG-IS?

Programowanie skryptowe I2C/SPI w przypadku REVELPROG-IS pełni funkcje tzw "BUS Pirate" dla protokołów szeregowej transmisji I2C oraz SPI. Narzędzie jest nadal w fazie rozwojowej ale już o ogromnych możliwościach. Przy wykorzystaniu skryptów istnieje możliwość wywoływania dowolnych komend (rozkazów) na magistrali w dowolnej sekwencji z zachowaniem odpowiednich opóźnień czasowych. Przykładowe zastosowanie to wszelkie niestandardowe operacje na pamięci, udokumentowane (bądź nie) w nocie katalogowej układu, np. odblokowanie urządzeń (ukryta sekwencja zapisu haseł), odczyt i zapis ukrytych rejestrów, zapis niestandardowych rejestrów (sector protection bits, rejestry OTP) itd.

W praktyce też jest to bardzo praktyczne narzędzie dla elektroników konstruktorów oraz programistów embedded. Do złącza ICSP programatora REVELPROG-IS można podłączyć się z dowolnym urządzeniem lub układem po SPI lub I2C. W programatorze można wybrać napięcie zasilania i poziom sygnałów (od 1.0 do 5.0V z rozdzielczością 0,1V) więc dodatkowe zasilanie samego układu może być zbędne.

ProgramowanieSkryptoweI2CiSPI.jpg
ProgramowanieSkryptoweI2CiSPI.jpg (63.16 KiB) Viewed 3658 times

Struktura skryptów

Każdy skrypt składa się z:
  • nagłówka - informacja o wersji oprogramowania w jakiej został przygotowany skrypt
  • ustawień hardware - wybór napięcia (VPP), magistralii (I2C/SPI) oraz szybkości tranmisji,
  • sekwencji operacji (od 1 do n).

Każda operacja składa się z:
  • ustawień parametrów, tj. liczba bajtów do zapisu, liczba bajtów do odczytu, ustawienia opóźnień
  • instrukcji - sekwencji bajtów do wykonania w ramach pojedynczej instrukcji
  • danych (opcjonalnie) - sekwencji bajtów do przesłania po wykonaniu instrukcji
Każdy skrypt musi posiadać zdefiniowaną co najmniej jedną operacje (może być ich nieskończenie wiele).

Przykładowa struktura skryptu ze zdefiniowanym nagłówkiem (wersja 1.6.0), ustawieniami hardware (magistrala SPI, napięcie 3.3V, najwolniejsza prędkość transmisji) oraz jedną operacją z jedno-bajtową instrukcją.

Code: Select all

// przykladowa struktura skryptu
#SCRIPT HEADER;
SCRIPT:v1.6.0;
#HARDWARE SETTINGS;
HW:SPI,3.3V,SLOW;
#OPERATION;
SW:0,0,1,3,5,5,10,0,100,1000;
INSTR:9F;


Istotne elementy składni skryptu:
  • znak hash "#" definiujący sekcje, np. #SCRIPT HEADER; (nagłowek), #HARDWARE SETTINGS; (ustawienia hardware), #OPERATION; (dla każdej operacji)
  • średnik ";" umieszczany na końcu każdego polecenia,
  • dwukropek ":" umieszczany po słowach sterujących, np. SCRIPT: (wersja skryptu), HW: (ustawienia hardware), SW: (ustawienia parametrów operacji), INSTR: (instrukcja), DATA: (dane do zapisu)
  • przecinek "," oddziela parametry występujące po słowach sterujących (np. między "INSTR:" a ";" przecinek oddziela poszczególne bajty instrukcji)
  • podwójny ukośnik "//" poprzedza komentarze - dane ignorowane przez interpretator skryptu

Generator skryptu

W celu ułatwienia pisania skryptów można skorzystać z narzędzia generatora skryptu, w którym istnieje możliwość wygenerowania pojedynczych operacji z różnymi parametrami.
GeneratorSkryptu.jpg
GeneratorSkryptu.jpg (66.4 KiB) Viewed 3658 times

Ustawienia software dla poszczególnych operacji:
  • WREN (Write Enable) - właczenie zapisu danych + ilość bajtów danych do przesłania w pojedynczej operacji,
  • RDEN (Read Enable) - włączenie odczytu danych + ilość bajtów do odczytu po wykonaniu pojedynczej operacji,
  • DBO (Delay Before Operation) - dodatkowe opóźnienie w milisekundach przed wykonaniem danej operacji,
  • DAI (Delay After Instruction) - dodatkowe opóźnienie w milisekundach bezpośrednio po wykonaniu instrukcji dla danej operacji,
  • DAW (Delay After Write) - dodatkowe opóźnienie w milisekundach po przesłaniu bajtów danych (np. czas potrzebny na przetworzenie danych przez układ),
  • DAO (Delay After Operation) - dodatkowe opóźnienie w milisekundach po wykonaniu całej operacji (przed przejściem do wykonywania kolejnej operacji),
  • BSYO (Busy Operation) - maksymalny czas oczekiwania na gotowość układu (badanie flagi busy, np. tzw. Wait For Write End dla pamięci FLASH SPI czy maksymalny czas oczekiwania na ACK dla pamięci I2C)
  • TOUT (Timeout) - maksymalny czas oczekiwania przez PC na wykonanie całej operacji (zaleca się aby był dłuższy niż dwukrotność sumy powyższych opóźnień).

Ustawienie powyższych parametrów zgodnie z powyższym zrzutem ekranu wygeneruje następujący kod poniższej operacji:

Code: Select all

#OPERATION;
SW:0,0,1,3,5,5,10,0,100,500;
INSTR:9F;

Jak widać ustawienia software odpowiadają kolejnym parametrom dla ustawień "SW:" z pewnymi zastrzeżeniami:
- ilość bajtów odczytu/zapisu jest wyrównana do zera, tzn. 0 oznacza 1, a 255 oznacza 256
- jeżeli zapis lub odczyt jest wyłączony (0) to ilość bajtów zapisu/odczytu jest ignorowana

Format danych:
- ustawienia SW i HW defniniuje się w formacie dziesiętnym
- instrukcje (INSTR:) oraz dane do zapisu (DATA:) definiuje się w formacie hex (szasnastkowym)

Dodatkowe uwagi

Należy przestrzegać zachowania składni skryptu, gdyż interpretator skryptu nie toleruje błędów :-) To znaczy nie można zapominać o przecinkach, średnikach, dwukropkach ani poleceniach sterujących gdyż na tym etapie zachowanie programu może być nieprzewidywalne, jak również może nie wykonać danej operacji oraz nie poinformować o tym fakcie użytkownika.

W dodatkowych dodatkowych postach w tym temacie przedstawie kilka przykładowych skryptów realizujących różne operacje.

ArT
Posts: 1020
Joined: Wed Mar 25, 2015 8:54 am
Location: Warsaw, Poland
Has thanked: 20 times
Been thanked: 96 times

Re: Programowanie skryptowe I2C i SPI [PORADNIK]

Postby ArT » Sat May 06, 2017 3:33 pm

W ramach przykładów zacznijmy od czegoś prostego, np. odczyt ID pamięci SPI. Kto bardziej spostrzegawczy zapewne zauważył że przy okazji opisu generatora skryptu wykonaliśmy operacje odczytu ID pamięci FLASH SPI która składa się z pojedynczej instrukcji "9F" i odczytania 4 bajtów po wykonaniu instrukcji. W tym przykładzie jedynie ulega zmianie napięcie (2.6V zamiast 3.3V) - dobrą praktyką jest stosowanie bezpiecznych napięć - jeżeli by się okazało że mamy do czynienia z pamięcią niskonapięciową 1.8V to chwilowe 2.6V nie uszkodzi takiej pamięci, a jednocześnie będzie wystarczającym napięciem do odczytania ID układu 3.3V (do zapisu może się okazać zbyt niskie).

Odczyt ID (tzw. JEDEC) dla pamięci FLASH SPI:

Code: Select all

#SCRIPT HEADER;
SCRIPT:v1.6.0;

#HARDWARE SETTINGS;
HW:SPI,2.6V,SLOW;

// Odczyt ID (JEDEC) dla FLASH SPI
#OPERATION;
SW:0,0,1,3,5,5,10,0,100,1000;
INSTR:9F;


Efekt wykonania powyższego skryptu to odczytane 4 bajty identyfikujące układ (tzw. JEDEC ID):
WynikReadJEDECIDdlaW25Q64.jpg
WynikReadJEDECIDdlaW25Q64.jpg (17.87 KiB) Viewed 3655 times


Zgodnie z notą katalogową układu Winbond W25Q64FV(tzw. datasheet - strona 21)
W25Q64FV_JEDEC.jpg
W25Q64FV_JEDEC.jpg (45.52 KiB) Viewed 3655 times

pierwszy bajt to oznaczenie producenta (w tym przypadku bajt "EF" oznacza Winbond), bajt drugi to oznaczenie rodziny układów (w tym przypadku bajt "40" oznacza serie W25Q...), a bajt trzeci to pojemność układu (bajt "17" oznacza pojemność 64Mbit). Czwarty bajt (wg standardu JEDEC) to tzw. "Extended ID" zawierający dodatkowe informacje, jednak nie wspierany przez powyższy układ stąd "00".

Odczyt rejestrów SR1 oraz SR2 pamięci FLASH SPI:

Code: Select all

#SCRIPT HEADER;
SCRIPT:v1.6.0;

#HARDWARE SETTINGS;
HW:SPI,2.8V,SLOW;

// Status Register 1 Read
#OPERATION;
SW:0,0,1,0,5,5,0,0,100,500;
INSTR:05;

// Status Register 2 Read
#OPERATION;
SW:0,0,1,0,5,5,0,0,100,500;
INSTR:35;

Wystarczy że zmienimy naszą instrukcje z "9F" na "05" oraz odczyt 1 bajtu zamiast 4 i w ten sposób odczytamy stan rejestru SR1. Dodamy kolejną instrukcje "35" (pozostałe parametry bez zmian) w celu odczytu stanu rejestru SR2.
W25Q64CV_instructions.jpg
W25Q64CV_instructions.jpg (166.91 KiB) Viewed 3655 times

Efektem są odczytane 2 bajty: 00 (rejestr SR1) oraz 02 (SR2).
W25Q64FV_SR1_SR2_values.jpg
W25Q64FV_SR1_SR2_values.jpg (16.84 KiB) Viewed 3655 times

00h szesnastkowo to binarnie 00000000b
02h szesnastkowo to binarnie 00000010b
a to oznacze że pamięć ma włączony tryb QSPI (QUAD SPI) ponieważ bit S9 ma wartość "1":
W2564CV_SR1_SR2_QSPI.jpg
W2564CV_SR1_SR2_QSPI.jpg (81.43 KiB) Viewed 3655 times


Zapis rejestru SR2 pamięci FLASH SPI:
Załóżmy że potrzebujemy wyłączyć tryb QSPI. W tym celu należy zmienić wartość rejestru SR2 (wyzerować S9). Procedura zapisu rejestru SR2 wymaga jednoczesnego zapisu rejestru SR1 co zostało opisane w dokumentacji w sekcji "Write Status Register (01h)" na stronie 28. W przypadku innych pamięci procedura może być inna, więc zawsze trzeba postępować wg noty katalogowej danego układu.

Code: Select all

//Winbond W25.. (64Mbit+) disable QUAD SPI
#SCRIPT HEADER;
SCRIPT:v1.6.0;

#HARDWARE SETTINGS;
HW:SPI,2.8V,SLOW;

// WRITE ENABLE (06h)
#OPERATION;
SW:0,0,0,0,5,5,0,0,100,500;
INSTR:06;

// WRITE STATUS REGISTER 1&2 (01h + REG1 + REG2)
#OPERATION;
SW:0,0,0,0,5,5,10,0,100,500;
INSTR:01,00,00;

// READ STATUS REGISTER 2 (35h)
#OPERATION;
SW:0,0,1,0,5,5,0,0,100,500;
INSTR:35;

Powyższy skrypt najpierw odblokowuje możliwość zmiany rejestrów (Rozkaz Write Enable - 06h) a następnie wywołuje komendę Write Status Register (01h) i w kolejnych dwóch bajtach instrukcji przesyła wartości rejestru SR1 = 00h oraz SR2 = 00h. Na koniec wykonuje odczyt samego rejestru 2 w celu zweryfikowania czy zapis się powiódł (powinno odczytać nową wartość rejestru SR2 = 00h).

Dla osób nieobeznanych z czytaniem dokumentacji układów mogą to się wydawać rzeczy trudne - ale od czego jest support :-) Już wkrótce więcej przykładów - a jeżeli macie jakieś pytania lub wątpliwości jak wykonać daną operacje przy pomocy skryptu to pytajcie śmiało.

ArT
Posts: 1020
Joined: Wed Mar 25, 2015 8:54 am
Location: Warsaw, Poland
Has thanked: 20 times
Been thanked: 96 times

Re: Programowanie skryptowe I2C i SPI [PORADNIK]

Postby ArT » Sat May 06, 2017 3:42 pm

Odczyt rejestru SFDP dla pamięci FLASH SPI

Code: Select all

#SCRIPT HEADER;
SCRIPT:v1.6.0;

#HARDWARE SETTINGS;
HW:SPI,2.8V,SLOW;

// SFDP 256 Byte table read (5A + 3B start addr + dummy byte + 256B read)
#OPERATION;
SW:0,0,1,255,5,5,0,0,100,500;
INSTR:5A,0,0,0,0;


Wynik dla pamięci Spansion FL512SA (512Mbit FLASH SPI 3V):
S25FL512A_SFDP_Register.jpg
S25FL512A_SFDP_Register.jpg (158.18 KiB) Viewed 3654 times


Return to “Wsparcie Techniczne”

Who is online

Users browsing this forum: No registered users and 1 guest