Executar código uma vez na vida de um programa C incorporado

8

Como posso executar um snippet de código apenas uma vez na vida de um programa? Pode ser desligado e ligado várias vezes. A única opção para executar o trecho de código novamente deve estar piscando novamente no quadro.

O código é uma seção de calibração que não quero executar novamente. Se eu usar EEPROM ou Flash, definiremos um sinalizador como verdadeiro ou falso. Então, quando lemos pela primeira vez a localização da memória, qual seria o valor aleatório nessa área de memória?

Qual é o melhor método para implementar isso no C incorporado?

ganeshredcobra
fonte
5
Use uma bandeira e salve-a no eeprom (ou no flash). A cada instante, leia a bandeira da eeprom. Na primeira vez do instante, o valor do sinalizador forçará a execução da função. Depois disso, você pode alterar o valor da bandeira e salvá-lo na eeprom novamente. Todas as outras vezes que o valor do sinalizador não forçará a execução da função.
hoo2
2
não está claro o que você está perguntando.
old_timer
2
Qual é a sua motivação para impedir que o código seja executado uma segunda vez? É importante que o código não possa sofrer engenharia reversa; nesse caso, definir um sinalizador para contorná-lo pode não ser suficientemente seguro? A execução do código uma segunda vez danificaria o hardware? É uma coisa UX, como exibir uma mensagem de tutorial na primeira vez em que o sistema é usado; nesse caso, pode ser desejável que a função "redefinição de fábrica" ​​(se houver) faça com que o código seja executado novamente?
11266 Micheal Johnson
5
Geralmente, é uma boa ideia permitir a recalibração, caso algo estrague a primeira vez, ou o sistema precise ser recalibrado para uma configuração diferente ou para compensar o envelhecimento do hardware, etc. primeira vez porque não sei o que devo fazer.
Micheal Johnson
3
Que tal você configurar o código para que exista uma maneira de executá-lo (ou seja, envie algo através de uma porta serial). Dessa forma, não há necessidade de se preocupar com memória não volátil e você pode acionar a calibração durante a produção de maneira controlada.
alex.forencich

Respostas:

18

Seu microcontrolador pode ter alguma EEPROM, memória OTP, bits de fusível do usuário, onde você pode definir um sinalizador.

Não existe um "melhor método no C incorporado", a gravação de memória não volátil é diferente em cada microcontrolador.

editar:

INSTANTÂNEO

O conteúdo da memória flash é apagado durante a programação do dispositivo. Após a programação, todos os bytes que não foram gravados contêm 0xFF. Consulte a folha de dados para encontrar uma área que pode ser programada com segurança no firmware em execução.

EEPROM

Embora não seja garantido nas folhas de dados, todas as EEPROMs que eu vi até agora continham 0xFF: s quando enviadas da fábrica (exceto as pré-programadas com um endereço MAC exclusivo, mas explicitamente documentado). Alguns dispositivos / softwares de programação também podem apagar ou programar o conteúdo da EEPROM. Alguns podem ser protegidos contra gravação, de forma permanente ou reversível.

OTP

A memória programável única contém sempre valores iniciais bem definidos, documentados na folha de dados.

É sempre uma boa ideia incluir uma boa soma de verificação, como o CRC32, com os dados gravados, para proteger contra corrupção de dados causada por peças defeituosas, erros de transmissão, raios cósmicos, qualquer que seja.

berendi - protestando
fonte
Se eu usar EEPROM ou Flash, definiremos um sinalizador como true ou False.So Quando lemos pela primeira vez esse local de memória, qual seria o valor aleatório nessa área de memória.
ganeshredcobra
2
Durante a fabricação, redefina a EEPROM (seja com um programador, se possível, seja criando um programa estúpido de limpador, faça o flash, ligue-o normalmente por alguns segundos e carregue no programa de produção).
Nick T
13

Você disse:

A única opção para executar esse código deve piscar o quadro novamente.

Outros disseram usar a EEPROM para armazenar um sinalizador para indicar quando a função run_once () foi executada. No entanto, isso tem uma desvantagem: se você atualizar o microcontrolador, o sinalizador ran_it_once na EEPROM já foi definido e a função run_once () não será executada. Se o seu microcontrolador tiver incorporado EEPROM, talvez seja possível limpar o sinalizador ran_it_once quando você atualizar o microcontrolador, se o programador suportar isso.

Uma maneira melhor é ter números de versão na EEPROM e no código. Quando o código é executado na inicialização, ele deve ler o número da versão da EEPROM e compará-lo com o número da versão armazenado no código. Se eles não corresponderem, a função run_once () será chamada e o ato final do código run_once () será escrever o número da versão do firmware na EEPROM. Cada vez que você modifica o código-fonte do firmware, você deve incrementar o número da versão incorporado.

Steve G
fonte
1
Na verdade, isso teria o mesmo problema que um sinalizador booleano se tudo que o usuário fizesse fosse atualizar o microcontrolador e ele precisasse ser executado novamente novamente (nesse cenário). Definitivamente resolveria o problema se o firmware fosse atualizado e precisasse ser executado novamente.
Taegost 11/04/19
8

Escolha um microcontrolador que possa gravar / apagar sua própria memória de programa. Depois de executar o código em questão, faça com que a última parte do código substitua a primeira instrução por um salto que a ignore. Opcionalmente, você também pode apagar o restante (talvez substitua por nop), para que haja uma chance absolutamente zero de que ele seja executado novamente.

Esta mensagem se autodestruirá em 5..4 ...

apalopohapa
fonte
1
Por mais inteligente que seja essa resposta, acho que é desnecessariamente complexa. Talvez ele possa usar uma observação especificando que provavelmente só deve ser usada se a memória persistente fora da memória do código estiver indisponível?
Skrrgwasme
Mesmo que outras soluções sejam possíveis, acho que isso é mais fácil de entender do que outras.
Joshua
1
Mesmo que outras soluções fossem possíveis, acho que isso seria muito difícil de entender no nível do código fonte.
um CVn
A maioria dos PICs possui apenas 35 instruções ... o que pode dar errado? ;)
rdtsc
5

Como você está usando esse código para calibração, minha sugestão seria criar um processo de explosão que execute o código de calibração como um primeiro estágio e nem o tenha na versão de produção final da placa. Isso é semelhante à resposta de apalopohapa, exceto diferente no sentido de que você teria duas cargas de programa separadas: tenha um processo rápido que pisca a primeira carga de programa que executa todas as calibrações e cospe os dados a partir disso. Em seguida, pegue esses dados e incorpore-os aos dados da segunda carga do programa.

Um benefício dessa abordagem é que você minimiza absolutamente a quantidade de espaço de armazenamento necessária - não é necessário armazenar seu código único, apenas os dados que ele gera. Por ter um processo explosivo que carrega dois programas separados, você também se isola um pouco dos bugs no código de inicialização, que poderiam permanecer por aí. Você também tem alguma flexibilidade adicional se quiser executar novamente o seu código de calibração: em vez de precisar escrever um código extra para limpar o bit que denota que seu código foi executado (o que já pode ser acidentalmente limpo), basta executar novamente o seu código de calibração. processo de explosão.

Michael
fonte