Primeiramente, utilize o STM32CubeMX para gerar um programa básico de piscar LED, contendo apenas as inicializações necessárias para validação inicial da funcionalidade.
Após a confirmação do funcionamento básico, adicione as três pastas necessárias do QPC ao diretório do projeto e crie novos arquivos no mesmo local.
Como estamos utilizando uma placa de teste STM32F407ZGT6, podemos limpar o diretório da pasta ports, mantendo apenas o arm-cm.
Observa-se que esta pasta contém quatro subpastas: qk, qutest, qv e qxk. Estas representam diferentes núcleos da máquina de estados: qk: Núcleo preemptivo (não bloqueante) qxk: Núcleo preemptivo (bloqueante) qv: Núcleo cooperativo (RTC) qutest: Núcleo de teste (não utilizar)
No Keil, crie novos grupos de arquivos e inclua os arquivos correspondantes. Para este exemplo, utilizaremos o núcleo qv, portanto, selecione os arquivos da pasta qv.
Ao selecionar os arquivos do qv, certifique-se de escolher a versão armclang.
A estrutura de inclusão deve seguir a seguinte organização:
É importante notar que a não inclusão dos arquivos gerados na pasta APP resultará no seguinte erro:
Após importar os arquivos gerados para a pasta APP e organizar corretamente as dependências, a compilação deve ser bem-sucedida, concluindo esta etapa inicial.
A seguir, estabeleça a base de tempo adicionando a seguinte função ao manipulador de serviço SysTick:
void QF_onClockTick(void)
{
QF_TICK_X(0U, (void *)0); /* realiza o processamento do tick de relógio do QF */
}
Como mostrado abaixo:
Durante a compilação, é necessário marcar a opção MicrLib; caso contrário, o código pode funcionar em modo de depuração, mas falhará na execução real. A cadeia de compilação também deve ser da versão AC6.
Neste ponto, ainda pode ser que o código não execute corretamente. Verifique se a prioridade do SysTick está configurada adequadamente. Uma configuração incorreta de prioridade também impedirá a execução normal do código, pois o QP redefine todas as prioridades durante sua operação.
Portanto, após a reinicialização, devemos redefinir as prioridades:
void QF_onStartup(void)
{
NVIC_SetPriority(SysTick_IRQn, 1); // Define prioridade de interrupção
}
A função QF_onStartup é executada imediatamente após a inicialização da máquina de estados e geralmente contém inicializações de nível de placa, incluindo prioridades e periféricos. QF_onCleanup é executada durante o encerramento. QV_onIdle é executada na fase ociosa, funcionando como um gancho de ociosidade.
Se você estiver usando código gerado pelo Cube ou tiver código de inicialização BSP fixo, ainda pode colocar o código em QF_onStartup. Por exemplo:
void QF_onStartup(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
}
Código-fonte disponível em: https://gitee.com/lzc56/qp-stm32-f407-zgt6-state-machine.git