programowanie mikrokontrolera a programowanie obiektowe

11

Zrobiłem podstawowe programowanie obiektowe w C ++ (tworzenie B-drzewa, algorytmy mieszania, podwójnie połączone listy) i zrobiłem mały projekt w C (jak tworzenie kalkulatora naukowego itp.)

Czym różni się programowanie sprzętowe (szczególnie mikrokontrolerów) od programowania zorientowanego programowo / obiektowo pod względem sposobu myślenia i „myślenia”, które musi mieć programista?

Czy jeden jest zwykle uważany za trudniejszy od drugiego przez większość moich ludzi?

Czy na podstawie mojego doświadczenia (jak opisano powyżej) potrzebuję dużo przygotowania do programowania sprzętowego, czy mogę zanurzyć się bezpośrednio bez zbytniego przygotowania?

rrazd
źródło
4
Największą krzywą uczenia się będzie sposób prowadzenia określonego sprzętu w mikro. Będzie to wymagało godzinnego przesuwania arkusza danych. Niestety nie ma łatwego wyjścia.
drxzcl,
@rrazd, zauważyłem, że umieściłeś tag arduino. Czy to dlatego, że chcesz używać języka i bibliotek arduino? Czy będziesz pisać aplikacje osadzone w czystym C? Jeśli zamierzasz trzymać się środowiska arduino, jest całkiem bezpieczne i łatwe do zabawy, ponieważ wykonali pewne abstrakcje od sprzętu.
Jon L
@ Jon Planuję użyć tablicy Arduino na początek. Czy to nie jest podobne do języka C? Myślałem, że wiąże się to z tymi samymi podstawowymi pojęciami ...
rrazd
1
Zastanawiam się, czy masz na myśli to, co wiele osób nazwałoby „programowaniem we / wy”, czy też spodziewasz się ponownego uporządkowania sprzętu za pomocą kodu. Arduino jest zdecydowanie pierwszym; ta ostatnia byłaby domeną FPGA.
JustJeff,
1
@rrazd - Zmieniłem tytuł; „programowanie sprzętowe” brzmi zbyt podobnie do HDL (Hardware Description Language), np. VHDL i Verilog, które są używane do programowania układów FPGA i CPLD.
stevenvh,

Odpowiedzi:

10

Będziesz musiał całkowicie porzucić paradygmat zorientowany obiektowo, mając do czynienia z większością mikrokontrolerów.

Mikrokontrolery są generalnie ograniczone do rejestrów i pamięci RAM, z niską częstotliwością taktowania i brakiem potokowania / równoległych ścieżek kodu. Możesz na przykład zapomnieć o Javie na PIC.

Musisz wejść w sposób myślenia w asemblerze i pisać proceduralnie.

Musisz zachować względnie płaski kod i unikać rekurencji, ponieważ ograniczenia pamięci RAM mogą często prowadzić do problemów ze stosem.

Musisz nauczyć się pisać skuteczne procedury obsługi przerwań (zwykle w języku asemblera).

Konieczne może być ręczne przeredagowanie części kodu, w języku asemblera, w celu zaimplementowania funkcji, których kompilator nie obsługuje (lub źle obsługuje).

Musisz napisać kod matematyczny, który uwzględnia rozmiar słowa i brak możliwości FPU większości mikrokontrolerów (tj. 32-bitowe mnożenie na 8-bitowej mikro = zło).

To inny świat. Dla mnie posiadanie wykształcenia informatycznego lub profesjonalnego programowania może być tak samo przeszkodą, jak brak jakiejkolwiek wiedzy w kontaktach z mikrokontrolerami.

Adam Lawrence
źródło
1
Nie musisz całkowicie rezygnować z paradygmatu zorientowanego obiektowo, ale na mniejszych mikrach może być konieczne porzucenie implementacji obiektów o dużej masie i naprawdę pomyśl o tym, jaki jest najlepszy sposób rozwiązania każdego problemu. Często jest to proceduralne, ale lekkie obiekty, dobrze zaimplementowane (zwykle ręcznie), mogą czasami zmniejszać rozmiar skomplikowanych projektów mikrokontrolerów.
Chris Stratton
6
Wszystko to jest prawdą, z wyjątkiem porzucenia orientacji obiektowej. Prawdopodobnie nie będziesz używać języka z funkcjami OO, ale to nie wyklucza orientacji obiektowej. W przypadku mikrokontrolerów będziesz pisać sterowniki dla wszystkich urządzeń peryferyjnych (ADC, kontrolery magistrali szeregowej, PWM itp.). Taki sterownik powinien zawsze być napisany w sposób obiektowy, aby był 1) autonomiczny i nie wiedział / nie dbał o resztę programu oraz 2) implementował prywatną enkapsulację, aby reszta programu nie mogła wejdź i baw się z nim. Jest to możliwe w 100% w języku C i nie wpływa na wydajność.
Lundin
1
Zdecydowanie nie zgadzam się z pierwszym zdaniem, wszystkie moje projekty mikrokontrolerów zostały zbudowane w C ++ i zorientowanym obiektowo, a używane mikroskopy nie były bardzo duże (32 kB pamięci ROM), również obiektowy program ładujący miał mniej niż 2 kB, ja tak naprawdę nie widzę ograniczeń. Nie można robić szalonych rzeczy, ale projekt może być zorientowany obiektowo, nie ma problemu.
Arsenał
@Arsenal Uwaga Powiedziałem „większość” i zauważ, że komentujesz czteroletni wątek. :)
Adam Lawrence
Całkowicie nie zgadzam się z pierwszym i ostatnim zdaniem. A także asembler jest używany bardzo rzadko i, głównie, tylko dla 8-bitowych MCU (wystarczy sprawdzić to forum, ile postów z kodem asemblera można znaleźć?). Na pewno możesz i (IMHO) powinieneś pisać w stylu OO dla 32-bitowych MCU
Andrejs Gasilovs
10

Musisz pomyśleć o kilku rzeczach:

  • Użyjesz C jako języka
  • Nadal możesz stworzyć wrażenie orientacji obiektu za pomocą wskaźników funkcji, dzięki czemu możesz zastąpić funkcje itp. Użyłem tej metody w przeszłości i bieżących projektach i działa bardzo dobrze. Więc OO jest częściowo dostępne, ale nie w sensie C ++.

Pojawią się inne ograniczenia, takie jak ograniczona prędkość i pamięć. Tak więc, ogólnie rzecz biorąc, unikam:

  • Używając sterty, jeśli istnieje sposób na rozwiązanie problemu bez Malloc, robię to. Na przykład wstępnie przydzielam bufory i po prostu ich używam.
  • Celowo zmniejszam rozmiar stosu w ustawieniach kompilatora, aby wcześnie stawić czoła problemom z rozmiarem stosu, ostrożnie go optymalizuję.
  • Zakładam, że każda linia kodu zostanie przerwana przez zdarzenie, więc unikam kodu, który nie jest ponownie wysyłany
  • Zakładam, że nawet przerwania są zagnieżdżone, więc odpowiednio piszę ten kod
  • Unikam używania systemu operacyjnego, chyba że jest to konieczne. 70% osadzonych projektów tak naprawdę nie potrzebuje systemu operacyjnego. Jeśli muszę używać systemu operacyjnego, używam tylko czegoś z dostępnym kodem źródłowym. (Freertos itp.)
  • jeśli używam systemu operacyjnego, prawie zawsze abstrakcyjne rzeczy, dzięki czemu mogę zmienić system operacyjny w ciągu kilku godzin.
  • W przypadku sterowników itp. Będę korzystać tylko z bibliotek dostarczonych przez dostawcę, nigdy nie będę bezpośrednio manipulował bitami, chyba że nie mam innego wyjścia. Dzięki temu kod jest czytelny i usprawnia debugowanie.
  • Patrzę na pętle i inne rzeczy, szczególnie w ISR, aby upewnić się, że są wystarczająco szybkie.
  • Zawsze mam pod ręką kilka GPIO do pomiaru rzeczy, przełączania kontekstu, czasu działania ISR itp.

Lista jest długa, prawdopodobnie jestem poniżej średniej pod względem oprogramowania, jestem pewien, że istnieją lepsze praktyki.

Szczery
źródło
3
+1 za „możesz użyć paradygmatów OO, jeśli chcesz”. To, co musisz sprawdzić przy drzwiach, nie jest projektem OO. OOD to tylko filozofia, która zachęca do trzymania powiązanego kodu i danych razem. To, co musisz zostawić, to sposób, w jaki OO jest implementowany w systemach korporacyjnych, z wieloma warstwami abstrakcji, odwróceniem kontroli i całym tym jazzem. Zadaniem twojego oprogramowania układowego jest sterowanie sprzętem, to wszystko.
drxzcl
7

Robię oba, więc oto mój pogląd.

Myślę, że najważniejszą umiejętnością w osadzaniu jest umiejętność debugowania. Wymagany sposób myślenia różni się znacznie, ponieważ o wiele więcej może pójść nie tak i musisz być bardzo otwarty na rozważenie wszystkich różnych sposobów, w jakie to, co próbujesz zrobić, może się nie udać.

Jest to największy problem dla nowych programistów wbudowanych. Ludzie na PC mają gorzej, ponieważ są przyzwyczajeni do pracy dla nich. Zamiast tego będą marnować dużo czasu na szukanie narzędzi do robienia dla nich rzeczy (wskazówka: nie ma ich wiele). Wciąż wiele razy walić głowami w ściany, nie wiedząc, co jeszcze zrobić. Jeśli czujesz, że utkniesz, cofnij się i dowiedz się, czy potrafisz ustalić, co może być nie tak. Systematycznie przechodź przez zawężanie listy potencjalnych problemów, dopóki jej nie znajdziesz. Bezpośrednio z tego procesu wynika, że ​​należy ograniczyć zakres problemów, nie zmieniając zbyt wiele na raz.

Doświadczeni osadzeni ludzie biorą debugowanie za pewnik ... większość ludzi, którzy nie potrafią tego dobrze zrobić, nie trwa długo (lub pracuje w dużych firmach, które akceptują „oprogramowanie układowe jest trudne” jako odpowiedź na pytanie, dlaczego określona funkcja spóźnia się lat)

Pracujesz nad kodem, który działa w systemie zewnętrznym na twoim systemie programistycznym, z różnym stopniem widoczności twojego celu pomiędzy platformami. Jeśli masz kontrolę, poproś o pomoc rozwojową, aby zwiększyć widoczność swojego systemu docelowego. Używaj debugowanych portów szeregowych, wyjściowego debugowania bitów, słynnego migającego światła itp. Z pewnością przynajmniej naucz się obsługi oscyloskopu i używaj pinowego wejścia / wyjścia z „zakresem”, aby zobaczyć, kiedy niektóre funkcje wchodzą / wychodzą, uruchamiają się ISR itp. Widziałem ludzi walczących przez dosłownie lata dłużej niż to konieczne po prostu dlatego, że nigdy nie zadali sobie trudu, aby skonfigurować / nauczyć się, jak korzystać z odpowiedniego łącza debugującego JTAG.

O wiele ważniejsze jest, aby dokładnie wiedzieć, jakie zasoby masz w stosunku do komputera. Przeczytaj uważnie karty danych. Weź pod uwagę „koszt” zasobów wszystkiego, co próbujesz zrobić. Poznaj zorientowane na zasoby sztuczki debugowania, takie jak wypełnianie miejsca stosu magiczną wartością, aby śledzić użycie stosu.

Chociaż zarówno komputer, jak i oprogramowanie wbudowane wymagają pewnych umiejętności debugowania, jest o wiele ważniejsze w przypadku oprogramowania wbudowanego.

darron
źródło
5

Zakładam, że twoje doświadczenie w C ++ jest oparte na PC.

Często popełnianym błędem przez programistów przechodzących z komputera na mikrokontroler jest to, że nie zdają sobie sprawy z tego, jak ograniczone mogą być zasoby . Na komputerze nikt Cię nie zatrzyma, gdy utworzysz tabelę ze 100 000 wpisów lub napiszesz program, który kompiluje się do 1 MB kodu maszynowego.
Tam mikrokontrolery, które mają bogactwo zasobów pamięciowych, zwłaszcza w wysokiej klasy, ale to wciąż dalekie od tego, co będziesz kiedyś. W przypadku projektu hobbystycznego prawdopodobnie zawsze możesz osiągnąć maksimum, ale w profesjonalnym projekcie często będziesz zmuszony pracować z mniejszym urządzeniem, ponieważ jest tańsze .
Przy jednym projekcie pracowałem z TI MSP430F1101. 1 KB pamięci programu, 128 bajtów konfiguracji Flash, 128 bajtów pamięci RAM. Program nie pasował do 1K, więc musiałem napisać funkcję 23 bajtów w konfiguracji Flash. Za pomocą tych małych kontrolerów obliczasz według bajtów . Innym razem pamięć programu była o 4 bajty za mała. Szef nie pozwoliłby mi użyć kontrolera z większą pamięcią, ale zamiast tego musiałem zoptymalizować już zoptymalizowany kod maszynowy (został już napisany w asemblerze), aby zmieścił dodatkowe 4 bajty. Dostajesz obraz.

W zależności od platformy, nad którą pracujesz, będziesz musiał radzić sobie z bardzo niskim poziomem We / Wy . Niektóre środowiska programistyczne mają funkcje do zapisywania na wyświetlaczu LCD, ale na innych działasz samodzielnie i będziesz musiał przeczytać arkusz danych LCD od początku do końca, aby wiedzieć, jak nim sterować.
Może być konieczne sterowanie przekaźnikiem, co jest łatwiejsze niż wyświetlacz LCD, ale będzie wymagało przejścia do poziomu rejestru mikrokontrolera. Ponownie arkusz danych lub instrukcja obsługi. Musisz ponownie poznać strukturę mikrokontrolera, którą znajdziesz na schemacie blokowym, ponownie w arkuszu danych. W czasach mikroprocesora rozmawialiśmy o modelu programowania, który był w zasadzie zestawieniem rejestrów procesora. Dzisiejsze mikrokontrolery są tak złożone, że opis wszystkich rejestrów może stanowić najlepszą część 100-stronicowego arkusza danych. IIRC sam opis modułu zegara dla MSP430 miał 25 stron.

μ

Układy są często w języku C . C ++ jest raczej wymagający zasobów, więc zwykle nie ma go. (Większość implementacji C ++ dla mikrokontrolerów oferuje ograniczony podzbiór C ++.) Jak powiedziałem, w zależności od platformy możesz mieć dostęp do obszernej biblioteki funkcji, która może zaoszczędzić sporo czasu na rozwijanie. Warto poświęcić trochę czasu na przestudiowanie go, może Ci zaoszczędzić dużo czasu, jeśli wiesz, co jest dostępne.

stevenvh
źródło
Pisałem gry dla Atari 2600, która jest raczej ograniczoną platformą; moja pierwsza opublikowana gra była zasadniczo kodem 4K (ponieważ miałem wózek 32K, dodałem kilka dodatków, ale wersja 4K była w pełni grywalna); Pamięć RAM ma 128 bajtów. Ciekawe jest, że w roku, w którym napisałem tę grę (2005 r.), Wydano inne gry, które były dosłownie milion razy większe.
supercat
@ superupat - Tak, ale tego można było się spodziewać, w 2005 roku Atari 2600 miał już 200 lat! Nigdy nie grałem w gry akcji, takie jak FPS, ale kiedy patrzę na to, co jest potrzebne do grania, procesor graficzny o wiele mocniejszy niż twój procesor, zarówno programowo, jak i elektrycznie, nie mogę powstrzymać się od potrząsnięcia głową :-). Grałem w szachy (Sargon) na 16k TRS-80 IIRC. Flight Simulator mojego brata nie potrzebował więcej.
stevenvh
Niecałe 200 lat. Zadebiutował w 1977 roku, więc nie było nawet 30 lat. Chociaż zgadzam się, że to było eony temu pod względem technologicznym, nadal jestem zdumiony faktem, że nie jest to tylko wzrost o 100-krotności, ani wzrost tysiąc-krotny , ale MILION-krotny wzrost zarówno pamięci RAM, jak i rozmiaru kodu. Prędkość nie uzyskała aż tak dużego przyspieszenia, ponieważ 2600 wynosił 1,19 MHz, a nowsze systemy są tylko w zakresie niskich częstotliwości. Mogą zrobić znacznie więcej na cykl niż 2600 (co może - i musiało - wygenerować 1/76 linii wideo w każdym cyklu), ale nie sądzę, że są one 1 000 000 razy szybsze.
supercat
3

„programowanie sprzętowe” może oznaczać wiele rzeczy. Programowanie bardzo małego układu (pomyśl 10F200, 512 instrukcji, kilka bajtów pamięci RAM) może przypominać projektowanie obwodu elektronicznego. Z drugiej strony programowanie dużego mikrokontrolera Cortex (1 Mb FLASH, 64 kB RAM) może przypominać programowanie PC / GUI przy użyciu dużego zestawu narzędzi GUI. IMHO dobry programista osadzony / działający w czasie rzeczywistym potrzebuje umiejętności zarówno od strony oprogramowania, jak i od strony projektowania obwodu. Dla większych uC C ++ jest dobrym wyborem językowym, dla bardzo małych C może być jedynym wyborem. Znajomość asemby może się przydać, ale nie polecałbym wykonywania poważnych projektów w całości w asemblerze.

Wykonałem poważną pracę osadzoną z ludźmi z obu stron (SWI i EE). Generalnie wolę ludzi SWI, pod warunkiem, że mają pewne doświadczenie w programowaniu wielowątkowym.

Twoje pytanie brzmi, jakbyś chciał zanurzyć się w programowanie wbudowane. Jak najbardziej, zrób to. W przypadku aspektów niskiego poziomu (połączenie urządzeń peryferyjnych w układzie i otaczającego go sprzętu) musisz nauczyć się nowych umiejętności, ale jest to po prostu dużo pracy bez wielu nowych koncepcji. W przypadku wyższych warstw projektów możesz czerpać z istniejącego knwoledge.

Wouter van Ooijen
źródło
1

Dla każdej metody biblioteki arduino, którą wywołujesz, jest bogactwo kodu C / C ++, który to umożliwia, jest po prostu ładnie zapakowany do użycia jako API. Spójrz na kod źródłowy arduino w katalogu hardware / arduino / *, a zobaczysz wszystkie napisane dla ciebie C / C ++, które współdziałają bezpośrednio z rejestrami mikrokontrolera AVR. Jeśli Twoim celem jest nauczenie się pisania takich rzeczy (bezpośrednio na sprzęcie), jest wiele do omówienia. Jeśli Twoim celem jest uzyskanie czegoś do pracy przy użyciu ich bibliotek, może nie być wiele do powiedzenia, ponieważ większość ciężkiej pracy jest dla ciebie wykonana, a ich biblioteki i środowisko programistyczne są bardzo łatwe w użyciu.

Niektóre praktyczne zasady dotyczące pracy z urządzeniami o ograniczonych zasobach, które mogą mieć zastosowanie do środowiska arduino lub innych:

Pamiętaj, ile pamięci używasz. Zarówno rozmiar kodu (który idzie do pamięci flash), jak i statyczne użycie pamięci RAM (stałe w kodzie, które zawsze będą istnieć w pamięci RAM). Twierdziłbym, że użycie statycznej pamięci RAM jest nieco ważniejsze na początku, ponieważ łatwo jest go przeoczyć. Często zdarza się, że masz tylko 1000 bajtów do pracy ze stosem, stertą i stałymi. Bądź rozsądny w sposobie wydawania, więc unikaj takich rzeczy, jak długie tablice liczb całkowitych (4 bajty każdy), gdy wystarczą bajty lub znak bez znaku (1 bajt). Inna odpowiedź tutaj bardzo dobrze obejmuje kilka innych ważnych kwestii, więc zatrzymam się tutaj, chciałem przede wszystkim wyjaśnić, że jest wiele do omówienia, jeśli nie używasz biblioteki arduino i nie piszesz własnych bibliotek C.

Jon L.
źródło
0

Jeśli chodzi o mikrokontroler kontra programowanie OOP, nie są one przeciwieństwem. Prawdą jest, że wszystkie biblioteki dostawców znajdują się w zwykłym C, ale wszystkie platformy obsługują również OOP C ++. Poza tym programiści mogą budować i tworzyć biblioteki wysokiego poziomu C ++ i oprogramowanie układowe urządzeń. Dobrym przykładem są biblioteki Arduino, oficjalne i zbudowane przez użytkownika - głównie klasy C ++. Być może nie wszystkie zalety OOP mogą być w pełni wykorzystane w środowisku osadzonym, ale obowiązują tu również dobrze znane zalety C ++ vs. C.

Jeśli chodzi o sposób myślenia i myślenia, jak zauważono w innych odpowiedziach, mikrokontrolery są platformami o bardzo ograniczonych zasobach (szczególnie w pamięci RAM, mniejszej prędkości) - takie rzeczy jak dynamiczna alokacja pamięci, wyjątki C ++ są zwykle wykluczane. Biorąc pod uwagę dobór odpowiedniego sprzętu, łatwo jest dostosować się do tych ograniczeń i zastosować inne techniki (również szeroko stosowane na innych platformach).

Moim zdaniem trudniejszym wyzwaniem może być jeszcze jeden dodatkowy wymiar znaleziony w programowaniu wbudowanym - synchronizacja. Wynika to z faktu, że zwykle oprogramowanie wbudowane zajmuje się często zdarzeniami w czasie rzeczywistym, ściśle kontrolowanymi protokołami do sterowania urządzeniami peryferyjnymi i samym zadaniem ogólnym (są to również paralele na innych platformach „wysokiego poziomu”, takich jak aplikacje wielowątkowe).

Przygotowując się do zapoznania się z nowym sprzętem, przygotuj się na wiele arkuszy danych - myślę, że może to być związane z częścią pytań „sposobu myślenia” :) Z pewnością potrzebna byłaby wiedza na temat sprzętu komputerowego i sprzętu.

Chciałbym również zauważyć, że w dzisiejszych czasach tworzenie oprogramowania wbudowanego nie wymaga języka asemblera. W rzeczywistości Java (BTW to domyślnie OOP) jest już dostępna i staje się silniejsza (przynajmniej dla niektórych klas urządzeń wbudowanych, na przykład urządzeń IoT, może mieć bardzo świetlaną przyszłość).

Flanker
źródło
Jeśli chodzi o obawy, osoby wokół dynamicznego (ponownego) przydzielania pamięci są zwykle większą przeszkodą dla tradycyjnego OO niż synchronizacja .
Chris Stratton,
Może masz rację. Ale są ludzie, którzy zaprogramowali w latach 80-90 na oprogramowanie trybu rzeczywistego MSDOS, z dostępną pamięcią RAM 64K (segment pamięci danych) i dla nich było to „naturalne”. Być może MSDOS PC był bardziej „osadzony” w środowisko niż dzisiejszy STM32F4 :)
Flanker
STM32F4 zazwyczaj ma więcej pamięci programowej w postaci flasha, ale komputer zwykle zawiera znacznie więcej pamięci RAM do przechowywania zmiennych obiektów wykonawczych. Podczas gdy cała daleko idąca wskazówka wymuszona przez segmentowane adresowanie była uciążliwa, obaj nie mają prawdziwej MMU, a to będzie jeszcze bardziej niepokojące w systemie z mniejszą pamięcią RAM, którym jest STM32F4. Również czasy przestoju komputera były zwykle krótsze, a akceptowalne wskaźniki awarii wyższe.
Chris Stratton,