Para a questão do AVR e recordes mundiais

Faça bem, vai acabar mal


A razão para a publicação foi recente (quando comecei a escrever, era realmente recente, mas algo aconteceu por um longo tempo na pasta Unfinished) na Habré sobre aspectos da implementação do software UART no MK do AVR. As questões levantadas por eles mesmos não são de interesse, mas são dadas respostas tão estranhas que eles consideraram seu dever fazer as explicações necessárias. O tópico está marcado, aqueles que desejam ler sobre “reis, repolho e sapatos”, ou seja, os requisitos das normas, lendo a documentação técnica (correta) e os registros na programação em linguagem assembly para o AVR, podem clicar no botão abaixo.

Vamos descrever a questão com mais detalhes - é possível implementar o IRPS (o nome usual para a interface, em nome do UART), em um AVR tipo MK (especificamente, era Tiny13) ao trabalhar com um gerador interno. O fato é que esse gerador não possui indicadores muito bons da precisão da retenção de frequência, motivo pelo qual essa pergunta surge. Devo fazer uma reserva imediatamente, não importando se consideramos uma implementação de software (como sugerido na postagem original) ou usamos blocos de hardware MK. Os resultados de um método (em termos de parâmetros de precisão no tempo) são quase completamente traduzidos para outro.

A questão fundamental é se o gerador interno pode fornecer a precisão de operação necessária, pois, no caso de uma resposta negativa a essa pergunta, novos estudos se tornam sem sentido. Para comparar as duas grandezas independentes, precisamos conhecer as duas, portanto, começaremos determinando a precisão necessária do confinamento de frequência e os recursos fornecidos por este MK em particular nesta parte. Uma observação importante para a frase anterior - isso não significa uma instância específica, “dada a nós em sensações”, mas um tipo específico de MK, que é apresentado por sua descrição técnica.

Para começar, encontraremos algo mais fácil de encontrar (bem, eu pensava assim) - requisitos para a precisão dos parâmetros de tempo da interface. Vamos abrir o padrão para RS232 e ver tudo o que você precisa imediatamente. Acabou que "você não pode simplesmente pegar e ..." porque o padrão é pago e todas as cópias na Web são ilegais. Ok, levamos a versão doméstica do GOST para a articulação C2 e não encontramos nenhum parâmetro de tempo, com exceção da duração da frente e do corte do pulso. No início, isso causou uma ligeira agitação - como poderia ser -, mas depois entendeu que a articulação C2 descreve apenas a parte da interface do IRPS e os requisitos devem estar na segunda. Em princípio, tudo é lógico, não está claro apenas por que isso não é explicitamente descrito no GOST, mas, no final, às vezes você pode pensar por si mesmo, embora ainda seja "de alguma forma não obtido de maneira ordenada".

Obviamente, conhecendo o protocolo de transmissão, é possível, por considerações gerais, encontrar a incompatibilidade máxima permitida entre as velocidades do transmissor e do receptor (0,5 / 9,5 = 5,2%), mas isso será uma investigação do cavalo esférico que você sabe onde, porque:

  1. os requisitos da norma podem e devem ser mais rígidos que um cálculo teórico semelhante da diferença máxima admissível;
  2. saber o número final de incompatibilidade não nos fornecerá o orçamento do transmissor e do receptor.

A perambulação na Internet levou ao AppNote da Atmel (bem, como ainda usamos o MK dessa empresa), ele fala diretamente de uma incompatibilidade permitida de 2% com um orçamento igual, o que leva a um requisito de precisão para manter a frequência do transmissor de 1%. Confiaremos em uma empresa respeitável e suporemos que eles tenham acesso a materiais classificados e esse número está correto, especialmente porque parece plausível. Entendo a vulnerabilidade de tal posição, mas para ser sincero, estou cansado de procurar a resposta exata para uma pergunta tão simples e mal posso esperar para passar para a próxima parte.

A próxima metade da resposta está dentro do MK e é determinada pela documentação técnica para ele. Primeiro, um pouco sobre o dispositivo do gerador interno, principalmente porque ele é mais ou menos descrito. O gerador usa uma corrente RC como elemento de temporização e, como a tarefa de formar um capacitor integrado de um capacitor exato e um resistor exato é muito trivial, a frequência final de instância para instância do MC varia significativamente. Para tornar esse parâmetro mais previsível, os fabricantes adicionaram um nó de hardware controlado por um byte de calibração. Esta unidade permite alterar a frequência do gerador em uma ampla faixa e, consequentemente, obter o valor desejado com uma precisão muito maior.

Seria interessante descobrir exatamente como o controle é implementado no hardware; vejo uma opção: controlar a tensão de carga do capacitor através do DAC ou controlar a tensão de comparação no comparador. Essas duas opções, no entanto, levam a uma não linearidade significativa das características de controle, embora sejam simples de implementar. Mas estabelecer a implementação interna do gerador não faz parte da nossa tarefa, estamos interessados ​​em seus parâmetros externos.

Então, abrimos a documentação (você pode abrir o arquivo no visualizador, mas eu tenho uma versão tipográfica da descrição impressa pelo próprio fabricante - sim, costumava ser) e procuramos a seção apropriada. Os parâmetros em que estamos interessados ​​estão na seção "Oscilador RC interno calibrado" e, em seguida, siga os links, se necessário. E aqui nós (com certeza, não tenho certeza sobre você) estávamos esperando a primeira decepção - trabalho com os produtos da Atmel há muito tempo (cerca de 15 anos) e sempre acreditamos que eles têm uma boa documentação para o MK. Segundo os psiquiatras, “não há pessoas saudáveis, não há pessoas inexploradas” e um estudo cuidadoso da seção relevante confirmou essa verdade, pois eu não pude notar essas falhas na documentação antes. Em minha defesa, só posso dizer que:

  1. Eu nunca usei um gerador interno nos dados MK, por isso não os estudei com muito cuidado;
  2. quando comecei a trabalhar com esses MKs (há mais de 10 anos), eu era jovem (bem, definitivamente mais jovem do que agora) e estúpido e não entendia completamente a necessidade de uma boa documentação (compreensível, abrangente e inequívoca);
  3. Estou pronto para me perdoar muito, simplesmente porque me perdoo muito, e todas as minhas falhas não são fatais (o último argumento é especialmente convincente, não é).

Assim, depois de terminar de espanar minha cabeça com cinzas, começarei a declarar minhas reivindicações na documentação e não há desculpas para o fabricante. Abrimos a seção acima e começamos a estudá-la cuidadosamente, indo para as páginas necessárias, se necessário (você ainda clica nos links). Juntos, procuraremos os seguintes parâmetros que caracterizam as características de tempo do gerador: precisão nominal, influência da tensão de alimentação, influência da temperatura e parâmetros de envelhecimento - este é o conjunto mínimo necessário para avaliar os parâmetros de precisão de qualquer gerador.

A primeira parte do balé de Marleson é a precisão nominal.

Imediatamente encontramos o parâmetro desejado - a tabela de precisão de ajuste do gerador, na qual vemos duas linhas “Calibrado na Fábrica” com o valor especificado ± 10% e “Calibração Manual” com o mesmo parâmetro ± 2%.

Com relação a esses dados, surgem várias perguntas imediatamente - o que elas significam e como são as medidas desse parâmetro. Para a primeira linha, a tabela indica a temperatura (do ambiente ou do próprio MK - não está claro, mas isso é um capricho de minha parte) e a tensão de alimentação, além disso, a nota diz (na minha opinião, é desnecessário) que essa medição é realizada em um ponto específico no espaço condições externas. Pode-se adivinhar que, nesse caso, devemos usar o fator de calibração registrado no fabricante, embora seja melhor indicar isso explicitamente na nota. Tudo é mais ou menos claro e é interpretado quase sem ambiguidade (embora, no contexto do estudo da documentação técnica, deva-se dizer que tudo é confuso e permite variações nas interpretações, e isso é inaceitável, mas, se o fizermos, o tópico de mais discussões simplesmente desaparecerá (e o que vem a seguir) escrever, não está claro, portanto, mostrar indulgência).

Mas com a segunda linha do caso, é pior - os limites das mudanças de temperatura e tensão de alimentação são dados e argumenta-se que, usando algum tipo de procedimento de calibração mágico, você pode obter resultados significativamente melhores do que os resultados de fábrica em toda a faixa. Minha pergunta surge imediatamente - se isso pode ser alcançado em qualquer lugar (a qualquer momento da temperatura e da fonte de alimentação) e o fabricante sabe como fazer isso, então por que ela não fez isso sozinha na calibração de fábrica em um ponto específico das condições? Voltamos à descrição do byte de calibração e observamos que ele recebe 128 valores e isso abrange a faixa de 50% a 200% da nominal, que corresponde a 150/128 ~ 1,17% da variação de frequência por unidade de valor de calibração, o que deve fornecer a precisão esperada melhor do que em 1% Mas devemos levar em conta que a característica de ajuste não é claramente linear e, na região de grandes valores de calibração, temos 60% / 32 ~ 2% da etapa (dados retirados do gráfico, eu expressei repetidamente minha atitude com relação a um método semelhante de representação de parâmetros técnicos, mas repito - isso é inaceitável o método, embora, é claro, seja melhor que nada), o que fornece uma precisão de 1% e se levarmos em conta a monotonicidade da característica de ajuste (sim, é o que a documentação diz, ela não é desenhada no gráfico, mas claramente indicada no texto. Recuso-me categoricamente a entender para para, eo mais importante porque, a empresa queria torná-lo uma lei de ajuste, mas conseguiu), que é claramente indicado nas orientações, é necessário considerar a precisão de 2% é bastante viável. Não gosto muito de ver o gráfico, mas isso não é necessário e os dados tabulares são suficientes. Nesta parte, a documentação deve ser considerada completamente compreensível e consistente, o critério de correção está fora do escopo de nossa competência.

A segunda parte do balé de Marleson. - a influência de condições externas.

E então começa "lixo, fumaça e sodomia". Em vez de tabelas de valores, somos convidados a ver imagens (por algum motivo, elas são chamadas de gráficos de valores típicos na documentação) e, como você sabe, "a principal vantagem da representação gráfica da informação é a sua visibilidade e não tem outras vantagens". Seria possível usar essas informações e remover os valores-limite do gráfico ("embora isso seja ofensivo para a equipe") se esse gráfico não fosse fornecido na seção "Características típicas". Eu não sei como alguém, pessoalmente, estou profundamente convencido de que, para indicar significados típicos (ou típicos, não sei como ser mais corretos, em um filme eles disseram "aparência típica"), pelo menos na forma de gráfico, mesmo na tabela, isso simplesmente não indica nada. Eles não podem ser orientados no projeto, porque esses parâmetros não estão claros do que significam e qualquer desvio dos valores típicos é aceitável, em contraste com os valores mínimo e máximo, cuja transição indica um mau funcionamento do dispositivo.

Bem, nós passamos, tentaremos extrair pelo menos algumas informações e veremos que, quando a temperatura mudar de -40 a + 80 ° C, a frequência do gerador muda em ± 4%. Uma imagem semelhante com a tensão de alimentação - apenas gráficos típicos e o erro resultante em -6 + 2% de 3,3 a 5,5. Os dados sobre o envelhecimento do gerador simplesmente não são fornecidos, o que, em geral, é lógico, pois no contexto dos parâmetros já fornecidos, a precisão de um por cento por 5 anos (valor característico do silício) não incomoda ninguém.

Agora, temos todos os dados para responder à nossa pergunta inicial - durante a calibração de fábrica, o gerador não atende aos requisitos de interface para precisão, quando calibrado para condições específicas de aplicação - ele atende aos requisitos de limite, mas não atende ao padrão. Também deve ser levado em consideração que, se a calibração da tensão de alimentação e de um MK específico puder ser feita na fabricação do dispositivo e esperar que eles não mudem com o tempo, a temperatura poderá ser levada em consideração apenas em tempo real e requer um padrão de tempo externo de precisão adequada. Como o desenvolvimento de dispositivos deve ser guiado pela regra "acreditamos em Deus, tudo o mais exige prova" e não provamos a possibilidade de atender aos requisitos, a resposta correta é que é impossível garantir a implementação do IRPS que atenda aos requisitos do padrão neste MC com um gerador interno. Observe que fizemos a conclusão acima ao analisar a documentação e a formulamos de maneira a enfatizar que, em uma instância específica do MK, tudo pode acontecer e acontecerá se as estrelas subirem com sucesso. Ou seja, nossa conclusão contradiz o post mencionado anteriormente, como isso poderia acontecer, porque tudo funciona muito bem para uma pessoa - vamos descobrir.

Agora as críticas ao post acima começarão. Primeiro, vamos pensar em como podemos garantir que o dispositivo seja verificado quanto à conformidade com os requisitos de uma interface específica. Eu posso sugerir as seguintes maneiras:

  1. Uma boa maneira é medir os parâmetros críticos da interface do dispositivo e compará-los com os requisitos da norma - isso pode ser feito usando instrumentos universais (no nosso caso, o osciloscópio e a duração do intervalo de bits ou a transmissão completa) ou usando um dispositivo especializado certificado para testar essa interface.
  2. Fulano - para organizar a interação com outro dispositivo que implementa a parte de resposta da interface e é comprovado (atende aos requisitos do padrão). Obviamente, essa verificação é completamente insuficiente e pode ser aplicada mais para confirmar o mau funcionamento do dispositivo em teste, mas faz pelo menos alguma coisa.
  3. O lado ruim é implementar independentemente a parte da resposta da interface (no mesmo dispositivo ou em outro) e interagir com ele. Como os dois dispositivos obviamente não estão comprovados, a utilidade dessa verificação é muito, muito duvidosa. Um bom exemplo dessa abordagem é o "eco" em um canal serial, que não prova nada e relata pouco mais que nada sobre a velocidade do dispositivo, em princípio, não está quebrado e é capaz de transmitir alguma coisa.
  4. Uma maneira terrível é tomar como testador um dispositivo que não atenda aos requisitos da norma (ou melhor, ao contrário deles) e funcionar, como no parágrafo anterior.

É o último método usado no posto em consideração - é implementado um receptor de software de canal serial, que, contrariamente aos requisitos da norma, altera sua frequência, adaptando-se ao sinal de entrada (especificamente, a duração do bit inicial), o que possibilita receber de forma estável um sinal de baixa qualidade em termos de parâmetros de tempo. Isso não quer dizer que isso nunca deva ser feito; além disso, em modems analógicos, foi adotado o ajuste da velocidade de entrada, que foi implementado de maneira semelhante, mas estava precisamente mudando de frequência alterando o divisor, e esse claramente não é o nosso caso. E é nesta versão que tudo é perfeitamente obtido e a informação é transmitida de forma estável sob quaisquer condições externas. Portanto, se falarmos sobre a possibilidade de transmitir informações entre dois MCs operando a partir de geradores internos usando uma interface remotamente reminiscente do IRPS, a resposta é sim. Se estamos falando sobre interagir com dispositivos externos que atendem aos requisitos da norma e nada mais, esperamos muitas surpresas desagradáveis.

A conclusão geral do acima exposto:

  1. ao projetar dispositivos, você deve se concentrar na documentação (RTFM),
  2. você precisa estudar a documentação e interpretar corretamente o que lê (RTFMF),
  3. tenha em mente que, em nosso tempo, a documentação pode conter mal-entendidos, imprecisões (e até erros), portanto
  4. verifique as informações recebidas quanto à consistência e credibilidade e
  5. use as informações obtidas experimentalmente apenas para confirmar as conclusões obtidas na análise da documentação, enquanto
  6. escolha cuidadosamente os métodos de experimentos para testar o equipamento para obter um resultado confiável.

Bem, em conclusão, como prometido, um pequeno montador. Eu me permiti reescrever o trecho de código citado pelo autor de forma normal, porque o assembler incorporado ao GCC não passa de uma zombaria do programador, posso citar. Não, claro, eu entendo que os desenvolvedores do compilador foram guiados por boas razões, mas o resultado se assemelha dolorosamente à frase "bem, funciona".

.equ delay=15 TX_Byte: cli ; ld r18,Z+ ; cp r18,r1 ; breq Exit_Transmit ; dec r1 cbi port, TX_line Delay_TX: ldi r16,delay Do_Delay_TX: nop dec r16 brne Do_Delay_TX TX_Bit: sbrc r18,0 sbi port,TX_line sbrs r18,0 cbi port,TX_line lsr r18 lsr r17 brcs Delay_TX sbi port, TX_line ldi r16,delay Stop_Bit_TX: nop dec r16 brne Stop_Bit_TX Sei 

E imediatamente um erro no programa chama sua atenção - na linha 3 (comentado) o valor do registro 1 deve ser zero, mas a atribuição não está explicitamente escrita na função. Após a conclusão de um ciclo de transferência de byte único, esse valor é garantido pela linha 12, mas não na primeira passagem. Portanto, a inicialização deve ser adicionada, o que exigirá um aumento no tamanho do código.

A segunda desvantagem é a formação real do nível nas linhas 4-7, uma vez que o método adotado pelo autor para emitir o próximo bit levará ao jittering frontal por 2 ciclos de relógio em várias transições (0-1 e 1-0), o que implicará um aumento nos requisitos para a precisão da retenção de frequência. Não que isso daria uma influência muito forte, mas se você pode corrigir uma falha sem estender o programa, por que não - veja a epígrafe. A versão original teve 4 palavras e foi realizada em 4 compassos, a nova com 4 palavras e foi executada nos mesmos 4 compassos. Sim, a versão corrigida requer um estudo mais aprofundado da arquitetura MK, mas quem disse que seria fácil. Por outro lado, na primeira versão, a modificação da porta é atômica e, na segunda, não é, neste caso, não importa (proibimos explicitamente interrupções), mas o sedimento permanece. Se o MK em questão tivesse um processador de bits real, como na arquitetura 51, poderíamos escrever um fragmento ideal combinando todas as vantagens de ambas as abordagens (e até um pouco mais curtas), mas o que podemos sonhar com um sonho?

A terceira desvantagem é a questão de mais estilo. Expressei repetidamente minha atitude em relação às constantes mágicas que vemos no preâmbulo deste programa. Enfatizo mais uma vez - pelo fato de o autor definir uma constante no preâmbulo do programa, e não diretamente no operador, a "magia comum das ruas" não vai a lugar algum. O fato é que devemos apresentar explicitamente ao leitor o método de formação de um valor específico, e não criar sinônimo para o valor obtido de maneira desconhecida. Você pode, é claro, escrever um comentário em uma linha com um valor no qual especificar a fórmula de cálculo, mas é melhor usar explicitamente a fórmula de cálculo para formar a constante e então você não precisa de um comentário (é claro, com os nomes falantes das constantes aplicadas). Isso é feito no texto abaixo e observe que convertemos para um número inteiro apenas no último momento e arredondamos corretamente, o que nos permite não perder a precisão do resultado.

Há outro erro - a duração do bit inicial é um pouco diferente do intervalo de bits para os dados. Embora o desvio não seja muito significativo (3 ciclos de clock), no entanto, em altas taxas de bits, onde o intervalo de bits dura cerca de 90 ciclos de clock, esse já é um erro de porcentagem, o que é inaceitável. Esse erro pode ser facilmente corrigido adicionando comandos para gerar um atraso adicional, mas isso aumentará a duração do programa, para que apenas fixemos sua presença e depois garantamos que a arquitetura correta do programa (ou seja, mesmo a curto prazo se aplique) seja eliminada automaticamente.

Bem, agora que corrigimos os erros (exceto o último), tentaremos melhorar o programa no sentido do critério principal (obter um registro, neste caso em particular) - o comprimento do código. A primeira coisa que chama a atenção é a presença de dois atrasos, o que é ruim porque viola o princípio DRY (requisito geral) e aumenta o tamanho do código (requisito específico). Seria possível organizar esse fragmento na forma de um subprograma e ainda assim ganharíamos, pois adicionamos 3 palavras de código (1 para cada chamada em dois lugares e 1 para retorno) e economizamos 4, mas há uma maneira muito mais bonita - elegante organização do ciclo de transmissão de bytes, que pode ser visto no texto a seguir.

 .equ delay=15 TX_Byte: cli sec ;   - clt ;  - TransBit: ;    in r17,port bld r17,Tx_line out port,r17 Delay_TX: ;     ldi r17,delay Do_Delay_TX: nop dec r17 brne Do_Delay_TX TX_Bit: bst r16,0 ror r16 clc brne TransBit ;    brcs TransBit ;  - Exit_Transmit: Sei 

Observe como usamos o byte transmitido junto com o bit de transporte como um contador de bits, uma solução bonita, mas tem uma desvantagem - a duração do último bit de dados será vários (2 ciclos) mais longa que o restante, devido ao atraso na transição. Se estivéssemos falando de um bit de parada, "não se preocupe", pois não recebemos o intervalo mínimo entre as transferências, mas esse é um pouco significativo e acabamos de criticar o programa original por esse comportamento. Não seremos comparados ao caráter bíblico da parábola do mote aos olhos dos outros e tomaremos medidas para eliminá-lo. Esse fenômeno pode ser facilmente compensado com a introdução de um atraso de 2 medidas, mas o comprimento do código aumentará e esse é um parâmetro-chave. Portanto, vamos seguir o caminho clássico e alterar o tempo da memória - usamos um registro separado para organizar o contador de bits transmitidos e obtemos exatamente os mesmos intervalos de bits com o mesmo tamanho de código.

A próxima melhoria está associada à formação da duração do intervalo de bits, que no programa original é realizado em um ciclo de 4 ciclos. Se o fizermos em três horas (o menor possível neste MK), podemos salvar um byte de código e potencialmente melhorar os parâmetros de precisão, pois a discrição do atraso se tornará menor (o desvio não excede a metade do tamanho do discreto com arredondamento adequado). Mas deve-se ter em mente que, em um caso específico, podemos perder a precisão, tudo depende dos dados de origem. Outra circunstância que poderia afetar a escolha de uma duração desse ciclo - o tamanho máximo de atraso para um contador de bytes é de 256 valores - para a opção disponível, você pode usar velocidades de 9600 bauds ou mais, mas com um atraso de 3 ciclos isso não é possível. Seria muito bom refletir essa circunstância (a velocidade mínima permitida da porta) nos comentários do programa e, ao mesmo tempo, exibir uma mensagem de aviso em caso de violação deste requisito. Bem, faça as modificações apropriadas nas macros de formação de parâmetro para formar um atraso, sem esquecer de usar nomes "falantes" para indicar variáveis.

 .equ Freq = 8000000 .equ BaudRate = 115200 .equ PayLoad = 9 ;     .equ CycleTime = 3 ;    .equ delay=((Freq*2/BaudRate - PayLoad*2)+CycleTime)/(CycleTime*2) TX_Byte: cli ldi r18,10 sec ;   - clt ;  - TransBit: in r17,port bld r17,Tx_line out port,r17 Delay_TX: ldi r17,delay Do_Delay_TX: dec r17 brne Do_Delay_TX TX_Bit: bst r16,0 ror r16 dec r18 brne TransBit Exit_Transmit: sei 

Agora, vejamos o resultado - o tamanho do código diminuiu de 20 para 16 palavras (se levarmos em conta apenas a transmissão em si, e ainda mais impressionante - de 18 para 14, o jitter das frentes desapareceu (é claro, apenas o componente de jitter, causado pelos recursos do programa, no componente de hardware, nós não estamos violando), a precisão da manutenção de intervalos de tempo melhorou, o programa tornou-se mais visível e mais fácil de entender (devido a comentários, pois mesmo um programa de montagem bem escrito geralmente não é auto-documentado).

A conclusão da última parte é que, se vamos estabelecer recordes mundiais na programação em linguagem assembly, devemos estudar a arquitetura de um MK em particular e aplicar o conhecimento obtido para obter o resultado ideal, prestando atenção a todas as sutilezas.

Bem, e em conclusão - a tarefa de escrever código do tamanho mínimo hoje em dia parece um tanto artificial, mas, inesperadamente, recebe confirmação de sua vitalidade. No final do ano passado (2016, quanto tempo esse post aguardava a sua vez), foi anunciado um novo MK da família MSP430, que junto com o preço excepcionalmente baixo (26 centavos - estamos aguardando a aparência dos dispositivos chineses baseados nele) tem um tamanho de memória de programa excepcionalmente pequeno - 512 byte (não, não me enganei, a letra "k" imediatamente após o número não é). Portanto, o tamanho do código pode ser crítico ao usar este dispositivo, e geralmente escrever programas extremos exige um estudo aprofundado do MK, e "o trabalho em si é uma bênção".

Source: https://habr.com/ru/post/pt412959/


All Articles