Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 10

/* USER CODE BEGIN Header */

/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/


/* USER CODE BEGIN Includes */

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

#include <stdio.h>
#include <string.h>
#include <stdint.h>

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/


/* USER CODE BEGIN PTD */

typedef enum
{
Bit_RESET = 0,
Bit_SET
}BitAction;

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/


/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/


/* USER CODE BEGIN PM */

/* USER CODE END PM */


/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */


QueueHandle_t xQueue;
SemaphoreHandle_t xMutex;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/


void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);

/* USER CODE BEGIN PFP */


void vTask_print_q (void *pvParameters);
void vTask_print( void * pvParameter );
void vTask_blink( void *pvParameter );

void vPrintString (char* UartSend_f);


void USARTlib_Putc(UART_HandleTypeDef* huart, char c);
void USARTlib_Puts(char* str);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/


/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
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_USART2_UART_Init();
/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* USER CODE BEGIN RTOS_MUTEX */


xMutex = xSemaphoreCreateMutex();

/* USER CODE END RTOS_MUTEX */

/* USER CODE BEGIN RTOS_SEMAPHORES */


/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */

/* USER CODE BEGIN RTOS_TIMERS */


/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */

/* USER CODE BEGIN RTOS_QUEUES */

/*
* Realiza a alocação dinâmica da fila na memória RAM do STM32;
* Neste caso foi criado um fila com 5 elementos do tipo unsigned int 32
bits.
*/
if( (xQueue = xQueueCreate( 5, sizeof(char *)) ) == NULL )
{
//sprintf(UartSend,"nao foi possivel alocar xQueue");
//HAL_UART_Transmit(&huart2,(uint8_t*) UartSend, strlen(UartSend), 1);

vPrintString("nao foi possivel alocar a xQueue");


}
else{
vPrintString("Fila criada!");
}

/* USER CODE END RTOS_QUEUES */

/* Create the thread(s) */


/* definition and creation of defaultTask */

/* USER CODE BEGIN RTOS_THREADS */

if( (xTaskCreate( vTask_print_q, "TASK PRINT Q", configMINIMAL_STACK_SIZE *


3, NULL, 2, NULL) ) != pdTRUE)
{
//sprintf(UartSend,"nao foi possivel alocar tarefa vTaskTwo no
escalonador");
//HAL_UART_Transmit(&huart2,(uint8_t*) UartSend,
sizeof(UartSend), 10);

vPrintString("nao foi possivel alocar tarefa vTaskPrint_QUEUE no


escalonador");
}

/* configMINIMAL_STACK_SIZE é um #define que informa para o FreeRTOS qual o


tamanho mínimo
necessário para rodar uma task. Por meio do menuconfig é possível saber o
tamanho de configMINIMAL_STACK_SIZE;
*/

if( (xTaskCreate( vTask_blink, "blink task", configMINIMAL_STACK_SIZE,


NULL, 1, NULL) ) != pdTRUE )
{

//sprintf(UartSend,"nao foi possivel alocar tarefa vTask_blink no


escalonador");
//HAL_UART_Transmit(&huart2,(uint8_t*) UartSend, sizeof(UartSend),
10);

vPrintString("nao foi possivel alocar tarefa vTaskBlink no


escalonador");
}

/*
* Task_print e task_adc contém a função printf (ESP_LOGI). Portanto, foi
aumentado o stack
* para 2k;
*/

if( (xTaskCreate( vTask_print, "task print", configMINIMAL_STACK_SIZE * 3 ,


NULL, 1, NULL)) != pdTRUE )
{
//sprintf(UartSend,"nao foi possivel alocar tarefa vTask_print no
escalonador");
//HAL_UART_Transmit(&huart2,(uint8_t*) UartSend, sizeof(UartSend), 10);

vPrintString("nao foi possivel alocar tarefa vTask_Print no


escalonador");
}

vTaskStartScheduler();

/* USER CODE END RTOS_THREADS */

/* 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 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Initializes the CPU, AHB and APB busses clocks


*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)


{
Error_Handler();
}
}

/**
* @brief USART2 Initialization Function
* @param None
* @retval None
*/
static void MX_USART2_UART_Init(void)
{

/* USER CODE BEGIN USART2_Init 0 */

/* USER CODE END USART2_Init 0 */

/* USER CODE BEGIN USART2_Init 1 */

/* USER CODE END USART2_Init 1 */


huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */

/* USER CODE END USART2_Init 2 */

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */


__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();

/*Configure GPIO pin Output Level */


HAL_GPIO_WritePin(DOUT_LED1_GPIO_Port, DOUT_LED1_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin : DOUT_LED1_Pin */


GPIO_InitStruct.Pin = DOUT_LED1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DOUT_LED1_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pin : DIN_BUTTON_Pin */


GPIO_InitStruct.Pin = DIN_BUTTON_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DIN_BUTTON_GPIO_Port, &GPIO_InitStruct);

/* USER CODE BEGIN 4 */


void vPrintString (char * UartSend_f)
{
//xSemaphoreTake( xMutex, portMAX_DELAY );

taskENTER_CRITICAL();

USARTlib_Puts(UartSend_f);

taskEXIT_CRITICAL();

//xSemaphoreGive( xMutex );

}
void USARTlib_Putc(UART_HandleTypeDef* huart, char c)
{
//Envia caracter
HAL_UART_Transmit(huart, &c, 1, 10);
}

void USARTlib_Puts(char* str)


{
while (*str)
{
USARTlib_Putc(&huart2, *str++);
}
}

/* USER CODE END 4 */

/* USER CODE BEGIN Header_StartDefaultTask */

void vTask_print_q (void *pvParameters)


{

uint32_t status;
char Buffer_test[30];
char UartSend[100];

char * pt_string = Buffer_test; //ponteiro de queue recebe o endereço


do buffer de char

sprintf(Buffer_test,"String test queue");

vPrintString("Entrei na task QUEUE \n\n");

/* As Tasks normalmente possuem um loop sem saída */


for( ;; )
{
/*
* Envia na fila o valor da variável count;
* Caso a fila esteja cheia será retornado imediatamente;
* Sendo assim,
*/

/* status_return = xQueueSend( fila_name, variável_address,


timeout) */
status = xQueueSend( xQueue, &pt_string, 50 /
portTICK_PERIOD_MS );

if( status == pdPASS )


{
sprintf(UartSend,"O valor da string \" %s \" foi enviado na
Queue.\n", Buffer_test);
vPrintString(UartSend);
}
/* Bloqueia esta task por 1s */

vPrintString("Task Queue \r\n");


vTaskDelay( 1000 / portTICK_PERIOD_MS );
}
/* este comando não deveria ser executado... Caso algo estranho
aconteça,
* esta task será deletada; O parametro NULL informa que é para
desalocar
* da memória ESTA task;
*/
vTaskDelete( NULL );
}

/*
* Esta task é responsável em receber o valor de count
* por meio da leitura da fila e imprimir na saída do console serial.
*/
void vTask_print( void * pvParameter )
{
uint32_t status;
char * recebe_string;

vPrintString("Entrei na task print");

for(;;)
{
/* status_return = xQueueReceive( fila_name, variável_address, timeout)
*/
status = xQueueReceive(xQueue, &recebe_string, portMAX_DELAY);

//caso nao usar o portMAX_DELAY, fazer o bloqueio da tarefa com


vTaskDelay no fim da task
//status = xQueueReceive(xQueue, &recebe_string, 0);

if(status == pdPASS)
{
//Para entender a necessidade de alocação dinamica de memoria
//deixo o link abaixo, onde explica porque precisamos fazer um
malloc
//para alocar um buffer ao nosso ponteiro para uso na função
sprintf
//lembrando que iremos usar o pvPortMalloc que é safe thread para
o FreeRTOS
//https://stackoverflow.com/questions/19772667/c-sprintf-array-
char-pointers

char * UartSend = pvPortMalloc(strlen(recebe_string)+1);

sprintf(UartSend,"Recebido a string \" %s \" \n", recebe_string);

vPrintString(UartSend);

//liberando o o espaço de memoria dinamica alocado para enviar a


string
vPortFree(UartSend); //vPortFree é a implementação Thread Safe
da função free()

/*
* Depois testar essa implementação
*/
/*
vPrintString("Foi recebido a string: ");
vPrintString(recebe_string);
vPrintString("\r\n\r\n");
*/

vPrintString("Task print \r\n \n");

//caso usar portMAX_DELAY na fila, comentar esse bloqueio da task


abaixo
//vTaskDelay(1000 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}

/*
* Task responsável em inverter o estado lógico do led building
* do kit;
*/
void vTask_blink( void *pvParameter )
{

for( ;; )
{
/* Liga Led */
HAL_GPIO_TogglePin(DOUT_LED1_GPIO_Port, DOUT_LED1_Pin);
vTaskDelay( 1000 / portTICK_PERIOD_MS );

// vPrintString("Task Blink \r\n");


}
}

/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM4 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */

/* USER CODE END Callback 0 */


if (htim->Instance == TIM4) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */

/* USER CODE END Callback 1 */


}

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */

/* USER CODE END Error_Handler_Debug */


}

#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

You might also like