PIC32 vs dsPIC vs ARM vs AVR, czy architektura ma znaczenie, kiedy i tak programujemy w języku C? [Zamknięte]

10

Obecnie używamy 32-bitowego mikrokontrolera PIC32. Działa dobrze dla naszych potrzeb, ale badamy również inne mikrokontrolery, które mogą lepiej do nas pasować + mamy inne projekty, dla których wybieramy MCU. W tym celu wybraliśmy mikrokontroler SAM DA oparty na ARM, który jest taki sam 32-bitowy, ale oparty na ARM (bardziej popularny niż PIC32 - z punktu widzenia branży).

Teraz dla PIC32 używamy MPLAB, ale dla kory ARM-M0 będziemy używać Atmel Studio. Będziemy używać języka C na obu platformach. Chodzi mi o to, że będziemy używać dwóch 32-bitowych mikrokontrolerów (tej samej firmy), ale o różnych architekturach. Będzie to wymagało od nas nauki dwóch różnych urządzeń i zwiększy naszą „krzywą uczenia się” + czas dostawy. Ale z drugiej strony myślę, że ponieważ w obu przypadkach będziemy używać języka C, krzywa uczenia się dla ARM nie powinna być słyszalna i warto również zbadać ten procesor.

Moje główne pytanie dotyczy tego, jak duża jest różnica w architekturze, gdy programujemy w języku C, ponieważ zapewnia ona abstrakcję wewnętrznych elementów mikrokontrolera. I jakie są główne różnice w MPLAP i Atmel Studio , zważywszy C-język programowania.

inżynier
źródło
2
Jeśli wszystko działa z PIC32, to po co przełączać? Nawet jeśli kod całkowicie porty (nie będzie), wciąż jest nowy łańcuch narzędzi i IDE, do którego można się przyzwyczaić. Jaki jest sens? Zmiana z powodów religijnych lub na „ARM” (lub cokolwiek innego) jest głupia. Musisz mieć dobry powód, ale nam nie pokazałeś.
Olin Lathrop,
Nie pytałem o zmianę. Mówiłem o wyborze innej architektury dla innych projektów, ponieważ pracujemy nad wieloma projektami + istnieje możliwość ulepszenia naszego istniejącego projektu. Główny punkt dotyczył krzywej uczenia się i wyzwań związanych z pracą z dwiema różnymi architekturami jednocześnie.
inżynier
Jedną rzeczą, którą odkryłem, jest to, że Atmel Studio zapewnia lepszą synchronizację czasu niż wideo YouTube
inżynier

Odpowiedzi:

20

To dość uparty temat. Mogę mówić za siebie (AVR, ARM, MSP430).

Różnica 1 (najbardziej znacząca) dotyczy urządzeń peryferyjnych. Każdy MCU ma podobny UART, SPI, timery itp. - wystarczy zarejestrować nazwy i bity są różne. Przez większość czasu był to główny problem, z którym musiałem sobie poradzić, przenosząc kod między chipami. Rozwiązanie: napisz sterowniki za pomocą wspólnego interfejsu API, aby aplikacja była przenośna.

Różnica 2 to architektura pamięci. Jeśli chcesz umieścić stałe w flash na AVR, musisz użyć specjalnych atrybutów i funkcji specjalnych, aby je odczytać. W świecie ARM po prostu rezygnujesz ze wskaźnika, ponieważ istnieje pojedyncza przestrzeń adresowa (nie wiem, jak radzą sobie z tym małe PIC, ale zakładam, że są bliżej AVR).

Różnica 3 to deklaracja i obsługa przerwań. avr-gccma ISR()makro. ARM ma tylko nazwę funkcji (jak niektóre UART_Handler () - jeśli używasz nagłówków CMSIS i kodu startowego). Wektory przerwań ARM można umieszczać w dowolnym miejscu (w tym RAM) i modyfikować w czasie wykonywania (bardzo przydatne, jeśli masz na przykład dwa różne protokoły UART, które można przełączać). AVR ma tylko opcję użycia wektorów w „głównej pamięci flash” lub w „sekcji bootloadera” (więc jeśli chcesz inaczej obsługiwać przerwania, musisz użyć ifinstrukcji).

Różnica 4 - tryby uśpienia i kontrola mocy. Jeśli potrzebujesz najniższego zużycia energii, musisz wykorzystać wszystkie funkcje MCU. Może to bardzo różnić się między MCU - niektóre mają bardziej zgrubne tryby oszczędzania energii, niektóre mogą włączać / wyłączać poszczególne urządzenia peryferyjne. Niektóre MCU mają regulowane regulatory, dzięki czemu można je uruchamiać przy niższym napięciu przy niższej prędkości itp. Nie widzę łatwego sposobu osiągnięcia tej samej wydajności na MCU (powiedzmy) z 3 globalnymi trybami mocy i innym z 7 trybami mocy i indywidualne sterowanie zegarem peryferyjnym.

Najważniejszą rzeczą przy dbaniu o przenośność jest wyraźne podzielenie kodu na części zależne od sprzętu (sterowniki) i części niezależne od aplikacji (aplikacja). Możesz opracować i przetestować ten ostatni na zwykłym komputerze PC ze sztucznym sterownikiem (np. Konsolą zamiast UART). To mnie uratowało wiele razy, ponieważ 90% kodu aplikacji zostało ukończone, zanim prototypowy sprzęt wyszedł z pieca rozpływowego :)

Moim zdaniem dobrą rzeczą w ARM jest „monokultura” - dostępność wielu kompilatorów (gcc, Keil, IAR ... żeby wymienić tylko kilka), wielu darmowych i oficjalnie obsługiwanych IDE (przynajmniej dla NXP, STM32, Silicon Labs, Nordic), wiele narzędzi do debugowania (SEGGER - szczególnie Ozone, ULINK, OpenOCD ...) i wielu dostawców chipów (nawet nie zacznę ich nazywać). PIC32 ogranicza się głównie do Microchip (ale ma to znaczenie tylko wtedy, gdy nie lubisz ich narzędzi).

Jeśli chodzi o kod C. Jest w 99% taki sam, ifinstrukcja jest taka sama, pętla działa w ten sam sposób. Jednak powinieneś dbać o rozmiar natywnego słowa. Na przykład, forpętla na AVR jest najszybsza, jeśli używasz uint8_tlicznika, podczas gdy na ARM uint32_tjest najszybszym typem (lub int32_t). ARM musiałby za każdym razem sprawdzać przepełnienie 8-bitowe, jeśli używałeś mniejszego typu.

Wybór MCU i / lub dostawcy ogólnie dotyczy głównie polityki i logistyki (chyba że masz bardzo wyraźne ograniczenia techniczne, na przykład: wysoka temperatura - użyj MSP430 lub Vorago). Nawet jeśli aplikacja może działać na dowolnym urządzeniu, a tylko 5% kodu (sterowników) musi zostać opracowane i obsługiwane przez cały okres użytkowania produktu - jest to nadal dodatkowa opłata dla firmy. Wszystkie miejsca, w których pracowałem, miały ulubionego sprzedawcę i linię MCU (np. „Wybierz dowolną Kinetis, o ile chcesz, chyba że istnieje bardzo dobry powód, aby wybrać coś innego”). Pomaga to również, jeśli masz inne osoby, które proszą o pomoc, więc jako menedżer unikałbym posiadania 5-osobowego działu rozwoju, w którym wszyscy używali zupełnie innego układu.

filo
źródło
3
„AVR jest najszybszy, jeśli używasz uint8_t jako licznika, podczas gdy na ARM uint32_t jest najszybszym typem (lub int32_t). ARM musiałby za każdym razem sprawdzać przepełnienie 8-bitowe, jeśli używałeś mniejszego typu. ” możesz użyć uint_fast8_t, jeśli potrzebujesz tylko co najmniej 8 bitów.
Michael
@Michael - na pewno możesz używać _fast typów, ale nie możesz liczyć na zachowanie przepełnienia. W stdint.h mojego gcc mam „typedef unsigned int uint_fast8_t”, co w zasadzie jest uint32_t :)
filo
Próba napisania API, który jest wydajny, uniwersalny i kompletny, jest trudna, biorąc pod uwagę, że różne platformy mają różne możliwości. Procesor prawdopodobnie ma mniejsze znaczenie niż urządzenia peryferyjne i decyzje projektowe podejmowane z nimi. Na przykład niektóre urządzenia umożliwiają zmianę konfiguracji różnych urządzeń peryferyjnych w dowolnym momencie, co najwyżej kilka mikrosekund, podczas gdy inne mogą wymagać wielu kroków rozłożonych na setki mikrosekund, a nawet milisekund. Funkcja API, która jest przeznaczona dla poprzedniego wzorca, może być użyteczna w ramach procedury obsługi przerwań działającej z częstotliwością 10 000 Hz, ale ...
supercat,
... nie może obsługiwać takiego użycia na platformach, które wymagałyby rozłożenia operacji na setki mikrosekund. Nie wiem, dlaczego projektanci sprzętu nie starają się bardzo wspierać semantyki API „szybkiej operacji w dowolnym momencie”, ale wielu używa modelu, który synchronizuje poszczególne operacje, a nie stanu, aby np. Otrzymać np. włącz urządzenie, a kod zda sobie sprawę, że nie musi być włączony, kod musi poczekać na włączenie urządzenia, zanim będzie mógł wydać polecenie wyłączenia. Płynna obsługa w interfejsie API powoduje poważne komplikacje.
supercat,
11

Użyłem kilku MCU od czterech różnych producentów. Głównym zadaniem za każdym razem jest zapoznanie się z urządzeniami peryferyjnymi.

Na przykład sam UART nie jest zbyt skomplikowany i łatwo znajduję port sterowników. Ale ostatni raz zajęło mi prawie dzień, aby uzyskać zegary, piny I / O przerywają, włączają itp.

GPIO może być bardzo złożone. Bit-set, bit-clear, bit-toggle, Włączanie / wyłączanie funkcji specjalnych, tri-state. Następnie otrzymasz przerwania: dowolna krawędź, wzrost, spadek, poziom niski, poziom wysoki, samooczyszczanie lub nie.

Potem jest I2C, SPI, PWM, Timery i dwa tuziny innych rodzajów urządzeń peryferyjnych, każdy z własnym włączaniem zegara i za każdym razem, gdy rejestry różnią się nowymi bitami. Dla wszystkich z nich przeczytanie arkusza danych zajmuje wiele godzin, jak ustawić, który bit w jakich okolicznościach.

Ostatni producent miał wiele przykładów kodu, które uważałem za bezużyteczne. Wszystko było abstrakcyjne. Ale kiedy go prześledziłem, kod przeszedł sześć! poziomy wywołań funkcji, aby ustawić bit GPIO. Fajnie, jeśli masz procesor 3GHz, ale nie masz MCU 48 MHz. Mój kod ostatecznie był pojedynczą linią:

GPIO->set_output = bit.

Próbowałem użyć bardziej ogólnych sterowników, ale zrezygnowałem. Na MCU zawsze zmagasz się z cyklami miejsca i zegara. Odkryłem, że warstwa abstrakcji jako pierwsza wychodzi z okna, jeśli generujesz określony przebieg w procedurze przerwania o częstotliwości 10 kHz.

Więc teraz mam wszystko działające i nie planuję ponownie się przełączać, chyba że z bardzo, bardzo dobrego powodu.

Wszystkie powyższe należy zamortyzować, ile produktów sprzedajesz i ile oszczędzasz. Sprzedaż miliona: oszczędność 0,10 na zmianę na inny typ oznacza, że ​​możesz wydać 100 000 na roboczogodziny. Sprzedając 1000 masz tylko 100 do wydania.

Oldfart
źródło
1
Osobiście dlatego trzymam się asemblera. Piękny binarny, bez abstrakcji.
Ian Bland
Preprocesor C radzi sobie całkiem nieźle z różnymi rzeczami, szczególnie w połączeniu z __builtin_constant intrinsics. Jeśli definiuje się stałe dla każdego urządzenia I / O bitowej formie (liczba portów * 32 + liczba bitowy), jest możliwe zapisywanie makro na OUTPUT_HI(n)które daje równoważne identyfikacyjny GPIOD->bssr |= 0x400;, jeśli njest stała, jak 0x6A, ale wywołania prosty podprogramu, gdy njest w stanie nie stały. To powiedziawszy, większość interfejsów API dostawców, jakie widziałem, waha się między miernymi a okropnymi.
supercat,
8

To bardziej opinia / komentarz niż odpowiedź.

Nie chcesz i nie powinieneś programować w C. C ++, jeśli jest używany we właściwy sposób , jest znacznie lepszy. (OK, muszę przyznać, że przy niewłaściwym użyciu jest znacznie gorszy niż C.) To ogranicza cię do układów, które mają (nowoczesny) kompilator C ++, który jest mniej więcej wszystkim, co jest obsługiwane przez GCC, w tym AVR (z niektóre ograniczenia, filo wspomina o problemach z niejednorodną przestrzenią adresową), ale wyklucza prawie wszystkie PIC (PIC32 może być obsługiwany, ale nie widziałem jeszcze żadnego przyzwoitego portu).

Kiedy programujesz algorytmy w C / C ++, różnica między wspomnianymi opcjami jest niewielka (z wyjątkiem tego, że 8 lub 16-bitowy układ będzie miał poważną wadę, gdy wykonasz dużo 16, 32 lub więcej bitów). Kiedy potrzebujesz ostatniej uncji wydajności, prawdopodobnie będziesz musiał użyć asemblera (własnego lub kodu dostarczonego przez dostawcę lub osobę trzecią). W takim przypadku możesz ponownie rozważyć wybrany układ.

Podczas kodowania do sprzętu możesz albo użyć warstwy abstrakcji (często dostarczanej przez producenta), albo napisać własną (na podstawie arkusza danych i / lub przykładowego kodu). Istniejące abstrakcje C w edytorze IME (mbed, cmsis, ...) są często funkcjonalnie (prawie) poprawne, ale strasznie zawodzą pod względem wydajności (sprawdź, czy oldfarts zawierają około 6 warstw pośrednich dla operacji na zestawie pinów), użyteczności i przenośności. Chcą udostępnić Ci całą funkcjonalność konkretnego układu, co w prawie wszystkich przypadkach nie będzie ci potrzebne, a raczej nie będziesz się tym przejmować, a to zablokuje Twój kod dla tego konkretnego dostawcy (i prawdopodobnie tego konkretnego układu).

To jest, gdy C ++ może zrobić znacznie lepiej: po prawidłowym wykonaniu zestaw pinów może przejść przez 6 lub więcej warstw abstrakcji (ponieważ dzięki temu możliwy jest lepszy (przenośny!) Interfejs i krótszy kod), ale jednocześnie zapewnia interfejs niezależny od celu dla prostych przypadków i nadal skutkować tym samym kodem maszynowym, jak w przypadku asemblera .

Fragment stylu kodowania, którego używam, który może wywołać entuzjazm lub odwrócić się z przerażeniem:

// GPIO part of a HAL for atsam3xa
enum class _port { a = 0x400E0E00U, . . . };

template< _port P, uint32_t pin >
struct _pin_in_out_base : _pin_in_out_root {

   static void direction_set_direct( pin_direction d ){
      ( ( d == pin_direction::input )
         ? ((Pio*)P)->PIO_ODR : ((Pio*)P)->PIO_OER )  = ( 0x1U << pin );
   }

   static void set_direct( bool v ){
      ( v ? ((Pio*)P)->PIO_SODR : ((Pio*)P)->PIO_CODR )  = ( 0x1U << pin );    
   }
};

// a general GPIO needs some boilerplate functionality
template< _port P, uint32_t pin >
using _pin_in_out = _box_creator< _pin_in_out_base< P, pin > >;

// an Arduino Due has an on-board led, and (suppose) it is active low
using _led = _pin_in_out< _port::b, 27 >;
using led  = invert< pin_out< _led > >;

W rzeczywistości jest jeszcze kilka warstw abstrakcji. Jednak ostateczne użycie diody LED, powiedzmy, aby ją włączyć, nie pokazuje złożoności ani szczegółów celu (dla żarłocznego uno lub niebieskiej pigułki ST32 kod byłby identyczny).

target::led::init();
target::led::set( 1 );

Kompilator nie jest zastraszany przez wszystkie te warstwy, a ponieważ nie ma w nim żadnych funkcji wirtualnych, optymalizator przejrzy wszystko (niektóre szczegóły pominięto, na przykład włączenie zegara peryferyjnego):

 mov.w  r2, #134217728  ; 0x8000000
 ldr    r3, [pc, #24]   
 str    r2, [r3, #16]
 str    r2, [r3, #48]   

Tak napisałbym to w asemblerze - JEŚLI zdałem sobie sprawę, że rejestrów PIO można używać z przesunięciami ze wspólnej bazy. W tym przypadku prawdopodobnie bym to zrobił, ale kompilator jest znacznie lepszy w optymalizacji takich rzeczy niż ja.

O ile mam odpowiedź, to: napisz warstwę abstrakcji dla swojego sprzętu, ale zrób to we współczesnym C ++ (koncepcje, szablony), aby nie zaszkodziło to twojej wydajności. Dzięki temu możesz łatwo przejść na inny układ. Możesz nawet zacząć opracowywać losowy układ, na którym się układasz, masz rodzinę, masz dobre narzędzia do debugowania itp. I odkładasz ostateczny wybór na później (gdy będziesz miał więcej informacji o wymaganej pamięci, szybkości procesora itp.).

IMO jednym z błędów we wbudowanym rozwoju jest wybór chipa jako pierwszego (to pytanie często zadawane na tym forum: dla którego chipa powinienem wybrać ... Najlepsza odpowiedź brzmi ogólnie: to nie ma znaczenia).

(edycja - odpowiedź na „Czy pod względem wydajności C lub C ++ byłby na tym samym poziomie?”)

Dla tych samych konstrukcji C i C ++ są takie same. C ++ ma znacznie więcej konstrukcji do abstrakcji (tylko kilka: klasy, szablony, constexpr), które, jak każde narzędzie, mogą być użyte dla dobra lub zła. Aby dyskusje były bardziej interesujące: nie wszyscy zgadzają się co jest dobre, a co złe ...

Wouter van Ooijen
źródło
Czy pod względem wydajności C lub C ++ byłyby na tym samym poziomie? Myślę, że C ++ będzie miał większe przeciążenie. Zdecydowanie wskazałeś mi właściwy kierunek, C ++ to droga, a nie C.
inżynier
Szablony C ++ wymuszają polimorfizm w czasie kompilacji, który może być zerowy (lub nawet ujemny) pod względem wydajności, ponieważ kod jest kompilowany dla każdego konkretnego przypadku użycia. Jednak najlepiej nadaje się to do celowania w prędkość (O3 dla GCC). Polimorfizm w czasie wykonywania, podobnie jak funkcje wirtualne, może ponieść znacznie większą karę, chociaż można go łatwo utrzymać, aw niektórych przypadkach wystarczająco dobry.
Hans
1
Twierdzisz, że C ++ jest lepszy, ale potem używasz rzutów w stylu C. Wstyd.
JAB,
@JAB Nigdy nie czułem wiele za obsady w nowym stylu, ale dam im szansę. Ale moim obecnym priorytetem są inne części tej biblioteki. Prawdziwym problemem jest oczywiście to, że nie mogłem przekazać wskaźników jako parametrów szablonu.
Wouter van Ooijen,
@Hans mój styl cto (Compile Time Objects) ma raczej wąski przypadek użycia (zbliżony do sprzętu, znana sytuacja w czasie kompilacji), jest bardziej C-killerem niż zamiennikiem dla tradycyjnych zastosowań wirtualnego OO. Przydatnym przyłowem jest to, że brak pośrednictwa umożliwia obliczenie wielkości stosu.
Wouter van Ooijen,
4

Jeśli dobrze rozumiem, chcesz wiedzieć, jakie specyficzne dla architektury funkcje platformy „wyskakują” w środowisku języka C, co utrudnia pisanie łatwego w utrzymaniu, przenośnego kodu na obu platformach.

C jest już dość elastyczny, ponieważ jest „przenośnym asemblerem”. Wszystkie wybrane platformy mają dostępne kompilatory GCC / komercyjne, które obsługują standardy językowe C89 i C99, co oznacza, że ​​możesz uruchamiać podobny kod na wszystkich platformach.

Istnieje kilka uwag:

  • Niektóre architektury to Von Neumann (ARM, MIPS), inne to Harvard. Główne ograniczenia powstają, gdy Twój program C musi odczytywać dane z pamięci ROM, np. Aby wydrukować łańcuchy, mieć dane zdefiniowane jako „const” lub podobne.

Niektóre platformy / kompilatory mogą lepiej ukrywać to „ograniczenie” niż inne. Np. W AVR musisz użyć określonych makr, aby odczytać dane ROM. W PIC24 / dsPIC dostępne są również dedykowane instancje tblrd. Jednak dodatkowo niektóre części mają również funkcję „widoczności przestrzeni programowej” (PSVPAG), która pozwala na mapowanie strony FLASH do pamięci RAM, dzięki czemu natychmiastowe adresowanie danych jest dostępne bez tblrd. Kompilator może to zrobić dość skutecznie.

ARM i MIPS są Von Neumann, dzięki czemu mają obszary pamięci dla ROM, RAM i urządzeń peryferyjnych spakowanych na 1 magistrali. Nie zauważysz żadnej różnicy między odczytem danych z pamięci RAM lub „ROM”.

  • Jeśli zanurkujesz poniżej C i spojrzysz na wygenerowane instrukcje dla niektórych operacji, zauważysz duże różnice wokół I / O. ARM i MIPS to architektura rejestru pamięci masowej RISC . Oznacza to, że dostęp do danych na magistrali pamięci musi przejść przez instrukcje MOV. Oznacza to również, że każda modyfikacja wartości peryferyjnej doprowadzi do operacji odczytu-modyfikacji-zapisu (RMW). Istnieje kilka części ARM, które obsługują pasmowanie bitów, które mapują rejestry zestawów / clr-bitów w przestrzeni peryferyjnej we / wy. Musisz jednak samodzielnie zakodować ten dostęp.

Z drugiej strony PIC24 pozwala operacjom ALU na odczyt i zapis danych bezpośrednio przez adresowanie pośrednie (nawet przy modyfikacjach wskaźnika ..). Ma to pewne cechy z architektury podobnej do CISC, więc 1 instrukcja może wykonać więcej pracy. Ta konstrukcja może prowadzić do bardziej skomplikowanych rdzeni procesora, niższych zegarów, wyższego zużycia energii itp. Na szczęście dla Ciebie ta część jest już zaprojektowana. ;-)

Różnice te mogą oznaczać, że PIC24 może być „mocniejszy” we / wy operacji we / wy niż podobnie taktowany układ ARM lub MIPS. Jednak możesz uzyskać znacznie wyższą część ARM / MIPS zegara dla tych samych ograniczeń cena / pakiet / projekt. Sądzę, że dla praktycznych terminów dużo „uczenia się platformy” polega na opanowaniu tego, co architektura może, a czego nie może zrobić, jak szybko potrwa kilka zestawów operacji itp.

  • Urządzenia peryferyjne, zarządzanie zegarem itp. Różnią się w zależności od rodziny części. Ściśle mówiąc, zmieni się to również w ekosystemie ARM między dostawcami, z wyjątkiem kilku urządzeń peryferyjnych powiązanych z Cortex m, takich jak NVIC i SysTick.

Różnice te można nieco zawrzeć w sterownikach urządzeń, ale ostatecznie wbudowane oprogramowanie sprzętowe ma wysoki poziom sprzężenia ze sprzętem, więc czasami nie można uniknąć pracy niestandardowej.

Ponadto, jeśli opuszczasz ekosystemy Microchip / były Atmel, może się okazać, że części ARM wymagają większej konfiguracji, aby je uruchomić. Mam na myśli w kategoriach; włączanie zegarów do urządzeń peryferyjnych, a następnie konfigurowanie urządzeń peryferyjnych i „włączanie” ich, osobne konfigurowanie NVIC itp. To tylko część krzywej uczenia się. Kiedy pamiętasz, aby wykonać wszystkie te czynności, w odpowiedniej kolejności, pisanie sterowników urządzeń dla wszystkich tych mikrokontrolerów będzie w pewnym momencie wydawać się podobne.

  • Spróbuj także użyć bibliotek takich jak stdint.h, stdbool.h itp., Jeśli jeszcze tego nie zrobiłeś. Te typy liczb całkowitych wyraźnie określają szerokości, co sprawia, że ​​zachowanie kodu jest najbardziej przewidywalne między platformami. Może to oznaczać użycie 32-bitowych liczb całkowitych na 8-bitowym AVR; ale jeśli twój kod tego potrzebuje, niech tak będzie.
Hans
źródło
3

Tak i nie. Z perspektywy programisty idealnie ukrywasz szczegóły zestawu instrukcji. Ale to do pewnego stopnia już nie ma znaczenia, urządzenia peryferyjne, które są celem pisania programu, nie są częścią zestawu instrukcji. W tym samym czasie nie można po prostu porównać części flash 4096 bajtów w tych zestawach instrukcji, szczególnie jeśli używasz C, ilość zużycia pamięci flash / pamięci jest silnie określona przez zestaw instrukcji i kompilator, niektórzy nigdy nie powinni widzieć kompilatora (kaszel PIC kaszel) ze względu na ilość marnotrawstwa tych zasobów zużywaną przez kompilację. Inne zużycie lampy błyskowej jest mniejsze. Wydajność jest również problemem w przypadku używania języka wysokiego poziomu, a wydajność ma znaczenie w aplikacjach MCU, więc może mieć znaczenie między wydatkowaniem 3 USD za płytę na MCU lub 1 USD.

Jeśli chodzi o ułatwienie programowania (przy całkowitym koszcie produktu), powinieneś być w stanie pobrać pakiet programisty dla mcu, tak aby architektura zestawu instrukcji była czymś, czego nigdy nie widzisz, więc jeśli jest to twoja główna troska, to nie jest problemem. Nadal kosztuje Cię to tyle, ile koszt produktu związany z korzystaniem z tych bibliotek, ale czas na wprowadzenie na rynek może być krótszy, uważam, że korzystanie z bibliotek zajmuje więcej czasu / pracy w porównaniu do bezpośredniego komunikowania się z urządzeniami peryferyjnymi.

Podsumowując, zestawy instrukcji są najmniejszymi zmartwieniami, przejdźmy do prawdziwych problemów.

old_timer
źródło