W ramach krótkiego wst?pu, powiem tylko, ?e osobi?cie nie polecam u?ywania biblioteki standardowej dla STM32 (STM32F10x Standard Peripherals Library), z kilku powodów, z których najwa?niejszym jest to, ?e tak czy siak nie ominie nas przeczytanie manuala dla danego uk?adu i zrozumienie zasady dzia?ania i konfiguracji danego uk?adu peryferyjnego, wi?c po co dok?ada? sobie do tego jeszcze dokumentacj? biblioteki? Z bibliotek? ale bez zrozumienia danego uk?adu peryferyjnego nic nie zrobimy, w odwrotnej "konfiguracji" (bez biblioteki, z wiedz?) - mo?na zrobi? wszystko co si? tylko chce. Generalnie wi?kszo?? zarzutów wzgl?dem tej biblioteki zebrana zosta?a w tym temacie na forum elektrody.
Nie da si? jednak zaprzeczy?, ?e s? osoby dla których mo?liwo?? u?ycia tej biblioteki jest wa?na i do nich w?a?nie kierowany jest ten artyku?.
Artyku? ten oparty jest o nast?puj?ce sk?adniki w nast?puj?cych wersjach (s? to najnowsze wersje na obecn? chwil?):
- projekt dla STM32 w postaci archiwum .zip pobrany z dzia?u Download > ARM > Przyk?ady (artyku? bazuje na wersji stm32_blink_led-1.2.1-120107),
- biblioteka STM32F10x Standard Peripherals Library rozpakowana w dowolnym miejscu (artyku? bazuje na wersji 3.5.0 rozpakowanej w g?ównym katalogu dysku c:, a wi?c dost?pnej pod ?cie?k? c:\STM32F10x_StdPeriph_Lib_V3.5.0).
- ?rodowisko skonfigurowane wed?ug minimalnie zmodyfikowanego (unowocze?nionego, szczegó?y opisane w komentarzach pod artyku?em i w temacie na forum elektrody) opisu z artyku?u ARM toolchain - tutorial:
Sposobów sprz?gni?cia przyk?adowych projektów z bibliotek? jest kilka, przedstawi? dwa podstawowe jakie przysz?y mi do g?owy. Obydwa maj? wspólny "pocz?tek" i wspólny "koniec" (sprawdzenie konfiguracji).
Wspólny pocz?tek
Dzia?ania rozpoczynamy od zaimportowania przyk?adu jako nowego projektu do Eclipse. Po uruchomieniu Eclipse klikamy wi?c w menu File, a nast?pnie w opcj? Import..., z ga??zi General wybieramy opcj? Existing Projects into Workspace i klikamy Next. Na kolejnej stronie wybieramy radiobuttona obok Select archive file i wprowadzamy ?cie?k? do archiwum z projektem który chcemy zaimportowa? - r?cznie lub za pomoc? przycisku Browse.... Po klikni?ciu przycisku Finish w drzewie projektów stworzony zostanie nowy projekt z gotowymi ustawieniami i wszystkimi plikami.
Je?li w workspace istnieje ju? projekt o danej nazwie, nie b?dzie mo?liwe zaimportowanie go z archiwum. W takim wypadku nale?y otworzy? istniej?cy ju? projekt, zmieni? jego nazw? (File > Rename gdy projekt jest zaznaczony lub opcja Rename z menu kontekstowego projektu) i dopiero wtedy zaimportowa? projekt wg powy?szego opisu. Po poprawnym imporcie mo?na projektom zmieni? nazwy wed?ug uznania lub zostawi? takie jak s? obecnie.
Teraz nale?y przyst?pi? do "odchudzenia" projektu z plików, które b?d? nam zb?dne. Usuwamy wi?c:
- folder inc wraz z zawarto?ci?,
- wszystkie pliki poza hdr_special_registers.h z katalogu hdr (w wersji 1.2.1 skasowa? wi?c nale?y pliki hdr_bitband.h, hdr_gpio.h i hdr_rcc.h),
- wszystkie pliki poza startupem (startup.S), tablic? wektorów (vectors.c), Makefile i skryptem linkera (STM32F103xB_rom.ld lub STM32F107xB_rom.ld), ewentualnie mo?na zostawi? Doxyfile (w wersji 1.2.1 skasowa? wi?c nale?y pliki config.h, gpio.c, gpio.h i main.c).
Celem tej operacji jest pozbycie si? z projektu funkcji main(), tak wi?c mo?na si? ograniczy? do skasowania samego pliku main.c lub nawet jedynie zmiany nazwy istniej?cej w nim funkcji main() na cokolwiek innego.
W tym momencie do projektu mo?emy doda? kilka plików potrzebnych do funkcjonowania biblioteki. Po zaznaczeniu naszego projektu klikamy wi?c na opcj? Import... z menu File (lub ta sama opcja z menu kontekstowego projektu), z grupy General wybieramy pozycj? File System i klikamy na Next. Nast?pnie podajmy ?cie?k? do szablonu projektu wchodz?cego w sk?ad biblioteki - r?cznie lub przyciskiem Browse - w moim przypadku b?dzie to c:\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template. W prawym okienku wybieramy do zaimportowania (poprzez zaznaczenie checkboxów) pliki stm32f10x_conf.h oraz system_stm32f10x.c i klikamy przycisk Finish.
Do projektu dodajemy te? pusty plik main.c - menu File > New > Source File, nast?pnie podajemy nazw? main.c w polu Source file i klikamy Finish (nazwa pliku oczywi?cie dowolna, byle mia? on rozszerzenie .c). W pliku tym umieszczamy pust? (na razie) funkcj? main():
int main(void) { return 0; }
Sposób 1 - pliki bazowe z przyk?adów, biblioteka w folderze projektu
Jest to najprostsza metoda osi?gni?cia za?o?onego celu. W sposobie tym kopiujemy po prostu wszystkie potrzebne pliki biblioteki do folderu projektu.
W projekcie (dla wi?kszego porz?dku) tworzymy folder (menu File > New > Folder lub - jak zwykle - menu kontekstowe katalogu projektu) o dowolnej nazwie - np lib - i importujemy do niego (sposób importowania plików przedstawiony zosta? nieco wcze?niej w tym artykule) nast?puj?ce zasoby:
- z folderu c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport - wszystkie pliki (core_cm3.c i core_cm3.h),
- z folderu c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x - plik stm32f10x.h oraz system_stm32f10x.h (dla porz?dku mo?na te? zaimportowa? do folderu lib plik system_stm32f10x.c a nast?pnie skasowa? go z g?ównego katalogu projektu, lub mo?na go pó?niej przenie??),
- z folderu c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\inc - wszystkie pliki,
- z folderu c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src - wszystkie pliki.
Teraz nale?y doda? do pliku Makefile kilka opcji, które umo?liwi? poprawn? kompilacj? plików biblioteki. Po otwarciu pliku Makefile w edytorze dokonujemy w nim nast?puj?cych zmian:
- w liniach CXX_DEFS i C_DEFS dodajemy nast?puj?ce definicje: -DUSE_STDPERIPH_DRIVER -DHSE_VALUE=8000000 (warto?? HSE_VALUE oczywi?cie uzale?niona od u?ywanego rezonatora kwarcowego), spowoduje to do??czenie do kodu odpowiednich nag?ówków (definicja symbolu USE_STDPERIPH_DRIVER) i odpowiedni? konfiguracj? funkcji które korzystaj? z warto?ci cz?stotliwo?ci zewn?trznego rezonatora kwarcowego (warto?? symbolu HSE_VALUE),
- w linii C_DEFS dodatkowo dopisujemy jeszcze -DSystemInit=low_level_init_1 - spowoduje to wywo?aniem funkcji SystemInit() (z biblioteki) w startupie tu? przed wywo?aniem funkcji main() - jest to wymagane przez aktualn? konwencj? biblioteki,
- w liniach INC_DIRS i SRCS_DIRS dodajemy nazw? stworzonego przez nas katalogu - np. lib,
- z linii C_WARNINGS usuwamy pozycj? -Wstrict-prototypes, aby niezgodne z "czystym" standardem j?zyka C deklaracje funkcji z CMSISa nie zasypa?y nas ostrze?eniami, ?e "function declaration isn't a prototype".
W tym momencie mo?liwa jest ju? bezb??dna i bezproblemowa kompilacja ca?ego projektu.
Sposób 2 - pliki bazowe z przyk?adów, biblioteka w innym folderze
W tej metodzie w projekcie wykorzystane s? pliki bazowe (startup, skrypt linkera, tablica wektorów i Makefile) z przyk?adu, a biblioteka znajduje si? w dowolnym miejscu.
Jak zwykle najwa?niejszym etapem jest dodanie do pliku Makefile niezb?dnych wpisów. Otwieramy wi?c plik Makefile w edytorze i wykonujemy w nim nast?puj?ce czynno?ci:
- w liniach CXX_DEFS i C_DEFS dodajemy nast?puj?ce definicje: -DUSE_STDPERIPH_DRIVER -DHSE_VALUE=8000000 (warto?? HSE_VALUE oczywi?cie uzale?niona od u?ywanego rezonatora kwarcowego), spowoduje to do??czenie do kodu odpowiednich nag?ówków (definicja symbolu USE_STDPERIPH_DRIVER) i odpowiedni? konfiguracj? funkcji które korzystaj? z warto?ci cz?stotliwo?ci zewn?trznego rezonatora kwarcowego (warto?? symbolu HSE_VALUE),
- w linii C_DEFS dodatkowo dopisujemy jeszcze -DSystemInit=low_level_init_1 - spowoduje to wywo?aniem funkcji SystemInit() (z biblioteki) w startupie tu? przed wywo?aniem funkcji main() - jest to wymagane przez aktualn? konwencj? biblioteki,
- w linii INC_DIRS dodajemy nast?puj?ce ?cie?ki z potrzebnymi nag?ówkami:
- c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport
- c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
- c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\inc
- w linii SRCS_DIRS dodajemy nast?puj?ce ?cie?ki z potrzebnymi plikami ?ród?owymi:
- c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport
- c:\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src
- z linii C_WARNINGS usuwamy pozycj? -Wstrict-prototypes, aby niezgodne z "czystym" standardem j?zyka C deklaracje funkcji z CMSISa nie zasypa?y nas ostrze?eniami, ?e "function declaration isn't a prototype".
Podaj?c wiele parametrów mo?na rozdzieli? je na klika linii przy pomocy znaku backslasha "\" lub powtarza? dan? zmienn? operatorem "+=" w kolejnych liniach VAR1 = value1 \ value2 \ value3 VAR2 = value1 VAR2 += value2 VAR2 += value3
W tym momencie projekt mo?na ju? skompilowa? i powinno si? to odby? bez b??dów, a wi?c zasadniczo wszystko jest w teorii gotowe.
Sprawdzenie konfiguracji
W ramach sprawdzenia mo?na sobie stworzy? prosty programik testowy - nie?miertelne miganie diod? LED, w którym skorzystamy z funkcji udost?pnianych przez Standard Peripheral Library. Ca?? zawarto?? pliku z funkcj? main() zast?pujemy wi?c przedstawionym poni?ej kodem, dostosowuj?c definicje portów i pinów do posiadanej przez nas konfiguracji.
#include "stm32f10x.h"
#define LED_GPIO GPIOB #define LED_GPIO_RCC RCC_APB2Periph_GPIOB #define LED_Pin GPIO_Pin_1
int main(void) { volatile uint32_t count, count_max = 3000000; GPIO_InitTypeDef GPIO_InitStructure;
/* LED_GPIO Periph clock enable */ RCC_APB2PeriphClockCmd(LED_GPIO_RCC, ENABLE);
/* Configure LED pin in output pushpull mode */ GPIO_InitStructure.GPIO_Pin = LED_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(LED_GPIO, &GPIO_InitStructure);
while (1) { /* Set */ GPIO_SetBits(LED_GPIO, LED_Pin); /* Delay */ for (count = 0; count < count_max; count++); /* Reset */ GPIO_ResetBits(LED_GPIO, LED_Pin); /* Delay */ for (count = 0; count < count_max; count++); } }
Po skompilowaniu ca?o?ci mo?na j? wgra? do uk?adu i debuggowa? - uruchamiaj?c dost?pne w projekcie predefiniowane skróty do OpenOCD (menu Run > External Tools > External Tool Configurations...) i GDB (menu Run > Degug Configurations... - nale?y wybra? skrót do GDB Hardware Debugging z ko?cówk? "+ load").
Niekiedy mo?e by? konieczne dostosowanie konfiguracji do dost?pnej wersji OpenOCD, konfiguracji sprz?towej lub innych szczegó?ów.
Po wgraniu i uruchomieniu program powinien miga? wybran? diod? z cz?stotliwo?ci? oko?o 1Hz (je?li rdze? pracuje na 72MHz, co jest domy?lnym ustawieniem biblioteki).
Je?li podczas kompilacji pliku core_cm3.c (szczególnie z w??czon? optymalizacj?) kompilator zasygnalizuje b??d assemblera: Error: registers may not be the same -- `strexb r0,r0,[r1]', Error: registers may not be the same -- `strexh r0,r0,[r1]', nale?y w pliku tym (po wy??czeniu atrybutu read-only) zmieni? "=r" na "=&r" w nast?puj?cych funkcjach: uint32_t __STREXB(uint8_t value, uint8_t *addr), uint32_t __STREXH(uint16_t value, uint16_t *addr), uint32_t __STREXW(uint32_t value, uint32_t *addr). Ciekawostk? jest to, ?e ARM w stworzonym przez siebie pliku nie trzyma si? swojej w?asnej dokumentacji... No có?...
Je?li pomimo poprawnej kompilacji projektu w konsoli Eclipse zasypuje nas b??dami typu Semantic Error o tre?ci "... could not be resolved" (gdy otwarty jest problematyczny plik ?ród?owy) nale?y wykona? nast?puj?ce kroki: 1. skompilowa? projekt tak aby powsta? plik wynikowy z rozszerzeniem .elf, 2. zamkn?? wszystkie zak?adki edytora, 3. zamkn?? i otworzy? projekt, 4. od?wie?y? zawarto?? folderu projektu (menu File > Refresh) - powinien pojawi? si? "folder" Binaries, 5. odbudowa? indeks projektu (menu kontekstowe projektu > Index > Rebuild).
Outro
Na podstawie opisanych powy?ej dwóch sposobów mo?na oczywi?cie opracowa? jeszcze kilka innych kombinacji, z których najbardziej interesuj?ca wydaje si? by? wersja z wykorzystaniem jedynie pliku Makefile z przyk?adów, podczas gdy pozosta?e pliki (startup, skrypt linkera, ...) b?d? pochodzi?y (np.) z paczki z bibliotek?. Taka konfiguracja by?aby jedynie nieznacznie zmieniona wzgl?dem drugiego z opisanych tu sposobów, trzeba tylko pami?ta? o dwóch drobnostkach z pliku Makefile:
- rozszerzenie plików assemblerowych (parametr AS_EXT) skonfigurowane jest jako .S, natomiast w paczce pochodz?cej od ST pliki te maj? rozszerzenie .s (ma?a litera),
- parametr USES_CXX nie ma znaczenia dla startupa nie pochodz?cego z przyk?adów.
W razie pyta? lub niejasno?ci, problemów i nie?cis?o?ci - jak zwykle - kontaktujcie si? ze mn? przez komentarze pod artyku?em, formularz kontaktowy strony lub przez temat na forum elektrody po?wi?cony temu artyku?owi. |