sandro emanuel salgado pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfresumo nos...

174
Sandro Emanuel Salgado Pinto Sistema Operativo Orientado a Objetos: porting, expansão e configuração Sandro Emanuel Salgado Pinto Outubro de 2012 UMinho | 2012 Sistema Operativo Orientado a Objetos: porting, expansão e configuração Universidade do Minho Escola de Engenharia

Upload: others

Post on 19-Jan-2020

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Sandro Emanuel Salgado Pinto

Sistema Operativo Orientado a Objetos:porting, expansão e configuração

Sand

ro E

man

uel S

alga

do P

into

Outubro de 2012UMin

ho |

201

2Si

stem

a O

pera

tivo

Ori

enta

do a

Obj

etos

:po

rtin

g, e

xpan

são

e co

nfig

uraç

ão

Universidade do MinhoEscola de Engenharia

Page 2: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Outubro de 2012

Tese de MestradoCiclo de Estudos Integrados Conducentes ao Grau deMestre em Engenharia Eletrónica Industrial e Computadores

Trabalho efetuado sob a orientação doProfessor Doutor José Mendes

Sandro Emanuel Salgado Pinto

Sistema Operativo Orientado a Objetos:porting, expansão e configuração

Universidade do MinhoEscola de Engenharia

Page 3: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Agradecimentos

As primeiras palavras de agradecimento sao direcionadas aos meus pais, Manuel

Pinto e Paula Salgado, por todo o apoio educacional, psicologico e financeiro, prestado

durante todo o meu percurso academico, pois sem eles esta dissertacao nunca seria

uma realidade.

Ao meu orientador Professor Doutor Jose Mendes, bem como aos Professores

Doutores Adriano Tavares e Jorge Cabral, por todo o apoio prestado e por toda

confianca depositada em mim para a concretizacao deste trabalho.

Ao Embedded System Research Group do Departamento de Eletronica Industrial

da Universidade do Minho, que me acolheu e proporcionou todas as condicoes ne-

cessarias para a elaboracao da dissertacao. Um obrigado especial para o mestre Nuno

Cardoso que sempre se mostrou disponıvel para me ajudar, esclarecer e partilhar co-

nhecimentos.

Aos meus colegas de curso que me acompanharam ao longo destes anos, em espe-

cial ao Tiago Castro e Vıtor Veiga que estiveram envolvidos no projeto onde se integra

a dissertacao, bem como ao Filipe Alves por todos os momentos de companheirismo

vividos.

Finalmente, e nao menos importante, a minha namorada, Barbara Fernandes,

e ao meu grupo de amigos, CN (Filtros, Fox, Maia, Marco, Milu, Moura, Peste,

Rica, Rojao, Slim), por me terem alegrado, compreendido e apoiado sobretudo nos

momentos de maior angustia e desilusao.

A todos, um muito obrigado!

iii

Page 4: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 5: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Resumo

Nos ultimos anos, cerca de 98% da producao anual de microprocessadores teve

como finalidade os sistemas embebidos [1]. No entanto, o desenvolvimento de software

e aplicacoes bare-metal pode tornar-se complexo, provocando uma enorme pressao

no time-to-market, aumento do tempo e esforco (colaboradores/hora) de desenvol-

vimento, e deficiente qualidade do sistema final. A estrategia passa entao por usar

sistemas operativos, tornando o desenvolvimento mais simples, rapido e seguro.

Normalmente, os sistemas operativos monolıticos nao se adequam as necessidades

e limitacoes dos sistemas embebidos, pois maximizam o numero de plataformas e

funcionalidades oferecidas, o que se traduz num aumento no consumo de recursos.

Por isso, a tendencia recai sobre sistemas operativos de tempo-real (baseados em

microkernel) desenvolvidos e adaptados a arquitetura do processador, e aos requisitos

e restricoes da aplicacao.

No entanto, com o aumento da complexidade dos sistemas atuais, existe uma pro-

cura crescente na configurabilidade, variabilidade e reutilizacao dos sistemas embebi-

dos. A maioria desses sistemas gere a variabilidade utilizando compilacao condicional

ou programacao orientado a objetos. A primeira aumenta a complexidade de gestao

do codigo. A ultima providencia a modularidade e adaptabilidade necessarios para

simplificar a tarefa de desenvolvimento de software reutilizavel e customizavel, no

entanto, degrada o desempenho e os recursos de memoria do sistema.

Neste sentido, a presente dissertacao propoe a utilizacao de C++ template me-

taprogramming como a metodologia para a gestao da variabilidade de um sistema

operativo orientado a objetos. Utilizando esta tecnica de programacao, e possıvel

gerar apenas as funcionalidades pretendidas, garantindo assim codigo otimizado e

ajustado as necessidades da aplicacao e aos recursos de hardware.

v

Page 6: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 7: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Abstract

In recent years, approximately 98% of microprocessors annual production was

aimed at embedded systems [1]. However, the development of bare-metal application

software can become complex, leading to a tremendous pressure on time-to-market,

increased time and effort development (staff / hour), and poor final system quality.

So, the strategy is to use operating systems, making development easier, faster and

safer.

Typically, monolithic operating systems do not fit the requirements and limitati-

ons of embedded systems since they attempt to maximize the number of supported

platforms and functionalities offered, which results in an increase in the consumption

of resources. Therefore, the trend became using real-time operating systems (mi-

crokernel based) developed and adapted to processor architecture and to application

requirements and constraints.

However, with the growing complexity of current systems, there is an increasing

demand for configurability, variability and reuse of embedded systems. Most of these

systems manage variability using conditional compilation or object oriented program-

ming. The former paradigm increases the management complexity of code. The latter

provides the modularity and adaptability needed to simplify the task of developing

reusable and customizable software; however, it degrades performance and memory

resources.

In this context, this thesis proposes the use of C++ template metaprogramming

as a methodology for managing the variability of an object-oriented operating system.

Using this advanced programming technique, it is possible to generate only the desired

functionalities, thus ensuring that code is optimized and adjusted to application

requirements and hardware resources.

vii

Page 8: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 9: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Conteudo

1 Introducao 1

1.1 Contextualizacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.3 Organizacao da Dissertacao . . . . . . . . . . . . . . . . . . . . . . . 4

2 Estado da Arte 5

2.1 Programacao Orientada a Objetos . . . . . . . . . . . . . . . . . . . . 5

2.1.1 Paradigmas de Programacao . . . . . . . . . . . . . . . . . . . 6

2.1.2 Objetos e Classes . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.1.3 Princıpios Fundamentais . . . . . . . . . . . . . . . . . . . . . 8

2.2 Sistemas Operativos . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.2.1 Arquitetura dos Sistemas Operativos . . . . . . . . . . . . . . 12

2.2.2 Sistemas Operativos de Tempo-Real . . . . . . . . . . . . . . . 14

2.2.3 Sistemas Operativos Orientados a Objetos . . . . . . . . . . . 15

2.3 Configurabilidade e Variabilidade no Software: tecnicas de programacao 21

2.3.1 Compilacao Condicional . . . . . . . . . . . . . . . . . . . . . 22

2.3.2 Orientacao a Objetos . . . . . . . . . . . . . . . . . . . . . . . 23

2.3.3 Orientacao a Componentes . . . . . . . . . . . . . . . . . . . . 23

2.3.4 Orientacao a Funcionalidades . . . . . . . . . . . . . . . . . . 24

2.3.5 Orientacao a Aspetos . . . . . . . . . . . . . . . . . . . . . . . 25

2.3.6 Programacao Generativa . . . . . . . . . . . . . . . . . . . . . 26

2.4 Conclusoes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3 Especificacao do Sistema 29

3.1 Microcontrolador 8051 . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.1.1 Arquitetura de Memoria . . . . . . . . . . . . . . . . . . . . . 31

ix

Page 10: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.1.2 Registos Basicos . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3.1.3 Perifericos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.1.4 Interrupcoes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

3.1.5 Arquitetura do Conjunto de Instrucoes . . . . . . . . . . . . . 35

3.2 ADEOS: A Decent Embedded Operating System . . . . . . . . . . . . 37

3.2.1 Tarefas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3.2.2 Escalonador . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3.2.3 Sincronizacao de Tarefas . . . . . . . . . . . . . . . . . . . . . 45

3.3 Template MetaProgramming . . . . . . . . . . . . . . . . . . . . . . . 47

3.3.1 Blocos Basicos do Template Metaprogramming . . . . . . . . . 47

3.3.2 O Fatorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

3.3.3 Lista Ligada Estatica . . . . . . . . . . . . . . . . . . . . . . . 51

3.4 Ambiente de Desenvolvimento . . . . . . . . . . . . . . . . . . . . . . 52

3.4.1 Compilador IAR C/C++ para o 8051 . . . . . . . . . . . . . . 55

4 Implementacao do Sistema 65

4.1 Porting do ADEOS para a Plataforma MCS-51 . . . . . . . . . . . . 65

4.1.1 Analise do Codigo Dependente do Processador . . . . . . . . . 67

4.1.2 Porting do Codigo Dependente do Processador . . . . . . . . . 75

4.2 Upgrade do ADEOS . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

4.2.1 Upgrade: clock-tick no escalonador . . . . . . . . . . . . . . . 83

4.2.2 Upgrade: device drivers . . . . . . . . . . . . . . . . . . . . . . 85

4.2.3 Upgrade: escalonador power-aware . . . . . . . . . . . . . . . 108

4.3 Refactoring do ADEOS . . . . . . . . . . . . . . . . . . . . . . . . . . 114

4.3.1 Diagrama de Funcionalidades . . . . . . . . . . . . . . . . . . 114

4.3.2 Estrategia de Gestao da Variabilidade . . . . . . . . . . . . . . 117

4.3.3 Reestruturacao do ADEOS . . . . . . . . . . . . . . . . . . . . 120

5 Resultados Experimentais 127

5.1 Ambiente de Testes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

5.2 Metricas de Teste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

5.3 Testes Realizados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

5.3.1 Teste ao Sistema Operativo . . . . . . . . . . . . . . . . . . . 131

5.3.2 Teste ao driver USART . . . . . . . . . . . . . . . . . . . . . 134

x

Page 11: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

6 Conclusoes 139

6.1 Conclusao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

6.2 Trabalho Futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

A Placa Circuito Impresso: spi2c 145

xi

Page 12: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 13: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Lista de Figuras

2.1 Modelos arquiteturais de um sistema operativo: monolıtico e microkernel 13

2.2 Diagrama de classes do core do sistema operativo BOSS . . . . . . . 20

2.3 Orientacao a funcionalidades: hierarquia de classes e modelo de funci-

onalidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

2.4 Juncao do codigo aspeto no codigo dos componentes . . . . . . . . . . 27

3.1 Diagrama de blocos do microcontrolador 8051 classico . . . . . . . . . 30

3.2 Mapa de memoria do 8051 generico . . . . . . . . . . . . . . . . . . . 32

3.3 Diagrama de classes do ADEOS . . . . . . . . . . . . . . . . . . . . . 38

3.4 Relacao dos estados das tarefas no ADEOS . . . . . . . . . . . . . . . 40

3.5 Ilustracao da lista de tarefas prontas a executar (readyList) . . . . . . 44

3.6 Resolucao dos templates no calculo do fatorial . . . . . . . . . . . . . 51

3.7 Processo de compilacao de codigo fonte em codigo executavel/maquina 54

4.1 Arquitetura de software do ADEOS . . . . . . . . . . . . . . . . . . . 66

4.2 Pilha do sistema apos entrada na funcao contextInit . . . . . . . . . . 69

4.3 Pilha da tarefa apos inicializacao . . . . . . . . . . . . . . . . . . . . 71

4.4 Diagrama de classes do driver PWM . . . . . . . . . . . . . . . . . . 87

4.5 Diagrama de classes do driver UART . . . . . . . . . . . . . . . . . . 92

4.6 Diagrama de classes do driver GPIO . . . . . . . . . . . . . . . . . . 96

4.7 Formato da trama I2C . . . . . . . . . . . . . . . . . . . . . . . . . . 99

4.8 Diagrama de classes do driver I2C . . . . . . . . . . . . . . . . . . . 100

4.9 SPI: barramento e diagrama temporal . . . . . . . . . . . . . . . . . . 104

4.10 Diagrama de classes do driver SPI . . . . . . . . . . . . . . . . . . . . 105

4.11 Diagrama de funcionalidades do ADEOS . . . . . . . . . . . . . . . . 115

5.1 Placa de desenvolvimento 8051DKUSB . . . . . . . . . . . . . . . . . 128

xiii

Page 14: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

5.2 Diagrama de funcionalidades do sistema operativo (teste ao sistema

operativo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

5.3 Resultados de desempenho e footprint de memoria (teste ao sistema

operativo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

5.4 Resultados de gestao do codigo (teste ao sistema operativo) . . . . . . 134

5.5 Resultados de desempenho e footprint de memoria (teste ao driver

USART) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

5.6 Resultados de gestao do codigo (teste ao driver USART) . . . . . . . 137

A.1 PCB spi2c: esquematico . . . . . . . . . . . . . . . . . . . . . . . . . 146

A.2 PCB spi2c: layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

xiv

Page 15: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Lista de Tabelas

2.1 Implementacao da classe Shape em C++ e Java . . . . . . . . . . . . 8

3.1 Vetores de interrupcao na famılia MCS-51 . . . . . . . . . . . . . . . 34

3.2 Modos de enderecamento do 8051 . . . . . . . . . . . . . . . . . . . . 35

3.3 Resultados de desempenho e memoria das aplicacoes Fatorial (C++

dinamico) e Fatorial (TMP) . . . . . . . . . . . . . . . . . . . . . . . 51

3.4 Codigo C++ TMP e codigo assembly da aplicacao estatica do fatorial 53

3.5 Convencoes de chamada de funcoes no compilador C/C++ 8051 da IAR 60

3.6 Registos utilizados nos parametros das funcoes . . . . . . . . . . . . . 61

3.7 Registos utilizados no retorno das funcoes . . . . . . . . . . . . . . . 62

4.1 Rotina de interrupcao do temporizador 1 . . . . . . . . . . . . . . . . 84

4.2 Configuracao do temporizador 1 . . . . . . . . . . . . . . . . . . . . . 85

4.3 Inicializacao da contagem do temporizador 1 . . . . . . . . . . . . . . 85

4.4 Implementacao C++ e assembly da selecao da frequencia . . . . . . . 114

4.5 Classes especificas da funcionalidade example . . . . . . . . . . . . . 117

4.6 Declaracao da classe template da funcionalidade Sched . . . . . . . . 120

4.7 Definicao das templates generica e especificas da funcionalidade Sched 121

4.8 Declaracao da classe template da funcionalidade Task . . . . . . . . . 123

4.9 Definicao das templates generica e especificas da funcionalidade Task 125

5.1 Caracterısticas de hardware da placa de desenvolvimento 8051DKUSB 128

5.2 Configuracao usada no teste ao sistema operativo . . . . . . . . . . . 131

xv

Page 16: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 17: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Lista de Listagens

2.1 Implementacao C (iterativa) do calculo do fatorial de um numero . . 6

2.2 Implementacao Haskell do calculo do fatorial de um numero . . . . . 6

2.3 Definicao da classe Triangle como herdeira da classe Shape . . . . . . 9

2.4 Exemplo de polimorfismo dinamico na classe Triangle . . . . . . . . . 10

2.5 Declaracao da classe Shape como abstrata . . . . . . . . . . . . . . . 11

2.6 Exemplo da utilizacao de compilacao condicional . . . . . . . . . . . 22

3.1 Declaracao da classe Task . . . . . . . . . . . . . . . . . . . . . . . . 39

3.2 Funcao de iniciacao das tarefas - run . . . . . . . . . . . . . . . . . . 41

3.3 Construtor da classe Task . . . . . . . . . . . . . . . . . . . . . . . . 41

3.4 Metodo schedule da classe Sched . . . . . . . . . . . . . . . . . . . . 44

3.5 Construtor da classe Mutex . . . . . . . . . . . . . . . . . . . . . . . 46

3.6 Valores em template metaprogramming . . . . . . . . . . . . . . . . . 47

3.7 Funcoes em template metaprogramming . . . . . . . . . . . . . . . . . 48

3.8 Saltos condicionais em template metaprogramming . . . . . . . . . . . 48

3.9 Recursividade em template metaprogramming . . . . . . . . . . . . . 49

3.10 Implementacao C++ recursiva do calculo do fatorial . . . . . . . . . . 49

3.11 Implementacao C++ TMP recursiva do calculo do fatorial . . . . . . 50

3.12 Implementacao C++ TMP de uma lista ligada estatica de inteiros . . 51

3.13 Metafuncao Length da lista ligada estatica . . . . . . . . . . . . . . . 52

3.14 Funcao de interrupcao de overflow do timer 0 . . . . . . . . . . . . . 57

3.15 Exemplo de utilizacao de inline assembler no compilador IAR . . . . 58

3.16 Definicao de uma funcao implementada num ficheiro assembly externo 59

3.17 Estrutura de um ficheiro assembly gerado pelo compilador IAR . . . . 59

4.1 Ficheiro bsp.h para a arquitetura 80188 . . . . . . . . . . . . . . . . . 67

4.2 Prototipo da funcao contextInit . . . . . . . . . . . . . . . . . . . . . 68

4.3 Prototipo da funcao contextSwitch . . . . . . . . . . . . . . . . . . . . 73

xvii

Page 18: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.4 Definicao da estrutura do estado da maquina (8051) de cada tarefa . 76

4.5 Macros para delimitacao de uma seccao crıtica . . . . . . . . . . . . . 76

4.6 Macro para comutacao de contexto (ContextSwitch) . . . . . . . . . . 77

4.7 Configuracao do clock-tick do escalonador . . . . . . . . . . . . . . . 85

4.8 Declaracao da classe Pwm8051 . . . . . . . . . . . . . . . . . . . . . 88

4.9 Estrutura de configuracao da classe Pwm8051 . . . . . . . . . . . . . 89

4.10 Enumeracoes da classe Pwm8051 . . . . . . . . . . . . . . . . . . . . 89

4.11 Metodo config da classe Pwm8051 . . . . . . . . . . . . . . . . . . . . 90

4.12 Declaracao da classe Uart8051 . . . . . . . . . . . . . . . . . . . . . . 93

4.13 Construtor da classe Uart8051 com configuracao . . . . . . . . . . . . 94

4.14 Metodos txStart e rxStart da classe Uart8051 . . . . . . . . . . . . . 94

4.15 Declaracao da classe Gpio8051 . . . . . . . . . . . . . . . . . . . . . 97

4.16 Metodo config da classe Gpio8051 . . . . . . . . . . . . . . . . . . . . 97

4.17 Declaracao da classe I2c051 . . . . . . . . . . . . . . . . . . . . . . . 101

4.18 Construtor por defeito da classe I2c051 . . . . . . . . . . . . . . . . . 102

4.19 Metodos start e write char da classe I2c8051 . . . . . . . . . . . . . 102

4.20 Declaracao da classe Spi8051 . . . . . . . . . . . . . . . . . . . . . . 106

4.21 Construtor da classe Spi8051 com configuracao . . . . . . . . . . . . 107

4.22 Metodos read char da classe Spi8051 . . . . . . . . . . . . . . . . . . 107

4.23 Construtor da classe do escalonador power-aware . . . . . . . . . . . 111

4.24 Alteracoes na ISR do clock-tick do escalonador . . . . . . . . . . . . . 112

4.25 Implementacao do metodo defer . . . . . . . . . . . . . . . . . . . . . 113

4.26 Ficheiro example tmp.h . . . . . . . . . . . . . . . . . . . . . . . . . . 118

4.27 Transparencia no codigo de acesso a funcionalidade example . . . . . 119

4.28 Transparencia no codigo de acesso a funcionalidade Sched . . . . . . . 122

4.29 Transparencia no codigo de acesso a funcionalidade Task . . . . . . . 124

xviii

Page 19: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 1

Introducao

Neste capıtulo e contextualizado o ambito desta dissertacao, sao definidos os ob-

jetivos a atingir, finalizando o capıtulo com a organizacao da dissertacao.

1.1 Contextualizacao

Vivemos na era tecnologica. As sociedades modernas atuais estao cada dia mais

dependentes de sistemas eletronicos e informaticos responsaveis por substituir e sim-

plificar as tarefas do quotidiano. Seja na industria, na medicina, na aviacao, ou

simplesmente em casa, cada vez mais existe uma necessidade de desenvolver solucoes

computacionais que auxiliem a realizacao dessas tarefas.

Neste sentido, acompanhando essa tendencia, tem-se verificado um crescimento

exponencial na utilizacao de microcontroladores no desenvolvimento e concepcao de

sistemas embebidos. Nos ultimos anos, cerca de 98% da producao anual de micropro-

cessadores teve como finalidade esse tipo de sistemas [1]. No entanto, o desenvolvi-

mento de software e aplicacoes bare-metal pode tornar-se complexo, provocando uma

enorme pressao no time-to-market, aumento do tempo e esforco (colaboradores/hora)

de desenvolvimento, e deficiente qualidade do sistema final. Isto e extremamente des-

favoravel numa sociedade extremamente competitiva e capitalista como a atual, pois

traduz-se num aumento dos custos, provavel diminuicao das vendas e consequente mi-

nimizacao dos lucros. Assim sendo, a estrategia passa por usar sistemas operativos,

de forma a que o processo de desenvolvimento seja mais simples, rapido e seguro.

Um sistema operativo e uma camada de software que abstrai o utilizador das

especificidades do hardware, atuando como um intermediario entre o utilizador e os

1

Page 20: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

1.1. Contextualizacao

dispositivos [2]. Tem como principal objetivo, fornecer os recursos e meios ao uti-

lizador para que este desenvolva e execute os programas de forma simplificada e

eficiente. Normalmente, os sistemas operativos monolıticos nao se adequam as ne-

cessidades e limitacoes do domınio embebido. Isto porque estes sistemas operativos

procuram maximizar nao so o numero de plataformas alvo, mas tambem as funcionali-

dades oferecidas ao utilizador, o que se traduz num aumento no consumo de recursos

(memoria). Neste caso, a tendencia recai sobre sistemas operativos de tempo real

(baseados em microkernel) desenvolvidos e adaptados a arquitetura do processador,

e aos requisitos e restricoes da aplicacao.

No entanto, com o aumento da complexidade dos sistemas atuais, existe uma pro-

cura crescente na configurabilidade, variabilidade e reutilizacao dos sistemas embebi-

dos. Um bom exemplo e o sistema operativo embebido especificado pela AUTOSAR

[3]. A maioria desses sistemas gere a variabilidade utilizando compilacao condicional.

A implementacao das funcionalidades configuraveis e embebida em blocos ]ifdef -

]endif, aumentando a complexidade na compreensao e manutencao do codigo. Uma

outra abordagem consiste na utilizacao do paradigma orientado a objetos. Esta me-

todologia providencia a abstracao, modularidade, e adaptabilidade necessarios para

simplificar a tarefa de desenvolvimento de software reutilizavel, com funcionalidades

variaveis e configuraveis.

Apesar de todos os benefıcios associados a programacao orientada a objetos, ca-

racterısticas como a multipla heranca, o polimorfismo dinamico, e a abstracao di-

minuem o desempenho e introduzem um enorme overhead de memoria [4, 5]. Este

fator torna-se extremamente crıtico sobretudo em sistemas com escassez de recursos

como os sistemas embebidos. Daı que seja necessario utilizar tecnicas de programacao

avancada que contornem e resolvam este problema.

Programacao generativa, nomeadamente template metaprogramming (TMP) [6,

7], e uma das tecnicas que apresenta resultados muito promissores [8, 9, 10, 11, 12].

Com esta metodologia toda a variabilidade e processada pelo compilador durante a

fase de resolucao dos templates, ou seja, todo o processamento e realizado em tempo

de compilacao e nao em tempo de execucao. Desta forma, e possıvel gerar apenas

as funcionalidades pretendidas, garantindo assim codigo otimizado e ajustado as ne-

cessidades da aplicacao e dos recursos de hardware. A biblioteca Boost.MPL [13] e

um exemplo de uma framework que usa C++ template metaprogramming para imple-

mentar algoritmos e metafuncoes de forma estatica, isto e, no instante de compilacao.

2

Page 21: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 1. Introducao

Assim sendo, o trabalho da presente dissertacao pode ser dividido em duas partes:

primeiro (i) avaliar os sistemas operativos orientados a objetos, de modo a efetuar o

porting e expandir o sistema operativo que mais se adeque aos recursos disponibiliza-

dos pela arquitetura da famılia MCS-51; e posteriormente (ii) reestruturar o sistema

operativo de modo a permitir a sua customizacao, gerindo a variabilidade do sistema

sem porventura comprometer o seu desempenho e consumo de memoria.

Finalmente, e para terminar, importa referir que este trabalho e apenas uma fracao

de um projeto de maior dimensao que consiste tambem (i) no desenvolvimento de um

microcontrolador da famılia MCS-51 low-power customizavel, assim como (ii) um IDE

capaz de gerar o sistema operativo e o microcontrolador, configurados de acordo com

as necessidades e especificacoes do utilizador. Basicamente, o microcontrolador low-

power permite executar o sistema operativo, que e customizado e gerado de acordo

com a configuracao desejada pelo utilizador no IDE.

1.2 Objetivos

O principal objetivo da presente dissertacao esta bastante claro no tıtulo da

mesma. Assim, este passa por fazer o porting, o upgrade e a customizacao de um sis-

tema operativo orientado a objetos para a arquitetura do microcontrolador MCS-51.

Com base neste objetivo central, e possıvel ramifica-lo em varios objetivos parciais.

Assim sendo, o primeiro passa por selecionar e efetuar o porting de um sistema

operativo orientado a objetos para a plataforma MCS-51. Com base nos sistemas

operativos orientados objetos disponıveis, e necessario perceber qual ou quais sao

mais propensos para os sistemas embebidos, e qual o que se torna a solucao mais

adequada para a finalidade da dissertacao.

O segundo objetivo consiste em melhorar e aumentar o conjunto de funcionalida-

des do sistema operativo escolhido. Otimizar o codigo dependente do processador,

desenvolver um conjunto de device drivers para os varios perifericos do microcontro-

lador, e expandir as funcionalidades (escalonadores, IPCs, etc.) do sistema operativo,

sao algumas das tarefas necessarias a concretizacao deste objectivo.

O terceiro objetivo consiste na aplicacao de tecnicas de programacao avancadas

para customizar, gerir a variabilidade e minimizar o overhead do sistema operativo

orientado a objetos. Pretende-se, portanto, realizar o refactoring do sistema utili-

zando template metaprogramming.

3

Page 22: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

1.3. Organizacao da Dissertacao

Finalmente, o quarto e ultimo objectivo passa por avaliar quais os ganhos obtidos

com a aplicacao do template metaprogramming na gestao da variabilidade, desem-

penho e overhead de memoria do sistema, em comparacao com a implementacao

utilizando polimorfismo dinamico.

1.3 Organizacao da Dissertacao

No capıtulo 1 e feita uma pequena introducao onde e contextualizado o trabalho,

sao especificados os objetivos e e descrita a estrutura da presente dissertacao.

O capıtulo 2 apresenta a fundamentacao teorica dos conceitos abordados na dis-

sertacao, nomeadamente a programacao orientada a objetos, os sistemas operativos,

e as metodologias para a gestao da variabilidade do software. Alem dos conceitos

teoricos, e discutida e justificada a escolha do sistema operativo orientado a objetos,

bem como a tecnica de programacao utilizada na gestao de variabilidade do sistema.

No capıtulo 3 sao explicados, numa aproximacao bottom-up, cada uma das ca-

madas e componentes que compoe a base do sistema a implementar. Sera analisada

e explicada a arquitetura do microcontrolador 8051, o sistema operativo ADEOS, a

tecnica de template metaprogramming e compilador C++ da IAR para o 8051.

O capıtulo 4 descreve o desenvolvimento dos componentes do sistema. Basica-

mente, descreve o trabalho propriamente desenvolvido, nomeadamente o porting do

sistema operativo ADEOS para a arquitetura MCS-51, as melhorias introduzidas e,

no final, a reestruturacao do sistema com template metaprogramming, de modo a

gerir a variabilidade e permitir a sua customizacao.

No capıtulo 5 sao apresentados os resultados experimentais dos testes realizados.

Para avaliar as metricas de desempenho e gestao do codigo, foram efetuados dois

testes distintos. No primeiro, o sistema operativo e as diversas funcionalidades foram

implementadas utilizado template metaprogramming e polimorfismo dinamico. No

segundo, apenas foi testado um modulo driver, isto para comparar os resultados

com uma implementacao na linguagem de programacao mais utilizada em sistemas

embebidos (C).

O documento termina com o capıtulo 6, que traduz as principais conclusoes do

trabalho realizado, assim como enuncia algumas sugestoes para trabalho futuro, que

visam melhorar e expandir o trabalho desenvolvido.

4

Page 23: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2

Estado da Arte

Este capıtulo apresenta uma visao geral dos principais conceitos abordados nesta

dissertacao. Sendo o objeto de estudo desta dissertacao a customizacao e gestao da

variabilidade de um sistema operativo orientado objetos, torna-se portanto essencial

clarificar e explicar os conceitos fundamentais sobre as tres principais tematicas ad-

jacentes ao trabalho a desenvolver: (i) a programacao orientada a objetos; (ii) os

sistemas operativos; e (iii) as diferentes metodologias de programacao para a gestao

da variabilidade do software. Para alem de todo o fundamento teorico, sao tambem

apresentadas as decisoes relativamente ao sistema operativo orientado objetos, bem

como a tecnica de gestao de variabilidade, a adoptar para concretizar o trabalho

proposto.

2.1 Programacao Orientada a Objetos

A Programacao Orientada a Objetos (POO) surgiu com a necessidade de tornar

as aplicacoes de software mais proximas do modelo usado pelas pessoas para pensar

e lidar com o mundo. Em metodologias e paradigmas de programacao mais antigos,

sempre que um programador se depara com um problema, a sua preocupacao consiste

em identificar uma tarefa de computacao responsavel por solucionar esse problema.

Assim sendo, a programacao consiste apenas em encontrar uma sequencia de ins-

trucoes capaz de realizar a tarefa pretendida. No entanto, o conceito de programacao

orientada a objetos e totalmente diferente. Em vez de tarefas, existem objetos, ou

seja, entidades que tem comportamentos, retem informacao, e que podem interagir

com outros objetos. Segundo este paradigma, programar consiste em desenhar um

5

Page 24: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.1. Programacao Orientada a Objetos

conjunto de objetos responsavel por modelar e resolver o problema pretendido. Es-

tes objetos podem representar entidades reais ou abstratas no domınio do problema.

Desta forma, e suposto tornar o processo de desenvolvimento mais simples e natural,

e por isso, mais facil de entender.

Resumindo, a programacao orientada a objetos fornece um conjunto de ferramen-

tas e metodos que possibilitam aos programadores desenvolver software confiavel,

sustentavel, reutilizavel e bem documentado, e que simultaneamente cumpre os re-

quisitos pretendidos pelos utilizadores.

2.1.1 Paradigmas de Programacao

Alem do paradigma orientado a objetos, existem outros paradigmas de pro-

gramacao: (i) a programacao imperativa (por exemplo, utilizado em linguagens como

C[14], Basic[15] e Pascal[16]); (ii) a programacao logica (por exemplo, Prolog[17]); e

(iii) a programacao funcional (por exemplo, Haskell[18] ou Lisp[19]).

As linguagens de programacao imperativas concebem um programa como um

conjunto de funcoes e sub-rotinas que realizam uma determinada tarefa. Por exemplo,

o codigo escrito em C da listagem 2.1 pode ser utilizado para calcular, iterativamente,

o fatorial de um numero.

int fatorial (int num)

{int result = 1;

for (int count = 1; count <= num; count++)

result ∗= count;

return result;

}

Listagem 2.1: Implementacao C (iterativa) do calculo do fatorial de um numero

A programacao funcional e um paradigma de programacao que trata a computacao

como uma avaliacao de funcoes matematicas, o que evita estados ou dados mutaveis.

Este tipo de paradigma enfatiza a definicao de funcoes, em contraste com a pro-

gramacao imperativa, que enfatiza a execucao de comandos sequenciais. O codigo

apresentado na listagem 2.2 calcula o fatorial de um numero em Haskell.

factorial :: Int −> Int

factorial 0 = 1

factorial n = n ∗ factorial (n − 1)

Listagem 2.2: Implementacao Haskell do calculo do fatorial de um numero

6

Page 25: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

Prolog (PROgramming in LOGic) e a linguagem de programacao mais usada se-

gundo o paradigma da programacao logica. Este paradigma e baseado em ideais

matematicos de relacoes e inferencia logica. Isto significa que, mais do que descrever

como computorizar uma solucao, um programa consiste numa base de dados de re-

gras logicas que descrevem as relacoes para uma determinada aplicacao. Por outras

palavras, quando se executa um programa para obter uma solucao, o utilizador res-

ponde a uma questao, e com base nessa resposta, o sistema procura (em tempo de

execucao), na base de dados, as regras que determinam (atraves de deducao logica)

a resposta pretendida.

Resumindo:

• em linguagens imperativas, utilizam-se procedimentos;

• em linguagens funcionais, utilizam-se funcoes;

• em linguagens de programacao logicas, utilizam-se expressoes logicas;

• em linguagens orientadas a objetos, utilizam-se objetos.

2.1.2 Objetos e Classes

Na programacao orientada a objetos, tal como designacao sugere, sao criados

objetos de software que modelam e representam os objetos do mundo real. Assim, tal

como os objetos reais, os objetos de software sao caracterizados por um determinado

estado e comportamento. Esse estado e conservado nos atributos. Cada atributo

e denominado por um identificador e e responsavel por armazenar a informacao e

dados desse estado. Por sua vez, o comportamento do objeto e implementado atraves

de metodos. Um metodo e entao uma funcao associada a um determinado objeto.

Portanto, um objeto e um componente de software que contem variaveis e metodos

intrınsecos. Alem disso, muitas vezes um objeto e designado por instancia, uma vez

que uma instancia refere-se a um objeto em particular. Por exemplo, um Porsche

Panamera e uma instancia de um carro, pois refere-se a um carro em particular.

Objetos e classes estao intrinsecamente relacionados. As classes sao as entidades

usadas para produzir e criar os objetos. Assim sendo, uma classe declara as variaveis

necessarias para reter o estado de cada objeto, assim como fornece as implementacoes

dos metodos necessarios para operar sobre o estado do objecto. Portanto, so depois

de ser criada a classe e que e possıvel criar ou instanciar objetos dessa classe. Por

outras palavras, uma classe e uma especie de planta para construir objetos. As partes

7

Page 26: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.1. Programacao Orientada a Objetos

Tabela 2.1: Implementacao da classe Shape em C++ e Java

Linguagem Codigo Exemplo

C++

class Shape{

public:Shape(int h, int w) { h = h; w = w; }void setH(int h) { h = h; }int getH() { return h; }void setW(int w) { w = w; }int getW() { return w; }

private:int h, w;

};

Java

class Shape{

public Shape(int h, int w) { h = h; w = w; }public void setH(int h) { h = h; }public int getH() { return h; }public void setW(int w) { w = w; }public int getW() { return w; }

private int h;private int w;

};

nao-estaticas da classe especificam ou descrevem que variaveis e metodos os objetos

irao ter. Isto permite entao estabelecer a distincao entre os dois conceitos: os objetos

sao criados e destruıdos ao executar o programa, podendo ter a mesma estrutura,

desde que sejam criados usando a mesma classe.

A tabela 2.1 ilustra a definicao de uma classe nas duas linguagens de programacao

orientadas a objetos mais utilizadas: C++ [20] e Java [21]. A classe exemplo repre-

senta um objeto do mundo concreto, nomeadamente, uma figura geometrica (Shape).

2.1.3 Princıpios Fundamentais

Os princıpios fundamentais de qualquer linguagem orientada a objetos sao: (i)

encapsulamento; (ii) heranca; (iii) polimorfismo; e (iv) abstracao.

Encapsulamento

O encapsulamento e uma caracteristica da POO que consiste em proteger as

variaveis dos objetos atraves dos seus metodos. Basicamente, definindo-se os atribu-

tos como privados e os metodos como publicos, garante-se assim que os valores dos

atributos apenas poderao ser modificados pelas regras que definem os metodos. Isto

8

Page 27: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

proporciona entao grandes vantagens ao desenvolvimento de software sobretudo em

dois aspectos:

• Modularidade: o codigo fonte de um objeto pode ser escrito e gerido inde-

pendetemente do codigo fonte de outros objetos. Alem disso, um objeto pode

ser facilmente passado no sistema.

• Ocultacao da Informacao: um objeto tem uma interface publica que os

outros objetos podem usar para comunicar com este. Assim, o objeto contem a

informacao privada e metodos que podem ser modificados a qualquer momento

sem que os outros objetos dependam disso.

O codigo da tabela 2.1 e um exemplo da utilizacao do encapsulamento em dife-

rentes linguagens de programacao. A classe Shape e constituıda por dois atributos:

w e h. O atributo w define o valor da largura (width) da figura, e o atributo h

define o valor da altura (height). Os atributos da classe sao definidos como privados

(private), para que nao seja possıvel a qualquer objeto externo aceder diretamente a

cada uma das variaveis. Daı que sejam definidos os metodos setH, getH, setW e getW,

para ler e escrever os valores de cada uma das variaveis. Os metodos sao definidos

como publicos (public), de forma a que sejam acessıveis a entidades externas a classe.

Heranca

Na POO, a heranca e uma metodologia de reutilizacao de software usado sempre

que uma classe herda a estrutura e o comportamento de outra classe. Por outras

palavras, atraves do mecanismo de subclasse, e possıvel herdar atributos e compor-

tamentos (metodos) comuns da classe base (tambem designada superclasse ou classe

pai), e acrescentar as especificidades a cada uma das subclasses. Portanto, pode-se

dizer que a heranca permite a customizacao e o refinamento incremental, isto e, cada

subclasse para alem dos metodos e atributos comuns pode ter metodos e atributos

especıficos.

Seguindo o exemplo da figura geometrica, o codigo da listagem 2.3 define a classe

Triangle, que implementa uma figura geometrica triangulo.

class Shape

{...

protected:

int h, w;

9

Page 28: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.1. Programacao Orientada a Objetos

};

class Triangle : public Shape

{public:

Triangle(int h, int w) : Shape(h,w) {}double area() { return ( h∗ w)/2; }

};

Listagem 2.3: Definicao da classe Triangle como herdeira da classe Shape

Como a classe Triangle herda da classe Shape, todas as propriedades da classe

Shape sao herdadas pela classe Triangle. A classe Triangle define um novo metodo

(area), que implementa o calculo da area de um triangulo. Os atributos w e h sao

definidos pela classe base Shape, bem como os metodos publicos que permitem aceder

a esses atributos. No exemplo apresentado, a subclasse herda apenas de uma classe

base, no entanto e possıvel herdar de varias classes base (multipla heranca).

Polimorfismo

A palavra polimorfismo vem do grego e significa ”pode tomar varias formas”.

Assim, enquanto que a heranca se refere as classes (e respectiva hierarquia), o po-

limorfismo diz respeito aos metodos dos objetos. Existem essencialmente tres tipos

de polimorfismo: (i) o polimorfismo ad-hoc, (ii) o polimorfismo parametrico e (iii)

o polimorfismo de heranca ou dinamico. O polimorfismo ad-hoc permite entao ter

funcoes com mesmo nome, com funcionalidades semelhantes, em classes sem nenhuma

relacao entre elas. O polimorfismo parametrico representa a possibilidade de definir

varias funcoes do mesmo nome mas possuindo parametros diferentes (em numero

e/ou tipo). O polimorfismo dinamico permite redefinir um metodo (overwriting) em

classes que sao herdeiras de uma classe base, isto e, e possıvel fazer a especializacao

desse metodo.

A listagem 2.4 apresenta um exemplo de polimorfismo dinamico onde e definida

classe Triangle que reimplementa a funcao virtual definida na classe Shape.

class Shape

{public:

...

virtual double area() { }...

};

class Triangle : public Shape

10

Page 29: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

{public:

...

double area() { return ( h∗ w)/2; }};

Listagem 2.4: Exemplo de polimorfismo dinamico na classe Triangle

A classe Triangle ao herdar da classe Shape reimplementa o metodo area. O

metodo e reimplementado pela subclasse porque a classe base define o metodo como

virtual. Assim, se o objeto criado for do tipo Shape, e chamado o metodo area da

classe Shape. Caso contrario, se for criado um objeto do tipo Triangle, e chamado

o metodo area da classe Triangle.

Abstracao

A abstracao e mais uma das caracterısticas fundamentais da POO. Consiste numa

forma de generalizacao que permite gerir melhor a complexidade. Assim sendo, sig-

nifica que devemos considerar as qualidades e comportamentos independentemente

dos objetos a que pertencem, e daı isolarmos os atributos que um determinado grupo

de objetos tem em comum.

Em C++, uma classe e considerada abstrata desde que contenha pelo menos um

metodo virtual puro (pure virtual). Um metodo e considerado virtual puro quando

e um metodo virtual igualado a zero, ou seja, e um metodo que pode ser reescrito na

subclasse (com a mesma assinatura) igualado a zero. O codigo da listagem 2.5 e se-

melhante ao do exemplo anterior (listagem 2.4), no entanto a classe Shape e declarada

como abstrata, uma vez que o metodo area e declarado como virtual puro (listagem

2.5). Neste exemplo, pode-se dizer que a classe Shape isola as caracterısticas de um

triangulo, como de tantas outras figuras geometricas. A classe Shape e entao utili-

zada pela subclasse Triangle para herdar os seus atributos e metodos, no entanto os

ultimos devem ser implementados especificamente. Por outras palavras, a classe abs-

trata Shape serve como base para outras classes que queiram ser do mesmo grupo de

objetos (Triangle). Por isso, a classe Shape nao pode ser instanciada, daı que todos

os metodos declarados como abstratos deveram ser implementados pelas subclasses

(Triangle).

class Shape

{public:

...

11

Page 30: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.2. Sistemas Operativos

virtual double area() = 0;//pure virtual

...

};

Listagem 2.5: Declaracao da classe Shape como abstrata

2.2 Sistemas Operativos

A seccao anterior terminou com a definicao do conceito de abstracao no ambito da

programacao orientada a objetos. Um sistema operativo e tambem uma abstracao,

pois fornece uma camada de software que abstrai o utilizador das especificidades

do hardware subjacente. Basicamente, este atua como um intermediario entre o

utilizador e o hardware do computador [22]. Assim sendo, o objectivo de um sistema

operativo passa por fornecer recursos e meios ao utilizador para que este execute

os programas de forma simplificada e eficiente. Basicamente, este e responsavel por

controlar cada ficheiro, cada dispositivo, cada endereco de memoria, e cada unidade

de tempo de processamento.

2.2.1 Arquitetura dos Sistemas Operativos

O kernel constitui o nucleo de um sistema operativo. Este representa a parte

mais importante, e indispensavel, do sistema. Basicamente, um sistema operativo

esta dividido em duas partes: o espaco do kernel (modo privilegiado) e o espaco

do utilizador (modo sem privilegios). Sem isso, a protecao entre os processos seria

impossıvel. Existem essencialmente dois modelos arquiteturais (conceitos de kernel)

que permitem caracterizar os sistemas operativos: (i) monolıticos; e (ii) microkernel.

A primeira arquitetura, monolıtica, executa cada um dos servicos basicos, como

o gestor de tarefas, gestor de memoria, gestor de interrupcoes, gestor de dispositivos,

sistema de ficheiros, etc., em modo kernel (figura 2.1). Este modelo encontra-se

organizado em camadas, construıdas a partir do gestor de tarefas (modo privilegiado)

ate as interfaces com o resto do sistema operativo - bibliotecas e por cima delas

as aplicacoes (modo sem privilegios). A inclusao de todos os servicos basicos no

espaco do kernel tem tres grandes inconvenientes: o tamanho do kernel, a falta de

extensibilidade e a dificuldade de manutencao. Sempre que se pretender corrigir um

bug ou a adicionar um novo recurso, e necessario recompilar o kernel todo. Esta

12

Page 31: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

operacao consome muito tempo e recursos, pois a compilacao pode levar varias horas

e consumir avultadas quantidades de memoria.

Figura 2.1: Modelos arquiteturais de um sistema operativo: monolıtico e microkernel

Para superar as limitacoes de extensibilidade e facilidade de manutencao, surgiu

o modelo baseado em microkernel. A estrategia (figura 2.1) consistiu na reducao dos

servicos implementados no espaco do kernel. Apenas servicos basicos de comunicacao

entre processos, escalonador e gestor de memoria virtual foram implementados em

modo privilegiado. Os outros servicos do sistema (sistema de ficheiros, device dri-

vers, pager) residem no espaco do utilizador em forma de processos normais (como

servidores de chamadas). Como os servidores deixam de ser executados no espaco

do kernel, entao e necessario implementar as chamadas ”trocas de contexto”, para

permitir aos processos de utilizador entrar e sair em modo privilegiado. Como a

comunicacao deixa de ser feita de forma direta, foi necessario introduzir um sistema

de mensagens que permite a comunicacao independente e favorece a extensibilidade.

Sistema Operativo monolıtico: GNU/Linux

O sistema operativo GNU/Linux [23] e uma implementacao open source do sis-

tema Unix, desenvolvido por milhares de pessoas. Este sistema representa uma im-

plementacao tıpica de um kernel monolıtico. Todas as funcoes do sistema, incluindo

gestor de tarefas, gestor de memoria, escalonador, funcionalidades I/O e drivers sao

13

Page 32: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.2. Sistemas Operativos

implementados no espaco do kernel. O tamanho estimado do kernel monolıtico deste

sistema e de algumas dezenas de megabytes, o que resulta num processo de manu-

tencao bastante complexo e fatigante.

Sistema Operativo baseado em microkernel: QNX

O QNX (Quick Unix ) [24] e uma das implementacoes mais populares de um

sistema operativo baseado em microkernel desenvolvido para aplicacoes em tempo

real. Apenas os servicos mais basicos, como escalonador, temporizadores e signals

residem dentro do espaco do kernel, o que resulta num tamanho do kernel de 64k-byte.

Todos os outros componentes, por exemplo, pilhas de protocolos, drivers e sistema

de ficheiros, sao executado no espaco do utilizador. O kernel do QNX (designado

neutrino) e implementado em C e, portanto, pode ser facilmente adaptado para

diferentes plataformas.

2.2.2 Sistemas Operativos de Tempo-Real

Um sistema operativo de tempo-real (RTOS) e concebido para atender as necessi-

dades de aplicacoes de tempo-real. Estes sistemas sao caracterizados pelo tempo que

demoram a completar uma determinada tarefa. A finalidade neste tipo de sistemas

nao e o throughput, mas sim a garantia de cumprimento das deadlines. Num sistema

em que o incumprimento ocasional numa deadline seja aceitavel e nao cause qual-

quer dano permanente ao sistema, e designado como soft real-time, no entanto caso

seja necessario garantir determinismo e satisfacao de todos os deadlines, este e desig-

nado como hard real-time. Sistemas de audio e sistemas multimedia enquadram-se

na primeira designacao. Sistemas para controlo de processos industriais, de aviacao

e militares enquadram-se na segunda categoria.

Com efeito, nos sistemas operativos de tempo-real e mais valorizado a rapidez

e a previsibilidade da resposta do sistema, do que propriamente a quantidade de

tarefas realizadas num determinado perıodo de tempo. Portanto, a minimizacao

da latencia de interrupcao e da latencia de comutacao entre tarefas, sao aspectos

preponderantes na concepcao deste tipo de sistemas operativos. Daı que os algoritmos

de escalonamento dos RTOS sejam um pouco complexos. Alguns exemplos comuns

sao: rate-monotonic (RM), earliest deadline first (EDF) e highest priority first (HPF).

Os sistemas operativos de tempo-real e a sua aplicabilidade em sistemas embebidos

14

Page 33: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

estao intrinsecamente relacionados. A grande maioria destes sistemas operativos

sao desenvolvidos para o domınio embebido. Isto porque geralmente os RTOS sao

baseados em microkernel, o que vai de encontro a escassez de recursos dos sistemas

embebidos. Alem disso, os sistemas embebidos sao sistemas desenvolvidos com um

proposito especıfico, para realizar um conjunto restrito e dedicado de tarefas com

deadlines concretas [25]. Resumindo, existe uma correlacao estrita entre os sistemas

operativos de tempo-real e a sua aplicacao no domınio embebido. Alguns exemplos

de sistemas operativos de tempo-real para o domınio embebido sao o LynxOS [26], o

FreeRTOS [27] e QNX (referido anteriormente).

2.2.3 Sistemas Operativos Orientados a Objetos

Um sistema operativo orientado a objetos distingue-se dos sistemas operativos

tradicionais (implementados com linguagens de programacao imperativas) essencial-

mente por duas caracterısticas fundamentais.

Primeiro, porque o sistema operativo orientado a objetos deve ser desenhado e

implementado segundo o paradigma orientado a objetos. Isto significa que todo o

sistema operativo deve ser implementado atraves de um conjunto de objetos, que

representam uma instancia de cada uma das classes que o constituem. Alem disso,

os princıpios fundamentais da programacao orientada objetos (encapsulamento, he-

ranca, polimorfismo) devem ser utilizados para organizar as classes e as respectivas

inter-relacoes. Principalmente, a heranca e o polimorfismo parametrico devem ser

usados para facilitar a partilha e reutilizacao do codigo, assim como a configuracao

do sistema operativo.

Um sistema operativo disponibiliza um conjunto de interfaces/primitivas que per-

mitem as aplicacoes invocar funcoes do sistema (system calls) que implementam os

servicos pretendidos. Portanto, um sistema operativo orientado a objetos distingue-se

dos demais pois disponibiliza os seus servicos ou primitivas atraves de mensagens tro-

cadas entre objetos. Por outras palavras, num sistema operativo orientado a objetos

todas as entidades sao representadas por objetos que sao instancias das respectivas

classes. Alguns exemplos de classes a utilizar na implementacao do sistema opera-

tivo podem ser: Processor, para representar fisicamente o processador; Scheduler,

para representar o escalonador; Task, para representar uma tarefa de execucao; e

DeviceDriver, para representar um periferico.

15

Page 34: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.2. Sistemas Operativos

Vantagens dos sistemas operativos orientados a objetos

Tal como a utilizacao do paradigma da orientacao a objetos tem enumeras vanta-

gens no desenho e concepcao de aplicacoes de software, tambem os sistemas operativos

beneficiam da utilizacao deste paradigma. Assim, desenhando e concebendo um sis-

tema operativo orientado a objetos e possıvel obter vantagens sobretudo ao nıvel

da portabilidade, reutilizacao de codigo, e gestao da complexidade e manutencao do

codigo [28].

Quando se pretende desenvolver um sistema operativo portavel, e essencial iso-

lar as especificidades de determinados dispositivos em modulos separados das partes

do sistema que sao independentes da arquitetura (architecture independent modu-

les). Para isso e necessario disponibilizar interfaces dos modulos dependentes da

arquitetura (architecture dependent modules) para permitir aos projetistas desenhar

e implementar o resto do sistema operativo sem a necessidade de saber os detalhes de

implementacao desses modulos. Desta forma, e possıvel reimplementar os modulos

especıficos sempre que se pretenda alterar a arquitetura, sem contudo modificar o

resto do sistema operativo. A programacao orientada a objetos permite implementar

a portabilidade atraves das classes abstratas. Assim, estas podem ser usadas para

definir as interfaces enquanto as classes concretas implementam as especificidades dos

modulos dependentes das arquiteturas. Isto significa que criando as classes abstratas

para definir as interfaces das entidades dependentes da arquitetura e possıvel desen-

volver os algoritmos e a estrutura do sistema operativo sem conhecimento detalhado

do hardware a ser usado.

Outra das vantagens obtidas com a utilizacao do paradigma da orientacao a obje-

tos nos sistemas operativos e a reutilizacao de codigo. Geralmente, dispositivos seme-

lhantes tem caracterısticas comuns e por isso implementacoes semelhantes. Atraves

do conceito de heranca e classe abstrata e possıvel desenhar um sistema operativo

reduzindo o codigo escrito e consequentemente aumentado a produtividade. Ou seja,

as caracterısticas comuns de um recurso podem ser abstraıdas numa nova classe e as

diferencas representadas em cada uma das classes derivadas ou subclasses. Exem-

plificando, imaginemos uma classe chamada DeviceDrivers e duas subclasses dessa

classe base designadas Timer1 e Timer2 que tem caracterısticas comuns, mas cujo

codigo e repetido em cada uma das classes. Assim definindo uma classe abstrata

designada por Timer que contem tudo que e comum e derivando duas subclasses

dessa classe abstrata, e possıvel partilhar o codigo comum dos dispositivos. Alem

16

Page 35: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

disso, ainda existe o benefıcio de que efetuando qualquer modificacao na superclasse

abstrata, por exemplo, a correcao de um bug ou uma melhoria no desempenho de

uma implementacao, sera automaticamente herdada pelas subclasses concretas.

Combinando a heranca e o polimorfismo e possıvel obter no sistema operativo

benefıcios ao nıvel da optimizacao da gestao de complexidade e da manutencao do

codigo. Para entender como e possıvel optimizar recorrendo a estes conceitos convem

exemplificar. Considere-se um sistema operativo multitarefa, onde existe a possi-

bilidade de executar varias tarefas concorrentemente. Sempre que acontece uma

mudanca de contexto, isto e, sempre que e alterada a tarefa em execucao e necessario

gravar estado da tarefa em execucao, e restaurar o estado da tarefa a executar. Con-

tudo, nas tarefas existentes num sistema operativo e possıvel encontrar tarefas do

sistema e tarefas de aplicacoes. As do sistema como estao associados ao sistema nao

precisam de gravar tanta informacao numa mudanca de contexto em comparacao

com as das aplicacoes, em que e necessario gravar informacao adicional da aplicacao.

Uma forma tradicional de implementar esta situacao consiste em definir uma flag

para especificar que tipo de tarefa esta representado. Conforme o estado da flag e

entao decidido o volume de informacao a ser guardada ou restaurada. A programacao

orientada a objetos possibilita uma solucao mais simples e mais otimizada. A classe

Task pode ser criada como abstrata e as classes SysTask e AppTask como subclasses

concretas. Os metodos da subclasse SysTask podem guardar e restaurar o estado de

uma tarefa do sistema, enquanto que os metodos da subclasse AppTask guardam a

informacao adicional das tarefas das aplicacoes.

Exemplos de sistemas operativos orientados a objetos

Para a realizacao desta dissertacao e essencial selecionar um sistema operativo

orientado a objetos para efetuar o porting e upgrade do mesmo para a famılia de

microcontroladores MCS-51. Assim sendo, torna-se essencial averiguar o trabalho

desenvolvido nesta area e avaliar as solucoes existentes, para que com base nas suas

caracterısticas e propriedades perceber qual o que mais se adequa aos recursos da

arquitetura a utilizar. De seguida sao apresentados e caracterizados os sistemas ope-

rativos orientados a objetos que o autor considera mais relevantes.

Choices

O Choices [28, 29] e um sistema operativo orientado a objetos desenvolvido pela

17

Page 36: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.2. Sistemas Operativos

Universidade de Illinois em Urbana-Champaign no Estados Unidos da America. Este

foi o primeiro sistema operativo a utilizar o paradigma da orientacao a objetos, isto e,

os componentes do sistema estao encapsulados em classes e apresentam flexibilidade

para a gestao e extensibilidade. Desenvolvido em C++, o Choices foi desenhado

como uma framework que suporta a maioria das caracterısticas dos sistemas opera-

tivos de proposito geral: gestao de processos, memoria virtual, sistema de ficheiros,

dispositivos entrada/saıda (input/output - I/O) e suporte de rede.

Ao nıvel da gestao de processos, o Choices e um sistema multithread com suporte

de varios escalonadores (FIFO1, LIFO2, Round Robin3, etc.). Alem disso, oferece

mudanca de contexto otimizada, isto e, utilizando a heranca e subclasse implementa

mudanca de contexto entre processos de aplicacoes, processos do sistema ou entao

processos com interrupcao. Quanto aos mecanismos de sincronizacao de processos, o

Choices disponibiliza spin-locks 4 (lock) e busy-wait loops 5 (busy wait) para exclusao

mutua, e semaforos (semaphore) para exclusao mutua e sincronizacao. Relativamente

ao sistema de memoria virtual, este utiliza page tables independentes da maquina

alvo. No que diz respeito ao sistema de ficheiros, o Choices inclui suporte para

discos, particoes, ficheiros e diretorias conforme os sistemas standard V UNIX, BSD

4.2 UNIX ou MS-DOS. Quanto aos dispositivos I/O, o sistema tem suporte para

discos, RAM, dispositivos serie, buffers tty, entre outros. A nıvel de rede suporta

ethernet6, UDP/IP7 e TCP/IP8. Alem disso, para aqueles que queiram executar

aplicacoes UNIX, o Choices possui uma biblioteca de compatibilidade.

Resumindo, o sistema operativo Choices foi o primeiro sistema operativo orientado

a objetos desenvolvido para plataformas de proposito geral. Devido a sua arquitetura

monolıtica e extensa lista de propriedades e caracterısticas, aliado ao elevado con-

sumo de memoria (memory footprint), o autor considera que este sistema operativo

1FIFO (First-In-First-Out): algoritmo de escalonamento que determina a ordem de execucao dastarefas pela ordem de entrada no sistema

2LIFO (Last-In-First-Out): algoritmo de escalonamento que determina a ordem de execucao dastarefas pela ordem inversa de entrada no sistema

3Round Robin: algoritmo de escalonamento que atribui um tempo fixo a cada tarefa paraexecucao

4Spin-locks: mecanismo de sincronizacao de tarefas em que o lock da thread e feito em ciclo ateque o recurso esteja disponıvel

5Busy-wait loops: tecnica de programacao em que um processo verifica repetidamente se umadeterminada condicao e verdadeira

6Ethernet: padrao (IEEE 802.3) de transmissao de dados para redes locais (LAN)7UDP (User Datagram Protocol): protocolo da camada de transporte8TCP (Transmission Control Protocol): protocolo da camada de transporte

18

Page 37: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

nao se enquadra no domınio embebido, sobretudo na arquitetura MCS-51 onde os

recursos de memoria sao muito reduzidos.

Trion OS

O Trion Operating System [30] e um projeto de codigo aberto cuja intencao passa

por criar um sistema operativo moderno de 32/64-bits utilizando os conceitos e ideais

da orientacao a objetos.

Apesar do sistema operativo ainda estar em desenvolvimento, ja se encontra dis-

ponıvel para download a versao 0.2. Nesta versao, apesar de previa, e possıvel en-

contrar ja a implementacao em C++ de uma serie de funcionalidades dos sistemas

operativos: nucleo, gestao de dispositivos, gestao de memoria e gestao de tarefas.

Relativamente ao nucleo o sistema e baseado numa estrutura em microkernel com

suporte para threads, IPC (Inter Process Comunication), sincronizacao de tarefas

(mutex ), interrupcoes e excecoes. Por sua vez, o gestor de dispositivos e responsavel

por gerir os recursos do kernel, isto e, garante ao sistema o acesso a todos os recursos

de hardware, atraves da deteccao de todos os dispositivos usando tecnicas de plug

and play, informacao da BIOS e ficheiros de configuracao. Relativamente ao gestor

de memoria, este pode ser divido em tres partes: gestor de memoria fısica, gestor

de memoria virtual e gestor de memoria paginada. O gestor de memoria fısica e

responsavel por controlar o acesso a toda memoria fısica do sistema, assim como a

gestao da pilha. O gestor de memoria virtual mantem o controlo da memoria virtual

usada ou nao usada de cada espaco de endereco. O gestor de memoria paginada

sobretudo grava e carrega paginas de memoria em disco. Por fim, o gestor de tarefas

e responsavel pelo escalonamento das tarefas, isto e, e responsavel por carregar novas

tarefas e agendar as threads ja em execucao.

Resumidamente, apesar do Trion ser um sistema operativo baseado em microker-

nel, o autor considera que este tambem nao e uma solucao valida porque implementa

algumas funcionalidades (memoria paginada, memoria virtual, tecnicas plug and play,

) demasiado complexas para a plataforma alvo. Alem disso, este ainda nao atingiu

sequer uma versao estavel e final (apenas esta disponıvel a versao 0.2).

BOSS

O sistema operativo BOSS [31, 32] e um sistema operativo orientado a objetos de

tempo real desenvolvido pela FHG-FIRST, utilizado no satelite BIRD (Bi-Spectral

19

Page 38: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.2. Sistemas Operativos

Infrared Detection) [33], e outras aplicacoes roboticas no espaco.

O BOSS foi desenhado com a finalidade de reduzir a complexidade do software de

forma a garantir a confiabilidade. O nucleo do sistema operativo foi desenvolvido em

C++, e foi efetuado o porting para varias plataformas, nomeadamente para PowerPC,

x86 e Atmel AVR. Como o objectivo deste sistema operativo passa pela aplicacao em

sistemas embebidos, este foi desenvolvido seguindo um modelo arquitetural baseado

em microkernel : tem escalonador, gestor de tarefas, mecanismo de sincronizacao de

tarefas (semaphore), gestor de temporizacao e mailbox. A figura 2.2 [32] apresenta o

diagrama de classes do nucleo do BOSS.

Figura 2.2: Diagrama de classes do core do sistema operativo BOSS

Para alem do nucleo principal, o grupo de Sistemas Embebidos (ESRG) da Univer-

sidade do Minho [34] foi responsavel por introduzir suporte para tolerancia a falhas.

Assim sendo, foi desenvolvida uma framework de middleware que torna possıvel a

implementacao de um conjunto de estrategias de tolerancia a falhas, e integrada no

sistema operativo BOSS utilizando programacao orientada a aspetos (AOP - seccao

2.3.5).

Em suma, a simplicidade do BOSS assim como a utilizacao do mesmo em siste-

mas embebidos de alta fiabilidade, fazem deste sistema operativo orientado a objetos

um potencial candidato para o objectivo da presente tese. Todavia, uma vez que o

codigo do sistema operativo e fechado e proprietario, nao foi possıvel utilizar o BOSS

no trabalho de dissertacao.

20

Page 39: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

ADEOS

ADEOS [35], acronimo de A Decent Embedded Operating System, e um sistema

operativo orientado a objetos baseado em microkernel, desenvolvido por Michael Barr.

Desenvolvido em C++, o sistema operativo com cerca de 1000 linhas de codigo

fonte foi desenhado para aplicacoes em sistemas embebidos com escassez de recursos.

Apesar de compacto, este tem as funcionalidades essenciais de um sistema operativo:

gestor de tarefas, escalonador, sincronizacao de tarefas e mudanca de contexto. Re-

lativamente ao gestor de tarefas, este encarrega-se de criar novas tarefas, adicionar

e remover tarefas da lista de tarefas, e ainda colocar as tarefas em execucao. O

sistema e multitask pois permite correr varias tarefas ”simultaneamente”. No que

diz respeito ao escalonador, este e responsavel por decidir que tarefa deve executar

em cada instante de tempo e gerir as interrupcoes. A estrategia de escalonamento e

preemptiva e baseada em prioridades, isto e, a cada tarefa e associada uma priori-

dade e a tarefa que deve ser executada e a de mais alta prioridade da lista de tarefas

prontas para execucao. Quanto a sincronizacao de tarefas, e implementado o meca-

nismo de mutex, disponibilizando os metodos take e release para garantir que num

determinado instante de tempo apenas uma tarefa acede a um mesmo recurso parti-

lhado. Finalmente, a mudanca de contexto permite guardar e restaurar o estado de

uma determinada tarefa sempre que e alterada a tarefa em execucao. A mudanca de

contexto neste sistema operativo e implementada em linguagem assembly especıfica

para a plataforma 80188.

Concluindo, devido ao seu modelo arquitetural e propensao para o domınio embe-

bido, assim como o facto do codigo fonte ser livre e com possibilidade de ser facilmente

melhorado e expandido, fazem deste sistema operativo a escolha do autor para o tra-

balho a desenvolver.

Este sistema operativo sera analisado e explicado ao detalhe na seccao 3.2.

2.3 Configurabilidade e Variabilidade no Software:

tecnicas de programacao

Devido a complexidade dos sistemas atuais, o desenvolvimento de software re-

quer cada vez mais um pensamento estruturado, assim como o uso de mecanismos

que permitam desenvolver bem, de modo a minimizar os recursos de hardware ne-

cessarios, e, simultaneamente, maximizar o desempenho do sistema. Alem disso, se

21

Page 40: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.3. Configurabilidade e Variabilidade no Software: tecnicas de programacao

pensarmos no desenvolvimento de software para diferentes aplicacoes ou produtos,

para diferentes plataformas, com diferentes necessidades, e normal que a complexi-

dade de desenvolvimento cresca exponencialmente, e portanto seja necessario arranjar

mecanismos, tecnicas ou metodologias que permitam gerir toda essa variabilidade e

configurabilidade.

E neste sentido que o autor apresenta de seguida as principais tecnicas e me-

todologias de programacao utilizadas na gestao da variabilidade e configurabilidade

do software - (i) compilacao condicional, (ii) orientacao a objetos, (iii) orientacao a

componentes, (iv) orientacao a funcionalidades, (v) orientacao a aspetos, (vi) pro-

gramacao generativa -, procurando apontar os pontos fortes e os inconvenientes de

cada uma, de modo a perceber qual a mais adequada para aplicar no refactoring do

sistema operativo.

2.3.1 Compilacao Condicional

A compilacao condicional e uma estrategia de refactoring usada no ambiente de

programacao C/C++ para o desenvolvimento de software para diferentes platafor-

mas e com diferentes funcionalidades [36]. Do ponto de vista do programador, a

compilacao condicional, em conjunto com o pre-processador C/C++, e bastante facil

de aprender e aplicar no software configuravel. Diretivas de pre-processador C como

]define, ]ifdef, ]ifndef, ]if, ]else, etc., sao usadas para controlar e gerir zonas

ou trechos de codigo que devem ser incluıdos ou excluıdos conforme a condicao espe-

cificada. O exemplo da listagem 2.6 apresenta a utilizacao de compilacao condicional

num simples programa escrito em C. Caso o codigo seja compilado (por exemplo,

com o compilador da GNU - GCC [37]) com a macro DEBUG o programa mostra

no ecra a frase ” DEBUG DEFINED”, caso contrario sera mostrado ” DEBUG

not defined”.

#include <stdio.h>

int main()

{#ifdef DEBUG

printf(” DEBUG DEFINED\n”);

#else

printf(” DEBUG notdefined\n”);

#endif

return 0;

22

Page 41: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

}

Listagem 2.6: Exemplo da utilizacao de compilacao condicional

O sistema operativo Linux e o exemplo tıpico e magno da aplicacao da compilacao

condicional para gerir a variabilidade e configurabilidade do mesmo. Contudo, como

todo o codigo precisa de ser anotado com diretivas de pre-processamento, este acaba

por ficar confuso e ofuscado, tornando extremamente difıcil a manutencao e o upgrade.

Alem disso, uma vez que as anotacoes nao sao seguras, isto e, podem ser alteradas

com recurso a um simples editor de texto, faz com que esta tecnica seja propensa

a erros. A simples troca de uma letra numa diretiva de pre-processamento ou de

uma macro associada a esta, pode levar a uma inconsistencia de funcionamento. Isto

atinge uma proporcao colossal se pensarmos na quantidade de ficheiros e linhas de

codigo da maioria dos sistemas operativos UNIX atuais. Daı que esta tecnica seja

muitas vezes criticada na literatura, e tenha sido designada de ”]ifdef considered

harmful”[38] ou ”]ifdef-hell”[39].

2.3.2 Orientacao a Objetos

Outra tecnica ou metodologia que pode ser usada para gerir a variabilidade e

configurabilidade de um sistema, e a propria orientacao a objetos. Suportada pela

linguagem C++, este paradigma pode ser usado para implementar as diversas funci-

onalidades utilizando o polimorfismo dinamico. Basicamente, consiste em implemen-

tar o sistema utilizando o conceito de heranca e funcoes virtuais, gerindo as possıveis

configuracoes em runtime, o que torna o sistema dinamico e parametrizavel. No en-

tanto, este tipo de abordagem resulta numa sobrecarga excessiva de recursos, e numa

degradacao do desempenho do sistema.

2.3.3 Orientacao a Componentes

O conceito da orientacao a componentes surgiu com a visao do desenvolvimento

de software generalizado. Assim, esta metodologia pretende substituir os sistemas

de software monolıticos tradicionais, por componentes de software reutilizaveis e fra-

meworks de componentes em camadas. Desta forma, os componentes aumentam

as capacidades das frameworks, enquanto as frameworks fornecem um ambiente de

execucao para os componentes. No entanto, este termo ainda nao e totalmente aceite

na comunidade cientıfica, daı que nao exista nenhuma linguagem de programacao

23

Page 42: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.3. Configurabilidade e Variabilidade no Software: tecnicas de programacao

desenvolvida segundo este paradigma, e apenas exista suporte de orientacao a com-

ponentes em linguagens orientadas a objetos como o C++, o Java, e, mais concreta-

mente, o Lagoona. [40]

Contudo, apesar das vantagens inerentes a esta metodologia, como por exemplo,

a reutilizacao e a especializacao, o desenvolvimento de um sistema com a abordagem

orientada a componentes proporciona um overhead de recursos, da mesma magni-

tude da abordagem dinamica e parametrizavel da orientacao a objetos. Alem disso,

ainda tem a desvantagem do compilador nao possibilitar a otimizacao ao nıvel do

componente (devido ao conceito de black-box 9), o que acrescenta funcionalidades

desnecessarias as aplicacoes.

2.3.4 Orientacao a Funcionalidades

A orientacao a funcionalidades, introduzida por Prehofer em 1997 [41], e uma es-

trategia de software utilizada para combater o problema do crescimento exponencial

de classes da orientacao a objetos. Em vez de uma estrutura de classes rıgida, esta

metodologia propoe o desenvolvimento de funcionalidades que descrevem a relacao

da classe base com as suas extensoes, sem utilizar a heranca. Isto e, as funcionalida-

des sao semelhantes a subclasses abstratas, contudo com a grande diferenca de que

as funcionalidades do nucleo da subclasse sao separados dos metodos de overwriting

da classe base. Desta forma, atraves da implementacao separada dos metodos de

overwriting e possıvel resolver as dependencias e interacoes entre as diversas funcio-

nalidades, isto e, algumas funcionalidades apresentam comportamentos diferentes na

presenca de outras.

Neste sentido, com a programacao orientada a funcionalidades e construıdo um

repositorio de funcionalidades, que substitui a estrutura rıgida e convencional de uma

hierarquia de classes tradicional (figura 2.3a [41]). Conforme se pode ver pela figura

2.3b [41], para construir um objeto, em vez do tradicional metodo de heranca, as

funcionalidades sao adicionadas umas apos as outras, com uma determinada ordem.

Para adicionar interacao e construir uma especie de hierarquia de classes persona-

lizada, sao utilizados os chamados lifters. No trabalho realizado por Prehofer [41]

e possıvel encontrar pormenores de implementacao, nomeadamente um exemplo em

Java da utilizacao desta tecnica para modelacao de pilhas (stacks) com diversas fun-

9Black-box: dispositivo, sistema, ou objeto que pode ser visto apenas em termos de entradas,saıdas e caracterısticas, sem nenhum conhecimento da implementacao e funcionamento interno

24

Page 43: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

cionalidades.

(a) Hierarquia de classes tıpica

(b) Composicao de objetos no modelo defuncionalidades

Figura 2.3: Orientacao a funcionalidades: hierarquia de classes e modelo defuncionalidades

Resumindo, comparando com a programacao orientada a objetos classica, a pro-

gramacao orientada a funcionalidades fornece maior modularidade e flexibilidade. A

reutilizacao e simplificada, uma vez que para cada funcionalidade, as caracterısticas

do nucleo sao separadas das interacoes. Daı que esta tecnica tenha sido utilizada em

diferentes aplicacoes de diferentes domınios [42], nomeadamente em simuladores de

incendio do exercito Norte Americano, em protocolos de rede de alta performance, e

ferramentas de verificacao de programas.

2.3.5 Orientacao a Aspetos

Em 1997, Kiczales et al. [43] foi o responsavel por criar o conceito de orientacao

a aspetos para lidar com um problema de programacao designado por cross-cutting.

25

Page 44: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.3. Configurabilidade e Variabilidade no Software: tecnicas de programacao

De forma sucinta, sempre que duas propriedades a programar componham multiplos

elementos, e, simultaneamente, necessitem de coordenacao, entao diz-se que estas sao

transversais ou que se ”cross-cut”uma a outra. Foi na tentativa de simplificar este

problema, e melhorar o desenvolvimento e manutencao dos sistemas de software, que

Kiczales apresentou o conceito de aspetos. Um exemplo tıpico onde este problema de

cross-cutting acontece, e onde e possıvel aplicar a programacao orientada a aspetos,

e nos sistemas de autenticacao. Como a estrategia de loggin afeta necessariamente

inumeras partes do sistema, entao diz-se que o logging e transversal a todas as classes

e metodos de autenticacao.

Por outras palavras, a programacao orientada a aspetos (aspect oriented program-

ming - AOP) procura resolver o problema que geralmente uma unica dimensao da

decomposicao funcional nao e suficiente para implementar todos os aspetos de um

programa de forma modular [44]. Isto significa que o codigo que resulta de uma unica

decisao de design e amplamente disseminado por todo o sistema, ou seja, este nao

pode ser encapsulado numa unica funcao, classe ou metodo. Este tipo de codigo e

designado por aspect code. Um exemplo muito referenciado para ilustrar este efeito

consiste no codigo para efetuar sincronizacao em programas nao-sequenciais. Ape-

sar de no design ser possıvel especificar onde tem que ser introduzido o codigo de

sincronizacao, e o que este deve fazer, nao e possıvel encapsular de forma transpa-

rente. Portanto, a AOP ajuda neste dilema, pois o ambiente de desenvolvimento

desta abordagem permite implementar o cross-cutting em unidades modulares (aspe-

tos) e uma ferramenta - aspect weaver - insere os fragmentos de codigo, derivados do

codigo aspeto, onde estes sao precisos. Estes pontos de insercao sao designados por

joint points. A figura 2.4 [44] ilustra, simplificadamente, como e que o codigo aspeto

e embutido pelo aspect weaver no codigo dos componentes.

Para possibilitar o desenvolvimento e implementacao de codigo aspeto nas ferra-

mentas de desenvolvimento C++, e necessario utilizar uma extensao para a lingua-

gem, como AspectC++ [44], que atua como um pre-processador source-to-source.

2.3.6 Programacao Generativa

Todas as tecnicas e metodologias de customizacao mencionadas ate ao momento

apresentam algumas limitacoes ou inconvenientes, nomeadamente, propensao a er-

ros, consumo excessivo de recursos, debilidades no desempenho, e necessidade de

ferramentas adicionais demasiado precoces no estagio de desenvolvimento.

26

Page 45: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 2. Estado da Arte

Figura 2.4: Juncao do codigo aspeto no codigo dos componentes

Neste sentido, e numa tentativa de resolver a maioria dos problemas apontados an-

teriormente, uma outra forma de gerir a configurabilidade e variabilidade do software

consiste em usar tecnicas da programacao generativa, nomeadamente C++ template

metaprogramming (C++ TMP) [6, 7, 45, 46]. Esta metodologia acaba por ser classi-

ficada, em parte, como uma linguagem funcional, pois e processada pelo compilador

durante a fase de instanciacao dos templates, ou seja, e processada em tempo de

compilacao e nao em tempo de execucao. Desta forma, e possıvel efetuar geracao de

codigo, calculo de constantes, selecao de tipos, etc., e ao mesmo tempo gerar ape-

nas as funcionalidades pretendidas, garantindo assim codigo otimizado e ajustado as

necessidades da aplicacao. Por outras palavras, como o compilador atua momenta-

neamente como um interpretador, todo o processamento e realizado em tempo de

compilacao, resultando em codigo otimizado e especıfico para a configuracao reque-

rida, garantindo assim uma melhor gestao dos recursos e desempenho do sistema.

Contudo, apesar da potencialidade desta metodologia para a gestao de variabilidade

e customizacao de sistemas, esta apresenta um inconveniente. Caso algo de errado

aconteca durante a fase de compilacao, o compilador gera mensagens que podem ser

demasiado difıceis de interpretar, o que pode tornar crıtico e moroso o processo de

desenvolvimento. No entanto, existem ja mecanismos para minimizar o problema:

por um lado, (i) usar tecnicas que permitam a geracao de mensagens de erros custo-

27

Page 46: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

2.4. Conclusoes

mizadas; por outro lado, (ii) utilizar compiladores com melhor suporte ao template

metaprogramming.

Esta tecnica sera revista e explicada com mais detalhe na seccao 3.3.

2.4 Conclusoes

Este capıtulo, para alem de fundamentar e familiarizar a leitura do documento

com os termos tecnicos e conceitos das diferentes tematicas adjacentes ao trabalho -

programacao orientada a objetos, sistemas operativos, e variabilidade e configurabi-

lidade no software -, permitiu tomar duas decisoes fundamentais para o sucesso da

dissertacao.

A primeira esta centrada na escolha do sistema operativo orientado a objetos.

Segundo a avaliacao do autor, o sistema operativo ADEOS (codigo aberto) e a escolha

mais acertada para os recursos da plataforma alvo. Por sua vez, a decisao de utilizar

TMP para gerir a variabilidade do sistema operativo de forma estatica, promete a

geracao de codigo otimizado, sem overhead e deterioracao do desempenho do sistema.

28

Page 47: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3

Especificacao do Sistema

O capıtulo anterior permitiu expor os conceitos essenciais ao enquadramento da

tematica da dissertacao. Alem disso, foi discutido e definido o sistema operativo a

adotar, assim como a metodologia e abordagem para a gestao da variabilidade do

sistema. Neste capıtulo, por sua vez, serao explicados, numa aproximacao bottom-up,

cada uma das camadas e componentes que compoe a base do sistema a implementar.

Assim, primeiro sera explicada a arquitetura do microcontrolador 8051. Memoria,

perifericos, conjunto de instrucoes, sao alguns dos conceitos essenciais para a com-

preender a sua arquitetura. Depois disso, o sistema operativo ADEOS sera revisto,

com o objetivo de perceber detalhadamente o codigo implementado por Michael Barr

ao nıvel de escalonamento, tarefas e sincronizacao das mesmas. A tecnica de C++

template metaprogramming tambem sera novamente abordada, de modo a explicar

detalhes de implementacao, bem como exemplos de aplicacao. No fim do capıtulo

serao apresentadas algumas particularidades do compilador C++ da IAR para o 8051,

que o autor considera importantes para o sucesso do trabalho da presente dissertacao.

3.1 Microcontrolador 8051

Em 1981, a Intel Corporation [47] apresentou um microcontrolador designado por

8051. Seguindo uma arquitetura Harvard, isto e, memoria de codigo separada fisica-

mente da memoria de dados, este microcontrolador, na sua versao classica, possuıa

128-byte de RAM (memoria de dados), 4-kbyte de ROM (memoria de codigo), dois

temporizadores, uma porta serie, e quatro portas (8-bit) entrada/saıda de proposito

geral. O 8051 e um microcontrolador de 8-bit, o que significa que a unidade de proces-

29

Page 48: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.1. Microcontrolador 8051

samento apenas consegue processar 8-bit de dados a cada instante de tempo. Dados

com tamanho superior a 8-bit tem que ser divididos e processados ao byte. A figura

3.1 apresenta o diagrama de blocos dessa versao do microcontrolador. [48]

Figura 3.1: Diagrama de blocos do microcontrolador 8051 classico

Este microcontrolador tornou-se ainda mais popular quando a Intel Corporation

permitiu que outros fabricantes o reproduzissem, na condicao de que estes garantissem

compatibilidade do codigo e instrucoes do 8051 original. Isto levou ao aparecimento

de muitas versoes do microcontrolador, com diferentes configuracoes de velocidades,

tipo e capacidade da memoria de codigo e dados, e perifericos. Os microcontrolado-

res atuais baseados no nucleo do 8051 tem varias caracterısticas importantes, como

interfaces de comunicacoes I2C (seccao 4.2.2), SPI (seccao 4.2.2), CAN1, converso-

res analogico-digital (ADC), conversores digital-analogico (DAC), geradores PWM

(seccao 4.2.2), e memoria de programa Flash auto-programavel. Inclusive, recente-

mente a Texas Instruments [49] lancou uma famılia de microcontroladores baseado

no nucleo do 8051, que possui on-chip um transceiver de radio frequencia para co-

municacoes sem fios sub-1GHz (p.e. CC1111 [50]) e 2.4GHz (p.e. CC2530 [51]).

1CAN (Controller Area Network): protocolo de comunicacao desenhado especialmente para aindustria automovel

30

Page 49: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

3.1.1 Arquitetura de Memoria

O microcontrolador 8051 tem quatro memorias distintas: (i) memoria de dados

interna (RAM interna); (ii) registos de funcoes especiais (SFR - special function

registers, RAM interna); (iii) memoria de programa ou de codigo (Flash interna ou

ROM externa); (iv) e memoria de dados externa (RAM externa).

A versao original do 8051 possui 128-byte de memoria de dados interna que podem

ser enderecados direta ou indiretamente (seccao 3.1.5). Nos enderecos de 00h a 1Fh

desta memoria, estao localizados os bancos de registos. Este possui quatro bancos,

sendo, por defeito, selecionado o banco 0. No banco de registo selecionado estao

sempre mapeados oito registos de trabalho (R0 a R7) disponıveis ao programador.

Por sua vez, do endereco 20h a 2Fh estao disponıveis 128 localizacoes enderecaveis ao

bit. Isto significa que com uma unica instrucao pode-se executar operacoes booleanas

sobre os bits individuas desta area. As restantes posicoes de memoria, 30h a 7Fh,

estao livres, o que significa que estao disponıveis para armazenar dados e variaveis

definidas pelo programador. Existem outras versoes deste microcontrolador que dis-

ponibilizam mais 128-byte de dados de proposito geral. Como estes 128-byte estao

nos enderecos 80h a FFh, ou seja, os mesmos enderecos da area do SFR, o microcon-

trolador faz essa distincao atraves do enderecamento utilizado. Se a instrucao utilizar

enderecamento direto acede ao SFR. Caso a instrucao utilize enderecamento indireto

acede aos 128-byte de dados extra.

Todos os registos internos do 8051 estao mapeados nos 128-byte superiores da

memoria de dados interna. Assim sendo, nos enderecos 80h a FFh esta localizada

a area do SFR, que contem todos os registos do 8051, com excecao dos bancos de

registos de proposito geral R0 a R7. No 8051 original estao apenas definidos 21

enderecos, no entanto nos derivados mais recentes desta famılia a grande maioria dos

enderecos do SFR esta ja ocupada. Estes registos permitem o acesso e o controlo de

todos os perifericos internos do 8051.

A memoria de programa e destinada a armazenar o codigo e constantes da aplicacao.

Assim sendo, a memoria e apenas de leitura e tipicamente e implementada em

memoria ROM. Esta pode estar dentro ou fora do chip, com capacidade ate 64k-

byte, dependendo do modelo usado. Tal como ja foi referido, algumas variantes do

8051 possuem memoria flash em substituicao da memoria ROM.

A memoria externa de dados pode ser utilizada para armazenar dados e variaveis

do programador, ou simplesmente para implementar uma segunda area do SFR. Esta

31

Page 50: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.1. Microcontrolador 8051

memoria pode ser acedida atraves de acesso indireto, utilizando uma instrucao espe-

cial, de mnemonica MOVX. Atualmente, algumas versoes do microcontrolador colocam

parte desta memoria externa dentro do chip. O espaco de memoria permitido pela

arquitetura e de 64k-byte, tendo tres barramentos disponibilizados para o efeito: bar-

ramento de enderecos de 16-bit ; barramento de dados de 8-bit ; barramento de controlo

de 3-bit.

A figura 3.2 resume e ilustra o mapa de memoria generico das diferentes variantes

do microcontrolador 8051.

Figura 3.2: Mapa de memoria do 8051 generico

3.1.2 Registos Basicos

Para alem dos quatro bancos de registos de uso geral ja mencionados anterior-

mente (R0 a R7), o microcontrolador dispoe de outros registos basicos de significativa

relevancia. O registo A (Accumulator) e o registo B, ambos de 8-bits, sao utilizados

para operacoes aritmeticas. O registo PSW (Program Status Word) contem os bits

de estado que refletem o estado atual do CPU, nomeadamente as flags de carry (C),

carry auxiliar (CA), selecao do banco de registos (RS0 e RS1), overflow (OV) e pari-

dade (P). O registo IE (Interrupt Enable) permite configurar e gerir as interrupcoes.

32

Page 51: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

O registo SP (Stack Pointer) e utilizado como apontador para a pilha. O registo

DPTR (Data Pointer), de 16-bit, e muito util para enderecar memoria de dados ex-

terna e memoria de codigo. Finalmente o registo PC (Program Counter), tambem

de 16-bit, contem o endereco de memoria de programa da proxima instrucao a ser

executada.

3.1.3 Perifericos

O microcontrolador 8051, na sua versao classica, inclui essencialmente tres grupos

de perifericos: (i) portas entrada/saıda digital; (ii) contadores/temporizadores de 16-

bit ; e (iii) porta serie.

As quatro portas de entrada/saıda digital possuem quatro registos de 8-bit, mape-

ados no SFR, que permitem controla-las: P0, P1, P2 e P3. Cada um destes registos

possui oito latches2 e hardware de interface as saıdas (output drivers) e de leitura das

entradas (input buffers) que permitem implementar as funcionalidades necessarias a

uma porta de entrada/saıda digital. As oito linhas de cada uma destas portas I/O

podem ser tratadas individualmente, de modo a realizar a interface a dispositivos de

1-bit (LEDs3, ataque de MOSFETs4, etc.), ou entao como unidades para realizar a

interface paralela de 8-bit a outros dispositivos (display LCD, teclado, etc.).

Relativamente as unidades de contagem, contador/temporizador 0 e contador/-

temporizador 1, estes podem ser configurados para funcionar como temporizador

ou contador de eventos. Quando configurados como temporizadores, os registos de

contagem THx e TLx (onde x corresponde a 0 ou 1 dependendo do numero do tempo-

rizador), sao incrementados a cada ciclo maquina atraves de um sinal cuja frequencia

e 1/12 da frequencia do oscilador interno do CPU. Quando configurados como conta-

dores, os registos de contagem sao incrementados na transicao descendente do sinal

a entrada do pino P3.4 e P3.5.

A porta serie existente na famılia MCS-51 permite a transferencia no modo full-

duplex 5 e pode funcionar em varios modos e frequencias. A sua principal funcao

consiste na conversao paralelo-serie dos dados a serem transmitidos, e na conversao

serie-paralelo dos dados. O hardware da porta serie pode ser acedido atraves dos

2Latches: circuito sequencial biestavel assıncrono capaz de armazenar um bit de informacao3LED (Light-Emitting Diode): semicondutor (dıodo) emissor de luz4MOSFET (Metal Oxide Semiconductor Field Effect Transistor): transistor de efeito de campo5Full-duplex: permite comunicacao (transmissao e recepcao) em ambos os sentidos simultanea-

mente

33

Page 52: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.1. Microcontrolador 8051

Tabela 3.1: Vetores de interrupcao na famılia MCS-51

Interrupcao Flag de Interrupcao Bit SFR Endereco SFRRESET RST 00hExterna 0 IE0 TCON.1 03hTimer 0 TF0 TCON.5 0BhExterna 1 IE1 TCON.3 13hTimer 1 TF1 TCON.7 1BhPorta serie RI ou TI SCON.0 ou SCON.1 23h

pinos TxD e RxD e apresenta um buffer que permite a rececao de um segundo byte,

antes da leitura do primeiro. Pode-se configurar a porta serie para transmissao com

frequencia fixa, derivado do oscilador interno, ou variavel, atraves da programacao

do temporizador 1 (nas novas variantes do 8051 o temporizador 2 tambem pode ser

utilizado para gerar a frequencia de transmissao). [52]

3.1.4 Interrupcoes

O 8051 original apresenta duas fontes de interrupcoes externa, duas interrupcoes

das unidades contadoras/temporizadoras, e uma interrupcao da porta serie. Existem

tres registos que fornecem o controlo total sobre todas as interrupcoes do 8051: (i)

registo IE, que controla a ativacao das interrupcoes; (ii) registo IP (Interrupt Pri-

ority), que permite configurar a prioridade individual das fontes de interrupcoes; e

(iii) o registo TCON (Timer Control), que permite configurar a forma de aciona-

mento das duas interrupcoes externas. A tabela 3.1 apresenta algumas informacoes

sobre as varias fontes de interrupcao, entre os quais os enderecos das ISR, as flags de

interrupcao associadas e as SFR onde se encontram as flags.

Na ocorrencia de uma interrupcao e da aceitacao da mesma pelo processador, o

programa principal e interrompido, desencadeando o seguinte conjunto de acoes: (i) e

concluıda a execucao da instrucao atualmente em execucao; (ii) o endereco de retorno

do PC e guardado na pilha; (iii) o estado atual da interrupcao e guardado interna-

mente; (iv) as interrupcoes sao desativadas; (v) o PC e carregado com o endereco do

vetor da ISR; e, finalmente, (vi) a ISR e executada, sendo posteriormente terminada

com a instrucao de RETI.

34

Page 53: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

Tabela 3.2: Modos de enderecamento do 8051

Modo de enderecamento Codigo exemploEnderecamento imediato MOV A,#55H

Enderecamento direto MOV A,50H

Enderecamento direto por registo MOV A,R7

Enderecamento indireto por registo MOV A,@R0

Enderecamento implıcito PUSH ACC

Enderecamento indexado MOVC @A+DPTR

Enderecamento relativo SJMP loop0

Enderecamento absoluto ACALL loop1

Enderecamento longo LJMP loop2

3.1.5 Arquitetura do Conjunto de Instrucoes

A arquitetura do conjunto de instrucoes (ISA - Instruction Set Architecture) define

a interface entre o programador e o processador, isto e, fornece ao programador

toda a informacao necessaria para a interacao e comunicacao com o processador.

Por outras palavras, o ISA descreve o conjunto de instrucoes assembly suportadas

pelo processador, juntamente com as informacoes relativas aos registos acessıveis ao

programador, interacao com a memoria e gestao das interrupcoes.

Modos de Enderecamento

Independentemente do tipo de ISA, o processador, quando acede a um operando

para efetuar uma operacao de leitura ou escrita, deve especificar como e que os

enderecos de memoria e registos devem ser representados e interpretados. Uma ins-

trucao em linguagem assembly pode usar um de varios modos de enderecamento, a

partir do qual o CPU gera o endereco especificado para, posteriormente, aceder ao

subsistema de memoria. A tabela 3.2 apresenta os nove modos de enderecamento

disponıveis no 8051, assim como algumas instrucoes onde estes se aplicam.

O modo de enderecamento imediato utiliza constantes de 8 ou 16 bits como ope-

rando fonte. Esta constante e especificada diretamente na instrucao, ao inves de ser

especificada por registo ou por endereco de memoria.

No modo de enderecamento direto, a instrucao define o endereco do operando

como uma constante e o processador acede a localizacao de memoria. Este modo e

tipicamente utilizado para aceder a area de memoria do SFR.

O modo de enderecamento direto por registo e identico ao modo de enderecamento

35

Page 54: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.1. Microcontrolador 8051

direto, exceptuando o facto de ser especificado um registo (isto e, um meio endereco)

e nunca um endereco de memoria, ou seja, e o registo que contem o operando.

No modo de enderecamento indireto, a instrucao especifica o endereco de uma

localizacao de memoria que contem o endereco do operando. Isto significa que re-

quer duas referencias a memoria para ler o operando. Apenas os registos R0, R1 e

DPTR podem ser utilizados. Este modo de enderecamento e muito utilizado para

implementar o conceito de apontadores, visto o 8051 nao implementar o modo de

enderecamento indirecto por memoria (apenas suporta enderecamento indirecto por

registo).

O modo de enderecamento implıcito nao especifica explicitamente um operando

pois tem-se sempre associado um determinado registo ou a pilha. Apesar de este

modo de enderecamento nao se aplicar diretamente no 8051, as instrucoes PUSH e POP

especificam implicitamente o topo da pilha como sendo o outro operando.

O modo de enderecamento por deslocamento, nomeadamente base por registo, e

especialmente util quando se necessita aceder a dados em memoria de codigo. Neste

modo especificam-se dois operandos, onde um deles contem um endereco de memoria

e o outro o deslocamento relativo ao endereco de memoria.

O modo de enderecamento relativo e utilizado por algumas instrucoes de salto

(por exemplo, SJMP) e salto condicional (por exemplo, JNZ). O operando fornecido

pela instrucao contem um offset que sera adicionado ao endereco da instrucao atual

por forma a gerar o endereco efetivo. Este destino efetivo deve-se encontrar entre

-128 e +127 bytes da instrucao atual dado o comprimento de 8-bit do offset.

O modo de enderecamento absoluto esta associado as instrucoes ACALL e AJMP.

Estas sao instrucoes de 2-byte, que especificam um endereco absoluto de 11-bit. Aten-

dendo ao fato dos 5-bit mais significativos do PC (16-bit) nao serem modificados, estas

instrucoes permitem apenas saltos dentro de paginas de 2k-byte, onde a memoria de

codigo se encontra logicamente dividida em 32 paginas.

O modo de enderecamento longo e utilizado atraves das instrucoes LCALL e LJMP.

Estas sao instrucoes de 3-byte em que os ultimos 2-byte especificam um endereco de

destino de 16-bit. Desta forma e possıvel percorrer os 64k-byte de memoria de codigo.

Tipos de Instrucoes

O microcontrolador 8051 disponibiliza 255 instrucoes assembly [53], agrupadas

em tres grupos funcionais: (i) instrucoes logicas e aritmeticas; (ii) instrucoes de

36

Page 55: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

transferencia de dados; e (iii) instrucoes de controlo.

As instrucoes logicas e aritmeticas caracterizam-se por modificarem o valor do

operando destino. Instrucoes que efetuam a soma, subtracao, multiplicacao, divisao

ou deslocamento, sao classificadas como instrucoes aritmeticas, enquanto as que efe-

tuam o e-logico, ou-logico, xor-logico e complemento, sao designadas por instrucoes

logicas. As instrucoes do tipo set ou clear, podem ser classificadas como logicas ou

aritmeticas. As operacoes aritmeticas tem a particularidade de afectarem as flags do

processador, nomeadamente, carry, carry auxiliar, overflow, e paridade. [52]

Por sua vez, as instrucoes de transferencia de dados nao modificam os dados

originais, pois estes nao sao removidos da sua localizacao, apenas sao copiados para

uma nova localizacao. As instrucoes que efetuam a transferencia de dados podem ser

divididas em tres grandes tipos: (1) MOV destino, fonte; (2) PUSH fonte ou POP

fonte; e (3) XCH destino, fonte. [52]

Finalmente, as instrucoes de controlo alteram o fluxo de execucao do programa

e efetuam o fetch da proxima instrucao de uma localizacao de memoria diferente do

endereco consecutivo. Normalmente, alteram o valor do registo PC com um endereco

de uma instrucao diferente da instrucao consecutiva, e o proximo ciclo de fetch usa

este novo endereco colocado no registo PC para obter a proxima instrucao. Tal como

as instrucoes de transferencia de dados, tambem as instrucoes de controlo podem ser

divididas em tres tipos: (1) salto condicional; (2) salto incondicional; e (3) gestao de

subrotinas e interrupcoes. [52]

3.2 ADEOS: A Decent Embedded Operating Sys-

tem

Acronimo de ADEOS, A Decent Embedded Operating System e um sistema ope-

rativo orientado a objetos desenvolvido em C++ por Michael Barr. Foi desenvolvido

para aplicacoes embebidas, daı que o numero de linhas do codigo fonte seja infe-

rior a 1000. A maioria do codigo foi implementado independente da arquitetura e

seguindo o paradigma de abstracao da programacao orientada a objetos. Por isso,

a maioria das funcionalidades estao estruturadas em classes, sendo apenas escritas

em linguagem assembly tres rotinas especıficas ao processador 80188 [54]. Portanto,

para fazer o porting do sistema operativo para a plataforma 8051, apenas devem ser

re-implementadas estas tres rotinas.

37

Page 56: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.2. ADEOS: A Decent Embedded Operating System

As funcionalidades implementadas pelo sistema operativo sao mınimas, mas as

essenciais para o correto funcionamento do mesmo: gestor de tarefas (Task), escalo-

nador (Sched) e sincronizacao de tarefas (Mutex ). A figura 3.3 apresenta o diagrama

de classes do ADEOS.

Figura 3.3: Diagrama de classes do ADEOS

3.2.1 Tarefas

Quando se fala de um sistema operativo multitarefa (multitasking) significa que o

sistema operativo possibilita a execucao de varias tarefas ”ao mesmo tempo”. No en-

tanto, em arquiteturas com um unico processador (single-processor) e nucleo (single-

core), como e o caso da famılia MCS-51, as tarefas nao sao executadas paralelamente,

mas sim de forma pseudo-paralela.

38

Page 57: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

Desta forma, o sistema operativo e responsavel por decidir que tarefa executara

em instante de tempo. Portanto, durante a comutacao da tarefa este deve guar-

dar a informacao sobre o estado de cada tarefa, designado como contexto da tarefa

(context). O mecanismo de comutacao de contexto guarda o estado do processador

antes de outra tarefa assumir o controlo do mesmo, e de seguida restaura o estado

da tarefa selecionada para execucao. Esse estado consiste basicamente no apontador

para a proxima instrucao a ser executada, no endereco do topo da pilha da tarefa, e

o conteudo dos registos e flags do processador.

Neste sentido, para manter as tarefas e respetivos contextos organizados, o sistema

operativo retem a informacao de cada tarefa. Essa informacao e guardada sob a forma

de estruturas de dados designados por task control block (TCB). No ADEOS a classe

(Task) (listagem 3.1) e uma implementacao C++ do TCB.

class Task

{public:

Task (void (∗function)(), Priority, int stackSize);

TaskId id;

Priority priority;

TaskState state;

Context context;

int ∗ pStack;

Task ∗ pNext;

void (∗entryPoint)();

private:

static TaskId nextId;

};

Listagem 3.1: Declaracao da classe Task

Nesta classe importa explicar os atributos id, priority, state, context, pStack,

pNext. O id contem um numero inteiro (entre 0 e 255) que identifica a tarefa. O

priority identifica a prioridade da tarefa. O state informa sobre o estado da tarefa,

isto e, se a tarefa esta em execucao, se esta pronta a executar ou se esta em espera.

O context e a estrutura de dados que contem o estado do processador da ultima vez

que a tarefa teve acesso a execucao. O pStack e um apontador para o topo da pilha

da tarefa (isto e, stack frame da tarefa). Finalmente, o pNext e um apontador para a

proxima entrada TCB de uma das possıveis tarefas, estando a lista ligada ordenada

por prioridade.

39

Page 58: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.2. ADEOS: A Decent Embedded Operating System

Estado das Tarefas

Conforme foi referido anteriormente apenas uma tarefa pode usar o processador

em cada instante de tempo. Portanto, essa tarefa e designada como a tarefa em

execucao (running), e e a unica que pode ter associado esse estado em cada instante

de tempo. Por sua vez, tarefas que estao prontas a executar mas que nao estao a

usar o processador encontram-se no estado ready, enquanto que tarefas que estao

bloqueados a espera de um evento externo sao tarefas no estado waiting. A figura

3.4 ilustra a relacao entre os tres estados que podem ser associados a uma tarefa.

Figura 3.4: Relacao dos estados das tarefas no ADEOS

Uma transicao entre o estado ready e running ocorre sempre que o escalonador

do sistema operativo seleciona uma nova tarefa para executar. Por outras palavras, a

tarefa que estava em execucao passa para o estado ready, e a nova tarefa passa para

execucao (running). Desde que uma tarefa esteja em execucao, esta apenas transita

desse estado para outro se for forcada pelo escalonador do sistema operativo ou entao

se tiver de esperar que um determinado evento externo ocorra. Nesse caso a tarefa

e colocada em estado waiting e uma nova tarefa e colocada em execucao. Logo que

esse evento externo ocorra a tarefa e entao colocada no estado ready. Resumindo,

embora possa haver varias tarefas no estado ready e waiting, apenas uma e so uma

tarefa pode estar no estado running em cada instante de tempo.

Mecanismos das Tarefas

Qualquer classe definida numa linguagem de programacao tem sempre associada

um conjunto de rotinas. Neste sentido, tambem a class Task tem o seu proprio

grupo de rotinas que permitem fazer a gestao das tarefas. No entanto, a interface

das tarefas no ADEOS e mais simples que na maioria dos sistemas operativos, pois

40

Page 59: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

a unica funcionalidade disponıvel consiste em criar objetos dessa classe. Isto porque

o ADEOS distingue-se dos demais RTOS no mecanismo de controlo de execucao

das tarefas. Este e baseado numa maquina de estados com apenas tres estados,

ao contrario da maioria dos RTOS que apresentam um quarto estado (por exemplo

Dead) indicando a conclusao de execucao da tarefa. Este estado e que indica que

a tarefa deve ficar fora do processo de escalonamento. No entanto, no ADEOS nao

e obrigatorio que a rotina da tarefa seja implementada em corpo infinito. Como a

primeira execucao da tarefa e efetuada utilizando a funcao Run (listagem 3.2), se o

corpo da tarefa nao for implementada com um ciclo infinito, assim que a esta termine

o sistema operativo retorna a funcao run, que e responsavel por excluir a tarefa da

lista de tarefas prontas a executar, e colocar uma nova tarefa em execucao (ponto de

escalonamento).

void run(Task ∗ pTask)

{// Start the task, by executing the associated function.

pTask−>entryPoint();

enterCS();////// Critical Section Begin

// Remove this task from the scheduler’s data structures.

os.readyList.remove(pTask);

os.pRunningTask = NULL;

// Free the task’s stack space.

delete pTask−>pStack;

os.schedule(); // Scheduling Point

// This line will never be reached.

}

Listagem 3.2: Funcao de iniciacao das tarefas - run

Voltando de novo ao construtor da classe Task (listagem 3.3) este recebe tres

parametros de entrada. O primeiro parametro, function, e um apontador para

a funcao a ser executada pela nova tarefa. O segundo parametro, p, e um numero

unico entre 1 e 255 que representa a prioridade da nova tarefa relativamente as outras

tarefas no sistema. Estes numeros sao usados pelo escalonador quando seleciona uma

nova tarefa para execucao (255 representa a prioridade maxima). Por fim, o terceiro

parametro, stackSize, consiste no numero de bytes que devem ser reservados para

a pilha da tarefa.

Task::Task(void (∗function)(), Priority p, int stackSize)

{stackSize /= sizeof(int);// Convert bytes to words.

enterCS();////// Critical Section Begin

41

Page 60: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.2. ADEOS: A Decent Embedded Operating System

// Initialize the task−specific data.

...

// Initialize the processor context.

contextInit(&context, run, this, pStack + stackSize);

// Insert the task into the ready list.

os.readyList.insert(this);

os.schedule();// Scheduling Point

exitCS();////// Critical Section End

};

Listagem 3.3: Construtor da classe Task

Relativamente ao corpo do construtor, pode-se verificar que a rotina e envolvida

por duas macros: enterCS e exitCS. O bloco de codigo entre estas duas macros e

designado por seccao critica. Uma seccao crıtica e um pedaco de programa que deve

ser executado de forma atomica, ou seja, o codigo deve ser executado sequencial-

mente e sem interrupcoes. Assim sendo, basicamente o que essas macros fazem e

habilitar e desabilitar as interrupcoes de forma a garantir a atomicidade do codigo a

ser executado.

Nesse bloco de codigo atomico importa referenciar especialmente a chamada de

tres funcoes: contextInit, os.readyList.insert e os.schedule. A rotina de

contextInit estabelece o contexto inicial de uma tarefa. A segunda rotina adi-

ciona a tarefa a lista de tarefas prontas a executar do sistema operativo. Esta lista e

um objeto do tipo TaskList, que consiste numa lista ligada de tarefas ordenada por

prioridade. Finalmente, a rotina os.schedule invoca o escalonador do ADEOS de

forma a decidir que tarefa deve ser colocada em execucao.

3.2.2 Escalonador

O escalonador e a fracao do sistema operativo que decide que tarefa sera escolhida

para execucao em cada instante de tempo. No entanto, o metodo de decisao ou, por

outras palavras, o algoritmo de escalonamento pode ser diferente. Nos sistemas ope-

rativos de tempo-real e necessario que a estrategia de escalonamento permita que as

tarefas mais importantes entrem em execucao com a menor latencia possıvel. Daı que

a maioria dos RTOS utilizem algoritmos de escalonamento baseado em prioridades

com preempcao.

Quando um algoritmo baseado em prioridades e implementado, e necessario im-

plementar tambem uma estrategia de ”desempate”. Por outras palavras, e necessario

estabelecer uma regra que permita definir que tarefa deve ser executada no caso de

42

Page 61: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

existirem varias tarefas com a mesma prioridade. A estrategia mais usada nesses

casos e o algoritmo round robin. No caso do ADEOS, tal como ja foi referido, o esca-

lonador tambem e baseado em prioridades. No entanto, por questoes de simplicidade

a estrategia de ”desempate”implementada consiste no algoritmo FIFO.

Pontos de Escalonamento

Os pontos de escalonamento (scheduling points) podem ser designados como even-

tos do sistema operativo que desencadeiam a invocacao do escalonador.

Neste sentido, podemos desde ja estabelecer dois pontos de escalonamento: na

criacao de tarefas e na eliminacao das mesmas. Na ocorrencia destes eventos, o

metodo os.schedule e invocado de forma a selecionar a proxima tarefa a ser exe-

cutada. Se a tarefa atualmente em execucao ainda for a de maior prioridade, entao

esta continuara a usar o processador. Caso contrario, a tarefa de maior prioridade

da lista de tarefas (readyList) sera executada. A eliminacao da tarefa e feita pelo

sistema operativo utilizando o metodo run explicado anteriormente. Isto significa

que o ADEOS nao fornece nenhum servico para de forma explicita matar uma tarefa.

Um terceiro ponto de escalonamento acontece aquando do ”clock-tick”. O clock-

tick e um evento periodico desencadeado pelo trigger da interrupcao do temporizador.

No ADEOS, este e responsavel por acordar as tarefas que estao a espera que um

determinado temporizador por software termine a contagem. Na verdade, a utilizacao

de temporizadores por software e uma funcionalidade comum em sistemas operativos

embebidos. Com a ocorrencia do clock-tick o sistema operativo decrementa e verifica

os temporizadores por software ativos, e caso algum finalize a contagem todas as

tarefas colocadas em estado waiting a espera da temporizacao sao comutadas para o

estado de ready. De seguida, o escalonador e invocado e e verificada se alguma das

novas tarefas ”acordadas”tem associada uma prioridade mais elevada que a tarefa em

execucao antes da interrupcao temporal.

Ready list

O escalonador, para gerir as tarefas que estao prontas a ser executadas, usa uma

estrutura de dados chamada readyList, implementada com uma lista ligada ordenada

pela prioridade da tarefa. Portanto, na cabeca da lista esta sempre a tarefa pronta a

executar com a prioridade mais elevada, e na cauda da lista a tarefa com prioridade

mais baixa. A figura 3.5 ilustra a lista ligada explicada. A principal vantagem da lista

43

Page 62: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.2. ADEOS: A Decent Embedded Operating System

ligada ordenada e a facilidade e rapidez com que o escalonador seleciona a proxima

tarefa a executar, pois e sempre a tarefa no topo da lista.

Figura 3.5: Ilustracao da lista de tarefas prontas a executar (readyList)

Tarefa Idle

Na eventualidade de nao haver tarefas prontas a executar (no estado ready)

quando o escalonador e chamado, e entao necessario garantir a existencia de uma

tarefa para ser executada. Essa tarefa e designada por idle task e e semelhante em

muitos dos RTOS. Consiste simplesmente num ciclo vazio infinito que mantem ocu-

pado o processador a saltar sempre para a mesma instrucao. No entanto, em sistemas

operativos mais avancados, esta tarefa e explorada na gestao do consumo, para evi-

tar desperdıcios de energia desnecessarios. Inclusive, isso acontece no trabalho da

presente dissertacao (seccao 4.2.3).

No ADEOS, a idle task tem associado um identificador e uma prioridade validos,

sendo zero em ambos os casos. Assim sendo, essa tarefa esta sempre presente na

readyList, e devido a sua baixa prioridade, e a tarefa da cauda da lista. Desta

forma, o escalonador executara esta tarefa apenas quando nao existirem mais tarefas

prontas para execucao.

Algoritmo Escalonamento

Uma vez que e usada uma lista ligada ordenada para gerir as tarefas prontas a

executar, o algoritmo de escalonamento torna-se bastante simples de implementar.

Em poucas palavras, este simplesmente verifica se a tarefa em execucao e a tarefa do

topo da lista sao a mesma. Se sao, entao nao e preciso escalonar. Caso contrario, e

necessario comutar de contexto e colocar em execucao a tarefa do topo da readyList.

A implementacao C++ do algoritmo de escalonamento do ADEOS pode ser visto na

listagem 3.4.

void Sched::schedule(void)

44

Page 63: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

{...

// If there is a higher−priority ready task, switch to it.

if (pRunningTask != readyList.pTop)

{pOldTask = pRunningTask;

pNewTask = readyList.pTop;

pNewTask−>state = Running;

pRunningTask = pNewTask;

if (pOldTask == NULL)

{contextSwitch(NULL, &pNewTask−>context);

}else

{pOldTask−>state = Ready;

contextSwitch(&pOldTask−>context, &pNewTask−>context);

}}

}

Listagem 3.4: Metodo schedule da classe Sched

3.2.3 Sincronizacao de Tarefas

Num sistema operativo multitarefa, a maioria das tarefas executadas concorrente-

mente nao funcionam como entidades completamente independentes. Muitas vezes,

as varias tarefas trabalham cooperativamente no sentido de resolver problemas de

maior complexidade, daı que necessitem de comunicar entre elas para sincronizar as

suas atividades. Por exemplo, num sistema de controlo em que se faz amostragem

de dados e se aplica controlo PID (Proportional-Integral-Derivative), a tarefa res-

ponsavel pela aplicacao do algoritmo de controlo nao pode ser executada ate que a

amostra seja fornecida pelo ADC. Uma forma de resolver esse problema e usar um

mecanismo designado por mutex.

Assim sendo, os mutexes sao disponibilizados pelo sistema operativo para auxiliar

na sincronizacao de tarefas. No entanto, nao sao a unica forma de o fazer. Existem

outros mecanismos de sincronismo e comunicacao, como os semaphores, message

queues6 e shared memory7. Na verdade, o mutex e um tipo especial de semaphore

6Message queue: mecanismo de comunicacao entre tarefas que utiliza queues para enviar men-sagens entre os processos/threads

7Shared memory: mecanismo que utiliza porcoes reservadas de memoria para a troca de dadosentre tarefas

45

Page 64: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.2. ADEOS: A Decent Embedded Operating System

designado binario ou mesmo mutuamente exclusivo. Em poucas palavras, um mu-

tex pode ser definido como um sinalizador multitarefa, isto e, havendo um recurso

partilhado por mais que uma tarefa, logo que uma das tarefas associe e sinalize esse

recurso com o mutex, entao mais nenhuma das tarefas pode aceder a esse recurso ate

que a tarefa desative o sinalizador.

No caso do ADEOS, para sincronizacao de tarefas o mecanismo disponıvel sao

os mutexes. Utilizando a classe Mutex e possıvel criar e destruı-los, e ainda ativar

ou desativa-los. Estas duas ultimas operacoes sao fornecidas pelos metodos take e

release. O processo de criacao de um novo mutex (listagem 3.5) e bastante simples:

todos os mutexes sao criados com estado available, e associados a uma lista ligada de

tarefas em estado waiting inicialmente vazia. No entanto, claro que uma vez criado

um mutex e necessario arranjar alguma forma de mudar o seu estado. Neste sentido,

foram implementadas no ADEOS os metodos take e realese.

Mutex::Mutex()

{enterCS();////// Critical Section Begin

state = Available;

waitingList.pTop = NULL;

exitCS();////// Critical Section End

}

Listagem 3.5: Construtor da classe Mutex

No que diz respeito ao metodo take este deve ser chamado por uma tarefa antes

de aceder a um recurso partilhado. Por outras palavras, este metodo garante a

tarefa exclusividade sobre o recurso. Se o mutex ja estiver associado a uma tarefa

(sinalizador binario ativado), a outra tarefa que o invocou sera suspensa ate que o

mutex seja libertado. E possıvel que varias tarefas estejam em espera do mesmo

mutex, todavia uma vez que a lista de espera e ordenada pela prioridade das tarefas,

assim que o mutex e libertado apenas a tarefa de maior prioridade e ”acordada”.

Relativamente ao metodo release, embora este possa ser invocado por qualquer

tarefa, e expectavel que apenas o invoque a tarefa que anteriormente tenha chamado

o metodo take. Isto significa que apenas faz sentido que a tarefa que sinalizou o

acesso a um recurso seja a mesma a libertar esse recurso. Um possıvel resultado de

libertar o mutex pode ser o de ”acordar”uma tarefa de maior prioridade. Nesse caso,

a tarefa que libertou o recurso deve ser forcada a ceder a execucao a tarefa de maior

prioridade que estava a espera desse mesmo recurso.

46

Page 65: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

3.3 Template MetaProgramming

Descoberta a possibilidade de aplicacao em 1994 por Erwin Unruh, e aplicada

em 1998 por Krzysztof Czarnecki [6], o template metaprograming e uma tecnica que

utiliza templates para gerar e manipular o codigo de uma aplicacao em tempo de

compilacao (compile time) [45]. Assim, com a utilizacao desta tecnica e possıvel

expandir as capacidades do compilador, permitindo que atue momentaneamente como

um interpretador, de forma a produzir configuracoes estaticas e otimizadas.

A sintaxe e idiomas do TMP sao isotericos quando comparados com a pro-

gramacao convencional em C++. Por outras palavras, o codigo TMP (codigo estatico

C++) e consideravelmente diferente, e mais difıcil de perceber, que o codigo C++

standard (codigo dinamico C++). O codigo C++ dinamico e imperativo e orientado

a objetos, enquanto o codigo C++ estatico pode mesmo ser considerado funcional.

Como o TMP pode ser considerado uma linguagem de programacao funcional, este

nao possui variaveis, atribuicoes, e iteracoes. O codigo e baseado no conceito de

funcoes matematicas, onde cada passo do processo e separado em multiplos casos, e,

normalmente, utiliza as funcoes recursivamente.

3.3.1 Blocos Basicos do Template Metaprogramming

O codigo C++ TMP e composto essencialmente por quatro blocos basicos: (i)

valores; (ii) funcoes; (iii) saltos condicionais; e (iv) recursividade. [55]

Em TMP as ”variaveis”nao podem ser modificadas, uma vez que sao nomes pre-

definidos (typedefed) e constantes. Caso seja requerido um novo tipo ou valor, este

deve ser implementado dessa forma. O codigo da listagem 3.6 mostra como se faz

essa definicao.

// named value definition

struct NamedValue

{typedef int value;

} ;

// integer value definition

struct IntegerValue

{enum { value = 2 } ;

} ;

...

// using named and integer values

47

Page 66: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.3. Template MetaProgramming

NamedValue::value var = 19;

int x = IntegerValue::value;

Listagem 3.6: Valores em template metaprogramming

As funcoes, ou mais precisamente metafuncoes, sao definidas em TMP utilizando

estruturas ou classes. Para passar meta-argumentos as metafuncoes sao utilizados

argumentos template. Para definir o valor ou tipo de retorno sao utilizados nomes

pre-definidos ou valores inteiros. A listagem 3.7 apresenta um exemplo de uma me-

tafuncao para a adicao de dois inteiros.

// function definition

template<int X, int Y>

struct Add

{// define the result type

typedef int result type;

// store the result value

enum { result = X + Y } ;

} ;

...

// call Add function

Add::result type var = Add<2,3>::result;

Listagem 3.7: Funcoes em template metaprogramming

Sempre que sejam necessarios utilizar construtores condicionais, sao usadas as

templates especializadas. Em compile time o compilador instancia a template que

melhor se identifica com os meta-argumentos especificados. O codigo da listagem 3.8

implementa a especializacao de templates para verificar se dois tipos sao identicos

(is same).

// generic implementation

template<typename T, typename U>

struct is same

{enum { result = 0 } ;

} ;

// partial specialized implementation

template<typename T>

struct is same<T, T>

{enum { result = 1 } ;

} ;

...

48

Page 67: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

// check if the provided types are the same

bool value = is same<int, char>::result;

Listagem 3.8: Saltos condicionais em template metaprogramming

Tal como nas linguagens funcionais, tambem o codigo TMP utiliza recursividade

em vez da iteracao (ciclos). Para parar a recursao, e definida uma template especi-

alizada. A listagem 3.9 implementa uma metafuncao para o calculo da soma dos n

primeiros numeros inteiros.

// generic implementation

template <unsigned n>

struct sum

{enum { value = n + sum<n − 1>::value } ;

};// stop condition

template <>

struct sum<0>

{enum { value = 0 } ;

};

...

// call sum metafunction

int result = sum<4>::value;

Listagem 3.9: Recursividade em template metaprogramming

3.3.2 O Fatorial

Um exemplo basico para demonstrar as potencialidades do C++ template me-

taprogramming consiste no calculo do fatorial de um numero. A implementacao

standard (dinamica) para o calculo do fatorial, consiste na implementacao de uma

funcao iterativa ou recursiva, que e invocada durante a execucao da aplicacao. O

codigo da listagem 3.10 apresenta a implementacao recursiva em linguagem C++.

// dinamic factorial function

int factorial(int n)

{if(n == 0)

{return 1;

}return n ∗ factorial(n − 1);

}

49

Page 68: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.3. Template MetaProgramming

...

// call factorial function

int value = factorial(3);

Listagem 3.10: Implementacao C++ recursiva do calculo do fatorial

Com esta implementacao, o resultado do fatorial do numero tres e conhecido em

tempo de execucao. No entanto, em tempo de compilacao, o numero para o qual se

pretende calcular o fatorial ja e conhecido. Assim sendo, utilizando C++ TMP, e

possıvel calcular em compile time o resultado da constante correspondente ao fatorial

de tres. O codigo apresentado na listagem 3.11 traduz a implementacao estatica em

TMP do calculo do fatorial desse numero.

// generic implementation

template<int n>

struct Factorial

{enum {value = Factorial<n−1>::value ∗ n};

};// specific implementation/stop condition

template<>

struct Factorial<0>

{enum {value = 1};

};

...

// call factorial metafunction

int value = Factorial<3>::value;

Listagem 3.11: Implementacao C++ TMP recursiva do calculo do fatorial

De forma sucinta, o primeiro trecho de codigo implementa a template generica do

calculo do fatorial, enquanto o segundo implementa a template especializada para a

condicao de paragem da recursao. A figura 3.6 ilustra o processo que o compilador

utiliza para resolver os templates no calculo do fatorial.

Para ter uma ideia do nıvel de optimizacao do codigo gerado com a utilizacao

do TMP, o autor decidiu avaliar, nesta fase preliminar, o desempenho e os recursos

de memoria de cada uma das aplicacoes (estatica e dinamica), implementadas no

microcontrolador 8051. O desempenho da aplicacao foi obtido utilizando o debugger

do ambiente de desenvolvimento, enquanto a memoria de codigo (sem otmizacoes do

compilador) foi conseguida com a utilizacao do FLIP da Atmel [56]. A tabela 3.3

apresenta os resultados obtidos.

50

Page 69: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

Figura 3.6: Resolucao dos templates no calculo do fatorial

Tabela 3.3: Resultados de desempenho e memoria das aplicacoes Fatorial (C++dinamico) e Fatorial (TMP)

Aplicacao Tempo execucao (ciclos relogio) Memoria de codigo (bytes)Fatorial (C++ dinamico) 2578 300

Fatorial (TMP) 8 53

3.3.3 Lista Ligada Estatica

Um exemplo mais avancado que ilustra a aplicabilidade do TMP consiste na

implementacao estatica de uma lista ligada (linked list). Uma lista ligada e uma

estrutura de dados que consiste num grupo de nos, que globalmente representam uma

sequencia. De forma simplificada, cada no e composto por dados e uma referencia

(link) para o proximo nodo da sequencia.

A implementacao estatica da lista ligada e semelhante a lista ligada dinamica, no

entanto tudo e resolvido em compile time, reduzindo o tempo de execucao de uma

determinada tarefa, e aumentando portanto o desempenho do sistema. Por exemplo,

supondo que se pretende determinar o numero de ocorrencias da letra ’a’ num ficheiro

de texto, a ideia passa por implementar uma lista ligada estatica em que cada nodo da

lista e preenchida com um caracter do ficheiro de texto. Depois disso, basta percorrer

a lista ligada e incrementar um contador a cada ocorrencia do caracter ’a’. O codigo

da listagem 3.12 apresenta a implementacao de uma lista ligada estatica de inteiros.

const int endValue = ˜(˜0u >> 1); //lowest integer value

//Linked List Implementation

struct End

51

Page 70: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.4. Ambiente de Desenvolvimento

{enum { head = endValue};typedef End Tail;

};template<int head , typename Tail = End>

struct Cons

{enum { head = head };typedef Tail Tail;

};

...

//Create a Linked List

Cons<1, Cons<2, Cons<3, End> > >;

Listagem 3.12: Implementacao C++ TMP de uma lista ligada estatica de inteiros

Com esta lista e possıvel implementar metafuncoes para determinar, por exemplo,

o tamanho (length), ou entao se esta vazia (is empty). A listagem 3.13 apresenta a

metafuncao Lenght. A metafuncao utiliza recursividade, implementando portanto a

template generica e a template especıfica para a condicao de paragem.

// LL Length Implementation

template<typename List>

struct Lenght

{enum { value = Lenght<typename List::Tail>::value + 1 };

};template<>

struct Lenght<End>

{enum { value = 0 };

};

Listagem 3.13: Metafuncao Length da lista ligada estatica

Resumindo, em tempo de compilacao e possıvel definir a lista ligada, assim como

utilizar as metafuncoes para determinar algumas das suas caracterısticas. Mais uma

vez, so para mostrar o poder de otimizacao das implementacoes com TMP, e apresen-

tado na tabela 3.4 uma pequena aplicacao em C++ com TMP e o respectivo codigo

assembly gerado pelo compilador para a arquitetura 8051.

3.4 Ambiente de Desenvolvimento

Nos sistemas informaticos de proposito geral, assim como nos sistemas embe-

bidos, para converter o codigo fonte de uma aplicacao, escrito numa linguagem de

52

Page 71: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

Tabela 3.4: Codigo C++ TMP e codigo assembly da aplicacao estatica do fatorial

Codigo C++ com TMP Codigo assembly

void main (){

typedef Cons<1,Cons<2,Cons<3,End>>> list1;P0 = Lenght<list1>::value;P0 = IsEmpty<list1>::value;

}

main:CODE; Auto size: 0; P0 = list1.lenght (3)MOV 0x80,#0x3; P0 = list1.isEmpty (1)MOV 0x80,#0x1RET

programacao de alto nıvel, para codigo objeto ou mesmo codigo maquina, e necessario

recorrer sobretudo a tres ferramentas: (i) compilador, (ii) assembler e (iii) linker.

Os compiladores podem ser definidos como programas para computador que tra-

duzem uma linguagem para outra [57]. Por outras palavras, um compilador recebe

como entrada o codigo fonte de uma determinada aplicacao, e produz como saıda um

programa semanticamente equivalente, porem escrito noutra linguagem. Geralmente,

o codigo fonte e escrito numa linguagem de alto nıvel, como C ou C++, e e conver-

tido para codigo objeto especıfico ao processador. Por sua vez, um assembler traduz

o codigo em linguagem assembly para codigo objeto ou codigo maquina proprio do

processador [57] (3.7a). A linguagem assembly e uma forma simbolica da linguagem

maquina dos processadores e e particularmente facil de traduzir. As vezes, alguns

compiladores geram mesmo codigo assembly como saıda, e de seguida chamam o as-

sembler para concluir a traducao em codigo objeto (3.7b). Tanto os compiladores

como os assemblers muitas vezes dependem de um programa chamado linker. Esta

ferramenta e entao responsavel pela fusao de todo o codigo relocatable (codigo que

tem sımbolos por resolver, que o compilador nao reconhece porque compila os fi-

cheiros separadamente) presente nos ficheiros objetos, num unico ficheiro executavel

[57].

Tal como foi referido na seccao 3.2, o sistema operativo ADEOS foi desenhado se-

gundo o paradigma da orientacao a objetos, sendo portanto implementado com uma

linguagem de programacao orientada a objetos, concretamente C++. Alem disso,

determinadas rotinas crıticas do sistema operativo estao implementadas em lingua-

gem assembly. Neste sentido, para traduzir esse codigo fonte escrito em C++ para

codigo assembly ou codigo objecto, e necessario um compilador C++ para o proces-

sador alvo, ou seja, um compilador C++ para o 8051. Mais, e tambem necessario

um assembler e um linker para o 8051, de modo a converter o codigo assembly das

rotinas crıticas em codigo objeto, e fundir todo o codigo objecto e traduzir em codigo

53

Page 72: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.4. Ambiente de Desenvolvimento

(a) (b)

Figura 3.7: Processo de compilacao de codigo fonte em codigo executavel/maquina

maquina especıfico ao processador, respectivamente.

Com efeito, o autor investigou quais os ambientes de desenvolvimento disponıveis

no mercado que integrassem as ferramentas especificadas anteriormente. As solucoes

encontradas foram unicamente duas: (i) Ceibo 8051 C++ Compiler + Keil uVision

IDE [58] e (ii) IAR Embedded Workbench for 8051 [59]. Relativamente a primeira,

consiste na integracao do compilador C++ da Ceibo com o software Keil, permitindo

assim a compilacao de codigo C++, C e assembly em codigo objeto. Esse codigo

objeto e depois traduzido em codigo maquina com o linker do Keil. O editor e o

debugger tambem fazem parte do IDE Keil. Portanto, esta solucao consiste numa

dualidade de esforcos por parte da Ceibo e da Keil Software. Por outro lado, a segunda

54

Page 73: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

solucao consiste na utilizacao da Embedded Workbench para o microcontrolador 8051

desenvolvida pela IAR. Este ambiente de desenvolvimento integra conjuntamente nao

so compilador C/C++, assemblador e linker, assim como editor e debugger. Portanto,

todas as ferramentas sao desenvolvidas por uma unica entidade, a IAR SYSTEMS.

Analisando e comparando as solucoes, o autor decidiu optar pela IAR Embedded

Workbench pelas seguintes razoes:

• O compilador da Ceibo nao e actualizado desde 2002, e requer a versao do

Keil uVision2 (atualmente o software Keil encontra-se na versao uVision4 ). O

software da IAR foi atualizado em Fevereiro do presente ano;

• O Compilador C++ da Ceibo nao suporta templates, o que impossibilita a

aplicacao de C++ TMP para a gestao da variabilidade do SO, essencial para o

sucesso deste trabalho. O compilador da IAR na versao IAR Extended Embed-

ded C++ (EEC++) suporta;

3.4.1 Compilador IAR C/C++ para o 8051

O IAR C/C++ Compiler for 8051 e uma das ferramentas integradas na IAR Em-

bedded Workbench for 8051. Este programa permite a compilacao de duas linguagens

de programacao de alto-nıvel:

• C, a linguagem de programacao mais usada na industria dos sistemas embebi-

dos. E possıvel desenvolver aplicacoes que sigam os standards:

– Standard C : tambem conhecido como C99;

– C89: tambem conhecido como C94, C90, C89 e ANSI C.

• C++, a linguagem de programacao orientada a objetos, com bibliotecas com

recursos para a programacao modular. Qualquer um dos seguintes standards

pode ser usado:

– Embedded C++ (EC++): um subconjunto de funcionalidades da pro-

gramacao standard C++, definidas pelo consorcio Embedded C++ Te-

chnical committee;

– IAR Extended Embedded C++ (EEC++): corresponde ao EC++ com

funcionalidades adicionais, como suporte completo a templates, namespace

e Standard Template Library (STL).

55

Page 74: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.4. Ambiente de Desenvolvimento

Memoria de Codigo

Conforme foi explicado da seccao 3.1, no 8051 classico o tamanho da memoria de

codigo e de 4k-byte com possibilidade de extensao ate 64k-byte. Por sua vez, existem

alguns 8051/8052 em que a memoria de codigo e expandida atraves do conceito de

bancos. E possıvel estender a memoria ate 16M-byte utilizando 256 bancos de 64k-

byte. O C8051F12X da Silabs [60] e o CC2430 da Texas Instruments [61] sao alguns

exemplos onde isso e feito por hardware. Mas, alem disso, existem ainda dispositivos

com memoria de codigo estendida, o que significa que podem ter ate 16M-byte de

memoria de codigo linear. Os dispositivos da Maxim DS80C390/DS80C400[62, 63]

sao exemplo disso.

O compilador da IAR suporta todas as configuracoes da memoria de codigo apre-

sentadas acima. Para especificar o nucleo e o modelo de memoria de codigo pretendido

este pode ser feito de duas formas:

• No IAR Embedded Workbench IDE, escolhendo Project->Options->General

Options->Target->CPUcore e Project->Options->General Options-

>Target->Codemodel;

• Atraves da linha de comandos com a opcao de compilacao –core = { plain

| p1 | extended1 | e1 | extended2 | e2 } e –code model = { near | n

| banked | b | banked ext2 | b2 | far | f } ;

Memoria de Dados

Relativamente ao modelo de dados, ou seja, ao modelo que especifica o tipo de

memoria usada por defeito para armazenar os dados, o compilador da IAR suporta

seis, dos quais importa destacar os seguintes:

• Tiny - O modelo de dados Tiny usa a memoria tiny por defeito, que esta

localizada nos primeiros 128-byte do espaco de memoria de dados interna. Esta

memoria pode ser acedida usando enderecamento directo. A vantagem e que

sao apenas necessarios 8-bit para o apontador.

• Small - O modelo de dados Small usa, por defeito, os primeiros 256-byte do

espaco de memoria de dados interna. Esta memoria pode ser acedida com

apontadores de 8-bits, tendo entao como vantagem ser apenas necessarios 8-bit

para o apontador.

56

Page 75: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

• Large - O modelo de dados Large usa, por defeito, os primeiros 64k-kbyte do

espaco de memoria de dados externa. Esta memoria pode ser acedida apenas

com apontadores de 16-bit.

Para especificar o modelo de dados no compilador, e possıvel faze-lo de duas

formas:

• No IAR Embedded Workbench IDE, escolhendo Project -> Options -> Ge-

neralOptions -> Target -> Data model;

• Atraves da linha de comandos com a opcao de compilacao –data model = {tiny | t | small | s | large | l | far | f | far generic | fg | generic | g } ;

Funcoes

Para alem do tradicional suporte a funcoes standard C, este compilador fornece

um conjunto de extensoes - mecanismos que controlam as funcoes - que permitem

acrescentar e personalizar determinados aspetos inerentes as mesmas.

Desta forma, seja atraves das opcoes de compilacao, da utilizacao de keywords ou

diretivas pragma, ou mesmo com o uso de funcoes intrınsecas, e possıvel controlar onde

e que as funcoes sao armazenadas em memoria, usar primitivas para programar inter-

rupcoes e concorrencia, configurar e utilizar o sistema de bancos do microcontrolador

8051, otimizar funcoes, e aceder a recursos de hardware. Por exemplo, configurando

o modelo de codigo (near ou banked) e possıvel controlar o espaco de memoria para

o armazenamento das funcoes, nomeadamente o tamanho maximo e o conjunto de

enderecos dedicados.

Para definir uma funcao interrupcao, tem que ser usada a keyword interrupt

e a directiva ]pragma vector. Com a directiva especifica-se qual a interrupcao pre-

tendida do vector de interrupcoes existente no microcontrolador , e com a keyword

define-se que a funcao e uma rotina de servico a interrupcao. O codigo da listagem

3.14 mostra como definir uma funcao interrupcao para o overflow do temporizador 0

do 8051. Uma funcao do tipo interrupcao, obrigatoriamente, nao pode retornar nada

(tipo de retorno void), e nao pode especificar nenhum parametro.

#pragma vector = TF0 int /∗Symbol defined in I/O header file∗/interrupt void MyISR(void)

{/∗ISR code∗/

57

Page 76: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.4. Ambiente de Desenvolvimento

}

Listagem 3.14: Funcao de interrupcao de overflow do timer 0

Interface Assembly

Quando se desenvolvem aplicacoes, sobretudo para sistemas embebidos, e nor-

mal existirem situacoes onde e necessario escrever partes de codigo em linguagem

assembly. Seja para obter timings precisos, seja para escrever sequencias especiais de

instrucoes, para obter melhorias a nıvel de performance, ou entao simplesmente por-

que os compiladores mesmo com recurso aos varios pragmas nao conseguem aceder a

todos os recursos de hardware. Conforme foi visto na seccao 3.2, o sistema operativo

ADEOS nao e excecao, e tanto a rotina de inicializacao de contexto (contextInit)

como de mudanca de contexto (contextSwitch) estao escritas em assembly. Desta

forma, para se poder fazer o porting do sistema operativo para a plataforma MCS-

51 e preciso perceber de que forma e que o compilador IAR para o 8051 suporta

o interface com o assembly. Assim sendo, o compilador IAR C/C++ para o 8051

disponibiliza tres formas de aceder aos recursos de baixo nıvel: (i) assembly inline;

(ii) modulos escritos inteiramente em assembly ; e (iii) funcoes intrınsecas.

Relativamente a primeira, e possıvel inserir codigo assembly diretamente em

funcoes escritas em C e C++, atraves da utilizacao da keyword asm. O codigo

apresentado na listagem 3.15 e um pequeno exemplo da utilizacao do inline assem-

bler para introduzir instrucoes assembly num pequeno programa em C. E possıvel

introduzir apenas uma instrucao, ou entao um bloco de instrucoes. E importante

nao esquecer que as instrucoes inline sao inseridas naquela localizacao no programa.

Portanto, e preciso ter presente as possıveis consequencias da indevida utilizacao da

mesma.

int main()

{int a = 2;

asm(”MOV SP,#0x80”); //change stack adress

int b = 0;

asm(

”PUSH 0 \n\t”

”MOV A,#10 \n\t”

”MOV 0,A \n\t”

”POP 0 \n\t”

);

return 0;

58

Page 77: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

}

Listagem 3.15: Exemplo de utilizacao de inline assembler no compilador IAR

No que diz respeito a segunda possibilidade, o compilador permite chamar rotinas

escritas totalmente em assembly (em ficheiros assembler) a partir do C ou C++.

Como o trabalho do autor esta enquadrado na programacao orientada a objetos, sera

somente explicado o metodo para C++, podendo o leitor consultar mais detalhes

para linguagem C no Manual do compilador IAR C/C++ para o 8051 [64]. Desta

forma, em primeiro lugar e preciso declarar o nome, parametros e retorno da funcao

no ficheiro de codigo C++, conforme e apresentado na listagem 3.16.

extern ”C”

{int assembler routine(int val);

}

Listagem 3.16: Definicao de uma funcao implementada num ficheiro assembly externo

Depois, no ficheiro assembler, as rotinas devem ser declaradas como publicas e

deve ser especificado o codigo de cada uma delas. O ficheiro assembly deve ser

estruturado conforme apresentado na listagem 3.17. Os parametros das funcoes sao

passados atraves dos registos R0-R5 ou pela pilha, dependendo no numero e tipo

de parametros em questao. O retorno e somente feito atraves dos registos R0-R5.

Na subseccao seguinte sera analisado e explicado com mais detalhe a convencao de

chamada suportada pelo compilador.

NAME assembler example

RSEG DOVERLAY:DATA:NOROOT(0)

RSEG IOVERLAY:IDATA:NOROOT(0)

RSEG ISTACK:IDATA:NOROOT(0)

RSEG PSTACK:XDATA:NOROOT(0)

RSEG XSTACK:XDATA:NOROOT(0)

;Name of Assembler functions here

PUBLIC assembler routine

RSEG NEAR CODE:CODE:NOROOT(0)

;Declaration of functions here

assembler routine:

;Assembly Code

END

Listagem 3.17: Estrutura de um ficheiro assembly gerado pelo compilador IAR

Finalmente, a terceira e ultima forma de interface assembly consiste na utilizacao

de funcoes intrınsecas, isto e, sao funcoes pre-definidas disponibilizadas pelo compi-

lador que permitem aceder aos recursos de baixo nıvel sem ter de usar a linguagem

59

Page 78: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.4. Ambiente de Desenvolvimento

Tabela 3.5: Convencoes de chamada de funcoes no compilador C/C++ 8051 da IAR

Convencaode cha-mada

Atributo da funcao Stackpointer

Descricao

Data over-lay

data overlay – Uma porcao da memoriainterna com acesso di-reto e usada para dadose parametros

Idata over-lay

idata overlay – Uma porcao da memoriainterna com acesso indi-reto e usada para dadose parametros

Idata reen-trant

idata reentrant SP A pilha da memoria in-terna com acesso indireto(idata) e usada para da-dos e parametros

Pdatareentrant

pdata reentrant PSP Uma pilha emulada na(pdata) e usada para da-dos e paramteros

Xdatareentrant

xdata reentrant XSP Uma pilha emulada na(xdata) e usada para da-dos e parametros

Extendedstackreentrant

ext stack reentrant ESP:SP Uma pilha estendidae usada para dados eparametros

assembly. A vantagem das funcoes intrınsecas relativamente ao uso de inline assem-

bler, e que o compilador tem toda a informacao necessaria para garantir uma correta

sequencia de interface, isto e, garante que tanto os registos como as variaveis sao

corretamente salvaguardados e restaurados.

Convencao de Chamada de Funcoes

Normalmente, as funcoes podem ser invocadas dentro de um programa por nome

ou por endereco. A convencao de chamada e o processo subjacente a essa invocacao

gerida automatica e transparentemente pelo compilador, delegando responsabilidades

a funcao chamada e ao chamante. Contudo, se uma funcao for escrita em linguagem

assembly, e necessario saber onde e como os parametros podem ser encontrados, bem

como quando retornar ao chamante e como retornar o resultado. O compilador IAR

60

Page 79: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

Tabela 3.6: Registos utilizados nos parametros das funcoes

Parametro Passado nos registos1-bit B.0, B.1, B.2, B.3, B.4, B.5, B.6, B.7, VB.0, VB.1,

VB.2, VB.3, VB.4, VB.5, VB.6 ou VB.7

8-bit R1, R2, R3, R4 ou R5

16-bit R3:R2 ou R5:R4

32-bit R5:R4:R3:R2

C/C++ para o 8051 suporta seis diferentes convencoes de chamada, responsaveis por

controlar como e que a memoria e usada para os parametros e as variaveis locais. A

tabela 3.5 lista as diversas convencoes de chamada disponıveis.

Para especificar a convencao de chamada utilizado por defeito pelo compilador, e

possıvel faze-lo de duas formas:

• No IAR Embedded Workbench IDE, escolhendo Project -> Options ->

GeneralOptions -> Target -> Calling model ;

• Atraves da linha de comandos com a opcao de compilacao –calling convention

= { data overlay | do | idata overlay | io | idata reentrant | ir |pdata reentrant | pr | xdata reentrant | xr | ext stack reentrant | er

} ;

Apesar de apenas ser possıvel definir uma convencao de chamada para cada pro-

jeto em cada instante de tempo, o compilador possibilita definir a convencao de

chamada para funcoes individuais atraves da utilizacao dos atributos apresentados

na tabela 3.5.

Prologo da funcao

Os parametros podem ser passados para uma funcao usando tres metodos distin-

tos: em registos, na pilha, em janelas de memoria (overlay frame). E muito mais

eficiente usar os registos do que utilizar a pilha, daı que todas as convencoes de cha-

mada tenham sido desenhadas para maximizar o uso de registos. Apenas um numero

limitado de registos pode ser usado para a passagem de parametros. A tabela 3.6

apresenta os registos que podem ser utilizados para a passagem de parametros.

Quando nao estejam disponıveis mais registos, os restantes parametros sao pas-

sados pela pilha. Em alguns casos, nomeadamente em estruturas, unioes, classes ou

parametros de funcoes com tamanho variavel (ellipsis), estes sao sempre passados

61

Page 80: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

3.4. Ambiente de Desenvolvimento

Tabela 3.7: Registos utilizados no retorno das funcoes

Valores de Retorno Passado nos registos1-bit Carry (C)

8-bit R1

16-bit R3:R2

32-bit R5:R4:R3:R2

pela pilha. Os parametros passados por pilha sao guardados na memoria na loca-

lizacao apontada pelo apontador da pilha especificada pela convencao da chamada. O

primeiro parametro e colocado diretamente na localizacao seguinte ao endereco apon-

tado pelo apontador da pilha. A pilha da convencao idata e extended stack cresce

para enderecos de memoria superiores, enquanto a pilha da convencao xdata e pdata

cresce para enderecos de memoria inferiores.

Epılogo da funcao

Uma funcao pode ou nao retornar um valor para o chamante. O retorno de

uma funcao, se existir, pode ser escalar (inteiro ou apontador), ponto-flutuante, ou

estrutura. Em todas as convencoes de chamada, o valor de retorno e passado em

registos ou no bit de carry. A tabela 3.7 apresenta os registos que podem ser utilizados

para o valor de retorno das funcoes.

Ambiente de Execucao - DLIB

O ambiente de execucao corresponde ao ambiente na qual a aplicacao e executada.

Este depende do hardware alvo, do ambiente de software, e do codigo da aplicacao, e

disponibiliza:

• Suporte as caracterısticas do hardware, nomeadamente acesso direto a camada

de baixo nıvel do processador (funcoes intrınsecas), registos dos perifericos e

interrupcoes (ficheiros cabecalho);

• Suporte a ambiente de execucao, isto e, codigo para a inicializacao e termino

do sistema;

• Suporte a operacoes de ponto-flutuante (fenv);

O compilador IAR C/C++ para o 8051 possibilita a execucao de aplicacoes em

dois ambientes de execucao: (i) CLIB; e (ii) DLIB. Enquanto o primeiro apenas

62

Page 81: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 3. Especificacao do Sistema

pode ser utilizado com linguagem C, o segundo suporta tanto C como C++. Assim

sendo, no contexto do trabalho a desenvolver, interessa apenas ao autor perceber o

ambiente de execucao DLIB. Portanto, este consiste numa biblioteca de execucao, que

contem funcoes definidas em C e C++, e ficheiros cabecalho que definem a interface

da biblioteca (headers). Essa biblioteca de execucao e disponibilizada tanto sob a

forma de bibliotecas pre-compiladas ($IAR directory/8051/lib/dlib) como ficheiros

de codigo fonte ($IAR directory/8051/src/lib/dlib). As bibliotecas pre-compiladas

sao configuradas para diferentes combinacoes das seguintes caracterısticas: ambiente

de execucao DLIB; variante do core; localizacao da pilha; modelo de codigo; modelo

de dados; convencao de chamada; localizacao das constantes; e numero, visibilidade,

tamanho e metodo de selecao do(s) data pointer(s).

O nome da biblioteca pre-compilada e gerado com a seguinte configuracao:

{lib} - {core} {stack} - {code mod} {data mod} {cc} {const loc} -

{]dptrs} {dptr vis} {dptr size} {dptr select}.r51.

Caso o compilador nao disponibilize uma biblioteca DLIB pre-compilada para as

combinacoes pretendidas, ou entao caso seja necessario alterar as rotinas de startup

ou exit, ou caso seja mesmo necessario adicionar suporte a alguma funcionalidade,

e possıvel criar uma biblioteca customizada. O processo e complexo, e toda a in-

formacao pode ser consultada no manual do compilador. Finalmente, para terminar,

importa referir que a biblioteca DLIB nao pode ser construıda para os modelos de

dados Tiny e Small, devido a necessidade de certos recursos inerentes a linguagem

C++.

63

Page 82: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 83: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4

Implementacao do Sistema

Este capıtulo descreve o desenvolvimento dos componentes do sistema especifica-

dos no capıtulo anterior. Basicamente, o capıtulo anterior permitiu a familiarizacao

com a arquitetura do microcontrolador alvo, o sistema operativo orientado a objetos,

a tecnica de programacao para a gestao da variabilidade, bem como o compilador

C++ a utilizar. Este capıtulo descreve entao o trabalho concretamente desenvolvido.

Numa primeira fase e explicado o processo de porting do ADEOS, ou seja, e anali-

sado o codigo dependente do microcontrolador 80188, e apresentada a implementacao

para o 8051. De seguida, na fase de upgrade, sao explicadas as melhorias introduzidas

no ADEOS. Clock-tick intrınseco ao escalonador, device-drivers para os diversos pe-

rifericos, e escalonador power-aware. Finalmente, no final do capıtulo e apresentado

e explicado o refactoring do sistema operativo com template metaprogramming, de

modo a permitir e possibilitar a sua customizacao de acordo com as necessidades do

utilizador.

4.1 Porting do ADEOS para a Plataforma MCS-

51

Todo o codigo de software pode ser classificado, segundo o conceito de porta-

bilidade, de duas formas distintas: (i) codigo dependente do processador (CDP); e

(ii) codigo independente do processador (CIP). Portanto, ou estamos perante codigo

universal que corre em qualquer plataforma, como bytecode compilado em Java para

maquinas virtuais, ou entao codigo binario que corre apenas numa arquitetura dedi-

65

Page 84: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.1. Porting do ADEOS para a Plataforma MCS-51

cada. Regra geral, quanto mais proxima a linguagem de programacao for do hardware,

menos portavel esta e. Assim sendo, o porting de software consiste basicamente em

reescrever o CDP de uma arquitetura original, para outra arquitetura alvo.

Neste sentido, para efetuar o porting do sistema operativo ADEOS da arquite-

tura 80188 para a arquitetura 8051, basta alterar, reescrever e adaptar o codigo BSP

(escrito em assembly especıfico ao 80188). Analisando a figura 4.1, que ilustra a ar-

quitetura de software do ADEOS e a sua relacao com o hardware, e possıvel constatar

que para efetuar o porting deste sistema operativo, basta portanto alterar e reescrever

o codigo dos ficheiros bsp.h e bsp.asm. Basicamente, esses ficheiros contem o codigo

responsavel por inicializar o contexto das tarefas, assim como realizar a mudanca de

contexto entre as mesmas.

Figura 4.1: Arquitetura de software do ADEOS

O autor decidiu, de modo a tornar a tarefa mais organizada e simplificada, dividir

a actividade de porting do SO em duas fases subsequentes: (i) analisar e compreender

o codigo assembly especıfico ao 80188; (ii) substituir o codigo assembly 80188 pelo

codigo assembly 8051, procurando manter a estrutura e estrategia (o mais fidedigno

quanto possıvel) de inicializacao e mudanca de contexto utilizada no processador

original;

66

Page 85: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

4.1.1 Analise do Codigo Dependente do Processador

A primeira tarefa de porting do ADEOS para a arquitetura 8051 passa entao

por analisar e perceber o codigo, especıfico ao 80188, responsavel pela inicializacao

e mudanca de contexto das tarefas do SO. Esta tarefa torna-se essencial para o

autor, nao so para interiorizar e assimilar conceitos inerentes ao porting de software,

assim como perceber a estrategia e abordagem utilizada pelo projetista do sistema

operativo, para relacionar e perceber os contornos da mudanca para a arquitetura

8051. Alem disso, vai permitir que o mesmo adquira competencia e conhecimentos

relativamente a arquitetura e conjunto de instrucoes do 80188.

Ficheiro Cabecalho (bsp.h)

O ficheiro cabecalho bsp.h (listagem 4.1) e utilizado para definir a estrutura de

dados responsavel por guardar o estado da maquina de cada tarefa (contexto), es-

pecificar as macros que delimitam seccoes de codigo crıtico, e declarar o prototipo

das funcoes implementadas em assembly responsaveis pela inicializacao e mudanca

de contexto. Alem disso, e ainda gerido o problema de name mangling subjacente ao

interface entre as linguagens C e C++.

struct Context

{int IP;

int CS;

int Flags;

int SP;

int SS;

int SI;

int DS;

};#include ”task.h”

#define enterCS() asm { pushf; cli }#define exitCS() asm { popf }extern ”C”

{void contextInit(Context ∗, void (∗run)(Task ∗), Task ∗, int ∗ pStackTop);

void contextSwitch(Context ∗ pOldContext, Context ∗ pNewContext);

void idle();

};

Listagem 4.1: Ficheiro bsp.h para a arquitetura 80188

A estrutura Context permite guardar o estado atual do processador, isto e, o

valor dos registos essenciais do 80188 utilizados por uma determinada tarefa. Neste

67

Page 86: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.1. Porting do ADEOS para a Plataforma MCS-51

caso, os registos necessarios a salvaguardar sao: o Instruction Pointer (IP); o Code

Segment (CS); as flags (Flags); o Stack Pointer (SP); o Stack Segment (SS); o Source

Index (SI); e o Data Segment (DS). As macros enterCS e exitCS permitem delimitar

seccoes de codigo consideradas crıticas. Por outras palavras, sempre que uma porcao

de codigo nao possa ser interrompido, entao este e considerado uma seccao de codigo

crıtica, nao podendo as interrupcoes estarem habilitadas. Daı que as macros sejam

implementadas em inline assembler, com recurso as instrucoes pushf, cli, e popf.

Segundo o conjunto de instrucoes do 80x86 [65] (compatıvel com o 80188), a instrucao

pushf guarda as flags na pilha, a instrucao cli desabilita a flag de interrupcao, e

a instrucao popf restaura as flags da pilha. Finalmente, a utilizacao da diretiva

extern "C", serve para informar o compilador que as funcoes foram escritas em

assembly seguem a convencao de nomes do C, que e diferente da convencao de nomes

do C++.

Ficheiro Assembly (bsp.asm)

O ficheiro assembly bsp.asm contem a implementacao das tres funcoes declaradas

no ficheiro cabecalho bsp.h, ou seja, implementa a funcao de inicializacao do contexto,

a funcao de mudanca de contexto, e a funcao idle.

Inicializacao de Contexto

Relativamente a funcao de inicializacao do contexto - contextInit -, esta apre-

senta uma estrategia de implementacao baseada em cinco etapas. O algoritmo 1

apresenta a estrategia utilizada.

Antes de explicar propriamente a implementacao da funcao, convem perceber

o prototipo da mesma (listagem 4.2). Assim, a funcao contextInit tem quatro

parametros de entrada. O primeiro e um apontador para a estrutura do contexto

da tarefa, o segundo um apontador para a rotina de startup da tarefa, o terceiro um

apontador para o objeto da tarefa, e o quarto e ultimo parametro um apontador para

o endereco do topo da pilha dedicada a tarefa. A funcao nao retorna nenhum valor

(void).

void contextInit(Context ∗, void (∗run)(Task ∗), Task ∗, int ∗ pStackTop);

Listagem 4.2: Prototipo da funcao contextInit

A primeira etapa da inicializacao do contexto representa a primeira parte do

prologo da funcao. Resume-se em gravar o base pointer na pilha do sistema, actualizar

68

Page 87: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

Algoritmo 1 Inicializacao do contexto no 80188 - contextInit

contextInit(...):

aceder ao apontador da estrutura context da tarefa;

inicializar o endereco de retorno;

inicializar as flags do processador;

inicializar o segmento da stack ;

inicializar o segmento de dados;

esse base pointer depois de o ter gravado, e posteriormente, atraves da instrucao les,

obter o apontador para a estrutura do contexto passado como parametro pela pilha,

colocando 16-bit do endereco no destination index e os outros 16-bit no extra segment.

O codigo apresentado abaixo representa a implementacao, e a imagem 4.2 ilustra a

organizacao da pilha do sistema logo apos a chamada da funcao e execucao destas

instrucoes.

push bp

mov bp, sp

les di, dword ptr ss:[bp+6]; Get pContext.

Figura 4.2: Pilha do sistema apos entrada na funcao contextInit

69

Page 88: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.1. Porting do ADEOS para a Plataforma MCS-51

Na segunda etapa (continuacao do prologo e inıcio do corpo da funcao) inicia-

se o preenchimento da estrutura de dados do contexto da tarefa, concretamente e

inicializado o endereco de retorno de startup da tarefa.

push ds

lds bx, dword ptr ss:[bp+10]; Get pFunc from the caller.

mov dx, ds

mov es:[di], bx

mov es:[di+2], dx

Basicamente, com a instrucao lds obtem-se o apontador da rotina de startup

passado como parametro (16-bit do endereco no registo base e os outros 16-bit no

data segment), e com as duas ultimas duas instrucoes mov preenche-se o primeiro (IP)

e segundo elemento (CS) da estrutura do contexto da tarefa (es:[di]) com o endereco

do apontador pFunc.

A terceira etapa e responsavel por inicializar as flags do processador na estrutura

do contexto da tarefa.

pushf

pop ax

or ax, 0000001000000000b; Enable interrupts by default.

mov es:[di+4], ax

Para isso, comeca por guardar as flags na pilha (pushf), restaura as flags para ao

acumulador (pop ax) e activa as interrupcoes por defeito. Por fim, com a instrucao

mov preenche o terceiro elemento(Flags - es:[di+4]) da estrutura com esse valor.

A quarta etapa e a etapa mais complexa da rotina de inicializacao de contexto,

pois inicializa-se a area de memoria reservada a pilha da tarefa.

les di, dword ptr ss:[bp+18]; Point to the task’s stack.

lds bx, dword ptr ss:[bp+14]; Get pTask from the caller.

mov dx, ds

mov es:[di−4], bx ; Place pTask onto the stack.

mov es:[di−2], dx

les di, dword ptr ss:[bp+6] ; Point to the task’s context.

lds bx, dword ptr ss:[bp+18]; Get pStack from the caller.

mov dx, ds

sub bx, 8 ; Save stack space for pTask.

mov es:[di+6], bx

mov es:[di+8], dx

Assim sendo, as duas primeiras instrucoes assembly permitem obter, respecti-

vamente, o apontador para o topo da pilha da tarefa (enderecos em es e di) e o

apontador para o objeto da tarefa (enderecos em ds e bx ). Depois disso, guarda-

se o endereco do objeto da tarefa (enderecos em bx e dx ) nos primeiros enderecos

da propria pilha reservada para a tarefa (es:[di-4] e es:[di-2]). As duas instrucoes

70

Page 89: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

seguintes permitem aceder, respectivamente, ao apontador para a estrutura do con-

texto da tarefa (enderecos em es e di) e novamente o apontador para o topo da pilha

da tarefa (enderecos em ds e bx ). A instrucao sub subtrai 8 unidades ao endereco

do topo da pilha da tarefa, e as duas instrucoes seguintes preenchem o quarto (SP -

es:[di+6]) e quinto elemento (SP - es:[di+8]) da estrutura com os enderecos da pilha

da tarefa atualizada. A imagem 4.3 representa a organizacao da pilha da tarefa apos

a execucao desse bloco de codigo.

Figura 4.3: Pilha da tarefa apos inicializacao

A quinta e ultima etapa inicializa o segmento de dados, isto e, preenche na estru-

tura do contexto da tarefa os valores dos registos de segmentos si e ds. Alem disso,

e tambem responsavel por implementar o codigo epılogo da funcao (instrucoes pop e

ret).

pop ds

mov dx, ds

mov es:[di+10], si

mov es:[di+12], dx

pop bp

ret

Neste sentido, na sequencia da instrucao push ds da segunda etapa, que continha

o valor inicial desse registo, a instrucao pop ds restaura entao novamente o registo.

Desta forma, as instrucoes seguintes preenchem o sexto (SI - es:[di+10]) e setimo

elemento (DS - es:[di+12]) da estrutura com o valor original desses registos. A ins-

trucao pop bp restaura o base pointer com o valor que este tinha antes da chamada

da funcao. A etapa termina com a instrucao ret, responsavel por retornar a execucao

de codigo para a instrucao seguinte a chamada da rotina.

71

Page 90: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.1. Porting do ADEOS para a Plataforma MCS-51

Mudanca de Contexto

Por sua vez, a rotina de mudanca de contexto - contextSwitch - basicamente

salvaguarda o estado da tarefa atual em execucao (a excecao da tarefa idle), e restaura

o estado da que se pretende executar a posteriori. Com efeito, esta rotina apresenta

uma estrategia de implementacao baseada em seis ou dez etapas, dependendo da

condicao da tarefa que se encontra atualmente em execucao. Caso seja a idle nao e

necessario guardar o estado da tarefa actual, resumindo-se portanto a rotina a seis

etapas. O algoritmo 2 ilustra a estrategia utilizada.

Algoritmo 2 Mudanca de contexto no 80188 - contextSwitch

contextSwitch(...):

aceder ao apontador do parametro old Context ;

if tarefa idle then;

guardar o endereco do final da rotina;

guardar as flags do processador;

guardar o segmento da stack ;

guardar o segmento de dados;

endif ;

aceder ao apontador do parametro new Context ;

restaurar o segmento de dados;

restaurar o segmento da stack ;

restaurar as flags do processador;

restaurar o endereco de retorno;

O prototipo da funcao contextSwitch (listagem 4.3) tem dois parametros de

entrada, sendo estes os apontadores para a estrutura do contexto da tarefa atualmente

em execucao (pOldContext), e para a tarefa que se pretende que entre em execucao

72

Page 91: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

(pNewContext). A funcao tem retorno vazio (void).

void contextSwitch(Context ∗ pOldContext, Context ∗ pNewContext);

Listagem 4.3: Prototipo da funcao contextSwitch

A primeira etapa da inicializacao do contexto representa o prologo da funcao.

Este consiste em gravar o base pointer na pilha do sistema, atualizar esse base poin-

ter depois de o ter gravado, e posteriormente, atraves da instrucao les, aceder ao

apontador para a estrutura do contexto da tarefa atualmente em execucao (16-bit

no destination index e 16-bit no extra segment). Alem disso, com a utilizacao das

instrucoes mov copia-se esses enderecos para o registo data (dx ) e para o acumulador

(ax ), para avaliar a a condicao da tarefa idle.

push bp

mov bp, sp

les di, dword ptr ss:[bp+6]

mov dx, es

mov ax, di

O codigo assembly apresentado abaixo inicia o corpo da funcao. Consiste na

verificacao da tarefa atualmente em execucao. Com o or-logico verifica-se se ambos

os enderecos da estrutura da tarefa em execucao sao nulos, pois caso isso aconteca

significa que a tarefa atualmente em execucao e a idle, nao sendo portanto necessario

guardar o estado da mesma.

or ax, dx

jz fromIdle

Na segunda etapa inicia-se o processo de backup do estado da tarefa, isto e,

preenche-se a estrutura de dados do contexto da tarefa atualmente em execucao

com o estado atual da tarefa.

mov dx, cs

lea ax, switchComplete

mov es:[di], ax

mov es:[di+2], dx

Assim, com a primeira instrucao guarda-se o code segment, com a instrucao lea

obtem-se o endereco (offset) da label switchComplete (16-bit apenas), e com as duas

ultimas duas instrucoes mov preenche-se o primeiro (IP) e segundo elemento (CS) da

estrutura do contexto da tarefa (es:[di]) atual com o endereco do final da rotina.

A terceira etapa guarda as flags do processador na estrutura do contexto da

tarefa. Para isso, guarda as flags na pilha (pushf), e posteriormente preenche o

terceiro elemento (Flags - es:[di+4]) da estrutura com esse valor.

73

Page 92: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.1. Porting do ADEOS para a Plataforma MCS-51

pushf

pop es:[di+4]

A quarta etapa consiste no backup do segmento da pilha da tarefa.

mov dx, ss

mov es:[di+6], sp

mov es:[di+8], dx

Com a execucao das duas ultimas instrucoes mov preenche-se o quarto (SP -

es:[di+6]) e quinto elemento (SS - es:[di+8]) da estrutura do contexto da tarefa com

o stack pointer e stack segment.

A quinta etapa e a ultima etapa destinada ao backup do estado da tarefa, nome-

adamente o segmento de dados da mesma.

mov dx, ds

mov es:[di+10], si

mov es:[di+12], dx

Com a execucao das duas ultimas instrucoes mov preenche-se o sexto (SI - es:[di+10])

e setimo elemento (DS - es:[di+12]) da estrutura do contexto da tarefa com os registos

source index e data segment.

A sexta etapa e a primeira destinada ao restauro do processador com a informacao

da tarefa que se pretende colocar em execucao.

fromIdle:

les di, dword ptr ss:[bp+10]

mov dx, es

mov ax, di

Com a instrucao les acede-se ao apontador para a estrutura do contexto da tarefa

que ira entrar em execucao, mais concretamente ao ultimo elemento (SI - es:[di+10])

da mesma. As duas instrucoes mov efetuam o backup do apontador para o registo

data (dx ) e para o acumulador (ax ).

A setima etapa restaura entao o registo source ındex do segmento de dados. Para

isso, utiliza a instrucao lds, colocando em si o sexto elemento (SI) da estrutura do

contexto da nova tarefa.

lds si, dword ptr [di+10]; si = pNewContext−>SI

A oitava etapa consiste no restauro do segmento da pilha.

mov dx, es:[di+8]

mov ax, es:[di+6]

pushf ; Save the current interrupt state.

pop cx

cli ; Disable interrupts.

74

Page 93: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

mov ss, dx

mov sp, ax

push cx

popf ; Restore the saved interrupt state.

Com efeito, as duas primeiras instrucoes colocam no registo de dados e no acumu-

lador o quinto (SS) e quarto (SP) elementos da estrutura do contexto da nova tarefa,

respetivamente. As tres instrucoes seguintes permitem guardar o estado das flags e

desabilitar as interrupcoes. Depois disso, sao restaurados os registos sack segment e

stack pointer, com as instrucoes mov. A etapa termina com o restauro das flags.

Finalmente, o ultimo segmento de codigo representa o epılogo da funcao, res-

ponsavel por restaurar, de forma indireta, as flags do processador e do endereco de

retorno. Por outras palavras, com a instrucoes push coloca na pilha o primeiro (IP),

segundo (CS) e terceiro (Flags) elementos da estrutura do contexto da nova tarefa, e

com a instrucao iret retorna da rotina restaurando as flags simultaneamente.

push es:[di+4]

push es:[di+2]

push es:[di]

iret

4.1.2 Porting do Codigo Dependente do Processador

A segunda tarefa do processo de porting do ADEOS consiste entao na substituicao

do codigo dependente da arquitetura 80188 por codigo assembly 8051, procurando

manter, tanto quanto possıvel, a estrategia utilizada na versao original do sistema

operativo. Obviamente que uma vez que os processadores tem arquiteturas dispares,

sera necessario efetuar algumas modificacoes. Neste sentido, de seguida serao apre-

sentadas as alteracoes efetuadas pelo autor, assim como as estrategias utilizadas para

a inicializacao e mudanca de contexto.

Ficheiro Cabecalho (bsp.h)

No ficheiro cabecalho bsp.h a primeira alteracao surge desde logo com a alteracao

da estrutura do contexto (listagem 4.4). Como os microprocessadores tem arquite-

turas diferentes, e compreensıvel que tenham registos e estados diferentes. Assim

sendo, a estrutura apresentada abaixo implementa o contexto de uma tarefa do 8051.

De toda a estrutura importa referenciar as variaveis PC H e PC L, XSP H e XSP L,

que correspondem, respetivamente, ao endereco da memoria da proxima instrucao

75

Page 94: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.1. Porting do ADEOS para a Plataforma MCS-51

de execucao da tarefa e ao endereco da pilha da tarefa (em memoria externa). Os

restantes sao registos intrınsecos ao estado do microprocessador.

struct context

{unsigned char PC H, PC L;

unsigned char A, B;

unsigned char IE;

unsigned char DPL, DPH;

unsigned char R0, R1, R2, R3, R4, R5, R6, R7;

unsigned char PSW;

unsigned char SP;

unsigned char XSP H, XSP L;

};

Listagem 4.4: Definicao da estrutura do estado da maquina (8051) de cada tarefa

Tambem as macros para delimitacao de seccoes crıticas foram ligeiramente alte-

radas (listagem 4.5). Apesar da logica ser a mesma, nao existe instrucoes dedicadas

para gravar as flags e desabilitar as interrupcoes, pelo que isso tem que ser feito com

os respetivos registos. Portanto, sempre que se entra numa secacao crıtica o registo

IE (0xA8) e colocado na pilha e e desabilitado o bit geral das interrupcoes. Nao e

utilizada a instrucao CLR EA, pois o compilador nao reconhece a flag. Por sua vez,

quando sai da seccao crıtica, e feito o restauro atraves da pilha

#define enterCS()\{\

asm(\”PUSH 0xA8 \n” \”ANL 0xA8, #0x7F \n” \

);\}#define exitCS()\{\

asm(\”POP 0xA8 \n” \

);\}

Listagem 4.5: Macros para delimitacao de uma seccao crıtica

No prototipo das funcoes nao existe nenhuma alteracao na declaracao, apenas

e utilizada uma macro para redefinir a funcao de mudanca de contexto (listagem

4.6). Isto e necessario devido a convencao da chamada de funcoes do compilador

da IAR. Como na chamada de uma funcao os parametros sao colocados nos registos

do microprocessador (por questoes de otimizacao), e entao necessario guardar esses

registos na pilha antes de invocar a funcao.

76

Page 95: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

#define ContextSwitch(old context, new context)\{ \

asm( \”PUSH A \n” \”PUSH 1 \n” \”PUSH 2 \n” \”PUSH 3 \n” \”PUSH 4 \n” \”PUSH 5 \n” \”PUSH DPL \n” \”PUSH DPH \n” \); \

contextSwitch(&old context, &new context); \} \

Listagem 4.6: Macro para comutacao de contexto (ContextSwitch)

Ficheiro Assembly (bsp.asm)

No ficheiro assembly bsp.asm e onde se verificam as principais alteracoes. Ape-

sar deste continuar a ter a implementacao das tres funcoes declaradas no ficheiro

cabecalho, existem modificacoes consideraveis em duas delas. De seguida, serao apre-

sentadas e explicadas as novas metodologias para inicializacao e mudanca de contexto,

assim como as alteracoes na implementacao das mesmas.

Inicializacao do contexto

Relativamente a funcao de inicializacao do contexto, esta apresenta agora uma

estrategia de implementacao baseada em oito etapas. Apesar de seguir a mesma

abordagem que a anterior, e mais longa pois esta mais detalhada a nıvel dos registos

do estado do processador. O algoritmo 3 ilustra a estrategia utilizada.

De forma a simplificar a explicacao da implementacao da funcao, convem clari-

ficar, desde ja, onde e que os parametros de entrada sao colocados na chamada da

funcao. Assim sendo, conforme foi apresentado na subseccao 3.4.1, o primeiro ar-

gumento, endereco para uma estrutura localizada em memoria externa (64k-byte), e

um endereco de 16-bit, pelo que e colocado nos registos R2 e R3 do banco 0. Por

sua vez, o segundo argumento e um apontador para uma localizacao da memoria de

codigo (216 = 64k-byte), daı que seja um endereco de 16-bit colocado nos registos R4

e R5. O terceiro argumento e um apontador para o objeto tarefa, colocado na pilha

externa (XSP), devido a inexistencia de mais registos para variaveis de 16-bit.

O codigo apresentado abaixo implementa a primeira e segunda etapa do processo

77

Page 96: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.1. Porting do ADEOS para a Plataforma MCS-51

Algoritmo 3 Inicializacao do contexto no 8051 - contextInit

contextInit(...):

aceder ao apontador da estrutura context da tarefa;

inicializar o apontador para a rotina de startup;

inicializar o registo A e B;

inicializar o registo de interrupoes;

inicializar o registo DPTR;

inicializar os registo R0-R7;

inicializar as flags do processador;

inicializar o segmento da stack ;

de inicializacao do contexto da tarefa.

;Get the pointer to context

MOV DPH, 3; Load pContext H into DPH

MOV DPL, 2; Load pContext L into DPL

;Initialize the pointer to startup routine

MOV A, 5; A = pFunc H

MOVX @DPTR, A; pContext−>PC H = pFunc H

INC DPTR; point to pContext−>PC L

MOV A, 4; A = pFunc L

MOVX @DPTR, A; pContext−>PC L = pFunc L

INC DPTR; point to pContext−>A

As duas primeiras instrucoes (prologo da funcao) permitem aceder ao apontador

do contexto da tarefa. O restante codigo (inıcio do corpo da funcao) inicializa o

apontador para a rotina de startup da tarefa. Com as instrucoes MOVX inicializa-se

o primeiro (PC H) e segundo (PC L) elemento da estrutura do contexto da tarefa,

atraves de enderecamento indirecto para memoria externa.

A terceira etapa consiste na inicializacao dos registos A e B. Seguindo a mesma

linha da etapa anterior, com a utilizacao das instrucoes MOVX inicializa-se o terceiro

(A) e quarto (B) elemento da estrutura do contexto da tarefa.

;Initialize A and B

MOV A, #0; A = 0;

78

Page 97: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

MOVX @DPTR, A; pContext−>A = A (0)

INC DPTR; point to pContext−>B

...

A inicializacao do estado das interrupcoes acontece na quarta etapa. O estado

actual das interrupcoes e salvaguardado na pilha (PUSH), as interrupcoes gerais e a do

temporizador 0 sao ativadas por defeito (valor 0x82), o quinto elemento da estrutura

(IE) e inicializado com esse valor, e o estado anterior das interrupcoes e restaurado

(POP). A activacao da interrupcao do timer 0 esta ligada a metodologia utilizada na

versao original para tornar as tarefas periodicas.

; Initialize interrupts

PUSH 0xA8; Save IE in stack

ORL 0xA8,#0x82; Enable Interrupts (Timer0 for clock tick) by default

MOV A, 0xA8; A = IE;

MOVX @DPTR, A; pContext−>IE = 0x82

POP 0xA8; Restore IE

As proximas tres etapas permitem inicializar o data pointer, os registos R0 a R7 e

as flags do processador. A metodologia e exactamente a mesma das etapas anteriores,

que consiste em aceder aos elementos seis a dezasseis (DPL a PSW) da estrutura da

tarefa, e inicializar a nulo. No registo PSW isso significa limpar todas as flags, como

por exemplo, a flag de carry (C) e paridade (P).

; Initialize DPTR

INC DPTR; point to pContext−>DPL

MOVX @DPTR, A; pContext−>DPL = 0

INC DPTR; point to pContext−>DPH

MOVX @DPTR, A; pContext−>DPH = 0

;Initialize Registers.

INC DPTR; point to pContext−>R0

MOV A, #0;

MOVX @DPTR, A; pContext−>R0 = 0

...

;Initialize Processor Flags

PUSH PSW; Save PSW in stack

ANL PSW,#0x00; CLEAN ALL FLAGS

MOV A, PSW; A = PSW;

MOVX @DPTR, A; pContext−>PSW = 0x00

POP PSW; Restore PSW

A oitava e ultima etapa da inicializacao do contexto da tarefa permite inicializar

as variaveis da estrutura do contexto da tarefa que armazenam a informacao relativa

ao segmento da stack. Por outras palavras, inicializam a variavel SP com o endereco

da pilha interna, bem como as variaveis XSP L e XSP H com o endereco da pilha

externa.

79

Page 98: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.1. Porting do ADEOS para a Plataforma MCS-51

Mudanca de contexto

Tal como na inicializacao, tambem a rotina de mudanca de contexto apresenta

uma estrategia de implementacao mais longa, quando comparada com a estrategia

descrita na seccao 4.1.1. Mais uma vez, o processo e condicionado pela tarefa atual

em execucao. O algoritmo 4 apresenta essa estrategia.

O codigo apresentado abaixo (em parte, prologo da funcao) implementa a condicao

da tarefa em dois passos.

MOV A, 2; put pOldContext L in A

JNZ fromTask; if pOldContext L != 0, no NULL pointer

MOV A,3; put pOldContext H in A

JNZ fromTask; if pOldContext H != 0, no NULL pointer , goto fromTask

CALL fromIdle; NULL pointer , goto fromIdle

Caso a tarefa em execucao seja a idle, entao o apontador para o contexto dessa

tarefa e nulo. Portanto, o codigo acima testa o LSB e MSB desse endereco, e so na

eventualidade de ambos serem nulos e que salta para a etapa oito. Isso e conseguido

com a instrucao JNZ, que verifica se o valor do acumulador e nulo e salta para o

endereco de codigo da label caso isso nao aconteca. Se acontecer continua o fluxo

normal de execucao, sem efetuar nenhum salto.

A segunda etapa implementa o primeiro estagio do backup da informacao da tarefa

em execucao, isto e, salvaguarda o endereco da proxima instrucao a executar assim

que a tarefa volte a obter o controlo do processador.

As etapas tres a oito permitem gravar os registos, flags e interrupcoes do proces-

sador, bem como a pilha da tarefa. A metodologia de implementacao e semelhante

em todos os casos. Como esses registos sao guardados na pilha (interna) antes da

chamada da funcao contextSwitch, consistem basicamente em aceder ao endereco da

pilha que tem o estado do registo, e copiar essa informacao para a respetiva estrutura.

O codigo abaixo exemplifica para o caso do registo A do processador.

;Save A

MOV A, SP; Save into ACC SP adress

CLR C; Clear Carry to subtract

SUBB A,#9; Point to the adress of ACC saved in stack

MOV R1,A; R1 = adress ACC (saved)

MOV A,@R1; A = A(saved into stack)

INC DPTR; point to pOldContext−>A

MOVX @DPTR, A; pOldContext−>A = A

...

Depois de efetuado o backup da informacao da tarefa em execucao, e entao ne-

cessario restaurar o estado da nova tarefa. Como a execucao de instrucoes afeta

80

Page 99: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

Algoritmo 4 Mudanca de contexto no 8051 - contextSwitch

contextSwitch(...):

aceder ao apontador do parametro old Context ;

if tarefa idle then;

guardar o endereco de retorno;

guardar o registo A e B;

guardar o estado das interrupcoes;

guardar o registo DPTR;

guardar os registo R0-R7;

guardar as flags do processador;

guardar o segmento da stack ;

endif ;

aceder ao apontador do parametro new Context ;

restaurar o segmento da stack ;

restaurar o endereco de retorno

restaurar o registo A e B;

restaurar o estado das interrupcoes;

restaurar o registo DPTR;

restaurar os registo R0-R7;

restaurar as flags do processador;

81

Page 100: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

registos no processador, a estrategia passa por reter a informacao do novo estado na

pilha (interna), e apenas restaura-lo no processador no momento anterior ao retorno

da funcao.

A nona etapa e a primeira destinada ao restauro do estado da nova tarefa. Com as

instrucoes MOV acede-se ao endereco na estrutura do contexto da nova tarefa, passado

como argumento atraves dos registos R4 e R5.

;Get pNewContext

MOV DPL, 4; get pNewContext

MOV DPH, 5; get pNewContext

As etapas dez a quinze permitem restaurar o endereco de retorno, registos, flags

e interrupcoes do processador. Conforme foi previamente explicado, esse restauro e

feito em dois momentos, pelo que o codigo apresentado acima reflete esse primeiro

estagio. Acede-se os elementos da estrutura da nova tarefa, e copia-se a informacao

para a pilha (interna). So mais tarde e que essa informacao e restaurada ao proces-

sador.

;Save the return address into stack

INC DPTR; point to pNewContext−>PC L

MOVX A,@DPTR; A = pNewContext−>PC L

PUSH A; Save ACC (pNewContext−>PC L) into stack

MOV DPL, 4; get pNewContext

MOV DPH, 5; get pNewContext

MOVX A,@DPTR; A = pNewContext−>PC H

PUSH A; Save ACC (pNewContext−>PC H) into stack

;Save A and B into stack

INC DPTR; point to pNewContext−>PC L

INC DPTR; point to pNewContext−>A

MOVX A,@DPTR; A = pNewContext−>A

PUSH A

...

;Save PSW into stack

INC DPTR; point to pNewContext−>PSW

MOVX A,@DPTR; A = pNewContext−>PSW

PUSH A

A etapa dezasseis reflete o restauro da pilha da tarefa (interna e externa). Depois

disso, o ultimo bloco de codigo (epılogo da funcao) faz o restauro sequencial da

informacao da nova tarefa.

4.2 Upgrade do ADEOS

O upgrade de software e um processo gradual e progressivo, que requer tempo

pois existe sempre alguma funcionalidade a implementar. O ADEOS nao e excepcao.

82

Page 101: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

Assim sendo, o upgrade de um sistema operativo podia, por si so, dar origem a uma

dissertacao. Como tal, o autor decidiu expandir e melhorar o sistema operativo em

tres aspetos: (1) clock-tick intrınseco ao escalonador; (2) device-drivers para os pe-

rifericos do 8051; (3) escalonador power-aware. O primeiro porque possibilita ao sis-

tema operativo implementar estrategias de escalonamento com time-slice. O segundo

porque os device drivers simplificam a interface com os perifericos do microcontrola-

dor. Finalmente, o escalonador power-aware porque implementa uma estrategia de

escalonamento tendo em vista a minimizacao do consumo, caracterıstica fundamen-

tal nos sistemas embebidos atuais. Outras funcionalidades como metodos de comu-

nicacao entre processos (message queue, shared memory, etc.), outras estrategias de

escalonamento, ou mesmo uma pilha TCP/IP, podem ser implementadas de forma

gradual, pois nao sao o foco central nem desempenham um papel crucial na presente

dissertacao.

4.2.1 Upgrade: clock-tick no escalonador

Conforme mencionado na seccao 3.2.2, um dos pontos de escalonamento acontece

com o clock-tick dos temporizadores por software. A versao original do sistema opera-

tivo implementa temporizadores por software para gerir a periocidade e o estado das

tarefas. Por outras palavras, sempre que esse clock-tick ocorre, o sistema operativo

decrementa e verifica os temporizadores por software ativos, e caso algum termine as

tarefas colocadas em estado waiting a espera dessa temporizacao sao comutadas para

o estado ready. Esta metodologia e bastante eficaz para o tipo de escalonador im-

plementado, no entanto em escalonadores com time-slice esta abordagem e ineficaz.

Neste sentido, como a tarefa do autor passa por criar a base do sistema operativo

para o melhorar e aumentar gradualmente, este decidiu implementar um clock-tick

intrınseco ao proprio escalonador, responsavel por invocar o escalonador a cada time-

slice. Desta forma e possıvel escalonar utilizando a abordagem dos temporizadores

por software, ou entao seguindo a estrategia de time-slice.

Para implementar essa nova estrategia, convem primeiro definir uma nova inter-

rupcao desencadeada pelo trigger da interrupcao do temporizador. O 8051 classico

dispoe de dois temporizadores. O temporizador 0 e utilizado para gerar a interrupcao

responsavel pela gestao dos temporizadores por software. O temporizador 1 tem que

ser entao utilizado para desencadear o trigger responsavel pelo time-slice. A tabela

4.1 apresenta a implementacao da rotina de ISR invocada aquando da ocorrencia do

83

Page 102: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

Tabela 4.1: Rotina de interrupcao do temporizador 1

Metodo C++ CDP (8051)#pragma vector = TF1 int

interrupt void Sched::tick(void){

enterCS();

recharge sched tick(˜CYCLES PER TICK);os.schedule();

exitCS();}

recharge sched tick:CODEMOV TL1,R2MOV TH1,R3RET

overflow do temporizador 1, assim como a implementacao assembly de recarrega-

mento dos registos de contagem do temporizador.

A definicao da rotina de interrupcao e feita com a macro ]pragma vector. A

interrupcao e embutida na classe definindo-a como estatica na sua declaracao. Na

ocorrencia da interrupcao, o temporizador e novamente carregado com o valor da

temporizacao pretendida, e o escalonador e invocado. Como e uma rotina de servico

a interrupcao, e considerada uma zona crıtica, daı que o codigo esteja delimitado pelas

macros enterCS() e exitCS(). De forma a tornar o codigo o mais portavel possıvel, a

funcao responsavel pela reconfiguracao da temporizacao e implementada diretamente

em assembly, juntamente com o restante codigo dependente do processador (ficheiros

bsp.asm). Basicamente, os registos do temporizador 1 sao carregados com o valor do

parametro de temporizacao passado na funcao atraves dos registos R2 e R3 (inteiro).

Para alem da especificacao da rotina de servico a interrupcao, e necessario configu-

rar o temporizador 1. Por exemplo, e preciso especificar a cadencia (temporizacao) a

que ocorre a interrupcao, assim como a habilitacao da mesma. A tabela 4.2 apresenta

o metodo responsavel pela configuracao do temporizador responsavel pelo clock-tick,

assim como o respetivo CDP implementado em assembly. O codigo assembly confi-

gura o timer 1 para funcionar como temporizador de 16-bit, habilita a interrupcao de

overflow do respetivo temporizador, e carrega os registos de contagem com o valor

para gerar o trigger da interrupcao com a cadencia temporal pretendida.

Depois de configurado o clock-tick e definida a rotina de ISR, apenas e necessario

colocar o correr a temporizacao. Para isso, e especificado o metodo run tick, res-

ponsavel por iniciar a contagem no temporizador. O codigo C++ e assembly apre-

sentados na tabela 4.3 especificam o metodo explicado anteriormente e a respetiva

implementacao. A implementacao de baixo nıvel e bastante simples, e corresponde

apenas a activacao da flag TR1 (Timer 1 Run) no registo TCON.

84

Page 103: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

Tabela 4.2: Configuracao do temporizador 1

Metodo C++ CDP (8051)

void Sched::config tick(){

config sched tick(˜CYCLES PER TICK);}

config sched tick:CODEORL TMOD,#0x10ORL IEN0,#0x88MOV TL1,R2MOV TH1,R3RET

Tabela 4.3: Inicializacao da contagem do temporizador 1

Metodo C++ CDP (8051)void Sched::run tick(){

run sched tick();}

run sched tick:CODEORL TCON,#0x40RET

Desta forma, a possibilidade de inclusao do clock-tick para o time-slice fica apenas

restringindo a duas linhas de codigo. Antes da execucao do metodo de inicializacao do

sistema operativo, sao executados os metodos config tick e run tick (listagem 4.7).

Omitindo a chamada desses metodos o sistema operativo nao invoca a ISR responsavel

por esse clock-tick. Assim sendo, o sistema operativo fica preparado para algoritmos

de escalonamento com time-slice, possibilitando, no futuro, a implementacao, por

exemplo, do escalonador round-robin com time-slice.

void main(void)

{os.config tick();

os.run tick();

os.start();

}

Listagem 4.7: Configuracao do clock-tick do escalonador

4.2.2 Upgrade: device drivers

Um device driver e um componente de software que permite que aplicacoes de

alto nıvel comuniquem e interajam com dispositivos de hardware. Por outras pala-

vras, podem ser definidos como black boxes que permitem que um componente de

hardware responda a uma determinada interface de programacao. Estes escondem

completamente os detalhes de como o dispositivo funciona, e disponibilizam apenas

operacoes e chamadas padronizadas que atuam no hardware real [66].

Na versao original do ADEOS a interface ao hardware nao utiliza a pura abstracao

85

Page 104: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

associada ao conceito de device driver (que tem associado um modelo comum), ape-

nas implementa controladores de hardware sob a forma de classes. Isto porque o

projetista apenas pretendeu demonstrar como e que os dois dispositivos (porta serie,

temporizador) podiam ser implementados usando classes. Assim sendo, a ideia do

autor passa entao, numa primeira fase, por desenvolver os varios controladores de

hardware como objetos representativos dos diversos perifericos do 8051. Contudo,

futuramente definir-se-a um modelo para uma framework I/O, em que essa abstracao

e implementada com template metaprogramming. Desta forma, implementar-se-a a

verdadeira abstracao caracterıstica do modelo dos device drivers. Isto tudo para expli-

car o porque da designacao de device drivers atribuıda aos controladores de hardware

desenvolvidos para os varios perifericos - (i) PWM, (ii) UART, (iii) GPIO, (iv) I2C

e (v) SPI - do 8051.

Device Driver : PWM

Pulse with modulation, ou em portugues, modulacao por largura de pulso, e uma

tecnica que permite gerar sinais analogicos, recorrendo a hardware externo (filtro

passa-baixo), a partir de sinais digitais. O controlo digital e usado para gerar uma

onda quadrada, que alterna constantemente entre o estado ligado (on) e desligado

(off ). A porcao de tempo que o sinal esta em estado on, relativamente ao seu perıodo,

e designado de largura de impulso (duty-cycle). Assim, controlando o tempo que o

sinal esta a on e off num determinado perıodo de tempo, e possıvel obter diferentes

valores analogicos. Por exemplo, num sinal com um perıodo de 10ms e com uma

tensao maxima de 5V, se a onda estiver 6ms em estado on (5V) e 4ms em estado off

(0V), o valor medio analogico conseguido e de 3V. Este tipo de tecnica e muito utili-

zada para controlar o brilho de LEDs e a velocidade de motores de corrente contınua

(DC).

PWM no 8051

O microcontrolador 8051, na versao AT89C51ID2 da Atmel, dispoe de quatro

modulos de PWM configurados atraves do periferico PCA (Programmable Counter

Array). O PCA consiste num temporizador/contador dedicado que serve de base

para um vetor de cinco modulos de comparacao/captura.

Todos os modulos do PCA podem ser usados com saıdas de PWM. A frequencia

da saıda e comum a todos os modulos, pois depende da fonte de relogio do periferico:

86

Page 105: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

(i) frequencia de relogio do microcontrolador com divisao por seis; (ii) frequencia de

relogio do microcontrolador com divisao por dois; (iii) overflow do timer 0; (iv) fonte

externa atraves do pino P1.2. O valor do duty-cycle de cada modulo e independente

e variavel (registo CCAPLn). Quando o valor do contador do PCA e inferior ao valor

carregado no registo do modulo, a saıda permanece em baixo, no entanto quando

esse valor e igual ou superior entao a saıda e ativada. Quando o registo de tempo-

rizacao do PCA atinge o overflow, o valor do registo CCAPLn e carregado com o

valor do registo CCAPHn. Isto permite fazer atualizacao do valor do PWM sem a

ocorrencia de falhas no sinal. Os bits de PWMn e ECOMn devem ser ativados no

registo CCAPMn para selecionar o modo pretendido.

PWM DD: Design

O diagrama de classes da figura 4.4 representa a estrutura de classes do driver de

PWM. Este e composto por uma classe principal, uma estrutura de configuracao e

varias enumeracoes.

Figura 4.4: Diagrama de classes do driver PWM

A classe tem quatro atributos e dez metodos. Relativamente aos atributos, dois de-

les sao atributos da instancia e dois atributos da classe (atributos estaticos). Os atri-

butos da instancia permitem caracterizar cada objeto com a especificacao do modulo

87

Page 106: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

(module) e o valor do duty-cycle (dutycycle). Os atributos da classe permitem gerir

e garantir a unicidade dos modulos de PWM. No que diz respeito aos metodos, estes

tambem podem ser caracterizados como metodos da instancia e metodos da classe.

Assim, a classe Pwm8051 possui sete metodos da instancia e tres metodos da classe.

Os primeiros permitem instanciar e configurar um objeto, enquanto os outros permi-

tem gerir os modulos, de modo a nao permitir tanto a instanciacao de modulos de

PWM ja criados, como ultrapassar o limite maximo de modulos de PWM existentes

no periferico.

A estrutura pwm8051 config e utilizada para configurar cada um dos modulos da

sua instanciacao ou configuracao. Com esta metodologia, apenas e passado o aponta-

dor da estrutura no chamada do metodo, garantindo assim melhor desempenho. Isto

porque o compilador em vez de colocar todos os argumentos na pilha ou em regis-

tos, coloca apenas o apontador da estrutura. Quando a configuracao requer poucos

parametros a diferenca de performance nao e assim tao acentuada, no entanto em

drivers com muitos parametros de configuracao a diferenca e consideravel.

A utilizacao das diversas enumeracoes permite adicionar alguma portabilidade ao

codigo a desenvolver. Exemplificando, caso outra versao do microcontrolador utilize

o valor 0x60 em vez de 0x40 para ativar o modulo de PWM, entao basta modificar

esse valor na enumeracao sem ter de modificar todos os segmentos de codigo que o

usam.

PWM DD: Implementacao

A utilizacao da orientacao a objetos no desenvolvimento de software tem crescido

exponencialmente, muito por causa da simplicidade e transparencia na passagem do

design para a implementacao. Se o software for bem desenhado utilizando as tecnicas

de UML, a implementacao torna-se muito clara e fidedigna. Portanto, o codigo da

listagem 4.8 representa a declaracao da classe especificada no diagrama da figura 4.4.

class Pwm8051

{public:

Pwm8051();

Pwm8051(pwm8051 Config ∗ Config);

˜Pwm8051();

void config(pwm8051 Config ∗ Config);

void config DC module(unsigned char dc);

void config Freq module(pwm freq freq);

void enable module(pwm en enable);

static bool check module(unsigned char module);

88

Page 107: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

static void enable ALL(pwm en enable);

static void config Freq ALL(pwm freq freq);

private:

unsigned char module;

unsigned char dutycycle;

enum {max pwm modules = 4};static unsigned char modules[];

static unsigned char num modules;

};

Listagem 4.8: Declaracao da classe Pwm8051

Na classe apresentada acima, utiliza-se a tecnica de encapsulamento. Portanto,

os metodos sao declarados como publicos, enquanto os atributos como privados. Os

primeiros tres metodos representam o construtor e destrutor da classe. Os quatro

metodos seguintes permitem fazer a configuracao total ou parcial do device driver, isto

e, permitem configurar o duty-cycle, frequencia e activacao de cada um dos modulos.

Os ultimos tres metodos sao os metodos da classe, pois permitem a configuracao de

todos os modulos simultaneamente, e nao de cada instancia ou modulo em particular.

Os primeiros dois atributos permitem configurar cada modulo. A enumeracao limita

o numero maximo de modulos do periferico. Os ultimos dois atributos da classe

permitem fazer essa gestao dos modulos.

A estrutura que permite fazer a configuracao do driver e apresentada na listagem

4.11. Esta e composta por dois elementos, que permitem configurar qual o modulo

que se pretende instanciar (0 a 4) e o respectivo valor do duty-cycle (0 a 255, em que

255 corresponde a estar sempre activo).

typedef struct pwm8051 config

{unsigned char dc;

unsigned char module;

}pwm8051 Config;

Listagem 4.9: Estrutura de configuracao da classe Pwm8051

A definicao das enumeracoes que contem a informacao dos parametros especıficos

deste hardware e apresentada na listagem 4.10.

enum pwm freq {f osc2 = 0x02, f osc6= 0x00, f timer = 0x04, f ext = 0x06};enum pwm en {enable = 0x40, disable = 0x00};enum pca pwm {pwm 8bit = 0x42, none = 0x00};

Listagem 4.10: Enumeracoes da classe Pwm8051

Sempre que um novo objeto e instanciado, o periferico PCA e configurado para

funcionar no modo PWM. Depois, com o metodo de configuracao total (config) e

89

Page 108: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

possıvel configurar o modulo criado (listagem 4.11). Esta recebe como parametro o

apontador da estrutura de configuracao, que permite inicializar os atributos module

e dutycycle intrınsecos ao objecto. As duas linhas de codigo seguintes adicionam

esse modulo aos atributos da classe. Por fim, e inicializado o registo de configuracao

do duty-cycle com o valor pretendido.

void Pwm8051::config(pwm8051 Config ∗ Config)

{module = Config−>module;

dutycycle = (255−Config−>dc);

modules[num modules] = module;

num modules++;

switch(module)

{case 0:

CCAP0H=DutyCycle; //Reload value to Duty−Cycle

break;

case 1:

CCAP1H=DutyCycle; //Reload value to Duty−Cycle

break;

case 2:

CCAP2H=DutyCycle; //Reload value to Duty−Cycle

break;

case 3:

CCAP3H=DutyCycle; //Reload value to Duty−Cycle

break;

}}

Listagem 4.11: Metodo config da classe Pwm8051

A implementacao dos restantes metodos pode ser consultada no codigo fonte do

driver PWM desenvolvido.

Device Driver : UART

Universal Asynchronous Receiver/Transmitter (UART) e um transmissor/recep-

tor full-duplex que fornece toda a logica para a transferencia assıncrono, isto e, e

um componente de hardware que converte e formata os dados entre as formas serie

e paralela. Estes geralmente sao usados em conjunto com normas de comunicacao,

nomeadamente RS-232, RS-422 ou RS-485. A designacao universal indica que o for-

mato de dados e as velocidades de transmissao sao configuraveis, e que os nıveis de

tensao dos sinais eletricos sao convertidos por um circuito externo, como por exemplo

o MAX232 [67].

90

Page 109: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

UART no 8051

A porta serie integrada no AT89C51ID2 e compatıvel com a porta serie da famılia

MCS-51. Assim, esta permite a transmissao no modo full-duplex, e pode funcionar

em varios modos e frequencias. A sua principal funcao assenta, portanto, na con-

versao paralelo-serie dos dados a serem transmitidos e conversao serie-paralelo dos

dados recebidos. O hardware da porta serie pode ser acedido atraves dos pinos TxD

(transmissao) e RxD (rececao), e apresenta um buffer que permite a rececao de um

segundo caracter antes da leitura do primeiro. Assim, a rececao dos caracteres e efe-

tuada atraves da leitura do registo SBUF, enquanto o envio de um caracter e realizado

pela escrita no mesmo registo. A porta serie fornece quatro modos de funcionamento,

programados atraves da escrita nos bits SM0 e SM1 do registo SCON. Este registo

contem tambem os bits de estado e controlo da mesma. Os modos 1, 2 e 3 permitem

a comunicacao assıncrona, com os bits de dados encapsulados entre o start e stop

bit. O modo 0 e sıncrono e a porta serie funciona como um registo de deslocamento.

Nos modos 1 e 3 o baud rate e variavel e pode ser gerado pelo temporizador 1 ou 2.

Os modos 2 e 3 permitem a comunicacao entre varios processadores 8051, usando o

modelo de multiprocessamento mestre-escravo. Para isso basta ativar o bit SM2 do

registo SCON.

UART DD: Design

O diagrama de classes da figura 4.5 representa a estrutura de classes do driver

UART. Este e composto por duas classes, uma estrutura de configuracao e varias

enumeracoes.

A classe Uart8051 tem dois atributos e oito metodos. Os atributos, ambos da

instancia, permitem definir um apontador para um buffer de rececao e transmissao,

responsaveis por reter os dados da comunicacao. No que diz respeito aos metodos,

os primeiros quatro permitem instanciar e configurar um objeto UART, enquanto os

outros permitem iniciar o processo de transmissao e rececao, e obter o tamanho de

cada um dos buffers.

A classe Buffer tem cinco atributos e oito metodos. Relativamente aos atributos,

o primeiro (array) e um apontador para o primeiro elemento do buffer, o segundo

(size) define o tamanho do buffer, o terceiro (head) e quarto (tail) permitem gerir

os elementos do mesmo, e, finalmente, o quinto atributo (count) permite saber o

numero de itens presentes no buffer. Os metodos, os primeiros correspondem ao

91

Page 110: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

Figura 4.5: Diagrama de classes do driver UART

construtor e destrutor do objeto, enquanto os restantes fazem a gestao do buffer,

como por exemplo adicionar e remover itens do mesmo.

A estrutura uart8051 config e utilizada para configurar a porta serie no mo-

mento da sua instanciacao ou configuracao. Desta forma, e possıvel configurar por

exemplo o baud rate, modo de operacao (sıncrona ou assıncrona), rececao, e buf-

fers. Com a utilizacao desta metodologia, o ganho de desempenho e relativamente

maior que no caso anterior (driver PWM), pois, tal como foi explicado, o numero

de parametros que seriam passados como argumentos da funcao e consideravelmente

superior.

Mais uma vez, a utilizacao das enumeracoes para especificar os valores dos regis-

tos na configuracao da porta serie, permite adicionar alguma portabilidade e clareza

ao codigo a desenvolver.

UART DD: Implementacao

Na classe Uart8051 (listagem 4.12) e utilizado o encapsulamento para garantir

a integridade dos dados contidos no objeto. Portanto, os metodos sao declarados

92

Page 111: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

como publicos enquanto os atributos como privados. Os primeiros tres metodos

representam o construtor e destrutor da classe. Os sete metodos seguintes permitem

fazer a configuracao total ou parcial do device driver, isto e, permitem configurar,

por exemplo, o baud rate, o modo de funcionamento (sıncrono ou assıncrono), e a

multicomunicacao. Os ultimos quatro metodos permitem desencadear a transmissao

e rececao dos dados, assim como saber o numero de elementos de cada um dos buffers

(rececao e transmissao)

class Uart8051

{public:

Uart8051();

Uart8051(uart8051 Config ∗ Config);

˜Uart8051();

void config(uart8051 Config ∗ Config);

void config baudrate(uart baud baudrate);

void config mode(uart mode mode);

void config reception(uart reception reception);

void config multiCom(uart multiCom multiCom);

void config TX b8(uart tx b8 TX b8);

void config RX b8(uart tx b8 RX b8);

void txStart(void);

void rxStart(void);

int get tx buf size() {return pTx buf−>getSize();}int get rx buf size() {return pRx buf−>getSize();}

private:

Buffer ∗ pTx buf;

Buffer ∗ pRx buf;

};

Listagem 4.12: Declaracao da classe Uart8051

A estrutura que permite fazer a configuracao do driver e composta por oito mem-

bros, que permitem configurar o baud rate (4800, 9600, 19200, 28800, ...), o modo

de operacao (modo 0,1,2 ou 3), a ativacao da rececao, a multicomunicacao, e o 8-

bit de dados da transmissao e rececao. Os elementos ptx buf e prx buf definem

apontadores para os buffers de transmissao e rececao.

A implementacao do construtor da classe que permite a configuracao da porta

serie e apresentado na listagem 4.13. Este recebe como parametro o apontador da

estrutura de configuracao. As primeiras oito linhas de codigo permitem configurar

o valor do baud rate, no entanto apenas nos modos onde isso e possıvel (modos 1 e

3). O temporizador 2 e definido como o gerador de baud rate pois os temporizadores

0 e 1 ja sao utilizados para outras funcoes do sistema operativo. O registo SCON e

93

Page 112: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

configurado com as funcionalidades pretendidas. Os elementos pTx buf e pRx buf,

intrınsecos a classe, sao inicializados com os apontadores pretendidos.

Uart8051::Uart8051(uart8051 Config ∗ Config)

{if(Config−>mode == mode1 || Config−>mode == mode3)

{int baud value;

T2CON = 0x34;//timer 2 baud rate generator

baud value = (int)(65535)−(F OSC/(32∗Config−>baudrate));

RCAP2H = (baud value&0xff00)>>8;

RCAP2L = (baud value&0x00ff);

}SCON |= Config−>mode | Config−>reception | Config−>multiCom

| Config−>tx b8 | Config−>rx b8;

pTx buf = Config−>ptx buf;

pRx buf = Config−>prx buf;

}

Listagem 4.13: Construtor da classe Uart8051 com configuracao

Os metodos apresentados na listagem 4.14 implementam a transmissao e rececao

de dados na porta serie. A transmissao consiste em colocar no registo SBUF um

elementos do buffer de transmissao, e esperar que a flag de conclusao de transmissao

(TI) seja ativa. Para enviar n elementos, repete-se o processo n vezes. A recepcao e

o processo inverso. Aguarda-se que a flag de conclusao de recepcao (RI) seja ativada,

e coloca-se o elemento recebido no buffer de rececao. Para receber n elementos,

repete-se o processo n vezes.

void Uart8051::txStart(void)

{SBUF = tx buf−>remove();

while(!(SCON&TI)); //while TI=0

SCON &=˜TI;//Clean TI

}void Uart8051::rxStart(void)

{while(!(SCON&RI));//while RI=0

SCON &=˜RI;//Clean RI

rx buf−>add(SBUF);

}

Listagem 4.14: Metodos txStart e rxStart da classe Uart8051

A implementacao dos restantes metodos, assim como a implementacao da classe

Buffer, pode ser consultada no codigo fonte do driver UART desenvolvido.

94

Page 113: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

Device Driver: GPIO

General Purpose Input/Output (GPIO), ou em portugues, entradas/saıdas de

proposito geral, podem ser designadas como pinos genericos presentes em chips cujo

comportamento (incluindo a definicao de entrada ou saıda) pode ser controlador por

software. Este tipo de hardware e muito utilizado em integrados multifuncoes (por

exemplo, codecs de audio, placas de vıdeo) ou em aplicacoes embebidas (por exemplo,

Arduino) para leitura de sensores (temperatura, aceleracao, orientacao) ou controlo

de motores de corrente continua e brilho de LEDs. As capacidades de um pino de

GPIO incluem a configuracao da direcao (entrada ou saıda), mascara (ativos ou ina-

tivos), valores de entrada e saıda, e configuracao de interrupcoes. Um grupo de pinos

GPIO, tipicamente 8 pinos, e designado como um porto GPIO.

GPIO no 8051

Todos os registos de controlo de perifericos do 8051 estao mapeados na memoria

de dados interna, concretamente na area do SFR. Assim sendo, as quatro portas de

entrada/saıda possuem quatro registos de 8-bit que permitem controla-los: P0, P1,

P2 e P3. Cada um destes registos possui latches e hardware de interface as saıdas

(output drivers) e de leitura das entradas (input buffers) que permitem implementar

as funcionalidades necessarias a uma porta de entrada/saıda digital. As oito linhas de

cada uma destas portas I/O podem ser tratadas individualmente, de modo a realizar

a interface a dispositivos de 1-bit, ou entao como unidades para realizar a interface

paralela de 8-bit a outros dispositivos. Por defeito todos os pinos estao definidos como

entradas digitais. Sempre que se pretende definir um pino como saıda, e necessario

ativar a respetiva latch, ou seja, escrever o valor logico ’1’. So depois de definido

como saıda e que o pino pode ser especificado como saıda a nıvel logico alto ou baixo.

GPIO DD: Design

O diagrama de classes da figura 4.6 representa a estrutura de classes do driver

GPIO. Este e composto por uma classe principal, uma estrutura de configuracao e

varias enumeracoes.

A classe tem cinco atributos e sete metodos. Relativamente aos atributos, tres sao

atributos da instancia enquanto os outros sao atributos da classe (atributos estaticos).

Os atributos da instancia permitem caracterizar cada objeto com a definicao da porta

(port), pino (pin) e direcao (direction). Os atributos da classe permitem gerir e

95

Page 114: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

Figura 4.6: Diagrama de classes do driver GPIO

garantir a unicidade dos pinos. No que diz respeito aos metodos, existem tambem

metodos da instancia e metodos da classe. Assim, a classe Gpio8051 possui seis

metodos da instancia e um metodo da classe. Os primeiros permitem instanciar e

configurar um objeto GPIO, enquanto o metodo da classe permite fazer a gestao dos

mesmos, isto e, garantir nao so que nao e instanciado nenhum pino ja utilizado, assim

como um pino que nao exista.

A estrutura gpio8051 Config e utilizada para configurar o pino de GPIO no mo-

mento da sua instanciacao ou configuracao. Desta forma, e possıvel configurar por

exemplo o porto, o pino e a direcao.

GPIO DD: Implementacao

Na classe Gpio8051 (listagem 4.15) os primeiros tres metodos representam o cons-

trutor e destrutor da classe. Os tres metodos seguintes permitem fazer a configuracao

total ou parcial do device driver, isto e, permitem configurar, por exemplo, a porta,

pino e direcao. O ultimo, metodo da classe, permite verificar, antes da configuracao,

se um determinado pino de GPIO e valido. Os primeiros tres atributos permitem a

sua configuracao. Os ultimos dois atributos da classe permitem fazer essa gestao dos

96

Page 115: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

pinos.

class Gpio8051

{public:

Gpio8051();

Gpio8051(gpio8051 Config ∗ Config);

˜Gpio8051();

void config(gpio8051 Config ∗ Config);

void config direction(gpio direction direction);

bool config output(gpio out value);

static bool check gpio(gpio8051 Config ∗ Config);

private:

unsigned char port;

unsigned char pin;

unsigned char direction;

static unsigned char gpios[max gpio];

static unsigned char num gpios;

};

Listagem 4.15: Declaracao da classe Gpio8051

A estrutura que permite fazer a configuracao do driver e composta por tres ele-

mentos, que permitem configurar qual a porta (p0 a p3), o pino (0 a 7), e a direcao

(input ou output) do pino de GPIO.

Sempre que um objeto do tipo pino e instanciado este deve ser devidamente con-

figurado. A listagem 4.16 apresenta a implementacao do metodo de configuracao.

Esta recebe como parametro o apontador da estrutura de configuracao, que permite

inicializar os atributos port, pin e direction intrınsecos ao objecto. As duas li-

nhas de codigo seguintes adicionam esse modulo aos atributos da classe. Por fim, e

especificado no hardware o valor do registo para configuracao da direcao do pino.

void Gpio8051::config(gpio8051 Config ∗ Config)

{port = Config−>port;

pin = Config−>pin;

direction = Config−>direction;

gpios[num gpios] = (port<<4)|(pin);

num gpios++;

switch(port)

{case p0:

if(direction == input) P0|=(1<<pin);

else P0&=˜(1<<pin);

break;

case p1:

if(direction == input) P1|=(1<<pin);

else P1&=˜(1<<pin);

97

Page 116: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

break;

case p2:

if(direction == input) P2|=(1<<pin);

else P2&=˜(1<<pin);

break;

case p3:

if(direction == input) P3|=(1<<pin);

else P3&=˜(1<<pin);

break;

}}

Listagem 4.16: Metodo config da classe Gpio8051

A implementacao dos restantes metodos pode ser consultada no codigo fonte do

driver GPIO desenvolvido.

Device Driver: I2C

Inter-Integrated Circuit (I2C) e um protocolo de comunicacao bidirecional de-

senvolvido e patenteado pela Philips (atual NXP), de forma a reduzir os custos de

fabrico dos dispositivos eletronicos. Isto porque os dispositivos utilizam apenas duas

linhas para a comunicacao (interface serie), permitindo a comunicacao utilizando um

numero reduzido de pinos. As duas linhas utilizadas pelo barramento I2C sao a SCL

(Serial Clock) e SDA (Serial Data). A linha SDA e responsavel por transportar os

dados, enquanto a linha SCL sincroniza a transferencia dos mesmos. Os dispositivos

I2C podem ser classificados como mestre (master) ou escravos (slave). Um disposi-

tivo que inicia a comunicacao e designado por master, enquanto um dispositivo que

responde as mensagens e denominado por slave. Um dispositivo pode ser unicamente

master, unicamente slave, ou entao comutar entre master e slave, dependendo da

finalidade da aplicacao. Normalmente, a velocidade de comunicacao corresponde a

100k-bit/s para modo standard, 400k-bit/s para o modo fast e 3.4M-bit/s para o

modo high-speed. [68]

A figura 4.7 ilustra o formato da trama I2C. A comunicacao inicia-se com o en-

vio da condicao de start pelo dispositivo master : enquanto a linha SCL esta a nıvel

logico alto (’1’), a linha de SDA e colocada a nıvel logico baixo (’0’). Depois disso, sao

enviados 7-bit com o endereco do dispositivo slave, mais 1-bit para definir se e uma

operacao de leitura (’1’) ou escrita (’0’). A transmissao e confirmada com o envio de

um acknowledge (linha SDA a ’0’) pelo dispositivo slave. A etapa seguinte consiste

no envio do byte de dados. Caso seja bem sucedido o slave envia novo acknowledge.

98

Page 117: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

Posto isso, ou sao enviados dados continuamente, ou entao e sinalizada a condicao

de paragem por parte do master. Essa condicao consiste em colocar ambas as linhas

de comunicacao a nıvel logico alto.

Figura 4.7: Formato da trama I2C

I2C no 8051

No 8051 classico, nao existe uma implementacao por hardware do protocolo de co-

municacao I2C. No entanto, com o aumento exponencial da utilizacao do mesmo, os

fabricantes decidiram implementa-lo em algumas das versoes mais modernas. Assim,

o AT89C51ID2 da Atmel e um exemplo onde este esta presente.

Neste microcontrolador, o protocolo esta implementado com a designacao TWI

(2-wire interface). Isto porque a NXP patenteou o nome I2C, pelo que os outros fabri-

cantes implementam um protocolo analogo com uma designacao diferente. Tal como

o I2C, o TWI utiliza duas linhas para comunicacao, SCL e SDA, que sao responsaveis

pela transferencia e sincronizacao da informacao entre os dispositivos. O CPU con-

trola a logica do protocolo atraves de quatro registos especiais: SSCON (Synchronous

Serial Control); SSDAT (Synchronous Serial Data); SSCS (Synchronous Serial Con-

trol and Status); e SSADR (Synchronous Serial Address). Estes registos permitem

definir quatro modos de operacao: (i) master transmitter ; (ii) master receive; (iii)

slave transmitter ; e (iv) slave receive.

O registo SSCON e usado para ativar a interface TWI, programar a taxa de trans-

ferencia, ativar o modo slave, assinalar ou nao a rececao de dados, e enviar a condicao

de start ou stop. O registo SSCS especifica o estado da logica e barramento do pro-

tocolo. Existem 26 possibilidades diferentes. Estes codigos podem ser consultados

com mais detalhe do datasheet do microcontrolador [69]. O registo SSDAT contem

o byte de dados serie a ser transmitido ou recebido. Por outras palavras, antes de

99

Page 118: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

desencadear e iniciar uma transmissao e necessario carregar o byte para o registo.

Por outro lado, sempre que uma rececao e concluıda, e necessario ler o byte deste

registo. Finalmente, o registo SSADR e responsavel por definir o endereco (7-bit) do

dispositivo sempre que este e definido como slave.

I2C DD: Design

O diagrama de classes da figura 4.8 representa a estrutura de classes do driver

I2C. Este e composto por uma classe principal, uma estrutura de configuracao e

varias enumeracoes.

Figura 4.8: Diagrama de classes do driver I2C

A classe I2c8051 tem tres atributos e dezoito metodos. Os atributos, ambos da

instancia, permitem caracterizar o objeto I2C, nomeadamente o modo de funciona-

mento e o endereco (seja ele o proprio endereco, no caso de ser slave, ou entao o

endereco do dispositivo com o qual pretende comunicar, no caso de ser master). No

que diz respeito aos metodos, os primeiros nove permitem instanciar e configurar um

objeto I2C, enquanto os outros permitem activar, iniciar, enviar, receber e parar a

100

Page 119: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

transferencia de dados. Por exemplo, o metodo start envia a condicao de start do

protocolo, o metodo send address o endereco do dispositivo com o qual se pretende

comunicar, e o metodo read char recebe um byte de um dispositivo slave.

A estrutura i2c8051 Config e utilizada para configurar o dispositivo I2C no mo-

mento da sua instanciacao ou configuracao. Desta forma, e possıvel configurar, por

exemplo, o modo (master ou slave), o sentido da comunicacao (escrita ou leitura), o

endereco e a taxa de transferencia de dados.

I2C DD: Implementacao

Na classe I2c8051 (listagem 4.17) os primeiros tres metodos representam o cons-

trutor e destrutor da classe. Os seis metodos seguintes permitem fazer a configuracao

total ou parcial do device driver, isto e, permitem configurar, por exemplo, o modo,

o endereco e velocidade da comunicacao. Os ultimos metodos permitem a ativacao

(enable), iniciacao(start e rstart), envio (send address e write char), rececao

(read address e read char) e paragem (stop) da transferencia de dados. Os atri-

butos permitem configurar os dispositivos I2C.

class I2c8051

{public:

I2c8051();

I2c8051(i2c8051 Config ∗ Config);

˜I2c8051();

void config(i2c8051 Config ∗ Config);

void config mode(i2c mode mode);

void config rw(i2c rw rw);

void config adress(unsigned char addr);

void config rate(i2c rate rate);

void config assertACK(i2c assert ack assert ack);

void enable(i2c en enable);

void start();

void rstart();

void stop();

bool send address();

bool read address();

bool write char(unsigned char c);

bool read char(unsigned char ∗ c);

void end read char();

private:

i2c mode mode;

i2c rw rw;

unsigned char address;

101

Page 120: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

};

Listagem 4.17: Declaracao da classe I2c051

A estrutura que permite fazer a configuracao do driver e composta por cinco

elementos, que permitem configurar o modo, o sentido (leitura ou escrita), o endereco,

a taxa de transferencia e o envio de confirmacoes (acknowledges).

A implementacao do construtores default da classe e apresentado na listagem 4.18.

Sempre que um dispositivo I2C e instanciado este e configurado como dispositivo

master de escrita, cujo endereco do dispositivo slave com o qual pretende comunicar

e 0x00. Por defeito, o registo de controlo SSCON e configurado de modo a desabilitar

o modulo I2C, a taxa de transmissao igual a frequencia do relogio do CPU com pre-

escalar de 256, e envio de acknowledge.

I2c8051::I2c8051()

{address = 0x00;

rw = write;

mode = master;

SSCON|= fclk 256 | not en | assert;

}

Listagem 4.18: Construtor por defeito da classe I2c051

Os metodos apresentados na listagem 4.19 implementam tanto o envio da condicao

de start como o envio de um byte utilizando o protocolo I2C. O envio da condicao

de start consiste em habilitar a respectiva flag no registo de controlo e aguardar que

o registo de estado (SSCS) sinalize o sucesso no envio. Por sua vez, para o envio

de dados e necessario preencher o registo SSDAT com o byte a enviar, e aguardar

que o registo de estado sinalize a transmissao correta, ou entao notifique a ocorrencia

de alguma anomalia. Daı que o metodo retorne verdade em caso de rececao de

acknowledge, ou falso caso isso nao aconteca.

void I2c8051::start()

{SSCON&=˜isr; //Clear SI interrupt

SSCON|=start ; //TWI start sending

do

{}while(SSCS != start t);//Wait to transmitt ACK

SSCON&=˜start ; //Clear start Condition

}

bool I2c8051::write char(unsigned char c)//return 1 OK, return 0 Error

{SSCON&=˜isr; //Clear SI interrupt

102

Page 121: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

SSDAT = c;

do //Wait Data byte has been transmitted and ACK returned

{}while(SSCS != data t ack r && SSCS != data t nack r

&& SSCS != arbitation lost);

if(SSCS == data t ack r)

{return true;

}else

{return false;

}}

Listagem 4.19: Metodos start e write char da classe I2c8051

A implementacao dos restantes metodos pode ser consultada no codigo fonte do

driver I2C desenvolvido.

Device Driver: SPI

Serial Peripheral Interface Bus (SPI) e um protocolo de comunicacao serie sıncrono,

desenvolvido pela Motorola, que opera no modo full-duplex. Muitas vezes e tambem

designado por protocolo four-wire, isto porque utiliza quatro linhas para a comu-

nicacao: SCLK (Serial Clock); MOSI ou SIMO (Master Out Slave In); MISO ou

SOMI (Master In Slave Out); e SS (Slave Select). As linhas de MOSI e MISO sao

responsaveis pela transferencia dos dados, a linha SCLK pela sincronizacao da trans-

ferencia, e a linha SS pela selecao do dispositivo. Assim, neste protocolo existe um

dispositivo master e um ou mais dispositivos slave. Se existir mais do que um dis-

positivo slave no sistema, entao sao necessarias tantas linhas de selecao quantos os

dispositivos (figura 4.9a [70]).

A figura 4.9b [71] ilustra o diagrama temporal do protocolo. Sempre que o dis-

positivo master pretende iniciar a comunicacao este seleciona o dispositivo slave de-

sabilitando (nıvel logico ’0’) a respetiva linha de SS. Depois disso, habilita o sinal

de relogio (SCLK) com uma frequencia inferior a frequencia maxima do dispositivo

slave (tipicamente entre 1 a 30MHz). A polaridade do sinal de relogio pode ser ajus-

tada com as opcoes CPOL e CPHA. A comunicacao e full-duplex, pelo que o master

envia um byte para o slave enquanto recebe tambem um byte do mesmo. Quando

nao existirem mais dados para serem transmitidos, o dispositivo master interrompe

o sinal de relogio. Tipicamente o que acontece e manter o sinal de relogio ativo e

103

Page 122: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

habilitar (nıvel logico ’1’) a linha de SS.

(a) Barramento SPI: um master etres slaves independentes

(b) Diagrama temporal do protocolo SPI

Figura 4.9: SPI: barramento e diagrama temporal

SPI no 8051

No 8051 classico, tambem nao existe uma implementacao por hardware do pro-

tocolo de comunicacao SPI. No entanto, tal como fizeram com o protocolo I2C,

os fabricantes decidiram implementa-lo em algumas das versoes mais modernas. O

AT89C51ID2 e exemplo disso.

Neste microcontrolador, os modulos de SPI incluem comunicacao full-duplex,

operacao no modo master ou slave, oito taxas de transferencia programaveis, si-

nal de relogio com polaridade e fase programaveis, e protecao contra colisoes. O

CPU controla a logica do protocolo atraves de tres registos especiais: SPCON (Serial

Peripheral Control); SPSTA (Serial Peripheral Status); e SPDAT (Serial Peripheral

Data). O registo SPCON e usado para ativar a interface SPI, configurar o modo de

operacao, programar a frequencia de transferencia, e selecionar a polaridade e fase do

sinal de relogio. O registo SPSTA contem as flags que traduzem o estado da logica e

barramento do protocolo. Por exemplo, se os dados foram transferidos com sucesso e

ativada a flag SPIF (Serial Peripheral Data Transfer Flag), enquanto se houver uma

colisao de informacao e ativada a flag WCOL (Write Collision Flag). Finalmente, o

registo SPDAT representa o buffer de escrita/leitura para a rececao de dados. Uma

escrita para este registo coloca os dados diretamente no shift register.

SPI DD: Design

104

Page 123: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

O diagrama de classes da figura 4.10 representa a estrutura de classes do dri-

ver SPI. Este e composto por uma classe, uma estrutura de configuracao e varias

enumeracoes.

Figura 4.10: Diagrama de classes do driver SPI

A classe tem seis atributos e dezassete metodos. Relativamente aos atributos,

quatro sao atributos da instancia, enquanto dois sao atributos da classe. Os atributos

da instancia permitem caracterizar cada objeto com a especificacao do modo (mode),

operacao (rw), endereco (address) e linha de selecao (chip select). Os atributos da

classe permitem gerir e garantir a unicidade dos modulos SPI, mais concretamente, a

linha de selecao. No que diz respeito aos metodos, a classe Spi8051 possui dezasseis

metodos da instancia e unicamente um metodo da classe. Os primeiros dez permitem

instanciar e configurar um objeto, enquanto os restante permitem activar, iniciar,

enviar, receber e parar a transferencia de dados. O unico metodo da classe permite

gerir as linhas de selecao, de forma a que sao seja instanciados objetos de dispositivos

105

Page 124: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

com a mesma linha de selecao.

A estrutura spi8051 Config e utilizada para configurar o dispositivo SPI no mo-

mento da sua instanciacao ou configuracao. Desta forma, e possıvel configurar por

exemplo o modo (master ou slave), a operacao (escrita ou leitura), a taxa de trans-

ferencia de dados, e a polaridade e fase do sinal de sincronismo.

SPI DD: Implementacao

Na classe Spi8051 (listagem 4.20) os primeiros tres metodos representam o cons-

trutor e destrutor da classe. Os sete metodos seguintes permitem fazer a configuracao

total ou parcial do device driver, isto e, permitem configurar, por exemplo, o modo, a

operacao, e a polaridade e fase do sinal de relogio. Os restantes metodos da instancia

permitem a ativacao, envio e rececao de dados. O ultimo metodo e o metodo da

classe, responsavel por verificar a unicidade de cada instancia. Os primeiros quatro

atributos permitem a configuracao do dispositivo. A enumeracao limita o numero

maximo de dispositivos SPI (limitado ao numero de linhas de selecao). Os ultimos

dois atributos da classe permitem fazer essa gestao das linhas de selecao.

class Spi8051

{public:

Spi8051();

Spi8051(spi8051 Config ∗ Config);

˜Spi8051();

void config(spi8051 Config ∗ Config);

void config mode(spi mode mode);

void config clk pol(spi clk pol clk pol);

void config clk phase(spi clk phase clk phase);

void config rate(spi rate rate);

void config RW(spi rw rw);

void config address(unsigned char addr);

void enable(spi enable enable);

bool send address();

int read address();

bool write char(unsigned char c);

bool read char(unsigned char ∗c);

void enableCS(bool value);

static bool check Device(unsigned char CS);

private:

spi mode mode;

spi rw rw;

unsigned char address;

unsigned char chip select;

enum {max spi devices = 7};static unsigned char devices[];

106

Page 125: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

static unsigned char num devices;

};

Listagem 4.20: Declaracao da classe Spi8051

A estrutura que permite fazer a configuracao do driver e composta por sete ele-

mentos, que permitem configurar o modo, a linha de selecao, a taxa de transferencia,

o endereco, a operacao, e a polaridade e fase do sinal de relogio.

A implementacao do construtor que permite a configuracao do dispositivo SPI e

apresentado na listagem 4.21. Este recebe como parametro o apontador da estrutura

de configuracao. As primeiras tres linhas de codigo permitem inicializar os atributos

intrınsecos ao objeto com os respetivos parametros da estrutura e configuracao. De-

pois disso, e feita a configuracao no hardware atraves do registo de controlo SPCON.

As ultimas tres linhas de codigo permitem especificar a linha de selecao e adiciona-la

aos atributos da classe.

Spi8051::Spi8051(spi8051 Config ∗ Config)

{Address = Config−>addr;

RW = Config−>rw;

Mode = Config−>mode;

SPCON|= Config−>mode | Config−>rate |Config−>clk pol | Config−>clk phase;

Chip Select = (1<<Config−>cs);

Devices[Num Devices] = Chip Select;

Num Devices++;

}

Listagem 4.21: Construtor da classe Spi8051 com configuracao

O metodo da listagem 4.22 implementa a rececao de um byte de dados. Para

receber a informacao e necessario limpar o registo de status e de dados, e esperar

que esse registo sinalize a finalizacao da transferencia ou a ocorrencia de algum erro.

Caso os dados sejam recebidos corretamente, estes sao lidos do registo SPDAT e a

funcao retorna true (!0). Caso contrario a funcao retorna false (0).

bool spi8051::read char(unsigned char ∗ c)

{SPSTA=reset; //Clear

SPDAT=reset; //Data

do

{}while(SPSTA != data t complete && SPSTA != write collision && SPSTA !=

ss slave error && SPSTA != mode fault);

if(SPSTA == data t complete)

{∗ c = SPDAT;

107

Page 126: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

return true;

}else

{return false;

}}

Listagem 4.22: Metodos read char da classe Spi8051

A implementacao dos restantes metodos pode ser consultada no codigo fonte do

driver SPI desenvolvido.

4.2.3 Upgrade: escalonador power-aware

Nos ultimos anos, o consumo de energia tem sido uma das principais metricas no

projeto e concepcao de dispositivos digitais, devido ao aumento crescente na procura

de sistemas portateis como telemoveis, tablets, maquinas fotograficas e dispositivos

medicos, onde se pretende minimizar o consumo de energia e simultaneamente maxi-

mizar a performance e a complexidade das funcionalidades. O design destes sistemas

requer obviamente o uso de processadores reprogramaveis (microcontroladores, mi-

croprocessadores, DSPs), que funcionam como o nucleo do sistema. Assim sendo, o

constante aumento de funcionalidades dos sistemas tende a ser realizado por software,

que e sustentado pela elevada performance dos processadores mais modernos. Por

outras palavras, existe um conflito no desenho e concepcao destes sistemas: como

sistemas portateis, estes devem ser desenhados para maximizar a duracao da bateria;

mas, como dispositivos inteligentes, estes necessitam de processadores com elevada

capacidade de processamento (que consomem mais energia que os que sao usados em

dispositivos simplistas), o que se traduz numa reducao do tempo util da bateria.

Reconhecendo a necessidade de reducao do consumo de energia nos processadores

destes dispositivos modernos, a comunidade cientıfica propos um conjunto de solucoes

a nıvel de hardware e software. A nıvel de software, os metodos propostos podem

ser classificados em duas categorias: (i) tecnicas de compilacao power-aware; (ii)

tecnicas de gestao do consumo de energia atraves do sistema operativo. A segunda

abordagem tem sido mais explorada, devido ao reconhecimento da importancia dos

sistemas operativos na gestao do consumo dos componentes do sistema.

E neste sentido que surge o escalonador power-aware. Um escalonador power-

aware e um escalonador que procura tirar partido das funcionalidades dos processa-

108

Page 127: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

dores mais modernos, de modo a minimizar o consumo de energia (dos processadores),

todavia sem comprometer a execucao das aplicacoes. Por outras palavras, um esca-

lonador power-aware implementa ou modifica uma estrategia de escalonamento com

base no facto dos processadores mais modernos disponibilizarem diferentes modos

de operacao, bem como frequencia e tensao de operacao variaveis. Resumindo, estas

estrategias de escalonamento so sao implementaveis caso os processadores disponham

desses recursos.

Como foi mencionado no inıcio do documento, a presente dissertacao e apenas uma

fracao de um trabalho conjunto de hardware-software co-design, que inclui tambem o

desenvolvimento de um microcontrolador de baixo consumo customizavel. O micro-

controlador sera implementado em FPGA, daı que apenas dara suporte a frequencias

de operacao diferentes. Assim sendo, o estrategia de escalonamento a implementar

tera de explorar apenas essa caracterıstica para minimizar o consumo do microcon-

trolador, visto que a variacao da tensao apenas e possıvel de implementar em ASIC.

Algoritmo de escalonamento power-aware

Dos inumeros trabalhos desenvolvidos na area [72, 73, 74, 75, 76], o autor reco-

nheceu especial interesse ao trabalho desenvolvido por Pillai e Shin [75]. O trabalho

desenvolvido pelos investigadores distingue-se dos demais, pois os metodos de reducao

de energia implementados garantem as deadlines das tarefas, daı poderem ser apli-

cados em sistemas de tempo-real. Os autores exploram as alteracoes necessarias a

aplicar a escalonadores usados em sistemas operativos de tempo-real, de modo a con-

seguir reduzir o consumo energetico, sem porventura comprometer as deadlines das

tarefas.

Os metodos implementados sao baseados nos algoritmos DVS (Dynamic Voltage

Scaling), que diminuem a tensao de operacao e a frequencia do processador nos mo-

mentos em que a carga de processamento e baixa. Neste caso, os investigadores

exploram apenas a variacao da frequencia nos metodos implementados, daı a especial

atencao do autor da dissertacao para este trabalho. Os tres metodos implementa-

dos - (i) statically-scaled, (ii) cycle-conversing e (iii) look-ahead - modificam duas

estrategias de escalonamento de tempo-real: rate-monotonic e earliest deadline first.

O primeiro metodo (statically-scaled) e estatico e consiste na reducao da frequencia

para um valor que garanta as deadlines de um conjunto de tarefas. Para selecio-

nar a frequencia apropriada e calculado um fator baseado na frequencia maxima de

109

Page 128: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

operacao e a frequencia discreta selecionada. A frequencia mınima e aceite com base

na menor frequencia discreta que garanta a deadline das tarefas. A garantia da dea-

dline e testada com base no perıodo e o pior tempo de execucao (WCET - worst case

execution time) de cada tarefa. Este metodo nao explora completamente a reducao

da frequencia, pois ignora os casos nos quais a tarefa executa menos que o seu WCET.

Apesar de nao ser o mais agressivo e sem duvida o mais facil de implementar, pois

os calculos sao realizados estaticamente.

Algoritmo 5 Look-Ahead DVS para o escalonador EDF

select frequency(x):lowest freq. fi ∈ {f1, ... ,fm|f1< ... <fm}such that x ≤ fi/fm

upon task release(Ti):set c lefti = Ci;defer();

upon task completation(Ti):set c lefti = 0;defer();

during task execution(Ti):decrement c lefti;

defer():set U = C1/P1 + ... + Cn/Pn;set s = 0;for i = 1 to n, Ti ∈ {T1, ... ,Tn|D1≥ ... ≥Dn};

set U = U - Ci/Pi;set x = max(0 , c lefti - (1-U)(Di-Dn));set U = U + (c lefti-x)/(Di-Dn);set s = s + x;

endforselect frequency (s/(Dn - current time));

Por sua vez, o metodo cycle-conserving, contrariamente ao metodo estatico, pro-

cura aproveitar os ciclos que sobram das execucoes das tarefas anteriores para execu-

tar as proximas tarefas a velocidades mais baixas, isto e, com frequencias mais baixas.

Para isso, cada vez que uma tarefa termina ou e suspensa, o escalonador recalcula

a utilizacao do sistema. Este metodo e mais agressivo e mais difıcil de implementar

110

Page 129: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

que o anterior, pois o calculo da utilizacao do processador e feito dinamicamente.

O ultimo metodo, look-ahead, ao contrario dos outros metodos, comeca a execucao

das tarefas a baixa frequencia e apenas aumenta a frequencia se precisar de garantir

as deadlines. Este metodo aproveita da melhor forma a existencia de ciclos mortos,

resultantes da execucao da tarefa em menos tempo que o WCET. De todos este e o

metodo mais agressivo, e o mais difıcil de implementar. Em contrapartida, e o que

apresenta melhores resultados, segundo Pillai e Shin, conseguindo atingir reducoes de

consumo na ordem dos 66% quando comparado com a execucao plena do algoritmo

EDF.

Com base nesses resultados, o autor ira implementar o metodo look-ahead (algo-

ritmo 5). No pseudo-codigo fi representa a frequencia selecionada entre as frequencias

discretas disponıveis, fm a frequencia maxima, Ti representa a tarefai da lista de ta-

refas, Ci o WCTE da tarefai, c lefti o tempo que falta para atingir o WCET da

tarefai, Pi o perıodo da tarefai, Di a deadline da tarefai, U a utilizacao do sistema,

e s o numero total de ciclos mınimo que e necessario executar antes da deadline mais

proxima.

Implementacao do escalonador power-aware

A implementacao do metodo look-ahead com escalonamento EDF para o sistema

operativo ADEOS, consistiu basicamente na reimplementacao da classe Sched, Task e

TaskList. Estas classes foram implementadas com uma nova designacao (Sched PW,

Task PW e TaskList PW) ja a pensar na customizacao e configuracao do sistema ope-

rativo.

Na definicao da classe Task PW (listagem 4.23), foram acrescentadas alguns atri-

butos, cuja informacao se torna essencial para o metodo look-ahead, nomeadamente o

perıodo, deadline e WCET da tarefa. No construtor e tambem calculada a utilizacao

global do sistema (U) para determinar se o conjunto de tarefas e escalonavel ou nao.

Assim sendo, antes de adicionar a tarefa, e verificado se o e possıvel fazer. Caso nao

o seja, o construtor da classe retorna sem adicionar a tarefa a lista de tarefas.

Task PW::Task PW(void (∗function)(), int stackSize, Deadline Task deadline, WCET Task wcet)

{stackSize /= sizeof(int);

//Power−Aware: global Utilization test

int tempUtili = os.GlobUtiliz + ((float)Task wcet/(float)Task deadline )∗100;

if(tempUtili >=100) return; //If U > 100% return and dont insert this task

else

111

Page 130: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.2. Upgrade do ADEOS

{if(!(function == idle)) //If Not idle, update GlobalUtilization

{os.GlobUtiliz = tempUtili;

}}

enterCS(); ////// Critical Section Begin

// Initialize the task−specific data.

...

period = Task deadline;//PowerAware

deadline = Task deadline;//PowerAware

wcet = Task wcet; //PowerAware

cleft = wcet; //PowerAware

...

exitCS(); ////// Critical Section End

}

Listagem 4.23: Construtor da classe do escalonador power-aware

Na classe TaskList PW foi necessario reimplementar os metodos de insercao e

remocao das tarefas. Isto porque foi necessario implementar uma lista duplamente

ligada, uma vez que o metodo look-ahead necessita de percorrer a lista de tarefas nos

dois sentidos.

Por sua vez, na classe Sched PW, para alem das modificacoes ao nıvel da classe,

foram tambem modificadas a rotina da interrupcao de overflow do temporizador 1,

bem como o metodo schedule. Alem disso, foram introduzidos os metodos defer e

select freq essenciais para a implementacao do algoritmo look-ahead especificado

anteriormente.

Na rotina de interrupcao de overflow do temporizador 1 (listagem 4.24), res-

ponsavel pelo clock-tick do escalonador, sao entao atualizadas as variaveis responsaveis

pelo tempo total decorrido no sistema (os.currentTime), assim como o tempo que

falta para a conclusao do WCET da tarefa (os.pRunningTask->cleft).

#pragma vector = TF1 int

interrupt void Sched::tick(void)

{enterCS();

recharge sched tick(˜os.cycles tick);

os.pRunningTask−>cleft−=os.tick;//Power Aware

os.currentTime+=os.tick;//Power Aware

os.schedule();

exitCS();

}

Listagem 4.24: Alteracoes na ISR do clock-tick do escalonador

112

Page 131: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

No metodo schedule, e entao introduzida a chamada do metodo defer, res-

ponsavel por determinar se e possıvel baixar a frequencia de relogio do CPU sem

comprometer as deadlines das tarefas. Alem disso, caso a proxima tarefa a entrar

em execucao seja a idle, entao a frequencia e baixada para o mınimo e os atributos

do escalonador que permitem gerir as temporizacoes dinamicamente sao atualizados

(os.F cpu e os.cycles tick). A implementacao da funcao defer e apresentada na

listagem 4.25. Aqui nao ha muito a explicar porque consiste na traducao fidedigna

do pseudo-codigo apresentado no algoritmo look-ahead.

void Sched PW::defer(void)

{...

// Look−Ahead Algorithm

do

{Utilization= Utilization + (((float)pPrev−>wcet/(float)pPrev−>period) ∗ 100);

pPrev = pPrev−>pNext;

}while (pPrev != &os.idleTask && readyList.pTop != &os.idleTask);

pPrev = pPrev−>pPrevious;//Idle−>pPrevious

s = 0;

while(pPrev!= NULL)

{long temp = (((float)pPrev−>wcet/(float)pPrev−>period) ∗ 100);

Utilization = Utilization − temp;

temp = (long)(pPrev−>cleft − (long)(100 − Utilization)∗(long)(pPrev−>deadline − readyList.pTop−>deadline));

if(temp<0) x = 0;

else x= temp;

Utilization = Utilization + (pPrev−>cleft − x)/

(pPrev−>deadline − readyList.pTop−>deadline);

s=s+x;

pPrev = pPrev−>pPrevious;

}SelectFreq(((unsigned int)(s∗16)/(unsigned int)(readyList.pTop−>deadline − currentTime))∗100);

}

Listagem 4.25: Implementacao do metodo defer

Finalmente, a tabela 4.4 apresenta o codigo C++ e assembly da implementacao

do metodo de seleccao de frequencia, invocado no final do metodo defer. Esta funcao

para alem de invocar a funcao implementada em assembly de selecao de frequencia,

atualiza tambem os atributos que permitem gerir a temporizacao dinamicamente. A

implementacao em assembly atualiza os registos do microcontrolador customizavel

dedicados ao escalonador.

113

Page 132: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.3. Refactoring do ADEOS

Tabela 4.4: Implementacao C++ e assembly da selecao da frequencia

Metodo C++ CDP (8051)

void Sched PW::SelectFreq(unsigned int x){

os.F cpu = F max>>select freq(x);

os.cycles tick = (((F cpu)∗os.tick)/12);}

select freq:CODE;HWFSH = ((unsigned char)x >> 8) | 0xC0;MOV A,R5ORL A,#0xC0MOV HWFSH,A;HWFSL = (unsigned char)x;MOV A,R4MOV HWFSL,Aflag freq:;while ( HWFSH & (1<<7))MOV A,HWFSHMOV C,A.7JC flag freq; CKRL = ((HWFSH >> 3) & 0x7)MOV A,HWFSHRR ARR ARR AANL A,#0x07MOV CKRL,A;return CKRL in R1MOV R1,CKRLRET

4.3 Refactoring do ADEOS

A terceira e ultima parte do desenvolvimento do sistema, e a fracao fundamental

do problema da dissertacao. Basicamente, consiste na reestruturacao ou refactoring

do sistema operativo ADEOS, aplicando a tecnica de programacao template metapro-

gramming. Desta forma, e possıvel gerir a variabilidade das funcionalidades e permitir

a customizacao do sistema operativo, sem comprometer o desempenho e introduzir

overhead de memoria.

4.3.1 Diagrama de Funcionalidades

O diagrama de funcionalidades e uma representacao visual do modelo de funcio-

nalidades. Este modelo surgiu com o conceito da orientacao a funcionalidades [77],

permitindo a gestao das funcionalidades comuns e variaveis de um sistema em linha de

producao, sem ter em conta o mecanismo de implementacao a utilizar. O diagrama de

funcionalidades representa um conjunto de funcionalidades, organizadas hierarquica-

mente, onde o nodo da raiz representa o conceito do sistema e os nodos descendentes

as funcionalidades [7]. Este contem quatro tipos possıveis de funcionalidades:

• Funcionalidades obrigatorias: O sistema deve ter obrigatoriamente certas

114

Page 133: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

funcionalidades. Estas funcionalidades sao representadas com um cırculo pre-

enchido a preto.

• Funcionalidades opcionais: O sistema pode, ou nao, ter certas funcionali-

dades. Estas funcionalidades sao representadas com um cırculo sem preenchi-

mento.

• Funcionalidades alternativas: O sistema apenas tem uma funcionalidade

em cada instante de tempo. Estas funcionalidades sao representadas com um

arco sem preenchimento.

• Funcionalidades combinadas: O sistema pode ter uma combinacao de fun-

cionalidades. Estas funcionalidades sao representadas com um arco preenchido

a preto.

Figura 4.11: Diagrama de funcionalidades do ADEOS

A figura 4.11 apresenta o diagrama de funcionalidades do sistema operativo ADEOS.

O no raiz representa o conceito (ADEOS) que e composto por quatro funcionalidades:

Task, IPC, Driver e Scheduler. As funcionalidades apresentadas correspondem aos

componentes do sistema operativo. A funcionalidade Task tem cardinalidade [1..*], o

115

Page 134: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.3. Refactoring do ADEOS

que significa que o ADEOS tem que ser composto no mınimo por uma tarefa (idle).

No entanto, pode ter outras tarefas, consoante as necessidades do utilizador. A funci-

onalidade Scheduler tem cardinalidade [1], ou seja, e obrigatorio a presenca de um, e

apenas um, escalonador no nucleo do sistema. As funcionalidades IPC e Driver tem

cardinalidade [0..*], que indica que estas funcionalidades sao opcionais. Por exemplo,

so e necessario ter a funcionalidade Driver caso seja necessario comunicar com algum

periferico. Da mesma forma, so e necessario a funcionalidade IPC, caso se pretenda

ter comunicacao entre as tarefas.

A funcionalidade Task tem variabilidade. Por exemplo, uma tarefa pode ser ca-

racterizada pela prioridade, caso a intencao seja utilizar a estrategia de escalonamento

(highest priority first), ou entao pela sua deadline, caso se pretenda utilizar o algo-

ritmo earliest deadline first. Neste sentido, e possıvel ter tantos gestores de tarefas

quantos os desejados, todavia mutuamente exclusivos. Apenas um deles pode ser

usado em cada configuracao.

A funcionalidade IPC e constituıda por tantas funcionalidades cumulativas quan-

tas as pretendidas. Como exemplo apresenta-se os mecanismos semaphores e mutex,

mas tambem podem ser utilizados message queue e shared memory. Estas funcionali-

dades sao cumulativas, porque podem ser utilizadas todas ao mesmo tempo, de forma

combinada, ou ate podem nao ser utilizadas. Cada uma das funcionalidades tambem

apresenta variabilidade. No entanto as subfuncionalidades sao exclusivas. Quer isto

dizer que o sistema operativo ADEOS pode utilizar, por exemplo, o mecanismo de

semaphore e mutex ao mesmo tempo, no entanto so pode utilizar uma implementacao

de cada mecanismo em cada configuracao.

A funcionalidade Driver e semelhante a funcionalidade anterior. Desta forma,

podem existir tantos drivers quantos os perifericos com quem se pretende comunicar.

Porta-serie, I2C, bem como SPI, PWM, sao tudo funcionalidades cumulativas que

podem ser utilizadas ao mesmo tempo, mas com implementacoes exclusivas. Ou

seja, as funcionalidades sao cumulativas, no entanto a variabilidade dentro delas

(subfuncionalidades) e exclusiva.

Finalmente, a funcionalidade Scheduler e semelhante a funcionalidade Task. Isto

significa que o sistema operativo pode ter diferentes implementacoes do escalonador,

no entanto mutuamente exclusivas.

116

Page 135: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

4.3.2 Estrategia de Gestao da Variabilidade

Conforme foi visto na seccao 3.3 a tecnica de template metaprogramming nao e

intuitiva e a sintaxe e por vezes um pouco isoterica. Neste sentido, para gerir a

variabilidade do sistema operativo, e consequentemente as diversas funcionalidades,

e necessario definir uma metodologia que sistematize a restruturacao de cada uma.

Assim, como foi visto anteriormente, a variabilidade dentro de cada funcionalidade

especifica e mutuamente exclusiva, o que significa que, por exemplo, se for definido o

driver usart1 na configuracao, implica que nao pode ser usado mais nenhum. Assim

sendo, a metodologia de gestao da variabilidade de uma funcionalidade com template

metaprogramming completa-se em tres etapas.

Tabela 4.5: Classes especificas da funcionalidade example

example1.h example2.hclass example1{

public:example1() {} //Constructor˜example1() {} //Destructorvoid func();void set attr(unsigned char);unsigned char get attr();

private:unsigned char attr 1;

};

//Method examplevoid example1::func(){}

//Attribute set examplevoid example1::set attr(unsigned char attr){

attr 1 = attr;}

//Attribute get exampleunsigned char example1::get attr(){

return attr 1;}

class example2{

public:example2() {} //Constructor˜example2() {} //Destructorvoid func();void set attr(unsigned int);unsigned int get attr();

private:unsigned int attr 2;

};

//Method examplevoid example2::func(){}

//Attribute set examplevoid example2::set attr(unsigned int attr){

attr 2 = attr;}

//Attribute get exampleunsigned int example2::get attr(){

return attr 2;}

A primeira etapa consiste na divisao de cada uma das implementacoes da funcio-

nalidade em tantos ficheiros cabecalhos quantas as implementacoes. Supondo que o

sistema operativo inclui a funcionalidade example, com variabilidade exclusiva a dois

nıveis, isto e, ou e utilizada a implementacao example1 ou entao a implementacao

example2. Assim, a primeira etapa consiste entao em definir cada uma das clas-

117

Page 136: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.3. Refactoring do ADEOS

ses que implementa cada uma das funcionalidades especıficas, em diferentes ficheiros

cabecalho. A tabela 4.5 apresenta a definicao de cada uma dessas hipoteticas classes.

Estas classes servem apenas para explicar a estrategia que deve ser utilizada, nao im-

plementando portanto qualquer funcionalidade. Para alem do construtor e destrutor

da classe, implementam um metodo generico, bem como os metodos set e get de

um atributo. Importa salientar que os atributos tem tipos diferentes, para ilustrar a

possibilidade de o utilizar.

Por sua vez, na segunda etapa e definido um ficheiro cabecalho (* tmp.h) onde

e feita entao a implementacao da funcionalidade com template metaprogramming.

Basicamente, consiste em definir o prototipo da template e a funcionalidade especifica

a utilizar. Depois disso e implementada a template generica, bem como cada uma

das templates especıficas (example1 e example2 ). O codigo 4.26 apresenta o ficheiro

example tmp.h, que corresponde a implementacao com template metaprogramming da

funcionalidade example.

#include ”example1.h”

#include ”example2.h”

template <typename exampleType> class exampleManager; //Specify Template Prototype

typedef example1 example; //Specify Specific Template

typedef exampleManager<example> Example;

example example object; //Define object

//Generic Template

template <>

class exampleManager <exampleGeneric>

{public:

inline static void func() {return; /∗error∗/}inline static void set attr() {return; /∗error∗/}inline static void get attr() {return; /∗error∗/}

};

//Specific Template 1

template <>

class exampleManager <example1>

{public:

inline static void func()

{example object.func();

}inline static void set attr(unsigned char attr)

{example object.set attr(attr);

}

118

Page 137: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

inline static unsigned char get attr()

{return example object.get attr();

}};

//Specific Template 2

template <>

class exampleManager <example2>

{public:

inline static void func()

{example object.func();

}inline static void set attr(unsigned int attr)

{example object.set attr(attr);

}inline static unsigned int get attr()

{return example object.get attr();

}};

Listagem 4.26: Ficheiro example tmp.h

Finalmente, a ultima etapa consiste em utilizar a funcionalidade com a abstracao

necessaria independentemente da funcionalidade especifica. Quer isto dizer, que o

codigo produzido que utiliza a funcionalidade nao deve ser diferente independente-

mente da funcionalidade especificada na configuracao pretendida. Seguindo o exem-

plo da funcionalidade example, o codigo da listagem 4.27 permite aceder tanto aos

metodos da classe example1 como da classe example2. A escolha e feita exclusiva-

mente no ficheiro example tmp.h na linha typedef exampleX example. Substituindo

X por 1 ou por 2 e possıvel definir a configuracao pretendida. Todavia, o codigo que

usa a funcionalidade e exatamente o mesmo.

...

int var = 0;

Example ex;

ex.func();

ex.set attr(0x12);

var = ex.get attr();

...

Listagem 4.27: Transparencia no codigo de acesso a funcionalidade example

Esta metodologia sistematiza entao a estrategia de implementacao das diversas

119

Page 138: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.3. Refactoring do ADEOS

funcionalidades com TMP. No exemplo anterior, apenas foi tratada a variabilidade

a dois nıveis. No entanto, caso a variabilidade fosse a tres nıveis, a metodologia

era a mesma. Simplesmente bastava definir mais um ficheiro cabecalho (example3.h)

com a implementacao da classe pretendida, e no ficheiro example tmp.h especificar a

template especifica para esse caso. O codigo que usa a funcionalidade permanece o

mesmo, e e otimizado para a configuracao escolhida no ficheiro example tmp.h, nao

incluindo portanto o codigo das implementacoes excluıdas.

4.3.3 Reestruturacao do ADEOS

Na reestruturacao do sistema operativo ADEOS para permitir a gestao da vari-

abilidade das funcionalidades, o autor centra-se mais em implementar o suporte a

variabilidade do que a propria variabilidade. Nesse sentido, e normal que a variabi-

lidade dentro de uma funcionalidade apareca replicada, pois o importante e aplicar

a metodologia explicada anteriormente a cada uma das funcionalidades do ADEOS.

Sao reestruturadas as funcionalidades Sched, Task, Mutex, bem como todos os device

drivers desenvolvidos. No entanto, o autor decidiu explicar apenas duas: a gestao

do escalonador e a gestao das tarefas. Isto porque apesar destas funcionalidades

seguirem todas a mesma estrategia, apresentam pequenas variantes. Todas as ou-

tras funcionalidades que nao sao apresentadas, sao reestruturadas de forma analoga,

podendo os detalhes da implementacao serem consultados no codigo do sistema ope-

rativo configuravel.

Escalonador com Template Metaprogramming

Tabela 4.6: Declaracao da classe template da funcionalidade Sched

sched tmp.h config adeos.h#include ”sched1.h”#include ”sched2.h”

template <typename SchedType> class schedManager;typedef schedManager<sched> Sched;sched sched obj;

...

...

/∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ sched tmp ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/#define sched Sched1

...

A reestruturacao do escalonador para permitir a sua customizacao consiste exata-

mente na aplicacao da metodologia explicada anteriormente. Isto porque no sistema

120

Page 139: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

Tabela 4.7: Definicao das templates generica e especificas da funcionalidade Sched

Template Codigo Template

Generic

template <>class schedManager <SchedGeneric>{

public:inline static void start() {return; /∗error∗/}inline static void schedule() {return; /∗error∗/}inline static void add Task(Task ∗ pTask) {return; /∗error∗/}inline static void enterIsr() {return; /∗error∗/}inline static void exitIsr() {return; /∗error∗/}inline static void get pRunningTask() {return; /∗error∗/}inline static void get pIdleTask() {return; /∗error∗/}inline static void get pReadyList() {return; /∗error∗/}

};

Sched1

template <>class schedManager <Sched1>{

public:inline static void start() {sched obj.start();}inline static void schedule() {sched obj.schedule();}inline static void add Task(Task ∗ pTask) {sched obj.add Task(pTask);}inline static void enterIsr() {sched obj.enterIsr();}inline static void exitIsr() {sched obj.exitIsr();}inline static Task ∗ get pRunningTask() {return sched obj.pRunningTask;}inline static Task ∗ get pIdleTask() {return &sched obj.idleTask;}inline static ReadyList ∗ get pReadyList() {return &sched obj.readyList;}

};

Sched2

template <>class schedManager <Sched2>{

public:inline static void start() {sched obj.start();}inline static void schedule() {sched obj.schedule();}inline static void add Task(Task ∗ pTask) {sched obj.add Task(pTask);}inline static void enterIsr() {sched obj.enterIsr();}inline static void exitIsr() {sched obj.exitIsr();}inline static Task ∗ get pRunningTask() {return sched obj.pRunningTask;}inline static Task ∗ get pIdleTask() {return &sched obj.idleTask;}inline static ReadyList ∗ get pReadyList() {return &sched obj.readyList;}

};

operativo existe apenas uma instancia dessa funcionalidade. Assim sendo, em pri-

meiro lugar cada uma das classes que implementa o escalonador deve ser definida

num ficheiro cabecalho. Como o autor implementa duas estrategias de escalona-

mento diferentes, havera dois ficheiros cabecalhos. No entanto, caso surjam novas

implementacoes, sera necessario criar tantos ficheiros cabecalhos quantas as novas

implementacoes. Depois disso, e criado o ficheiro cabecalho sched tmp.h, responsavel

por fazer a gestao da funcionalidade estaticamente com template metaprogramming.

No inicio do ficheiro e feita a inclusao a todos os ficheiros cabecalhos que implemen-

tam os algoritmos de escalonamento, e e definido o prototipo da template. Depois

disso, simplifica-se a sintaxe isoterica das templates, e e definida uma instancia de

121

Page 140: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.3. Refactoring do ADEOS

um objeto do tipo escalonador. No ficheiro cabecalho config adeos.h configura-se o

algoritmo especifico de escalonamento a utilizar. A tabela 4.6 apresenta o codigo do

que foi descrito.

O proximo passo consiste na especificacao da template generica, e de cada uma das

templates especıficas para cada algoritmo de escalonamento. Basicamente, consiste

em definir uma classe template que tem metodos comuns a toda a funcionalidade

do escalonador, mas que sao substituıdos pelos metodos especıficos da estrategia de

escalonamento configurada. O facto dos metodos serem inline, significa que no local

onde sao utilizados sao substituıdos pelo codigo da implementacao, evitando um salto

adicional. A tabela 4.7 resume essa implementacao.

Desta forma, o codigo transparente que gere a funcionalidade e sempre o mesmo,

pois todas as classes templates tem a mesma especificacao. No entanto, a imple-

mentacao dos metodos de cada template e que e diferente. Contudo, como o codigo

generico e substituıdo apenas pelo codigo especıfico da template configurada, garante-

se assim que apenas a funcionalidade pretendida e incorporada, gerando codigo oti-

mizado de acordo com a configuracao. A listagem 4.28 ilustra como o codigo da

funcionalidade Sched permanece transparente, apesar da inclusao da variabilidade

na funcionalidade.

Sched os;

...

void main(void)

{os.add Task(os.get pIdleTask());

os.add Task(&taskA);

os.add Task(&taskB);

os.start();

}

Listagem 4.28: Transparencia no codigo de acesso a funcionalidade Sched

Tarefas com Template Metaprogramming

O refactoring do codigo relativo a funcionalidade Task segue a mesma metodologia

ate agora apresentada, no entanto com umas ligeiras modificacoes. Isto porque a

estrategia apresentada funciona corretamente quando existe apenas um objeto da

classe especıfica da funcionalidade. No entanto, no caso da funcionalidade Task isso

nao acontece. Primeiro porque o sistema operativo pode executar varias tarefas

(varias instancias da classe Taskx), e segundo porque para gerir as tarefas este e

122

Page 141: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

composto por varias listas de tarefas (varias instancias da classe TaskListx). Uma

lista de tarefas e responsavel por reter as tarefas prontas a executar (readyList),

enquanto outras listas estao associadas a cada mutex responsavel por remover a

tarefa da lista de tarefas e coloca-la na waitList. Como cada objeto do tipo mutex

tem associado uma waitList, entao havera tantas listas quantos os mutex.

Neste sentido, e necessario modificar a metodologia ate agora utilizada, de modo

a suportar diferentes e multiplas instancias da mesma classe. No caso da gestao

da lista de tarefas, e necessario um objeto do tipo readyList e tantos objetos do tipo

waitList quantos os mutex (tarefas) utilizados. A solucao encontrada passa entao por

utilizar um meta-argumento na definicao da template da classe. Este meta-argumento

permite distinguir uma readyList duma waitList. Por sua vez, para distinguir cada

uma das waitList, e utilizado um atributo (id) na chamada dos metodos associados.

Este atributo e intrınseco a cada mutex, e incrementado a cada nova instanciacao.

Tabela 4.8: Declaracao da classe template da funcionalidade Task

task tmp.h config adeos.h#include ”task1.h”#include ”task2.h”

template <unsigned char n, typename taskType> class taskManager;typedef taskManager<0,TaskList> ReadyList;typedef taskManager<1,TaskList> WaitList;TaskList readyList, waitList[num waitList];

...

...

/∗∗∗∗∗∗∗∗ task tmp ∗∗∗∗∗∗∗∗/#define num waitList 3#define Task Task1#define TaskList TaskList1

...

Explicando concretamente a reestruturacao do codigo da funcionalidade Task, a

primeira parte consiste entao na definicao de tantos ficheiros cabecalho tantas as

especificacoes. O autor implementa a variabilidade a dois nıveis, daı haver dois fi-

cheiros cabecalhos (task1.h e task2.h). Depois disso, e criado o ficheiro cabecalho

task tmp.h, responsavel por fazer a gestao da funcionalidade estaticamente com tem-

plate metaprogramming. No inıcio do ficheiro (tabela 4.8) e feita a inclusao a todos

os ficheiros cabecalhos, e e definido o prototipo da template. De notar a utilizacao do

meta-argumento n, do tipo unsigned char, que permite especificar 256 variantes da

mesma lista. A utilizacao da keyword typedef no codigo permite simplificar a sintaxe

na designacao atribuıda a ReadyList e WaitList. A ultima linha de codigo define um

objeto do tipo ReadyList e tantos objetos do tipo WaitList quantos os especificados

no ficheiro de configuracao. Nesse ficheiro tambem se define qual a funcionalidade

especifica das tarefas a utilizar.

123

Page 142: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

4.3. Refactoring do ADEOS

De seguida sao especificadas as templates generica e especıficas de cada uma das

implementacoes (tabela 4.9). Basicamente, consiste em definir uma classe template

que tem metodos comuns a toda a funcionalidade das tarefas, mas que sao subs-

tituıdos pelos metodos especıficos da classe configurada (no ficheiro config adeos.h).

Aqui importa justificar o porque de implementar metodos overloading. Esta foi a

forma mais simples de implementar a existencia de diferentes objetos. Como existe

apenas uma lista ReadyList, entao nao e preciso identificar qual delas e. Daı que os

metodos sejam implementados sem a utilizacao do argumento id. Por outro lado,

como existem varios objetos do tipo WaitList, entao e necessario implementar os

mesmos metodos, mas com o argumento extra de identificacao da lista. Daı ser uti-

lizado o argumento id. Tal como foi referido este argumento utilizado no metodo

e um atributo intrınseco de cada objeto mutex, que permite identificar no array de

objetos WaitList, a respetiva lista associada ao mutex. Por isso e comum utilizar

waitList[id ] na implementacao dos metodos da template.

Com esta abordagem, o codigo do sistema operativo que gere esta funcionalidade

permanece praticamente o mesmo (listagem 4.29), isto e, semelhante ao codigo do

sistema operativo sem variabilidade, apenas nos metodos da waitList e necessario

especificar o id do mutex. Alem disso o codigo e suficientemente transparente e

abstracto para que alterando a configuracao da funcionalidade, nao seja necessario

modificar esse codigo que a gere.

...

ReadyList readyList;

readyList.insert(pTask);

readyList.set pTop(NULL);

readyList.get pTop();

...

WaitList waitingList;

waitingList.insert(pCallingTask,this−>id);

waitingList.set pTop(NULL,this−>id);

waitingList.get pTop(this−>id)

...

Listagem 4.29: Transparencia no codigo de acesso a funcionalidade Task

124

Page 143: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 4. Implementacao do Sistema

Tabela 4.9: Definicao das templates generica e especificas da funcionalidade Task

Template Codigo Template

Generic

template <unsigned char n>class taskManager <n, TaskListGeneric>{

public:inline static void insert(Task ∗ pTask) {return; /∗error∗/}inline static void insert(Task ∗ pTask, unsigned char id ) {return; /∗error∗/}inline static void remove(Task ∗ pTask) {return; /∗error∗/}inline static void remove(Task ∗ pTask, unsigned char id ) {return; /∗error∗/}inline static void get pTop() {return; /∗error∗/}inline static void get pTop(unsigned char id ) {return; /∗error∗/}inline static void set pTop(Task ∗ pTask) {return; /∗error∗/}inline static void set pTop(Task ∗ pTask, unsigned char id ) {return; /∗error∗/}

};

Task1

template <>class taskManager <0, TaskList1>{

public:inline static void insert(Task ∗ pTask) { readyList.insert(pTask); }inline static Task ∗ remove(Task ∗ pTask) { return readyList.remove(pTask); }inline static Task ∗ get pTop() { return readyList.pTop; }inline static void set pTop(Task ∗ pTask) { readyList.pTop = pTask; }

};template <>class taskManager <1, TaskList1>{

public:inline static void insert(Task ∗ pTask, unsigned char id ) { waitList[id ].insert(pTask); }inline static Task ∗ remove(Task ∗ pTask, unsigned char id )

{ return waitList[id ].remove(pTask); }inline static Task ∗ get pTop(unsigned char id ) { return waitList[id ].pTop; }inline static void set pTop(Task ∗ pTask, unsigned char id )

{ waitList[id ].pTop = pTask; }};

Task2

template <>class taskManager <0, TaskList2>{

public:inline static void insert(Task ∗ pTask) { readyList.insert(pTask); }inline static Task ∗ remove(Task ∗ pTask) { return readyList.remove(pTask); }inline static Task ∗ get pTop() { return readyList.pTop; }inline static void set pTop(Task ∗ pTask) { readyList.pTop = pTask; }

};template <>class taskManager <1, TaskList2>{

public:inline static void insert(Task ∗ pTask, unsigned char id ) { waitList[id ].insert(pTask); }inline static Task ∗ remove(Task ∗ pTask, unsigned char id )

{ return waitList[id ].remove(pTask); }inline static Task ∗ get pTop(unsigned char id ) { return waitList[id ].pTop; }inline static void set pTop(Task ∗ pTask, unsigned char id )

{ waitList[id ].pTop = pTask; }};

125

Page 144: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 145: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 5

Resultados Experimentais

No capıtulo anterior foi apresentada a implementacao do sistema, comecando pelo

porting do ADEOS para a arquitetura MCS-51, seguindo-se o upgrade e refactoring

do sistema operativo. A reestruturacao do ADEOS para a gestao da variabilidade foi

conseguida utilizando a tecnica de template metaprogramming.

Neste capıtulo, sao apresentados os resultados experimentais dos testes realizados,

numa placa de desenvolvimento com o microcontrolador da famılia 8051 da Atmel,

para avaliar o desempenho e overhead de memoria, bem como as metricas de gestao

do codigo. Foram efetuados dois testes distintos. No primeiro, o sistema operativo

e as diversas funcionalidades foram implementadas de duas formas diferentes: a im-

plementacao na linguagem C++ onde e utilizado template metaprogramming para

gerir da variabilidade; e a implementacao na linguagem C++ onde e utilizado poli-

morfismo dinamico para gerir a variabilidade do sistema operativo. Por sua vez, no

segundo teste, apenas foi averiguado um modulo de device driver. Isto porque para

alem das duas implementacoes em C++, surge uma terceira implementacao em C

utilizando compilacao condicional.

5.1 Ambiente de Testes

Caracterizar o ambiente em que decorreram os testes realizados implica caracte-

rizar essencialmente tres componentes: o hardware onde os testes foram realizados; o

compilador usado para compilar o codigo fonte dos testes realizados; e as ferramentas

de software para avaliacao das metricas em teste.

Para acelerar o desenvolvimento e avaliar o sistema operativo customizavel no

127

Page 146: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

5.1. Ambiente de Testes

Tabela 5.1: Caracterısticas de hardware da placa de desenvolvimento 8051DKUSB

Placa de desenvolvimento Caracterısticas

8051DKUSB

Arquitetura: 8051Processador: AT89C51ID2Velocidade CPU: 12MHzRAM: 256-bytesXRAM: 1792-bytesFlash: 64-kbytesEEPROM: 2048-bytes

desempenho e footprint de memoria, sem depender do trabalho de terceiros, os testes

foram realizados na plataforma de hardware 8051DKUSB (figura 5.1). Esta placa

de desenvolvimento, desenvolvida in-house (ESRG), vem equipada com um micro-

controlador AT89C51ID2 da Atmel, alimentacao USB, conector de 44 pinos para

expansao dos quatro portos do microcontrolador, comunicacao serie atraves da porta

USB (FTDI), display de 7-segmentos ligado ao porto 1, e programacao ISP (In-

System Programming) manual ou automatica. A tabela 5.1 resume as caracterısticas

fundamentais do microcontrolador.

Figura 5.1: Placa de desenvolvimento 8051DKUSB

Para compilar o codigo fonte do sistema operativo ADEOS, incluindo o codigo

das tarefas a executar, foi utilizado o compilador C/C++ da IAR para o 8051. Nas

opcoes de compilacao foi definida a opcao de otimizacao None, de modo a obter codigo

maquina sem qualquer otimizacao. Desta forma sera possıvel avaliar de forma mais

fidedigna da influencia do template metprogramming nas metricas de desempenho,

128

Page 147: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 5. Resultados Experimentais

sem grande interferencia do compilador.

Para obter os resultados das metricas pretendidas foram utilizados essencialmente

tres utilitarios. Para obter os resultados relacionados com o desempenho e memoria,

foram utilizados o debugger do IAR Embedded Workbench for 8051 e o Flip da Atmel,

respetivamente. Por sua vez, para obter os resultados relacionados com as metricas

de gestao do codigo foi utilizado o software Understand da Scientific Toolworkss [78].

5.2 Metricas de Teste

Na seccao 2.3 o autor justificou a escolha da tecnica de template metaprogramming

como a solucao adequada para gerir a variabilidade do sistema operativo implemen-

tado com o paradigma da programacao orientada a objetos. Isto porque apesar do

overhead associado a algumas caracterısticas desse paradigma de programacao, a

tecnica de template metaprogramming permite reestruturar o software de forma a ge-

rir a variabilidade do mesmo, sem porventura comprometer o desempenho e memoria

do sistema.

Assim sendo, faz todo sentido que as metricas em teste estejam relacionadas

essencialmente com o tempo de execucao (desempenho) e o tamanho do ficheiro de

codigo (memoria). No entanto, apesar das metricas desempenho e memoria serem

fatores preponderantes no projeto e concepcao de qualquer sistema, a facilidade de

gestao e expansao do codigo tambem desempenha um papel importante. Isto porque

codigo ilegıvel e mal organizado requer um esforco de engenharia superior. Portanto,

para verificar o grau de complexidade inerente a gestao do codigo bem como a sua

expansao sao analisadas as seguintes metricas:

• Linhas de Codigo (LOC): numero de linhas de codigo, excluindo comentarios e

linhas em branco, presentes nos ficheiros de codigo fonte;

• Numero de Classes (NOC): numero de classes presentes nos ficheiros de codigo

fonte.

5.3 Testes Realizados

Como o sistema operativo pode ser configurado de tantas formas quantas as fun-

cionalidades disponıveis, entao a realizacao dos testes e recolha de resultados torna-se

129

Page 148: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

5.3. Testes Realizados

uma tarefa complexa. Isto devido ao aumento substancial de configuracoes a cada

introducao de uma nova funcionalidade.

Para simplificar essa tarefa, o autor decidiu realizar um primeiro teste, limitando a

variabilidade de cada funcionalidade a dois nıveis. Por outras palavras, apenas com a

variabilidade a dois nıveis, o sistema permite 32 (variabilidadefuncionalidades = 25) con-

figuracoes. A figura 5.2 ilustra o diagrama de funcionalidades do teste em causa. Para

este teste, o autor implementou o sistema utilizando duas metodologias diferentes: (i)

a implementacao na linguagem C++ onde e utilizado template metaprogramming ; e

(ii) a implementacao na linguagem C++ onde e utilizado polimorfismo dinamico. Isto

para tentar sustentar a premissa de que e possıvel utilizar a programacao orientada

a objetos e template metaprogramming para implementar software customizavel em

sistemas embebidos, pois a maioria das funcionalidades da POO (com excecao do po-

limorfismo dinamico, multipla heranca e abstracao) nao compromete o desempenho

do sistema, e facilita a gestao do codigo.

Figura 5.2: Diagrama de funcionalidades do sistema operativo (teste ao sistemaoperativo)

130

Page 149: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 5. Resultados Experimentais

Tabela 5.2: Configuracao usada no teste ao sistema operativo

Funcionalidade ImplementacaoSched Sched HPFTask Task HPFIPC - Mutex Mutex1Driver - USART USART AT89C51Driver - SPI SPI AT89C51

Contudo, uma vez que o primeiro teste apenas permite fazer uma comparacao

entre duas implementacoes que utilizam programacao orientada a objetos, somente

com isso nao e possıvel perceber concretamente qual o potencial de otimizacao da

tecnica de template metaprogramming, quando comparada com uma implementacao

imperativa como linguagem C. No entanto, implementar todo o sistema operativo

assim como as diversas funcionalidades em linguagem C, seria para o autor uma

tarefa inexequıvel. Por este motivo, o segundo teste centra-se apenas numa funcio-

nalidade de um driver, ou seja, sao comparadas e avaliadas as duas implementacoes

em C++ bem como uma implementacao em C do device driver UART (tambem

com variabilidade a dois nıveis). A implementacao em linguagem C utiliza com-

pilacao condicional. Tambem poderia ser implementada utilizando apontadores para

funcoes, no entanto esta metodologia nao e tao otimizada quanto a anterior. Com

este teste, e entao possıvel estabelecer um ponto de comparacao (embora pequeno)

entre a implementacao C++ TMP e a implementacao C otimizada.

5.3.1 Teste ao Sistema Operativo

Com base no diagrama de funcionalidades da figura 5.2, foi possıvel definir a con-

figuracao do sistema operativo (tabela 5.2) para a realizacao do teste. A configuracao

implementa um sistema operativo baseado em prioridades, e utiliza a implementacao

dos drivers UART e SPI na variante Atmel (AT89C51). O teste consiste na execucao

de duas tarefas periodicas: (i) envio de um caracter via serie; e (ii) comunicacao

com um dispositivo SPI slave. O envio do caracter (tarefa de maior prioridade) e

feito a cada dois segundos, enquanto a comunicacao com o dispositivo slave e feita

a cada cinco segundos. O dispositivo SPI slave esta implementado numa placa de

circuito impresso (PCB) concebida pelo autor para avaliar e testar os drivers SPI e

I2C desenvolvidos (apendice A).

131

Page 150: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

5.3. Testes Realizados

Resultados de Desempenho e Footprint de Memoria

Os resultados de desempenho traduzem os resultados a nıvel de tempo de execucao.

Estes indicam os ciclos de relogio necessarios para executar o teste com cada uma das

implementacoes - C++ template metaprogramming e C++ polimorfismo dinamico.

Os resultados de footprint de memoria indicam qual a memoria de codigo necessaria

para executar o teste com cada uma das implementacoes.

Para obter os tempos de execucao de cada uma das implementacoes do sistema

operativo, foi utilizado o debugger do ambiente de desenvolvimento. Nessa avaliacao

nao foi considerado o tempo que demora efetivamente a enviar o caracter via serie,

nem o tempo que demora a enviar a trama I2C. Por outras palavras, como os

drivers foram implementados utilizando o mecanismo de polling, significa dizer que

ao efetuar a depuracao a condicao de verificacao da flag que indica fim de transmissao

foi desprezada. Por outro lado, para avaliar o tamanho da memoria de codigo foi

utilizado o ficheiro de codigo produzido para executar na plataforma de teste.

(a) Tempo de execucao (b) Memoria de codigo

Figura 5.3: Resultados de desempenho e footprint de memoria (teste ao sistemaoperativo)

Os graficos da figura 5.3 apresentam os resultados do tempo de execucao e memoria

de codigo das implementacoes C++ com template metaprogramming (C++ TMP) e

polimorfismo dinamico (C++ PD) do sistema operativo, para a execucao das tarefas

anteriormente descritas.

Tal como os graficos ilustram, a implementacao com TMP apresenta tanto um

132

Page 151: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 5. Resultados Experimentais

tempo de execucao como dimensao de memoria de codigo inferior a outra imple-

mentacao. Basicamente, a implementacao com template metaprogramming reduz

cerca de 20% o tempo de execucao e 40% a memoria de codigo, relativamente a im-

plementacao com polimorfismo dinamico. Isto deve-se ao facto do codigo TMP ser

otimizado para a configuracao pretendida, enquanto na implementacao com polimor-

fismo dinamico o codigo e compilado com todas as funcionalidades selecionadas. Isto

afecta a linearidade do codigo, devido ao elevado numero de saltos (jumps), con-

sequentes do elevado numero de instrucoes que nao sao utilizadas, produzindo um

impacto negativo na performance do sistema.

Os resultados apresentados traduzem apenas dois graus de variabilidade em cada

uma das funcionalidades. Experiencias realizadas pelo autor com tres graus de vari-

abilidade indicam que a implementacao TMP pode reduzir o tempo de execucao em

cerca de 25% e a memoria de codigo em cerca de 50%. Resumindo, num sistema alta-

mente configuravel com elevado grau de variabilidade, a otimizacao usando a tecnica

de template metaprogramming permite atingir resultados significativos nas metricas

em causa.

Resultados de Gestao do Codigo

Embora as metricas de desempenho do sistema sejam de especial importancia em

tempo de execucao, nao implica que a forma como e feita a gestao e manutencao da

variabilidade do codigo nao tenha que ser tida em conta. Assim, torna-se tambem

importante avaliar e comparar as duas implementacoes do sistema operativo ao nıvel

da gestao do codigo, nomeadamente, na metricas LOC e NOC.

Os graficos da figura 5.4 apresentam os valores das metricas LOC e NOC para as

implementacoes C++ com template metaprogramming (C++ TMP) e com polimor-

fismo dinamico (C++ PD) do sistema operativo.

Dos graficos da figura 5.4, conclui-se que o numero de linhas de linhas de codigo

(LOC) das duas implementacoes e praticamente o mesmo (ligeira superioridade para

a implementacao com TMP). No que diz respeito a metrica relacionado com o numero

de classes (NOC), a implementacao C++ com template metaprogramming apresenta

um valor superior ao da implementacao C++ com polimorfismo dinamico. Isto in-

dica que o codigo e mais modular e apresenta um nıvel de encapsulamento superior.

Como consequencia, torna-se mais facil fazer a sua gestao, manutencao e possıvel

reutilizacao.

133

Page 152: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

5.3. Testes Realizados

(a) Numero de linhas de codigo (b) Numero de classes

Figura 5.4: Resultados de gestao do codigo (teste ao sistema operativo)

5.3.2 Teste ao driver USART

Como o teste anteriormente apresentado permite apenas fazer uma comparacao

entre duas implementacoes que utilizam programacao orientada a objetos, por si so

esse teste nao permite aferir o potencial de otimizacao da tecnica de template me-

taprogramming quando comparada com uma implementacao em linguagem C. Nesse

sentido, o autor decidiu focar-se apenas num modulo e implementar a variabilidade

desse modulo com compilacao condicional. Isto para obter resultados conclusivos

acerca da comparacao das duas implementacoes C++ com uma implementacao em

C.

O teste realizado concentra-se no modulo do driver UART. Toda a variabilidade

nas interfaces do driver foram implementadas tambem com compilacao condicional.

Os resultados traduzem o tempo de execucao, memoria de codigo, e metricas de

gestao de codigo, para uma aplicacao sequencial que transmite e recebe um caracter

e uma string via serie.

Resultados de Desempenho e Footprint de Memoria

Os resultados de desempenho traduzem os resultados a nıvel de tempo de execucao.

Estes indicam os ciclos de relogio necessarios para executar o teste com cada uma

das implementacoes - C++ template metaprogramming, C++ polimorfismo dinamico,

C compilacao condicional. Os resultados de footprint de memoria indicam qual

134

Page 153: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 5. Resultados Experimentais

a memoria de codigo necessaria para executar o teste com cada uma das imple-

mentacoes.

Para obter os tempos de execucao de cada uma das implementacoes do sistema

operativo, foi utilizado o debugger do ambiente de desenvolvimento. Nessa avaliacao

nao foi considerado o tempo que demora efetivamente a enviar ou receber o caracter

via serie. Por outro lado, para avaliar o tamanho da memoria de codigo foi utilizado

o ficheiro de codigo produzido para executar na plataforma de teste.

(a) Tempo de execucao (b) Memoria de codigo

Figura 5.5: Resultados de desempenho e footprint de memoria (teste ao driver USART)

Os graficos da figura 5.5 apresentam os resultados do tempo de execucao e memoria

de codigo das implementacoes C com compilacao condicional (C CC), C++ com poli-

morfismo dinamico (C++ PD), e C++ com template metaprogramming (C++ TMP),

do driver, para a execucao da aplicacao anteriormente descrita.

Tal como seria de esperar a implementacao com TMP apresenta novamente um

melhor desempenho e gestao da memoria de codigo quando comparada com a imple-

mentacao com polimorfismo dinamico.

Na comparacao das implementacoes C (compilacao condicional) e TMP, tal como

os graficos ilustram, a implementacao C apresenta tanto um tempo de execucao

como dimensao de memoria de codigo inferior a implementacao TMP. No entanto,

a diferenca e relativamente mais baixa que a diferenca existente entre as duas im-

plementacoes com programacao orientada a objetos. Por exemplo, a implementacao

TMP apenas agrava o desempenho em 5% e o footprint de memoria em 20% quando

135

Page 154: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

5.3. Testes Realizados

comparada com a implementacao C. Ja a implementacao com polimorfismo dinamico

agrava o desempenho em 17% e o footprint de memoria em 75% quando comparada

com a implementacao em linguagem C.

Os resultados apresentados traduzem apenas dois graus de variabilidade na fun-

cionalidade em analise. Experiencias realizadas pelo autor com mais graus de vari-

abilidade indicam que os valores apresentados anteriormente na comparacao entre a

implementacao TMP e a implementacao C mantem-se praticamente constantes com

o aumento da variabilidade. Contudo, quando se compara com a implementacao com

polimorfismo dinamico, o agravamento nas metricas em analise pode ser muito supe-

rior (sobretudo em termos de footprint de memoria) com o aumento da variabilidade

na funcionalidade.

Resultados de Gestao do Codigo

Se as metricas de gestao e manutencao da variabilidade do codigo tenham sido

importantes na interpretacao dos resultados do teste realizado ao sistema operativo,

entao agora neste caso desempenham um papel preponderante. Isto porque como foi

visto anteriormente, apesar da tecnica de template metaprogramming ser muito mais

otimizada que a implementacao com polimorfismo dinamico, esta agrava ligeiramente

o desempenho e memoria da aplicacao quando comparada com a linguagem C. No

entanto, como o overhead e relativamente baixo, as metricas de gestao de codigo

desempenham um papel fundamental na comparacao entre as mesmas.

Os graficos da figura 5.6 apresentam os valores das metricas LOC e NOC para

as implementacoes C com compilacao condicional (C CC), C++ com polimorfismo

dinamico (C++ PD), e C++ com template metaprogramming (C++ TMP), na fun-

cionalidade em analise.

Dos graficos da figura 5.6, conclui-se que o numero de linhas de linhas de codigo

(LOC) das tres implementacoes e praticamente o mesmo (ligeira superioridade para

a implementacao em C). No que diz respeito a metrica relacionado com o numero

de classes (NOC), a implementacao C++ com template metaprogramming apresenta

um valor superior ao da implementacao C++ com polimorfismo dinamico e C com

compilacao condicional. Alias, a implementacao em C, embora apresente uma ligeira

melhoria no desempenho e footprint de memoria que a implementacao com TMP,

nao apresenta qualquer modularidade e encapsulamento no codigo. Em sistemas com

enorme variabilidade, isso reflete-se numa degradacao da organizacao do codigo, pois

136

Page 155: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 5. Resultados Experimentais

(a) Numero de linhas de codigo (b) Numero de classes

Figura 5.6: Resultados de gestao do codigo (teste ao driver USART)

este e poluıdo com as diretivas de pre-processador. Portanto, a gestao e manutencao

deste tipo de sistemas torna-se uma tarefa fastidiosa e suscetıvel a erros, que acaba

por nao compensar os ganhos obtidos nas outras duas metricas.

137

Page 156: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 157: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 6

Conclusoes

Neste ultimo capitulo da dissertacao, sao apresentadas as ilacoes retiradas pelo

autor, com base no que foi implementado. Alem disso, sao apresentadas algumas

sugestoes para melhorar e expandir o trabalho realizado.

6.1 Conclusao

A dissertacao apresenta o porting, expansao e customizacao de um sistema ope-

rativo orientado a objetos para a arquitetura MCS-51. No entanto, esta distingue-se

essencialmente pela aplicacao de template metaprogramming como metodologia para

a gestao da variabilidade do sistema operativo.

Este foi sem duvida um projeto desafiante pela variedade e profundidade de co-

nhecimentos necessarios no domınio dos sistemas embebidos. Desde a compreensao

de diferentes arquiteturas de processadores (80188 e 8051), passando pelos sistemas

operativos (sobretudo de sistemas operativos de tempo-real baseados em microker-

nel), linguagem assembly, programacao orientada a objetos (sobretudo C++), tem-

plate metaprogramming e compiladores, todas estas tematicas foram utilizadas no

desenvolvimento da dissertacao.

Relativamente aos objetivos do trabalho, estes foram efetivamente cumpridos.

Depois de analisados alguns sistemas operativos orientados a objetos, o sistema ope-

rativo ADEOS foi selecionado como a melhor solucao para os recursos da arquitetura

alvo. Assim, foi realizado com sucesso o porting desse sistema operativo para a

plataforma MCS-51. Depois disso, foram expandidas uma serie de funcionalidades

no sistema operativo, principalmente um conjunto de device drivers para comunicar

139

Page 158: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

6.2. Trabalho Futuro

com os perifericos do microcontrolador, bem como um escalonador power-aware para

aplicacoes cujo principal foco seja o baixo consumo energetico. O objetivo seguinte,

e de todo o mais importante do trabalho, consistiu na aplicacao de template meta-

programming para efetuar o refactoring do sistema operativo. Por outras palavras,

a gestao da variabilidade do sistema foi realmente conseguida utilizando essa tecnica

de programacao avancada. Finalmente, o ultimo objetivo concretizado com sucesso

focou-se na validacao da premissa de que e possıvel utilizar C++ template metapro-

gramming (POO), sem comprometer consideravelmente o desempenho e recursos de

memoria, para implementar software embebido altamente customizavel, reutilizavel

e de facil gestao e manutencao. Os resultados obtidos demonstraram que isso e efe-

tivamente possıvel a custa de um overhead reduzido.

6.2 Trabalho Futuro

Apesar do cumprimento de todos os objetivos inicialmente propostos, existem

bastantes funcionalidades e melhorias que podem expandir o trabalho desenvolvido.

A primeira esta relacionada com os device drivers. Conforme foi referido na seccao

4.2.2, mais do que desenvolver controladores de hardware sob a forma de classes, o

conceito de device drivers tem intrinsecamente associado uma determinada abstracao,

que implica disponibilizar servicos comuns a todos os dispositivos. Assim sendo,

propoe-se o desenvolvimento de uma camada de abstracao recorrendo a template

metaprogramming para encapsular todos os perifericos na mesma interface.

A segunda sugestao consiste na expansao das funcionalidades e da sua variabi-

lidade. Mais do que implementar a propria variabilidade em cada funcionalidade,

esta dissertacao preocupou-se mais com a metodologia para gerir essa variabilidade.

Assim sendo, na tentativa de expandir ainda mais o trabalho desenvolvido, propoe-se

implementar mais mecanismos de IPC (semaphore, shared memory, message queue),

mais algoritmos de escalonamento (rate-monotonic, round robin), mais device drivers

(CAN, ADC, DAC), e mais variantes dos mesmos.

A terceira sugestao diz respeito as interrupcoes. O sistema operativo nao dispo-

nibiliza uma interface que permita configurar as interrupcoes do microcontrolador.

Inclusive os device drivers foram implementados apenas com o mecanismo de polling.

Assim sendo, propoe-se a expansao do sistema operativo com uma interface para

configuracao das interrupcoes disponibilizadas pelo 8051.

140

Page 159: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Capıtulo 6. Conclusoes

A quarta sugestao esta ligada aos resultados experimentais. Como foi possıvel

constatar, a avaliacao do sistema operativo nas metricas em causa so foi possıvel en-

tre duas implementacoes: polimorfismo dinamico e template metaprogramming. Isto

porque implementar todo o sistema operativo e respetiva variabilidade em linguagem

C tornava-se uma tarefa inexequıvel para o autor. Neste sentido, propoe-se a imple-

mentacao do sistema operativo (e de todas as funcionalidades) em linguagem C, e

consequente estudo comparativo das metricas de desempenho, footprint de memoria

e gestao do codigo. Desta forma, sera possıvel sustentar fidedignamente os resultados

aqui apresentados.

A quinta e ultima sugestao propoe o porting do sistema operativo para outras

plataformas. Basicamente, consiste na reimplementacao do codigo dependente do

processador para arquiteturas como a AVR ou ARM. Desta forma, reestruturando

o IDE seria possıvel gerar o sistema operativo orientado a objetos customizado para

diferentes arquiteturas alvo. Tudo de forma facil e simplificada.

141

Page 160: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 161: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Apendices

Page 162: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 163: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Apendice A

Placa Circuito Impresso: spi2c

Para validar o codigo dos drivers SPI e I2C, o autor decidiu projetar e implemen-

tar um add-on para a plataforma de desenvolvimento de testes (8051DKUSB). Isto

porque por si so, essa plataforma nao dispoe de hardware capaz de comunicar com

as interfaces desses protocolos do microcontrolador.

O add-on designado spi2c foi concebido de forma a ser acoplado ao conector de

expansao da placa 8051DKUSB. Desta forma e possıvel aceder facilmente aos pinos

dedicados a cada um dos protocolos de comunicacao. A nıvel de hardware, a placa

vem equipada essencialmente com dois I/O expanders de 16-bit e dois conversores

analogico-digital (ADC). Dos I/O expanders, ambos da Microchip Technology [79],

o MCP23S17 [80] tem interface SPI, enquanto o MCP23017 [80] tem interface I2C.

Quanto aos ADCs, o ADS7834 [81] tem interface SPI, e o ADS7823 [82] tem interface

I2C. Nos pinos de ambos os I/O expanders sao ligados LEDs, em logica negada, para

visualizar as saıdas, bem como switchs para avaliar as entradas. Nas entradas dos

ADCs sao ligados divisores de tensao com potenciometro, para variar o valor da

tensao lida. A alimentacao do add-on e feita com a alimentacao da plataforma de

desenvolvimento, disponıvel no conector de acoplamento. Sao usadas resistencias de

polarizacao para limitar a corrente nos LEDs, resistencias de pull-up nas linhas I2C,

bem como alguns condensadores de desacoplamento. O esquematico e o layout da

placa spi2c pode ser visto nas figuras A.1 e A.2, respetivamente.

145

Page 164: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Figura A.1: PCB spi2c: esquematico

146

Page 165: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Apendice A. Placa Circuito Impresso: spi2c

Figura A.2: PCB spi2c: layout

147

Page 166: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade
Page 167: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

Bibliografia

[1] D. Tennenhouse, “Proactive computing,” Communications of the ACM, pp. 43–

45, May 2000.

[2] A. McHoes and I. M. Flynn, Understanding Operating Systems, 6th ed. Course

Technology, 2010.

[3] AUTOSAR, “Requirements on operating system,” Automotive Open System

Architecture GbR, Tech. Rep., June 2006.

[4] P. J. Plauger, “Embedded c++: An overview,” Embedded Systems Programming,

1997.

[5] D. Herity, “C++ in embedded systems: Myth and reality,” EE Times India,

1998.

[6] K. Czarnecki, “Generative programming: Principles and techniques of software

engineering based on automated configuration and fragment-based component

models,” Ph.D. dissertation, University of Ilmenau, 1998.

[7] K. Czarnecki and U. Eisenecker, Generative Programming: Methods, Tools, and

Applications, 1st ed. Addison-Wesley Professional, 2000.

[8] N. Cardoso, P. Rodrigues, O. Ribeiro, J. Cabral, J. Monteiro, J. Mendes, and

A. Tavares, “An agile software product line model-driven design environment for

video surveillance systems,” September 2012.

[9] N. Cardoso, J. Vale, O. Ribeiro, J. Cabral, P. Cardoso, J. Mendes, and A. Ta-

vares, “Model-driven template metaprogramming,” September 2012.

149

Page 168: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

[10] N. Cardoso, J. Vale, J. Cabral, J. Mendes, P. Cardoso, A. Tavares, and J. Mon-

teiro, “Use of template metaprogramming to address the heterogeneity of video

surveillance systems,” March 2012.

[11] N. Cardoso, J. Cabral, P. Cardoso, J. Mendes, A. Tavares, and J. Monteiro, “A

novel approach to manage the complexity and heterogeneity of video surveillance

systems,” March 2012.

[12] C. Steup, M. Schulze, and J. Kaiser, “Exploiting template-metaprogramming

for highly adaptable device drivers - a case study on canary an avr can-driver,”

in 12th Brazilian Workshop on Real-Time and Embedded Systems, 2010.

[13] D. Abrahams and A. Gurtovoy, “The boost mpl library.”

[14] B. W. Kernighan and D. M. Ritchie, C Programming Language, 2nd ed. Prentice

Hall, 1988.

[15] D. G. Alcock, Illustrating BASIC (A Simple Programming Language), 1st ed.

Cambridge University Press, 1977.

[16] S. Leestma and L. Nyhoff, Pascal Programming and Problem Solving, 4th ed.

Prentice Hall, 1993.

[17] M. A. Covington, D. Nute, and A. Vellino, Prolog Programming in Depth, 1st ed.

Prentice Hall, 1996.

[18] G. Hutton, Programming in Haskell, 1st ed. Cambridge University Press, 2007.

[19] P. Winston and B. Horn, Lisp, 3rd ed. Addison-Wesley, 1989.

[20] B. Stroustrup, C++ Programming Language, 3rd ed. Addison-Wesley Profes-

sional, 1997.

[21] J. Smiley, Learn to Program with Java, 1st ed. Osborne/McGraw-Hill, 2002.

[22] G. G. Abraham Silberschatz, Peter Galvin, Operating System Concepts, 8th ed.

Wiley, 2008.

[23] GNU Operating System. [Online]. Available: http://www.gnu.org/

150

Page 169: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

[24] QNX: Operating systems, development tools, and professional services for

connected embedded systems. [Online]. Available: http://www.qnx.com/

[25] D. Lewis, Fundamentals of Embedded Software: Where C and Assembly Meet,

1st ed. Prentice Hall, 2001.

[26] LynxOS RTOS: The real-time operating system for complex embedded systems.

[Online]. Available: http://www.lynuxworks.com/rtos/

[27] Using the FreeRTOS Real Time Kernel. [Online]. Available: http:

//www.freertos.org/

[28] V. F. Russo, “An object-oriented operating system,” Ph.D. dissertation, Univer-

sity of Illinois at Urbain-Champaign, 1990.

[29] Choices. [Online]. Available: http://choices.cs.uiuc.edu/

[30] Trion Development Object Oriented Operating System. [Online]. Available:

http://trion.sourceforge.net/index.php

[31] F. Afonso, C. Silva, S. Montenegro, and A. Tavares, “Middleware fault tolerance

support for the boss embedded operating system,” in Aspects, Components, and

Patterns for Infrastructure Software, International Workshop on, 2007.

[32] ——, “Applying aspects to a real-time embedded operating system,” in Intelli-

gent Solutions in Embedded Systems (WISES), International Workshop on, 2006.

[33] S. Montenegro and F. Zolzky, “Boss/evercontrol os/middleware target ultra high

dependability,” in Data Systems on Aerospace (DASIA), 2005.

[34] CERG. Embedded System Research Group . [Online]. Available: http:

//esrg.dei.uminho.pt/

[35] M. Barr, Programming Embedded Systems in C and C ++, 1st ed. O’Reilly

Media, 1999.

[36] Y. Hu, E. Merlo, M. Dagenais, and B. Lague, “C/c++ conditional compilation

analysis using symbolic execution,” 2000.

[37] G. team. GCC, the GNU Compiler Collection. [Online]. Available: http:

//gcc.gnu.org/

151

Page 170: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

[38] H. Spencer and G. Collyer, “]ifdef considered harmful, or portability experience

with c news,” in USENIX ’92, June 1992.

[39] D. Lohmann, F. Scheler, R. Tartler, O. Spinczyk, and W. Schroder-Preikschat,

“A quantitative analysis of aspects in the ecos kernel,” in EuroSys ’06, April

2006.

[40] M. Franz, P. Frohlich, and T. Kistler, “Towards language support for component-

oriented real-time programming (position paper).”

[41] C. Prehofer, “Feature oriented programming: A fresh look at objects,” 1997.

[42] D. Batory, “A tutorial on feature oriented programming and product-lines,” in

25th International Conference on Software Engineering (ICSE’03), 2003.

[43] G. Kiczales, J. Lamping, A. Mendhekar, C. Maeda, C. V. Lopes, J.-M. Loing-

tier, and J. Irwin, “Aspect-oriented programming,” in European Conference on

Object-Oriented Programming (ECOOP), 1997.

[44] O. Spinczyk, A. Gal, and W. Schroder-Preikschat, “Aspectc++: An aspect-

oriented extension to the c++ programming language,” in 40th Internacional

Conference on Technology of Object-Oriented Languages and Systems, 2002.

[45] D. Abrahams and A. Gurtovoy, C++ Template Metaprogramming: Concepts,

Tools, and Techniques from Boost and Beyond, 1st ed. Addison-Wesley Profes-

sional, 2004.

[46] D. D. Gennaro, Advanced C++ Metaprogramming, 1st ed. CreateSpace Inde-

pendent Publishing Platform, 2011.

[47] Intel. [Online]. Available: http://www.intel.com

[48] M. A. Mazidi, J. G. Mazidi, and R. D. McKinlay, The 8051 Microcontroller and

Embedded Systems, 2nd ed. Prentice Hall, 2005.

[49] Texas Instruments. [Online]. Available: http://www.ti.com/

[50] CC1111/CC2511 USB HW User’s Guide. [Online]. Available: http://www.ti.

com/lit/ug/swru082b/swru082b.pdf

152

Page 171: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

[51] A True System-on-Chip Solution for 2.4-GHz IEEE 802.15.4 and ZigBee Appli-

cations. [Online]. Available: http://www.ti.com/lit/ds/swrs081b/swrs081b.pdf

[52] A. Tavares, C. Lima, C. Silva, J. Cabral, and P. Cardoso, Programacao de Mi-

crocontroladores, 1st ed. Netmove Comunicacao Global, Lda. Editora, 2009.

[53] ATMEL - 8051 Microcontroller Instruction Set. [Online]. Available: http:

//www.atmel.com/Images/doc0509.pdf

[54] Intel - 80186/80188 HIGH-INTEGRATION 16-BIT MICROPROCESSORS.

[Online]. Available: http://www.ieeta.pt/∼jaf/apoio ip/praticas/data sheets/

ds80188red.pdf

[55] N. Cardoso, J. Vale, O. Ribeiro, J. Cabral, P. Cardoso, J. Mendes, and A. Ta-

vares, “Model-driven template metaprogramming,” 2012.

[56] Atmel - FLIP. [Online]. Available: http://www.atmel.com/tools/FLIP.aspx

[57] K. C. Louden, Compiler Construction: Principles and Practice, 1st ed. Course

Technology, 1997.

[58] Ceibo Offers 8051 C++ Compiler. [Online]. Available: http://www.keil.com/

pr/article/1032.htm

[59] IAR Embedded Workbench for 8051. [Online]. Available: http://www.iar.com/

en/Products/IAR-Embedded-Workbench/8051/

[60] SILICON LABS - C8051F120/1/2/3/4/5/6/7 C8051F130/1/2/3. [Online].

Available: http://www.silabs.com/Support%20Documents/TechnicalDocs/

C8051F12x-13x.pdf

[61] A True System-on-Chip Solution for 2.4-GHz IEEE 802.15.4/ZigBee. [Online].

Available: http://www.ti.com/lit/ds/symlink/cc2430.pdf

[62] DS80C390 Dual CAN High-Speed Microprocessor. [Online]. Available:

http://datasheets.maximintegrated.com/en/ds/DS80C390.pdf

[63] DS80C400 Network Microcontroller. [Online]. Available: http://datasheets.

maximintegrated.com/en/ds/DS80C400.pdf

153

Page 172: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

[64] 8051 IAR C/C++ Compiler - Reference Guide, 4th ed., IAR Systems, February

2008.

[65] Tabela de Instrucoes do 8086. [Online]. Available: http://dcc.ufrj.br/∼renancg/

hs/cp/uteis/INSTRUCOES 8086.pdf

[66] J. Corbet, A. Rubini, and G. Kroah-Hartman, Linux Device Drivers, 3rd ed.

O’Reilly Media, 2005.

[67] MAX232, MAX232I - DUAL EIA-232 DRIVERS/RECEIVERS. [Online].

Available: http://www.ti.com/lit/ds/symlink/max232.pdf

[68] I2C Bus - Technical Overview. [Online]. Available: http://www.mcc-us.com/

I2CBusTechnicalOverview.pdf

[69] AT89C51ID2 - Datasheet. [Online]. Available: http://www.atmel.com/Images/

doc4289.pdf

[70] SPI three slaves. [Online]. Available: http://upload.wikimedia.org/wikipedia/

commons/f/fc/SPI three slaves.svg

[71] SPI timing diagram. [Online]. Available: http://upload.wikimedia.org/

wikipedia/commons/6/6b/SPI timing diagram2.svg

[72] B. Mochocki, X. S. Hu, and G. Quan, “A realistic variable voltage scheduling

model for real-time applications,” 2002.

[73] H. Aydin, R. Melhem, D. Mosse, and P. Mejıa-Alvarez, “Dynamic and aggressive

scheduling techniques for power-aware real-time systems,” 2001.

[74] Y. Shin and K. Choi, “Power conscious fixed priority scheduling for hard real-

time systems,” 1999.

[75] P. Pillai and K. G. Shin, “Real-time dynamic voltage scaling for low-power

embedded operating systems,” 2001.

[76] Y. SHIN, K. CHOI, and T. SAKURAI, “Power-conscious scheduling for real-time

embedded systems design,” 2001.

154

Page 173: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade

[77] K. C. Kang, S. G. Cohen, J. A. Hess, W. E. Novak, and A. S. Peterson, “Feature-

oriented domain analysis (foda) feasibility study,” Carnegie-Mellon University

Software Engineering Institute, Tech. Rep., 1990.

[78] S. Toolworks. Understand - Source Code Analysis & Metrics. [Online].

Available: http://www.scitools.com/

[79] M. Technology. Microchip. [Online]. Available: http://www.microchip.com/

[80] ——. MCP23017/MCP23S17 Datasheet: 16-Bit I/O Expander with Se-

rial Interface. [Online]. Available: http://ww1.microchip.com/downloads/en/

devicedoc/21952b.pdf

[81] T. Instruments. ADS7834 Datasheet: 12-Bit High-Speed, Low-Power

Sampling ANALOG-TO-DIGITAL CONVERTER. [Online]. Available: http:

//www.ti.com/lit/ds/sbas098a/sbas098a.pdf

[82] ——. ADS7823 Datasheet: 12-Bit, Sampling A/D Converter with I2C

INTERFACE. [Online]. Available: http://www.ti.com/lit/ds/symlink/ads7823.

pdf

[83] Trion Design Proposition. [Online]. Available: http://sourceforge.net/cvs/

?group id=90198

[84] E. Gamma, R. Helm, R. Johnson, and J. Vlissides, Design Patterns: Elements of

Reusable Object-Oriented Software, 1st ed. Addison-Wesley Professional, 1994.

155

Page 174: Sandro Emanuel Salgado Pintointranet.dei.uminho.pt/gdmi/galeria/temas/pdf/52725.pdfResumo Nos ultimos anos, cerca de 98% da produ˘c~ao anual de microprocessadores teve como nalidade