Controle de LED com Botão usando Azure RTOS na Franzininho C0

Este post faz parte da série Franzininho C0 com STM32CubeIDE

O que é RTOS? 

RTOS é a sigla para “Sistema Operacional de Tempo Real” (Real Time Operating System). Um sistema operacional é um programa que gerencia as funções básicas de um computador e oferece serviços para outros programas que rodam nele. Em um sistema operacional, vários programas são executados ao mesmo tempo. Cada núcleo do processador executa uma única tarefa (ou thread) que é escolhida pelo planejador. O planejador decide qual programa será executado em cada momento, alternando rapidamente entre eles para dar a ilusão de que todos estão rodando simultaneamente. O RTOS é um tipo especial de sistema operacional projetado para gerenciar o tempo de resposta de tarefas em ambientes onde a precisão e a previsibilidade são cruciais, priorizando, assim, a execução de tarefas dentro de prazos definidos. Isso é importante em sistemas embarcados, como em dispositivos médicos, automóveis e equipamentos industriais, onde atrasos ou variações no tempo de resposta podem resultar em falhas críticas ou perigosas.

O que é Azure RTOS? 

O Azure RTOS é  uma classe de RTOS, sendo um pacote de middleware de nível profissional com um conjunto de componentes desenvolvidos pela Microsoft para aplicar em sistemas embarcados e dispositivos de IoT (Internet das Coisas). A Azure RTOS está integrada no ecossistema STM32Cube e pode ser facilmente implementada no firmware das placas da STM.

Os componentes principais do Azure RTOS são: 

  • ThreadX: núcleo principal do Azure RTOS.
  • FileX: sistema de arquivos de alto desempenho que oferece suporte para várias estruturas de diretório e tipos de arquivo.
  • GUIX: biblioteca de interface gráfica de usuário (GUI) que facilita a criação de interfaces gráficas sofisticadas para dispositivos embarcados. 
  • NetX Duo: protocolos de rede que fornecem suporte para conectividade de rede, incluindo TCP/IP, adequadas para dispositivos conectados à Internet.
  • USBX: conjunto de componentes que oferece suporte para USB host, dispositivo e On-The-Go (OTG), permitindo a comunicação com periféricos USB.

Descrição Projeto

Neste artigo, vamos aprender a trabalhar com o ThreadX configurando o Azure RTOS usando a ferramenta CubeMX. Nosso objetivo é controlar o LED conectado ao pino PB6 ao pressionar o BOTÃO conectado ao pino PA8 e exibir o status do LED via UART. Para isso, criaremos duas tarefas e utilizaremos uma fila para a comunicação entre essas tarefas. Não será necessário nenhum hardware adicional além da Franzininho C0.

Configurando CubeMX

  1. Abra STM32Cube , crie um novo projeto e selecione o microcontrolador de destino “STM32C011F6P6”. 
  1. Entre na página de configurações de relógio e ajuste HCLK para 48 MHz. 
  1. Volte para a página de configuração dos pinos. Em “System Core” > “SYS”, habilite os pinos PA9 e PA10. Em seguida, selecione “TIM16” como a base de tempo (timebase source). Ao usar o Azure RTOS, a fonte de base de tempo não pode ser o clock interno do microcontrolador. Deve-se usar um temporizador (timer) específico para garantir precisão e estabilidade nas operações de tempo real.
  1. Depois, vamos configurar nossa UART. Selecione o pino PA10 como “USART1_RX” e PA9 como “USART1_TX”. Em “Connectivity” selecione a opção “USART1” e em Mode escolha o “Asynchronous”. As demais configurações deixe padrão. 
  1. Em seguida, habilite o ThreadX do Azure RTOS. Para fazer isso, vá para “Middleware and Software,” procure por “THREADX,” e habilite a opção “Core.”
  1. Na sequência, configuraremos as entradas e saídas. Para configurar a entrada, selecione o pino “PA8”, defina seu modo como “Input Mode” e ative o resistor de Pull-up. Depois, selecione o pino “PB6”, defina seu modo como “Output Mode” e renomeie-o para “LED”.
  1. Por fim, gere o código em “Project” > “Generate Code”.

Implementação código

Ao gerar o código, serão incluídos dois arquivos específicos para trabalhar com o Azure RTOS.  

Primeiro, acesse o arquivo main.c, e inclua  MX_ThreadX_Init() na função principal int main: 

int main(void)
{
 /* USER CODE BEGIN 1 */
 /* USER CODE END 1 */
 /* MCU Configuration--------------------------------------------------------*/
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 /* USER CODE BEGIN Init */
 /* USER CODE END Init */
 /* Configure the system clock */
 SystemClock_Config();
 /* USER CODE BEGIN SysInit */
 /* USER CODE END SysInit */
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_USART1_UART_Init();
 /* USER CODE BEGIN 2 */
 /* USER CODE END 2 */
 MX_ThreadX_Init();
 /* We should never get here as control is now taken by the scheduler */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}

Depois, acesse o arquivo app_threadx.c e realize as seguintes modificações:

  1. Inclua stdio.h e main.h 
#include <stdio.h>
#include "main.h"
  1. Crie as definições a seguir:
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define BTN_STATUS_STACK_SIZE 512
#define LED_STATUS_STACK_SIZE 512
#define QUEUE_STACK_SIZE  16
/* USER CODE END PD */
  1. Crie as seguintes variáveis e protótipos das funções (tarefas):
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
extern UART_HandleTypeDef huart1;
uint8_t btn_status_stack[BTN_STATUS_STACK_SIZE];
uint8_t led_status_stack[LED_STATUS_STACK_SIZE];
uint8_t queue_stack[QUEUE_STACK_SIZE];
TX_THREAD btn_status_ptr;
TX_THREAD led_status_ptr;
TX_QUEUE  queue_ptr;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
VOID btn_status(ULONG initial_input);
VOID led_status(ULONG initial_input);
/* USER CODE END PFP */
  1. Procure por App_ThreadX_Init e inclua a criação das tarefas e fila. 
UINT App_ThreadX_Init(VOID *memory_ptr)
{
 UINT ret = TX_SUCCESS;
 /* USER CODE BEGIN App_ThreadX_MEM_POOL */
 /* USER CODE END App_ThreadX_MEM_POOL */
 /* USER CODE BEGIN App_ThreadX_Init */
  tx_queue_create(&queue_ptr, "message_btn_status", TX_1_ULONG ,queue_stack,QUEUE_STACK_SIZE);
 tx_thread_create(&btn_status_ptr,"btn_status",btn_status,0,btn_status_stack, BTN_STATUS_STACK_SIZE,15,15,1,TX_AUTO_START);
 tx_thread_create(&led_status_ptr,"led_status",led_status,0,led_status_stack, LED_STATUS_STACK_SIZE,15,15,1,TX_AUTO_START);
 /* USER CODE END App_ThreadX_Init */
 return ret;
}

A função tx_thread_create cria e inicia uma nova thread (tarefa). Seus parâmetros são:

  • &btn_status_ptr: Ponteiro para a estrutura da thread.
  • “btn_status”: Nome da thread (tarefa).
  • btn_status: Ponteiro para a função da thread.
  • 0: Valor passado como argumento para a função da thread (não utilizado nesta implementação).
  • btn_status_stack: Ponteiro para o stack da thread.
  • BTN_STATUS_STACK_SIZE: Tamanho do stack da thread.
  • 15: Prioridade da thread (quanto menor o valor, maior a prioridade).
  • 15: Sub-prioridade da thread (em sistemas com preempção de múltiplos níveis, geralmente igual à prioridade principal).
  • 1: Time-slice para a thread (quantidade de ticks que a thread pode rodar antes de outra thread com a mesma prioridade ser executada).
  • TX_AUTO_START: Opção de auto-start para a thread (a thread começa a rodar automaticamente após ser criada).

A função tx_queue_create cria a fila que será usada para passar mensagens entre as tarefas btn_status e led_status. A criação da fila possui os seguintes parâmetros:

  • queue_ptr: Ponteiro para a fila.
  • “message_btn_status”: Nome da fila.
  • TX_1_ULONG: Tipo de mensagem (um ULONG).
  • queue_stack: Array utilizado como armazenamento da fila.
  • QUEUE_STACK_SIZE: Tamanho do array queue_stack.
  1. Crie a função da thread btn_status (ULONG initial_input). Esta tarefa lê o estado de um botão conectado ao pino GPIOA, GPIO_PIN_8 e envia uma mensagem para a fila queue_ptr sempre que o estado do botão muda.
VOID btn_status (ULONG initial_input) {
   ULONG message_pin_status = DISABLE;
   ULONG message_pin_status_new = DISABLE;
   while(1) {
       tx_thread_sleep(10);
       if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_RESET) {
           message_pin_status_new = ENABLE;
       } else {
           message_pin_status_new = DISABLE;
       }
       if (message_pin_status != message_pin_status_new) {
           message_pin_status = message_pin_status_new;
           tx_queue_send(&queue_ptr, &message_pin_status, TX_NO_WAIT);
       }
   }
}
  1. Crie  a função da thread  led_status(ULONG initial_input). Esta tarefa recebe mensagens da fila queue_ptr e aciona um LED conectado ao LED_GPIO_Port e LED_Pin com base nas mensagens recebidas. Também transmite mensagens pela UART para indicar o estado do LED. 
VOID led_status(ULONG initial_input) {
   ULONG message_status;
   uint8_t msg_led_on[] = "The LED is ON\r\n";
   uint8_t msg_led_off[] = "The LED is OFF\r\n";
   while(1) {
       tx_queue_receive(&queue_ptr, &message_status, TX_WAIT_FOREVER);
       if(message_status == ENABLE) {
           HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
           HAL_UART_Transmit(&huart1, msg_led_on, sizeof(msg_led_on) - 1, 1000);
       } else {
           HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
           HAL_UART_Transmit(&huart1, msg_led_off, sizeof(msg_led_off) - 1, 1000);
       }
   }
}

Gravação

Ao finalizar o código, partiremos para gravação. Nessa etapa você pode utilizar o ST-Link seguindo as conexões da imagem abaixo e clicando em “run” no STM32CubeIde.

Ou você pode optar por utilizar um cabo usb e gravar conforme explicado no seguinte tutorial: gravar-franzininho-c0-via-stm32cubeprogrammer

Funcionamento

Conclusão

Neste artigo, demonstramos como configurar e utilizar o Azure RTOS para controlar um LED com um botão utilizando a placa Franzininho C0 com a ferramenta STM32CubeMX. Através da integração do ThreadX, parte do Azure RTOS, configuramos duas tarefas principais para monitorar o estado de um botão e controlar um LED com base nas leituras do botão.

Franzininho C0 com STM32CubeIDE

Monitoramento de Temperatura e Umidade com DHT11 e Franzininho C0 e Exibição em Display OLED Leitura dos Eixos X, Y e Z do acelerômetro LIS3DH com a Franzininho C0 via SPI
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
0 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Home » Hardware » Microcontroladores » Controle de LED com Botão usando Azure RTOS na Franzininho C0

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: