Exemplo mínimo executável newlib
Aqui, forneço um exemplo altamente automatizado e documentado que mostra newlib em ação no QEMU .
Com o newlib, você implementa suas próprias chamadas de sistema para sua plataforma baremetal.
Por exemplo, no exemplo acima, temos um programa de exemplo exit.c
:
#include <stdio.h>
#include <stdlib.h>
void main(void) {
exit(0);
}
e em um arquivo C separado common.c
, implementamos o exit
com semi - hospedagem ARM :
void _exit(int status) {
__asm__ __volatile__ ("mov r0, #0x18; ldr r1, =#0x20026; svc 0x00123456");
}
Os outros syscalls típicos que você implementará são:
write
para produzir resultados para o host. Isso pode ser feito com:
- mais semi-hospedagem
- um hardware UART
brk
para malloc
.
Fácil no baremetal, já que não precisamos nos preocupar com paginação!
TODO Gostaria de saber se é realista alcançar a execução de syscalls de agendamento preventivo sem entrar em um RTOS completo, como Zephyr ou FreeRTOS .
O interessante do Newlib é que ele implementa todas as coisas específicas que não são do SO, como string.h
para você, e permite implementar apenas os stubs do SO.
Além disso, você não precisa implementar todos os stubs, mas apenas os necessários. Por exemplo, se o seu programa precisar apenas exit
, você não precisará fornecer a print
.
A árvore de origem Newlib já possui algumas implementações, incluindo uma implementação de semi-hospedagem do ARM newlib/libc/sys/arm
, mas, na maioria das vezes, você precisa implementar suas próprias. No entanto, fornece uma base sólida para a tarefa.
A maneira mais fácil de configurar o Newlib é criar seu próprio compilador com o crosstool-NG, basta dizer que você deseja usar o Newlib como a biblioteca C. Minha instalação lida com isso automaticamente com esse script , que usa as configurações newlib presentes em crosstool_ng_config
.
Eu acho que C ++ também funcionará, mas TODO testá-lo.