# Relógio de tempo real

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

Página: https://resumos.rgo.pt/cadeiras/lc/relogio-tempo-real/

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.

| Índice | Conteúdo |
| --- | --- |
| `0x00`, `0x02`, `0x04` | Segundos, minutos e horas |
| `0x01`, `0x03`, `0x05` | Campos do alarme |
| `0x07`, `0x08`, `0x09` | Dia do mês, mês e ano |
| `0x0A` | Registo A, atualização e taxa periódica |
| `0x0B` | Registo B, formatos e ativação de eventos |
| `0x0C` | Registo C, causas de eventos |
| `0x0D` | Registo 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\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.

![Leitura partida: segundos 59 lidos antes da atualização de 07:32:59 para 07:33:00 e horas 07 com minutos 33 lidos depois, formando 07:33:59, uma hora que não correspondeu ao relógio em nenhum instante da leitura.](https://resumos.rgo.pt/cadeiras/lc/relogio-tempo-real/figura-1.svg)

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 B | Ativa |
| --- | --- |
| 6, PIE | Eventos periódicos |
| 5, AIE | Alarmes |
| 4, UIE | Fim 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/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](https://resumos.rgo.pt/cadeiras/lc/relogio-tempo-real/#bcd-e-formato-das-horas)

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](https://resumos.rgo.pt/cadeiras/lc/relogio-tempo-real/#tr%C3%AAs-causas-uma-irq)

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](https://resumos.rgo.pt/cadeiras/lc/relogio-tempo-real/#ler-uma-hora-coerente)

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](https://resumos.rgo.pt/cadeiras/lc/relogio-tempo-real/#alarmes-e-validade)

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](https://resumos.rgo.pt/cadeiras/lc/relogio-tempo-real/#bcd-e-formato-das-horas)
