AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78995814
Accepted
Richard Klosinski
Richard Klosinski
Asked: 2024-09-18 05:05:19 +0800 CST2024-09-18 05:05:19 +0800 CST 2024-09-18 05:05:19 +0800 CST

Usando WDT para detectar código travado em sistema embarcado, especificamente STM32

  • 772

Estou projetando um firmware STM32 bare-metal que deve detectar código travado/perdido e reinicializar. Minha abordagem é fazer com que cada um dos processos de base de interrupção (basicamente código orientado a interrupção) incremente sua própria variável global conforme é executado, então em uma tarefa de 'supervisor' de prioridade mais alta, verifique para garantir que cada variável global esteja mudando. Se alguma parou de mudar, então permita que o WDT reinicie a placa.

Isso parece uma abordagem sólida? Alguma ideia melhor?

embedded
  • 2 2 respostas
  • 36 Views

2 respostas

  • Voted
  1. Best Answer
    Clifford
    2024-09-18T06:36:50+08:002024-09-18T06:36:50+08:00

    Assumindo uma arquitetura de "super-loop" de primeiro/segundo plano, com manipuladores de interrupção e um único thread principal, então eu sugeriria que um método melhor seria implementar tempos limite para cada interrupção.

    Por exemplo, supondo que você implementou uma interface básica de tick do sistema (usando SYSTICK no Cortex-M), com uma função tickms()retornando o tempo decorrido em milissegundos. Então, para cada interrupção sendo watch-dogged, você pode ter uma enumeração como:

    typedef enum
    {
        WDG_UART1,
        WDG_UART2,
        WDG_TIMER1,
        ...
        NUMBER_OF_WDG
    } eWdg ;
    

    Então uma matriz como:

    volatile struct
    {
        unsigned period ;
        unsigned timestamp ;
    } wdg[NUMBER_OF_WDG] =
    {
        {1000, 0}, // WDG_UART1
        {1000, 0,  // WDG_UART2
        {100,  0}  // WDG_TIMER1
        ...
    }
    

    e uma API:

    void wdgReset( eWdg wdg_id )
    {
        wdg[wdg_id].timestamp = tickms() ;
    }
    
    void wdgCheck()
    {
        for( int i = 0; i < NUMBER_OF_WDG; i++ )
        {
            while( tickms() - wdg[i].timestamp > wdg[i].period )
            {
                // spin while timeout expired until 
                // interrupt recovers or hardware watchdog
                // fires
            }
           
            resetHwWatchdog() ;
        }
    }
    

    Então, cada interrupção redefine seu tempo limite via wdgReset(), e o loop principal verifica continuamente os watchdogs de software, assim:

    int main()
    {
        for(;;)
        {
            // do any background processing here
            backgroundTasks() ;
    
            // Check interrupts
            wdgCheck()
        }
    }
    

    Então:

    • se o thread principal parar, o watchdog de hardware será acionado,
    • se alguma interrupção parar, o watchdog de hardware será acionado,
    • se uma interrupção parar de disparar, o wdgCheck()irá girar e o watchdog de hardware irá disparar,
    • se tudo estiver funcionando normalmente, os watchdogs de software serão redefinidos e o watchdog de hardware será atendido por wdgCheck(),
    • cada tarefa ou interrupção tem seu próprio período específico adequado à sua taxa esperada na aplicação.

    Observação: no Cortex-M, você pode emitir uma redefinição de software por meio do NVIC, portanto, você pode, opcionalmente, redefinir imediatamente quando o watchdog de software expirar, em vez de esperar pelo watchdog de hardware.

    Claramente, este é apenas um esboço de pseudocódigo e puramente ilustrativo - ele poderia ser refinado e estendido de várias maneiras. Se você fosse usar um RTOS, você poderia proteger tarefas de forma semelhante, com o supervisor no loop ocioso ou em uma tarefa com prioridade menor do que qualquer outra.

    Um refinamento que eu sugeriria seria ter um registro dinâmico de watchdogs de software em vez de uma matriz estática e ter uma API:

    tWdgHandle wdgCreate( unsigned period ) ;
    

    por exemplo, para que tarefas e drivers de dispositivo possam adicionar seus próprios watchdogs de forma independente, e wdgCheck()iterariam todos os manipuladores registrados. Uma tarefa poderia até mesmo modificar o período dinamicamente conforme necessário (se fosse temporariamente desabilitada, por exemplo):

    void wdgSetPeriod( tWdgHandle wdg, unsigned period ) ;
    
    • 4
  2. Lundin
    2024-09-18T20:01:51+08:002024-09-18T20:01:51+08:00

    Primeiramente, observe que se nenhuma tarefa puder ser travada, o método mais simples é simplesmente configurar o watchdog timer de hardware adequadamente, já que uma reinicialização brusca do MCU é uma maneira aceitável de lidar com erros.

    Você só precisa de supervisão de software nos seguintes casos:

    • Em caso de erro, você deseja parar e encerrar o programa graciosamente, relatando erros etc. antes de fazer uma reinicialização do MCU, ou
    • Certas tarefas são consideradas menos críticas, mesmo quando estão suspensas, ou
    • Você está implementando algum tipo de "limp home", ou seja, relatar erros, mas tenta executar o programa da melhor forma possível, mesmo em caso de erros (ou seja, algum tipo de produto de missão crítica).

    Para simplificar, vamos supor que cada tarefa tenha permissão para consumir no máximo x ms, sem timeouts individuais. O pseudocódigo pode se parecer com isto:

    typedef err_t task_t (void);  // function template for tasks
    
    
    void main (void)
    {
      /* init everything here */
    
    
      static task_t* const task[] = 
      {
        /* misc tasks in turn calling the drivers */
        uart_task,
        lcd_task,
        buttons_task,
      };
    
      state_t state = UART_STATE; // in case the list of tasks is also some manner of state machine
    
      for(;;)
      {
        kick_dog(); // refresh the hardware WDG here, and only here
    
        err_t result = OK;
        timer_start(n_milliseconds); // some fixed timeout shorter than hw WDG timeout
          do // busy-wait polling
          {
            result = task[state](); // non-blocking call polling something in turn
          } while(!timer_timeout() && result==ERR_BUSY);
        timer_stop();
    
        // here result is either OK, ERR_BUSY meaning timeout, or some other error code
    
        state = error_handler(result); // all error handling and state changes in the program here
      }
    }
    

    Em alguns sistemas, você também poderá alternar entre os modos seguro e operacional e talvez reverter para o modo seguro em caso de erros.

    • 0

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve