W praktyce każdego elektronika konstruktora zajmującego się mikrokontrolerami nadchodzi moment, gdy staje on przed problemem zaprogramowania układu, który nie jest obsługiwany przez używane środowisko IDE oraz programatory. O ile w przypadku bardziej popularnych mikrokontrolerów zdobycie odpowiedniego programatora nie stanowi większego problemu, o tyle w przypadku układów niszowych, ewentualnie używanych sporadycznie, inwestowanie w środowisko IDE i programator okazuje się trudne lub po prostu nie ma ekonomicznego uzasadnienia.
W takiej sytuacji można posłużyć się programem OpenOCD. Jednak, o ile obsługuje on dużą liczbę różnych typów programatorów JTAG i SWD, o tyle zbiór obsługiwanych przez ten program mikrokontrolerów jest ograniczony do bardziej popularnych układów. Niestety, nie zaliczają się do nich mikrokontrolery typu HC32F003 i HC32F005, z którymi przyszło pracować autorowi.
Mikrokontrolery HC32F003 i HC32F005
Układy te są produkowane przez firmę Huada Semiconductor. Należą one do bardzo szerokiej grupy układów scalonych wytwarzanych przez firmy dalekowschodnie, głównie chińskie, które są zgodne na poziomie wyprowadzeń z mikrokontrolerem typu STM8S003. Układy te są wyposażane w różne typy rdzeni, zarówno 8-bitowe, jak i 32-bitowe oraz bogate zestawy peryferii. Układy te nie są więc zgodne na poziomie kodu programu z mikrokontrolerem STM8S003. Z powodu firmowych układów peryferyjnych nie są one również zgodne programowo między sobą, nawet jeśli mają taki sam rdzeń. Zestawienie przykładowych układów należących do tej grupy zawiera tabela 1.
Układy HC32F003 i HC32F005 są typowymi mikrokontrolerami z rdzeniem ARM Cortex-M0+ wyposażonymi w podstawowy zestaw układów peryferyjnych obejmujący: liczniki/timery, szeregowe układy komunikacyjne I²C, SPI i UART, 12-bitowy przetwornik analogowo-cyfrowy oraz komparatory analogowe. Na wyposażeniu tych mikrokontrolerów znajduje się też sprzętowy blok obliczania CRC. Cechą wyróżniającą omawiane układy na tle bardziej popularnych w naszym kraju rodzin mikrokontrolerów z rdzeniem Cortex-M0+ jest szeroki zakres napięć zasilania rozciągający się od 1,8 V do 5,5 V.
Oba układy zawierają ten sam zestaw identycznych peryferiów i różnią się jedynie rozmiarem zaimplementowanej pamięci. Układ HC32F003 jest wyposażony w 2 kB pamięci SRAM i 16 kB pamięci Flash, natomiast układ HC32F005 ma 4 kB pamięci SRAM i 32 kB pamięci Flash. Na portalach aukcyjnych dostępne są proste płytki uruchomieniowe do tych mikrokontrolerów (fotografia 1). Ich wyposażenie jest minimalistyczne. Poza mikrokontrolerem, stabilizatorem napięcia zasilania, rezonatorem kwarcowym i przyciskiem RESET płytki zawierają tylko jeden przycisk i jedną diodę LED, które są przeznaczone do użycia przez program użytkownika. Na płytce uruchomieniowej nie ma układu programatora. Co gorsza, układy HC32F003 i HC32F005 nie mają też fabrycznego bootloadera, przez co ich programowanie jest możliwe tylko przez interfejs SWD.
Projekt pySTlink
Producent oferuje oczywiście własny programator dla tych układów, jak również wtyczki dla środowisk IDE firm Keil i IAR, pozwalające na programowanie mikrokontrolerów HC32F003/HC32F005 za pomocą programatora J-Link. W przypadku używania innego środowiska IDE stanowi to dla konstruktora problem, ponieważ nie są dostępne wtyczki dla innych IDE. Co gorsza, używany zazwyczaj w takich przypadkach program OpenOCD nie obsługuje omawianych mikrokontrolerów. Implementacja w tym pakiecie obsługi innych typów mikrokontrolerów jest możliwa, jednak ze względu na złożoność oprogramowania OpenOCD nie jest to zadanie proste, nie wspominając już o konieczności późniejszej rekompilacji tak zmodyfikowanego programu.
Poszukiwania w Internecie alternatywy dla programu OpenOCD, najchętniej obsługującej popularny programator typu STLink, doprowadziły do projektu pySTlink, którego autorem jest Pavel Revak. Program ten jest dostępny na licencji MIT. Obsługuje on co prawda tylko wybrane typy mikrokontrolerów STM32, ale jest prosty i pozwala na stosunkowo łatwą implementację obsługi innych typów układów. Ponieważ program został napisany w języku Python, odpada konieczność rekompilacji zmodyfikowanego kodu.
Pomimo swej prostoty, program pySTlink na dość duże możliwości. Pozwala on nie tylko na programowanie pamięci Flash mikrokontrolera, lecz także na zapis i odczyt jego pamięci SRAM, rejestrów roboczych rdzenia oraz rejestrów układów peryferyjnych. Możliwe jest także zatrzymywanie wykonywania programu przez mikrokontroler oraz praca krokowa. Pozwala to w podstawowym zakresie na debugowanie działania kodu programu. Pełną listę komend programu pyStlink umieszczono w ramce.
Uruchomienie pySTlink
Projekt pyStlink jest dostępny do pobrania z repozytorium git znajdującego się pod adresem https://github.com/pavelrevak/pystlink. Strukturę projektu pokazuje rysunek 1.
Do uruchomienia i prawidłowej pracy projekt pyStlink wymaga zainstalowanego środowiska języka Python w wersji 3.7 lub nowszej. Do prac nad programatorem mikrokontrolerów HC32F003/HC32F005 autor z powodzeniem używał środowiska Thonny IDE (https://thonny.org), które implementuje język Python w wersji 3.7.9. Oprócz interpretera języka Python konieczne jest też zainstalowanie modułu pyusb. Jest on dostępny do pobrania z repozytorium git pod adresem https://github.com/walac/pyusb. Ewentualnie pakiet ten może być pobrany z poziomu środowiska Python po wpisaniu komendy:
Ostatnim elementem niezbędnym do uruchomienia projektu pyStlink jest sterownik libusb. Jest on dostępny do pobrania pod adresem https://github.com/libusb/libusb. Sterownik ten należy pobrać, rozpakować archiwum i w przypadku systemów Windows umieścić plik libusb-1.0.dll w folderze Windows/System32. Teraz można podłączyć do komputera programator STlink w wersji V2, V2-1 albo V3 i uruchomić program pyStlink komendą:
Jeżeli wszystko działa prawidłowo, powinna zostać wyświetlona lista dostępnych opcji i komend programu pyStlink (rysunek 2).
Praca pySTlink
Program pyStlink automatycznie identyfikuje typ podłączonego mikrokontrolera. Definicje obsługiwanych przez program układów znajdują się w pliku devices.py umieszczonym w folderze /lib projektu (oryginalnie plik ten nosi nazwę stm32devices.py). Mają one postać listy słowników o nazwie DEVICES, z których każdy zawiera opisy mikrokontrolerów z tym samym typem rdzenia, poczynając od Cortex-M0 a kończąc na Cortex-M7. Łącznie lista ta liczy 5 pozycji.
{
‘part_no’: 0xc20,
‘core’: ‘CortexM0’,
‘idcode_reg’: 0x40015800,
‘devices’: [
………………………….
]
}
Każdy słownik listy DEVICES (listing 1) zawiera:
- kod identyfikatora rdzenia part_no,
- nazwę rdzenia core,
- listę adresów rejestrów idcode_reg, pod którymi należy poszukiwać rejestru z identyfikatorem mikrokontrolera,
- listę devices słowników zawierających definicje mikrokontrolerów o takim samym identyfikatorze mikrokontrolera.
{
‘dev_id’: 0x440,
‘flash_size_reg’: 0x1FFFF7CC,
‘flash_driver’: ‘STM32FP’,
‘erase_sizes’: (1024, ),
‘devices’: [
………………………….
]
}
Strukturę słownika listy devices z definicjami grup poszczególnych mikrokontrolerów o tym samym identyfikatorze pokazuje listing 2. Słownik ten zawiera:
- kod identyfikatora układu dev_id,
- adres rejestru flash_size_reg, w którym zapisany jest rozmiar zaimplementowanej w mikrokontrolerze pamięci Flash,
- nazwę sterownika flash_driver z funkcjami obsługi pamięci Flash w danej grupie mikrokontrolerów,
- rozmiar sektorów pamięci Flash erase_sizes,
- listę devices definicji poszczególnych typów mikrokontrolerów, ponownie w postaci listy słowników.
{‘type’: ‘STM32F030x8’, ‘flash_size’: 64, ‘sram_size’: 8, ‘eeprom_size’: 0, ‘freq’: 48}
Strukturę słownika z definicją typu mikrokontrolera pokazuje listing 3. Słownik ten zawiera:
- nazwę układu type,
- rozmiar pamięci Flash flash_size w kB,
- rozmiar pamięci SRAM sram_size w kB,
- rozmiar pamięci EEPROM eeprom_size w kB,
- maksymalną częstotliwość freq taktowania rdzenia w MHz.
Po uruchomieniu program pyStlink w pierwszym kroku identyfikuje typ rdzenia podłączonego mikrokontrolera. W tym celu odczytuje z układu zawartość rejestru CPUID znajdującego się pod adresem 0xE000 ED00 i wydziela bity b15...b4 określające typ rdzenia (rysunek 3). Uzyskany identyfikator part_no służy do wyboru słownika z listy DEVICES obsługiwanych układów mających wykryty typ rdzenia. Następnie program pyStlink pobiera z wybranego słownika listę idcore_reg adresów, pod którymi należy poszukiwać rejestru zawierającego identyfikator dev_id układu. W przypadku mikrokontrolerów STM32 identyfikator układu zawarty jest w większości przypadków w rejestrze DBGMCU_IDCODE o adresie 0x4001 5800. Strukturę tego rejestru pokazuje rysunek 4. Bity b11...b0 zawierają poszukiwany identyfikator układu dev_id. Jest on używany przez program pyStlink do wyboru z listy devices słownika z definicjami typów mikrokontrolerów.
W kolejnym kroku program pyStlink pobiera z wybranego słownika nazwę sterownika pamięci Flash oraz odczytuje adres rejestru zawierającego rozmiar zaimplementowanej w mikrokontrolerze pamięci Flash. W przypadku mikrokontrolerów STM32 jest to Flash Size Data Register. Jego adres zależy od rodziny mikrokontrolerów i w przypadku układów STM32F0 jest równy 0x1FFF F7CC. Następnie program pyStlink odczytuje z układu rozmiar pamięci Flash i używa go do wyboru z listy devices słownika z opisem konkretnego typu mikrokontrolera. W sytuacji, gdy kilka typów mikrokontrolerów o tym samym identyfikatorze dev_id ma identyczny rozmiar pamięci Flash, program pyStlink posiłkuje się podaną przez użytkownika w linii komend nazwą podłączonego układu. Wybór słownika z opisem konkretnego typu mikrokontrolera kończy proces automatycznej identyfikacji. Program wyświetla dane zidentyfikowanego układu i przystępuje do wykonywania komend podanych przez użytkownika podczas uruchomienia programu.
Modyfikacja pySTlink
Rozbudowa programu pyStlink o obsługę mikrokontrolera nowego typu sprowadza się do dodania do listy DEVICES słownika z opisem mikrokontrolera oraz napisania sterownika pamięci Flash dla tego układu. W przypadku mikrokontrolerów HC32F003/HC32F005, słownik z ich opisem powinien znaleźć się na liście devices w słowniku zawierającym definicje układów o identyfikatorze rdzenia part_no równym 0xC60, tj. grupującym układy wyposażone w rdzeń Cortex-M0+.
W przeciwieństwie do układów SMT32, kod identyfikacyjny w mikrokontrolerach HC32F003/HC32F005 ma postać łańcucha tekstowego znaków ASCII o maksymalnej długości 16 B. Znajduje się on w obszarze pamięci o adresie 0x0010 0C60 ~ 0x0010 0C6F, np. identyfikator mikrokontrolera zamontowanego w przedstawionej na fotografii 1 płytce uruchomieniowej jest równy ‘HC32F005C6PA’. Aby nie modyfikować sposobu identyfikacji układu przez program pyStlink, najprościej jest potraktować pierwsze cztery znaki łańcucha identyfikatora mikrokontrolera HC32F003/HF23F005 jakby były one 32-bitowym rejestrem DBGMCU_IDCODE w układzie STM32. Przy takim podejściu zawartość tego rejestru będzie równa 0x3233 4348 (odwrócenie kolejności znaków łańcucha identyfikatora układu wynika z faktu, że mikrokontrolery ARM z rdzeniem Cortex-M0+ stosują konwencję organizacji pamięci Little Endian). Kod identyfikacyjny układu rozpoznawany przez program pyStlink będzie więc równy 0x348.
Rozmiar pamięci Flash zaimplementowanej w mikrokontrolerze HC32F003/HC32F005 jest zawarty w rejestrze Flash o adresie 0x0010 0C70, a pamięci SRAM – w rejestrze RAM o adresie 0x0010 0C74. W przeciwieństwie do mikrokontrolerów STM32 rozmiar pamięci jest tutaj podawany w bajtach. Dodatkowo w 16-bitowym rejestrze PINCOUNT o adresie 0x0010 0C7A zawarta jest informacja o liczbie wyprowadzeń układu, np. w przypadku mikrokontrolera zamontowanego w przedstawionej na fotografii 1 płytce uruchomieniowej rejestr Flash zawiera liczbę 0x0000 8000 (tj. 32768B), rejestr RAM – liczbę 0x0000 1000 (tj. 4096B), a rejestr PINCOUNT – liczbę 0x0014 (tj. 20 pinów). Zdefiniowane na podstawie powyższych informacji opisy mikrokontrolerów HC32F003 i HC32F005 w liście DEVICES przedstawia listing 4.
{
‘part_no’: 0xc60,
‘core’: ‘CortexM0+’,
‘idcode_reg’: [0x40015800, 0x00100C60],
‘devices’: [
………………………….
{
‘dev_id’: 0x348, # Huada Semiconductor
‘flash_size_reg’: 0x00100C70,
‘flash_size_units’: ‘Bytes’,
‘flash_driver’: ‘HC32F0’,
‘erase_sizes’: (512, ),
‘devices’: [
{‘type’: ‘HC32F003’, ‘flash_size’: 16, ‘sram_size’: 2, ‘eeprom_size’: 0, ‘freq’: 32},
{‘type’: ‘HC32F005’, ‘flash_size’: 32, ‘sram_size’: 4, ‘eeprom_size’: 0, ‘freq’: 32},
]
}
]
}
Ze względu na przyjęte w tych mikrokontrolerach podawanie rozmiaru pamięci w bajtach w opisie mikrokontrolerów HC32F003/HC32F005 dodano dodatkową pozycję słownika flash_size_units, która będzie sterowała w programie pyStlink obliczaniem rozmiaru pamięci. Dzięki takiemu rozwiązaniu nie ma konieczności modyfikowania jednostek rozmiaru pamięci w już zdefiniowanych w programie pyStlink opisach układów SMT32.
Jak wynika z podanego w listingu 4 opisu mikrokontrolerów HC32F003/HC32F005, ich sterownik pamięci Flash będzie nosił nazwę ‘HC32F0’. Zgodnie ze strukturą projektu pyStlink (rysunek 1) będzie on znajdował się w dedykowanym pliku o nazwie hdsc.py w folderze /lib. Plik ten zawiera opisy dwóch klas: klasy HC32F0, która jest właściwym sterownikiem, oraz klasy Flash zawierającej metody obsługi pamięci Flash w mikrokontrolerze.
Klasa HC32F0 została stworzona jako klasa pochodna klasy Stm32, dzięki czemu konieczne jest tylko dodanie do niej definicji dwóch nowych metod: metody flash_erase_all kasowania zawartości całej pamięci Flash mikrokontrolera HC32F003 i HC32F005 oraz metody flash_write zapisu pamięci Flash. Pozostałe metody odczytu i zapisu rejestrów mikrokontrolera, odczytu i zapisu pamięci SRAM, odczytu pamięci Flash itd. pochodzą z klasy Stm32 i nie wymagają modyfikacji. Uproszczony kod klasy HC32F0, pozbawiony komunikatów debug i wizualizacji postępu zapisu pamięci Flash, przedstawia listing 5.
class HC32F0(lib.stm32.Stm32):
Flash_START = 0x00000000
Flash_PAGE_SIZE = 512
SRAM_START = 0x20000000#
# b0=1 for Thumb2 instruction set
SRAM_CODE = SRAM_START | 0x00000001
def flash_erase_all(self, flash_size):
flash = Flash(self, self._stlink, self._dbg)
flash.erase_all();
def flash_write(self, addr, data, erase=False, erase_sizes=None):
if addr is None:
addr = self.Flash_START
flash = Flash(self, self._stlink, self._dbg)
if erase:
if erase_sizes:
flash.erase_pages(addr, len(data))
else:
flash.erase_all()
flash.set_nvm_mode(flash.Flash_CR_OP_PRG)
flash.unlock_all()
self.set_reg(‘PC’, self.SRAM_CODE)
data_block = data
data_addr = addr
while len(data_block):
if (data_addr % 4 == 0) & (len(data_block) >= 4):
self._stlink.set_mem32(data_addr, data_block[:4])
data_addr += 4
data_block = data_block[4:]
elif (data_addr % 2 == 0) & (len(data_block) >= 2):
self._stlink.set_mem16(data_addr, data_block[:2])
data_addr += 2
data_block = data_block[2:]
else :
self._stlink.set_mem8(data_addr, data_block[:1])
data_addr += 1
data_block = data_block[1:]
flash.wait_busy(0.005)
flash.lock_all()
flash.set_nvm_mode(flash.Flash_CR_OP_RD)
Działanie metody flash_write zapisu pamięci rozpoczyna się od skasowania zawartości pamięci Flash. Standardowo kasowane są tylko te sektory pamięci, które mają zostać zapisane (komenda flash.erase_pages(addr, len(data))), chyba że w wywołaniu programu pyStlink podano komendę kasowania całej pamięci Flash. W takim przypadku czyszczona jest cała pamięć (komenda flash.erase_all()). Następnie kontroler pamięci Flash w mikrokontrolerze jest przełączany w tryb programowania (komenda set_nvm_mode(flash.Flash_CR_OP_PRG)) i odblokowywany jest zapis do wszystkich sektorów pamięci Flash (komenda flash.unlock_all()). Dodatkowo licznik rozkazów w mikrokontrolerze jest ustawiany na początek pamięci SRAM (komenda set_reg(‘PC’, SRAM_CODE)).
Jest to konieczne, ponieważ mikrokontrolery HC32F003/HC32F005 mają dodatkowe zabezpieczenie przed kasowaniem i zapisem sektora pamięci Flash, z którego jest wykonywany program. Aby więc nie kontrolować położenia licznika rozkazów i nie przełączać go pomiędzy kolejnymi sektorami pamięci podczas jej zapisu, najprościej jest ustawić go na stałe na pobieranie kodu z pamięci SRAM.
Sam zapis pamięci Flash jest realizowany słowo po słowie. Aby odbywał się on z największą możliwą prędkością, sterownik HC32F0, w zależności od liczby zapisywanych danych i ich położenia, dokonuje zapisu pamięci Flash słowem o długości 32-bitów (komenda _stlink.set_mem32(data_addr, data_block[:4])), 16-bitów (komenda _stlink.set_mem16(data_addr, data_block[:2])) albo 8-bitów (komenda _stlink.set_mem8(data_addr, data_block[:1])). W zasadzie można byłoby poprzestać tylko na zapisie słów o długości 8-bitów, co uprościłoby kod metody flash_write, jednak wydłużyłoby to czterokrotnie czas programowania. Zapis pamięci kończy się włączeniem ochrony wszystkich sektorów (komenda flash.lock_all()) i przełączeniem kontrolera pamięci Flash w tryb odczytu (komenda flash.set_nvm_mode(flash.Flash_CR_OP_RD)). Wszystkie metody obsługi pamięci Flash w mikrokontrolerze HC32F003/HC32F005 są zgrupowane w klasie Flash. Zestawiono je w tabeli 2.
Sterownik HC32F0 wykonuje operacje na pamięci Flash mikrokontrolera za pośrednictwem jego kontrolera pamięci Flash, dokonując zapisu i odczytu odpowiednich rejestrów w kontrolerze. Mapę rejestrów kontrolera pamięci Flash w mikrokontrolerach HC32F003/HC32F005 zestawiono w tabeli 3.
Rejestry Flash_Txxxx określają parametry czasowe operacji zapisu i kasowania pamięci Flash. Są one ściśle powiązane z częstotliwością taktowania układu. Wymagane ustawienia tych rejestrów dla częstotliwości zegara systemowego równej 4 MHz, 8 MHz, 16 MHz, 24 MHz i 32 MHz są podane w dokumentacji mikrokontrolerów HC32F003/HC32F005. Rejestr kontrolny Flash_CR (rysunek 5) zawiera z kolei stan kontrolera pamięci Flash oraz określa tryb jego pracy. Zawartość wszystkich rejestrów kontrolera jest chroniona przed niezamierzoną modyfikacją. Ochronę tę wyłącza rejestr Flash_BYPASS. Zapis do niego słowa 0x5A5A a następnie słowa 0xA5A5 zezwala na dokonanie jednej operacji zapisu do jednego rejestru kontrolera pamięci Flash.
Koncepcyjnie operacje wykonywane przez sterownik HC32F0 nie różnią się niczym od operacji na pamięci Flash wykonywanych przez np. program bootloader uruchomiony w pamięci mikrokontrolera. Jedyna różnica polega na tym, że zapis i odczyt rejestrów kontrolera pamięci Flash jest wykonywany nie bezpośrednio, lecz za pośrednictwem programatora ST-Link. Poszczególne operacje zostały zaimplementowane zgodnie z zaleceniami zawartymi w dokumentacji mikrokontrolera HC32F003/HC32F005. Obsługa pamięci Flash odbywa się przy zegarze systemowym skonfigurowanym do pracy z częstotliwością 4 MHz. Ponieważ sterownik HC32F0 nie używa sygnału nRST, inicjalizacja mikrokontrolera i jego kontrolera pamięci Flash jest dość długa. Głównym ograniczeniem jest fakt, iż w mikrokontrolerze HC32F003/HC32F005 zmiana źródła i częstotliwości sygnału taktującego musi być wykonana ściśle według kroków opisanych w dokumentacji układu. Inaczej nie jest gwarantowana prawidłowa praca mikrokontrolera. Same operacje na kontrolerze pamięci Flash są już znacznie prostsze.
def erase_all(self):
self._dbg.verbose(‘Erase chip’)
self.set_nvm_mode(self.Flash_CR_OP_CHIP_ERASE)
self.unlock_all()
self._driver.set_reg(‘PC’, self._driver.SRAM_CODE)
self._stlink.set_mem8(self._driver.Flash_START, [0x00])
self.wait_busy(5, ‘Erasing Flash’)
self.lock_all()
self.set_nvm_mode(self.Flash_CR_OP_RD)
Listing 6 prezentuje przykładowy kod metody realizującej kasowanie zawartości całej pamięci Flash. Ze szczegółowym kodem pozostałych metod klasy Flash można zapoznać się, analizując kod źródłowy programu pyStlink znajdujący się w materiałach dodatkowych do artykułu.
Podsumowanie
Mikrokontrolery HC32F003/HC32F005 nie zostały wyposażone przez producenta w możliwość sprzętowej konfiguracji części parametrów ich pracy, znaną np. w mikrokontrolerach AVR pod postacią Fuse Bits, czy układach STM32 jako Option Bytes. Układy te nie mają też zaimplementowanych mechanizmów zabezpieczających kod w pamięci Flash przed nieautoryzowanym dostępem (tj. programowanych przez użytkownika bitów zabezpieczających). Implementacja w sterowniku HC32F0 kasowania pamięci Flash oraz jej zapisu w całości wyczerpuje więc funkcjonalność układów HC32F003/HC32F005.
Użytkowanie programu pyStlink jest identyczne jak innych tego rodzaju narzędzi wywoływanych z linii komend. Większość środowisk IDE pozwala na integrację takich programów i uruchamianie ich z poziomu IDE przez wybranie odpowiedniej ikony. W najprostszej postaci wywołanie zapisu do pamięci Flash mikrokontrolera pliku z kodem programu w formacie binarnym będzie miało postać:
Na rysunku 6 pokazano zrzut ekranu z procesu zapisu za pomocą programatora/debuggera ST-Link V2, wchodzącego w skład płytki uruchomieniowej STMF0DISCOVERY, pamięci Flash mikrokontrolera HC32F005 na płytce uruchomieniowej z fotografii 1. Płytka uruchomieniowa była połączona z programatorem ST-Link dwoma liniami interfejsu SWD: SWCLK i SWDIO oraz przewodami zasilania i masy. Widok całego zmontowanego zestawu testowego prezentuje fotografia tytułowa.
Aleksander Borysiuk
alex_priv@wp.pl
Źródła:
- Mikrokontrolery HC32F003/HC32F005: https://bit.ly/3pBtdDA
- Program pyStlink: https://github.com/pavelrevak/pystlink
- Moduł pyusb: https://github.com/walac/pyusb
- Sterownik libusb: https://github.com/libusb/libusb
- Thonny IDE: https://thonny.org
Wywołanie programu z linii komend:
pystlink [-h] [-q | -i | -v | -d] [-V] [-c CPU] [-r] [-u] [-s SERIAL] [-n INDEX] [-H] [action [action…]]
Opcjonalne parametry:
-h, --help: wyświetlenie listy dostępnych parametrów i komend
-q, --quiet: wyłączenie komunikatów
-i, --info: podstawowy zestaw komunikatów (opcja domyślna)
-v, --verbose: rozszerzony zestaw komunikatów
-d, --debug: komunikaty debug pracy programu
-V, --version: wyświetlenie wersji programu
-c CPU, --cpu CPU: oczekiwany typ mikrokontrolera [np.: STM32F051, STM32L4]
-r, --no-run: pozostawienie rdzenia mikrokontrolera w stanie zatrzymania po zakończeniu działania programu
-u, --no-unmount: brak odmontowania funkcji DISCOVERY dla programatora ST-Link/V2-1 w systemie OS/X
-s SERIAL, --serial SERIAL: wybór programatora STLink o podanym numerze seryjnym
-n INDEX, --num-index INDEX: wybór programatora STLink o podanym indeksie
-H, --hard: sprzętowy reset mikrokontrolera linią NRST
Akcje:
dump:core: wyświetlenie zawartości wszystkich rejestrów roboczych rdzenia
dump:{reg}: wyświetlenie zawartości wybranego rejestru roboczego rdzenia
dump:{addr}:{size}: wyświetlenie zawartości pamięci, poczynając od podanego adresu
dump:sram[:{size}]: wyświetlenie zawartości pamięci SRAM
dump:flash[:{size}]: wyświetlenie zawartości pamięci Flash
dump:{addr}: wyświetlenie zawartości 32-bitowego rejestru o podanym adresie
dump16:{addr}: wyświetlenie zawartości 16-bitowego rejestru o podanym adresie
dump8:{addr}: wyświetlenie zawartości 8-bitowego rejestru o podanym adresie
set:{reg}:{data}: zapis podanej wartości do podanego rejestru roboczego rdzenia
set:{addr}:{data}: zapis podanej wartości do 32-bitowego rejestru o podanym adresie
read:{addr}:{size}:{file}: zapis do pliku zawartości pamięci, poczynając od podanego adresu
read:sram[:{size}]:{file}: zapis do pliku zawartości pamięci SRAM
read:flash[:{size}]:{file}: zapis do pliku zawartości pamięci Flash
fill:{addr}:{size}:{pattern}: wypełnienie pamięci SRAM podanym wzorem, poczynając od podanego adresu
fill:sram[:{size}]:{pattern}: wypełnienie pamięci SRAM podanym wzorem
write:{file.srec}: zapis danych z pliku w formacie SREC do pamięci SRAM
write:{addr}:{file}: zapis danych z pliku w formacie binarnym do pamięci SRAM, poczynając od podanego adresu
write:sram:{file}: zapis danych z pliku w formacie binarnym do pamięci SRAM
flash:erase: skasowanie zawartości całej pamięci Flash
flash[:erase][:verify]:{file.srec}: skasowanie wymaganej liczby sektorów pamięci Flash + zapis danych z pliku w formacie SREC do pamięci Flash + weryfikacja poprawności zapisu
flash[:erase][:verify][:{addr}]:{file}: skasowanie wymaganej liczby sektorów pamięci Flash + zapis
danych z pliku w formacie binarnym do pamięci Flash, poczynając od podanego adresu + weryfikacja poprawności zapisu
flash:check:{file.srec}: weryfikacja zawartości pamięci Flash z danymi z pliku w formacie SREC
flash:check[:{addr}]:{file}: weryfikacja zawartości pamięci Flash z danymi z pliku w formacie binarnym, poczynając od podanego adresu
reset: reset rdzenia mikrokontrolera
reset:halt: reset i zatrzymanie rdzenia mikrokontrolera
halt: zatrzymanie rdzenia mikrokontrolera
step: wykonanie przez rdzeń jednego rozkazu
run: wznowienie wykonywania programu
sleep:{seconds}: wstawienie opóźnienia pomiędzy akcjami