Pergunta

Eu estou trabalhando em um projeto de C incorporado que depende de algum HW externo. Desejo stub o código de acesso a essas partes, para que eu possa simular o sistema sem usar qualquer HW. Até agora eu tenho usado algumas macros mas isso me obriga a mudar um pouco no meu código de produção, o que eu gostaria de evitar.

Exemplo:

stub.h
#ifdef _STUB_HW
#define STUB_HW(name) Stub_##name
#else /*_STUB_HW*/
#define STUB_HW(name) name
#endif /*_STUB_HW*/

my_hw.c
WORD STUB_HW(clear_RX_TX)()
{ /* clear my rx/tx buffer on target HW */ }

test_my_hw.c
#ifdef _STUB_HW
WORD clear_RX_TX()
{ /* simulate clear rx/tx buffer on target HW */ }

Com este código eu posso ligar / desligar a stubbing com a tag pré-processador _STUB_HW
Existe uma maneira de acomplish isso sem ter que mudar meu código prod, e evitando um monte de IFDEFs. E eu não vou misturar prod e código de teste no mesmo arquivo se eu puder evitá-lo. Eu não me importo como os olhares de código de teste, desde que eu possa manter, tanto quanto possível fora do código de produção.

Editar:

Seria bom se era posible para selecionar as funções / alterar nome sem substituir o arquivo inteiro. Como tomar todas as funções a partir de nRF_## e dando em seguida um novo nome e, em seguida, inserindo test_nRF_## para nRF_## se é posible

Foi útil?

Solução

Acabei de fazer dois arquivos ActualDriver.c e StubDriver.c contendo exatamente os mesmos nomes de função. Ao fazer duas versões ligando o código de produção contra os diferentes objetos existe nenhum conflito de nomeação. Desta forma, o código de produção não contém nenhum teste ou código condicional.

Outras dicas

Como Gerhard disse, use um arquivo de cabeçalho comum "driver.h" e arquivos de implementação camada de hardware separadas contendo as funções reais e stubbed.

No eclipse, tenho dois alvos e eu "excluir de construir" o arquivo driver.c que não é para ser usado e certifique-se o correto é incluído na compilação. Eclipse, em seguida, gera o makefile em tempo de compilação.

Outra questão a apontar é para garantir que você está definindo inteiros de tamanho fixo para que seu código se comporta da mesma a partir de uma perspectiva de transbordamento. (Apesar de sua amostra de código que eu posso ver que você está fazendo isso.)

Eu concordo com o acima exposto. A solução padrão para isso é definir um conjunto abstraída opaca de chamadas de função que são o "driver" para o hw e, em seguida, chamar que no programa principal. Em seguida, fornecem duas implementações de drivers diferentes, um para hw, um para sw. A variante sw irá simular o efeito IO do hw de alguma forma apropriada.

Note que, se o objetivo é a um nível inferior, ou seja, escrever código onde cada acesso ao hardware deve ser simulado em vez de funções inteiras, pode ser um pouco tricker. Mas aqui, "write_to_memory" diferente e funções "read_from_memory" (ou macros, se a velocidade no alvo é essencial) poderia ser definido.

Não há necessidade em ambos os casos para alterar os nomes de funções, só tem dois arquivos diferentes em lote, arquivos de marca, ou alvos de compilação IDE (dependendo do que ferramentas que você está usando).

Finalmente, em muitos casos, a melhor solução técnica é ir para um simulador de sistema de destino full-blown, como Qemu , Simics , SystemC , CoWare , vastas , ou similar. Isso permite que você execute o mesmo código o tempo todo, e, em vez de construir um modelo do hardware que funciona como o hardware real a partir da perspectiva do software. Ele faz demorar um investimento maior up-front muito, mas para muitos projetos que vale bem a pena o esforço. Ele basicamente se livrar do problema desagradável de ter diferentes versões para o alvo e host, e garante que você sempre usa o seu cross-compilador com opções de compilação de implantação. Note-se que muitas suites do compilador embutidos vêm com algum tal habilidade básica de simulação construído em.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top