collapse

* Posts Recentes

Emulador NES em ESP32 por dropes
[Hoje às 15:31]


Arame de Estendal por almamater
[Ontem às 16:16]


O que é isto ? por SerraCabo
[12 de Abril de 2024, 14:20]


Amplificador - Rockboard HA 1 In-Ear por almamater
[11 de Abril de 2024, 20:46]


Meu novo robô por josecarlos
[29 de Março de 2024, 18:30]


Bateria - Portátil por almamater
[25 de Março de 2024, 22:14]


Escolher Osciloscópio por jm_araujo
[06 de Fevereiro de 2024, 23:07]


TP4056 - Dúvida por dropes
[31 de Janeiro de 2024, 14:13]


Leitura de dados por Porta Serie por jm_araujo
[22 de Janeiro de 2024, 14:00]


Distancia Cabo por jm_araujo
[08 de Janeiro de 2024, 16:30]

Autor Tópico: como ter um delay ou millis sem este interferir com o loop.  (Lida 8026 vezes)

0 Membros e 1 Visitante estão a ver este tópico.

StarRider

  • Visitante
Re: como ter um delay ou millis sem este interferir com o loop.
« Responder #15 em: 28 de Dezembro de 2014, 17:56 »
vou só aproveitar um pouco para perguntar uma cena.

Njay tive uma idea e gostava da tua opinião.
Para fazer tipo 2-3 programas a correr em paralelo poderia fazer isto?

Criar um interrupt periódico com um timer de 1 em 1 ms.
Programa1 começa.
Interrupt é chamado - salta para Programa2.
Interrupt é chamado - salta para Programa3.
Interrupt é chamado - salta para Programa1.
Por ai a fora.

A ideia é ter um interrupt handler que tem tipo um variavel que vai de 0-2, ou seja o numero do programa a correr (usando um if), e chama essa função.
O meu problema é que isto teria de ser de forma a que o interrupt chama-se a função mas era mesmo um Jump, não um jump and link para voltar. Não é?
Claro que teria de ter cuidados para os programas não se atropelarem mas isso é trabalho que teria de ser feito e cuidados a ter. Tambem algumas funções criticas podiam desativar o interrupt por momentos.
Isto seria para um ARM-M0 de 48Mhz ou um MCU mais rápido.
Se disser alguma asneira calem-me :p

Boas,

A primeira questão que deves  colocar é se realmente necessitas de um verdadeiro multitasking ou
se uma simples state machine pode servir. Em termos de desempenho uma state machine tem
vantagens, um sistema verdadeiramente multitasking é muito mais versátil.

Nos cores ARM uso o Systick (e respectiva interrupção) para implementar um round-robin com uma
fracção de 5us por tarefa. Cada tarefa deve ter uma estrutura associada onde vais guardar o
estado da mesma, e podes até implementar um sistema de prioridades, e cada estrutura deve ter
uma área que sirva de stack. O switching de tarefas é relativamente simples, guardar o code pointer, stack pointer, interrups state, etc, e activar o novo code pointer, stack pointer, etc. Deves também
manter e actualizar (na dita INTR) uma variável com o tickcount que é muito útil para implementar
delays, sendo que para isso deves ter uma função de delay global que seja transversal a todas as
tarefas de forma a que os timings sejam assegurados.

É claro que numa verdadeira multi-tarefa é depois necessário controlar o acesso aos periféricos, e
uma vez que podes aceder aos mesmos dentro de diversas tarefas concorrentes, deves implementar
um sistema de semáforos para evitar que duas tarefas possam aceder por exemplo à UART1 ou usar
a mesma buffer da mesma enquanto a anterior não libertar este periférico. E isto é aplicável a todos
os periféricos, memória partilhada, canais DMA, etc.

Deves ponderar muito bem se necessitas mesmo de multi-tarefa, uma state-machine mesmo que
seja muito rude pode resolver a questão sem estes problemas.

Se realmente pretendes multi-tarefa tens toda a vantagem em recorrer a um RTOS que já tenha
dado provas, não vale a pena queimar neurónios e correr riscos a reinventar a roda,  a não ser que
seja por um desafio pessoal.

Geralmente só uso o RTEMS nos cores SPARC (MCUs LEON)  e o RTX da ARM/Keil nos cores ARM
mas existem por ai muitos RTOS com licença FOSS que podes usar sem problemas.

Abraços,
PA
« Última modificação: 28 de Dezembro de 2014, 18:03 por StarRider »

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: como ter um delay ou millis sem este interferir com o loop.
« Responder #16 em: 28 de Dezembro de 2014, 18:31 »
O já aqui foi dito, sendo que saliento a pergunta: qual é a aplicação?

Se é para pura recreação tua, aprender e tal, fiquei um pouco na dúvida se os teus 3 programas são interrompidos "sem saberem", mas vamos assumir que sim. Em C há um par de funções que pode ajudar a fazer esse tipo de coisa, setjmp e longjmp (http://en.wikipedia.org/wiki/Setjmp.h) . Precisas de ver a documentação do compilador que estiveres a usar para ficares a par de todos os detalhes. Já usei isto por exemplo para "simular" excepções, em que podes estar algures dentro duma função que chamou outra que chamou outra que chamou outra que ... e voltar "instantaneamente" para a função "de topo". Lembro-me de ter usado na implementação dum parser preditivo.

A decisão que vais tomar na interrupção sobre qual o próximo "programa" a executar é o trabalho do "scheduler", e podes implementar N politicas de atribuição do CPU.

vou só aproveitar um pouco para perguntar uma cena.

Njay tive uma idea e gostava da tua opinião.
Para fazer tipo 2-3 programas a correr em paralelo poderia fazer isto?

Criar um interrupt periódico com um timer de 1 em 1 ms.
(...)
« Última modificação: 28 de Dezembro de 2014, 18:32 por Njay »

StarRider

  • Visitante
Re: como ter um delay ou millis sem este interferir com o loop.
« Responder #17 em: 28 de Dezembro de 2014, 19:36 »

A ideia é ter um interrupt handler que tem tipo um variável que vai de 0-2, ou seja o numero do programa a correr (usando um if), e chama essa função.

Boas novamente,

Todo o código que é executado dentro de uma INTR deve ser o mais conciso possível, chamar funções que
tenham loops ou bastante processamento de dentro de uma ISR alem de ser má pratica vai possivelmente
causar stack overflow mesmo em ISR que não sejam reentrantes.

Vais chamar a "função" dentro da ISR e esperar que esta retorne ? Mesmo sendo uma função não blocking
vais ter que dentro dessa mesma função ter um state machine se pretendes executar código mais complexo,
e nunca vais poder ter ciclos infinitos.

Abraços,
PA

Offline LuísR.A.

  • Mini Robot
  • *
  • Mensagens: 1.224
    • Clube de Robotica
Re: como ter um delay ou millis sem este interferir com o loop.
« Responder #18 em: 28 de Dezembro de 2014, 19:38 »
Obrigado pelo info. Não sabia sobre o setjmp e longjmp.

Para multitasking a sério usaria um RTOS de certeza, isso dá demasiado trabalho.

Eu em todos os programas tenho sempre o SysTick de 1ms em 1ms e uma função delay parecida ao do arduino. Isto para poder contar tempo.

A idea por agora é mesmo por recreação. Isto porque andei a mexer nos legos com programação de blocos - dá para ter 3 linhas de código e fiquei curioso
A ideia é começar a aprender mais sobre como controlar vários actuadores que dependem de varios sensores.
Neste caso é mais uma curiosidade, os programas não precisam de saber se foram interrompidos.

Vou ter de ver mais sobre isto depois :p



Tiva MCU é que é.

Tutoriais Tiva+codigos exemplo:
https://sites.google.com/site/luiselectronicprojects/

Offline LuísR.A.

  • Mini Robot
  • *
  • Mensagens: 1.224
    • Clube de Robotica
Re: como ter um delay ou millis sem este interferir com o loop.
« Responder #19 em: 28 de Dezembro de 2014, 19:41 »

Boas novamente,

Todo o código que é executado dentro de uma INTR deve ser o mais conciso possível, chamar funções que
tenham loops ou bastante processamento de dentro de uma ISR alem de ser má pratica vai possivelmente
causar stack overflow mesmo em ISR que não sejam reentrantes.


Era isso uma das duvidas que tinha, obrigado!

Então é melhor ir para os RTOS se precisar de tal coisa.

Por agora vou ver melhores praticas simples. Tenho de começar a para de usar delays :p
Tiva MCU é que é.

Tutoriais Tiva+codigos exemplo:
https://sites.google.com/site/luiselectronicprojects/