Esto es más una opinión / comentario que una respuesta.
No desea y no debe programar en C. C ++, cuando se usa de la manera correcta , es muy superior. (OK, debo admitir que, cuando se usa de manera incorrecta, es mucho peor que C.) Eso lo limita a los chips que tienen un compilador C ++ (moderno), que es más o menos lo que es compatible con GCC, incluido AVR (con Algunas limitaciones, filo menciona los problemas de un espacio de direcciones no uniforme), pero excluye casi todos los PIC (PIC32 podría ser compatible, pero todavía no he visto ningún puerto decente).
Cuando está programando algoritmos en C / C ++, la diferencia entre las opciones que menciona es pequeña (excepto que un chip de 8 o 16 bits tendrá una grave desventaja cuando realice una gran cantidad de aritmética de 16, 32 o más bits). Cuando necesite la última onza de rendimiento, probablemente necesitará usar el ensamblador (ya sea el suyo o el código proporcionado por el proveedor o un tercero). En ese caso, es posible que desee volver a considerar el chip que seleccionó.
Cuando está codificando el hardware, puede usar alguna capa de abstracción (a menudo provista por el fabricante) o escribir la suya (según la hoja de datos y / o el código de ejemplo). Las abstracciones C existentes de IME (mbed, cmsis, ...) a menudo son funcionalmente (casi) correctas, pero fallan horriblemente en el rendimiento (verifique que los viejos pedos despotrican sobre 6 capas de indirección para una operación de configuración de pin), usabilidad y portabilidad. Quieren exponerle toda la funcionalidad del chip en particular, que en casi todos los casos no necesitará y no le importará, y bloquea su código a ese proveedor en particular (y probablemente ese chip en particular).
Esto es donde C ++ puede hacerlo mucho mejor: cuando se hace correctamente, un conjunto de pines puede atravesar 6 o más capas de abstracción (porque eso hace una mejor interfaz (¡portátil!) Y un código más corto posible), pero proporciona una interfaz que es independiente del objetivo para los casos simples , y aun así se obtiene el mismo código de máquina que escribiría en el ensamblador .
Un fragmento del estilo de codificación que uso, que puede hacerte entusiasta o alejarte con horror:
// 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 > >;
En realidad hay algunas capas más de abstracción. Sin embargo, el uso final del led, digamos que encenderlo, no muestra la complejidad o los detalles del objetivo (para una píldora azul Arduin uno o ST32, el código sería idéntico).
target::led::init();
target::led::set( 1 );
El compilador no se siente intimidado por todas esas capas, y debido a que no hay funciones virtuales involucradas, el optimizador ve a través de todo (algunos detalles, omitidos, como habilitar el reloj periférico):
mov.w r2, #134217728 ; 0x8000000
ldr r3, [pc, #24]
str r2, [r3, #16]
str r2, [r3, #48]
Así es como lo habría escrito en ensamblador: SI me hubiera dado cuenta de que los registros PIO se pueden usar con compensaciones desde una base común. En este caso probablemente lo haría, pero el compilador es mucho mejor para optimizar tales cosas que yo.
Entonces, hasta donde tengo una respuesta, es: escriba una capa de abstracción para su hardware, pero hágalo en C ++ moderno (conceptos, plantillas) para que no perjudique su rendimiento. Con eso en su lugar, puede cambiar fácilmente a otro chip. Incluso puede comenzar a desarrollar en algún chip aleatorio que tenga, con el que esté familiarizado, tenga buenas herramientas de depuración, etc. y posponga la elección final hasta más tarde (cuando tenga más información sobre la memoria requerida, la velocidad de la CPU, etc.).
En mi opinión, una de las falacias del desarrollo integrado es elegir el chip primero (es una pregunta que a menudo se hace en este foro: qué chip debería elegir ... La mejor respuesta es generalmente: no importa).
(editar - respuesta a "Entonces, en cuanto al rendimiento, ¿C o C ++ estarían al mismo nivel?")
Para las mismas construcciones, C y C ++ son iguales. C ++ tiene muchas más construcciones para la abstracción (solo unas pocas: clases, plantillas, constexpr) que pueden, como cualquier herramienta, usarse para bien o para mal. Para hacer las discusiones más interesantes: no todos están de acuerdo en lo que es bueno o malo ...