Jak tworzysz duże projekty osadzone? [Zamknięte]

21

Tło :

Młodszy inżynier elektroniki R&D ( jedyny EE w firmie ) - sprzęt i kodowanie to nie problem. Moim największym problemem jest uzyskanie właściwego przeglądu projektu i od czego zacząć.

Do tej pory wykonałem tylko niewielkie projekty oprogramowania (poniżej 500 linii kodu), ale nie mogę sobie wyobrazić, że będę robił większe projekty bez utraty widoku funkcjonalności lub braku funkcjonalności.

Jak najlepiej ułożyć strukturę / jakich narzędzi używasz do struktury dużych systemów oprogramowania wbudowanego?

Co aktualnie robię :

Zazwyczaj zaczynam od szkicowania funkcjonalności projektu. Może to być jeden do wielu warstwowych schematów blokowych lub powiązanych diagramów (schematy blokowe itp.) I przeprowadzanie pewnych badań komponentów / układów. Potem wskakuję prosto do kodowania (chyba szybko się nie udaje), odnosząc się do kart danych / Internetu, kodując jedną funkcję na raz i testując ją za pomocą fałszywych danych lub podobnego testu. Może to być zapis danych do układu MEM, a jeśli to zadziała, może to być sterownik SPI między układem głównym a układem MEM.

Jakiej odpowiedzi szukam :

Coś naprawdę. Rozwiążę to, co uważam za rozsądne. Może to być książka, artykuł, osobiste doświadczenie, rekomendacje itp.

Jestem bardzo zainteresowany wiedzą, jak radzą sobie z tym seniorzy.


Edytować

Po pierwsze, dziękuję za podzielenie się latami! Wszystkie odpowiedzi są mile widziane. Moje zdanie z tego jest;

  • Utwórz jasny i precyzyjny dokument specyfikacji.
  • Utwórz dokument projektu oprogramowania. (Coś, co teraz dodam) Projektowanie szablonów dokumentów
  • Pomyśl w modułach, jak może się to wydawać zbędne. (Coś, na czym muszę się bardziej skoncentrować)
  • Postępuj zgodnie ze standardem kodowania przy tworzeniu plików nagłówkowych / źródłowych. (Nigdy tego nie robił) Barr Group C standard
  • Najpierw skup się na tworzeniu implementacji niskiego poziomu. (Komunikacja itp.)
  • Wdrażaj wzorce projektowe tam, gdzie to możliwe / rozsądne. Wzorce projektowe
  • Skonfiguruj coś do kontroli wersji (Github itp. - nigdy tak często nie korzystałem)
  • Badanie ciągłej integracji / ciągłego wdrażania (coś nowego, na co natknąłem się) Podstawy CI i CD
Sorenp
źródło
4
To pytanie nie należy tutaj ... Może być na softwareengineering.stackexchange.com
Swanand
11
Może to pytanie należy tutaj. Dziesiątki lat temu uhonorowałem zespół projektantów składający się z wielu układów i śledziliśmy postępy, rozkładając każdy z układów na różne funkcje, a następnie szacując tygodnie potrzebne (zespołowi początkujących, zmotywowanych, ale początkujących) na zrozumienie / projektowanie / testowanie / przegląd każdej z ponad 60 funkcji. Mimo że nie dotrzymaliśmy pierwotnego harmonogramu nałożonego przez kierownictwo, zarządzanie było cierpliwe, ponieważ mogli z łatwością śledzić postęp dzięki ponad 60 funkcjom, o których wiedzieliśmy, że musimy zaprojektować, a następnie zintegrować.
analogsystemsrf
13
@Swanand Nie zgadzam się. Często zadawane pytania na ten temat brzmią „[pytania o ...] pisanie oprogramowania układowego dla aplikacji bez systemu operacyjnego lub RTOS” - powiedziałbym, że zdecydowanie obejmuje to także fazę planowania. Pytanie dotyczy w szczególności „dużych systemów wbudowanych”.
Araho
2
Chociaż programowanie oprogramowania układowego jest tutaj tematem, dobrym sposobem, aby sprawdzić, czy pytanie jest zbyt szerokie i oparte na opiniach, jest liczba odpowiedzi w krótkim okresie czasu. To zdecydowanie za szerokie. W sekcji pomocy jest coś w stylu „jeśli można napisać książkę…” i napisano o tym książki!
rura
2
OP stworzył dobre podsumowanie. Chciałbym tylko podkreślić, że GitHub nie jest jedynym sposobem na uruchomienie repozytorium Git. Możesz to zrobić lokalnie, z uruchomionym specjalnym serwerem Git lub bez niego. Git nie jest jedyną formą Systemu Kontroli Źródła (SCS) / Systemu Kontroli Wersji (VCS), ale obecnie jest bardzo popularny. Kiedy zaczynałem jako EE z dużą ilością szkoleń C i C ++, miałem zerową ekspozycję na takie rzeczy.
TafT

Odpowiedzi:

23

Istnieje kilka aspektów wpływających na stopień szczegółowości struktury potrzeb projektu. Dla mnie jednym z głównych czynników jest to, czy jestem jedynym kodującym (co wydaje się być w twoim przypadku, gdy piszesz, że jesteś jedynym EE), czy też są zaangażowani inni. Następnie pojawia się pytanie, co tak naprawdę oznacza „duże”. Zazwyczaj proces projektowania dzielę na następujące kroki:

Definicja wymagań Jeśli uzyskasz odpowiednią specyfikację oprogramowania do pracy z dużą ilością planowania, to już zostało zrobione. Jeśli po prostu otrzymujesz niejasne wymagania, pierwszą rzeczą, którą musisz zrobić, jest ustalenie, czego tak naprawdę chce klient (czasem tak naprawdę nie wiedzą). Wiem, że to kuszące, aby przejść od razu do kodowania, ale wiąże się to z ryzykiem pominięcia ważnej funkcji, która może nie była oczywista w pierwszej kolejności i nie może być łatwo wciśnięta w Twój kod gdzieś w trakcie programowania.

Granice systemu i łatwość konserwacji W systemach wbudowanych często masz pewne interfejsy systemowe, niektóre na zewnątrz (operator), ale także wewnątrz. Zdefiniuj je dobrze i staraj się utrzymywać zależności na jak najniższym poziomie, co uprości ciągłą inżynierię i łatwość konserwacji. Również komentarz / kod dokumentu w razie potrzeby, nigdy nie wiadomo, kto jeszcze będzie musiał z nim pracować, z przyjemnością nie będzie musiał kopać kilkunastu warstw kodu, zanim faktycznie dowie się, co robi funkcja.

Zdefiniuj weryfikowalne zadania Zwłaszcza jeśli inni programiści pracują na tej samej podstawie kodu, nieuniknione jest zdefiniowanie przejrzystych zadań (funkcji) i wymaganych interfejsów między nimi. O ile to możliwe, poszczególne funkcje powinny być testowane / weryfikowane niezależnie od innych, właśnie tam potrzebujesz dobrze zdefiniowanych interfejsów, aby móc zdefiniować przypadki testowe.

Jedna funkcja po drugiej Ludzie lubią postęp, więc jeśli masz różne zadania, zwykle pracują nad tym, co obiecuje największy postęp. Zwykle staram się zakończyć zadanie i doprowadzić je do zweryfikowanego i przetestowanego stanu, zanim zacznę od następnego. Dzięki temu Twój kod może być testowany przez innych i nie zapominasz o czymś.

Kontrola wersji W trakcie realizacji projektu czasami potrzebujesz starszych wersji, na przykład w celu zidentyfikowania błędu wprowadzonego w nowej wersji lub po prostu zbudowania urządzenia, które zachowuje się dokładnie tak samo, jak ten, który został dostarczony 3 lata temu. Upewnij się, że masz w kodzie jasne wersje kompilacji i tagi. Git jest tu zdecydowanie twoim przyjacielem.

Papież
źródło
3
Zwłaszcza wymagania! Nie ma to jak budowanie produktu lub funkcji, która robi coś złego.
ConcernedHobbit
13

Humpawumpa napisał świetną odpowiedź ! Chcę tylko uzupełnić niektóre z jego uwag, ale ponieważ jest to zbyt długo, aby być komentarzem, napiszę osobną odpowiedź.

Kiedyś byłem na pozycji OP - nie tylko EE, ale jedyne EE, które dokonało jakiegokolwiek rozwoju MCU w małej firmie.

Nie mogę podkreślić znaczenia modułowości , nawet jeśli jesteś jedynym programistą. To jedyny sposób na zachowanie rozsądku w miarę rozwoju projektu. Musisz być surowy w pisaniu modułów obsługujących tylko jedną koncepcję funkcjonalną, a ich interfejsy zewnętrzne powinny być jak najmniejsze. Moduły wysokiego poziomu będą odpowiadały wymaganiom funkcjonalnym, podczas gdy moduły niskiego poziomu będą ściśle powiązane z zasobami sprzętowymi (tj. Sterownikami urządzeń).

Spędziłem dużo czasu na utrzymaniu szczegółowego schematu przepływu danych 1 , który dokładnie pokazuje, w jaki sposób różne moduły współużytkują informacje. Niektóre funkcje będą miały bardzo różne wymagania pod względem wydajności w czasie rzeczywistym; upewnij się, że wiesz, jak na to wpływa udostępnianie informacji. Na diagramie narysowano granice, które oddzielały nieprzerwany kod od różnych domen sterowanych przerwaniami.


1 Bardzo różni się od schematu blokowego, który koncentruje się na przepływie kontrolnym .

Dave Tweed
źródło
12

W przypadku każdego dużego projektu planuję to tak, jakby zaangażowanych było wielu programistów, nawet jeśli zamierzam zrobić to wszystko sam.

Powody są proste:

1 złożoność. Duży projekt zawsze wiąże się ze złożonością. Zaplanowanie projektu tak, jakby było w nim zaangażowanych wiele zespołów oznacza, że ​​złożoność została wzięta pod uwagę i udokumentowana . Liczba przypadków, w których widziałem problemy dużych projektów, jest wysoka i zwykle dlatego, że coś „prześlizgnęło się przez pęknięcia”. Nie zapominaj, że należy również wziąć pod uwagę montaż mechaniczny, a nie tylko wielkość pudełka - czy będzie potrzeba radiatorów? Czy pudełko musi być uziemione dla bezpieczeństwa? Tylko w tej kategorii jest wiele pytań.

2 Wymagania. Zakładając, że zaangażowanych jest wiele osób, oznacza to, że wymagania najwyższego poziomu (które często kwestionuję, ponieważ mogą powodować niepotrzebną złożoność i koszty) muszą zostać podzielone na różne mniejsze wymagane i możliwe do wykonania zadania (które mogłyby być przekazane innemu zespołowi w większej organizacji ) zamiast patrzeć tylko na jedną kroplę.

3 Partycjonowanie. Istnieją dwa podstawowe typy partycjonowania; funkcjonalność sprzętu i sprzęt / oprogramowanie. Pierwszy typ polega na określeniu, jakie oddzielne (ale komunikujące się) bloki funkcjonalne muszą być obecne. Drugi to kompromis prostszego (czasem) sprzętu i oprogramowania, ale pamiętaj, że przeniesienie większej liczby rzeczy do oprogramowania niekoniecznie rozwiąże problem sprzętowy. Przejście na więcej oprogramowania może w niektórych przypadkach znacznie zwiększyć złożoność sprzętu (więcej mocy obliczeniowej, bardziej złożone interfejsy i więcej).

4 interfejsy. Proces partycjonowania pomoże zdefiniować interfejsy wewnętrzne; interfejsy zewnętrzne są zwykle częścią ogólnych wymagań (choć nie zawsze). Istnieje wiele sposobów współpracy różnych części systemu, które mogą być złożonym protokołem komunikacyjnym lub po prostu dobrym / złym sygnałem.

5 Weryfikacja. Jest to połączenie testów niskiego poziomu (sprzętu i sterowników) i poziomu systemu. Wykonanie projektu w dobrze zdefiniowanych blokach pozwala na solidną weryfikację (która może być przeprowadzona przez analizę lub rzeczywisty test i jest zwykle mieszanką tych dwóch; aktualizacje projektów mogą wykorzystywać argumenty podobieństwa).

6 standardów. Używam standardów kodowania i rysowania, jakby to był większy zespół. Używam standardów kodowania grupy Barr, ponieważ nie są one zbyt uciążliwe, ale zapobiegają wielu klasom błędów w kodzie. W przypadku dokumentacji wyjściowej PCB stosuję się do IPC-D-326 (która wywołuje IPC-D-325), ponieważ jest to sprawdzona metoda komunikowania moich zamiarów producentom i asemblerom PCB. Może się to wydawać dziwne, ale dyscyplina zgodna z szeregiem standardów oznacza, że ​​jakość jest stała.

7 Kontrola wersji. Używam kontroli wersji dla wszystkich części projektu (system, sprzęt, oprogramowanie. Mechanika, wymagania testowe - wszystko). Narzędzia CAD, których używam, obsługują takie przechowywanie wersji, podobnie jak całe oprogramowanie i narzędzia do budowania FPGA.

Pracowałem nad wieloma osadzonymi projektami (podobnie jak wielu doświadczonych ludzi tutaj), a rozmiary zespołów różniły się od 1 (ja) do kilkudziesięciu (lub setek w określonym zestawie projektów) rozłożonych na wiele dyscyplin, a czasem inne geograficznie odległe strony. Zastosowanie tego samego nadrzędnego podejścia (które znane jest z pracy) oznacza, że ​​mogę podjąć określone zadanie we względnej izolacji, ukończyć je i dokładnie przetestować jako samodzielną część większego projektu. Oznacza to również, że mogę od czasu do czasu załatwić pewne sprawy, jeśli to konieczne.

Wykonanie tych wszystkich czynności wymaga nieco czasu z góry, ale ostatecznie jest szybszą drogą dla złożonych systemów osadzonych.

Peter Smith
źródło
5

Inne odpowiedzi dają wiele świetnych wskazówek. Oto dwa, które uznałem za najważniejsze w mojej karierze programistycznej:

  1. Zrób jak najwięcej kodu w oddzielne, dobrze zdefiniowane moduły, jak to możliwe.
  2. Spraw, by moduły były automatycznie testowane na PC.

Właśnie tego potrzebujesz do tworzenia stylu „ciągłej integracji” w systemach wbudowanych. Zawsze będzie pewna ilość kodu, który jest zbyt ściśle powiązany ze sprzętem do automatycznego testowania, ale spróbuj go zminimalizować. Możesz dotrzeć dość daleko, używając danych symulowanych lub przechwytywania danych z rzeczywistego sprzętu, które następnie podajesz do systemu testowego.

jpa
źródło
4

Aby dodać do istniejących odpowiedzi ...

Zawsze zaczynam od podstaw. Z projektu sprzętu wiesz, jakie jest Twoje We / Wy. Zacznij od zbudowania modułów sterowników, które zawierają w sobie dane we / wy, aby Twój kod wysokiego poziomu nie musiał wiedzieć zbyt wiele o rzeczach niskiego poziomu.

Kiedy budujesz interfejsy niskiego poziomu, oczywiście potrzebujesz uprzęży testowej. Jeśli zaprojektujesz to, aby od samego początku podłączało się do komputera (być może z portem RS-232, być może USB, być może telnet przez Ethernet), możesz zachować interfejs testowej wiązki przewodów podczas tworzenia aplikacji. Możesz dodawać kolejne zaczepy uprzęży testowych, gdy aplikacja nabierze kształtu, co pozwoli ci testować kod regresji w miarę upływu czasu.

Graham
źródło
4

Mam tendencję do myślenia w czterech pytaniach. Pierwsze dwa należą do początku projektu systemowego, dwa następne pod koniec.

  1. Czy oni naprawdę chcą systemu? Czy system rozwiąże problem klientów w akceptowanej skali czasu i kosztów? Częstym problemem jest budowanie systemów, z których klient nie będzie korzystał.

  2. Czy rzeczywiście możemy zbudować ten system? Czy możliwe będzie zapewnienie niezbędnej wydajności, precyzji, zużycia energii, ...?


Tworzenie wczesnych prototypów to dobry sposób na udzielenie odpowiedzi na te dwa pierwsze pytania. Ograniczanie ryzyka jest niezwykle ważne na wczesnych etapach.


Następne dwa pytania są bardziej ukierunkowane na późniejsze etapy projektu:

  1. czy faktycznie skończyliśmy? Wszystko zaprojektowane, zakodowane, przetestowane, dostarczone

  2. Czy faktycznie korzystają z systemu?

ghellquist
źródło