Isenção de responsabilidade. O autor não defende o uso de sistemas operacionais multitarefa para microcontroladores.
A vida impiedosamente força o uso de sistemas operacionais (SO) para microcontroladores. Há um número imenso desses sistemas no mercado. Os desenvolvedores de sistemas operacionais, competindo entre si, estão tentando maximizar a funcionalidade de seus produtos. Isso geralmente leva a um aumento no "peso" do sistema e também aumenta significativamente o "limite de entrada" para um programador que desenvolve software para sistemas embarcados.
Para não me atormentar com a escolha do SO para meus projetos, assim como não obscurecer minha mente com o estudo do produto de outra pessoa, bem como dominar a técnica de escrever aplicativos incorporados para sistemas operacionais e também descobrir o que é, decidi escrever meu SO. Não é cheiro.
O SO proposto (SO, o idioma não se atreve a chamar seu SO, e especialmente o OSRV) coopera com tarefas estáticas. Como observado acima, não sou um defensor do uso do SO para microcontroladores, mas ainda mais não sou um defensor do uso de sistemas operacionais preventivos em microcontroladores. A multitarefa preemptiva, comparada à cooperativa, não é apenas procedimentos complicados de alternância de contexto, mas também sincronização de threads com uso intenso de recursos. O uso de tarefas dinâmicas também complica significativamente o sistema operacional.
O sistema operacional foi desenvolvido para o processador da família Cortex-M0. Com pequenas alterações nas regras para salvar e restaurar o contexto, ele pode ser usado para outros tipos de processadores.
Código fonte
Arquivo IntorOS.h#ifndef __INTOROS_H #define __INTOROS_H
Arquivo IntorOS.c #define _INTOROS_C #include "stm32l0xx.h" #include "IntorOS.h"
Arquivo IntorOSSleepIAR.s #define SHT_PROGBITS 0x1 EXTERN KolvoTask EXTERN TaskList EXTERN TaskNum PUBLIC Sleep SECTION `.text`:CODE:NOROOT(2) THUMB
Arquivo IntorOSSleepGCC.s .cpu cortex-m0 .text .cfi_sections .debug_frame .section .text.Sleep,"ax",%progbits .align 1 .global Sleep .syntax unified .thumb .thumb_func .type Sleep, %function .extern KolvoTask .extern TaskList .extern TaskNum .cfi_startproc
Constantes de compilação do SO
#define IntorOSMaxKolvoZadach (2)
Por motivos religiosos, não posso usar a alocação dinâmica de memória; portanto, a quantidade de memória necessária deve ser especificada no estágio de compilação.
Serviços de SO
void InitTask(void (*TaskPointer)(void), unsigned long Stek);
Inicialização de tarefas. A tarefa é executada na forma de uma função, um ponteiro para uma função é passado para o procedimento de inicialização. Durante a inicialização, você deve especificar o tamanho da pilha alocada para a tarefa. A ordem em que as tarefas são inicializadas determina seus identificadores. A tarefa inicializada primeiro possui o identificador 0. Se você especificar o tamanho total da pilha maior que o reservado, ocorrerá um erro. Quando a tarefa é inicializada, o ponteiro para a pilha de tarefas é definido, a pilha é carregada pelo contexto da tarefa.
void StartOS(unsigned long Num);
O início do sistema operacional. Como argumento para a função, o identificador da tarefa com a qual iniciar a execução é passado. Quando o sistema operacional é iniciado, o timer do sistema é definido para um quantum de um milissegundo. O contexto é baixado da pilha da tarefa iniciada e a tarefa é chamada.
void Sleep(unsigned long ms);
Planejador Quando essa função é chamada de uma tarefa, o controle é transferido para o sistema operacional. O sistema operacional seleciona uma tarefa pronta para execução da lista e transfere o controle para ela. O argumento da função é o tempo em milissegundos após o qual é necessário retornar o controle para a tarefa atual. Quando uma função é chamada com o argumento 0xFFFFFFFF, o controle nunca retornará.
Como é impossível escrever essa função em C, o algoritmo de sua operação destrói completamente a lógica da linguagem. O código fonte contém testes de programas em linguagem assembly para os sistemas de programação IAR e GCC. Para quem sofre, o código em C é fornecido. Mas eu gostaria de observar que ele é capaz de compilar corretamente apenas com certas "fases da lua". No meu caso, isso aconteceu apenas ao usar o nível intermediário de otimização; no nível alto e baixo, o código foi compilado erroneamente.
Arquivo Sleep.c extern Task_t TaskList[IntorOSMaxKolvoZadach];
void EndTask(void);
Conclusão da tarefa. Como observado acima, as tarefas são estáticas, é impossível descarregar tarefas. Se você precisar concluir a tarefa, poderá usar esta função. A tarefa permanece na lista, mas o controle não é transferido para ela.
void StopTask(unsigned long Num); void StartTask(unsigned long Num);
Pare ou inicie uma tarefa. Argumento é o identificador da tarefa. Essas funções permitem implementar o gerenciador de tarefas. Deve-se observar que você só pode iniciar uma tarefa interrompida anteriormente, o tempo até o início é 0xFFFFFFFF.
Usando o SO
Por exemplo, um microcontrolador tradicional "helword" para um sistema operacional desenvolvido.
#include "stm32l0xx.h" #include "stm32l0xx_ll_gpio.h" #include "IntorOS.h"
Em conclusão, gostaria sinceramente de que este sistema operacional desenvolvido por diversão seja interessante e útil para desenvolvedores de software para sistemas embarcados.