freertos simple serial port

Let’s first improve the configuration file FreeRTOSConfig.h

/*
    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
    All rights reserved

    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.

    This file is part of the FreeRTOS distribution.

    FreeRTOS is free software; you can redistribute it and/or modify it under
    the terms of the GNU General Public License (version 2) as published by the
    Free Software Foundation >>>> AND MODIFIED BY <<<<the FreeRTOS exception.

    *************************************************** *************************
    >>! NOTE: The modification to the GPL is included to allow you to !<<
    >>! distribute a combined work that includes FreeRTOS without being !<<
    >>! obliged to provide the source code for proprietary components !<<
    >>! outside of the FreeRTOS kernel. !<<
    *************************************************** *************************

    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE. Full license text is available on the following
    link: http://www.freertos.org/a00114.html

    *************************************************** *************************
     * *
     * FreeRTOS provides completely free yet professionally developed, *
     * robust, strictly quality controlled, supported, and cross *
     * platform software that is more than just the market leader, it *
     * is the industry's de facto standard. *
     * *
     * Help yourself get started quickly while simultaneously helping *
     * to support the FreeRTOS project by purchasing a FreeRTOS *
     * tutorial book, reference manual, or both: *
     * http://www.FreeRTOS.org/Documentation *
     * *
    *************************************************** *************************

    http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
    the FAQ page "My application does not run, what could be wrong?". Have you
    defined configASSERT()?

    http://www.FreeRTOS.org/support - In return for receiving this top quality
    embedded software for free we request you assist our global community by
    participating in the support forum.

    http://www.FreeRTOS.org/training - Investing in training allows your team to
    be as productive as possible as early as possible. Now you can receive
    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
    Ltd, and the world's leading authority on the world's leading RTOS.

    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
    including FreeRTOS + Trace - an indispensable productivity tool, a DOS
    compatible FAT file system, and our tiny thread aware UDP/IP stack.

    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
    Come and try FreeRTOS + TCP, our new open source TCP/IP stack for FreeRTOS.

    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
    Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
    licenses offer ticketed support, indemnification and commercial middleware.

    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
    engineered and independently SIL3 certified version for use in safety and
    mission critical applications that require provable dependability.

    1 tab == 4 spaces!
*/

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

#include "stm32f10x.h" // Device header


//* 1: RTOS uses a preemptive scheduler; 0: RTOS uses a cooperative scheduler (time slice)
#define configUSE_PREEMPTION 1

/*Some FreeRTOS ports have two methods of selecting the next task to execute,
 *0: One is a general method,
 *1: The other is a port-specific approach (relying on one or more architecture-specific assembly instructions (usually the Count Leading Zeros [CLZ] instruction or equivalent),
 *Thus only applicable to the architecture for which this directive was written. ).
 */
//#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0

//Set to 1 to use low power no tick mode, or to 0 to keep tick interrupts running at all times.
#define configUSE_TICKLESS_IDLE 1

//kernel clock
#define configCPU_CLOCK_HZ (SystemCoreClock)

//SysTick clock frequency has been defined by the system, no need to define it here
//#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ

//RTOS system beat interrupt frequency 1ms
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )

//The maximum priority that can be used
#define configMAX_PRIORITIES (32)

//Stack size used by idle tasks
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )

//Task name string length
#define configMAX_TASK_NAME_LEN 16

//System beat counter variable data type, 1 represents a 16-bit unsigned integer, 0 represents a 32-bit unsigned integer
#define configUSE_16_BIT_TICKS 0

//The number of times the tick interrupt has been executed after the RTOS kernel is started. The number of ticks is stored in a variable of type tickType_t
//#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS

//Idle tasks give up CPU usage rights to other user tasks of the same priority
#define configIDLE_SHOULD_YIELD 1

//Enable task notification function, 1 is enabled
//#define configUSE_TASK_NOTIFICATIONS 1

//Each RTOS task has a task notification array. configTASK_NOTIFICATION_ARRAY_ENTRIES sets the index number of the array.
//#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3

//1 Use mutually exclusive semaphore
//#define configUSE_MUTEXES 0

//1 Use recursive mutex semaphore
//#define configUSE_RECURSIVE_MUTEXES 0

//1 Use counting semaphore
//#define configUSE_COUNTING_SEMAPHORES 0

//#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */

//Set the number of semaphores and message queues that can be registered
//#define configQUEUE_REGISTRY_SIZE 10

//enable queue
//#define configUSE_QUEUE_SETS 0

//1 Enable time slice scheduling
//#define configUSE_TIME_SLICING 1

//If configUSE_NEWLIB_REENTRANT is set to 1, a newlib reentrant structure will be allocated for each created task.
//#define configUSE_NEWLIB_REENTRANT 0

//1 Compatible with versions prior to 8.0
//#define configENABLE_BACKWARD_COMPATIBILITY 0

//Set the thread local storage array for each task
//#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5

//When set to 0, MiniListItem_t and ListItem_t remain consistent. When set to 1, MiniListItem_t contains 3 fewer fields than ListItem_t
//#define configUSE_MINI_LIST_ITEM 1

//Set the type used to specify the stack depth when calling xTaskCreate()
//#define configSTACK_DEPTH_TYPE uint16_t

//The message buffer uses variables of type configMESSAGE_BUFFER_LENGTH_TYPE to store the length of each message
//#define configMESSAGE_BUFFER_LENGTH_TYPE size_t

//
//#define configHEAP_CLEAR_MEMORY_ON_FREE 1



/****************************************************** ****************
              FreeRTOS configuration options related to memory application
*************************************************** ***************/

//Support static memory
#define configSUPPORT_STATIC_ALLOCATION 1

//Support dynamic memory application
#define configSUPPORT_DYNAMIC_ALLOCATION 1

//The total heap size of the system
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) )

/*By default, the FreeRTOS heap is declared by FreeRTOS and placed in memory by the linker.
 *Set configAPPLICATION_ALLOCATED_HEAP to 1,
 *Allows application writers to declare the heap, which allows the application writer to place the heap anywhere in memory.
 *If using heap_1.c, heap_2.c or heap_4.c and setting configAPPLICATION_ALLOCATED_HEAP to 1,
 *Then the application writer must provide an array of uint8_t with the exact name and size shown below.
 *This array will be used as the FreeRTOS heap. How the array is placed at a specific location in memory depends on the compiler used, see your compiler's documentation.
 */
//#define configAPPLICATION_ALLOCATED_HEAP 1

/*Set to 1, then for any task created using xTaskCreate or xTaskCreateRestricted API,
 *The stack is allocated using the pvPortMallocStack function and released using the vPortFreeStack function.
 *Users need to implement thread-safe pvPortMallocStack and vPortFreeStack functions.
 */
//#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 1

/****************************************************** ******************
             FreeRTOS configuration options related to hook functions
*************************************************** ************/

/* Set to 1: use idle hook (Idle Hook is similar to a callback function); set to 0: ignore idle hook
 *
 * The idle task hook is a function, which is implemented by the user.
 * FreeRTOS specifies the name and parameters of the function: void vApplicationIdleHook(void),
 * This function will be called in every idle task cycle
 * For RTOS tasks that have been deleted, idle tasks can release the stack memory allocated to them.
 * Therefore, it must be ensured that idle tasks can be executed by the CPU
 * It is very common to use the idle hook function to set the CPU into power saving mode
 * Do not call API functions that will cause idle tasks to block.
 */
#define configUSE_IDLE_HOOK 0

/* Set to 1: use the time slice hook (Tick Hook); set to 0: ignore the time slice hook
 *
 *
 * The time slice hook is a function, which is implemented by the user.
 * FreeRTOS specifies the name and parameters of the function: void vApplicationTickHook(void)
 * Time slice interrupt can be called periodically
 * The function must be very short and cannot use the stack extensively.
 * API functions ending with "FromISR" or "FROM_ISR" cannot be called
 */
 /*xTaskIncrementTick function is called in xPortSysTickHandler interrupt function. Therefore, the execution time of the vApplicationTickHook() function must be very short*/
#define configUSE_TICK_HOOK 0

/*
 * When greater than 0, the stack overflow detection function is enabled, if this function is used
 * The user must provide a stack overflow hook function if used
 * This value can be 1 or 2 because there are two stack overflow detection methods
 */
//#define configCHECK_FOR_STACK_OVERFLOW 0

//Use memory application failure hook function
#define configUSE_MALLOC_FAILED_HOOK 0


//#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
//#define configUSE_SB_COMPLETED_CALLBACK 0

/****************************************************** *********************
          FreeRTOS configuration options related to runtime and task status collection
*************************************************** ************************/

//Enable running time statistics function
//#define configGENERATE_RUN_TIME_STATS 0

//Enable visual trace debugging
//#define configUSE_TRACE_FACILITY 0

/* When the macro configUSE_TRACE_FACILITY is 1 at the same time, the following three functions will be compiled.
 * prvWriteNameToBuffer()
 * vTaskList(),
 * vTaskGetRunTimeStats()
*/
//#define configUSE_STATS_FORMATTING_FUNCTIONS 1

/****************************************************** *********************
                FreeRTOS configuration options related to coroutines
*************************************************** *******************/
//Enable coroutine. After enabling coroutine, you must add the file croutine.c
#define configUSE_CO_ROUTINES 0

The effective number of priorities for the coroutine
#define configMAX_CO_ROUTINE_PRIORITIES 2

/****************************************************** **********************
                FreeRTOS configuration options related to software timers
*************************************************** ************************/

//Enable software timer
#define configUSE_TIMERS 0

//Software timer priority
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1)

//Software timer queue length
#define configTIMER_QUEUE_LENGTH 10

//Software timer task stack size
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2)

/****************************************************** *************
           Break nested behavior configuration
*************************************************** **********/
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
//Interrupt lowest priority
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15

//The highest interrupt priority level that the system can manage
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) /* 240 */

#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

//#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]

/****************************************************** *************
           Assertion configuration
*************************************************** **********/
//#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

/****************************************************** *************
           Specific definition of FreeRTOS MPU
*************************************************** **********/
//#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
//#define configTOTAL_MPU_REGIONS 8 /* Default value. */
//#define configTEX_S_C_B_FLASH 0x07UL /* Default value. */
//#define configTEX_S_C_B_SRAM 0x07UL /* Default value. */
//#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1
//#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1
//#define configENABLE_ERRATA_837070_WORKAROUND 1
//#define configUSE_MPU_WRAPPERS_V1 0
//#define configPROTECTED_KERNEL_OBJECT_POOL_SIZE 10
//#define configSYSTEM_CALL_STACK_SIZE 128

///* ARMv8-M secure side port related definitions. */
//#define secureconfigMAX_SECURE_CONTEXTS 5

/****************************************************** *************
            FreeRTOS optional function configuration options
*************************************************** **********/
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xResumeFromISR 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_uxTaskGetStackHighWaterMark2 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 0
#define INCLUDE_xTaskAbortDelay 0
#define INCLUDE_xTaskGetHandle 0
#define INCLUDE_xTaskResumeFromISR 1
#define INCLUDE_vTaskCleanUpResources 0
/* A header file that defines trace macro can be included here. */

#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
//#define xPortSysTickHandler SysTick_Handler


#endif /* FREERTOS_CONFIG_H */


Then add the implementation of usart
usart.h:

#ifndef __USART_H
#define __USART_H


#include "stm32f10x.h"
#include <stdio.h>

/**
  * Serial port macro definitions. Different serial ports mount different buses and IOs. These macros need to be modified during transplantation.
* 1-Modify the macro of the bus clock, mount uart1 to the apb2 bus, and mount other uarts to the apb1 bus
*2-Modify GPIO macros
  */
\t
// Serial port 1-USART1
#define DEBUG_USARTx USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200

// USART GPIO pin macro definition
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
    
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10

#define DEBUG_USART_IRQ USART1_IRQn
#define DEBUG_USART_IRQHandler USART1_IRQHandler


// Serial port 2-USART2
//#define DEBUG_USARTx USART2
//#define DEBUG_USART_CLK RCC_APB1Periph_USART2
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200

 USART GPIO pin macro definition
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
//
//#define DEBUG_USART_TX_GPIO_PORT GPIOA
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_2
//#define DEBUG_USART_RX_GPIO_PORT GPIOA
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_3

//#define DEBUG_USART_IRQ USART2_IRQn
//#define DEBUG_USART_IRQHandler USART2_IRQHandler

// Serial port 3-USART3
//#define DEBUG_USARTx USART3
//#define DEBUG_USART_CLK RCC_APB1Periph_USART3
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200

 USART GPIO pin macro definition
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOB)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
//
//#define DEBUG_USART_TX_GPIO_PORT GPIOB
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10
//#define DEBUG_USART_RX_GPIO_PORT GPIOB
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11

//#define DEBUG_USART_IRQ USART3_IRQn
//#define DEBUG_USART_IRQHandler USART3_IRQHandler

// Serial port 4-UART4
//#define DEBUG_USARTx UART4
//#define DEBUG_USART_CLK RCC_APB1Periph_UART4
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200

 USART GPIO pin macro definition
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
//
//#define DEBUG_USART_TX_GPIO_PORT GPIOC
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10
//#define DEBUG_USART_RX_GPIO_PORT GPIOC
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11

//#define DEBUG_USART_IRQ UART4_IRQn
//#define DEBUG_USART_IRQHandler UART4_IRQHandler


// Serial port 5-UART5
//#define DEBUG_USARTx UART5
//#define DEBUG_USART_CLK RCC_APB1Periph_UART5
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200

 USART GPIO pin macro definition
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
//
//#define DEBUG_USART_TX_GPIO_PORT GPIOC
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_12
//#define DEBUG_USART_RX_GPIO_PORT GPIOD
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_2

//#define DEBUG_USART_IRQ UART5_IRQn
//#define DEBUG_USART_IRQHandler UART5_IRQHandler


void USART_Config(void);
#endif /* __USART_H */

usart.c:

#include "usart.h"

 /**
  * @brief Configure nested vector interrupt controller NVIC
  * @param none
  * @retval None
  */
static void NVIC_Configuration(void)
{<!-- -->
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Nested vector interrupt controller group selection */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* Configure USART as interrupt source */
  NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
  /* Stealing priority*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* Sub-priority */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* Enable interrupts */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* Initialize configuration NVIC */
  NVIC_Init( & amp;NVIC_InitStructure);
}

 /**
  * @brief USART GPIO configuration, working parameter configuration
  * @param none
  * @retval None
  */
void USART_Config(void)
{<!-- -->
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

// Turn on the clock of the serial port GPIO
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
\t
// Turn on the clock of the serial port peripheral
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

//Configure the GPIO of USART Tx to push-pull multiplexing mode
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  //Configure the GPIO of USART Rx to floating input mode
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
\t
//Configure the working parameters of the serial port
//Configure baud rate
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
//Configure pin data word length
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// Configure stop bit
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//Configure check digit
USART_InitStructure.USART_Parity = USART_Parity_No;
//Configure hardware flow control
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
// Configure working mode, send and receive together
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// Complete the initial configuration of the serial port
USART_Init(DEBUG_USARTx, & amp;USART_InitStructure);
\t
// Serial port interrupt priority configuration
NVIC_Configuration();
\t
// Enable serial port reception interrupt
USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
\t
//Enable serial port
USART_Cmd(DEBUG_USARTx, ENABLE);
}

///Redirect the c library function printf to the serial port. The printf function can be used after redirection.
int fputc(int ch, FILE *f)
{<!-- -->
/* Send one byte of data to the serial port */
USART_SendData(DEBUG_USARTx, (uint8_t) ch);
\t\t
/* Wait for sending to complete */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
\t
return(ch);
}

///Redirect the c library function scanf to the serial port. After rewriting, you can use scanf, getchar and other functions
int fgetc(FILE *f)
{<!-- -->
/* Wait for serial port input data */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

return (int)USART_ReceiveData(DEBUG_USARTx);
}


Then modify stm32f10x_it.c

Just put it into the board and you can receive:

The complete project is here:
Link: https://pan.baidu.com/s/1OzcaDXFJVUJn6r1Nz6yWBQ?pwd=3q3t
Extraction code: 3q3t