Todos os microprocessadores e microcontroladores modernos contêm algum tipo de mecanismo de interrupção. Esses mecanismos são necessários para fornecer a capacidade de resposta exigida por muitos aplicativos. Obviamente, responsividade e previsibilidade são o principal objetivo ao usar o RTOS, mas ao mesmo tempo se opõem. O uso de interrupções pode prejudicar a integridade do sistema operacional em tempo real. Esse problema e sua solução foram mencionados em um dos artigos anteriores (nºs 4 e 6). Neste artigo, veremos a estratégia de manipulação de interrupções usada no Nucleus SE. Em todos os casos, as interrupções NÃO são controladas pelo Nucleus SE: são processadas quando ocorrem de acordo com a prioridade e os vetores da maneira usual. Seu tempo de execução é simplesmente "roubado" do tempo disponível no código do aplicativo principal e do planejador. Obviamente, segue-se que todos os manipuladores de interrupção devem ser simples, curtos e rápidos.

Artigos anteriores da série: Interrupções regulares e controladas
O Nucleus SE oferece duas maneiras de lidar com interrupções: "nativo" ou "regular" (Nativo), nas quais as interrupções não são nada de especial e, em certa medida, têm interação limitada com o SO (pelo menos ao usar o agendador prioritário) e " Gerenciado, no qual você pode acessar um número muito maior de chamadas de API do manipulador de interrupções.
Usando as macros de E / S, o manipulador de interrupção Nucleus SE pode ser usado no modo padrão ou gerenciado.
Interrupção do pessoal
As interrupções da equipe do Núcleo SE são o manipulador de interrupção padrão e podem ser consideradas "não gerenciadas". Eles geralmente são usados quando a interrupção pode ocorrer com alta frequência e requer processamento com baixo uso de recursos de computação. Esse manipulador provavelmente é escrito em C, pois muitos compiladores incorporados modernos suportam o desenvolvimento de manipuladores de interrupção usando a palavra-chave interrupt. Somente as informações contextuais que o compilador considera necessárias são armazenadas. Isso leva a limitações significativas sobre o que os manipuladores de interrupção padrão podem fazer, o que veremos em breve.
Para criar um manipulador de interrupção regular no Nucleus SE, basta escrever um manipulador de interrupção regular, incluindo chamar a macro
NUSE_NISR_Enter () no início e chamar
NUSE_NISR_Exit () no final. Essas macros são definidas no arquivo
nuse_types. he defina a variável global
NUSE_Task_State como
NUSE_NISR_CONTEXT .
Interrupções guiadas
Se você precisar de mais flexibilidade para operações do manipulador de interrupções, as interrupções gerenciadas do Nucleus SE podem ser a solução. A principal diferença da interrupção padrão é manter o contexto. Em vez de permitir que o compilador salve vários registros na pilha, uma interrupção controlada salva o contexto inteiro da tarefa (em seu próprio bloco de contexto) na entrada. Em seguida, o contexto da tarefa atual é restaurado do bloco de contexto na saída. Isso fornece a capacidade de alterar a tarefa atual pelo trabalho do código do manipulador de interrupções, o que é possível ao usar o planejador de prioridades. Uma descrição completa da preservação e restauração do contexto no Nucleus SE foi fornecida em um artigo anterior (
# 10 ).
Obviamente, a preservação total do contexto implica um aumento no uso de recursos de computação em comparação com o armazenamento de vários registros na pilha, o que ocorre durante uma interrupção padrão. Esse preço deve ser pago por uma flexibilidade adicional, e é por isso que é fornecida uma opção de abordagem de manipulação de interrupção.
Uma interrupção gerenciada é criada usando a macro
NUSE_MANAGED_ISR () descrita em
nuse_types.h . Essa macro cria uma função que contém as seguintes ações:
- manter o contexto da tarefa;
- Atribuindo NUSE_Task_State a NUSE_MISR_CONTEXT ;
- código de função do manipulador de interrupções fornecido pelo usuário;
- restaurando NUSE_Task_State para seu estado anterior;
- restaurar o contexto da tarefa.
A macro usa dois parâmetros: o nome da interrupção usado como o nome da função para o manipulador gerado e o nome da função que contém a lógica do usuário para o manipulador de interrupções.
Chamadas de API do manipulador de interrupções
O conjunto de funções da API que podem ser chamadas de um manipulador de interrupção padrão ou gerenciado depende de qual planejador é usado. Em termos gerais, o uso do agendador prioritário fornece muitas opções para acessar o agendador por meio de uma chamada de função da API, o que é difícil ao usar o manipulador de interrupção padrão.
Chamadas de API para o manipulador de interrupção padrão ao usar o planejador de prioridadeAo usar o planejador de prioridade, é permitido um número limitado de chamadas de função da API do manipulador de interrupção padrão. Essa limitação é o resultado da flexibilidade da API do Nucleus SE: muitas chamadas podem fazer com que a tarefa fique pronta e o planejador não pode ser chamado pelo manipulador de interrupção padrão (já que o contexto da tarefa não é salvo). Desativar bloqueios de tarefas fornece ainda mais flexibilidade.
As seguintes chamadas de API são sempre permitidas:
NUSE_Task_Current() NUSE_Task_Check_Stack() NUSE_Task_Information() NUSE_Task_Count() NUSE_Partition_Pool_Information() NUSE_Partition_Pool_Count() NUSE_Mailbox_Information() NUSE_Mailbox_Count() NUSE_Queue_Information() NUSE_Queue_Count() NUSE_Pipe_Information() NUSE_Pipe_Count() NUSE_Semaphore_Information() NUSE_Semaphore_Count() NUSE_Event_Group_Information() NUSE_Event_Group_Count() NUSE_Signals_Send() NUSE_Timer_Control() NUSE_Timer_Get_Remaining() NUSE_Timer_Reset() NUSE_Timer_Information() NUSE_Timer_Count() NUSE_Clock_Set() NUSE_Clock_Retrieve() NUSE_Release_Information()
No entanto, apenas
NUSE_Signals_Send () é útil para eles, pois fornece uma maneira conveniente de indicar à tarefa que alguma ação é necessária.
Se o bloqueio estiver desativado, ou seja, as tarefas não poderão ser colocadas em estado de prontidão por muitas chamadas de API, outras chamadas de API estarão disponíveis:
NUSE_Partition_Allocate() NUSE_Partition_Deallocate() NUSE_Mailbox_Send() NUSE_Mailbox_Receive() NUSE_Mailbox_Reset() NUSE_Queue_Send() NUSE_Queue_Receive() NUSE_Queue_Jam() NUSE_Queue_Reset() NUSE_Pipe_Send() NUSE_Pipe_Receive() NUSE_Pipe_Jam() NUSE_Pipe_Reset() NUSE_Semaphore_Obtain() NUSE_Semaphore_Release() NUSE_Semaphore_Reset() NUSE_Event_Group_Set() NUSE_Event_Group_Retrieve()
Algumas chamadas de API são sempre inacessíveis aos manipuladores de interrupção padrão, pois inevitavelmente exigem o trabalho de um agendador:
NUSE_Task_Suspend() NUSE_Task_Resume() NUSE_Task_Sleep() NUSE_Task_Relinquish() NUSE_Task_Reset() NUSE_Signals_Receive()
Chamadas de API para o manipulador de interrupções gerenciado ou manipulador de interrupção padrão ao usar qualquer agendador que não seja o agendador de prioridadeMuitas outras funções da API podem ser chamadas a partir do manipulador de interrupções ao usar os agendadores Run to Completion, Round Robin ou Time Slice. Se um agendador de prioridade for usado, os manipuladores de interrupção gerenciados terão um conjunto semelhante de funções. Isso ocorre porque as chamadas são permitidas, o que pode levar ao agendamento de outra tarefa. Esse recurso é fornecido pelo código
NUSE_Reschedule () , que detecta o contexto de chamada no manipulador de interrupções e suprime a alteração de contexto (permitindo que isso aconteça no final do manipulador de interrupções). Uma análise completa do trabalho do agendador foi apresentada em um dos artigos anteriores (
nº 9 ).
O principal requisito é que as chamadas de API dentro do manipulador de interrupções não levem à suspensão da tarefa atual, por exemplo, aguardando a liberação de um recurso.
Em outras palavras, essas chamadas devem ser feitas com a
opção de pausa
NUSE_NO_SUSPEND .
Com isso em mente, as seguintes chamadas de API podem ser usadas:
NUSE_Task_Current() NUSE_Task_Check_Stack() NUSE_Task_Information() NUSE_Task_Count() NUSE_Task_Suspend() NUSE_Task_Resume() NUSE_Task_Reset() NUSE_Partition_Allocate() NUSE_Partition_Deallocate() NUSE_Partition_Pool_Information() NUSE_Partition_Pool_Count() NUSE_Mailbox_Send() NUSE_Mailbox_Receive() NUSE_Mailbox_Reset() NUSE_Mailbox_Information() NUSE_Mailbox_Count() NUSE_Queue_Send() NUSE_Queue_Receive() NUSE_Queue_Jam() NUSE_Queue_Reset() NUSE_Queue_Information() NUSE_Queue_Count() NUSE_Pipe_Send() NUSE_Pipe_Receive() NUSE_Pipe_Jam() NUSE_Pipe_Reset() NUSE_Pipe_Information() NUSE_Pipe_Count() NUSE_Semaphore_Obtain() NUSE_Semaphore_Release() NUSE_Semaphore_Reset() NUSE_Semaphore_Information() NUSE_Semaphore_Count() NUSE_Event_Group_Set() NUSE_Event_Group_Retrieve() NUSE_Event_Group_Information() NUSE_Event_Group_Count() NUSE_Signals_Send() NUSE_Timer_Control() NUSE_Timer_Get_Remaining() NUSE_Timer_Reset() NUSE_Timer_Information() NUSE_Timer_Count() NUSE_Clock_Set() NUSE_Clock_Retrieve() NUSE_Release_Information()
Algumas chamadas são sempre barradas, pois estão diretamente relacionadas à tarefa atual:
NUSE_Task_Relinquish() NUSE_Signals_Receive() NUSE_Task_Sleep()
Manipulador de interrupção de relógio em tempo real
O manipulador de interrupção do Real Time Clock (RTC) é o único manipulador de interrupção completo no Nucleus SE. Além de fornecer toda a funcionalidade necessária para o gerenciamento de tempo no Nucleus SE, também serve como exemplo de gravação de um manipulador de interrupções gerenciado.
Operações do manipulador de interrupção RTC
As funções fornecidas pelo manipulador de interrupções do RTC foram listadas em um dos artigos anteriores, que tratavam do amplo tópico de hora do sistema no Nucleus SE (
# 27 ). A funcionalidade descrita é opcional, dependendo da configuração do aplicativo.
A seguir está o código completo do manipulador de interrupção do RTC. #if NUSE_TIMER_NUMBER != 0 { U8 timer; for (timer=0; timer<NUSE_TIMER_NUMBER; timer++) { if (NUSE_Timer_Status[timer]) { if (--NUSE_Timer_Value[timer] == 0) { NUSE_Timer_Expirations_Counter[timer]++; #if NUSE_TIMER_EXPIRATION_ROUTINE_SUPPORT || NUSE_INCLUDE_EVERYTHING if (NUSE_Timer_Expiration_Routine_Address[timer] != NULL) { ((PF1)NUSE_Timer_Expiration_Routine_Address[timer]) NUSE_Timer_Expiration_Routine_Parameter[timer]); } #endif /* reschedule? */ if (NUSE_Timer_Reschedule_Time[timer] != 0) { /* yes: set up time */ NUSE_Timer_Value[timer] = NUSE_Timer_Reschedule_Time[timer]; } else { /* no: disable */ NUSE_Timer_Status[timer] = FALSE; } } } } } #endif #if NUSE_SYSTEM_TIME_SUPPORT || NUSE_INCLUDE_EVERYTHING NUSE_Tick_Clock++; #endif #if NUSE_TASK_SLEEP || NUSE_INCLUDE_EVERYTHING { U8 task; for (task=0; task<NUSE_TASK_NUMBER; task++) { if (NUSE_Task_Timeout_Counter[task] != 0) { NUSE_Task_Timeout_Counter[task]--; if (NUSE_Task_Timeout_Counter[task] == 0) { NUSE_Wake_Task(task); } } } } #endif #if NUSE_SCHEDULER_TYPE == NUSE_TIME_SLICE_SCHEDULER if (--NUSE_Time_Slice_Ticks == 0) { NUSE_Reschedule(); } #endif
A seguir, analisamos quatro áreas principais de funcionalidade do manipulador de interrupções RTC.
TemporizadoresSe os cronômetros do aplicativo estiverem configurados, o manipulador de interrupção entrará em um loop para processar cada cronômetro, diminuindo seu contador em 1. Se o cronômetro terminar a contagem (ou seja, o contador atingir 0), duas ações serão possíveis:
- se o manipulador de conclusão do timer estiver configurado e o cronômetro tiver um ponteiro de função correto (não NULL ) (em NUSE_Timer_Expiration_Routine_Address [] ), o manipulador será executado usando um parâmetro de NUSE_Timer_Expiration_Routine_Parameter [] ;
- se o cronômetro estiver configurado para inicializar após a conclusão (ou seja, NUSE_Timer_Reschedule_Time [] possui um valor diferente de zero), o cronômetro será recarregado com esse valor.
Os cronômetros de aplicativos foram descritos em detalhes em um artigo anterior (nº 28).
Relógio do sistemaSe um timer do sistema estiver configurado, o valor de
NUSE_Tick_Cloc k simplesmente aumentará em 1. Mais informações podem ser encontradas no artigo # 28.
Suspender uma tarefa (repouso da tarefa)Se o suporte para pausar tarefas estiver ativado (ou seja, a chamada da API
NUSE_Task_Sleep () estiver configurada), o contador de tempo limite de cada tarefa (o valor em
NUSE_Task_Timeout_Counter [] ) será verificado e, se não for igual a zero, diminui em 1. Se atingir zero, a tarefa correspondente será retomada. .
Agendamento de intervalo de tempoSe um agendador do Time Slice for usado, o contador do agendador (
NUSE_Time_Slice_Ticks ) será diminuído. Se atingir zero, o agendador é chamado. A chamada para
NUSE_Reschedule () é responsável por redefinir o contador.
Interrupção controlada
É necessário explicar por que o manipulador de interrupções do RTC é controlável, pois, sob certas circunstâncias, o usuário pode decidir reescrevê-lo como uma interrupção padrão para reduzir o uso de recursos de computação. Por exemplo, se apenas uma função de hora do sistema for usada (ou seja, não houver cronômetros de aplicativo, não houver suspensões de tarefas e não houver agendador de Time Slice), uma interrupção regular funcionará. A interrupção guiada é necessária nos seguintes casos:
- se os temporizadores forem usados e os manipuladores para sua conclusão estiverem configurados, pois esses manipuladores podem fazer chamadas de API (no contexto de interrupção), o que causará um novo agendamento. Eles têm as mesmas limitações que as chamadas de API feitas a partir de manipuladores de interrupção (veja anteriormente neste artigo);
- se um agendador de prioridade for usado, a conclusão de uma suspensão de tarefa poderá exigir a ativação de uma tarefa com prioridade mais alta;
- se o agendador do Time Slice for usado, ele será chamado a partir do manipulador de interrupções do RTC; portanto, é necessária uma interrupção controlada.
Compatível com núcleo RTOS
Como a implementação das interrupções do Nucleus SE é muito diferente do Nucleus RTOS, você não deve esperar compatibilidade nesse sentido. O Nucleus RTOS possui um esquema de interrupção padrão / de baixo nível / alto nível, que é um pouco como o esquema de interrupção padrão / controlado no Nucleus SE.
Manipuladores de interrupção de baixo e alto nível
Manipuladores de interrupção de baixo nívelUma Rotina de Serviço de Interrupção de Baixo Nível (LISR) é executada da mesma maneira que um manipulador regular, incluindo o uso da pilha atual. O núcleo RTOS mantém o contexto até que o manipulador de interrupção de baixo nível seja chamado e restaura o contexto após a conclusão do manipulador. Portanto, um manipulador de interrupção de baixo nível pode ser gravado em C e chamar outros manipuladores em C. No entanto, apenas alguns serviços Nucleus RTOS estão disponíveis para o manipulador de baixo nível. Se a manipulação de interrupções exigir serviços adicionais do Nucleus RTOS, você precisará ativar um manipulador de interrupções de alto nível. O Nucleus RTOS suporta o uso de vários manipuladores de interrupção de baixo nível.
Manipulador de interrupção de alto nívelA Rotina de Serviço de Interrupção de Alto Nível (HISR) é criada e excluída dinamicamente. Cada processador de alto nível possui seu próprio espaço de pilha e sua própria unidade de controle. A memória é alocada pelo aplicativo. E, é claro, um manipulador de interrupção de alto nível deve ser criado antes que um manipulador de interrupção de baixo nível possa ativá-lo.
Como o manipulador de interrupção de alto nível possui sua própria pilha e unidade de controle, ele pode ser temporariamente bloqueado se tentar acessar a estrutura de dados do Nucleus RTOS atualmente em uso.
Existem três níveis de prioridade disponíveis para um manipulador de interrupção de alto nível. Se um manipulador de nível superior com uma prioridade mais alta for ativado durante o trabalho de um manipulador com uma prioridade mais baixa, um manipulador com uma prioridade mais baixa será executado à medida que a tarefa for concluída. Manipuladores de interrupção de alto nível com a mesma prioridade são executados na ordem em que são ativados. Todos os manipuladores de interrupção de alto nível ativados devem ser concluídos antes de continuar a agendar tarefas no modo normal.
Utilitário de API do núcleo RTOS solicita interrupção
O núcleo RTOS possui várias chamadas de API para oferecer suporte a interrupções. Nenhum deles é implementado no Nucleus SE.
Para interrupções padrão, as chamadas de API fornecem as seguintes funções:
- controle (ativação / desativação) de interrupção (local e globalmente);
- definindo o vetor de interrupção.
Para interrupções de baixo nível:
- registrando um manipulador de interrupção de baixo nível no kernel.
Para interrupções de alto nível:
- criação / remoção de interrupções de alto nível;
- ativação de interrupção de alto nível;
- obtendo o número de interrupções de alto nível no aplicativo (no momento);
- obter indicadores para controlar unidades de todas as interrupções de alto nível;
- obter indicadores para controlar as unidades da atual interrupção de alto nível;
- Obtendo informações de interrupção de alto nível.
Controle global de interrupçãoEssa chamada ativa ou desativa interrupções, independentemente da tarefa. Portanto, a interrupção desativada por esta chamada permanecerá assim até que seja ativada reutilizando essa chamada.
Protótipo de chamada de serviço:
INT NU_Control_Interrupts (INT new_level);
Parâmetros:
new_level - um novo nível de interrupção para o sistema. Ele sempre pode aceitar os valores
NU_DISABLE_INTERRUPTS (desativa todas as interrupções) e
NU_ENABLE_INTERRUPTS (ativa todas as interrupções). Outros valores podem estar disponíveis, dependendo da arquitetura.
Valor de retorno:
Esta chamada de serviço retorna o nível anterior de interrupções ativadas.
Controle de interrupção localEssa chamada de serviço permite ativar ou desativar as interrupções, dependendo da tarefa. Essa chamada altera o registro de status para o valor especificado. O registro de status retornará ao valor especificado pela última chamada para
NU_Control_Interrupts () na próxima vez que o contexto for alterado.
Protótipo de chamada de serviço:
INT NU_Local_Control_Interrupts (INT new_level);
Parâmetros:
new_level - um novo nível de interrupção para a tarefa atual. Ele sempre pode aceitar os valores
NU_DISABLE_INTERRUPTS (desativa todas as interrupções) e
NU_ENABLE_INTERRUPTS (ativa todas as interrupções). Outros valores podem estar disponíveis, dependendo da arquitetura.
Valor de retorno:
Esta chamada de serviço retorna o nível anterior de interrupções ativadas.
Definindo o vetor de interrupçãoEssa sobrecarga substitui o vetor de interrupção especificado pelo vetor controlado pelo manipulador de interrupções.
Protótipo de chamada de serviço:
VOID *NU_Setup_Vector (INT vector, VOID *new);
Parâmetros:
vector -
vetor de interrupção para o qual a interrupção será registrada;
new é o manipulador de interrupção escrito para o vetor.
Valor de retorno:
Essa chamada de utilitário retorna um ponteiro para o manipulador de interrupções registrado anteriormente para o vetor de interrupção.
Registro de interrupção de baixo nívelEssa sobrecarga chama a função do manipulador de interrupção de baixo nível com o vetor de interrupção. O contexto do sistema é salvo automaticamente antes que o manipulador de interrupção de baixo nível especificado seja chamado e restaurado após a conclusão do manipulador de interrupção.
Protótipo de chamada de serviço:
STATUS NU_Register_LISR (INT vector, VOID (*lisr_entry) (INT), VOID (**old_lisr) (INT);
Parâmetros:
vector -
vetor de interrupção para o qual a interrupção será registrada;
lisr_entry - a função que será registrada para o vetor, o valor
NU_NULL limpará o vetor;
old_lisr é uma função registrada anteriormente para o vetor especificado.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_VECTOR - vetor inválido;
NU_NOT_Rector - no momento o vetor não está registrado, pois o
cancelamento de registro foi especificado em l
isr_entry ;
NO_MORE_LISRS - O número máximo de manipuladores de interrupção de baixo nível registrados foi atingido.
Criando um manipulador de interrupção de alto nívelEssa chamada de utilitário cria um manipulador de interrupção de alto nível.
Protótipo de chamada de serviço:
STATUS NU_Create_HISR (NU_HISR *hisr, CHAR *name, VOID (*hisr_entry) (VOID), OPTION priority, VOID *stack_pointer, UNSIGNED stack_size);
Parâmetros:
hisr - um ponteiro para um bloco de controle fornecido pelo usuário para um manipulador de interrupção de alto nível;
name - ponteiro para um nome de 7 caracteres para um manipulador de interrupção de alto nível com um zero final;
hisr_entry - o ponto de entrada da função de manipulador de interrupção de alto nível;
prioridade - há três prioridades para manipuladores de interrupção de alto nível (0-2); a prioridade 0 é a mais alta;
stack_pointer - ponteiro para a área de pilha do manipulador de interrupção de alto nível;
stack_size - o número de bytes na pilha do manipulador de interrupções de alto nível.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_HISR - um ponteiro nulo para a unidade de controle do manipulador de interrupção de alto nível (
NULL ) ou a unidade de controle já está em uso;
NU_INVALID_ENTRY - um ponteiro nulo para o ponto de entrada de um manipulador de interrupção de alto nível (
NULL );
NU_INVALID_PRIORITY - prioridade incorreta para um manipulador de interrupção de alto nível;
NU_INVALID_MEMORY - ponteiro de pilha inválido;
NU_INVALID_SIZE - o tamanho da pilha é muito pequeno.
Removendo um manipulador de interrupção de alto nívelEssa chamada de utilitário remove o manipulador de interrupção de alto nível criado anteriormente.
Protótipo de chamada de serviço:
STATUS NU_Delete_HISR (NU_HISR *hisr);
Parâmetros:
hisr é um ponteiro para o bloco de controle do manipulador de interrupção de alto nível fornecido pelo usuário.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_HISR - Ponteiro
inválido para um manipulador de interrupção de alto nível.
Ativando um manipulador de interrupção de alto nívelEssa chamada de utilitário ativa um manipulador de interrupção de alto nível. Se o manipulador de interrupção de alto nível especificado estiver sendo executado no momento, a solicitação de ativação não será executada até que o manipulador pare de funcionar. Um manipulador de interrupção de alto nível é executado uma vez para cada solicitação de ativação.
Protótipo de chamada de serviço:
STATUS NU_Activate_HISR (NU_HISR *hisr);
Parâmetros:
hisr é um ponteiro para o bloco de controle de um manipulador de interrupção de alto nível.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_HISR - ponteiro inválido para a unidade de controle de um manipulador de interrupção de alto nível.
Obtendo o número de manipuladores de interrupção de alto nível em um sistemaEssa chamada de utilitário retorna o número de manipuladores de interrupção de alto nível instalados. Todos os manipuladores de interrupção de alto nível criados são considerados instalados. Manipuladores de interrupção remotos de alto nível não são considerados instalados.
Protótipo de chamada de serviço:
UNSIGNED NU_Established_HISRs(VOID);
Parâmetros:
Estão ausentes.
Valor de retorno:
Essa chamada de utilitário retorna o número de manipuladores de interrupção de alto nível instalados no sistema.
Obtendo ponteiros para controlar blocos de manipuladores de interrupção de alto nívelEssa chamada de serviço forma uma lista seqüencial de ponteiros para todos os manipuladores de interrupção de alto nível instalados no sistema.
Protótipo de chamada de serviço:
UNSIGNED NU_HISR_Pointers(NU_HISR **pointer_list, UNSIGNED maximum_pointers);
Parâmetros:
pointer_list - ponteiro para uma matriz de ponteiros
NU_HISR ; essa matriz será preenchida com ponteiros para os manipuladores de interrupção de alto nível instalados no sistema;
maximum_pointers - o número máximo de ponteiros
NU_HISR que podem ser colocados na matriz; geralmente é igual ao tamanho da matriz
pointer_list .
Valor de retorno:
Essa chamada de utilitário retorna o número de manipuladores de interrupção de alto nível ativos no sistema.
Obtendo um ponteiro para o atual manipulador de interrupção de alto nívelEssa chamada de utilitário retorna um ponteiro para o manipulador de interrupção de alto nível em execução no momento.
Protótipo de chamada de serviço:
NU_HISR *NU_Current_HISR_Pointer(VOID);
Parâmetros:
Estão ausentes.
Valor de retorno:
Essa chamada de serviço retorna um ponteiro para a unidade de controle do manipulador de interrupção de alto nível em execução no momento. Se um manipulador de interrupção de nível não alto chamar essa função,
NU_NULL será retornado.
Obtendo informações sobre um manipulador de interrupção de alto nívelEssa chamada de utilitário retorna várias informações sobre o manipulador de interrupção de alto nível especificado.
Protótipo de chamada de serviço:
STATUS NU_HISR_Information(NU_HISR *hisr, char *name, UNSIGNED *scheduled_count, DATA_ELEMENT *priority, VOID **stack_base, UNSIGNED *stack_size, UNSIGNED *minimum_stack);
Parâmetros:
hisr - um ponteiro para um manipulador de interrupção de alto nível;
name - ponteiro para a região de 8 caracteres para o nome do manipulador de interrupção de alto nível, incluindo o zero final;
schedule_count - ponteiro para uma variável pelo número total de vezes que esse manipulador de interrupção de alto nível foi agendado;
prioridade - um ponteiro para uma variável para armazenar a prioridade de um manipulador de interrupção de alto nível;
stack_base - ponteiro para um ponteiro para armazenar o ponteiro original na pilha; esse é o mesmo ponteiro que foi passado ao criar o manipulador de interrupção de alto nível;
stack_size - um ponteiro para uma variável para armazenar o tamanho total da pilha de um manipulador de interrupção de alto nível;
minimum_stack - um ponteiro para uma variável para armazenar a quantidade mínima de espaço disponível na pilha detectada durante a execução de um manipulador de interrupção de alto nível.Valor de retorno:NU_SUCCESS - a chamada foi concluída com sucesso;NU_INVALID_HISR - Ponteiro inválido para um manipulador de interrupção de alto nível.Chamadas de API de manipuladores de interrupção
Chamada de API de manipuladores de interrupção de baixo nível Um manipulador de interrupção de baixo nívelpode usar apenas os seguintes recursos do Nucleus RTOS: NU_Activate_HISR() NU_Local_Control_Interrupts() NU_Current_HISR_Pointer() NU_Current_Task_Pointer() NU_Retrieve_Clock()
Chamadas de serviço da API de manipuladores de interrupção de alto nível Os manipuladores de interrupção dealto nível têm acesso à maioria das funções do Nucleus RTOS, exceto para funções de pausa automática, uma vez que um manipulador de interrupção de alto nível não pode suspender a função Nucleus RTOS, o parâmetro sempre deve ser NU_NO_SUSPEND .O próximo artigo desta série abordará os procedimentos de inicialização e inicialização do Nucleus SE.Sobre o autor:Colin Walls trabalha na indústria eletrônica há mais de trinta anos, passando a maior parte do tempo em firmware. Ele agora é engenheiro de firmware na Mentor Embedded (uma divisão da Mentor Graphics). Colin Walls frequentemente fala em conferências e seminários, autor de vários artigos técnicos e dois livros sobre firmware. Vive no Reino Unido. Blog profissional de Colin , e-mail: colin_walls@mentor.com.