Table of Contents
- 1. - Sequencia de aulas.
- 1.1. E1. acertar projetos
- 1.2. E2. chaveando processos - diversos processos em modo usuario.
- 1.3. E3. livro Wang - device drivers
- 1.4. E4. Cada processo controlando um pouco do video.
- 1.5. E5. uart com interrupcao e controle do video.
- 1.6. E6. criando uma system call para receber caracteres da uart.
- 1.7. P1 - relatorio e apresentacao geral para classe.
- 1.8. E7. primeira system call
- 1.9. E8. Usando a primeira system call para pintar os quadrados.
- 1.10. E9. system call putline
- 1.11. E10. sleep e wakeup e projeto semafaro - 1
- 1.12. E11. projeto semafaro - 2
- 1.13. E12. projeto semafaro - 3 - testes.
- 1.14. P2 - relatorio e apresentacao geral para classe.
- 2. referencia
- 3. referencia
- 4. avaliacao
PCS3558 - Sistemas Embarcados
prof. Jorge Kinoshita quinta 14:00H - 17:40H
1 - Sequencia de aulas.
1.1 E1. acertar projetos
- apresentacao do curso.
- verificar como estao os trabalhos desenvolvidos na disciplina anterior (teoria).
- dividir em equipes que terao que tomar uma escolha sobre a plataforma a usar: nodeMCU, raspberry, arduino, placa emulada versatilepb.
- apresentar possiveis projetos com nodeMCU, raspberry (falar do livro), arduino para discussao na equipe.
– nodeMCU https://www.youtube.com/watch?v=4-YbLiUpEfI 5':46
– raspberry https://www.youtube.com/watch?v=ZDfhcA0SCiM 11':56
- video sobre projetos (smartphones) que falharam.
https://www.youtube.com/watch?v=fMz0KO_9oeg 14':49
- projetos, sequencia de aulas.
1.1.1 Relatorio 1.
Embora o relatorio seja feito em grupo, eh necessario retornah-lo individualmente no google classroom. O relatorio tambem serve de comprovacao de presenca na aula; portanto entreguem-no.
- - para as equipes verstatilepb:
– localizem o codigo do nano kernel que chaveia processos. – rode o codigo e tire printscreens dos processos sendo chaveados. – retorne o codigo fonte + script que gera o codigo final + relatorio com printscreens.
- - para as outras equipes:
– descreva no relatorio como serah o projeto, como serah desenvolvido. Especifiquem o hardware ou software (bibliotecas, sistema operacional, etc.) a ser usado. Criem um cronograma para os seguintes dias:
- Setembro: 10, 17, 24
- Outubro: 1, 8, 15 (P1: relatorio e apresentacao sobre o andamento dos trabalhos), 22, 29
- Novembro: 5, 12, 19, 26
Obs: Dezembro: 3 - P2: apresentacao dos trabalhos
Entreguem um relatorio para cada participante da equipe
1.2 E2. chaveando processos - diversos processos em modo usuario.
- proposta para a criacao de sistema operacional para a placa emulada versatilepb.
–> retomar o trabalho do curso de labmicro; – confira o retorno da interrupcao. –> colocar outros processos para funcionarem. –> expandir a tabela de processos;
1.3 E3. livro Wang - device drivers
- estudar codigo C2.5 em [1] , [4]; UART sem interrupcao com entrada e saida de dados.
- rode fora do Docker do shibata, ou seja, instale o ambiente necessario (arm-none-eabi…) para rodar.
- Para debugar compile com -g e use gdb-multiarch no ubuntu 18.4. Dicas para debugar C2.5 rodando passo a passo:
jk@jk-G7-7588:~/casa/meuscursos/embed/wang/EmbeddedAndRTOSSamples-master/C2.5$ qemu-system-arm -M versatilepb -cpu arm926 -kernel build/t.bin -nographic -serial telnet:localhost:1111,server QEMU 2.11.1 monitor - type 'help' for more information (qemu) qemu-system-arm: -serial telnet:localhost:1111,server: info: QEMU waiting for connection on: disconnected:telnet:127.0.0.1:1111,server pulseaudio: set_sink_input_volume() failed pulseaudio: Reason: Invalid argument pulseaudio: set_sink_input_mute() failed pulseaudio: Reason: Invalid argument Depois: @jk-G7-7588:~$ telnet localhost 1111 xhost: bad hostname "vl" Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Enter lines from serial terminal 0 [You have input:] asf [You have input:] asf a [You have input:] a b [You have input:] b jk@jk-G7-7588:~/casa/meuscursos/embed/wang/EmbeddedAndRTOSSamples-master/C2.5$ qemu-system-arm -M versatilepb -cpu arm926 -kernel build/t.bin -nographic -serial telnet:localhost:1111,server -- debug qemu-system-arm -s -M versatilepb -cpu arm926 -kernel build/t.bin -nographic -serial telnet:localhost:1122,server -S Outra tela para debugar tenho que: 1. conectar na porta 1122 telnet localhost 1122 2. jk@jk-G7-7588:~/casa/meuscursos/embed/wang/EmbeddedAndRTOSSamples-master/C2.5$ gdb-multiarch GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word". (gdb) target remote :1234 Remote debugging using :1234 warning: No executable has been specified and target does not support determining executable automatically. Try using the "file" command. 0x00000000 in ?? () (gdb) file build/ dummy.txt t.bin t.elf t.o t_thumb.o ts.o (gdb) file build/t.elf A program is being debugged already. Are you sure you want to change the file? (y or n) y Reading symbols from build/t.elf...done. (gdb) load Loading section .text, size 0x45c lma 0x10000 Loading section .rodata, size 0x77 lma 0x1045c Loading section .data, size 0x28 lma 0x104d4 Start address 0x10000, load size 1275 Transfer rate: 1245 KB/sec, 425 bytes/write. (gdb) b main Breakpoint 1 at 0x102bc: file t.c, line 12. (gdb) c Continuing.
- codigo C2.6; LCD driver;
- Havia um erro em C2.6, t.c - grupo do Pedro Nunes corrigiu.
- libgcc.a em MySO/libs
- Colocar o C2.6 para rodar pelo debug.
1.4 E4. Cada processo controlando um pouco do video.
file:///home/jk/casa/meuscursos/embed/wang/EmbeddedAndRTOSSamples-master/C2.6/ file:///home/jk/casa/meuscursos/embed/wang/EmbeddedAndRTOSSamples-master/C2.6/t.c
- Observar como rodar e debugar o codigo C2.6 - LCD driver (de forma semelhante ao C2.5).
- alterar os processos de forma que cada um controle uma pequena area do video, fazendo-a piscar. Dica: olhe o codigo de kpchar ou showbmp em :
file:///home/jk/casa/meuscursos/embed/wang/EmbeddedAndRTOSSamples-master/C2.6/vid.c Procure observar se nao existe interferencia de um processo em outro ao colocar dados na tela do video. Nao pode acontecer de um processo estar imprimindo algo numa area que nao eh dele?
- faca com que um processo receba dados da serial e imprima o numero que recebeu. Experimente criar uma versao que usa interrupcao baseada no codigo C2.6
1.5 E5. uart com interrupcao e controle do video.
- Experimente fazer com que cada processo pisque um quadradinho no LCD.
- Receber caracteres pela uart
O codigo em C2.6 usa a interrupcao ao enviar e receber caracteres pela uart (simulado via telnet). Para observar como funciona o C2.6 com o debug, compile o C2.6 inserindo a opcao -g no compilador e assembler e responda:
- Por que a interrupcao eh usada na transmissao de caracteres?
- em que arquivo estah declarado o vetor de interrupcao?
- qual a funcao chamada quando ocorre uma interrupcao de hardware?
- Coloque um breakpoint nessa interrupcao e tire um printscreen quando cai lah (observe que voce tem que teclar algo no telnet, tanto no envio quanto no recebimento de caracteres; tenha paciencia porque no comeco gera muitas interrupcoes imprimindo um texto).
- O que eh o VIC (controlador da interrupcao) e para que serve? Dica em: https://github.com/smwikipedia/EmbeddedAndRTOSSamples veja o datasheet do VIC em EmbeddedAndRTOSSamples-master/HardwareSpec/VIC'PL190 VIC.pdf'
- O que faz o codigo abaixo em t.c:
VIC_INTENABLE |= UART0_IRQ_VIC_BIT; VIC_INTENABLE |= UART1_IRQ_VIC_BIT; u32 vicstatus = VIC_STATUS; //UART 0 if(vicstatus & UART0_IRQ_VIC_BIT)
fazer com que apenas um processo receba dados da UART receba dados da UART e imprima o que recebeu.
1.6 E6. criando uma system call para receber caracteres da uart.
- aviso sobre a P1
- criar uma system call que recebe uma linha, uma sequencia de caracteres ateh a vinda do ENTER. Testar com dois ou mais processos recebendo linhas de caracteres. O processo pode ecoar a linha, colocar um espaco entre cada caracter, colocar todos os caracteres em maiusuclo, etc. Cada processo deve fazer um processamento diferente na string recebida para ficar notorio qual processo eh quem processou a string. Muito provavelmente serah preciso fazer tambem uma system call que imprime os caracteres. Projetem a system call antes de implementarem.
1.7 P1 - relatorio e apresentacao geral para classe.
1.8 E7. primeira system call
Pessoal, na aula de hoje vamos parar um pouco com o atendimento da uart a fim de revisar e melhor o codigo que fizemos ateh agora. Para isso vamos retornar para a versao anterior ao tratamento da uart.
1.8.1 colocar os processos para rodarem em modo usuario.
Ateh agora temos lidado com os processos em modo supervisor. Vamos colocar os processos para rodarem em modo usuario. A fim de trocar o LR e SP do processo em modo usuario na interrupcao de relogio, voces terao que chavear do modo interrupt para o modo system pois o modo system compartilha todos os registrados do usuario e roda com os poderes de kernel (qualquer duvida veja a apostila [3] usada em labmicro, cap 1.
Vamos supor que tivessesmos processos rodando tanto em modo kernel (ex: um processo que estivesse atendendo uma interrupcao de software) e processos rodando em modo usuario. Nesse caso, como deveriamos salvar e recuperar os registradores? Nesse caso, dentro do tratamento da interrupcao de hardware precismos ver o spsr que contem o modo do processador. Antes de salvar os registradores SP e LR do processo rodando temos que ir ao modo correto (dado pelo spsr), para depois acessa-los. Da mesma forma, a firm de recuperar os registradores SP e LR para o proximo processo, temos que ir ao modo correto (dado cspsr do processo salvo), para depois recuperah-los (acertar o SP e LR no modo correto).
Testem fazer com que um processo rodando em modo usuario tente chavear para o modo supervisor alterando o cpsr em assembly. O que acontece?
1.8.2 criar a system call getpid.
No vetor de interrupcoes, na entrada para software interrupt, crie sua primeira system call: getpid - que retorna o pid do processo. Use esse numero para fazer com que o processo pinte o quadradinho correto. Coloque um printscreen no relatorio.
1.9 E8. Usando a primeira system call para pintar os quadrados.
1.9.1 cada processo chama getpid.
Cada processo chama getpid e com base no retorno, os quadrados sao pintados em suas devidas posicoes.
1.9.2 codigo unico para todos os processos.
Cada funcao em C possui variaveis globais e variaveis locais. As variaveis locais vao na pilha, enquanto que as globais ficam num posicao estatica na memoria. Teoricamente poderiamos fazer com que os processos rodassem o mesmo codigo (acendendo e apagando os quadradinhos, sem ainda mexer com a uart) desde que todo o codigo rodasse com variaveis locais (pois cada processo tem sua pilha separada). Cada processo deveria chamar o getpid e criar o quadradinho na area correta, sendo que todos os processos rodam o mesmo codigo! Experimente fazer isso e coloque o que voce conseguiu no relatorio.
1.9.3 retomar o codigo envolvendo a interrupcao da uart
Agora que vc. conseguiu criar a system call getpid, retome o codigo envolvendo a interrupcao da uart; para prosseguirmos com ele na proxima aula. Teste se chegam as interrupcoes da uart ao teclar qualquer coisa no telnet (que emula a tty). Crie a system call getline(buffer)
Para simplificar nosso problema vamos supor que toda linha tem no maximo 80 caracteres. Assim, o buffer eh declardo como:
char buffer[80];
A system call getline deve ser chamada de forma semelhante a getpid, mas o parametro eh passado no registrador R0 enquanto que o numero da system call eh passado em R7. Podemos ter R7=1 para getpid e R7=2 para getline. Dentro do kernel vamos declarar
char line_buffer[80];
que contem a linha digitada.
No tratamento da system call getline temos:
- existe linha uma linha jah digitada pelo usuario que estah armazenada em linebuffer? Se sim, retorna a linebuffer para o processo sem que ele fique bloqueado. Se nao, bloqueia o processo; ou seja, retire-o do round-robin. Crie a funcao "sleep()" especializada em bloquear o processo.
- O processo bloqueado deve ir para a fila de processos aguardando uma linha de entrada. Se este for o primeiro processo, ele eh bloqueado e vai para a fila aguardando a linha de entrada.
- Quando o usuario digita uma tecla, ela eh recebida pela interrupcao da uart. Cada caracter digitado eh colocado em linebuffer no tratamento da interrupcao da uart. Deve-se verificar na rotina de interrupcao, se recebeu o final de linha (0xa). Se recebeu, o processo deve ser desbloquedo, ou melhor, deve desbloquear o primeiro processo que aguarda a linha. Crie a funcao wakeup(pid) que faz que ele passe a rodar novamente. Copie linebuffer para o buffer do usuario ateh encontrar o final de linha.
1.10 E9. system call putline
De forma semelhante a getline, escreva a system call putline que imprime uma linha na tty emulada por telnet. Queremos bloquear um processo e retornar para onde ele estava. Queremos fazer algo como:
sleep()
que faz o processo dormir e:
wakeup(pid)
que acorda o processo com um certo pid. Quando dois ou mais processos fizerem getline, eles terao obrigatoriamente que chamarem sleep().
Assim, teremos que guardar o estado do processo e teremos que ter uma pilha dentro do kernel independente para cada processo (pois se assim nao for, nao poderemos continuar codigos independentes apos o sleep). ( Ver: https://www.cs.umb.edu/~eoneil/cs444_f06/class10.html#:~:text=Each process has a kernel,is executing in the kernel )
Vamos modificar a tabela de processos para incluir os registradores sp, lr, spsr em modo kernel e alem disso, vamos na inicializacao atribuir uma pilha de kernel independente para cada processo.
Assim, quando um processo fizer getline() , sleep() acaba sendo chamada dentro do kernel. Essa rotina guarda todos os registradores do usuario na tabela de processos alem de sp, lr, spsr do modo supervisor. Quando o "enter" vindo do teclado eh recebido na rotina de interrupcao, um processo eh acordado por wakeup(pid). O wakeup(pid) deve alterar o estado do processo de numero pid para o estado de "pronto", permitindo com que ele participe do round robin.
As rotinas sleep() e wakeup(pid) serao fundamentais para o projeto do semaforo nas proximas aulas.
1.11 E10. sleep e wakeup e projeto semafaro - 1
continuando o sleep e wakeup(); testem com o getline e putline.
1.12 E11. projeto semafaro - 2
continuando o sleep e wakeup(); testem com o getline e putline. Para implementar sleep e wakeup, voce pode se basear em 5.6.1 de [1]. Porém tome cuidado porque a declaracao de sleep e tswitch eh diferente da que foi proposta e alem disso, o tswitch - rotina que faz a troca de processo - tambem estah diferente. Ao inves de ter uma tabela de processos, o tswitch guarda os registradores do processo na pilha do processo. Portanto, talvez o livro nao ajude tanto… Voce pode ter uma ideia de como aplicar a getline e putline inspirando-se em 5.6.2 de [1].
Se sobrar tempo, crie as system calls para lidar com semaforos:
1.12.1 semid = initsem(valorinicial ) :
cria um semaforo inicializando-o com valorinicial e retorna semid : um numero inteiro que identifica o semaforo dentro do kernel.
Veja os videos:
1.12.2 up(semid):
1.12.3 down(semid):
1.13 E12. projeto semafaro - 3 - testes.
Crie os semaforos de acordo com:
1.13.1 semid = initsem(valorinicial ) :
cria um semaforo inicializando-o com valorinicial e retorna semid : um numero inteiro que identifica o semaforo dentro do kernel.
Veja os videos:
1.13.2 up(semid):
1.13.3 down(semid):
Verifique se o semaforo evita condicao de corrida.
Veja os videos:
- V67: https://www.youtube.com/watch?v=aCqYiUkb-U4
- V68: https://www.youtube.com/watch?v=3qel24yJmt4
- V69: https://www.youtube.com/watch?v=Pcna-c4vfR8
Faca com que dois processos incrementem continuamente um certo numero colocando-no no terminal atraves de putline. Mostre como ocorre condicao de corrida com semaforo e sem o uso do semaforo.
1.14 P2 - relatorio e apresentacao geral para classe.
2 referencia
K.C. Wang - Embedded and Real-Time Operating Systems (2017, Springer)]]
Derek Molloy-Exploring Raspberry Pi_ Interfacing to the Real World with Embedded Linux-Wiley (2016)
3 referencia
[1] K.C. Wang - Embedded and Real-Time Operating Systems (2017, Springer)]]
[2] Derek Molloy-Exploring Raspberry Pi_ Interfacing to the Real World with Embedded Linux-Wiley (2016)
[3] ARM Laboratory Exercises - - http://courses.cs.tamu.edu/rabi/cpsc617/resources/ARM Lab Mannual.pdf
[4] https://github.com/smwikipedia/EmbeddedAndRTOSSamples
[5] https://edisciplinas.usp.br/ PCS3558
4 avaliacao
Média =[(P1 + 2*P2)/3]*0,5 + R*0,5 , sendo que R é a média de relatórios
Regras para avaliacao:
- 8.0 bom - relatorio esperado
- duas reunioes com equipes por aula: no comeco da aula e no fim da aula. Se um aluno participar apenas de uma reuniao perderah 5 pontos; se um aluno nao participar de nenhuma reuniao, perderah a nota da experiencia no dia e receberah falta.
- todos os alunos deve responder as perguntas do professor, alunos que nao participarem terao nota descontada.