STM32F103Mini transplant RT threadnano

STM32F103 Mini transplant RT thread nano

Introduction to RT thread nano

RT thread nano is a minimalist version of hard real-time kernel. It is developed by C language, adopts object-oriented programming thinking and has a good code style. It is a tailorable, preemptive real-time multitasking RTOS. Its memory resources are very small, and its functions include relatively complete real-time operating system characteristics such as task processing, software timer, semaphore, mailbox and real-time scheduling. It is suitable for 32-bit ARM entry-level MCU widely used in home appliances, consumer electronics, medical equipment, industrial control and other fields.
The following figure is the software block diagram of RT thread nano, including supported CPU architecture and kernel source code, as well as removable fish components:

Use Nano source code compressed package for migration

RT-Thread Nano3.1.3 source code download link

RT thread nano source directory structure

bsp: official sample code and board level support files
Components: find components
docs: official documentation
include: header file of kernel
Libcpu: migration file of arm series and RISC-V series CPU s
SRC: nano kernel source code

Prepare an STM32 bare metal project

Here is the change based on the bare metal code in the STM32F103 Mini board data of punctual atom, and the project link completed by the change will be attached.
Firstly, delete the useless groups in the project groups, leaving only the ones in the figure

Delete the useless header file path and keep only the in the figure

Empty main C procedures in documents

Add RT thread nano kernel code

RT to be downloaded_ Copy the kernel source code of thread nano to the project directory


Add item grouping as follows

Add the following program files to the project respectively


|
Add reference to header file

Error reporting solution

After the kernel migration is completed, an error occurs and the RTE is prompted_ Components. H header file not found

This file is useless and can be commented out directly


Comment out the above line of code and recompile, prompting us that the interrupted entry function is repeatedly defined

This is due to our RT_Thread Nano has helped us implement these three functions in the project, so we need to add stm32f10x_ it. The interrupt entry function in C program file is shielded


After recompilation, the system compiler may have a warning. Ignore it. Finally, modify the rtconfig file to enable dynamic memory heap management and complete kernel migration

Test Engineering

Use the following code to test the transplanted project

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

#ifndef RT_USING_HEAP 		// Determine whether to use dynamic memory heap
rt_err_t rst;
static struct rt_thread led_thread = {0};			//Create an LED thread
static rt_uint8_t led_thread_stack[256];			//LED for static thread_ Thread creates a stack space
#else
static rt_thread_t led_thread;
#endif
static void led_entry(void* parameter){
	while(1){
#ifndef RT_USING_HEAP
		/* The dynamic memory heap is not enabled, and the red light flashes */
		GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
		rt_thread_mdelay(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
		rt_thread_mdelay(500); 
#else
		/* The dynamic memory heap is enabled and the yellow light flashes */
		GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_SET);
		rt_thread_mdelay(500);
		GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_RESET);
		rt_thread_mdelay(500); 
#endif
	}
}
/* led Thread initialization and startup function */
static void LED_INIT(void){
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);
	/*Initialize the GPIO corresponding to the two LED lights on the STM32 Mini development board*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;				//green light
	GPIO_Init(GPIOD, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;				//red light
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_SetBits(GPIOD, GPIO_Pin_2);								//Turn off the two LED lights
	GPIO_SetBits(GPIOA, GPIO_Pin_8);

#ifndef RT_USING_HEAP
	rst = rt_thread_init(	&led_thread,
									"led",
									led_entry, RT_NULL,
									&led_thread_stack[0], sizeof(led_thread_stack),
									RT_THREAD_PRIORITY_MAX-2, 20);
	if(rst == RT_EOK){
		rt_thread_startup(&led_thread);
	}
#else
	led_thread = rt_thread_create("led",
																led_entry, RT_NULL,
																256, 
																RT_THREAD_PRIORITY_MAX-2, 20);
	if(led_thread != RT_NULL){
		rt_thread_startup(led_thread);			//Start led thread
	}
#endif
}

int main(void)
{		
	LED_INIT();		//Start led thread
//	while(1){
//		/*Mask it, otherwise the led thread cannot be executed*/
//	}
}

Migrate console components (FISH)

Fish is a command-line component of RT thread, which provides a set of operation interfaces for users to call on the command line. It is mainly used to debug or view system information.

Serial port initialization

In main Add the following code to the C file

static int uart_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	USART_ClockInitTypeDef USART_ClockInitStructure;
	
	//-----------------------------------------------------
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
	USART_DeInit(USART1);


	//-----------------------------------------------------
	//Config USART1
	//TX(PA9) 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;    
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure); 
	//Rx(PA10)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;    
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure); 
	
	//-----------------------------------------------------
	//
	//USART_StructInit(&USART_InitStructure);
	USART_InitStructure.USART_BaudRate = 115200;                  
	USART_InitStructure.USART_WordLength = USART_WordLength_8b; 
	USART_InitStructure.USART_StopBits = USART_StopBits_1;      
	USART_InitStructure.USART_Parity = USART_Parity_No;         
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 
	USART_Init(USART1, &USART_InitStructure);
	
	USART_ClockStructInit(&USART_ClockInitStructure);
	USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; 
	USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; 
	USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge; 
	USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; 
	USART_ClockInit(USART1, &USART_ClockInitStructure);
	
	USART_GetFlagStatus(USART1, USART_FLAG_TC);    
	USART_Cmd(USART1, ENABLE);
	
	return 0;
}
INIT_BOARD_EXPORT(uart_init);  /* Default initialization method 1: use the macro INIT_BOARD_EXPORT is automatically initialized */

Implement console output rt_hw_console_output

///*Transplant console to realize console output and docking rt_hw_console_output */
void rt_hw_console_output(const char *str)
{
    /* Enter critical zone */
    rt_enter_critical();
    
    while(*str!='\0')
    {
        if(*str=='\n')
        {
            USART_SendData(USART1,'\r');
            while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET);
        }
        USART_SendData(USART1,*str++);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET);
    }
    
    /* Exit critical zone */
    rt_exit_critical();
}

In LED_ Add a printout statement to the thread entry function to test the program

rt_kprintf("Hello RT-Thread!!!\n");

Enable fish

In rtconfig Add the following macro definition to the H file

#define RTE_USING_FINSH 				// Start fish

When you start fish, you must start Dynamic memory heap .

Add project groups and program files (in the components \ fish folder)

Add reference address of fish header file

Implement console command input rt_hw_console_getchar

/* To transplant fish and realize command-line interaction, you need to add fish source code, and then connect rt_hw_console_getchar */
/* Query mode */
char rt_hw_console_getchar(void)
{
    int ch = -1;
 
    if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
    {
        //USART_ClearITPendingBit(USART_DEBUG,  USART_FLAG_RXNE);
        ch = USART_ReceiveData(USART1) & 0xFF;
    }
    else
    {
        if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
        {
            USART_ClearITPendingBit(USART1,  USART_FLAG_ORE);
        }
        rt_thread_mdelay(10);
    }
    
    return ch;
}

Error reporting solution


Locate the error position

Cancel RT_ USING_ Comments defined by device macro, compiled

Test Engineering

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

#ifndef RT_USING_HEAP 		// Determine whether to use dynamic memory heap
rt_err_t rst;
static struct rt_thread led_thread = {0};			//Create an LED thread
static rt_uint8_t led_thread_stack[256];			//LED for static thread_ Thread creates a stack space
#else
static rt_thread_t led_thread;
#endif
static void led_entry(void* parameter){
#if defined(RTE_USING_FINSH) && defined(RT_USING_HEAP)
	static rt_uint8_t count;
	for(count=0; count<10; count++){
#else
	while(1){
#endif
#ifndef RT_USING_HEAP
		/* The dynamic memory heap is not enabled, and the red light flashes */
		GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
		rt_thread_mdelay(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
		rt_thread_mdelay(500); 
#else
		/* The dynamic memory heap is enabled and the yellow light flashes */
		GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_RESET);
		rt_thread_mdelay(500);
		GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_SET);
		rt_thread_mdelay(500); 
#endif
	}
	rt_kprintf("led_thread exit\n");
}
/* led Thread initialization and startup function */
static void LED_INIT(void){
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);
	/*Initialize the GPIO corresponding to the two LED lights on the STM32 Mini development board*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;				//green light
	GPIO_Init(GPIOD, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;				//red light
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_SetBits(GPIOD, GPIO_Pin_2);								//Turn off the two LED lights
	GPIO_SetBits(GPIOA, GPIO_Pin_8);

#ifndef RT_USING_HEAP
	rst = rt_thread_init(	&led_thread,
									"led",
									led_entry, RT_NULL,
									&led_thread_stack[0], sizeof(led_thread_stack),
									RT_THREAD_PRIORITY_MAX-2, 20);
	if(rst == RT_EOK){
		rt_thread_startup(&led_thread);
	}
#else
	led_thread = rt_thread_create("led",
																led_entry, RT_NULL,
																256, 
																RT_THREAD_PRIORITY_MAX-2, 20);
	if(led_thread != RT_NULL){
		rt_thread_startup(led_thread);			//Start led thread
	}
#endif
}
MSH_CMD_EXPORT(LED_INIT, "The LED test");
int main(void)
{		
#ifndef RTE_USING_FINSH
	LED_INIT();
#endif
	while(1){
		/* Mask the while loop or suspend the thread, otherwise the led thread will not be executed */
		rt_thread_mdelay(500);
	}
}

#if defined(RTE_USING_FINSH)
/* Porting console to realize console output and docking rt_hw_console_output */
void rt_hw_console_output(const char *str)
{
    /* Enter critical zone */
    rt_enter_critical();
    
    while(*str!='\0')
    {
        if(*str=='\n')
        {
            USART_SendData(USART1,'\r');
            while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET);
        }
        USART_SendData(USART1,*str++);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET);
    }
    
    /* Exit critical zone */
    rt_exit_critical();
}
/* To transplant fish and realize command-line interaction, you need to add fish source code, and then connect rt_hw_console_getchar */
/* Query mode */
char rt_hw_console_getchar(void)
{
    int ch = -1;
 
    if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
    {
        //USART_ClearITPendingBit(USART_DEBUG,  USART_FLAG_RXNE);
        ch = USART_ReceiveData(USART1) & 0xFF;
    }
    else
    {
        if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
        {
            USART_ClearITPendingBit(USART1,  USART_FLAG_ORE);
        }
        rt_thread_mdelay(10);
    }
    
    return ch;
}

/* Serial port initialization */
static int uart_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	USART_ClockInitTypeDef USART_ClockInitStructure;
	
	//-----------------------------------------------------
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
	USART_DeInit(USART1);

	//-----------------------------------------------------
	//Config USART1
	//TX(PA9) 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;    
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure); 
	//Rx(PA10)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;    
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure); 
	
	//-----------------------------------------------------
	//
	//USART_StructInit(&USART_InitStructure);
	USART_InitStructure.USART_BaudRate = 115200;                  
	USART_InitStructure.USART_WordLength = USART_WordLength_8b; 
	USART_InitStructure.USART_StopBits = USART_StopBits_1;      
	USART_InitStructure.USART_Parity = USART_Parity_No;         
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 
	USART_Init(USART1, &USART_InitStructure);
	
	USART_ClockStructInit(&USART_ClockInitStructure);
	USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; 
	USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; 
	USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge; 
	USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; 
	USART_ClockInit(USART1, &USART_ClockInitStructure);
	
	USART_GetFlagStatus(USART1, USART_FLAG_TC);    
	USART_Cmd(USART1, ENABLE);
	
	return 0;
}
INIT_BOARD_EXPORT(uart_init);  /* The default option is initialization method 1: use the macro INIT_BOARD_EXPORT is automatically initialized */
#endif /* RTE_USING_FINSH */


After the project is downloaded, open the serial assistant and reset the development board. If the migration is successful, the version information and msh command input prompt will be printed

Input LED_ The green LED on the init instruction development board will flash ten times, and the console will print the LED after completion_ thread exit

Use the RT thread nano package provided by MDK for transplantation

RT thread nano package download
Method 1: RT thread offline installation package
Method 2:
Open the MDK software and click the Pack Installer icon in the toolbar

Click the Pack on the right, expand Generic, find realthread:: RT thread, and select version 3.1.3 for installation

Project creation

Create an STM32F103RC project


After creating the project, click manage run time environment

Check the following options



Click OK after checking all items. There will be a warning after compiling the project. Ignore it and complete the transplantation of RT thread nano kernel.

Test Engineering

Use the previous code pair engineering If everything runs normally, it means that the migration is successful.

Add fish component

Open the MDK software, click the Pack Installer icon on the toolbar, check the following parameters and click OK to complete the installation of components.

When using the fish component, be sure to enable the dynamic memory heap

Realize serial port initialization and console input and output functions

specific engineering

RT thread nano 3.1.5 migration using CubeMX

  • Download Cube MX 5.0 at https://www.st.com/en/development-tools/stm32cubemx.html .
  • Download the RT thread nano pack installation package on CubeMX.

Get RT thread nano package

Add in CubeMX https://www.rt-thread.org/download/cube/RealThread.RT-Thread.pdsc .




Click Check. After passing the check, click OK to finish adding the kernel

Create project


Select the chip model STM32F103RC

Select RT thread nano package


Choose to use an external crystal oscillator as the clock source

Set HCLK to 72MHz

Set interrupt

Select Nano component

Do not enable console
Set the pin corresponding to the LED of the development board to OUTPUT

Enter the project name and select the software and version to use

Create project (ignore warning)

Open project

Shield SystemClock_Config() function, which is in board C has been called

Test Engineering

Test Engineering

Migrate fish

Select package

Select Nano component and set the function of serial port 1 pin

Initialization function of masked GPIO

Add GPIO initialization function to board level initialization

INIT_BOARD_EXPORT(MX_GPIO_Init);


Configure rtconfig H file

Add HAL library file of serial port


Enable serial port clock

Modify the serial port to USART1

After all changes are completed, compile, download and migrate

Test Engineering

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <rtthread.h>
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

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

/* USER CODE BEGIN PV */
#ifndef RT_USING_HEAP 		// Determine whether to use dynamic memory heap
rt_err_t rst;
static struct rt_thread led_thread = {0};			//Create an LED thread
static rt_uint8_t led_thread_stack[256];			//LED for static thread_ Thread creates a stack space
#else
static rt_thread_t led_thread;
#endif
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static int MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static void led_entry(void* parameter){
#if defined(RT_USING_FINSH) && defined(RT_USING_HEAP)
	static rt_uint8_t count;
	for(count=0; count<10; count++){
#else
	while(1){
#endif
#ifndef RT_USING_HEAP
		/* The dynamic memory heap is not enabled, and the red light flashes */
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
		rt_thread_mdelay(500);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
		rt_thread_mdelay(500); 
#else
		/* The dynamic memory heap is enabled and the yellow light flashes */
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		rt_thread_mdelay(500);
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		rt_thread_mdelay(500); 
#endif
	}
	rt_kprintf("led_thread exit\n");
}
/* led Thread initialization and startup function */
static void LED_INIT(void){

#ifndef RT_USING_HEAP
	rst = rt_thread_init(	&led_thread,
									"led",
									led_entry, RT_NULL,
									&led_thread_stack[0], sizeof(led_thread_stack),
									RT_THREAD_PRIORITY_MAX-2, 20);
	if(rst == RT_EOK){
		rt_thread_startup(&led_thread);
	}
#else
	led_thread = rt_thread_create("led",
																led_entry, RT_NULL,
																256, 
																RT_THREAD_PRIORITY_MAX-2, 20);
	if(led_thread != RT_NULL){
		rt_thread_startup(led_thread);			//Start led thread
	}
#endif
}
MSH_CMD_EXPORT(LED_INIT, "The LED test");
/* 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();
  /* USER CODE BEGIN 2 */
#ifndef RT_USING_FINSH
	LED_INIT();
#endif
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		rt_thread_mdelay(500);	//Suspend the main thread so that other threads can execute
    /* 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 RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  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 buses 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 GPIO Initialization Function
  * @param None
  * @retval None
  */
static int 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_USART1_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PA9 */
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PA10 */
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PD2 */
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
	
	return 0;
}
INIT_BOARD_EXPORT(MX_GPIO_Init);
/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @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 */
  __disable_irq();
  while (1)
  {
  }
  /* 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,
     ex: 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****/

Article reference
https://blog.csdn.net/killercode11/article/details/104290949
https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/an0038-nano-introduction
Article code download address
https://gitee.com/SLHU/rt_-thread_-project

Keywords: RTOS

Added by scvinodkumar on Tue, 25 Jan 2022 08:04:41 +0200