Os simuladores de CPU incorporados geralmente podem ser programados para também simular hardware. Todas as tecnologias de virtualização, além do Xen, fazem isso. Mas você precisa escrever código que finge ter alguns registros em algum endereço físico ou, em x86, um endereço no barramento de E / S, e então você precisa responder a leituras e gravações nesses endereços como se o seu software fosse um físico. chip cujos registros de controle e status estavam sendo acessados.
Se você quiser fazer isso, sugiro modificar o QEMU. Mas isso não seria fácil. Esse tipo de coisa geralmente só é feito quando você está projetando um chip personalizado com um microcontrolador e alguns outros núcleos para o seu I / O.
O sistema de desenvolvimento vendido pela ARM Holdings prevê isso e é mais fácil de trabalhar do que hackear o QEMU, mas é muito caro.
Existem vários emuladores Open Source ARM que executam uma única sub-rotina, que pode chamar outras sub-rotinas, que você pode usar para depurar o desempenho de sub-rotinas que não dependem do acesso ao hardware. Eu usei um desses para obter grande sucesso para otimizar um criptografador AES para ARM7TDMI.
Você pode escrever um chicote simples de teste de unidade em C ou C ++, vincular a classe ou sub-rotina sob teste a ele e, em seguida, executá-lo no simulador.
Venho ponderando um problema semelhante há anos, como testar código de kernel Linux ou Mac OS X. Deve ser possível, mas eu nunca tentei. É possível construir um kernel completo em vez de testar seu código isoladamente, com a estrutura de teste de unidade vinculada diretamente ao seu kernel. Você então dispararia os testes de unidade de algum tipo de interface externa.
Talvez seja mais produtivo usar uma ferramenta de cobertura de código e testar seu firmware como um pacote completo por meio de sua interface externa. A ferramenta de cobertura encontraria caminhos de código que ainda não foram testados, para que você pudesse adicionar testes externos adicionais na tentativa de obter mais cobertura.