Lesson 2 [CMSIS and standard library development] standard library CMSIS layering

Posted by eskick on Wed, 15 Sep 2021 22:17:34 +0200

Basic knowledge framework

Class notes

CMSIS

Many peripheral manufacturers provide peripherals for Cortex kernel. The differences brought by different peripherals lead to great difficulties in software writing or transplantation. Therefore, Arm company and chip manufacturers jointly launched CMSIS standard. Its full name is Cortex MicroController Software Interface Standard

Hierarchical relationship and function of CMSIS

CMSIS standard specifies APPLICATION layer, CMSIS layer and MCU layer. The relationship between layers is shown in the figure below

The most important function of CMSIS standard is to establish a hardware abstraction layer between the user layer and the hardware layer, so as to shield the differences of the hardware layer and provide the processor software interface to the user layer

CMSIS layer file structure

According to the CMSIS standard, ST officially provides kernel register related files (CMSIS related) and peripheral register related files (peripheral standard library other than CMSIS). Their relationship is as follows

It can be seen from the file structure that the core of CMSIS layer is mainly divided into kernel function layer and peripheral function access layer:

  • Kernel function layer: the file is mainly provided by Arm company. The file content includes the name and address definition of the kernel register
  • Peripheral function access layer: the file is mainly provided by the chip manufacturer. The file content includes the name and address definition of peripheral registers and interrupts

Kernel function layer file

The kernel function layer file is mainly used to configure the clock and operate the kernel register, which is rarely used in general

  • system_ Stm32f10x. H /. C: operate RCC clock to realize system clock configuration. When the system is powered on, it will first execute the startup file, which will call the SystemInit function, which is defined in this file. After the default state is called, it will initialize the system clock to 72MHz
  • core_ Cm3. H /. C: implement the name and address definition of the kernel register and the function of operating the register

Peripheral function access layer file

The file of peripheral function access layer is mainly used to realize peripheral address mapping and operate peripheral registers. The files here are often used

  • stm32f10x_ xxxx. H /. C: xxxx refers to gpio, adc, etc. each peripheral has a corresponding src driver source file and inc definition related header file. It is the main part of peripheral standard library
  • stm32f10x.h: it realizes all register mapping of on-chip peripherals

Standard library development

In the previous lesson 1, you have implemented the basic library function and lit the LED light through it. After learning the standard library, you can try to realize the function of lighting led through the standard library and add other advanced functions

Standard library development LED-GPIO

Led function header file BSP_ Implementation of the main part of LED. H code

#ifndef __BSP_LED_H__
#define __BSP_LED_H__

#include "stm32f1xx_hal.h"
// GPIO outputs high, low and reverse levels
#define digitalHi(Port, Pin) ((Port)->BSRR = Pin)
#define digitalLi(Port, Pin) ((Port)->BRR  = Pin)
#define digitalRev(Port,Pin) ((Port)->ODR ^= Pin)
// RGB light on, off and reverse
#define LED1_ON  digitalLi(LED1_GPIO_Port, LED1_Pin)
#define LED1_OFF digitalHi(LED1_GPIO_Port, LED1_Pin)
#define LED1_REV digitalRev(LED1_GPIO_Port, LED1_Pin)

#define LED2_ON  digitalLi(LED2_GPIO_Port, LED2_Pin)
#define LED2_OFF digitalHi(LED2_GPIO_Port, LED2_Pin)
#define LED2_REV digitalRev(LED2_GPIO_Port, LED2_Pin)

#define LED3_ON  digitalLi(LED3_GPIO_Port, LED3_Pin)
#define LED3_OFF digitalHi(LED3_GPIO_Port, LED3_Pin)
#define LED3_REV digitalRev(LED3_GPIO_Port, LED3_Pin)
// RGB lamp and other derived color lamps
#define LED_RED \
				LED1_ON;\
				LED2_OFF;\
				LED3_OFF;

#define LED_GREEN \
				LED1_OFF;\
				LED2_ON;\
				LED3_OFF;

#define LED_BLUE \
				LED1_OFF;\
				LED2_OFF;\
				LED3_ON;

#define LED_YELLOW \
				LED1_ON;\
				LED2_ON;\
				LED3_OFF;

#define LED_PURPLE \
				LED1_ON;\
				LED2_OFF;\
				LED3_ON;

#define LED_CYAN \
				LED1_OFF;\
				LED2_ON;\
				LED3_ON;

#define LED_WHITE \
				LED1_ON;\
				LED2_ON;\
				LED3_ON;

#define LED_BLACK \
				LED1_OFF;\
				LED2_OFF;\
				LED3_OFF;

void LED_GPIO_Config(void);

#endif

LED function source file BSP_ Implementation of key. C code body

#ifndef BSP_LED_C_
#define BSP_LED_C_

#include "bsp_led.h"
#include "main.h"
// LED related GPIO port initialization
void LED_GPIO_Config(void)
{
	// Enable GPIOB clock
	__HAL_RCC_GPIOB_CLK_ENABLE();
	
	// Define and supplement structure information
	GPIO_InitTypeDef* GPIO_LED_Structure;
	
	GPIO_LED_Structure->Pin   = LED1_Pin;

	GPIO_LED_Structure->Mode  = GPIO_MODE_OUTPUT_PP;

	GPIO_LED_Structure->Speed = GPIO_SPEED_FREQ_HIGH;
	
	// Initialize GPIO port
	HAL_GPIO_Init(LED1_GPIO_Port, GPIO_LED_Structure);

	GPIO_LED_Structure->Pin   = LED2_Pin;

	HAL_GPIO_Init(LED2_GPIO_Port, GPIO_LED_Structure);

	GPIO_LED_Structure->Pin   = LED3_Pin;

	HAL_GPIO_Init(LED3_GPIO_Port, GPIO_LED_Structure);
	
	// Output high level
	HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);

	HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);

	HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET);
}
#endif

Implementation of main.c code body

/* 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 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 "bsp_led.h"
/* 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 */

/* USER CODE END PV */

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

/* 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();
  /* USER CODE BEGIN 2 */
  LED_GPIO_Config();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	LED1_ON;
    /* 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_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  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_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @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_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED2_Pin|LED3_Pin|LED1_Pin, GPIO_PIN_SET);

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

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

  /*Configure GPIO pins : LED2_Pin LED3_Pin LED1_Pin */
  GPIO_InitStruct.Pin = LED2_Pin|LED3_Pin|LED1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

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

Standard library development KEY-GPIO

KEY function header file BSP_ Implementation of KEY. H code body

#ifndef __BSP_LED_H__
#define __BSP_LED_H__

#include "stm32f1xx_hal.h"

void KEYScan(void);

void LED_GPIO_Config(void);

#endif

KEY function source file BSP_ Implementation of KEY. C code body

#ifndef BSP_LED_C_
#define BSP_LED_C_

#include "bsp_led.h"
#include "main.h"

void KEYScan(void)
{
	if (GPIO_PIN_SET == HAL_GPIO_WritePin(KEY_GPIO_Port, KEY_Pin))
		while(GPIO_PIN_SET == HAL_GPIO_WritePin(KEY_GPIO_Port, KEY_Pin));
		return GPIO_PIN_SET;
	else
		return GPIO_PIN_RESET;
}

// KEY related GPIO port initialization
void KEY_GPIO_Config(void)
{
	// Enable GPIOC clock
	__HAL_RCC_GPIOC_CLK_ENABLE();
	
	// Define and supplement structure information
	GPIO_InitTypeDef* GPIO_LED_Structure;
	
	GPIO_LED_Structure->Pin   = KEY_Pin;

	GPIO_LED_Structure->Mode  = GPIO_Mode_IN_FLOATING;
	
	// Initialize GPIO port
	HAL_GPIO_Init(LED1_GPIO_Port, GPIO_LED_Structure);

}
#endif

Implementation of main.c code body

/* 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 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 "bsp_led.h"
/* 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 */

/* USER CODE END PV */

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

/* 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();
  /* USER CODE BEGIN 2 */
  KEY_GPIO_Config();
  LED_GPIO_Config();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	if (GPIO_PIN_SET == KEYScan())
		LED1_ON;
    /* 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_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  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_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @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_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED2_Pin|LED3_Pin|LED1_Pin, GPIO_PIN_SET);

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

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

  /*Configure GPIO pins : LED2_Pin LED3_Pin LED1_Pin */
  GPIO_InitStruct.Pin = LED2_Pin|LED3_Pin|LED1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

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

Standard library development bit band operation

Bit band

Bit band

Bit operation means that a single bit can be read and written. When it is necessary to read and write some bits frequently, it can be easily and conveniently realized through bit operation. However, the addressing ability of Cortex kernel can only reach the byte level. If bit operation is required, it can only be carried out through bit band

The bit band refers to the address area in STM32 where bit operations can be performed. However, the bit operation here does not directly perform bit operation on the address in the bit band, but by accessing the "Avatar" of the bit band area: the bit band alias area

Bit aliased area

The bit band alias area is a special address range serving the bit band area in STM32. All operations in the bit aliased area will be reflected in the bit aliased area

The address area that can realize bit band in STM32 includes two peripheral bit band areas and sRam bit band areas

Peripheral bit band areasRam band
Address range: 0X4000 0000~0X4010 0000Address range: 0X2000 0000~X2010 0000
Size: 1MBSize: 1MB
Peripheral bit alias areasRam bit aliased area
Address range: 0x4200000 ~ 0x43ff ffffAddress range: 0X2200 0000~0X23FF FFFF
Size: 32MBSize: 32MB

Access principle: map each bit [bit] of the bit band area one by one to the 4 bytes [Byte] corresponding to the alias area. The content corresponding to the address of the bit band alias area is LSB, that is, the lowest bit is valid, which means that as long as the lowest bit of the four bytes of the read-write bit band alias area is equivalent to the corresponding bit of the read-write bit band area

Relationship between bit band area and bit band alias area size
Since one bit of the bit band area is mapped to four bytes of the bit band area, and one byte = 8 bits, the size of the bit band area is 32 times that of the bit band area


Why Map 1 bit to 4 bytes
Because the internal data bus of STM32 is 32-bit, the CPU is the most efficient in processing 32-bit data. Therefore, mapping 1 bit to 4 bytes is a method of exchanging space for time. The principle is similar to the member size alignment in the C language structure

Address translation of bit band area and bit band alias area

According to the mapping principle of bit band area and bit band alias area, in order to obtain the nth bit of the byte corresponding to address A in bit band area, the address of bit band alias area is corresponding.

Calculation formula: bit alias area address = (0xF000 000 * a + 0x0200 0000) + (a * 0x00ff ffff * 8 + n) * 4)

  • The first half 0xF000 000 * A + 0x0200 0000: calculates the starting address of the bit aliased area, and determines whether it is the peripheral bit aliased area or the sRam bit aliased area according to the address
  • The second half (A * 0x00FF FFFF * 8 + n) * 4: calculates the offset of bits from the start address of the bit aliased area, (A * 0x00FF FFFF * 8 + n) first calculates the offset of the nth bit of A relative to the start address in bits in the bit band area, and finally * 4 converts this offset into the offset of the corresponding bit aliased area

Turn on the LED lamp through bit band operation

Bit band operation LED function header file BSP_ Implementation of the main body of bitband. H code

/*
 * bsp_bitband.h
 *
 *  Created on: Sep 16, 2021
 *      Author: 67566
 */

#ifndef BSP_BITBAND_H_
#define BSP_BITBAND_H_

#include "stm32f1xx_hal.h"
// Calculate the address of the bit band alias area corresponding to the bit band area
#define BITBAND(addr,bit)   ((addr & 0xF0000000)+0x02000000+((addr & 0x000FFFFF)<<5)+(bit<<2))
// Strong forwarding address, where volatile cannot be omitted, otherwise the compiler will optimize the parameters
#define MEM_ADDR(addr)      (*(volatile unsigned long*)(addr))
#define BIT_ADDR(addr,bit)  MEM_ADDR(BITBAND(addr,bit))
// ODR\IDR address corresponding to GPIO
#define GPIOA_ODR_ADDR      GPIOA_BASE + 0x0c
#define GPIOB_ODR_ADDR      GPIOB_BASE + 0x0c
#define GPIOC_ODR_ADDR      GPIOC_BASE + 0x0c
#define GPIOD_ODR_ADDR      GPIOD_BASE + 0x0c
#define GPIOE_ODR_ADDR      GPIOE_BASE + 0x0c
#define GPIOF_ODR_ADDR      GPIOF_BASE + 0x0c
#define GPIOG_ODR_ADDR      GPIOG_BASE + 0x0c

#define GPIOA_IDR_ADDR      GPIOA_BASE + 0x08
#define GPIOB_IDR_ADDR      GPIOB_BASE + 0x08
#define GPIOC_IDR_ADDR      GPIOC_BASE + 0x08
#define GPIOD_IDR_ADDR      GPIOD_BASE + 0x08
#define GPIOE_IDR_ADDR      GPIOE_BASE + 0x08
#define GPIOF_IDR_ADDR      GPIOF_BASE + 0x08
#define GPIOG_IDR_ADDR      GPIOG_BASE + 0x08
// GPIO pin output \ input
#define GPIOA_OUT(bit)      BIT_ADDR(GPIOA_ODR_ADDR,bit)
#define GPIOA_IN(bit)       BIT_ADDR(GPIOA_IDR_ADDR,bit)

#define GPIOB_OUT(bit)      BIT_ADDR(GPIOB_ODR_ADDR,bit)
#define GPIOB_IN(bit)       BIT_ADDR(GPIOB_IDR_ADDR,bit)

#define GPIOC_OUT(bit)      BIT_ADDR(GPIOC_ODR_ADDR,bit)
#define GPIOC_IN(bit)       BIT_ADDR(GPIOC_IDR_ADDR,bit)

#define GPIOD_OUT(bit)      BIT_ADDR(GPIOD_ODR_ADDR,bit)
#define GPIOD_IN(bit)       BIT_ADDR(GPIOD_IDR_ADDR,bit)

#define GPIOE_OUT(bit)      BIT_ADDR(GPIOE_ODR_ADDR,bit)
#define GPIOE_IN(bit)       BIT_ADDR(GPIOE_IDR_ADDR,bit)

#define GPIOF_OUT(bit)      BIT_ADDR(GPIOF_ODR_ADDR,bit)
#define GPIOF_IN(bit)       BIT_ADDR(GPIOF_IDR_ADDR,bit)

#define GPIOG_OUT(bit)      BIT_ADDR(GPIOG_ODR_ADDR,bit)
#define GPIOG_IN(bit)       BIT_ADDR(GPIOG_IDR_ADDR,bit)

#endif /* BSP_BITBAND_H_ */

Implementation of main.c code body

/* 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 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 "bsp_led.h"
/* 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 */

/* USER CODE END PV */

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

/* 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();
  /* USER CODE BEGIN 2 */
  LED_GPIO_Config();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	GPIOB_OUT(5) = GPIO_PIN_RESET;
    /* 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_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  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_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @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_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED2_Pin|LED3_Pin|LED1_Pin, GPIO_PIN_SET);

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

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

  /*Configure GPIO pins : LED2_Pin LED3_Pin LED1_Pin */
  GPIO_InitStruct.Pin = LED2_Pin|LED3_Pin|LED1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

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

Basic knowledge framework Xmind file download

Link: Resource download

Topics: stm32