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 ...