基于stm32的嵌入式时间管理系统(半成品)

.ioc

#MicroXplorer Configuration settings - do not modify
File.Version=6
IWDG.IPParameters=Reload
IWDG.Reload=1000
KeepUserPlacement=false
Mcu.Family=STM32F1
Mcu.IP0=IWDG
Mcu.IP1=NVIC
Mcu.IP2=RCC
Mcu.IP3=RTC
Mcu.IP4=SYS
Mcu.IP5=USART1
Mcu.IPNb=6
Mcu.Name=STM32F103C(8-B)Tx
Mcu.Package=LQFP48
Mcu.Pin0=PC14-OSC32_IN
Mcu.Pin1=PC15-OSC32_OUT
Mcu.Pin10=VP_RTC_VS_RTC_Calendar
Mcu.Pin11=VP_RTC_No_RTC_Output
Mcu.Pin12=VP_SYS_VS_Systick
Mcu.Pin2=PD0-OSC_IN
Mcu.Pin3=PD1-OSC_OUT
Mcu.Pin4=PA9
Mcu.Pin5=PA10
Mcu.Pin6=PA13
Mcu.Pin7=PA14
Mcu.Pin8=VP_IWDG_VS_IWDG
Mcu.Pin9=VP_RTC_VS_RTC_Activate
Mcu.PinsNb=13
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F103C8Tx
MxCube.Version=4.26.1
MxDb.Version=DB.4.0.261
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.RTC_Alarm_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false
PA10.Mode=Asynchronous
PA10.Signal=USART1_RX
PA13.Mode=Serial_Wire
PA13.Signal=SYS_JTMS-SWDIO
PA14.Mode=Serial_Wire
PA14.Signal=SYS_JTCK-SWCLK
PA9.Mode=Asynchronous
PA9.Signal=USART1_TX
PC14-OSC32_IN.Mode=LSE-External-Oscillator
PC14-OSC32_IN.Signal=RCC_OSC32_IN
PC15-OSC32_OUT.Mode=LSE-External-Oscillator
PC15-OSC32_OUT.Signal=RCC_OSC32_OUT
PCC.Checker=false
PCC.Line=STM32F103
PCC.MCU=STM32F103C(8-B)Tx
PCC.PartNumber=STM32F103C8Tx
PCC.Seq0=0
PCC.Series=STM32F1
PCC.Temperature=25
PCC.Vdd=3.3
PD0-OSC_IN.Mode=HSE-External-Oscillator
PD0-OSC_IN.Signal=RCC_OSC_IN
PD1-OSC_OUT.Mode=HSE-External-Oscillator
PD1-OSC_OUT.Signal=RCC_OSC_OUT
PinOutPanel.RotationAngle=0
ProjectManager.AskForMigrate=true
ProjectManager.BackupPrevious=false
ProjectManager.CompilerOptimize=6
ProjectManager.ComputerToolchain=false
ProjectManager.CoupleFile=true
ProjectManager.CustomerFirmwarePackage=
ProjectManager.DefaultFWLocation=true
ProjectManager.DeletePrevious=true
ProjectManager.DeviceId=STM32F103C8Tx
ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.6.1
ProjectManager.FreePins=false
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x200
ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=0
ProjectManager.MainLocation=Src
ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=TimeCtrler.ioc
ProjectManager.ProjectName=TimeCtrler
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=MDK-ARM V5
ProjectManager.ToolChainLocation=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USART1_UART_Init-USART1-false-HAL-true,4-MX_RTC_Init-RTC-false-HAL-true,5-MX_IWDG_Init-IWDG-false-HAL-true
RCC.ADCFreqValue=36000000
RCC.AHBFreq_Value=72000000
RCC.APB1CLKDivider=RCC_HCLK_DIV2
RCC.APB1Freq_Value=36000000
RCC.APB1TimFreq_Value=72000000
RCC.APB2Freq_Value=72000000
RCC.APB2TimFreq_Value=72000000
RCC.FCLKCortexFreq_Value=72000000
RCC.FamilyName=M
RCC.HCLKFreq_Value=72000000
RCC.IPParameters=ADCFreqValue,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,PLLSourceVirtual,RTCClockSelection,RTCFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value,VCOOutput2Freq_Value
RCC.MCOFreq_Value=72000000
RCC.PLLCLKFreq_Value=72000000
RCC.PLLMCOFreq_Value=36000000
RCC.PLLMUL=RCC_PLL_MUL9
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
RCC.RTCClockSelection=RCC_RTCCLKSOURCE_LSE
RCC.RTCFreq_Value=32768
RCC.SYSCLKFreq_VALUE=72000000
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
RCC.TimSysFreq_Value=72000000
RCC.USBFreq_Value=72000000
RCC.VCOOutput2Freq_Value=8000000
RTC.Hours=12
RTC.IPParameters=Hours,Minutes,Seconds,WeekDay,Month,Year
RTC.Minutes=59
RTC.Month=RTC_MONTH_DECEMBER
RTC.Seconds=59
RTC.WeekDay=RTC_WEEKDAY_TUESDAY
RTC.Year=20
USART1.IPParameters=VirtualMode
USART1.VirtualMode=VM_ASYNC
VP_IWDG_VS_IWDG.Mode=IWDG_Activate
VP_IWDG_VS_IWDG.Signal=IWDG_VS_IWDG
VP_RTC_No_RTC_Output.Mode=RTC_OUT_NO
VP_RTC_No_RTC_Output.Signal=RTC_No_RTC_Output
VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled
VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate
VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar
VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
board=custom

main.h

/**
  ******************************************************************************
  * @file           : main.h
  * @brief          : Header for main.c file.
  *                   This file contains the common defines of the application.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H__
#define __MAIN_H__

/* Includes ------------------------------------------------------------------*/

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

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

/* ########################## Assert Selection ############################## */
/**
  * @brief Uncomment the line below to expanse the "assert_param" macro in the 
  *        HAL drivers code
  */
/* #define USE_FULL_ASSERT    1U */

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

#ifdef __cplusplus
 extern "C" {
#endif
void _Error_Handler(char *, int);

#define Error_Handler() _Error_Handler(__FILE__, __LINE__)
#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H__ */

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

main.c


/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx_hal.h"
#include "iwdg.h"
#include "rtc.h"
#include "usart.h"
#include "gpio.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

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

  /* USER CODE END 2 */

  /* 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;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE
                              |RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_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(__FILE__, __LINE__);
  }

    /**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(__FILE__, __LINE__);
  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  file: The file name as string.
  * @param  line: The line in file as a number.
  * @retval None
  */
void _Error_Handler(char *file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  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,
     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****/

stm32f1xx_it.c

/**
  ******************************************************************************
  * @file    stm32f1xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  *
  * COPYRIGHT(c) 2020 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "stm32f1xx.h"
#include "stm32f1xx_it.h"

/* USER CODE BEGIN 0 */
#include "sys.h"
#include "timer.h"

/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/
extern RTC_HandleTypeDef hrtc;
extern UART_HandleTypeDef huart1;

/******************************************************************************/
/*            Cortex-M3 Processor Interruption and Exception Handlers         */ 
/******************************************************************************/

/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */

  /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */
	printf("HardFault");
  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
  /* USER CODE BEGIN HardFault_IRQn 1 */

  /* USER CODE END HardFault_IRQn 1 */
}

/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
  /* USER CODE BEGIN MemoryManagement_IRQn 0 */

  /* USER CODE END MemoryManagement_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
    /* USER CODE END W1_MemoryManagement_IRQn 0 */
  }
  /* USER CODE BEGIN MemoryManagement_IRQn 1 */

  /* USER CODE END MemoryManagement_IRQn 1 */
}

/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
  /* USER CODE BEGIN BusFault_IRQn 0 */

  /* USER CODE END BusFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
    /* USER CODE END W1_BusFault_IRQn 0 */
  }
  /* USER CODE BEGIN BusFault_IRQn 1 */

  /* USER CODE END BusFault_IRQn 1 */
}

/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
  /* USER CODE BEGIN UsageFault_IRQn 0 */

  /* USER CODE END UsageFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
    /* USER CODE END W1_UsageFault_IRQn 0 */
  }
  /* USER CODE BEGIN UsageFault_IRQn 1 */

  /* USER CODE END UsageFault_IRQn 1 */
}

/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
  /* USER CODE BEGIN SVCall_IRQn 0 */

  /* USER CODE END SVCall_IRQn 0 */
  /* USER CODE BEGIN SVCall_IRQn 1 */

  /* USER CODE END SVCall_IRQn 1 */
}

/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
  /* USER CODE BEGIN DebugMonitor_IRQn 0 */

  /* USER CODE END DebugMonitor_IRQn 0 */
  /* USER CODE BEGIN DebugMonitor_IRQn 1 */

  /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
  /* USER CODE BEGIN PendSV_IRQn 0 */

  /* USER CODE END PendSV_IRQn 0 */
  /* USER CODE BEGIN PendSV_IRQn 1 */

  /* USER CODE END PendSV_IRQn 1 */
}

/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  HAL_SYSTICK_IRQHandler();
  /* USER CODE BEGIN SysTick_IRQn 1 */
	RA_Task();
	static uint8_t ctr=0;
	if(ctr<(1000/HZ))
	{
		ctr++;
	}
	else
	{
		ctr=0;
		jiffies_64+=1;
		timer_update(&timer_base);
	}
  /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f1xx.s).                    */
/******************************************************************************/

/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

/**
* @brief This function handles RTC alarm interrupt through EXTI line 17.
*/
void RTC_Alarm_IRQHandler(void)
{
  /* USER CODE BEGIN RTC_Alarm_IRQn 0 */

  /* USER CODE END RTC_Alarm_IRQn 0 */
  HAL_RTC_AlarmIRQHandler(&hrtc);
  /* USER CODE BEGIN RTC_Alarm_IRQn 1 */

  /* USER CODE END RTC_Alarm_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

sys.h

#ifndef __SYS_H__
#define __SYS_H__

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "list.h"

#define my_assert_param(expr) ((expr) ? (void)0U : my_assert_failed((uint8_t *)__FILE__, __LINE__))
inline void my_assert_failed(uint8_t* file, uint32_t line)
{ 
  printf("file:%s\r\nline:%d",file,line);
}

typedef void (*VOID_FUNC)(void);	

typedef struct RA
{
	VOID_FUNC func;
	
	uint32_t tickstart;//起始时间
	uint32_t wait_ms;//等待时间
	uint32_t cycle_index;//循环次数
}RA_st;

typedef struct IC
{
	VOID_FUNC func;
	uint32_t cycle_index;//循环次数
}IC_st;

typedef struct IC_Tab
{
	IC_st **IC_table;
	uint8_t tabsize;
	uint8_t counter;//注册个数计数
}IC_Tab_st;

extern HAL_TickFreqTypeDef uwTickFreq;

int8_t Run_Aftertimer_creat(VOID_FUNC func,uint32_t wait_ms,uint8_t index,uint32_t cycle_index);
int8_t Run_Aftertimer_release(uint8_t index);
void RA_Task(void);

int8_t Interrupt_Callback_creat(IC_Tab_st *IC_Tab,VOID_FUNC func,uint8_t index,uint32_t cycle_index);
int8_t Interrupt_Callback_release(IC_Tab_st *IC_Tab,uint8_t index);
int8_t Interrupt_Callback_Tab_creat(IC_Tab_st *IC_Tab,uint8_t tabsize);
int8_t Interrupt_Callback_Tab_release(IC_Tab_st *IC_Tab);
void IC_Task(IC_Tab_st *IC_Tab);

#endif

sys.c

#include "sys.h"
#include <stdlib.h>

/*******************************Run_Aftertimer*********************************/
#define RA_TABLE_SIZE	5
RA_st *RA_table[RA_TABLE_SIZE]={NULL};

int8_t Run_Aftertimer_register(RA_st *ra,uint8_t index)
{
	/*index为0时自动分配index*/
	if(index==0)
	{
		for(int i=1;i<RA_TABLE_SIZE;i++)
		{
			if(RA_table[i]==NULL)
			{
				index=i;
			}
			if(i>=RA_TABLE_SIZE)
			{
				free(ra);
				return -1;
			}
		}
	}
	
	if(RA_table[index]!=NULL)
	{
		free(ra);
		return -1;
	}
	
	RA_table[index]=ra;
	RA_table[index]->tickstart = HAL_GetTick();
	
	/* Add a freq to guarantee minimum wait */
	if (RA_table[index]->wait_ms < HAL_MAX_DELAY)
  {
    RA_table[index]->wait_ms += (uint32_t)(uwTickFreq);
  }
	
	return index;
}

int8_t Run_Aftertimer_creat(VOID_FUNC func,uint32_t wait_ms,uint8_t index,uint32_t cycle_index)
{
	if(RA_table[index]!=NULL)
	{
		return -1;
	}
	RA_st *ra=malloc(sizeof(RA_st));
	ra->func=func;
	ra->wait_ms=wait_ms;
	ra->cycle_index=cycle_index;
	return Run_Aftertimer_register(ra,index);
}

int8_t Run_Aftertimer_release(uint8_t index)
{
	__set_PRIMASK(1);  /* 禁止全局中断*/
	if(RA_table[index]==NULL)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		return -1;
	}
	/*释放内存*/
	free(RA_table[index]);
	RA_table[index]=NULL;
	__set_PRIMASK(0);  /*  使能全局中断 */
	
	return 0;
}

void RA_Task()
{
	for(int i=1;i<RA_TABLE_SIZE;i++)
	{
		if(RA_table[i]==NULL)
			continue;
		
		if ((HAL_GetTick() - RA_table[i]->tickstart) >= RA_table[i]->wait_ms)
		{
			RA_table[i]->func();
			
			if(RA_table[i]->cycle_index==1)
			{
				/*释放内存*/
				free(RA_table[i]);
				RA_table[i]=NULL;
				continue;
			}
			
			RA_table[i]->tickstart = HAL_GetTick();
			if(RA_table[i]->cycle_index!=0)
			{
				RA_table[i]->cycle_index--;
			}
		}
		
	}
}

/*******************************中断任务*********************************/
int8_t Interrupt_Callback_register(IC_Tab_st *IC_Tab,IC_st *ic,uint8_t index)
{
/*错误判断*/
	/*index为0时自动分配index*/
	if(index==0)
	{
		for(int i=1;i<IC_Tab->tabsize;i++)
		{
			if(IC_Tab->IC_table[i]==NULL)
			{
				index=i;
			}
			if(i>=IC_Tab->tabsize)
			{
				free(ic);
				return -1;
			}
		}
	}
	/*该位置已被使用*/
	if(IC_Tab->IC_table[index]!=NULL)
	{
		free(ic);
		return -1;
	}
/*正文*/	
	IC_Tab->counter++;
	IC_Tab->IC_table[index]=ic;
	
	return index;
}

int8_t Interrupt_Callback_creat(IC_Tab_st *IC_Tab,VOID_FUNC func,uint8_t index,uint32_t cycle_index)
{
/*错误判断*/
	/*Tab未创建*/
	if(IC_Tab->IC_table==NULL)
	{
		return -1;
	}
	/*该位置已被使用*/
	if(IC_Tab->IC_table[index]!=NULL)
	{
		return -1;
	}
/*正文*/
	IC_st *ic=malloc(sizeof(IC_st));
	if(ic==NULL)return -1;
	ic->func=func;
	ic->cycle_index=cycle_index;
	
	return Interrupt_Callback_register(IC_Tab,ic,index);
}

int8_t Interrupt_Callback_release(IC_Tab_st *IC_Tab,uint8_t index)
{
	__set_PRIMASK(1);  /* 禁止全局中断*/
/*错误判断*/
	/*该位置为NULL不用释放*/
	if(IC_Tab->IC_table[index]==NULL)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		return -1;
	}
	/*index为0(不支持一次释放全部)*/
	if(index==0)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		return -1;
	}
/*正文*/
	/*释放内存*/
	IC_Tab->counter--;
	free(IC_Tab->IC_table[index]);
	IC_Tab->IC_table[index]=NULL;
	__set_PRIMASK(0);  /*  使能全局中断 */
	
	return 0;
}

int8_t Interrupt_Callback_Tab_creat(IC_Tab_st *IC_Tab,uint8_t tabsize)
{
/*错误判断*/
	/*Tab已经创建*/
	if(IC_Tab->IC_table!=NULL)
	{
		return -1;
	}
	/*tabsize不满足要求*/
	if(tabsize==0)
	{
		return -1;
	}
/*正文*/	
	tabsize+=1;
	IC_Tab->tabsize=tabsize;
	IC_Tab->IC_table=malloc(tabsize*sizeof(IC_st *));
	if(IC_Tab==NULL)return -1;
	
	return tabsize;
}

int8_t Interrupt_Callback_Tab_release(IC_Tab_st *IC_Tab)
{
	__set_PRIMASK(1);  /* 禁止全局中断*/
/*错误判断*/
	/*未创建Tab或重复释放*/
	if(IC_Tab->IC_table==NULL)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		return -1;
	}
	/*Tab中还有未释放的项目*/
	if(IC_Tab->counter!=0)
	{
		__set_PRIMASK(0);  /*  使能全局中断 */
		return -1;
	}
/*正文*/	
	/*释放内存*/
	free(IC_Tab->IC_table);
	IC_Tab->IC_table=NULL;
	IC_Tab->tabsize=0;
	__set_PRIMASK(0);  /*  使能全局中断 */
	
	return 0;
}

void IC_Task(IC_Tab_st *IC_Tab)
{
	for(int i=1;i<IC_Tab->tabsize;i++)
	{
		if(IC_Tab->IC_table[i]==NULL)
			continue;

		IC_Tab->IC_table[i]->func();
		
		if(IC_Tab->IC_table[i]->cycle_index==1)
		{
			/*释放内存*/
			free(IC_Tab->IC_table[i]);
			IC_Tab->IC_table[i]=NULL;
			continue;
		}
		
		if(IC_Tab->IC_table[i]->cycle_index!=0)
		{
			IC_Tab->IC_table[i]->cycle_index--;
		}
	}
}

debug.h

#ifndef _DEBUG_H
#define _DEBUG_H

#include "stdio.h"
#include "stm32f1xx.h"
#include "main.h"
#include "usart.h"

/**
 * @brief DEBUG 常量文本索引
 */
enum DEBUG
{
    DEBUG_TEXT_INFO,                                    /* debug信息 */
    DEBUG_TEXT_CMD_TOO_LONG,                            /* 命令过长 */
    DEBUG_TEXT_BACK,                                    /* 退格 */
    DEBUG_TEXT_INPUT_HEAD,                              /* 输入前置打印 */
    DEBUG_TEXT_HELP,                                    /* help 命令打印 */
    DEBUG_TEXT_CMD_UNKNOWN,                              /* 未知命令类型 */
};

extern uint8_t byTmpData;
extern const char *pDebugText[];

void debug_analyze(void);

#endif /* DEBUG_H */

debug.c

#include "debug.h"
#include "string.h"

#define DEBUG_BUFF_SIZE  36

uint8_t byDebugBuff[DEBUG_BUFF_SIZE];

uint8_t byTmpData;
static uint8_t byCurrentDebugCursor = 0;
int dwTmpPara[6];
int i;

const char *pDebugText[] =
{
//    [DEBUG_TEXT_INFO] = 
        "\r\n======================================================================"
        "\r\n=              (C) COPYRIGHT 2020 STMicroelectronics                 ="
        "\r\n=                                                                    ="
        "\r\n=        STM32F4xx Application For Motion (Version xxxxx)            ="
        "\r\n=                                                                    ="
        "\r\n=                                                  By Alight Team    ="
        "\r\n======================================================================\r\n",
//     [DEBUG_TEXT_CMD_TOO_LONG] = 
    	"\r\nCommand is too long\r\n",
//     [DEBUG_TEXT_BACK] = 
     	"\b \b",
//	 [DEBUG_TEXT_INPUT_HEAD] = 
	 	">",
//	 [DEBUG_TEXT_HELP] = 
	 	"\r\nCommand List :"
	 	"\r\nreboot          reset mcu"
	 	"\r\nsm     step motor control(speed angle break)"
		"\r\npm     push motor control(speed time break)"
	 	"\r\nhelp            show command info\r\n",
//	 [DEBUG_TEXT_CMD_UNKNOWN] =
	 "\r\nCommand unknown\r\n"
};

/*
*********************************************************************************************************
*	函 数 名: debug_analyze
*	功能说明: DEBUG数据解析
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void debug_analyze(void)
{
		if('\b' == byTmpData)
		{
			if(byCurrentDebugCursor <= 0)
			{
				byCurrentDebugCursor = 0;
			}
			else
			{
				printf("%s", pDebugText[DEBUG_TEXT_BACK]);
				byCurrentDebugCursor--;
			}
			return;
		}
	
		if('\r' == byTmpData || '\n' == byTmpData)
		{
			byDebugBuff[byCurrentDebugCursor] = '\0';

			if(0 == byCurrentDebugCursor)
			{
				printf("\r\n");
			}
			else if(strcmp("reboot", (const char *)byDebugBuff) == 0)
			{
				HAL_NVIC_SystemReset();
				printf("\r\nreset mcu\r\n");
			}
			else if(strncmp("sm", (const char *)byDebugBuff,strlen("sm")) == 0)
			{
					sscanf((const char *)byDebugBuff, "sm %d %d %d",&dwTmpPara[0],&dwTmpPara[1],&dwTmpPara[2]);
					printf("\r\n%d,%d,%d\r\n",dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
			}
			else if(strcmp("help", (const char *)byDebugBuff) == 0)
			{
				printf("%s",pDebugText[DEBUG_TEXT_HELP]);
			}
			else
			{
				printf("%s",pDebugText[DEBUG_TEXT_CMD_UNKNOWN]);
			}
			
			byCurrentDebugCursor = 0;
			printf("%s", pDebugText[DEBUG_TEXT_INPUT_HEAD]);
		}
		else
		{
			HAL_UART_Transmit(&huart1,&byTmpData,1,0xff);	
			byDebugBuff[byCurrentDebugCursor] = byTmpData;
			byCurrentDebugCursor++;
			
			if(byCurrentDebugCursor >= DEBUG_BUFF_SIZE)
			{
				byCurrentDebugCursor = 0;
				printf("%s", pDebugText[DEBUG_TEXT_CMD_TOO_LONG]);
				printf("%s", pDebugText[DEBUG_TEXT_INPUT_HEAD]);
			}
		}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  UNUSED(huart);

  debug_analyze();
	
	HAL_UART_Receive_IT(&huart1,&byTmpData,1);
}

/*添加了GNU extensions后会默认定义__GNUC__,使得printf不正确,所以这里去掉该定义*/
#undef __GNUC__
#ifdef __GNUC__
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
	
PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;
}

app.h

#ifndef __APP_H__
#define __APP_H__

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "sys.h"
#include "list.h"
#include "timer.h"

#define READ	0
#define WRITE	1

#define IS_GPOUP(__GROUP__)		((__GROUP__>GROUP_BEGIN)&&(__GROUP__<GROUP_END))
#define IS_TIMING_TYPE(__TYPE__)		((__TYPE__>TIMING_TYPE_BEGIN)&&(__TYPE__<TIMING_TYPE_END))
#define IS_REMIND_TYPE(__TYPE__)		((__TYPE__>REMIND_TYPE_BEGIN)&&(__TYPE__<REMIND_TYPE_END))

/*分组*/
enum group
{
	GROUP_BEGIN,
	
	STUDY,		
	WORK,			
	DRINK,
	PILLS,		//吃药
	
	GROUP_END
};

/*闹钟类型*/
enum timing_type
{
	TIMING_TYPE_BEGIN,
	
	ONCE,		//只响一次
	CYCLE_DAY,		//每天循环
	
	TIMING_TYPE_END
};

/*提醒类型*/
enum remind_type
{
	REMIND_TYPE_BEGIN,
	
	DEBUG,
	BEEP,
	
	REMIND_TYPE_END
};

struct alarm
{
	struct timer_list timer;
	enum timing_type ttype;
	enum remind_type rtype;
	char *info;
	struct list_head node;
};

/*时间段*/
struct time_area
{
	uint32_t start;
	uint32_t end;
};

/*循环模式数据结构*/
struct cycle
{
	uint32_t cycle;		//循环周期
	uint32_t cnt;			//循环内部计数值
	struct time_area ta;
	
};


struct tobject
{
	enum group group;
	enum timing_type type;
	uint32_t moment;
	struct cycle cycle;
	
	struct list_head node;
};

#endif

app.c

#include "app.h"
#include "stdlib.h"
#include "string.h"

#define DEFAULT_GROUP		STUDY
#define DEFAULT_TYPE		MOMENT
#define DEFAULT_MOMENT	10
#define DEFAULT_CYCLE		10

LIST_HEAD(alarm_list);

static void alarm_timer_handler(unsigned long data)
{
	struct alarm *alm=(struct alarm *)data;
	
	switch((uint8_t)alm->rtype)
	{
		case DEBUG:
			printf("%s\r\n",alm->info);
			break;
		case BEEP:
			
			break;
	}
	
	switch((uint8_t)alm->ttype)
	{
		case CYCLE_DAY:
			mod_timer(&(alm->timer),jiffies + 24*60*60*HZ);
			break;
	}
}

int alarm_creat(enum remind_type rtype,enum timing_type ttype,char *info)
{
	struct alarm *alm;
	
	my_assert_param(IS_TIMING_TYPE(ttype));
	
	alm=malloc(sizeof(struct alarm));
	if(alm==NULL)return -1;
	
	alm->rtype=rtype;
	alm->ttype=ttype;
	alm->info=info;
	init_timer(&(alm->timer));
	alm->timer.function = alarm_timer_handler;
	alm->timer.expires = jiffies + HZ;
	alm->timer.data=(unsigned long)alm;
	add_timer(&(alm->timer));
	
	list_add_tail(&(alm->node),&(alarm_list));
}

void alarm_delete(struct alarm *alm)
{
	del_timer(&(alm->timer));
	list_del(&(alm->node));
	free(alm);
}

void alarm_setup(struct alarm *alm)
{
	
}

timer.h

#ifndef _LINUX_TIMER_H
#define _LINUX_TIMER_H

#include "list.h"
#include "typecheck.h"

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"

#define HZ	100

#define time_after(a,b)		\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)(b) - (long)(a) < 0))
#define time_before(a,b)	time_after(b,a)

#define time_after_eq(a,b)	\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)(a) - (long)(b) >= 0))
#define time_before_eq(a,b)	time_after_eq(b,a)

#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)

#define CONFIG_BASE_SMALL 0
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)

struct timer_list {
	struct list_head entry;//用于把一组定时器组成一个链表
	unsigned long expires;//指出了该定时器的到期时刻,也就是期望定时器到期时刻的jiffies计数值
	struct tvec_base *base;//每个cpu拥有一个自己的用于管理定时器的tvec_base结构,该字段指向该定时器所属的cpu所对应tvec_base结构
	void (*function)(unsigned long);//指向一个可执行函数。当定时器到期时,内核就执行function所指定的函数
	unsigned long data;//data域则被内核用作function函数的调用参数
};

struct tvec {
	struct list_head vec[TVN_SIZE];
};

struct tvec_root {
	struct list_head vec[TVR_SIZE];
};

struct tvec_base {
	//spinlock_t lock;
	struct timer_list *running_timer;//指向当前cpu正在处理的定时器所对应的timer_list结构
	unsigned long timer_jiffies;//表示当前cpu定时器所经历过的jiffies数,大多数情况下,该值和jiffies计数值相等,当cpu的idle状态连续持续了多个jiffies时间时,当退出idle状态时,jiffies计数值就会大于该字段,在接下来的tick中断后,定时器系统会让该字段的值追赶上jiffies值
	unsigned long next_timer;//指向该cpu下一个即将到期的定时器
	struct tvec_root tv1;
	struct tvec tv2;
	struct tvec tv3;
	struct tvec tv4;
	struct tvec tv5;
};
	 
#define TIMER_INITIALIZER(_function, _expires, _data) {.entry = { .prev = NULL },.function = _function,.expires = _expires,.data = _data,.base = &timer_base}
#define DEFINE_TIMER(_name, _function, _expires, _data) struct timer_list _name = TIMER_INITIALIZER(_function, _expires, _data)

static inline void set_running_timer(struct tvec_base *base,
					struct timer_list *timer)
{
	base->running_timer = timer;
}

static inline void detach_timer(struct timer_list *timer,
				int clear_pending)
{
	struct list_head *entry = &timer->entry;

	//debug_deactivate(timer);

	__list_del(entry->prev, entry->next);
	if (clear_pending)
		entry->next = NULL;
	entry->prev = LIST_POISON2;
}

#define jiffies		*pjiffies
extern unsigned long jiffies;
extern uint64_t jiffies_64;
extern uint32_t sys_start_rtc_time;

extern struct tvec_base timer_base;

void init_timers(void);
void timer_update(struct tvec_base *base);

#define init_timer(timer)\
	init_timer_key((timer), NULL)
void init_timer_key(struct timer_list *timer,
		    const char *name);
int mod_timer(struct timer_list *timer, unsigned long expires);
void add_timer(struct timer_list *timer);
int del_timer(struct timer_list * timer);

static inline void setup_timer_key(struct timer_list * timer,
				const char *name,
				void (*function)(unsigned long),
				unsigned long data)
{
	timer->function = function;
	timer->data = data;
	init_timer_key(timer, name);
}
#define setup_timer(timer, fn, data)\
	setup_timer_key((timer), NULL, (fn), (data))

#endif

timer.c

/*默认情况下,没有使能CONFIG_BASE_SMALL,TVR_SIZE的大小是256,TVN_SIZE的大小则是64,当需要节省内存空间时,也可以使能CONFIG_BASE_SMALL,这时TVR_SIZE的大小是64,TVN_SIZE的大小则是16,以下的讨论我都是基于没有使能CONFIG_BASE_SMALL的情况。当有一个新的定时器要加入时,系统根据定时器到期的jiffies值和timer_jiffies字段的差值来决定该定时器被放入tv1至tv5中的哪一个数组中*/
#include "timer.h"
#include "rtc.h"

#ifndef __ARMEB__
unsigned long *pjiffies=((unsigned long *)(&jiffies_64));
#else
unsigned long *pjiffies=((unsigned long *)(&jiffies_64))+4;
#endif

uint64_t jiffies_64=0;
struct tvec_base timer_base;

uint32_t sys_start_rtc_time;
static struct timer_list rtc_timer;

/**
  * @brief  Read the time counter available in RTC_CNT registers.
  * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
  *                the configuration information for RTC.
  * @retval Time counter
  */
static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc)
{
  uint16_t high1 = 0U, high2 = 0U, low = 0U;
  uint32_t timecounter = 0U;

  high1 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
  low   = READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT);
  high2 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);

  if (high1 != high2)
  { /* In this case the counter roll over during reading of CNTL and CNTH registers, 
       read again CNTL register then return the counter value */
    timecounter = (((uint32_t) high2 << 16U) | READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT));
  }
  else
  { /* No counter roll over during reading of CNTL and CNTH registers, counter 
       value is equal to first value of CNTL and CNTH */
    timecounter = (((uint32_t) high1 << 16U) | low);
  }

  return timecounter;
}

void init_timers()
{
	//读取RTC
	sys_start_rtc_time=RTC_ReadTimeCounter(&hrtc);
	
	for(int i=0;i<TVR_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv1.vec[i]));
	}
	for(int i=0;i<TVN_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv2.vec[i]));
	}
	for(int i=0;i<TVN_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv3.vec[i]));
	}
	for(int i=0;i<TVN_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv4.vec[i]));
	}
	for(int i=0;i<TVN_SIZE;i++)
	{
		INIT_LIST_HEAD(&(timer_base.tv5.vec[i]));
	}
}

static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
			  unsigned long data)
{
	fn(data);
}

//确定要插入的链表数组以及数组的哪一项链表中
static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
{
	unsigned long expires = timer->expires;
	unsigned long idx = expires - base->timer_jiffies;//也即timer->expires-base->timer_jiffies,差值范围可以大致判断属于哪一个分组
	struct list_head *vec;

	if (idx < TVR_SIZE) {																													//tv1
		int i = expires & TVR_MASK;
		vec = base->tv1.vec + i;
	} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {																//tv2
		int i = (expires >> TVR_BITS) & TVN_MASK;
		vec = base->tv2.vec + i;
	} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {														//tv3
		int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
		vec = base->tv3.vec + i;
	} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {														//tv4
		int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
		vec = base->tv4.vec + i;
	} else if ((signed long) idx < 0) {//异常处理,随机取了一个0~255之间的数值
		/*
		 * Can happen if you add a timer with expires == jiffies,
		 * or you set a timer to go off in the past
		 */
		vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
	} else {
		int i;
		/* If the timeout is larger than 0xffffffff on 64-bit
		 * architectures then we use the maximum timeout:
		 */
		if (idx > 0xffffffffUL) {
			idx = 0xffffffffUL;
			expires = idx + base->timer_jiffies;
		}
		i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
		vec = base->tv5.vec + i;																											//tv5
	}
	/*
	 * Timers are FIFO:
	 */
	list_add_tail(&timer->entry, vec);//相同vec的timer采取FIFO策略
}

//定时器的到期时的迁移代码
//参数index为事先计算好的高一级tv的需要迁移的数组索引
static int cascade(struct tvec_base *base, struct tvec *tv, int index)
{
	/* cascade all the timers from tv up one level */
	struct timer_list *timer, *tmp;
	struct list_head tv_list;

	list_replace_init(tv->vec + index, &tv_list);//用tv_list替换tv->vec+index表头,将tv->vec+index重新初始化,即为空,链表不会有timer存在。

	/*
	 * We are removing _all_ timers from the list, so we
	 * don't have to detach them individually.
	 */
	list_for_each_entry_safe(timer, tmp, &tv_list, entry) {//遍历刚取出的tv_list里的timer
		//BUG_ON(tbase_get_base(timer->base) != base);
		internal_add_timer(base, timer);//重新加入到定时器系统中,实际上将会迁移到下一级的tv数组中
	}

	return index;
}

static inline void __run_timers(struct tvec_base *base)
{
	struct timer_list *timer;

	//spin_lock_irq(&base->lock);
	while (time_after_eq(jiffies, base->timer_jiffies)) {//同步jiffies,在NO_HZ情况下,base->timer_jiffies可能落后不止一个tick
		struct list_head work_list;
		struct list_head *head = &work_list;
		int index = base->timer_jiffies & TVR_MASK;//计算到期定时器链表在tv1中的索引

		/*
		 * Cascade timers:
		 */
		if (!index &&																				//index为0时,表示有进位到tv2
			(!cascade(base, &(base->tv2), INDEX(0))) &&					//返回为0时,表示有进位到tv3
				(!cascade(base, &(base->tv3), INDEX(1))) &&				//返回为0时,表示有进位到tv4
					!cascade(base, &(base->tv4), INDEX(2)))					//返回为0时,表示有进位到tv5
			cascade(base, &(base->tv5), INDEX(3));							//从低位到高位逐级进位的迁移,在进位时将高位timer_list插入到低位
		
		++base->timer_jiffies;//该cpu定时器系统运行时间递增一个tick
		list_replace_init(base->tv1.vec + index, &work_list);//取出到期的定时器链表
		
		while (!list_empty(head)) {//遍历所有的到期定时器
			void (*fn)(unsigned long);
			unsigned long data;

			timer = list_first_entry(head, struct timer_list,entry);
			fn = timer->function;
			data = timer->data;

			set_running_timer(base, timer);//标记正在处理的定时器
			detach_timer(timer, 1);

			//spin_unlock_irq(&base->lock);
			call_timer_fn(timer, fn, data);//调用定时器的回调函数
			//spin_lock_irq(&base->lock);
		}
	}
	set_running_timer(base, NULL);
	//spin_unlock_irq(&base->lock);
}

void timer_update(struct tvec_base *base)
{
	if (time_after_eq(jiffies, base->timer_jiffies)) 
			__run_timers(base); 
}

static void __init_timer(struct timer_list *timer,
			 const char *name)
{
	timer->entry.next = NULL;
	timer->base = &timer_base;
}

void init_timer_key(struct timer_list *timer,
		    const char *name)
{
	__init_timer(timer, name);
}

static inline int timer_pending(const struct timer_list * timer)
{
	return timer->entry.next != NULL;
}

static inline int
__mod_timer(struct timer_list *timer, unsigned long expires)
{
	struct tvec_base *base;
	int ret = 0;

	base=timer->base;
	
	if (timer_pending(timer)) {
		detach_timer(timer, 0);
		if (timer->expires == base->next_timer)
			base->next_timer = base->timer_jiffies;
		ret = 1;
	} else {}

	timer->expires = expires;
	if (time_before(timer->expires, base->next_timer))
		base->next_timer = timer->expires;
	internal_add_timer(base, timer);

	return ret;
}

int mod_timer(struct timer_list *timer, unsigned long expires)
{
	/*
	 * This is a common optimization triggered by the
	 * networking code - if the timer is re-modified
	 * to be the same thing then just return:
	 */
	if (timer_pending(timer) && timer->expires == expires)
		return 1;

	return __mod_timer(timer, expires);
}

void add_timer(struct timer_list *timer)
{
	mod_timer(timer, timer->expires);
}

/**
 * del_timer - deactive a timer.
 * @timer: the timer to be deactivated
 *
 * del_timer() deactivates a timer - this works on both active and inactive
 * timers.
 *
 * The function returns whether it has deactivated a pending timer or not.
 * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
 * active timer returns 1.)
 */
int del_timer(struct timer_list *timer)
{
	struct tvec_base *base;
	int ret = 0;

	if (timer_pending(timer)) {
		detach_timer(timer, 1);
		if (timer->expires == base->next_timer)
			base->next_timer = base->timer_jiffies;
		ret = 1;
	}

	return ret;
}

list.h

/*此代码移植自linux kernel*/
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H

#include "mytype.h"

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"

#define LIST_POISON1  NULL
#define LIST_POISON2  NULL

#define prefetch(x)		x

/*
 * Simple doubly linked list implementation.
 *
 * Some of the internal functions ("__xxx") are useful when
 * manipulating whole lists rather than single entries, as
 * sometimes we already know the next/prev entries and we can
 * generate better code by using them directly rather than
 * using the generic single-entry routines.
 */

struct list_head {
	struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
	list->next = list;
	list->prev = list;
}

/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next);
#endif

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *new, struct list_head *head)
{
	__list_add(new, head, head->next);
}


/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);
}

/*
 * Delete a list entry by making the prev/next entries
 * point to each other.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
	next->prev = prev;
	prev->next = next;
}

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty() on entry does not return true after this, the entry is
 * in an undefined state.
 */
#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	entry->next = LIST_POISON1;
	entry->prev = LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif

/**
 * list_replace - replace old entry by new one
 * @old : the element to be replaced
 * @new : the new element to insert
 *
 * If @old was empty, it will be overwritten.
 */
static inline void list_replace(struct list_head *old,
				struct list_head *new)
{
	new->next = old->next;
	new->next->prev = new;
	new->prev = old->prev;
	new->prev->next = new;
}

static inline void list_replace_init(struct list_head *old,
					struct list_head *new)
{
	list_replace(old, new);
	INIT_LIST_HEAD(old);
}

/**
 * list_del_init - deletes entry from list and reinitialize it.
 * @entry: the element to delete from the list.
 */
static inline void list_del_init(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	INIT_LIST_HEAD(entry);
}

/**
 * list_move - delete from one list and add as another's head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static inline void list_move(struct list_head *list, struct list_head *head)
{
	__list_del(list->prev, list->next);
	list_add(list, head);
}

/**
 * list_move_tail - delete from one list and add as another's tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static inline void list_move_tail(struct list_head *list,
				  struct list_head *head)
{
	__list_del(list->prev, list->next);
	list_add_tail(list, head);
}

/**
 * list_is_last - tests whether @list is the last entry in list @head
 * @list: the entry to test
 * @head: the head of the list
 */
static inline int list_is_last(const struct list_head *list,
				const struct list_head *head)
{
	return list->next == head;
}

/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(const struct list_head *head)
{
	return head->next == head;
}

/**
 * list_empty_careful - tests whether a list is empty and not being modified
 * @head: the list to test
 *
 * Description:
 * tests whether a list is empty _and_ checks that no other CPU might be
 * in the process of modifying either member (next or prev)
 *
 * NOTE: using list_empty_careful() without synchronization
 * can only be safe if the only activity that can happen
 * to the list entry is list_del_init(). Eg. it cannot be used
 * if another CPU could re-list_add() it.
 */
static inline int list_empty_careful(const struct list_head *head)
{
	struct list_head *next = head->next;
	return (next == head) && (next == head->prev);
}

/**
 * list_rotate_left - rotate the list to the left
 * @head: the head of the list
 */
static inline void list_rotate_left(struct list_head *head)
{
	struct list_head *first;

	if (!list_empty(head)) {
		first = head->next;
		list_move_tail(first, head);
	}
}

/**
 * list_is_singular - tests whether a list has just one entry.
 * @head: the list to test.
 */
static inline int list_is_singular(const struct list_head *head)
{
	return !list_empty(head) && (head->next == head->prev);
}

static inline void __list_cut_position(struct list_head *list,
		struct list_head *head, struct list_head *entry)
{
	struct list_head *new_first = entry->next;
	list->next = head->next;
	list->next->prev = list;
	list->prev = entry;
	entry->next = list;
	head->next = new_first;
	new_first->prev = head;
}

/**
 * list_cut_position - cut a list into two
 * @list: a new list to add all removed entries
 * @head: a list with entries
 * @entry: an entry within head, could be the head itself
 *	and if so we won't cut the list
 *
 * This helper moves the initial part of @head, up to and
 * including @entry, from @head to @list. You should
 * pass on @entry an element you know is on @head. @list
 * should be an empty list or a list you do not care about
 * losing its data.
 *
 */
static inline void list_cut_position(struct list_head *list,
		struct list_head *head, struct list_head *entry)
{
	if (list_empty(head))
		return;
	if (list_is_singular(head) &&
		(head->next != entry && head != entry))
		return;
	if (entry == head)
		INIT_LIST_HEAD(list);
	else
		__list_cut_position(list, head, entry);
}

static inline void __list_splice(const struct list_head *list,
				 struct list_head *prev,
				 struct list_head *next)
{
	struct list_head *first = list->next;
	struct list_head *last = list->prev;

	first->prev = prev;
	prev->next = first;

	last->next = next;
	next->prev = last;
}

/**
 * list_splice - join two lists, this is designed for stacks
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(const struct list_head *list,
				struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head, head->next);
}

/**
 * list_splice_tail - join two lists, each list being a queue
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice_tail(struct list_head *list,
				struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head->prev, head);
}

/**
 * list_splice_init - join two lists and reinitialise the emptied list.
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * The list at @list is reinitialised
 */
static inline void list_splice_init(struct list_head *list,
				    struct list_head *head)
{
	if (!list_empty(list)) {
		__list_splice(list, head, head->next);
		INIT_LIST_HEAD(list);
	}
}

/**
 * list_splice_tail_init - join two lists and reinitialise the emptied list
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * Each of the lists is a queue.
 * The list at @list is reinitialised
 */
static inline void list_splice_tail_init(struct list_head *list,
					 struct list_head *head)
{
	if (!list_empty(list)) {
		__list_splice(list, head->prev, head);
		INIT_LIST_HEAD(list);
	}
}

/**
 * list_entry - get the struct for this entry
 * @ptr:	the &struct list_head pointer.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member) \
	container_of(ptr, type, member)

/**
 * list_first_entry - get the first element from a list
 * @ptr:	the list head to take the element from.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_struct within the struct.
 *
 * Note, that list is expected to be not empty.
 */
#define list_first_entry(ptr, type, member) \
	list_entry((ptr)->next, type, member)

/**
 * list_for_each	-	iterate over a list
 * @pos:	the &struct list_head to use as a loop cursor.
 * @head:	the head for your list.
 */
#define list_for_each(pos, head) \
	for (pos = (head)->next; prefetch(pos->next), pos != (head); \
        	pos = pos->next)

/**
 * __list_for_each	-	iterate over a list
 * @pos:	the &struct list_head to use as a loop cursor.
 * @head:	the head for your list.
 *
 * This variant differs from list_for_each() in that it's the
 * simplest possible list iteration code, no prefetching is done.
 * Use this for code that knows the list to be very short (empty
 * or 1 entry) most of the time.
 */
#define __list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); pos = pos->next)

/**
 * list_for_each_prev	-	iterate over a list backwards
 * @pos:	the &struct list_head to use as a loop cursor.
 * @head:	the head for your list.
 */
#define list_for_each_prev(pos, head) \
	for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
        	pos = pos->prev)

/**
 * list_for_each_safe - iterate over a list safe against removal of list entry
 * @pos:	the &struct list_head to use as a loop cursor.
 * @n:		another &struct list_head to use as temporary storage
 * @head:	the head for your list.
 */
#define list_for_each_safe(pos, n, head) \
	for (pos = (head)->next, n = pos->next; pos != (head); \
		pos = n, n = pos->next)

/**
 * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
 * @pos:	the &struct list_head to use as a loop cursor.
 * @n:		another &struct list_head to use as temporary storage
 * @head:	the head for your list.
 */
#define list_for_each_prev_safe(pos, n, head) \
	for (pos = (head)->prev, n = pos->prev; \
	     prefetch(pos->prev), pos != (head); \
	     pos = n, n = pos->prev)

/**
 * list_for_each_entry	-	iterate over list of given type
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member)				\
	for (pos = list_entry((head)->next, typeof(*pos), member);	\
	     prefetch(pos->member.next), &pos->member != (head); 	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

/**
 * list_for_each_entry_reverse - iterate backwards over list of given type.
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry_reverse(pos, head, member)			\
	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
	     prefetch(pos->member.prev), &pos->member != (head); 	\
	     pos = list_entry(pos->member.prev, typeof(*pos), member))

/**
 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
 * @pos:	the type * to use as a start point
 * @head:	the head of the list
 * @member:	the name of the list_struct within the struct.
 *
 * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
 */
#define list_prepare_entry(pos, head, member) \
	((pos) ? : list_entry(head, typeof(*pos), member))

/**
 * list_for_each_entry_continue - continue iteration over list of given type
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Continue to iterate over list of given type, continuing after
 * the current position.
 */
#define list_for_each_entry_continue(pos, head, member) 		\
	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
	     prefetch(pos->member.next), &pos->member != (head);	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

/**
 * list_for_each_entry_continue_reverse - iterate backwards from the given point
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Start to iterate over list of given type backwards, continuing after
 * the current position.
 */
#define list_for_each_entry_continue_reverse(pos, head, member)		\
	for (pos = list_entry(pos->member.prev, typeof(*pos), member);	\
	     prefetch(pos->member.prev), &pos->member != (head);	\
	     pos = list_entry(pos->member.prev, typeof(*pos), member))

/**
 * list_for_each_entry_from - iterate over list of given type from the current point
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Iterate over list of given type, continuing from current position.
 */
#define list_for_each_entry_from(pos, head, member) 			\
	for (; prefetch(pos->member.next), &pos->member != (head);	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

/**
 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member)			\
	for (pos = list_entry((head)->next, typeof(*pos), member),	\
		n = list_entry(pos->member.next, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
 * list_for_each_entry_safe_continue - continue list iteration safe against removal
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Iterate over list of given type, continuing after current point,
 * safe against removal of list entry.
 */
#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
		n = list_entry(pos->member.next, typeof(*pos), member);		\
	     &pos->member != (head);						\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
 * list_for_each_entry_safe_from - iterate over list from current point safe against removal
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Iterate over list of given type from current point, safe against
 * removal of list entry.
 */
#define list_for_each_entry_safe_from(pos, n, head, member) 			\
	for (n = list_entry(pos->member.next, typeof(*pos), member);		\
	     &pos->member != (head);						\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
 * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 *
 * Iterate backwards over list of given type, safe against removal
 * of list entry.
 */
#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
		n = list_entry(pos->member.prev, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))

/**
 * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
 * @pos:	the loop cursor used in the list_for_each_entry_safe loop
 * @n:		temporary storage used in list_for_each_entry_safe
 * @member:	the name of the list_struct within the struct.
 *
 * list_safe_reset_next is not safe to use in general if the list may be
 * modified concurrently (eg. the lock is dropped in the loop body). An
 * exception to this is if the cursor element (pos) is pinned in the list,
 * and list_safe_reset_next is called after re-taking the lock and before
 * completing the current iteration of the loop body.
 */
#define list_safe_reset_next(pos, n, member)				\
	n = list_entry(pos->member.next, typeof(*pos), member)

/*
 * Double linked lists with a single pointer list head.
 * Mostly useful for hash tables where the two pointer list head is
 * too wasteful.
 * You lose the ability to access the tail in O(1).
 */

struct hlist_head {
	struct hlist_node *first;
};

struct hlist_node {
	struct hlist_node *next, **pprev;
};

#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
	h->next = NULL;
	h->pprev = NULL;
}

static inline int hlist_unhashed(const struct hlist_node *h)
{
	return !h->pprev;
}

static inline int hlist_empty(const struct hlist_head *h)
{
	return !h->first;
}

static inline void __hlist_del(struct hlist_node *n)
{
	struct hlist_node *next = n->next;
	struct hlist_node **pprev = n->pprev;
	*pprev = next;
	if (next)
		next->pprev = pprev;
}

static inline void hlist_del(struct hlist_node *n)
{
	__hlist_del(n);
	n->next = LIST_POISON1;
	n->pprev = LIST_POISON2;
}

static inline void hlist_del_init(struct hlist_node *n)
{
	if (!hlist_unhashed(n)) {
		__hlist_del(n);
		INIT_HLIST_NODE(n);
	}
}

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
	struct hlist_node *first = h->first;
	n->next = first;
	if (first)
		first->pprev = &n->next;
	h->first = n;
	n->pprev = &h->first;
}

/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
					struct hlist_node *next)
{
	n->pprev = next->pprev;
	n->next = next;
	next->pprev = &n->next;
	*(n->pprev) = n;
}

static inline void hlist_add_after(struct hlist_node *n,
					struct hlist_node *next)
{
	next->next = n->next;
	n->next = next;
	next->pprev = &n->next;

	if(next->next)
		next->next->pprev  = &next->next;
}

/*
 * Move a list from one list head to another. Fixup the pprev
 * reference of the first entry if it exists.
 */
static inline void hlist_move_list(struct hlist_head *old,
				   struct hlist_head *new)
{
	new->first = old->first;
	if (new->first)
		new->first->pprev = &new->first;
	old->first = NULL;
}

#define hlist_entry(ptr, type, member) container_of(ptr,type,member)

#define hlist_for_each(pos, head) \
	for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
	     pos = pos->next)

#define hlist_for_each_safe(pos, n, head) \
	for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
	     pos = n)

/**
 * hlist_for_each_entry	- iterate over list of given type
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry(tpos, pos, head, member)			 \
	for (pos = (head)->first;					 \
	     pos && ({ prefetch(pos->next); 1;}) &&			 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
	     pos = pos->next)

/**
 * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @member:	the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_continue(tpos, pos, member)		 \
	for (pos = (pos)->next;						 \
	     pos && ({ prefetch(pos->next); 1;}) &&			 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
	     pos = pos->next)

/**
 * hlist_for_each_entry_from - iterate over a hlist continuing from current point
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @member:	the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_from(tpos, pos, member)			 \
	for (; pos && ({ prefetch(pos->next); 1;}) &&			 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
	     pos = pos->next)

/**
 * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @n:		another &struct hlist_node to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) 		 \
	for (pos = (head)->first;					 \
	     pos && ({ n = pos->next; 1; }) && 				 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
	     pos = n)

#endif

mytype.h

#ifndef __MYTYPE_H__
#define __MYTYPE_H__

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})

#endif

typecheck.h

#ifndef TYPECHECK_H_INCLUDED
#define TYPECHECK_H_INCLUDED

/*
 * Check at compile time that something is of a particular type.
 * Always evaluates to 1 so you may use it easily in comparisons.
 */
#define typecheck(type,x) \
({	type __dummy; \
	typeof(x) __dummy2; \
	(void)(&__dummy == &__dummy2); \
	1; \
})

/*
 * Check at compile time that 'function' is a certain type, or is a pointer
 * to that type (needs to use typedef for the function type.)
 */
#define typecheck_fn(type,function) \
({	typeof(type) __tmp = function; \
	(void)__tmp; \
})

#endif		/* TYPECHECK_H_INCLUDED */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值