En ese aspecto tienes toda la razón. Yo mismo he tenido que trabajar con un grupo de programadores expertos en drivers para desarrollar los de varios de los dispositivos que hacemos. Pero, del lado de la PC, se tiene por supuesto mucha ventaja. Puedes hacerlo todo con un lenguaje de alto nivel si lo deseas, y cumplir con todo un conjunto de reglas para asegurar la portabilidad, y otros aspectos como el reuso de código.
Sin intención de desviar el tema, del lado del Hardware que se conecta al PC por supuesto, muy pocas veces tienes oportunidad de trabajar con un procesador lo suficientemente veloz o poderoso como para seguir todas las reglas. De hecho, he recibido muchas críticas de otros programadores acerca de la gran mayoría de mi código. Aspectos como utilizar demasiadas variables globales, usar con demasiada frecuencia Inline Assembly, o tener múltiples puntos de salida para una función. Yo mismo evito hacer tales cosas programando aplicaciones para PC. Pero en algunas plataformas, las reglas estorban, o algunas cualidades de un lenguaje se vuelven la encarnación del mal. O lo que en estos procesadores genera una enorme mejora de velocidad, en un PC es irrelevante ya que, por la enorme cantidad de intrucciones que pueden procesar por segundo, un usuario no nota la diferencia entre 100 ciclos o 10,000. Por eso alguna vez te decía que muchas veces me da lo mismo el lenguaje de alto nivel que se use. Muchas veces termino optimizando sectores críticos con Assembly. Sobre todo en el manejo de interrupciones. En este mismísimo momento estoy trabajando con un procesador de Freescale de 8 bits. Te dejo dos ejemplos que en cuanto a funcionalidad, hacen exactamente lo mismo (reciben 8 bits con el protocolo I2C con un MCU funcionando a 3.2Mhz). Pero evidentemente, una de las soluciones es inaceptable.
Este ejemplo es fácil de comprender y breve...
Código:
//La variable i está declarada dentro de la función
//Y se está incrementando (esto ralentiza el bucle algunos ciclos)
//Se utilizaron BitFields
for(i=0; i<8; i++){
DDRA.BIT4 = 0;
if(PTA.BIT3) TxRxSHR |= (1<<i);
PTA.BIT4 = 0;
DDRA.BIT4 = 1;
}
Pero genera esto:
Código:
TSX
CLR ,X
LDA _DDRA
AND #-17
STA DDRA
LDA _PTA
AND #8
TSTA
BEQ +12
LDA #1
LDX ,X
BEQ +3
LSLA ;Aquí está el principal problema
DBNZX -3 ;Se retrasa (5*i) + (5*2i) + ... + (5*7i)
;es decir 140 ciclos
ORA TxRxSHR
STA TxRxSHR
LDA _PTA
AND #-17
STA _PTA
LDA _DDRA
ORA #16
STA _DDRA
TSX
INC ,X
LDA ,X
CMP #8
BCS -39
Este otro código, ya no es portable definitivamente, si quiero volver a usarlo en otro procesador, tendré que reescribirlo...
Código:
//bitCount es una variable global declarada como "byte __near bitCount"
//En lugar de incrementarla, se decrementa, por lo tanto
//se compara contra cero, que es el modo más eficiente en
// un procesador.
for(bitCount=8; bitCount>0; bitCount--){
DDRA &= ~0x10;
_asm{
LDA PTA
AND #0x08
ADD #0xF8
ROL TxRxSHR
}
PTA &= ~0x10;
DDRA |= 0x10;
}
Sim embargo, genera este código que se ejecuta en ~32 ciclos:
Código:
MOV #8,bitCount
BCLR 4,_DDRA
LDA _PTA
AND #8
ADD #-8
ROL TxRxSHR
BCLR 4,_PTA
BSET 4,_DDRA
DEC bitCount
TST bitCount
BNE -20
El primer código podría ser usado, y sería portable, aún considerando que es lento, pero para esta aplicación en particular, agotaría la batería con que debe operar el procesador mucho más rápido que con el segundo código. Podría aumentar la velocidad del circuito, pero esto también acabaría con la batería. Como puedes ver, el asunto de la portabilidad ya no resulta importante. Y sigue siendo lenguaje C.
Disculpándome por desviar tanto el tema, y volviendo al rubro de los OS, alguna vez hice uno, por supuesto no un Windows, no un Linux. Simplemente se trataba de poder ejecutar varias "aplicaciones" en un MCU de 8 bits, con limitadísima memoria RAM (2K), y en lugar de disco duro, una memoria flash de 2M. Encontré un libro llamado "μC/OS, The Real-Time Kernel" de Jean J. Labrosse. Los conceptos que expone son válidos para para OS "mayores", y te guía paso a paso para que hagas uno que funcionará en un X86, ya que probablemente será el procesador que tendrás a mano. Este μC/OS ha sido portado a muchas plataformas, como los 8052, 8051, Motorola 68K, Philips 80C166... en fin, una lista interminable.
Y como ultima nota y abuso, con el incremento de aplicaciones embebidas, hay un vacío enorme de programadores que desarrollen OS o aplicaciones para estas plataformas. Desde 4 bits hasta 64 bits.