Kiedyś programiści tworzyli cały swój kod od podstaw. Było to trudne, czasochłonne i niezbyt przyjemne dla osób pracujących z systemami embedded. Deweloperzy systemów wbudowanych walczyli o zmianę, a w reakcji na to dostawcy mikrokontrolerów generowali środowiska do kompilacji czy platformy abstrakcji sprzętowej dla niskopoziomowego kodu startowego i środowiska kompilacji. Programiści byli zadowoleni, gdyż dzięki temu mogli szybciej pisać kod dla swoich aplikacji. Chociaż udostępnienie wstępnie skonfigurowanego środowiska kompilacji jest pomocne, istnieje pięć czynników, dla których zespoły programistów powinny rozważyć zbudowanie własnego, dla pisania oprogramowania w C/C++, zamiast wykorzystywać to zapewniane przez dostawcę mikrokontrolerów.
Powód nr 1 — zrozumienie podstaw aplikacji
Wiele podmiotów przed chwilą wskazanych wykonało świetną robotę, tworząc platformy programistyczne, których osoby zainteresowane mogą używać do opracowywania swoich produktów wbudowanych. W końcu ich klienci odnoszą korzyści, jeśli producent przeprowadzi za nich wszystkie prace zwykle realizowane w każdym produkcie. Mowa tu o pisaniu skryptów linkera, przygotowaniu kodu startowego, linkerze dla standardowych bibliotek czy inicjowaniu mikrokontrolera. Klient może zignorować ten standardowy kod i skoncentrować się na szybszym stworzeniu logiki aplikacji. Dzięki czemu produkt prędzej wejdzie na rynek i ogólnie sprzeda się więcej mikrokontrolerów.
Problemem, którego wielu mogło być już świadkiem, jest to, że programiści często ignorują ten kod niskiego poziomu. Tudzież tracą go z oczu, przez co nie wiedzą, jak działa ich środowisko kompilacji, a nawet te jego elementy, które są krytycznie powiązane z ich projektem! Być może nawet gorzej — kod, napisany przez dostawcę mikrokontrolerów, został opracowany jako ogólny, który jest uniwersalnym rozwiązaniem, co oznacza, że może on nie współpracować idealnie z żadną konkretną aplikacją — jak coś jest do wszystkiego, to jest do niczego...
Budowanie środowiska kompilacji, w którym tworzy się konsolidatory, kod startowy, konfiguruje część wykonawczą C/C++ i generuje pliki makefile, zapewnia zrozumienie podstaw aplikacji i całości. Wiadomo wtedy, które sekcje tam są i dlaczego je wykorzystano. Dzięki temu deweloper lepiej zdaje sobie sprawę, jakiego zestawu i flag C/C++ używa do konstruowania swojej aplikacji i dlaczego. W rzeczywistości można dowiedzieć się więcej nawet o środowisku wykonawczym C/C++ i o tym, jak może ono wpływać na rozmiar generowanego kodu i wydajność jego wykonywania. Jeśli po prostu skorzysta się z tego, co dostarcza producent bez przeglądania, można przegapić istotne szczegóły.
Powód nr 2 — optymalizacja kodu
Domyślnie wiele środowisk kompilacji udostępnianych programistom może być przygotowanych do programowania wbudowanego, ale często są one konfigurowane jako rozwiązanie ogólne i uniwersalne. Założenie takie ma na celu zaspokojenie potrzeb 'przeciętnego dewelopera' lub 'typowej firmy'. Niestety, rezultatem może nierzadko być kod przepełniony niepotrzebnymi funkcjami bibliotecznymi, a nawet zbyt skomplikowany do odczytania. Na przykład — wystarczy spojrzeć na dużą część takowego abstrakcji sprzętowej, choć też na inne, dostarczanego przez dostawcę. Będzie on zawierać standardowe wywołania systemowe z biblioteki C, takie jak printf, _exit, _kill, _read, _write itp. Użycie minimalnej implementacji tych wywołań może z łatwością dodać ponad 10 kilobajtów przestrzeni kodu. Być może nie jest to wielki problem dla wielu zespołów pracujących nad najnowocześniejszymi procesorami 32-bitowymi, ale dla reszty branży systemów wbudowanych może to oznaczać różnicę pomiędzy powodzeniem projektu a porażką. (Często ma miejsce sytuacja, gdzie tworząc koncept bazowy z kodu platformy, który mruga tylko diodą LED, stwierdza się, że kompiluje się do ponad 60 kilobajtów!)
Inni programiści zajmujący się optymalizacją nieraz pomijają pewne sztuczki wydajnościowe, które domyślnie nie działają w ich predefiniowanym systemie kompilacji. Na przykład, jeśli pracuję z częścią ze specjalną pamięcią RAM typu no-wait, można skonfigurować kod startowy, aby umieścić w niej wektory przerwań, aby uzyskać bardziej efektywne, deterministyczne zachowanie w czasie ich wykonywania. Niestety kod dostarczany przez dostawcę często tego nie robi. Jeśli nie zbudujemy lub nie zbadamy dokładnie swojego środowiska, marnujemy cykle zegara i prawdopodobnie wydłużamy period reakcji systemu na przerwanie.
Powód nr 3 — łatwiejsza integracja z procesami Agile i DevOps
Korzystanie z metodyk zwinnych (Agile) i ujęć DevOps to współcześnie niezbędny proces przy produkcji oprogramowania, który staje się również popularny w wielu zespołach zajmujących się aplikacjami wbudowanymi. Zwinne metodologie zyskujące uznanie w społeczności systemów wbudowanych dotyczą między innymi ujęcia takiego jak programowanie sterowane testami (TDD). DevOpsing obejmuje znacznie więcej niż tylko ciągłą integrację i wdrażanie (CI/CD), ale na tym skupia się większość zespołów, użytkujących te narzędzia.
Korzystając ze środowiska dostarczonego przez producenta mikrokontrolera, spożytkowanie procesów TDD czy CI/CD może być bardziej kłopotliwe i złożone. Dzieje się tak dlatego, że nie biorą one pod uwagę takich ujęć, które wiążą się z wykonaniem pewnych dodatkowych kroków, aby dostarczyć produkt zgodnie ze zwinną metodologią, tylko to, czego po prostu potrzeba, aby ich procesor zwyczajnie działał. Rezultatem może być środowisko kompilacji, które nie współgra dobrze z innymi procesami i potrzebami. Zespoły nierzadko zmagają się z obejściem tego problemu. A czasem nawet wykorzystują dwa różne środowiska, aby wszystkie te procesy i narzędzia dobrze do siebie pasowały.
Powód nr 4 — elastyczność
Niekiedy zdarza się, że całość, która już została zbudowana, była trudna do dostosowania do zmieniających się wymagań. Czasami w systemie kompilacji jest tak wiele małych haczyków, że usprawnienie go zajęłoby dwa razy więcej czasu niż zaczynanie od zera. Na przykład można chcieć wyłączyć bibliotekę, ale okazuje się, że powoduje to kilkadziesiąt błędów kompilacji, które zmuszają do rozwiązania sporej liczby zależności, co wymaga wielu godzin pracy.
Jednym z podejść, które wydaje się bardzo pomocne, jest wykorzystanie elastyczności IDE. Często można stwierdzić, że różni programiści mają odmienne preferencje co do spożytkowania IDE i edytorów tekstu, których chcą używać. Na przykład ktoś może polubić Sublime Text, druga osoba pisze w Visual Studio Code lub stawia na jeszcze inne IDE dostarczone przez dostawcę mikrokontrolera. Deweloperzy nieraz żartują i kłócą się, próbując uzyskać preferowane narzędzie jako wybór całego zespołu. Jeśli skonstruujemy swoje środowisko od podstaw, każdy może korzystać z cenionego przez siebie narzędzia, które może pomóc poprawić wydajność programistów.
Powód nr 5 — zbuduj dostosowanie systemu
Dla wielu deweloperów najważniejszym powodem przygotowywania własnego środowiska do kodowania C/C++ jest możliwość dokonywania adaptacji. Jak wspomniano wcześniej, nie ma nigdy dwóch takich samych projektów. Istnieją pewne podobieństwa między poszczególnymi, ale zawsze można radykalnie zoptymalizować rozmiar kodu i/lub jego wydajność, dostosowując system kompilacji. Czasami nie uda się od razu zrozumieć, jakie modyfikacje są potrzebne, dopóki nie zacznie się stawiać środowiska od zera. Wielu z nas proces taki może otworzyć oczy na zyski z danego przeobrażenia.
Istnieje wiele dostosowań do rozważenia, takich jak:
* Środowisko skonfigurowane z kontenerami Dockerowymi;
* Flagi dla assemblera;
* Flagi dla C/C++;
* Integracje wybranych bibliotek;
* Sposób obsługi kodu startowego mikrokontrolera;
* Integracja dedykowanej tabeli wektorów;
* Integracja z procesami TDD;
* Integracja z procesami ciągłej integracji czy ciągłego wdrożenia (CI/CD);
* Analiza kodu;
* Itd.
Możliwość dostosowania środowiska C/C++ i systemu kompilacji może znacząco wpłynąć na powodzenie projektu.
Podsumowanie
Tworzenie niestandardowego systemu do kompilacji dla aplikacji wbudowanej ma wiele zalet. Powyżej wymieniono kilka z nich, które, miejmy nadzieję, wzbudziły zainteresowanie czytających programistów systemów wbudowanych. Z początku podjęcie takiego przedsięwzięcia może wydawać się skomplikowane i obarczone potencjalnymi, własnymi problemami. Na szczęście proces ten jest znacznie mniej zawiły, niż mogłoby się wydawać. Niestandardowy system kompilacji można stworzyć i wdrożyć dla prawie każdego wbudowanego procesora w mniej niż tydzień. Co więcej, omawiana całość jest wysoce dedykowanym, dobrze zoptymalizowanym ujęciem, które może pomóc w przygotowaniu podstaw dla naszej aplikacji i zbudowaniu procesów mogących wspierać produkty przez lata.
Źródło: https://www.embedded.com/5-reasons-to-build-your-own-c-c-environment/
Powód nr 1 — zrozumienie podstaw aplikacji
Wiele podmiotów przed chwilą wskazanych wykonało świetną robotę, tworząc platformy programistyczne, których osoby zainteresowane mogą używać do opracowywania swoich produktów wbudowanych. W końcu ich klienci odnoszą korzyści, jeśli producent przeprowadzi za nich wszystkie prace zwykle realizowane w każdym produkcie. Mowa tu o pisaniu skryptów linkera, przygotowaniu kodu startowego, linkerze dla standardowych bibliotek czy inicjowaniu mikrokontrolera. Klient może zignorować ten standardowy kod i skoncentrować się na szybszym stworzeniu logiki aplikacji. Dzięki czemu produkt prędzej wejdzie na rynek i ogólnie sprzeda się więcej mikrokontrolerów.
Problemem, którego wielu mogło być już świadkiem, jest to, że programiści często ignorują ten kod niskiego poziomu. Tudzież tracą go z oczu, przez co nie wiedzą, jak działa ich środowisko kompilacji, a nawet te jego elementy, które są krytycznie powiązane z ich projektem! Być może nawet gorzej — kod, napisany przez dostawcę mikrokontrolerów, został opracowany jako ogólny, który jest uniwersalnym rozwiązaniem, co oznacza, że może on nie współpracować idealnie z żadną konkretną aplikacją — jak coś jest do wszystkiego, to jest do niczego...
Budowanie środowiska kompilacji, w którym tworzy się konsolidatory, kod startowy, konfiguruje część wykonawczą C/C++ i generuje pliki makefile, zapewnia zrozumienie podstaw aplikacji i całości. Wiadomo wtedy, które sekcje tam są i dlaczego je wykorzystano. Dzięki temu deweloper lepiej zdaje sobie sprawę, jakiego zestawu i flag C/C++ używa do konstruowania swojej aplikacji i dlaczego. W rzeczywistości można dowiedzieć się więcej nawet o środowisku wykonawczym C/C++ i o tym, jak może ono wpływać na rozmiar generowanego kodu i wydajność jego wykonywania. Jeśli po prostu skorzysta się z tego, co dostarcza producent bez przeglądania, można przegapić istotne szczegóły.
Powód nr 2 — optymalizacja kodu
Domyślnie wiele środowisk kompilacji udostępnianych programistom może być przygotowanych do programowania wbudowanego, ale często są one konfigurowane jako rozwiązanie ogólne i uniwersalne. Założenie takie ma na celu zaspokojenie potrzeb 'przeciętnego dewelopera' lub 'typowej firmy'. Niestety, rezultatem może nierzadko być kod przepełniony niepotrzebnymi funkcjami bibliotecznymi, a nawet zbyt skomplikowany do odczytania. Na przykład — wystarczy spojrzeć na dużą część takowego abstrakcji sprzętowej, choć też na inne, dostarczanego przez dostawcę. Będzie on zawierać standardowe wywołania systemowe z biblioteki C, takie jak printf, _exit, _kill, _read, _write itp. Użycie minimalnej implementacji tych wywołań może z łatwością dodać ponad 10 kilobajtów przestrzeni kodu. Być może nie jest to wielki problem dla wielu zespołów pracujących nad najnowocześniejszymi procesorami 32-bitowymi, ale dla reszty branży systemów wbudowanych może to oznaczać różnicę pomiędzy powodzeniem projektu a porażką. (Często ma miejsce sytuacja, gdzie tworząc koncept bazowy z kodu platformy, który mruga tylko diodą LED, stwierdza się, że kompiluje się do ponad 60 kilobajtów!)
Inni programiści zajmujący się optymalizacją nieraz pomijają pewne sztuczki wydajnościowe, które domyślnie nie działają w ich predefiniowanym systemie kompilacji. Na przykład, jeśli pracuję z częścią ze specjalną pamięcią RAM typu no-wait, można skonfigurować kod startowy, aby umieścić w niej wektory przerwań, aby uzyskać bardziej efektywne, deterministyczne zachowanie w czasie ich wykonywania. Niestety kod dostarczany przez dostawcę często tego nie robi. Jeśli nie zbudujemy lub nie zbadamy dokładnie swojego środowiska, marnujemy cykle zegara i prawdopodobnie wydłużamy period reakcji systemu na przerwanie.
Powód nr 3 — łatwiejsza integracja z procesami Agile i DevOps
Korzystanie z metodyk zwinnych (Agile) i ujęć DevOps to współcześnie niezbędny proces przy produkcji oprogramowania, który staje się również popularny w wielu zespołach zajmujących się aplikacjami wbudowanymi. Zwinne metodologie zyskujące uznanie w społeczności systemów wbudowanych dotyczą między innymi ujęcia takiego jak programowanie sterowane testami (TDD). DevOpsing obejmuje znacznie więcej niż tylko ciągłą integrację i wdrażanie (CI/CD), ale na tym skupia się większość zespołów, użytkujących te narzędzia.
Korzystając ze środowiska dostarczonego przez producenta mikrokontrolera, spożytkowanie procesów TDD czy CI/CD może być bardziej kłopotliwe i złożone. Dzieje się tak dlatego, że nie biorą one pod uwagę takich ujęć, które wiążą się z wykonaniem pewnych dodatkowych kroków, aby dostarczyć produkt zgodnie ze zwinną metodologią, tylko to, czego po prostu potrzeba, aby ich procesor zwyczajnie działał. Rezultatem może być środowisko kompilacji, które nie współgra dobrze z innymi procesami i potrzebami. Zespoły nierzadko zmagają się z obejściem tego problemu. A czasem nawet wykorzystują dwa różne środowiska, aby wszystkie te procesy i narzędzia dobrze do siebie pasowały.
Powód nr 4 — elastyczność
Niekiedy zdarza się, że całość, która już została zbudowana, była trudna do dostosowania do zmieniających się wymagań. Czasami w systemie kompilacji jest tak wiele małych haczyków, że usprawnienie go zajęłoby dwa razy więcej czasu niż zaczynanie od zera. Na przykład można chcieć wyłączyć bibliotekę, ale okazuje się, że powoduje to kilkadziesiąt błędów kompilacji, które zmuszają do rozwiązania sporej liczby zależności, co wymaga wielu godzin pracy.
Jednym z podejść, które wydaje się bardzo pomocne, jest wykorzystanie elastyczności IDE. Często można stwierdzić, że różni programiści mają odmienne preferencje co do spożytkowania IDE i edytorów tekstu, których chcą używać. Na przykład ktoś może polubić Sublime Text, druga osoba pisze w Visual Studio Code lub stawia na jeszcze inne IDE dostarczone przez dostawcę mikrokontrolera. Deweloperzy nieraz żartują i kłócą się, próbując uzyskać preferowane narzędzie jako wybór całego zespołu. Jeśli skonstruujemy swoje środowisko od podstaw, każdy może korzystać z cenionego przez siebie narzędzia, które może pomóc poprawić wydajność programistów.
Powód nr 5 — zbuduj dostosowanie systemu
Dla wielu deweloperów najważniejszym powodem przygotowywania własnego środowiska do kodowania C/C++ jest możliwość dokonywania adaptacji. Jak wspomniano wcześniej, nie ma nigdy dwóch takich samych projektów. Istnieją pewne podobieństwa między poszczególnymi, ale zawsze można radykalnie zoptymalizować rozmiar kodu i/lub jego wydajność, dostosowując system kompilacji. Czasami nie uda się od razu zrozumieć, jakie modyfikacje są potrzebne, dopóki nie zacznie się stawiać środowiska od zera. Wielu z nas proces taki może otworzyć oczy na zyski z danego przeobrażenia.
Istnieje wiele dostosowań do rozważenia, takich jak:
* Środowisko skonfigurowane z kontenerami Dockerowymi;
* Flagi dla assemblera;
* Flagi dla C/C++;
* Integracje wybranych bibliotek;
* Sposób obsługi kodu startowego mikrokontrolera;
* Integracja dedykowanej tabeli wektorów;
* Integracja z procesami TDD;
* Integracja z procesami ciągłej integracji czy ciągłego wdrożenia (CI/CD);
* Analiza kodu;
* Itd.
Możliwość dostosowania środowiska C/C++ i systemu kompilacji może znacząco wpłynąć na powodzenie projektu.
Podsumowanie
Tworzenie niestandardowego systemu do kompilacji dla aplikacji wbudowanej ma wiele zalet. Powyżej wymieniono kilka z nich, które, miejmy nadzieję, wzbudziły zainteresowanie czytających programistów systemów wbudowanych. Z początku podjęcie takiego przedsięwzięcia może wydawać się skomplikowane i obarczone potencjalnymi, własnymi problemami. Na szczęście proces ten jest znacznie mniej zawiły, niż mogłoby się wydawać. Niestandardowy system kompilacji można stworzyć i wdrożyć dla prawie każdego wbudowanego procesora w mniej niż tydzień. Co więcej, omawiana całość jest wysoce dedykowanym, dobrze zoptymalizowanym ujęciem, które może pomóc w przygotowaniu podstaw dla naszej aplikacji i zbudowaniu procesów mogących wspierać produkty przez lata.
Źródło: https://www.embedded.com/5-reasons-to-build-your-own-c-c-environment/
Fajne? Ranking DIY
