Atualmente, tenho um número de série codificado no firmware para um design com o qual estou trabalhando. O firmware pode ler e reportar o número de série. Isso funciona bem para o que eu preciso. O problema é que cada novo número de série exige que eu mude meu código e recompile. Isso é complicado quando há muitas unidades a serem construídas, é possível introduzir erros e é uma má prática geral. Os números de série são fornecidos a mim e o design do hardware é definido, portanto, não posso adicionar nenhum recurso no hardware para serializar as unidades (EEPROM / Chip de identificação de silicone / pull-ups). O que eu gostaria de fazer é localizar o número de série em um endereço fixo, compilar o código uma vez e editar esse endereço no arquivo HEX compilado para cada novo número de série. O número é referenciado em vários lugares, então, idealmente, desejo defini-lo e localizá-lo uma vez, referencie essa "variável" em qualquer outro lugar do meu código. Alguém sabe como localizar dados constantes em um local específico de memória endereçável de minha escolha, usando o compilador C18? Existe uma maneira melhor de sugerir alguém?
fonte
Respostas:
Especificamente, para resolver a questão de vincular variáveis a endereços específicos na memória flash no PIC18 com o compilador C18, consulte a seção "Pragmas" no hlpC18ug.chm no diretório doc em que o compilador está instalado.
Para fazer isso, você precisa definir uma nova "seção" na memória e vinculá-la a um endereço inicial para
#pragma romdata serial_no_section=0x1700
Isso cria uma nova seção chamada "serial_no_section" que inicia no endereço 0x1700 na memória flash (programa) (porque definimos "romdata" no #pragma).
Diretamente após a linha #pragma, defina suas variáveis para:
Agora você tem 0x12 no endereço 0x1700 e 0x34 no endereço 0x1701 na memória (porque o PIC18 usa o modelo little-endian). O "const rom" garante que o compilador saiba que esse é um tipo de variável const e que a variável está na memória "rom" e, portanto, precisa ser acessado através de instruções de leitura de tabela.
A
#pragma romdata
declaração final garante que todas as seguintes declarações de variáveis sejam vinculadas às seções de memória padrão, conforme o vinculador vê, se encaixa em vez de seguir na seção "serial_no_section".Agora todo o código pode simplesmente fazer referência à variável "mySerialNumber" e você sabe exatamente em que endereço o número de série pode ser encontrado na memória.
A edição do código HEX pode ser um pouco desafiadora, pois você precisa calcular a soma de verificação para cada linha que editar. Estou trabalhando em uma classe C ++ para decodificar e codificar arquivos Intel HEX, o que deve facilitar isso, mas ainda não foi concluído. Arquivos de decodificação funcionam, a codificação novamente ainda não foi implementada. O projeto (se você estiver interessado) está aqui https://github.com/codinghead/Intel-HEX-Class
Espero que isto ajude
fonte
Fiz o número de série (s / n para abreviar) de maneira semelhante ao que Joel está descrevendo. Eu estava usando o compilador PIC18F4620 e CCS. A localização de s / n na memória Flash foi forçada nos últimos 4 bytes. Como eu estava usando apenas 80% do Flash, meu compilador e vinculador não escreveriam código executável nos últimos 4 bytes.
Então, eu tinha duas maneiras alternativas de escrever s / n em unidades individuais:
Responder ao comentário de Joel
Não sei sobre C18, mas o compilador CCS vem com funções de biblioteca
write_program_eeprom(...)
eread_program_eeprom(...)
. Aqui está como eles são na montagem.fonte
write_program_eeprom(...)
eread_program_eeprom(...)
. A EEPROM e o Flash são duas coisas diferentes!Eu fiz isso algumas vezes. Normalmente, defino uma área de informações de firmware em um local fixo na memória do programa e, em seguida, escrevo um programa que cria um arquivo HEX serializado a partir do arquivo HEX do modelo. Todas essas são coisas fáceis de fazer.
Na produção, você executa o programa de serialização uma vez após a passagem de todos os testes. Torna o arquivo HEX temporário com o número de série exclusivo, programado no PIC e, em seguida, o arquivo HEX temporário excluído.
Eu não deixaria o local ser realocável, então tenho que encontrá-lo. Isso pode mudar a cada compilação à medida que o vinculador move as coisas. Eu fiz isso para PICs muito pequenos, como a série 10F, onde essas constantes fazem parte das instruções do MOVLW. Nesses casos, eu tenho que ler o arquivo MAP em tempo real para determinar onde estão esses locais. Eu tenho o arquivo MPLINK MAP analisando o código em uma biblioteca apenas para esse fim.
Para colocar algo em um local fixo, defina um segmento em um endereço fixo. O vinculador colocará esses segmentos absolutos primeiro, depois os realocáveis em torno dele. Não se esqueça de usar CODE_PACK em vez de apenas CODE em uma PIC 18; caso contrário, você estará lidando com palavras inteiras de instância em vez de bytes individuais. Por exemplo (apenas digitado, não passe pela montagem):
fonte
Eu sugeriria armazenar o número de série em um endereço fixo. Dependendo do seu compilador / vinculador e da parte em questão, existem algumas abordagens que você pode adotar:
fonte
retlw
abordagem geralmente é muito mais rápida (em PICs de 18 bits, acall
a aretlw
leva quatro ciclos no total; o usoclrf TBLPTRU/movlw xx/movwf TBLPTRH/movlw xx/movwf TBLPTRL/tblrd *+/movf TABLAT,w
leva oito).Eu faria o oposto: compile e vincule o código e descubra onde o valor é armazenado no arquivo vinculador. Pode ser necessário localizar a variável explicitamente em um segmento mapeado para piscar.
Não solicitei isso, mas o software para PC fornecido para o programador Wisp648 tem a capacidade de ler um arquivo .hex, modificar um local específico e gravar o arquivo .hex novamente (no mesmo ou em outro arquivo). Não há necessidade de ter meu programador presente. A fonte está disponível (em Python), a licença permite todo o uso: www.voti.nl/xwisp Pode ser útil depois que você resolver o seu problema principal.
fonte