Relógio de tempo real

Registos RTC, formatos BCD, leituras coerentes e causas de interrupção.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

Para ler 07:32:59, precisas de obter horas, minutos e segundos de registos diferentes. O RTC conserva a data e a hora com alimentação própria e continua a contar mesmo quando o computador está desligado; o timer usado para contar ticks mede apenas intervalos de execução. A hora do RTC pode datar uma partida; os ticks podem medir a sua duração.

Endereço e dados

O RTC tem registos internos. Para aceder a um deles, seleciona o índice pela porta 0x70 e transfere o valor pela porta 0x71. A porta de endereço também tem um bit relacionado com o controlo de NMI no PC; conserva a política exigida pelo ambiente em vez de o alterar sem intenção.

ÍndiceConteúdo
0x00, 0x02, 0x04Segundos, minutos e horas
0x01, 0x03, 0x05Campos do alarme
0x07, 0x08, 0x09Dia do mês, mês e ano
0x0ARegisto A, atualização e taxa periódica
0x0BRegisto B, formatos e ativação de eventos
0x0CRegisto C, causas de eventos
0x0DRegisto D, validade da memória e hora

Escrever 0x0A em 0x70 e ler 0x71 consulta A. Uma leitura de 0x71 sem selecionar antes o índice pode consultar o registo que outra operação deixou selecionado. Seleção e transferência formam uma operação lógica que deve ser protegida de acessos concorrentes segundo o ambiente. Para ler os segundos, por exemplo, escreve 0x00 em 0x70 e lê o valor em 0x71; para os minutos, repete com 0x02.

BCD e formato das horas

No registo B, DM, bit 2, seleciona binário quando vale 1 e BCD quando vale 0. O bit 1 seleciona 24 horas quando vale 1, ou 12 horas quando vale 0.

Em BCD, cada nibble representa um algarismo decimal. O valor 0x59 representa 59, não 89. A conversão é:

decimal=10⋅(value≫4)+(value&0x0F).decimal=10\cdot(value\gg4)+(value\mathbin{\&}\texttt{0x0F}).

Para 0x59, o nibble alto vale 5 e o baixo vale 9, por isso o resultado é 10 vezes 5 mais 9, ou 59.

Esta fórmula assume dois algarismos BCD válidos. Um nibble acima de 9 é inválido. Em binário, 0x3B já representa 59 e não deve ser convertido por BCD.

No formato de 12 horas, o bit 7 do campo de horas marca PM, por isso retira-o antes de converter os algarismos. Para obter horas de 0 a 23, transforma 12 AM em 0 e soma 12 às horas PM depois de transformar 12 em 0. Assim, 12 AM dá 0, 12 PM dá 12 e 9 PM dá 21.

Não mudes o formato do RTC apenas para simplificar a leitura. Essa alteração afeta outros utilizadores do dispositivo e exigiria transformar os valores de tempo e alarme existentes.

Ler uma hora coerente

Os registos atualizam-se de forma assíncrona, por isso se leres os segundos de 07:32:59 e os minutos depois da passagem para 07:33:00, constróis 07:33:59, uma hora que o relógio nunca mostrou. Cada campo é válido isoladamente; a coerência exige que os campos pertençam à mesma atualização.

O registo A tem UIP, bit 7. O RTC assinala a atualização 244 µs antes de a começar e limpa UIP quando termina. Há por isso uma janela curta entre veres UIP a 0 e o início da escrita interna. Esperar UIP a 0 e depois ler os campos pressupõe que terminas antes da próxima atualização e que não és suspenso demasiado tempo durante a sequência.

Uma estratégia de polling reforça a coerência com repetição:

  1. Espera UIP a 0, com um limite de espera.
  2. Lê todos os campos e a configuração necessária para os interpretar; volta a consultar UIP e rejeita a leitura se estiver ativo.
  3. Repete a leitura a partir de UIP a 0.
  4. Aceita apenas duas fotografias consecutivas iguais e obtidas sem atualização assinalada; caso contrário, tenta novamente.

Esta estratégia depende de acessos curtos, de não haver outro programa a reconfigurar o relógio e de uma política de tentativas. Não dá ao programa controlo sobre os registos internos. Outra opção é usar a interrupção de fim de atualização e ler dentro do intervalo disponível antes da atualização seguinte.

O bit SET de B inibe atualizações para permitir escrever os campos de data e hora. Usá-lo descuidadamente para ler altera o funcionamento do dispositivo. Desativar interrupções num núcleo também não é uma solução universal para acessos concorrentes em vários núcleos.

Três causas, uma IRQ

O RTC pode produzir eventos periódicos, alarmes e fim de atualização. Todos usam IRQ8. B controla quais geram interrupções:

Bit de BAtiva
6, PIEEventos periódicos
5, AIEAlarmes
4, UIEFim de atualização

A contém o seletor de taxa periódica. Para os valores usuais do seletor RS entre 3 e 15, a frequência é 32768/2RS−132768/2^{RS-1} Hz. Por exemplo, RS = 6 dá 1024 Hz e RS = 15 dá 2 Hz. Preserva os bits superiores do registo ao alterar o seletor e não extrapoles a fórmula para os códigos especiais 0, 1 e 2.

O registo C assinala PF, AF e UF nos bits 6, 5 e 4. IRQF no bit 7 indica o pedido. Ler C limpa as causas assinaladas e permite que a linha deixe de manter esse pedido. Uma rotina que nunca lê C pode atender o primeiro evento e deixar de receber os seguintes.

Guarda o byte lido e testa cada causa com um if independente, porque com C = 0xD0 temos IRQF, PF e UF ativos e um else if trataria só um dos dois eventos. Os flags podem registar eventos mesmo quando a respetiva geração de interrupção está desativada; interpreta-os com a configuração aplicável.

Alarmes e validade

Os três campos de alarme comparam segundos, minutos e horas. Um campo com os dois bits superiores a 1 representa “qualquer valor”. Com hora e minuto indiferentes e segundos 0, o alarme coincide no início de cada minuto. Com os três campos indiferentes, coincide a cada segundo, se a geração de alarme estiver ativa.

O registo D tem VRT no bit 7. Se estiver a 0, a validade da memória e da hora é duvidosa, por exemplo após falha da alimentação de reserva. Converter bytes para uma data bem formada não prova que o relógio esteja certo.

Para alterar um bit de B, lê o valor anterior, modifica apenas a máscara pretendida e repõe-o quando terminares. Limpar PIE não deve mudar DM nem o formato de 12/24 horas. A limpeza final tem duas partes: desativar a causa no RTC e remover a subscrição no Minix.

Exercícios

Converter BCD e PM

O RTC está em BCD e formato de 12 horas. O byte de horas vale 0x89, com bit 7 a indicar PM. Qual é a hora em formato de 0 a 23?

Pista
Separa primeiro o bit PM.
Solução

0x89 contém PM e os algarismos BCD 09. Como é 9 PM, a conversão dá 9 + 12 = 21 horas. Não incluas o bit PM na conversão BCD.

Erros frequentes

Converter 0x89 inteiro como BCD ou tratar o byte como binário.

Voltar à explicação
Atender causas simultâneas

O handler lê C e obtém 0xE0. Quais são as causas assinaladas e por que deve usar o byte guardado para as tratar?

Pista
C tem IRQF no bit 7 e causas nos bits 6, 5 e 4.
Solução

IRQF está ativo e as causas são PF, periodic, e AF, alarm. UF não está ativo. A leitura de C limpa flags; reler C para decidir a segunda causa pode já não a mostrar. Guarda 0xE0 e usa if independentes para PF e AF.

Confere a tua resposta:

  • Identifiquei PF e AF.
  • Guardei o resultado da leitura de C.
  • Usei testes independentes e expliquei o efeito de limpeza.

Erros frequentes

Tratar só uma causa com else if ou omitir a leitura de C e deixar o pedido ativo.

Voltar à explicação
Reconstruir uma leitura impossível

A hora muda de 12:59:59 para 13:00:00. Lês horas antes da mudança e minutos e segundos depois. Que hora obténs e por que consultar UIP apenas uma vez pode não bastar?

Pista
O campo de horas veio da fotografia antiga.
Mais uma pista

O processo pode ser suspenso entre a consulta e as leituras.

Solução

Obténs 12:00:00, quase uma hora atrás da nova hora. Os campos pertencem a atualizações diferentes. UIP a 0 numa consulta anterior não impede uma atualização após suspensão do processo. Uma estratégia usa leituras completas repetidas e coerentes, ou uma leitura após fim de atualização, respeitando o intervalo de tempo disponível.

Confere a tua resposta:

  • Construí uma hora que não corresponde ao instante real.
  • Expliquei a atualização entre campos.
  • Propus uma estratégia com hipóteses e repetição.

Erros frequentes

Supor que registos distintos são lidos como uma fotografia atómica ou que converter BCD resolve coerência.

Voltar à explicação
Distinguir alarme e periodicidade

Em formato de 24 horas e BCD, os campos do alarme são hora 0xC0, minuto 0xC0 e segundo 0x30, com AIE ativo. Quando coincide o alarme? Isso equivale a configurar PIE para 2 Hz?

Pista
Os dois bits superiores a 1 tornam o campo indiferente.
Solução

O alarme coincide no segundo 30 de cada minuto, qualquer que seja a hora. Não é PIE a 2 Hz: essa causa produz dois eventos periódicos por segundo, sem comparar campos do alarme. AF e PF permitem distinguir as causas no registo C.

Confere a tua resposta:

  • Reconheci hora e minuto indiferentes.
  • Obtive segundo 30 de cada minuto.
  • Distingui AIE/AF de PIE/PF.

Erros frequentes

Converter 0xC0 como um número BCD ou tomar alarme repetido por frequência periódica.

Voltar à explicação
Converter 12 AM para 24 horas

O RTC está em BCD e 12 horas. O byte de horas vale 0x12, sem bit PM. Qual é a hora em formato de 0 a 23?

Pista
Separa o formato antes de converter.
Solução

Os algarismos BCD dão 12 e a ausência de PM indica AM. 12 AM transforma-se em 0. Sem esta regra, a leitura repetiria o 12 do meio-dia.

Erros frequentes

Converter 0x12 para 12 horas ou incluir um bit PM inexistente.

Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.