Tenho mais de 20 anos de sistemas embarcados, principalmente 8 e 16 micros. A resposta curta para sua pergunta é a mesma que qualquer outro desenvolvimento de software - não otimize até que você saiba que precisa e, em seguida, não otimize até saber o que precisa otimizar. Escreva seu código para que seja confiável, legível e mantenível primeiro. A otimização prematura é tanto, se não mais, um problema em sistemas embarcados
Quando você programa "sem desperdiçar recursos", considera seu tempo um recurso? Se não, quem está pagando pelo seu tempo e, se ninguém, você tem algo melhor a ver com isso. Uma vez que qualquer projetista de sistema embarcado deve escolher é o custo do hardware versus o custo do tempo de engenharia. Se você enviará 100 unidades, use um micro maior, com 100.000 unidades, uma economia de US $ 1,00 por unidade é igual a 1 homem / ano de desenvolvimento de software (ignorando o tempo de lançamento no mercado, custo de oportunidade etc.), a 1 milhão de unidades. obtendo ROI por ser obsessivo com o uso de recursos, mas tenha cuidado porque muitos projetos incorporados nunca atingiram a marca de 1 milhão porque projetaram vender 1 milhão (alto investimento inicial com baixo custo de produção) e faliram antes de chegarem lá.
Dito isso, é necessário considerar e estar ciente de sistemas (pequenos) incorporados, porque eles o impedirão de funcionar, de maneiras inesperadas, e não apenas tornarão lento.
a) Pilha - normalmente você tem apenas um tamanho pequeno e, geralmente, limitado, tamanhos de quadros de pilha. Você deve estar ciente de qual é a utilização da sua pilha o tempo todo. Esteja avisado, problemas na pilha causam alguns dos defeitos mais insidiosos.
b) Heap - novamente, tamanhos pequenos de heap, portanto, tenha cuidado com a alocação de memória injustificada. Fragmentação se torna um problema. Com esses dois, você precisa saber o que fazer quando acabar - isso não acontece em um sistema grande devido à paginação fornecida pelo SO. Quando malloc retorna NULL, você verifica e o que faz. Toda malva precisa de um cheque e manuseio, código inchaço ?. Como um guia - não use se houver uma alternativa. A maioria dos sistemas pequenos não usa memória dinmática por esses motivos.
c) Interrupções de hardware - Você precisa saber como lidar com elas de maneira segura e oportuna. Você também precisa saber como criar código de reentrante seguro. Por exemplo, as bibliotecas padrão C geralmente não são reentrantes, portanto, não devem ser usadas dentro de manipuladores de interrupção.
d) Montagem - quase sempre otimização prematura. No máximo, é necessária uma pequena quantidade (inline) para obter algo que C simplesmente não pode fazer. Como exercício, escreva um método pequeno na montagem artesanal (do zero). Faça o mesmo em C. Meça o desempenho. Aposto que o C será mais rápido, sei que será mais legível, sustentável e extensível. Agora, para a parte 2 do exercício - escreva um programa útil em assembly e C.
Como outro exercício, observe quanto do kernal do Linux é assembler, e depois leia o parágrafo abaixo sobre o kernel do linux.
Vale a pena saber como fazê-lo; pode até valer a pena ser proficiente nas línguas para um ou dois micros comuns.
e) "register unsigned int variable_name", "register" é, e sempre foi, uma dica para o compilador, não uma instrução, no início dos anos 70 (40 anos atrás), fazia sentido. Em 2012, é um desperdício de pressionamentos de tecla, pois os compiladores são muito inteligentes e as instruções do micros são tão complexas.
Voltando ao seu comentário sobre o Linux - o problema que você tem aqui é que não estamos falando de apenas 1 milhão de unidades, estamos falando de centenas de milhões, com um tempo de vida para sempre. O tempo e o custo de engenharia para obtê-lo da melhor forma possível humanamente vale a pena. Embora seja um bom exemplo das melhores práticas de engenharia, seria suicídio comercial para a maioria dos desenvolvedores de sistemas embarcados ser tão pedante quanto o linux kernal exige.