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 ------------------------------------------------------------*/
#define PushMotorPWM_Pin GPIO_PIN_0
#define PushMotorPWM_GPIO_Port GPIOA
#define PushMotorIN1_Pin GPIO_PIN_1
#define PushMotorIN1_GPIO_Port GPIOA
#define PushMotorIN2_Pin GPIO_PIN_2
#define PushMotorIN2_GPIO_Port GPIOA
#define Knob3_1_Pin GPIO_PIN_5
#define Knob3_1_GPIO_Port GPIOA
#define Knob3_2_Pin GPIO_PIN_6
#define Knob3_2_GPIO_Port GPIOA
#define Knob3_3_Pin GPIO_PIN_7
#define Knob3_3_GPIO_Port GPIOA
#define StepMotorPul_Pin GPIO_PIN_0
#define StepMotorPul_GPIO_Port GPIOB
#define StepMotorDir_Pin GPIO_PIN_1
#define StepMotorDir_GPIO_Port GPIOB
#define StepMotorEna_Pin GPIO_PIN_2
#define StepMotorEna_GPIO_Port GPIOB
#define LED_RED_Pin GPIO_PIN_11
#define LED_RED_GPIO_Port GPIOB
#define LED_GREEN_Pin GPIO_PIN_12
#define LED_GREEN_GPIO_Port GPIOB
#define PushMotor2IN1_Pin GPIO_PIN_13
#define PushMotor2IN1_GPIO_Port GPIOB
#define PushMotor2IN2_Pin GPIO_PIN_14
#define PushMotor2IN2_GPIO_Port GPIOB
#define PushMotor2PWM_Pin GPIO_PIN_8
#define PushMotor2PWM_GPIO_Port GPIOA
#define Proximity1_Pin GPIO_PIN_5
#define Proximity1_GPIO_Port GPIOB
#define Proximity1_EXTI_IRQn EXTI9_5_IRQn
#define proximity2_Pin GPIO_PIN_6
#define proximity2_GPIO_Port GPIOB
#define proximity2_EXTI_IRQn EXTI9_5_IRQn
#define Switch_Pin GPIO_PIN_7
#define Switch_GPIO_Port GPIOB
#define Switch_EXTI_IRQn EXTI9_5_IRQn
/* ########################## 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 "tim.h"
#include "usart.h"
#include "gpio.h"
/* USER CODE BEGIN Includes */
#include "StepMotor.h"
#include "debug.h"
#include "app.h"
#include "sys.h"
#include "mytype.h"
#include "list.h"
/* 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 */
void LED_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, LED_RED_Pin|LED_GREEN_Pin, GPIO_PIN_SET);
/*Configure GPIO pins : PBPin PBPin */
GPIO_InitStruct.Pin = LED_RED_Pin|LED_GREEN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* 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 */
LED_GPIO_Init();
for(int i=0;i<15;i++)
{
LED_Toggel(-1);
HAL_Delay(100);
}
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
//MX_IWDG_Init();
MX_TIM4_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
printf("start\r\n");
HAL_UART_Receive_IT(&huart1,&byTmpData,1);
//App1_Func();
switch(Get_Mod())
{
case 1:
printf("mod1\r\n");
App1_Func();
break;
case 2:
printf("mod2\r\n");
App2_Func();
break;
case 3:
printf("mod3\r\n");
App3_Func();
break;
default:
printf("moderr\r\n");
break;
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(10);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
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__);
}
/**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****/
PushMotor.h
#ifndef __PUSHMOTOR_H__
#define __PUSHMOTOR_H__
#include "stm32f1xx.h"
#include "main.h"
#include "tim.h"
#define PUSHMOTORPER_10US 10
extern uint16_t PushMotor_10us;
extern volatile uint32_t PM_Max_Counter;
extern volatile uint32_t PM_Counter;
extern uint16_t PushMotor2_10us;
extern volatile uint32_t PM2_Max_Counter;
extern volatile uint32_t PM2_Counter;
int8_t PushMotor_Control(int8_t speed,uint32_t time_off,uint8_t flag_break);
int8_t PushMotor2_Control(int8_t speed,uint32_t time_off,uint8_t flag_break);
void PushMotor1_irq_cb(void);
void PushMotor2_irq_cb(void);
#endif
PushMotor.c
#include "PushMotor.h"
#include "debug.h"
#define PushMotor2TIM TIM1
#define PushMotorTIM TIM2
uint16_t PushMotor_10us=0;
volatile uint32_t PM_Max_Counter=0;
volatile uint32_t PM_Counter=0;
uint16_t PushMotor2_10us=0;
volatile uint32_t PM2_Max_Counter=0;
volatile uint32_t PM2_Counter=0;
/*推杆电机控制函数
speed:速度
0 锁死
正数
负数
timout:运动时间
*/
int8_t PushMotor_Control(int8_t speed,uint32_t time_off,uint8_t flag_break)
{
/*判断是否需要打断之前的运行*/
if(flag_break!=0)//打断当前运行
{
debug("打断\r\n");
}
else
{
if(PushMotor_10us!=0)//电机正在运行
{
debug("定时器正在运行\r\n");
return -1;
}
else
{
}
}
/*需要打断或者上次运行已经结束*/
PushMotor_10us=speed<0?0-speed:speed;
if(speed<0)
{
HAL_GPIO_WritePin(PushMotorIN1_GPIO_Port,PushMotorIN1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(PushMotorIN2_GPIO_Port,PushMotorIN2_Pin,GPIO_PIN_RESET);
}
else if(speed>0)
{
HAL_GPIO_WritePin(PushMotorIN1_GPIO_Port,PushMotorIN1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(PushMotorIN2_GPIO_Port,PushMotorIN2_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(PushMotorIN1_GPIO_Port,PushMotorIN1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(PushMotorIN2_GPIO_Port,PushMotorIN2_Pin,GPIO_PIN_RESET);
HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
return 0;
}
PushMotorTIM->CNT=0;
PushMotorTIM->CCR1=PushMotor_10us;
/*转动时间控制,当time_off为0时一直转动*/
PushMotorTIM->SR&=0x00;
if(time_off==0)
{
debug("时间为0\r\n");
PushMotorTIM->DIER&=0x00;
}
else
{
PM_Counter=0;
PM_Max_Counter=time_off;
PushMotorTIM->DIER|=0x01;
}
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
return 0;
}
int8_t PushMotor2_Control(int8_t speed,uint32_t time_off,uint8_t flag_break)
{
/*判断是否需要打断之前的运行*/
if(flag_break!=0)//打断当前运行
{
debug("打断\r\n");
}
else
{
if(PushMotor2_10us!=0)//电机正在运行
{
debug("定时器正在运行\r\n");
return -1;
}
else
{
}
}
/*需要打断或者上次运行已经结束*/
PushMotor2_10us=speed<0?0-speed:speed;
if(speed<0)
{
HAL_GPIO_WritePin(PushMotor2IN1_GPIO_Port,PushMotor2IN1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(PushMotor2IN2_GPIO_Port,PushMotor2IN2_Pin,GPIO_PIN_RESET);
}
else if(speed>0)
{
HAL_GPIO_WritePin(PushMotor2IN1_GPIO_Port,PushMotor2IN1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(PushMotor2IN2_GPIO_Port,PushMotor2IN2_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(PushMotor2IN1_GPIO_Port,PushMotor2IN1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(PushMotor2IN2_GPIO_Port,PushMotor2IN2_Pin,GPIO_PIN_RESET);
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
return 0;
}
PushMotor2TIM->CNT=0;
PushMotor2TIM->CCR1=PushMotor2_10us;
/*转动时间控制,当time_off为0时一直转动*/
PushMotor2TIM->SR&=0x00;
if(time_off==0)
{
debug("时间为0\r\n");
PushMotor2TIM->DIER&=0x00;
}
else
{
PM2_Counter=0;
PM2_Max_Counter=time_off;
PushMotor2TIM->DIER|=0x01;
}
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
return 0;
}
void PushMotor1_irq_cb()
{
PM_Counter++;
if(PM_Counter>=PM_Max_Counter)
{
PM_Counter=0;
debug("over\r\n");
PushMotor_Control(0,0,1);
}
}
void PushMotor2_irq_cb()
{
PM2_Counter++;
if(PM2_Counter>=PM2_Max_Counter)
{
PM2_Counter=0;
debug("over\r\n");
PushMotor2_Control(0,0,1);
}
}
StepMotor.h
#ifndef __STEPMOTOR_H__
#define __STEPMOTOR_H__
#include "stm32f1xx.h"
#include "main.h"
#include "tim.h"
extern uint16_t StepMotor_10us;
int8_t StepMotor_Control(int16_t speed,uint16_t angle,uint8_t flag_break);
void StepMotor_irq_cb(void);
#endif
StepMotor.c
#include "StepMotor.h"
#include "debug.h"
#define StepMotorTIM TIM3
#define SlaveMotorTIM TIM4
uint16_t StepMotor_10us=0;
/*步进电机控制函数
speed:速度
0 锁死
正数
负数
angle:运动角度
*/
int8_t StepMotor_Control(int16_t speed,uint16_t angle,uint8_t flag_break)
{
/*判断是否需要打断之前的运行*/
if(flag_break!=0)//打断当前运行
{
debug("打断\r\n");
}
else
{
/*检测电机是否正在运行*/
//if(StepMotorTIM->CR1&0x00000001)//电机正在运行
if(StepMotor_10us!=0)
{
debug("定时器正在运行\r\n");
return -1;
}
else
{
}
}
/*需要打断或者上次运行已经结束*/
StepMotor_10us=speed<0?0-speed:speed;
if(speed<0)
{
HAL_GPIO_WritePin(StepMotorEna_GPIO_Port,StepMotorEna_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(StepMotorDir_GPIO_Port,StepMotorDir_Pin,GPIO_PIN_RESET);
}
else if(speed>0)
{
HAL_GPIO_WritePin(StepMotorEna_GPIO_Port,StepMotorEna_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(StepMotorDir_GPIO_Port,StepMotorDir_Pin,GPIO_PIN_SET);
}
else
{
//锁死步进电机
HAL_GPIO_WritePin(StepMotorEna_GPIO_Port,StepMotorEna_Pin,GPIO_PIN_SET);
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_3);
return 0;
}
StepMotorTIM->CNT = 0;
StepMotorTIM->ARR = StepMotor_10us;
StepMotorTIM->CCR3 = StepMotor_10us/2;
/*转动角度控制,当angle为0时一直转动*/
SlaveMotorTIM->SR&=0x00;
if(angle==0)
{
debug("角度为0\r\n");
HAL_TIM_Base_Stop_IT(&htim4);
}
else
{
SlaveMotorTIM->CNT=0;
SlaveMotorTIM->ARR=angle-1;
HAL_TIM_Base_Start_IT(&htim4);
}
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
return 0;
}
void StepMotor_irq_cb()
{
debug("over\r\n");
StepMotor_Control(0,0,1);
}
dubug.h
#ifndef _DEBUG_H
#define _DEBUG_H
#include "stdio.h"
#include "stm32f1xx.h"
#include "main.h"
#include "usart.h"
#define MKIMAGE_DEBUG
#ifdef MKIMAGE_DEBUG
#define debug(fmt,args...) printf (fmt ,##args)
#else
#define debug(fmt,args...)
#endif /* MKIMAGE_DEBUG */
extern uint8_t byTmpData;
void debug_analyze(void);
#endif /* DEBUG_H */
debug.c
#include "debug.h"
#include "string.h"
#include "StepMotor.h"
#include "PushMotor.h"
//#define RX_SHOW //处理器速度不够请不要打开这个,72M主频也不够
#define DEBUG_BUFF_SIZE 36
uint8_t byDebugBuff[DEBUG_BUFF_SIZE];
uint8_t byTmpData;
static uint8_t byCurrentDebugCursor = 0;
int dwTmpPara[6];
int i;
/**
* @brief DEBUG 常量文本索引
*/
enum
{
DEBUG_TEXT_INFO, /* debug信息 */
DEBUG_TEXT_CMD_TOO_LONG, /* 命令过长 */
DEBUG_TEXT_BACK, /* 退格 */
DEBUG_TEXT_INPUT_HEAD, /* 输入前置打印 */
DEBUG_TEXT_HELP, /* help 命令打印 */
DEBUG_TEXT_CMD_UNKNOWN, /* 未知命令类型 */
};
static 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]);
StepMotor_Control(dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
}
else if(strncmp("pm1", (const char *)byDebugBuff,strlen("pm1")) == 0)
{
sscanf((const char *)byDebugBuff, "pm1 %d %d %d",&dwTmpPara[0],&dwTmpPara[1],&dwTmpPara[2]);
printf("\r\n%d,%d,%d\r\n",dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
PushMotor_Control(dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
}
else if(strncmp("pm2", (const char *)byDebugBuff,strlen("pm2")) == 0)
{
sscanf((const char *)byDebugBuff, "pm2 %d %d %d",&dwTmpPara[0],&dwTmpPara[1],&dwTmpPara[2]);
printf("\r\n%d,%d,%d\r\n",dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
PushMotor2_Control(dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
}
else if(strncmp("get app1", (const char *)byDebugBuff,strlen("get app1")) == 0)
{
}
else if(strncmp("set app1", (const char *)byDebugBuff,strlen("set app1")) == 0)
{
sscanf((const char *)byDebugBuff, "set app1 %d",&dwTmpPara[0]);
printf("\r\n%d\r\n",dwTmpPara[0]);
}
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
{
#ifdef RX_SHOW
HAL_UART_Transmit(&huart1,&byTmpData,1,0xff);
#endif
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;
}
sys.h
#ifndef __SYS_H__
#define __SYS_H__
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "timer.h"
typedef void (*VOID_FUNC)(void);
typedef struct RA
{
VOID_FUNC func;
uint32_t tickstart;//起始时间
uint32_t wait_HZ;//等待时间
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_HZ,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>
#include "debug.h"
#include "timer.h"
#include "string.h"
/*******************************Run_Aftertimer*********************************/
#define RA_MAX_DELAY HAL_MAX_DELAY
#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)
{
debug("自动分配RA\r\n");
for(int i=1;i<RA_TABLE_SIZE;i++)
{
if(RA_table[i]==NULL)
{
index=i;
}
if(i>=RA_TABLE_SIZE)
{
if(ra!=NULL)
{
free(ra);
ra=NULL;
}
debug("RA自动分配失败,无可用\r\n");
return -1;
}
}
}
if(RA_table[index]!=NULL)
{
if(ra!=NULL)
{
free(ra);
ra=NULL;
}
debug("RA reg该位置已被占用\r\n");
return -1;
}
RA_table[index]=ra;
RA_table[index]->tickstart = jiffies;
/* Add a freq to guarantee minimum wait */
if (RA_table[index]->wait_HZ < RA_MAX_DELAY)
{
RA_table[index]->wait_HZ += 1;
}
else
{
debug("RA延时时间过长\r\n");
return -1;
}
return index;
}
int8_t Run_Aftertimer_creat(VOID_FUNC func,uint32_t wait_HZ,uint8_t index,uint32_t cycle_index)
{
uint8_t need_heap_size=0;
if(RA_table[index]!=NULL)
{
debug("RA该位置已被占用 %d\r\n",index);
return -1;
}
need_heap_size=sizeof(RA_st);
RA_st *ra=malloc(need_heap_size);
if(ra==NULL)
{
debug("RA分配内存失败\r\n");
return -1;
}
memset((uint8_t *)ra,0,need_heap_size);
ra->func=func;
ra->wait_HZ=wait_HZ;
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); /* 使能全局中断 */
debug("释放的RA为NULL\r\n");
return -1;
}
/*释放内存*/
if(RA_table[index]!=NULL)
{
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 (time_after_eq(jiffies, (RA_table[i]->tickstart+RA_table[i]->wait_HZ)))
{
RA_table[i]->func();
if(RA_table[i]->cycle_index==1)
{
/*释放内存*/
if(RA_table[i]!=NULL)
{
free(RA_table[i]);
RA_table[i]=NULL;
}
continue;
}
RA_table[i]->tickstart = jiffies;
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)
{
debug("自动分配IC\r\n");
for(int i=1;i<IC_Tab->tabsize;i++)
{
if(IC_Tab->IC_table[i]==NULL)
{
index=i;
}
if(i>=IC_Tab->tabsize)
{
if(ic!=NULL)
{
free(ic);
ic=NULL;
}
debug("IC自动分配失败,无可用\r\n");
return -1;
}
}
}
/*该位置已被使用*/
if(IC_Tab->IC_table[index]!=NULL)
{
if(ic!=NULL)
{
free(ic);
ic=NULL;
}
debug("IC reg该位置已被占用\r\n");
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)
{
uint8_t need_heap_size=0;
/*错误判断*/
/*Tab未创建*/
if(IC_Tab->IC_table==NULL)
{
debug("IC TAB未创建\r\n");
return -1;
}
/*该位置已被使用*/
if(IC_Tab->IC_table[index]!=NULL)
{
debug("IC该位置已被占用 %d\r\n",index);
return -1;
}
/*正文*/
need_heap_size=sizeof(IC_st);
IC_st *ic=malloc(need_heap_size);
if(ic==NULL)
{
debug("IC分配内存失败\r\n");
return -1;
}
memset((uint8_t *)ic,0,need_heap_size);
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)
{
debug("释放的IC为NULL\r\n");
__set_PRIMASK(0); /* 使能全局中断 */
return -1;
}
/*index为0(不支持一次释放全部)*/
if(index==0)
{
__set_PRIMASK(0); /* 使能全局中断 */
debug("index为0,不支持一次释放全部\r\n");
return -1;
}
/*正文*/
/*释放内存*/
IC_Tab->counter--;
if(IC_Tab->IC_table[index]!=NULL)
{
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)
{
uint8_t need_heap_size=0;
/*错误判断*/
/*Tab已经创建*/
if(IC_Tab->IC_table!=NULL)
{
debug("IC TAB已经创建\r\n");
return -1;
}
/*tabsize不满足要求*/
if(tabsize==0)
{
debug("tabsize不满足要求\r\n");
return -1;
}
/*正文*/
tabsize+=1;
IC_Tab->tabsize=tabsize;
need_heap_size=tabsize*sizeof(IC_st *);
IC_Tab->IC_table=malloc(need_heap_size);
if(IC_Tab->IC_table==NULL)
{
debug("IC TAB分配内存失败\r\n");
return -1;
}
memset((uint8_t *)IC_Tab->IC_table,0,need_heap_size);
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); /* 使能全局中断 */
debug("释放的IC TAB为NULL\r\n");
return -1;
}
/*Tab中还有未释放的项目*/
if(IC_Tab->counter!=0)
{
__set_PRIMASK(0); /* 使能全局中断 */
debug("IC TAB中还有未释放的项目\r\n");
return -1;
}
/*正文*/
/*释放内存*/
if(IC_Tab->IC_table!=NULL)
{
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)
{
/*释放内存*/
if(IC_Tab->IC_table[i]!=NULL)
{
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--;
}
}
}
app.h
#ifndef __APP_H__
#define __APP_H__
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "sys.h"
#define READ 0
#define WRITE 1
typedef enum Status
{
Init_StepMotor,
Init_PushMotor,
Creat_LED_RA,
Start_StepMotor,
Start_PushMotor__,
Start_PushMotor_,
Init_Monitor_Proximity,
Monitor_Proximitying,
Status_Delay,
Start_Delay_Long,
Delaying_Long,
Start_Delay_Short,
Delaying_Short,
Status_Stop,
}Status_en;
extern IC_Tab_st Proximity1_IC_Tab;
extern IC_Tab_st Proximity2_IC_Tab;
int8_t Get_Mod(void);
void App1_Func(void);
void App2_Func(void);
void App3_Func(void);
void LED_Toggel(int led);
int8_t Flag_App_Start(uint8_t rw,int8_t parameter);
#endif
app.c
#include "app.h"
#include "StepMotor.h"
#include "PushMotor.h"
#include "iwdg.h"
const struct env_t
{
uint32_t crc32;
uint32_t app1_long_time;
uint32_t app1_short_time;
uint32_t app2_long_time;
uint32_t app2_short_time;
uint32_t app3_long_time;
uint32_t app3_short_time;
}env __attribute__((at(0x0800fc00)));
volatile Status_en status=Status_Stop;
IC_Tab_st Proximity1_IC_Tab={NULL};
IC_Tab_st Proximity2_IC_Tab={NULL};
int8_t Get_Mod()
{
static uint8_t counter=1;
static int8_t mod=1;
uint8_t f1=0,f2=0;
if(counter==0)
{
return mod;
}
counter--;
if(HAL_GPIO_ReadPin(Knob3_2_GPIO_Port,Knob3_2_Pin)==GPIO_PIN_RESET)
{
f1=1;
}
if(HAL_GPIO_ReadPin(Knob3_3_GPIO_Port,Knob3_3_Pin)==GPIO_PIN_RESET)
{
f2=1;
}
if((f1==1)&&(f2==0))
{
mod=1;
}
else if((f1==0)&&(f2==0))
{
mod=2;
}
else if((f1==0)&&(f2==1))
{
mod=3;
}
else{return -1;}
return mod;
}
void App1_Proximity1_callback1()
{
if(status!=Monitor_Proximitying)
return;
printf("App1_Proximity1_callback1\r\n");
StepMotor_Control(0,0,1);
PushMotor_Control(4,0,1);
status=Start_Delay_Short;
}
void App1_Proximity2_callback1()
{
if(status!=Monitor_Proximitying)
return;
printf("App1_Proximity2_callback1\r\n");
StepMotor_Control(0,0,1);
PushMotor_Control(-4,0,1);
status=Start_Delay_Long;
}
void LED_Toggel(int led)
{
if(led<0)
{
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_SET);
HAL_GPIO_TogglePin(LED_RED_GPIO_Port,LED_RED_Pin);
}
else
{
HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_SET);
HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin);
}
}
void LED_Toggel_RA_func()
{
HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_SET);
HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin);
}
void App1_Func()
{
uint32_t start_time;
int8_t ret;
static uint8_t dir=2;
uint32_t num=0;
ret=Interrupt_Callback_Tab_creat(&Proximity1_IC_Tab,2);if(ret<0){goto ERR;}
ret=Interrupt_Callback_Tab_creat(&Proximity2_IC_Tab,2);if(ret<0){goto ERR;}
while(1)
{
if(Flag_App_Start(READ,0))
{
switch(status)
{
case Status_Stop:
status=Init_StepMotor;
break;
case Init_StepMotor:
printf("Init_StepMotor\r\n");
StepMotor_Control(0,0,1);
status=Init_Monitor_Proximity;
break;
case Init_Monitor_Proximity:
printf("Init_Monitor_Proximity\r\n");
ret=Interrupt_Callback_creat(&Proximity1_IC_Tab,App1_Proximity1_callback1,1,0);if(ret<0){goto ERR;}
ret=Interrupt_Callback_creat(&Proximity2_IC_Tab,App1_Proximity2_callback1,1,0);if(ret<0){goto ERR;}
status=Creat_LED_RA;
break;
case Creat_LED_RA:
ret=Run_Aftertimer_creat(LED_Toggel_RA_func,0.1*HZ,4,0);if(ret<0){goto ERR;}
status=Start_StepMotor;
break;
case Start_StepMotor:
printf("Start_StepMotor");
StepMotor_Control(150,0,0);
status=Monitor_Proximitying;
break;
case Monitor_Proximitying:
break;
case Start_Delay_Long:
printf("Start_Delay_Long");
start_time=HAL_GetTick();
status=Delaying_Long;
break;
case Delaying_Long:
if(HAL_GetTick()-start_time>18000)
{
status=Start_StepMotor;
}
break;
case Start_Delay_Short:
printf("Start_Delay_Short");
start_time=HAL_GetTick();
status=Delaying_Short;
break;
case Delaying_Short:
if(HAL_GetTick()-start_time>1000)
{
status=Start_StepMotor;
}
break;
default:
break;
}
}
else
{
HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_RESET);
switch(status)
{
case Status_Stop:
break;
default:
status=Status_Stop;
StepMotor_Control(0,0,1);
PushMotor_Control(0,0,1);
ret=Run_Aftertimer_release(4);if(ret<0){goto ERR;}
ret=Interrupt_Callback_release(&Proximity1_IC_Tab,1);if(ret<0){goto ERR;}
ret=Interrupt_Callback_release(&Proximity2_IC_Tab,1);if(ret<0){goto ERR;}
break;
}
}
//HAL_IWDG_Refresh(&hiwdg);
}
ret=Interrupt_Callback_Tab_release(&Proximity1_IC_Tab);if(ret<0){goto ERR;}
ret=Interrupt_Callback_Tab_release(&Proximity2_IC_Tab);if(ret<0){goto ERR;}
ERR:
printf("err\r\n");
while(1)
{
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_RESET);
//HAL_IWDG_Refresh(&hiwdg);
HAL_Delay(50);
}
}
void App2_Func()
{
App1_Func();
while(1)
{
}
}
void App3_Proximity2_callback1()
{
if(status!=Monitor_Proximitying)
return;
printf("App3_Proximity2_callback1\r\n");
PushMotor2_Control(0,0,1);
PushMotor_Control(4,0,1);
status=Start_Delay_Short;
}
void App3_Proximity1_callback1()
{
if(status!=Monitor_Proximitying)
return;
printf("App3_Proximity1_callback1\r\n");
PushMotor2_Control(0,0,1);
PushMotor_Control(-4,0,1);
status=Start_Delay_Long;
}
void App3_Func()
{
uint32_t start_time;
int8_t ret;
static uint8_t dir=2;
uint32_t num=0;
ret=Interrupt_Callback_Tab_creat(&Proximity1_IC_Tab,2);if(ret<0){goto ERR;}
ret=Interrupt_Callback_Tab_creat(&Proximity2_IC_Tab,2);if(ret<0){goto ERR;}
while(1)
{
if(Flag_App_Start(READ,0))
{
switch(status)
{
case Status_Stop:
status=Init_PushMotor;
break;
case Init_PushMotor:
printf("Init_PushMotor\r\n");
PushMotor2_Control(0,0,1);
status=Init_Monitor_Proximity;
break;
case Init_Monitor_Proximity:
printf("Init_Monitor_Proximity\r\n");
ret=Interrupt_Callback_creat(&Proximity1_IC_Tab,App3_Proximity1_callback1,1,0);if(ret<0){goto ERR;}
ret=Interrupt_Callback_creat(&Proximity2_IC_Tab,App3_Proximity2_callback1,1,0);if(ret<0){goto ERR;}
status=Creat_LED_RA;
break;
case Creat_LED_RA:
ret=Run_Aftertimer_creat(LED_Toggel_RA_func,0.1*HZ,4,0);if(ret<0){goto ERR;}
if(HAL_GPIO_ReadPin(Proximity1_GPIO_Port,Proximity1_Pin)==GPIO_PIN_RESET)
status=Start_PushMotor__;
else
status=Start_PushMotor_;
break;
case Start_PushMotor__:
printf("Start_PushMotor__");
PushMotor2_Control(-4,105000,0);
status=Monitor_Proximitying;
break;
case Start_PushMotor_:
printf("Start_PushMotor_");
PushMotor2_Control(4,0,0);
status=Monitor_Proximitying;
break;
case Monitor_Proximitying:
break;
case Start_Delay_Long:
printf("Start_Delay_Long");
start_time=HAL_GetTick();
status=Delaying_Long;
break;
case Delaying_Long:
if(HAL_GetTick()-start_time>5000)
{
status=Start_PushMotor__;
}
break;
case Start_Delay_Short:
printf("Start_Delay_Short");
start_time=HAL_GetTick();
status=Delaying_Short;
break;
case Delaying_Short:
if(HAL_GetTick()-start_time>2000)
{
status=Start_PushMotor_;
}
break;
default:
break;
}
}
else
{
HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_RESET);
switch(status)
{
case Status_Stop:
break;
default:
status=Status_Stop;
PushMotor2_Control(0,0,1);
PushMotor_Control(0,0,1);
ret=Run_Aftertimer_release(4);if(ret<0){goto ERR;}
ret=Interrupt_Callback_release(&Proximity1_IC_Tab,1);if(ret<0){goto ERR;}
ret=Interrupt_Callback_release(&Proximity2_IC_Tab,1);if(ret<0){goto ERR;}
break;
}
}
//HAL_IWDG_Refresh(&hiwdg);
}
ret=Interrupt_Callback_Tab_release(&Proximity1_IC_Tab);if(ret<0){goto ERR;}
ret=Interrupt_Callback_Tab_release(&Proximity2_IC_Tab);if(ret<0){goto ERR;}
ERR:
printf("err\r\n");
while(1)
{
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_RED_GPIO_Port,LED_RED_Pin,GPIO_PIN_RESET);
//HAL_IWDG_Refresh(&hiwdg);
HAL_Delay(50);
}
}
int8_t Flag_App_Start(uint8_t rw,int8_t parameter)
{
static uint8_t flag=0;
switch(rw)
{
case READ:
break;
case WRITE:
flag=parameter;
break;
default:
return -1;
}
return flag;
}
gpio.h
gpio.c
/**
******************************************************************************
* File Name : gpio.c
* Description : This file provides code for the configuration
* of all used GPIO pins.
******************************************************************************
** 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 "gpio.h"
/* USER CODE BEGIN 0 */
#include "sys.h"
#include "app.h"
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure GPIO */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, PushMotorIN1_Pin|PushMotorIN2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, StepMotorDir_Pin|StepMotorEna_Pin|PushMotor2IN1_Pin|PushMotor2IN2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, LED_RED_Pin|LED_GREEN_Pin, GPIO_PIN_SET);
/*Configure GPIO pins : PAPin PAPin */
GPIO_InitStruct.Pin = PushMotorIN1_Pin|PushMotorIN2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PAPin PAPin PAPin */
GPIO_InitStruct.Pin = Knob3_1_Pin|Knob3_2_Pin|Knob3_3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PBPin PBPin PBPin PBPin */
GPIO_InitStruct.Pin = StepMotorDir_Pin|StepMotorEna_Pin|PushMotor2IN1_Pin|PushMotor2IN2_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);
/*Configure GPIO pins : PBPin PBPin */
GPIO_InitStruct.Pin = LED_RED_Pin|LED_GREEN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PBPin PBPin PBPin */
GPIO_InitStruct.Pin = Proximity1_Pin|proximity2_Pin|Switch_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}
/* USER CODE BEGIN 2 */
void Proximity1_RA_func()
{
static GPIO_PinState status=GPIO_PIN_SET;
if(HAL_GPIO_ReadPin(Proximity1_GPIO_Port,Proximity1_Pin)==status)
{
EXTI->IMR|=(0x01<<5);
return;
}
status=HAL_GPIO_ReadPin(Proximity1_GPIO_Port,Proximity1_Pin);
if(status==GPIO_PIN_RESET)
{
printf("Proximity1 reset\r\n");
IC_Task(&Proximity1_IC_Tab);
}
else
{
printf("Proximity1 set\r\n");
}
EXTI->IMR|=(0x01<<5);
}
void Proximity2_RA_func()
{
static GPIO_PinState status=GPIO_PIN_SET;
if(HAL_GPIO_ReadPin(proximity2_GPIO_Port,proximity2_Pin)==status)
{
EXTI->IMR|=(0x01<<6);
return;
}
status=HAL_GPIO_ReadPin(proximity2_GPIO_Port,proximity2_Pin);
if(status==GPIO_PIN_RESET)
{
printf("Proximity2 reset\r\n");
IC_Task(&Proximity2_IC_Tab);
}
else
{
printf("Proximity2 set\r\n");
}
EXTI->IMR|=(0x01<<6);
}
void Switch_RA_func()
{
static GPIO_PinState status=GPIO_PIN_SET;
if(HAL_GPIO_ReadPin(Switch_GPIO_Port,Switch_Pin)==status)
{
EXTI->IMR|=(0x01<<7);
return;
}
status=HAL_GPIO_ReadPin(Switch_GPIO_Port,Switch_Pin);
if(status==GPIO_PIN_RESET)
{
Flag_App_Start(WRITE,1);
printf("Switch reset\r\n");
}
else
{
Flag_App_Start(WRITE,0);
printf("Switch set\r\n");
}
EXTI->IMR|=(0x01<<7);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == Proximity1_Pin)
{
EXTI->IMR&=(~(0x01<<5));
int8_t ret=Run_Aftertimer_creat(Proximity1_RA_func,0.002*HZ,1,1);
}
else if(GPIO_Pin == proximity2_Pin)
{
EXTI->IMR&=(~(0x01<<6));
int8_t ret=Run_Aftertimer_creat(Proximity2_RA_func,0.002*HZ,2,1);
}
else if(GPIO_Pin == Switch_Pin)
{
EXTI->IMR&=(~(0x01<<7));
int8_t ret=Run_Aftertimer_creat(Switch_RA_func,0.1*HZ,3,1);
}
else
{
printf("err\r\n");
}
}
/* USER CODE END 2 */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
tim.h
/**
******************************************************************************
* File Name : TIM.h
* Description : This file provides code for the configuration
* of the TIM instances.
******************************************************************************
** 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 __tim_H
#define __tim_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim4;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
extern void _Error_Handler(char *, int);
void MX_TIM1_Init(void);
void MX_TIM2_Init(void);
void MX_TIM3_Init(void);
void MX_TIM4_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ tim_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
tim.c
/**
******************************************************************************
* File Name : TIM.c
* Description : This file provides code for the configuration
* of the TIM instances.
******************************************************************************
** 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 "tim.h"
/* USER CODE BEGIN 0 */
#include "StepMotor.h"
#include "PushMotor.h"
/* USER CODE END 0 */
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;
/* TIM1 init function */
void MX_TIM1_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 720-1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = PUSHMOTORPER_10US;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = PushMotor2_10us;
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_MspPostInit(&htim1);
}
/* TIM2 init function */
void MX_TIM2_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 720-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = PUSHMOTORPER_10US;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = PushMotor_10us;
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_MspPostInit(&htim2);
}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
htim3.Instance = TIM3;
htim3.Init.Prescaler = 720-1;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = StepMotor_10us;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = StepMotor_10us/2;
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_MspPostInit(&htim3);
}
/* TIM4 init function */
void MX_TIM4_Init(void)
{
TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim4.Instance = TIM4;
htim4.Init.Prescaler = 0;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 0;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
sSlaveConfig.InputTrigger = TIM_TS_ITR2;
if (HAL_TIM_SlaveConfigSynchronization(&htim4, &sSlaveConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
{
if(tim_pwmHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* TIM1 interrupt Init */
HAL_NVIC_SetPriority(TIM1_UP_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
else if(tim_pwmHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
else if(tim_pwmHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspInit 0 */
/* USER CODE END TIM4_MspInit 0 */
/* TIM4 clock enable */
__HAL_RCC_TIM4_CLK_ENABLE();
/* TIM4 interrupt Init */
HAL_NVIC_SetPriority(TIM4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM4_IRQn);
/* USER CODE BEGIN TIM4_MspInit 1 */
/* USER CODE END TIM4_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(timHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspPostInit 0 */
/* USER CODE END TIM1_MspPostInit 0 */
/**TIM1 GPIO Configuration
PA8 ------> TIM1_CH1
*/
GPIO_InitStruct.Pin = PushMotor2PWM_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(PushMotor2PWM_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN TIM1_MspPostInit 1 */
/* USER CODE END TIM1_MspPostInit 1 */
}
else if(timHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspPostInit 0 */
/* USER CODE END TIM2_MspPostInit 0 */
/**TIM2 GPIO Configuration
PA0-WKUP ------> TIM2_CH1
*/
GPIO_InitStruct.Pin = PushMotorPWM_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(PushMotorPWM_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN TIM2_MspPostInit 1 */
/* USER CODE END TIM2_MspPostInit 1 */
}
else if(timHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspPostInit 0 */
/* USER CODE END TIM3_MspPostInit 0 */
/**TIM3 GPIO Configuration
PB0 ------> TIM3_CH3
*/
GPIO_InitStruct.Pin = StepMotorPul_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(StepMotorPul_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN TIM3_MspPostInit 1 */
/* USER CODE END TIM3_MspPostInit 1 */
}
}
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
{
if(tim_pwmHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspDeInit 0 */
/* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
/* TIM1 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM1_UP_IRQn);
/* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM1_MspDeInit 1 */
}
else if(tim_pwmHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* TIM2 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
}
else if(tim_pwmHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspDeInit 0 */
/* USER CODE END TIM4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM4_CLK_DISABLE();
/* TIM4 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM4_IRQn);
/* USER CODE BEGIN TIM4_MspDeInit 1 */
/* USER CODE END TIM4_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == htim4.Instance)
{
StepMotor_irq_cb();
}
else if (htim->Instance == htim2.Instance)
{
PushMotor1_irq_cb();
}
else if (htim->Instance == htim1.Instance)
{
PushMotor2_irq_cb();
}
}
/* USER CODE END 1 */
/**
* @}
*/
/**
* @}
*/
/************************ (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 TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim4;
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("hard fault\r\n");
/* 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 */
static uint8_t ctr=0;
if(ctr<(1000/HZ))
{
ctr++;
}
if(ctr>=(1000/HZ))
{
ctr=0;
jiffies_64+=1;
RA_Task();
#ifdef USE_KERNEL_TIMER
timer_update(&timer_base);
#endif
}
/* 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 EXTI line[9:5] interrupts.
*/
void EXTI9_5_IRQHandler(void)
{
/* USER CODE BEGIN EXTI9_5_IRQn 0 */
/* USER CODE END EXTI9_5_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7);
/* USER CODE BEGIN EXTI9_5_IRQn 1 */
/* USER CODE END EXTI9_5_IRQn 1 */
}
/**
* @brief This function handles TIM1 update interrupt.
*/
void TIM1_UP_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_UP_IRQn 0 */
/* USER CODE END TIM1_UP_IRQn 0 */
HAL_TIM_IRQHandler(&htim1);
/* USER CODE BEGIN TIM1_UP_IRQn 1 */
/* USER CODE END TIM1_UP_IRQn 1 */
}
/**
* @brief This function handles TIM2 global interrupt.
*/
void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
/* USER CODE END TIM2_IRQn 1 */
}
/**
* @brief This function handles TIM4 global interrupt.
*/
void TIM4_IRQHandler(void)
{
/* USER CODE BEGIN TIM4_IRQn 0 */
/* USER CODE END TIM4_IRQn 0 */
HAL_TIM_IRQHandler(&htim4);
/* USER CODE BEGIN TIM4_IRQn 1 */
/* USER CODE END TIM4_IRQn 1 */
}
/**
* @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 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
timer.h
#ifndef _LINUX_TIMER_H
#define _LINUX_TIMER_H
#include "list.h"
#include "typecheck.h"
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
//#define USE_KERNEL_TIMER
#define HZ 1000
#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"
//#define USE_RTC
#ifdef USE_RTC
#include "rtc.h"
#endif
#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;
#ifdef USE_RTC
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;
}
#endif
void init_timers()
{
#ifdef USE_RTC
//读取RTC
sys_start_rtc_time=RTC_ReadTimeCounter(&hrtc);
#endif
#ifdef USE_KERNEL_TIMER
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]));
}
#endif
}
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 */
test.ioc(stm32cubemx文件)
#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=SYS
Mcu.IP4=TIM1
Mcu.IP5=TIM2
Mcu.IP6=TIM3
Mcu.IP7=TIM4
Mcu.IP8=USART1
Mcu.IPNb=9
Mcu.Name=STM32F103C(8-B)Tx
Mcu.Package=LQFP48
Mcu.Pin0=PD0-OSC_IN
Mcu.Pin1=PD1-OSC_OUT
Mcu.Pin10=PB2
Mcu.Pin11=PB11
Mcu.Pin12=PB12
Mcu.Pin13=PB13
Mcu.Pin14=PB14
Mcu.Pin15=PA8
Mcu.Pin16=PA9
Mcu.Pin17=PA10
Mcu.Pin18=PA13
Mcu.Pin19=PA14
Mcu.Pin2=PA0-WKUP
Mcu.Pin20=PB5
Mcu.Pin21=PB6
Mcu.Pin22=PB7
Mcu.Pin23=VP_IWDG_VS_IWDG
Mcu.Pin24=VP_SYS_VS_Systick
Mcu.Pin25=VP_TIM4_VS_ControllerModeClock
Mcu.Pin26=VP_TIM4_VS_ClockSourceITR
Mcu.Pin3=PA1
Mcu.Pin4=PA2
Mcu.Pin5=PA5
Mcu.Pin6=PA6
Mcu.Pin7=PA7
Mcu.Pin8=PB0
Mcu.Pin9=PB1
Mcu.PinsNb=27
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.EXTI9_5_IRQn=true\:0\:0\:false\:false\:true\:true
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_2
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false
NVIC.TIM1_UP_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.TIM4_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false
PA0-WKUP.GPIOParameters=GPIO_Label
PA0-WKUP.GPIO_Label=PushMotorPWM
PA0-WKUP.Signal=S_TIM2_CH1_ETR
PA1.GPIOParameters=GPIO_Label
PA1.GPIO_Label=PushMotorIN1
PA1.Locked=true
PA1.Signal=GPIO_Output
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
PA2.GPIOParameters=GPIO_Label
PA2.GPIO_Label=PushMotorIN2
PA2.Locked=true
PA2.Signal=GPIO_Output
PA5.GPIOParameters=GPIO_PuPd,GPIO_Label
PA5.GPIO_Label=Knob3_1
PA5.GPIO_PuPd=GPIO_PULLUP
PA5.Locked=true
PA5.Signal=GPIO_Input
PA6.GPIOParameters=GPIO_PuPd,GPIO_Label
PA6.GPIO_Label=Knob3_2
PA6.GPIO_PuPd=GPIO_PULLUP
PA6.Locked=true
PA6.Signal=GPIO_Input
PA7.GPIOParameters=GPIO_PuPd,GPIO_Label
PA7.GPIO_Label=Knob3_3
PA7.GPIO_PuPd=GPIO_PULLUP
PA7.Locked=true
PA7.Signal=GPIO_Input
PA8.GPIOParameters=GPIO_Label
PA8.GPIO_Label=PushMotor2PWM
PA8.Locked=true
PA8.Signal=S_TIM1_CH1
PA9.Mode=Asynchronous
PA9.Signal=USART1_TX
PB0.GPIOParameters=GPIO_Label
PB0.GPIO_Label=StepMotorPul
PB0.Signal=S_TIM3_CH3
PB1.GPIOParameters=GPIO_Label
PB1.GPIO_Label=StepMotorDir
PB1.Locked=true
PB1.Signal=GPIO_Output
PB11.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PB11.GPIO_Label=LED_RED
PB11.GPIO_PuPd=GPIO_PULLUP
PB11.Locked=true
PB11.PinState=GPIO_PIN_SET
PB11.Signal=GPIO_Output
PB12.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label
PB12.GPIO_Label=LED_GREEN
PB12.GPIO_PuPd=GPIO_PULLUP
PB12.Locked=true
PB12.PinState=GPIO_PIN_SET
PB12.Signal=GPIO_Output
PB13.GPIOParameters=GPIO_Label
PB13.GPIO_Label=PushMotor2IN1
PB13.Locked=true
PB13.Signal=GPIO_Output
PB14.GPIOParameters=GPIO_Label
PB14.GPIO_Label=PushMotor2IN2
PB14.Locked=true
PB14.Signal=GPIO_Output
PB2.GPIOParameters=GPIO_Label
PB2.GPIO_Label=StepMotorEna
PB2.Locked=true
PB2.Signal=GPIO_Output
PB5.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
PB5.GPIO_Label=Proximity1
PB5.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
PB5.GPIO_PuPd=GPIO_PULLUP
PB5.Locked=true
PB5.Signal=GPXTI5
PB6.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
PB6.GPIO_Label=proximity2
PB6.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
PB6.GPIO_PuPd=GPIO_PULLUP
PB6.Locked=true
PB6.Signal=GPXTI6
PB7.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
PB7.GPIO_Label=Switch
PB7.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
PB7.GPIO_PuPd=GPIO_PULLUP
PB7.Locked=true
PB7.Signal=GPXTI7
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=test.ioc
ProjectManager.ProjectName=test
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_TIM2_Init-TIM2-false-HAL-true,4-MX_TIM3_Init-TIM3-false-HAL-true,5-MX_USART1_UART_Init-USART1-false-HAL-true,6-MX_IWDG_Init-IWDG-false-HAL-true,7-MX_TIM4_Init-TIM4-false-HAL-true,8-MX_TIM1_Init-TIM1-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,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.SYSCLKFreq_VALUE=72000000
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
RCC.TimSysFreq_Value=72000000
RCC.USBFreq_Value=72000000
RCC.VCOOutput2Freq_Value=8000000
SH.GPXTI5.0=GPIO_EXTI5
SH.GPXTI5.ConfNb=1
SH.GPXTI6.0=GPIO_EXTI6
SH.GPXTI6.ConfNb=1
SH.GPXTI7.0=GPIO_EXTI7
SH.GPXTI7.ConfNb=1
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
SH.S_TIM1_CH1.ConfNb=1
SH.S_TIM2_CH1_ETR.0=TIM2_CH1,PWM Generation1 CH1
SH.S_TIM2_CH1_ETR.ConfNb=1
SH.S_TIM3_CH3.0=TIM3_CH3,PWM Generation3 CH3
SH.S_TIM3_CH3.ConfNb=1
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
TIM1.IPParameters=Channel-PWM Generation1 CH1,Prescaler,Period,Pulse-PWM Generation1 CH1,OCPolarity_1
TIM1.IPParametersWithoutCheck=Pulse-PWM Generation1 CH1,Period
TIM1.OCPolarity_1=TIM_OCPOLARITY_LOW
TIM1.Period=PUSHMOTORPER_10US
TIM1.Prescaler=720-1
TIM1.Pulse-PWM\ Generation1\ CH1=PushMotor2_10us
TIM2.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
TIM2.IPParameters=Prescaler,Period,Channel-PWM Generation1 CH1,Pulse-PWM Generation1 CH1,OCPolarity_1
TIM2.IPParametersWithoutCheck=Pulse-PWM Generation1 CH1,Pulse-PWM Generation2 CH2,Period
TIM2.OCPolarity_1=TIM_OCPOLARITY_LOW
TIM2.Period=PUSHMOTORPER_10US
TIM2.Prescaler=720-1
TIM2.Pulse-PWM\ Generation1\ CH1=PushMotor_10us
TIM3.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
TIM3.IPParameters=Prescaler,Period,TIM_MasterSlaveMode,TIM_MasterOutputTrigger,Channel-PWM Generation3 CH3,Pulse-PWM Generation3 CH3,OCPolarity_3
TIM3.IPParametersWithoutCheck=Pulse-PWM Generation3 CH3,Period,Pulse-Output Compare3 CH3
TIM3.OCPolarity_3=TIM_OCPOLARITY_LOW
TIM3.Period=StepMotor_10us
TIM3.Prescaler=720-1
TIM3.Pulse-PWM\ Generation3\ CH3=StepMotor_10us/2
TIM3.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
TIM3.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_ENABLE
TIM4.IPParameters=Period,TIM_MasterOutputTrigger
TIM4.Period=0
TIM4.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
USART1.IPParameters=VirtualMode
USART1.VirtualMode=VM_ASYNC
VP_IWDG_VS_IWDG.Mode=IWDG_Activate
VP_IWDG_VS_IWDG.Signal=IWDG_VS_IWDG
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
VP_TIM4_VS_ClockSourceITR.Mode=TriggerSource_ITR2
VP_TIM4_VS_ClockSourceITR.Signal=TIM4_VS_ClockSourceITR
VP_TIM4_VS_ControllerModeClock.Mode=Clock Mode
VP_TIM4_VS_ControllerModeClock.Signal=TIM4_VS_ControllerModeClock
board=custom