CardOS: Escrevendo um SO para o Cardputer

Traduções: en
25/05/2024

Recentemente eu comprei um Cardputer da M5Stack. O que me motivou foi que eu conhecia outras pessoas pessoalmente que também tinham ele, então eu teria com quem compartilhar o meu progresso, mas eu estava preocupado em acabar sendo só mais uma placa que ficaria guardada no meu armário para sempre sem ser tocada. De qualquer forma eu resolvi arriscar.

Assim que eu peguei ele nas mãos, ele me conquistou. Ele tem tudo que é necessário para ser um computador: teclado completo para entrada, tela para saída, bateria para portabilidade, entrada de cartão microSD para armazenamento persistente, além de WiFi e Bluetooth para conectividade. O fato de ele ser um computador muito limitado, e tão minúsculo, só fez eu achar ele mais charmoso.

Eu tenho muito interesse na idea de implementar um sistema completo do zero para entender todas as diferentes camadas e interações. Eu também sempre quis fazer o meu próprio sistema operacional (SO). Então antes de eu perceber, eu já tinha decidido em um objetivo: Eu iria fazer meu próprio SO do zero para o Cardputer.

Mas quando eu digo do zero, eu não quero dizer necessariamente começar com um arquivo vazio, mas que eventualmente todo código tem que ter sido escrito por mim. Uma coisa que eu lembro dos vídeos do Andreas Kling (criador do SerenityOS) é que ele não começou a escrever o SO dele pelo bootloader, mas pela interface de usuário, e que isso o permitiu ver imediatamente o efeito das mudanças que ele fazia e trabalhar em pequenos passos em direção ao SO completo. Eu também lembro do Tarn Adams (co-criador do Dwarf Fortress) dando a mesma dica sobre como manter motivação no desenvolvimento de um jogo. E ambas são pessoas que eu admiro profundamente, então eu segui o conselho deles.

Com isso em mente, eu comecei meu projeto a partir de uma demo do Cardputer que já tinha tela e teclado funcionais, e eu escrevi um shell simples em cima dela.

Só depois disso que eu comecei a implementar meu próprio suporte ao teclado e à tela do zero e remover o código da demo.

Fazendo a tela funcionar

Implementar suporte para a tela foi muito mais complicado do que eu esperava e eu fiquei travado por um tempo. Nessa etapa eu já tinha implementado meu próprio suporte para o teclado, testado ele e ele tinha funcionado. Mas eu não conseguia fazer a tela nem mesmo acender, mesmo depois de ter lido o datasheet dela com cuidado várias vezes e implementado todo o procedimento de inicialização.

Eventualmente eu dei um passo para trás e testei funcionalidades mais básicas e percebi que meu código para configurar GPIOs como saída não estava funcionando. Isso foi uma surpresa porque isso era necessário para o teclado, e eu já tinha testado ele. Mas o que eu não tinha percebido é que apesar de o meu código ser capaz de ligar e desligar pinos de saída para escanear o teclado, ele estava dependendo implicitamente do código de inicialização da demo para que os pinos de saída funcionassem, e por isso quando eu troquei todo esse código pela minha própria implementação da tela nem a tela nem o teclado funcionavam.

Mas como muitas vezes é o caso em comportamentos inexplicáveis, esse não era o único problema. Para minha surpresa, o manual do ESP32 apresenta o endereço errado para um dos registradores necessários para configurar GPIOs. Por sorte ele também mostra o endereço correto em outra página, e eventualmente eu percebi essa diferença.

Então depois que eu implementei o suporte para habilitar GPIOs de saída e corrigi o endereço do registrador, eu consegui consertar o suporte do teclado para ser completamente auto-contido, e consegui finalmente, depois de muito suor, implementar o suporte para a tela e remover a dependência a bibliotecas externas.

Essa foi a maior conquista do projeto até agora e eu estou muito orgulhoso!

Estado atual

Esse é o estado atual do cardOS:

{image}/cardos_demo.mp4

Em outras palavras, ele tem suporte a teclado e tela sem depender de bibliotecas externas. A comunicação com a tela é bem lenta, então tem bastante oportunidade para melhorias futuras 🙂. Ele tem um shell com alguns comandos, incluindo help para mostrar os comandos, clear para limpar a tela, read para ler um endereço de memória arbitrário e led para mudar a cor do LED RGB integrado. É possível navegar pelo histórico de comandos do shell e repetir comandos anteriores. E quando o terminal enche a tela ela é limpa automaticamente.

Eu também passei um tempo consertando problemas. Nesse ponto o SO pareceu finalmente estar usável, então eu marquei ele v0.1.

Próximos passos

A próxima coisa em que eu estou trabalhando é em parar de usar a toolchain do Arduino. O principal motivo é que ela adiciona código implicitamente ao binário quando usada, e eu quero continuar removendo dependências do meu código.

Além disso, o Arduino basicamente força o uso de um único arquivo de código fonte. O fonte do cardOS é atualmente um único arquivo de 1900 linhas (sendo que 600 são a estrutura contendo os caracteres da fonte) e eu estou começando a me perder nele, então é uma boa hora para separar o código em múltiplos arquivos.

Finalmente, o Arduino usa C++, e já que eu estou programando em C, essa mudança me permitiria usar um compilador de C, que fornece mensagens de erro melhores.

Depois disso eu vou continuar trabalhando para fazer o cardOS ser um SO de verdade. Eu quero que ele passe a sensação de um computador hackeável, então minha meta é que seja possível abrir um editor de texto, editar um arquivo de inicialização de shell, salvar, reiniciar e ver os efeitos dessa mudança. Isso já me da trabalho suficiente: Eu preciso criar um editor de texto, uma linguagem de script de shell, e implementar suporte ao leitor de cartão microSD e a um sistema de arquivos.

Mais no futuro eu estou bastante curioso sobre implementar suporte ao WiFi e quem sabe ser possível mandar e receber mensagens de IRC, se for possível. Tenho certeza que vai ser difícil, mas também vai ser divertido 😃.

E é sobre isso: diversão! Fazem dois meses desde que eu comecei o projeto e eu posso dizer confiança que esse é o projeto em que eu mais me diverti de todos. Então enquanto ele continuar divertido eu vou continuar mexendo nele. Mas sem pressa para acabar, eu estou aproveitando a viagem 🙂.