typedef和define具体的详细区别 2011.07.12

本文详细解析了C/C++中预处理指令#define与类型定义typedef的区别与使用场景。通过具体的例子展示了它们如何影响代码的编写及理解,并强调了它们在预处理阶段与编译阶段的不同行为。
1) #define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不关含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错。例如:
#define PI 3.1415926
程序中的:area=PI*r*r 会替换为3.1415926*r*r
如果你把#define语句中的数字9 写成字母g 预处理也照样带入。

2)typedef是在编译时处理的。它在自己的作用域内给一个已经存在的类型一个别名,但是You cannot use the typedef specifier inside a function definition。

3)typedef int * int_ptr;
与
#define int_ptr int * 
作用都是用int_ptr代表 int * ,但是二者不同,正如前面所说 ,#define在预处理 时进行简单的替换,而typedef不是简单替换 ,而是采用如同定义变量的方法那样来声明一种类型。也就是说;


#define int_ptr int *
int_ptr a, b; //相当于int * a, b; 只是简单的宏替换(a是指针,b不是指针)

typedef int* int_ptr;
int_ptr a, b; //a, b 都为指向int的指针,typedef为int* 引入了一个新的助记符(a,b都是指针)


这也说明了为什么下面观点成立

typedef int * pint ;
#define PINT int *

那么:
const pint p ;//p不可更改,但p指向的内容可更改
const PINT p ;//p可更改,但是p指向的内容不可更改。

pint是一种指针类型 const pint p 就是把指针给锁住了 p不可更改
而const PINT p 是const int * p 锁的是指针p所指的对象。

3)也许您已经注意到#define 不是语句 不要在行末加分号,否则 会连分号一块置换。
/** ****************************************************************************** * @file stm32f10x_gpio.h * @author MCD Application Team * @version V3.5.0 * @date 11-March-2011 * @brief This file contains all the functions prototypes for the GPIO * firmware library. ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2> ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32F10x_GPIO_H #define __STM32F10x_GPIO_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32f10x.h" /** @addtogroup STM32F10x_StdPeriph_Driver * @{ */ /** @addtogroup GPIO * @{ */ /** @defgroup GPIO_Exported_Types * @{ */ #define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \ ((PERIPH) == GPIOB) || \ ((PERIPH) == GPIOC) || \ ((PERIPH) == GPIOD) || \ ((PERIPH) == GPIOE) || \ ((PERIPH) == GPIOF) || \ ((PERIPH) == GPIOG)) /** * @brief Output Maximum frequency selection */ typedef enum { GPIO_Speed_10MHz = 1, GPIO_Speed_2MHz, GPIO_Speed_50MHz }GPIOSpeed_TypeDef; #define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) || \ ((SPEED) == GPIO_Speed_50MHz)) /** * @brief Configuration Mode enumeration */ typedef enum { GPIO_Mode_AIN = 0x0, GPIO_Mode_IN_FLOATING = 0x04, GPIO_Mode_IPD = 0x28, GPIO_Mode_IPU = 0x48, GPIO_Mode_Out_OD = 0x14, GPIO_Mode_Out_PP = 0x10, GPIO_Mode_AF_OD = 0x1C, GPIO_Mode_AF_PP = 0x18 }GPIOMode_TypeDef; #define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \ ((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \ ((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \ ((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP)) /** * @brief GPIO Init structure definition */ typedef struct { uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins. This parameter can be a value of @ref GPIOSpeed_TypeDef */ GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins. This parameter can be a value of @ref GPIOMode_TypeDef */ }GPIO_InitTypeDef; /** * @brief Bit_SET and Bit_RESET enumeration */ typedef enum { Bit_RESET = 0, Bit_SET }BitAction; #define IS_GPIO_BIT_ACTION(ACTION) (((ACTION) == Bit_RESET) || ((ACTION) == Bit_SET)) /** * @} */ /** @defgroup GPIO_Exported_Constants * @{ */ /** @defgroup GPIO_pins_define * @{ */ #define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */ #define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */ #define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */ #define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */ #define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */ #define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */ #define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */ #define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */ #define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */ #define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */ #define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */ #define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */ #define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */ #define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */ #define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */ #define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */ #define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */ #define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00)) #define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || \ ((PIN) == GPIO_Pin_1) || \ ((PIN) == GPIO_Pin_2) || \ ((PIN) == GPIO_Pin_3) || \ ((PIN) == GPIO_Pin_4) || \ ((PIN) == GPIO_Pin_5) || \ ((PIN) == GPIO_Pin_6) || \ ((PIN) == GPIO_Pin_7) || \ ((PIN) == GPIO_Pin_8) || \ ((PIN) == GPIO_Pin_9) || \ ((PIN) == GPIO_Pin_10) || \ ((PIN) == GPIO_Pin_11) || \ ((PIN) == GPIO_Pin_12) || \ ((PIN) == GPIO_Pin_13) || \ ((PIN) == GPIO_Pin_14) || \ ((PIN) == GPIO_Pin_15)) /** * @} */ /** @defgroup GPIO_Remap_define * @{ */ #define GPIO_Remap_SPI1 ((uint32_t)0x00000001) /*!< SPI1 Alternate Function mapping */ #define GPIO_Remap_I2C1 ((uint32_t)0x00000002) /*!< I2C1 Alternate Function mapping */ #define GPIO_Remap_USART1 ((uint32_t)0x00000004) /*!< USART1 Alternate Function mapping */ #define GPIO_Remap_USART2 ((uint32_t)0x00000008) /*!< USART2 Alternate Function mapping */ #define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010) /*!< USART3 Partial Alternate Function mapping */ #define GPIO_FullRemap_USART3 ((uint32_t)0x00140030) /*!< USART3 Full Alternate Function mapping */ #define GPIO_PartialRemap_TIM1 ((uint32_t)0x00160040) /*!< TIM1 Partial Alternate Function mapping */ #define GPIO_FullRemap_TIM1 ((uint32_t)0x001600C0) /*!< TIM1 Full Alternate Function mapping */ #define GPIO_PartialRemap1_TIM2 ((uint32_t)0x00180100) /*!< TIM2 Partial1 Alternate Function mapping */ #define GPIO_PartialRemap2_TIM2 ((uint32_t)0x00180200) /*!< TIM2 Partial2 Alternate Function mapping */ #define GPIO_FullRemap_TIM2 ((uint32_t)0x00180300) /*!< TIM2 Full Alternate Function mapping */ #define GPIO_PartialRemap_TIM3 ((uint32_t)0x001A0800) /*!< TIM3 Partial Alternate Function mapping */ #define GPIO_FullRemap_TIM3 ((uint32_t)0x001A0C00) /*!< TIM3 Full Alternate Function mapping */ #define GPIO_Remap_TIM4 ((uint32_t)0x00001000) /*!< TIM4 Alternate Function mapping */ #define GPIO_Remap1_CAN1 ((uint32_t)0x001D4000) /*!< CAN1 Alternate Function mapping */ #define GPIO_Remap2_CAN1 ((uint32_t)0x001D6000) /*!< CAN1 Alternate Function mapping */ #define GPIO_Remap_PD01 ((uint32_t)0x00008000) /*!< PD01 Alternate Function mapping */ #define GPIO_Remap_TIM5CH4_LSI ((uint32_t)0x00200001) /*!< LSI connected to TIM5 Channel4 input capture for calibration */ #define GPIO_Remap_ADC1_ETRGINJ ((uint32_t)0x00200002) /*!< ADC1 External Trigger Injected Conversion remapping */ #define GPIO_Remap_ADC1_ETRGREG ((uint32_t)0x00200004) /*!< ADC1 External Trigger Regular Conversion remapping */ #define GPIO_Remap_ADC2_ETRGINJ ((uint32_t)0x00200008) /*!< ADC2 External Trigger Injected Conversion remapping */ #define GPIO_Remap_ADC2_ETRGREG ((uint32_t)0x00200010) /*!< ADC2 External Trigger Regular Conversion remapping */ #define GPIO_Remap_ETH ((uint32_t)0x00200020) /*!< Ethernet remapping (only for Connectivity line devices) */ #define GPIO_Remap_CAN2 ((uint32_t)0x00200040) /*!< CAN2 remapping (only for Connectivity line devices) */ #define GPIO_Remap_SWJ_NoJTRST ((uint32_t)0x00300100) /*!< Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST */ #define GPIO_Remap_SWJ_JTAGDisable ((uint32_t)0x00300200) /*!< JTAG-DP Disabled and SW-DP Enabled */ #define GPIO_Remap_SWJ_Disable ((uint32_t)0x00300400) /*!< Full SWJ Disabled (JTAG-DP + SW-DP) */ #define GPIO_Remap_SPI3 ((uint32_t)0x00201100) /*!< SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices) */ #define GPIO_Remap_TIM2ITR1_PTP_SOF ((uint32_t)0x00202000) /*!< Ethernet PTP output or USB OTG SOF (Start of Frame) connected to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices) */ #define GPIO_Remap_PTP_PPS ((uint32_t)0x00204000) /*!< Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices) */ #define GPIO_Remap_TIM15 ((uint32_t)0x80000001) /*!< TIM15 Alternate Function mapping (only for Value line devices) */ #define GPIO_Remap_TIM16 ((uint32_t)0x80000002) /*!< TIM16 Alternate Function mapping (only for Value line devices) */ #define GPIO_Remap_TIM17 ((uint32_t)0x80000004) /*!< TIM17 Alternate Function mapping (only for Value line devices) */ #define GPIO_Remap_CEC ((uint32_t)0x80000008) /*!< CEC Alternate Function mapping (only for Value line devices) */ #define GPIO_Remap_TIM1_DMA ((uint32_t)0x80000010) /*!< TIM1 DMA requests mapping (only for Value line devices) */ #define GPIO_Remap_TIM9 ((uint32_t)0x80000020) /*!< TIM9 Alternate Function mapping (only for XL-density devices) */ #define GPIO_Remap_TIM10 ((uint32_t)0x80000040) /*!< TIM10 Alternate Function mapping (only for XL-density devices) */ #define GPIO_Remap_TIM11 ((uint32_t)0x80000080) /*!< TIM11 Alternate Function mapping (only for XL-density devices) */ #define GPIO_Remap_TIM13 ((uint32_t)0x80000100) /*!< TIM13 Alternate Function mapping (only for High density Value line and XL-density devices) */ #define GPIO_Remap_TIM14 ((uint32_t)0x80000200) /*!< TIM14 Alternate Function mapping (only for High density Value line and XL-density devices) */ #define GPIO_Remap_FSMC_NADV ((uint32_t)0x80000400) /*!< FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices) */ #define GPIO_Remap_TIM67_DAC_DMA ((uint32_t)0x80000800) /*!< TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices) */ #define GPIO_Remap_TIM12 ((uint32_t)0x80001000) /*!< TIM12 Alternate Function mapping (only for High density Value line devices) */ #define GPIO_Remap_MISC ((uint32_t)0x80002000) /*!< Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, only for High density Value line devices) */ #define IS_GPIO_REMAP(REMAP) (((REMAP) == GPIO_Remap_SPI1) || ((REMAP) == GPIO_Remap_I2C1) || \ ((REMAP) == GPIO_Remap_USART1) || ((REMAP) == GPIO_Remap_USART2) || \ ((REMAP) == GPIO_PartialRemap_USART3) || ((REMAP) == GPIO_FullRemap_USART3) || \ ((REMAP) == GPIO_PartialRemap_TIM1) || ((REMAP) == GPIO_FullRemap_TIM1) || \ ((REMAP) == GPIO_PartialRemap1_TIM2) || ((REMAP) == GPIO_PartialRemap2_TIM2) || \ ((REMAP) == GPIO_FullRemap_TIM2) || ((REMAP) == GPIO_PartialRemap_TIM3) || \ ((REMAP) == GPIO_FullRemap_TIM3) || ((REMAP) == GPIO_Remap_TIM4) || \ ((REMAP) == GPIO_Remap1_CAN1) || ((REMAP) == GPIO_Remap2_CAN1) || \ ((REMAP) == GPIO_Remap_PD01) || ((REMAP) == GPIO_Remap_TIM5CH4_LSI) || \ ((REMAP) == GPIO_Remap_ADC1_ETRGINJ) ||((REMAP) == GPIO_Remap_ADC1_ETRGREG) || \ ((REMAP) == GPIO_Remap_ADC2_ETRGINJ) ||((REMAP) == GPIO_Remap_ADC2_ETRGREG) || \ ((REMAP) == GPIO_Remap_ETH) ||((REMAP) == GPIO_Remap_CAN2) || \ ((REMAP) == GPIO_Remap_SWJ_NoJTRST) || ((REMAP) == GPIO_Remap_SWJ_JTAGDisable) || \ ((REMAP) == GPIO_Remap_SWJ_Disable)|| ((REMAP) == GPIO_Remap_SPI3) || \ ((REMAP) == GPIO_Remap_TIM2ITR1_PTP_SOF) || ((REMAP) == GPIO_Remap_PTP_PPS) || \ ((REMAP) == GPIO_Remap_TIM15) || ((REMAP) == GPIO_Remap_TIM16) || \ ((REMAP) == GPIO_Remap_TIM17) || ((REMAP) == GPIO_Remap_CEC) || \ ((REMAP) == GPIO_Remap_TIM1_DMA) || ((REMAP) == GPIO_Remap_TIM9) || \ ((REMAP) == GPIO_Remap_TIM10) || ((REMAP) == GPIO_Remap_TIM11) || \ ((REMAP) == GPIO_Remap_TIM13) || ((REMAP) == GPIO_Remap_TIM14) || \ ((REMAP) == GPIO_Remap_FSMC_NADV) || ((REMAP) == GPIO_Remap_TIM67_DAC_DMA) || \ ((REMAP) == GPIO_Remap_TIM12) || ((REMAP) == GPIO_Remap_MISC)) /** * @} */ /** @defgroup GPIO_Port_Sources * @{ */ #define GPIO_PortSourceGPIOA ((uint8_t)0x00) #define GPIO_PortSourceGPIOB ((uint8_t)0x01) #define GPIO_PortSourceGPIOC ((uint8_t)0x02) #define GPIO_PortSourceGPIOD ((uint8_t)0x03) #define GPIO_PortSourceGPIOE ((uint8_t)0x04) #define GPIO_PortSourceGPIOF ((uint8_t)0x05) #define GPIO_PortSourceGPIOG ((uint8_t)0x06) #define IS_GPIO_EVENTOUT_PORT_SOURCE(PORTSOURCE) (((PORTSOURCE) == GPIO_PortSourceGPIOA) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOB) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOC) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOD) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOE)) #define IS_GPIO_EXTI_PORT_SOURCE(PORTSOURCE) (((PORTSOURCE) == GPIO_PortSourceGPIOA) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOB) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOC) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOD) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOE) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOF) || \ ((PORTSOURCE) == GPIO_PortSourceGPIOG)) /** * @} */ /** @defgroup GPIO_Pin_sources * @{ */ #define GPIO_PinSource0 ((uint8_t)0x00) #define GPIO_PinSource1 ((uint8_t)0x01) #define GPIO_PinSource2 ((uint8_t)0x02) #define GPIO_PinSource3 ((uint8_t)0x03) #define GPIO_PinSource4 ((uint8_t)0x04) #define GPIO_PinSource5 ((uint8_t)0x05) #define GPIO_PinSource6 ((uint8_t)0x06) #define GPIO_PinSource7 ((uint8_t)0x07) #define GPIO_PinSource8 ((uint8_t)0x08) #define GPIO_PinSource9 ((uint8_t)0x09) #define GPIO_PinSource10 ((uint8_t)0x0A) #define GPIO_PinSource11 ((uint8_t)0x0B) #define GPIO_PinSource12 ((uint8_t)0x0C) #define GPIO_PinSource13 ((uint8_t)0x0D) #define GPIO_PinSource14 ((uint8_t)0x0E) #define GPIO_PinSource15 ((uint8_t)0x0F) #define IS_GPIO_PIN_SOURCE(PINSOURCE) (((PINSOURCE) == GPIO_PinSource0) || \ ((PINSOURCE) == GPIO_PinSource1) || \ ((PINSOURCE) == GPIO_PinSource2) || \ ((PINSOURCE) == GPIO_PinSource3) || \ ((PINSOURCE) == GPIO_PinSource4) || \ ((PINSOURCE) == GPIO_PinSource5) || \ ((PINSOURCE) == GPIO_PinSource6) || \ ((PINSOURCE) == GPIO_PinSource7) || \ ((PINSOURCE) == GPIO_PinSource8) || \ ((PINSOURCE) == GPIO_PinSource9) || \ ((PINSOURCE) == GPIO_PinSource10) || \ ((PINSOURCE) == GPIO_PinSource11) || \ ((PINSOURCE) == GPIO_PinSource12) || \ ((PINSOURCE) == GPIO_PinSource13) || \ ((PINSOURCE) == GPIO_PinSource14) || \ ((PINSOURCE) == GPIO_PinSource15)) /** * @} */ /** @defgroup Ethernet_Media_Interface * @{ */ #define GPIO_ETH_MediaInterface_MII ((u32)0x00000000) #define GPIO_ETH_MediaInterface_RMII ((u32)0x00000001) #define IS_GPIO_ETH_MEDIA_INTERFACE(INTERFACE) (((INTERFACE) == GPIO_ETH_MediaInterface_MII) || \ ((INTERFACE) == GPIO_ETH_MediaInterface_RMII)) /** * @} */ /** * @} */ /** @defgroup GPIO_Exported_Macros * @{ */ /** * @} */ /** @defgroup GPIO_Exported_Functions * @{ */ void GPIO_DeInit(GPIO_TypeDef* GPIOx); void GPIO_AFIODeInit(void); void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); void GPIO_EventOutputCmd(FunctionalState NewState); void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState); void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface); #ifdef __cplusplus } #endif #endif /* __STM32F10x_GPIO_H */ /** * @} */ /** * @} */ /** * @} */ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 将上述代码改为HAL库
07-25
后面我将给你一个IPC的dhcps模块,给我注释,大概1000行代码, /* dhcps.h */ #ifndef _DHCPS_H #define _DHCPS_H #include "dhcp.h" #define MAX_FILE_NAME_LEN 256 #define MAX_BOOTP_SRV_NAME_LEN 16 #define DHCPS_DOMAIN_NAME_LENGTH 32 #define DHCP_4G_ROUTER_STR "4g router" #define DHCP_4G_ROUTER_LEN 9 /***************************************************************************************** **********************DHCPS SERVER CLASS************************************************** *****************************************************************************************/ #define DHCPS_LEASE_LIST_SIZE 128 typedef struct _DHCPS_LEASE { U8 host_name[32]; U8 mac[6]; U32 state; U32 ip; U32 expires; }DHCPS_LEASE; typedef struct _DHCP_OPTION_STATIC { UINT8 lease[6]; UINT8 subnet[6]; UINT8 router[6]; UINT8 dns[10]; char domain[34]; UINT8 router4g[DHCP_4G_ROUTER_LEN+2]; }DHCP_OPTION_STATIC; /* Struct to store public server config.*/ typedef struct _DHCPS_PARAMS { S32 sock; /* Berkeley Packet Filter Device in vxworks OS or skt in linux OS */ S32 inet_iendx; S32 timer_index; char dev_name[32]; S32 dev; UINT8 mac[6]; /* Our mac address */ U32 decline_time; /* how long an address is reserved if a client returns a * decline message */ U32 conflict_time; /* how long an arp conflict offender is leased for */ U32 offer_time; /* how long an offered address is reserved */ U32 min_lease; /* minimum lease a client can request*/ U32 server; /* Our IP, in network order */ U32 netmask; /* Our netmask */ U32 gateway; /*added by yangying for*/ U32 dns_server[2]; char host_name[DHCPS_DOMAIN_NAME_LENGTH]; DHCP_OPTION_STATIC options; /* List of DHCP options loaded from the config file */ U32 start; /* Start address of leases, network order */ U32 end; /* End of leases, network order */ U32 lease_time; /* lease time in seconds (host order) */ U32 siaddr; /* next server bootp option */ char sname[MAX_BOOTP_SRV_NAME_LEN]; /* bootp server name */ char boot_file[MAX_FILE_NAME_LEN]; /* bootp boot file option */ DHCPS_LEASE lease[DHCPS_LEASE_LIST_SIZE]; U16 is_lte; }DHCPS_PARAMS; #define DHCPS_DEBUG(fmt, ...) NSD_DEBUG("[DHCPS]" fmt, ##__VA_ARGS__) #define DHCPS_INFO(fmt, ...) NSD_LOG(LOG_INFO, "[Network][DHCP]" fmt, ##__VA_ARGS__) #define DHCPS_WARN(fmt, ...) NSD_WARN("[DHCPS]" fmt, ##__VA_ARGS__) #endif /* dhcps.c * * udhcp Server * Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au> * Chris Trew <ctrew@moreton.com.au> * * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <netinet/if_ether.h> #include <linux/filter.h> #include <linux/if_packet.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include "options.h" #include "packet.h" #include "dhcp.h" #include "dhcps.h" #include "libds.h" /* DHCPS模块中各个参数项单位都改为秒 */ #define LEASE_TIME_MAX (48*60*60) /* 租期最长2天 */ #define LEASE_TIME_MIN (1*60) /* 租期最短一分钟 */ #define LEASE_OFFER_TIME (2*60*60) #define DECLINE_TIME (60*60) #define CONFLICT_TIME (60*60) #define DHCP_CHANGE_RECEIVE_PORT 52261 #define DHCP_CHANGE_SEND_PORT 52262 #define DEFAULT_DHCPS_IP "192.168.191.1" #define DEFAULT_DHCPS_MASK "255.255.255.0" #define DEF_DHCPS_IP_BEGIN "192.168.191.120" #define DEF_DHCPS_IP_END "192.168.191.199" #define DHCPS_HOST_NAME_LEN 32 #define DHCPS_OPTION_AUTO "auto" #define DHCPS_OPTION_ENABLE "enable" #define DHCPS_OPTION_POOLSTART "pool_start" #define DHCPS_OPTION_POOLEND "pool_end" #define DHCPS_OPTION_LEASETIME "lease_time" #define DHCPS_OPTION_GATEWAY "gateway" #define DHCPS_OPTION_PRIDNS "pri_dns" #define DHCPS_OPTION_SNDDNS "snd_dns" #define DHCPS_OPTION_IP "ip" #define DHCPS_OPTION_MAC "mac" #define DHCPS_OPTION_EXPIRES "expires" #define DHCPS_OPTION_HOSTNAME "hostname" DHCPS_PARAMS dhcps_params; LOCAL struct dhcp_packet recv_dhcp_packet; LOCAL struct dhcp_packet packet; #define DHCPS_MALLOC(size) malloc(size) #define DHCPS_FREE(addr) free((UINT8*)(addr)) #define ISNOTSAMESUBNET(ip1, ip2, mask) (0 != (((ip1) ^ (ip2)) & (mask))) /* 是否4G IPC - 4G上网模式 */ LOCAL U16 get_lte_enabled(void) { LTE_CAPABILITY lte_cap = {0}; LTE_CONFIG_INFO_DATA lte_config = {0}; if (0 == ds_read(LTE_CAPABILITY_PATH, (U8 *)&lte_cap, sizeof(lte_cap))) { //未定义lte_capability,判断为非4G IPC,未开启4G上网模式 return 0; } if (0 == ds_read(LTE_INFO_DATA_PATH, (U8 *)&lte_config, sizeof(lte_config))) { //4G IPC默认4G上网模式,获取失败时按照4G上网处理 return 1; } return !(lte_cap.internet_wired_support && lte_config.internet_wired_enable); } /* clear every lease out that chaddr OR yiaddr matches and is nonzero */ LOCAL void clear_lease(U8 *mac, U32 ip, DHCPS_LEASE *leases) { S32 i, j, k; for (j = 0; j < CHADDR_LEN && !mac[j]; j++); for (i = 0; i < DHCPS_LEASE_LIST_SIZE; i++) { if ((j != CHADDR_LEN && !memcmp(leases[i].mac, mac, 6)) || (ip && leases[i].ip == ip)) { memset(&(leases[i]), 0, sizeof(leases[i])); for (k = i;(k + 1) < DHCPS_LEASE_LIST_SIZE; k++) { memcpy(&(leases[k]), &(leases[k + 1]), sizeof(leases[k])); memset(&(leases[k + 1]), 0, sizeof(leases[k + 1])); } i--; } } } /* Find the oldest expired lease, NULL if there are no expired leases */ LOCAL S32 oldest_expired_lease(DHCPS_LEASE *leases) { U32 i; for (i = 0; i < DHCPS_LEASE_LIST_SIZE; i++) { if (leases[i].expires == 0) { return i; } } return -1; } /* add a lease into the table, clearing out any old ones */ LOCAL S32 add_lease(U32 state, char *host_name, U8 *mac, U32 ip, U32 time_lease, DHCPS_LEASE *dhcps_lease) { S32 lease_index = -1 ; IP_ADDR ipAddr = {0}; /* clean out any old ones */ clear_lease(mac, ip, dhcps_lease); lease_index = oldest_expired_lease(dhcps_lease); if (lease_index != -1) { dhcps_lease[lease_index].state = state; DHCPS_DEBUG("state = %d", dhcps_lease[lease_index].state); memcpy(dhcps_lease[lease_index].host_name, host_name, 32); /* add by Li Shaozhang, 07Jun07 */ DHCPS_DEBUG("hostname = %s", dhcps_lease[lease_index].host_name); memcpy(dhcps_lease[lease_index].mac, mac, 6); DHCPS_DEBUG("mac = %02x-%02x-%02x-%02x-%02x-%02x", dhcps_lease[lease_index].mac[0],\ dhcps_lease[lease_index].mac[1], dhcps_lease[lease_index].mac[2],\ dhcps_lease[lease_index].mac[3], dhcps_lease[lease_index].mac[4],\ dhcps_lease[lease_index].mac[5]); dhcps_lease[lease_index].ip = ip; ipAddr.ipAddr = ip; DHCPS_DEBUG("ip = %d.%d.%d.%d", ipAddr.ipAddrByteFormat[0], ipAddr.ipAddrByteFormat[1], ipAddr.ipAddrByteFormat[2], ipAddr.ipAddrByteFormat[3]); dhcps_lease[lease_index].expires = time_lease; DHCPS_DEBUG("lease = %d", dhcps_lease[lease_index].expires); } return lease_index; } /* true if a lease has expired */ LOCAL S32 lease_expired(S32 lease_index, DHCPS_LEASE *dhcps_lease) { return (dhcps_lease[lease_index].expires == 0); } /* * Find the first lease that matches chaddr, NULL if no match. * Modified by xcl, if the lease ip is not in the same subnet, deleted it and return null. */ LOCAL S32 find_lease_by_mac(U8 *mac, DHCPS_LEASE *dhcps_lease) { U32 i; for (i = 0; i < DHCPS_LEASE_LIST_SIZE; i++) { if (!memcmp(dhcps_lease[i].mac, mac, 6)) { /* If not in the very subnet, delete this lease. Modified by xcl.*/ if (0 == ((dhcps_lease[i].ip ^ dhcps_params.server) & dhcps_params.netmask)) { return i; } memset(&(dhcps_lease[i]), 0, sizeof(dhcps_lease[i])); } } return -1; } /* Find the first lease that matches yiaddr, NULL is no match */ LOCAL S32 find_lease_by_ip(U32 ip, DHCPS_LEASE *dhcps_lease) { U32 i; for (i = 0; i < DHCPS_LEASE_LIST_SIZE; i++) { if (dhcps_lease[i].ip == ip) { return i; } } return -1; } /* check is an IP is taken, if it is, add it to the lease table */ LOCAL S32 check_ip(U32 addr, DHCPS_LEASE *dhcps_lease) { char strIp[18] = {0}; /* Added for bug: dut会将lan IP(若在地址池范围内)分配出去,若收到此IP的Client无 * 免费arp检查功能,将导致IP冲突. 2011-12-27, xcl.*/ if (addr == dhcps_params.server) { DHCPS_WARN("The IP distributed equals to server ip, ignore!!!"); return 1; } if (0 == arpping(addr, recv_dhcp_packet.chaddr, dhcps_params.server, dhcps_params.mac, dhcps_params.dev_name, 500)) { DHCPS_WARN("%s belongs to someone, reserving it for %ld seconds.", strIp, dhcps_params.conflict_time); return 1; } return 0; } /* Check if an ip is in dhcp server pool or not. */ LOCAL S32 ip_in_srv_pool(U32 ip) { IP_ADDR ipAddr = {0}; ipAddr.ipAddr = ip; ip = ntohl(ip); if ((ip >= ntohl(dhcps_params.start)) && (ip <= ntohl(dhcps_params.end)) && (ip != ntohl(dhcps_params.server))) { return 1; } DHCPS_WARN("IP(%d.%d.%d.%d) not in dhcp pool or equal to server ip, ignore!!!", ipAddr.ipAddrByteFormat[0], ipAddr.ipAddrByteFormat[1], ipAddr.ipAddrByteFormat[2], ipAddr.ipAddrByteFormat[3]); return 0; } /* find an assignable address, it check_expired is true, we check all the expired leases as well. * Maybe this should try expired leases by age... */ LOCAL U32 find_address(S32 check_expired, DHCPS_LEASE *dhcps_lease) { U32 addrStart, addrEnd; /* 主机序,用于遍历地址池 */ U32 ret; /* 网络序,存放查找到的地址 */ S32 lease_index = -1; U32 mask = 0; mask = ntohl(dhcps_params.netmask); addrStart = ntohl(dhcps_params.start); addrEnd = ntohl(dhcps_params.end); for (; addrStart <= addrEnd; addrStart++)/* Modified by xcl, 2011-06-01.*/ { ret = htonl(addrStart); /* ie, 192.168.55.0 */ if (!(ret & (~mask))) { continue; } /* ie, 192.168.55.255 */ if ((ret & (~mask)) == (~mask)) { continue; } /* ip已被dhcps分配出去 */ if (-1 != (lease_index = find_lease_by_ip(ret, dhcps_lease))) { if (check_expired && lease_expired(lease_index, dhcps_lease)) { return ret; } continue; } /* 有静态接入主机正在使用该IP也要跳过 */ if (TRUE == check_ip(ret, dhcps_lease)) { continue; } return ret; } return 0; } /* send a dhcp packet, if force broadcast is set, the packet will be broadcast to the client */ LOCAL S32 send_packet(struct dhcp_packet *payload, S32 force_broadcast) { U8 *chaddr = NULL; U32 ciaddr = 0; if (force_broadcast) { DHCPS_DEBUG("Broadcasting packet to client (NAK)."); ciaddr = INADDR_BROADCAST; chaddr = MAC_BCAST_ADDR; } else if (ntohs(payload->flags) & BROADCAST_FLAG) { DHCPS_DEBUG("Broadcasting packet to client (requested)."); ciaddr = INADDR_BROADCAST; chaddr = MAC_BCAST_ADDR; } else if ((0 == payload->yiaddr) && (payload->ciaddr)) { DHCPS_DEBUG("Unicasting packet to client ciaddr."); ciaddr = payload->ciaddr; chaddr = payload->chaddr; } else { ciaddr = payload->yiaddr; chaddr = payload->chaddr; } return make_and_send_dhcp_frame(payload, dhcps_params.server, SERVER_PORT, ciaddr, CLIENT_PORT, chaddr, dhcps_params.dev); } LOCAL void init_packet(struct dhcp_packet *packet, struct dhcp_packet *old_packet, char type) { init_header(packet, type); packet->xid = old_packet->xid; memcpy(packet->chaddr, old_packet->chaddr, CHADDR_LEN); packet->flags = old_packet->flags; packet->giaddr = old_packet->giaddr; packet->ciaddr = old_packet->ciaddr; add_simple_option(packet->options, DHCP_SERVER_ID, dhcps_params.server); } /* add in the bootp options */ LOCAL void add_bootp_options(struct dhcp_packet *packet) { packet->siaddr = dhcps_params.siaddr; if (dhcps_params.sname) { strncpy((char *)packet->sname, dhcps_params.sname, sizeof(packet->sname) - 1); } if (dhcps_params.boot_file) { strncpy((char *)packet->file, dhcps_params.boot_file, sizeof(packet->file) - 1); } } LOCAL S32 get_host_name_len(char* name, S32 len) { S32 index = 0; S32 language_flag = 0; if (len < 32) { return len; } for (index=0; index < 31; index++) { /* GB2312编码每个汉字及符号以两个字节来表示,高位字节使用了0xA1-0xF7,低位字节使用了0xA1-0xFE。*/ /* 为保障存储汉字不出现乱码,出现奇数个大于0xA1的字节时,去掉最后一个。这种方法只能解决采用 */ /* GB2312编码的乱码问题 */ if (*(UINT8*)(name + index) >= 0xA1) { language_flag ^= 1; } } if (language_flag == 0) { return 31; } return 30; } /* send a DHCP OFFER to a DHCP DISCOVER */ LOCAL S32 send_offer(struct dhcp_packet *old_packet, DHCPS_LEASE *dhcps_lease) { S32 lease_index = -1; U32 req_align, lease_time_align = dhcps_params.lease_time; U8 *req, *lease_time; char blank_hostname[] = /*"Unknown"*/""; S32 copy_host_name_len; IP_ADDR ip_addr = {0}; char host_name[DHCPS_HOST_NAME_LEN]; char *host_name_start, *host_name_len; U32 lease_ip; DHCPS_DEBUG("before init_packet."); init_packet(&packet, old_packet, DHCPOFFER); /* the client has a requested ip */ if ((req = get_option(old_packet, DHCP_REQUESTED_IP)) && memcpy(&req_align, req, 4) && ip_in_srv_pool(req_align) && (((-1 == (lease_index = find_lease_by_ip(req_align, dhcps_lease))) || lease_expired(lease_index, dhcps_lease)))) { lease_ip = req_align; if (TRUE == check_ip(lease_ip, dhcps_lease)) { goto choose_dynamic_lease_ip; } packet.yiaddr = lease_ip; goto send_offer; } choose_dynamic_lease_ip: lease_index = find_lease_by_mac(old_packet->chaddr, dhcps_lease); if (-1 != lease_index) { /* lease的时间到期或者ip已经不在地址池中。 */ if ((FALSE == ip_in_srv_pool(dhcps_lease[lease_index].ip)) || lease_expired(lease_index, dhcps_lease)) { memset(&(dhcps_lease[lease_index]), 0, sizeof(dhcps_lease[lease_index])); lease_index = -1; goto choose_pool_ip; } lease_time_align = dhcps_lease[lease_index].expires; packet.yiaddr = dhcps_lease[lease_index].ip; goto send_offer; } choose_pool_ip: packet.yiaddr = find_address(0, dhcps_lease); if (0 == packet.yiaddr) { packet.yiaddr = find_address(1, dhcps_lease); } if(0 == packet.yiaddr) { DHCPS_WARN("No ip addresses to give, OFFER abandoned."); return -1; } send_offer: if (0xFFFFFFFF != lease_time_align) /* 非静态条目。 */ { if (!(host_name_start = (char *)get_option(old_packet, DHCP_HOST_NAME))) { DHCPS_WARN("Lease host name not found."); /* host_name_start = blank_hostname;*/ memset(host_name, 0, DHCPS_HOST_NAME_LEN); memcpy(host_name, blank_hostname, strlen(blank_hostname)); } else { host_name_len = host_name_start - OPT_LEN; memset(host_name, 0, DHCPS_HOST_NAME_LEN); /* fix host name length bug by tiger 20091208 */ copy_host_name_len = get_host_name_len(host_name_start, *host_name_len); memcpy(host_name, host_name_start, copy_host_name_len); } if (-1 == add_lease(DHCPOFFER, host_name, packet.chaddr, packet.yiaddr, dhcps_params.offer_time, dhcps_lease)) { DHCPS_WARN("Lease pool is full, OFFER abandoned."); return -1; } if ((lease_time = get_option(old_packet, DHCP_LEASE_TIME))) { memcpy(&lease_time_align, lease_time, 4); DHCPS_DEBUG("lease time = %d ", lease_time); lease_time_align = ntohl(lease_time_align); if (lease_time_align > (dhcps_params.lease_time*60)) { lease_time_align = (dhcps_params.lease_time*60); } } /* Make sure we aren't just using the lease time from the previous offer */ if (lease_time_align < dhcps_params.min_lease) { lease_time_align = dhcps_params.lease_time; } } DHCPS_DEBUG("OFFER lease time = %d; configed dhcp lease = %d\n", lease_time_align, dhcps_params.lease_time); add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_align)); add_option_string(packet.options, dhcps_params.options.dns); add_option_string(packet.options, dhcps_params.options.subnet); add_option_string(packet.options, dhcps_params.options.router); if(dhcps_params.is_lte) { DHCPS_DEBUG("OFFER: lte enabled\n"); add_option_string(packet.options, dhcps_params.options.router4g); } /*addVendorSpecInfo(oldpacket, packet.options);*/ add_bootp_options(&packet); ip_addr.ipAddr = packet.yiaddr; DHCPS_INFO("Send OFFER with ip %d.%d.%d.%d.", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); return send_packet(&packet, 0); } LOCAL S32 send_NAK(struct dhcp_packet *old_packet) { init_packet(&packet, old_packet, DHCPNAK); return send_packet(&packet, 1); } LOCAL S32 send_ACK(struct dhcp_packet *old_packet, U32 ip, DHCPS_LEASE *dhcps_lease) { U8 *lease_time; U32 lease_time_align = dhcps_params.lease_time; char blank_hostname[] = /*"Unknown"*/""; IP_ADDR ipAddr = {0}; U8 host_name[DHCPS_HOST_NAME_LEN]; U8 *host_name_start = NULL; U8 *host_name_len = NULL; S32 copy_host_name_len = 0; init_packet(&packet, old_packet, DHCPACK); packet.yiaddr = ip; if ((lease_time = get_option(old_packet, DHCP_LEASE_TIME))) { memcpy(&lease_time_align, lease_time, 4); lease_time_align = ntohl(lease_time_align); if ((lease_time_align < dhcps_params.min_lease) || (lease_time_align > dhcps_params.lease_time)) { lease_time_align = dhcps_params.lease_time; } } DHCPS_DEBUG("ACK lease time = %d\n", lease_time_align); add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_align)); add_option_string(packet.options, dhcps_params.options.dns); add_option_string(packet.options, dhcps_params.options.subnet); add_option_string(packet.options, dhcps_params.options.router); if(dhcps_params.is_lte) { DHCPS_DEBUG("ACK: lte enabled\n"); add_option_string(packet.options, dhcps_params.options.router4g); } /*addVendorSpecInfo(oldpacket, packet.options);*/ add_bootp_options(&packet); ipAddr.ipAddr = packet.yiaddr; DHCPS_DEBUG("Send ACK to %d.%d.%d.%d.", ipAddr.ipAddrByteFormat[0], ipAddr.ipAddrByteFormat[1], ipAddr.ipAddrByteFormat[2], ipAddr.ipAddrByteFormat[3]); /* TODO:只在请求OFFER时输出信息 */ if (send_packet(&packet, 0) < 0) { return -1; } if (!(host_name_start = get_option(old_packet, DHCP_HOST_NAME))) { DHCPS_DEBUG("Lease host name not found."); /* TODO:只在请求OFFER时输出信息 */ memset(host_name, 0, DHCPS_HOST_NAME_LEN); memcpy(host_name, blank_hostname, strlen(blank_hostname)); } else { /* fix host name length bug by tiger 20091208 */ host_name_len = host_name_start - OPT_LEN; copy_host_name_len = get_host_name_len((char *)host_name_start, (int)*host_name_len); if(copy_host_name_len > DHCPS_HOST_NAME_LEN) { return -1; } memset(host_name, 0, DHCPS_HOST_NAME_LEN); memcpy(host_name, host_name_start, copy_host_name_len); } add_lease(DHCPACK, (char *)host_name, packet.chaddr, packet.yiaddr, lease_time_align, dhcps_lease); return OK; } LOCAL S32 send_inform(struct dhcp_packet *old_packet) { init_packet(&packet, old_packet, DHCPACK); add_option_string(packet.options, dhcps_params.options.dns); add_option_string(packet.options, dhcps_params.options.subnet); add_option_string(packet.options, dhcps_params.options.router); if(dhcps_params.is_lte) { DHCPS_DEBUG("INFORM: lte enabled\n"); add_option_string(packet.options, dhcps_params.options.router4g); } add_bootp_options(&packet); return send_packet(&packet, 0); } LOCAL S32 check_and_ack(struct dhcp_packet* packet, UINT32 ip, DHCPS_LEASE *dhcps_lease) { IP_ADDR ip_addr1 = {0}; ip_addr1.ipAddr = ip; /* if some one reserve it */ if (ip != packet->ciaddr && check_ip(ip, dhcps_lease)) { DHCPS_INFO("REQUEST ip %d.%d.%d.%d already reserved by someone", ip_addr1.ipAddrByteFormat[0], ip_addr1.ipAddrByteFormat[1], ip_addr1.ipAddrByteFormat[2] ,ip_addr1.ipAddrByteFormat[3]); return send_NAK(packet); } if (!ip_in_srv_pool(ip)) { DHCPS_INFO("REQUEST ip %d.%d.%d.%d is not in the address pool", ip_addr1.ipAddrByteFormat[0], ip_addr1.ipAddrByteFormat[1], ip_addr1.ipAddrByteFormat[2] ,ip_addr1.ipAddrByteFormat[3]); return send_NAK(packet); } return send_ACK(packet, ip, dhcps_lease); } LOCAL void destroy_sock(S32 sock) { if (-1 != sock) { close(sock); } } LOCAL S32 create_sock() { struct sockaddr_in sock_addr; S32 option = 1; S32 sock = -1; /* 因为MAX_GROUP_NUM为1,而且这里也只有1份DHCP服务器配置,这里就暂不考虑为多网段提供DHCP服务了。 */ if (ERROR == (sock = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPS_WARN("server socket call failed: %m"); goto error_exit; } if (ERROR == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPS_WARN("server socket set reuseaddr option failed: %m"); goto error_exit; } if (ERROR == setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &option, sizeof(option))) { DHCPS_WARN("server socket set broadcast option failed: %m"); goto error_exit; } memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_port = htons(SERVER_PORT); sock_addr.sin_addr.s_addr = INADDR_ANY; /* 这里只是针对单个网段提供服务,可以这样做,但如果考虑多网段,多接口,则必须绑定接口的实际地址。 */ if (ERROR == bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr))) { DHCPS_WARN("server socket set broadcast option failed: %m"); goto error_exit; } return sock; error_exit: destroy_sock(sock); return -1; } LOCAL void dhcps_check_timer() { U32 index = 0; U32 move_index = 0; DHCPS_LEASE *dhcps_lease = NULL; dhcps_lease = dhcps_params.lease; for (index = 0; index < DHCPS_LEASE_LIST_SIZE; index++) { if (dhcps_lease[index].ip == 0 || dhcps_lease[index].expires == 0xFFFFFFFF) { continue; } if (dhcps_lease[index].expires > 0) { dhcps_lease[index].expires -= 1; continue; } for (move_index = index; (move_index + 1) < DHCPS_LEASE_LIST_SIZE; move_index++) { memcpy(&(dhcps_lease[move_index]), &(dhcps_lease[move_index + 1]), sizeof(dhcps_lease[move_index])); memset(&(dhcps_lease[move_index + 1]), 0, sizeof(dhcps_lease[move_index + 1])); } index--; } } LOCAL void dhcps_handle(S32 sock) { U8 *server_id, *requested; U32 server_id_align, requested_align; S32 bytes = 0; U8 *state = NULL; S32 lease_index = -1; DHCPS_LEASE *dhcps_lease = NULL; U32 move_index = 0; IP_ADDR ip_addr1 = {0}; IP_ADDR ip_addr2 = {0}; dhcps_lease = dhcps_params.lease; if ((bytes = get_packet(&recv_dhcp_packet, dhcps_params.sock)) < 0) { DHCPS_WARN("Error on read, %m, reopening socket."); return; } if ((state = get_option(&recv_dhcp_packet, DHCP_MESSAGE_TYPE)) == NULL) { DHCPS_WARN("Couldn't get option from packet, ignoring."); return; } lease_index = find_lease_by_mac(recv_dhcp_packet.chaddr, dhcps_lease); if (-1 != lease_index) { /* 如果租约过期需要老化,或者租约与地址段不匹配,需要强制老化。 */ if ((lease_expired(lease_index, dhcps_lease)) || !ip_in_srv_pool(dhcps_lease[lease_index].ip)) { memset(&(dhcps_lease[lease_index]), 0, sizeof(dhcps_lease[lease_index])); lease_index = -1; } } switch (state[0]) { case DHCPDISCOVER: DHCPS_DEBUG("Recv DISCOVER from %02X:%02X:%02X:%02X:%02X:%02X.", recv_dhcp_packet.chaddr[0], recv_dhcp_packet.chaddr[1], recv_dhcp_packet.chaddr[2], recv_dhcp_packet.chaddr[3], recv_dhcp_packet.chaddr[4], recv_dhcp_packet.chaddr[5]); /* 防止被攻击时持续刷log */ if (send_offer(&recv_dhcp_packet, dhcps_lease) < 0) { DHCPS_WARN("Send OFFER failed."); } break; case DHCPREQUEST: DHCPS_DEBUG("Recv REQUEST from %02X:%02X:%02X:%02X:%02X:%02X.", recv_dhcp_packet.chaddr[0], recv_dhcp_packet.chaddr[1], recv_dhcp_packet.chaddr[2], recv_dhcp_packet.chaddr[3], recv_dhcp_packet.chaddr[4], recv_dhcp_packet.chaddr[5]); requested = get_option(&recv_dhcp_packet, DHCP_REQUESTED_IP); server_id = get_option(&recv_dhcp_packet, DHCP_SERVER_ID); if (NULL != requested) { memcpy(&requested_align, requested, 4); } if (NULL != server_id) { memcpy(&server_id_align, server_id, 4); } if (-1 != lease_index) { /* SELECTING State */ if ((NULL != server_id) && (server_id_align == dhcps_params.server) && (NULL != requested) && (requested_align == dhcps_lease[lease_index].ip)) { send_ACK(&recv_dhcp_packet, dhcps_lease[lease_index].ip, dhcps_lease); } /* INIT-REBOOT State */ else if ((NULL == server_id) && (NULL != requested) && (dhcps_lease[lease_index].ip == requested_align)) { send_ACK(&recv_dhcp_packet, dhcps_lease[lease_index].ip, dhcps_lease); } /* RENEWING or REBINDING State */ else if ((NULL == server_id) && (NULL == requested) && (dhcps_lease[lease_index].ip == recv_dhcp_packet.ciaddr)) { send_ACK(&recv_dhcp_packet, dhcps_lease[lease_index].ip, dhcps_lease); } else { /* todo: 显示有效的requested_align */ ip_addr1.ipAddr = recv_dhcp_packet.ciaddr; ip_addr2.ipAddr = dhcps_lease[lease_index].ip; DHCPS_INFO("Send NAK to %d.%d.%d.%d, lease ip %d.%d.%d.%d.", ip_addr1.ipAddrByteFormat[0], ip_addr1.ipAddrByteFormat[1], ip_addr1.ipAddrByteFormat[2] ,ip_addr1.ipAddrByteFormat[3], ip_addr2.ipAddrByteFormat[0], ip_addr2.ipAddrByteFormat[1],ip_addr2.ipAddrByteFormat[2], ip_addr2.ipAddrByteFormat[3]); send_NAK(&recv_dhcp_packet); } } else if (NULL != requested) { /* INIT-REBOOT State */ if (-1 != (lease_index = find_lease_by_ip(requested_align, dhcps_lease))) { /* Requested IP already reserved by other one */ if (lease_expired(lease_index, dhcps_lease)) { /* probably best if we drop this lease */ memset(&(dhcps_lease[lease_index]), 0, sizeof(dhcps_lease[lease_index])); lease_index = -1; check_and_ack(&recv_dhcp_packet, requested_align, dhcps_lease); /* make some contention for this address */ } else /* still reserved by someone */ { ip_addr1.ipAddr = requested_align; DHCPS_INFO("REQUEST ip %d.%d.%d.%d already reserved by %02X:%02X:%02X:%02X:%02X:%02X", ip_addr1.ipAddrByteFormat[0], ip_addr1.ipAddrByteFormat[1], ip_addr1.ipAddrByteFormat[2], ip_addr1.ipAddrByteFormat[3], dhcps_lease[lease_index].mac[0], dhcps_lease[lease_index].mac[1], dhcps_lease[lease_index].mac[2], dhcps_lease[lease_index].mac[3], dhcps_lease[lease_index].mac[4], dhcps_lease[lease_index].mac[5]); send_NAK(&recv_dhcp_packet); } } else { check_and_ack(&recv_dhcp_packet, requested_align, dhcps_lease); } } else { ip_addr1.ipAddr = recv_dhcp_packet.ciaddr; DHCPS_INFO("Send NAK to %d.%d.%d.%d.", ip_addr1.ipAddrByteFormat[0], ip_addr1.ipAddrByteFormat[1], ip_addr1.ipAddrByteFormat[2], ip_addr1.ipAddrByteFormat[3]); send_NAK(&recv_dhcp_packet); } /* otherwise on reply. */ break; case DHCPDECLINE: DHCPS_INFO("Recv DECLINE from %02X:%02X:%02X:%02X:%02X:%02X.", recv_dhcp_packet.chaddr[0], recv_dhcp_packet.chaddr[1], recv_dhcp_packet.chaddr[2], recv_dhcp_packet.chaddr[3], recv_dhcp_packet.chaddr[4], recv_dhcp_packet.chaddr[5]); if (lease_index != -1) { memset(dhcps_lease[lease_index].mac, 0, 6); dhcps_lease[lease_index].expires = dhcps_params.decline_time; dhcps_lease[lease_index].state = 0; } break; case DHCPRELEASE: DHCPS_INFO("Recv RELEASE from %02X:%02X:%02X:%02X:%02X:%02X.", recv_dhcp_packet.chaddr[0], recv_dhcp_packet.chaddr[1], recv_dhcp_packet.chaddr[2], recv_dhcp_packet.chaddr[3], recv_dhcp_packet.chaddr[4], recv_dhcp_packet.chaddr[5]); if (lease_index != -1) { /* Delete the lease, lsz 080221 */ memset(&(dhcps_lease[lease_index]), 0, sizeof(dhcps_lease[lease_index])); for (move_index = lease_index; (move_index + 1) < DHCPS_LEASE_LIST_SIZE; move_index++) { memcpy(&(dhcps_lease[move_index]), &(dhcps_lease[move_index + 1]), sizeof(dhcps_lease[move_index])); memset(&(dhcps_lease[move_index + 1]), 0, sizeof(dhcps_lease[move_index + 1])); } } break; case DHCPINFORM: DHCPS_DEBUG("Recv INFORM from %02X:%02X:%02X:%02X:%02X:%02X.", recv_dhcp_packet.chaddr[0], recv_dhcp_packet.chaddr[1], recv_dhcp_packet.chaddr[2], recv_dhcp_packet.chaddr[3], recv_dhcp_packet.chaddr[4], recv_dhcp_packet.chaddr[5]); send_inform(&recv_dhcp_packet); break; default: DHCPS_WARN("Unsupported DHCP message (%02x) -- ignoring.", state[0]); } return; } LOCAL S32 dhcps_start_cb(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPS_MSG *dhcps_msg = (DHCPS_MSG *)mbuf; U32 temp_ip = 0; IP_ADDR ipaddr; if ((NULL == dhcps_msg) || (mlen != sizeof(DHCPS_MSG))) { return ERROR; } strcpy(dhcps_params.dev_name, dhcps_msg->dev_name); if (0 > read_interface_info(dhcps_params.dev_name, &dhcps_params.dev, dhcps_params.mac)) { DHCPS_DEBUG("Read interface info error"); return ERROR; } if (ntohl(dhcps_msg->pool_start) > ntohl(dhcps_msg->pool_end)) { temp_ip = dhcps_msg->pool_start; dhcps_msg->pool_start = dhcps_msg->pool_end; dhcps_msg->pool_end = temp_ip; } if ((dhcps_msg->pool_start != dhcps_params.start) || (dhcps_msg->pool_end != dhcps_params.end)) { dhcps_params.start= dhcps_msg->pool_start; dhcps_params.end = dhcps_msg->pool_end; memset(dhcps_params.lease, 0, sizeof(DHCPS_LEASE)*DHCPS_LEASE_LIST_SIZE); } dhcps_params.gateway = dhcps_msg->gateway; dhcps_params.lease_time = dhcps_msg->lease_time; dhcps_params.dns_server[0] = dhcps_msg->pri_dns; dhcps_params.dns_server[1] = dhcps_msg->snd_dns; dhcps_params.server = dhcps_msg->gateway; dhcps_params.netmask = dhcps_msg->netmask; /* 是否4G路由 */ dhcps_params.is_lte = get_lte_enabled(); memset(&dhcps_params.options, 0, sizeof(DHCP_OPTION_STATIC)); dhcps_params.options.lease[0] = DHCP_LEASE_TIME; dhcps_params.options.lease[1] = 4; memcpy(&(dhcps_params.options.lease[2]), &(dhcps_params.lease_time), 4); temp_ip = dhcps_params.netmask; dhcps_params.options.subnet[0] = DHCP_SUBNET; dhcps_params.options.subnet[1] = 4; memcpy(&(dhcps_params.options.subnet[2]), (char *)&temp_ip, 4); dhcps_params.options.router[0] = DHCP_ROUTER; dhcps_params.options.router[1] = 4; memcpy(&(dhcps_params.options.router[2]), (char *)&dhcps_params.gateway, 4); dhcps_params.options.dns[0] = DHCP_DNS_SERVER; dhcps_params.options.dns[1] = 4; memcpy(&(dhcps_params.options.dns[2]), (char *)&dhcps_params.dns_server[0], 4); dhcps_params.options.router4g[0] = DHCP_4G_ROUTER; dhcps_params.options.router4g[1] = DHCP_4G_ROUTER_LEN; memcpy(&(dhcps_params.options.router4g[2]), DHCP_4G_ROUTER_STR, DHCP_4G_ROUTER_LEN); if (-1 == dhcps_params.sock) { dhcps_params.sock = create_sock(); if (-1 == dhcps_params.sock) { DHCPS_DEBUG("create socket error"); return ERROR; } } if (-1 == dhcps_params.inet_iendx) { dhcps_params.inet_iendx = inet_add_socket(dhcps_params.sock, (void*)dhcps_handle, NULL, NULL); if (ERROR == dhcps_params.inet_iendx) { destroy_sock(dhcps_params.sock); dhcps_params.sock = -1; DHCPS_DEBUG("Listen socket error"); return ERROR; } } if (-1 == dhcps_params.timer_index) { dhcps_params.timer_index = inet_add_timer((void*)dhcps_check_timer, 0, 1, EXECUTE_FOREVER); if (ERROR == dhcps_params.timer_index) { inet_del_socket(dhcps_params.inet_iendx); dhcps_params.inet_iendx = -1; destroy_sock(dhcps_params.sock); dhcps_params.sock = -1; DHCPS_DEBUG("Add timer error"); return ERROR; } } DHCPS_INFO("Start DHCP server"); ipaddr.ipAddr = dhcps_params.server; DHCPS_DEBUG("Server = %d.%d.%d.%d", ipaddr.ipAddrByteFormat[0], ipaddr.ipAddrByteFormat[1], ipaddr.ipAddrByteFormat[2], ipaddr.ipAddrByteFormat[3]); ipaddr.ipAddr = dhcps_params.netmask; DHCPS_DEBUG("Netmask = %d.%d.%d.%d", ipaddr.ipAddrByteFormat[0], ipaddr.ipAddrByteFormat[1], ipaddr.ipAddrByteFormat[2], ipaddr.ipAddrByteFormat[3]); ipaddr.ipAddr = dhcps_params.dns_server[0]; DHCPS_DEBUG("DNS1 = %d.%d.%d.%d", ipaddr.ipAddrByteFormat[0], ipaddr.ipAddrByteFormat[1], ipaddr.ipAddrByteFormat[2], ipaddr.ipAddrByteFormat[3]); ipaddr.ipAddr = dhcps_params.dns_server[1]; DHCPS_DEBUG("DNS2 = %d.%d.%d.%d", ipaddr.ipAddrByteFormat[0], ipaddr.ipAddrByteFormat[1], ipaddr.ipAddrByteFormat[2], ipaddr.ipAddrByteFormat[3]); ipaddr.ipAddr = dhcps_params.start; DHCPS_DEBUG("Pool Start = %d.%d.%d.%d", ipaddr.ipAddrByteFormat[0], ipaddr.ipAddrByteFormat[1], ipaddr.ipAddrByteFormat[2], ipaddr.ipAddrByteFormat[3]); ipaddr.ipAddr = dhcps_params.end; DHCPS_DEBUG("Pool End = %d.%d.%d.%d", ipaddr.ipAddrByteFormat[0], ipaddr.ipAddrByteFormat[1], ipaddr.ipAddrByteFormat[2], ipaddr.ipAddrByteFormat[3]); DHCPS_DEBUG("Lease Time = %d", dhcps_params.lease_time); return OK; } LOCAL S32 dhcps_stop_cb(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { if (-1 != dhcps_params.inet_iendx) { inet_del_socket(dhcps_params.inet_iendx); dhcps_params.inet_iendx = -1; } if (-1 != dhcps_params.sock) { destroy_sock(dhcps_params.sock); dhcps_params.sock = -1; } if (-1 != dhcps_params.timer_index) { inet_del_timer(dhcps_params.timer_index); dhcps_params.timer_index = -1; } return OK; } LOCAL int dhcps_init() { memset(&recv_dhcp_packet, 0, sizeof(recv_dhcp_packet)); memset(&dhcps_params, 0, sizeof(DHCPS_PARAMS)); dhcps_params.inet_iendx = -1; dhcps_params.timer_index = -1; dhcps_params.sock = -1; dhcps_params.decline_time = DECLINE_TIME; dhcps_params.conflict_time = CONFLICT_TIME; dhcps_params.offer_time = LEASE_OFFER_TIME; dhcps_params.min_lease = LEASE_TIME_MIN; msg_attach_handler(DHCPS_START_MSG, dhcps_start_cb); msg_attach_handler(DHCPS_STOP_MSG, dhcps_stop_cb); return OK; } LOCAL S32 dhcps_reload(DS_MSG *msg) { /* 4G上网模式变化 */ if (ds_path_id_exist(msg->id, msg->num, LTE_INFO_DATA_PATH)) { dhcps_params.is_lte = get_lte_enabled(); } return OK; } LOCAL void dhcps_main() { DS_DAT_MON_DESC dhcps_monitor[] = { DS_DAT_MON(LTE_INFO_DATA_PATH, DATA_ATTRI_NOTIFY), }; DS_MOD_DESC dhcps_module = DS_STRUCT_MOD("dhcps", dhcps_init, NULL, dhcps_reload, NULL, NULL, NULL, dhcps_monitor); MODULE *module_node = ds_register_module("dhcps", &dhcps_module); NSD_ASSERT(NULL != module_node); } NSD_INIT(dhcps_main);
最新发布
11-21
/** ****************************************************************************** * @file stm32f10x_usart.c * @author MCD Application Team * @version V3.5.0 * @date 11-March-2011 * @brief This file provides all the USART firmware functions. ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2> ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32f10x_usart.h" #include "stm32f10x_rcc.h" /** @addtogroup STM32F10x_StdPeriph_Driver * @{ */ /** @defgroup USART * @brief USART driver modules * @{ */ /** @defgroup USART_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USART_Private_Defines * @{ */ #define CR1_UE_Set ((uint16_t)0x2000) /*!< USART Enable Mask */ #define CR1_UE_Reset ((uint16_t)0xDFFF) /*!< USART Disable Mask */ #define CR1_WAKE_Mask ((uint16_t)0xF7FF) /*!< USART WakeUp Method Mask */ #define CR1_RWU_Set ((uint16_t)0x0002) /*!< USART mute mode Enable Mask */ #define CR1_RWU_Reset ((uint16_t)0xFFFD) /*!< USART mute mode Enable Mask */ #define CR1_SBK_Set ((uint16_t)0x0001) /*!< USART Break Character send Mask */ #define CR1_CLEAR_Mask ((uint16_t)0xE9F3) /*!< USART CR1 Mask */ #define CR2_Address_Mask ((uint16_t)0xFFF0) /*!< USART address Mask */ #define CR2_LINEN_Set ((uint16_t)0x4000) /*!< USART LIN Enable Mask */ #define CR2_LINEN_Reset ((uint16_t)0xBFFF) /*!< USART LIN Disable Mask */ #define CR2_LBDL_Mask ((uint16_t)0xFFDF) /*!< USART LIN Break detection Mask */ #define CR2_STOP_CLEAR_Mask ((uint16_t)0xCFFF) /*!< USART CR2 STOP Bits Mask */ #define CR2_CLOCK_CLEAR_Mask ((uint16_t)0xF0FF) /*!< USART CR2 Clock Mask */ #define CR3_SCEN_Set ((uint16_t)0x0020) /*!< USART SC Enable Mask */ #define CR3_SCEN_Reset ((uint16_t)0xFFDF) /*!< USART SC Disable Mask */ #define CR3_NACK_Set ((uint16_t)0x0010) /*!< USART SC NACK Enable Mask */ #define CR3_NACK_Reset ((uint16_t)0xFFEF) /*!< USART SC NACK Disable Mask */ #define CR3_HDSEL_Set ((uint16_t)0x0008) /*!< USART Half-Duplex Enable Mask */ #define CR3_HDSEL_Reset ((uint16_t)0xFFF7) /*!< USART Half-Duplex Disable Mask */ #define CR3_IRLP_Mask ((uint16_t)0xFFFB) /*!< USART IrDA LowPower mode Mask */ #define CR3_CLEAR_Mask ((uint16_t)0xFCFF) /*!< USART CR3 Mask */ #define CR3_IREN_Set ((uint16_t)0x0002) /*!< USART IrDA Enable Mask */ #define CR3_IREN_Reset ((uint16_t)0xFFFD) /*!< USART IrDA Disable Mask */ #define GTPR_LSB_Mask ((uint16_t)0x00FF) /*!< Guard Time Register LSB Mask */ #define GTPR_MSB_Mask ((uint16_t)0xFF00) /*!< Guard Time Register MSB Mask */ #define IT_Mask ((uint16_t)0x001F) /*!< USART Interrupt Mask */ /* USART OverSampling-8 Mask */ #define CR1_OVER8_Set ((u16)0x8000) /* USART OVER8 mode Enable Mask */ #define CR1_OVER8_Reset ((u16)0x7FFF) /* USART OVER8 mode Disable Mask */ /* USART One Bit Sampling Mask */ #define CR3_ONEBITE_Set ((u16)0x0800) /* USART ONEBITE mode Enable Mask */ #define CR3_ONEBITE_Reset ((u16)0xF7FF) /* USART ONEBITE mode Disable Mask */ /** * @} */ /** @defgroup USART_Private_Macros * @{ */ /** * @} */ /** @defgroup USART_Private_Variables * @{ */ /** * @} */ /** @defgroup USART_Private_FunctionPrototypes * @{ */ /** * @} */ /** @defgroup USART_Private_Functions * @{ */ /** * @brief Deinitializes the USARTx peripheral registers to their default reset values. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @retval None */ void USART_DeInit(USART_TypeDef* USARTx) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); if (USARTx == USART1) { RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE); } else if (USARTx == USART2) { RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, DISABLE); } else if (USARTx == USART3) { RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, DISABLE); } else if (USARTx == UART4) { RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, DISABLE); } else { if (USARTx == UART5) { RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, DISABLE); } } } /** * @brief Initializes the USARTx peripheral according to the specified * parameters in the USART_InitStruct . * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_InitStruct: pointer to a USART_InitTypeDef structure * that contains the configuration information for the specified USART * peripheral. * @retval None */ void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct) { uint32_t tmpreg = 0x00, apbclock = 0x00; uint32_t integerdivider = 0x00; uint32_t fractionaldivider = 0x00; uint32_t usartxbase = 0; RCC_ClocksTypeDef RCC_ClocksStatus; /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_BAUDRATE(USART_InitStruct->USART_BaudRate)); assert_param(IS_USART_WORD_LENGTH(USART_InitStruct->USART_WordLength)); assert_param(IS_USART_STOPBITS(USART_InitStruct->USART_StopBits)); assert_param(IS_USART_PARITY(USART_InitStruct->USART_Parity)); assert_param(IS_USART_MODE(USART_InitStruct->USART_Mode)); assert_param(IS_USART_HARDWARE_FLOW_CONTROL(USART_InitStruct->USART_HardwareFlowControl)); /* The hardware flow control is available only for USART1, USART2 and USART3 */ if (USART_InitStruct->USART_HardwareFlowControl != USART_HardwareFlowControl_None) { assert_param(IS_USART_123_PERIPH(USARTx)); } usartxbase = (uint32_t)USARTx; /*---------------------------- USART CR2 Configuration -----------------------*/ tmpreg = USARTx->CR2; /* Clear STOP[13:12] bits */ tmpreg &= CR2_STOP_CLEAR_Mask; /* Configure the USART Stop Bits, Clock, CPOL, CPHA and LastBit ------------*/ /* Set STOP[13:12] bits according to USART_StopBits value */ tmpreg |= (uint32_t)USART_InitStruct->USART_StopBits; /* Write to USART CR2 */ USARTx->CR2 = (uint16_t)tmpreg; /*---------------------------- USART CR1 Configuration -----------------------*/ tmpreg = USARTx->CR1; /* Clear M, PCE, PS, TE and RE bits */ tmpreg &= CR1_CLEAR_Mask; /* Configure the USART Word Length, Parity and mode ----------------------- */ /* Set the M bits according to USART_WordLength value */ /* Set PCE and PS bits according to USART_Parity value */ /* Set TE and RE bits according to USART_Mode value */ tmpreg |= (uint32_t)USART_InitStruct->USART_WordLength | USART_InitStruct->USART_Parity | USART_InitStruct->USART_Mode; /* Write to USART CR1 */ USARTx->CR1 = (uint16_t)tmpreg; /*---------------------------- USART CR3 Configuration -----------------------*/ tmpreg = USARTx->CR3; /* Clear CTSE and RTSE bits */ tmpreg &= CR3_CLEAR_Mask; /* Configure the USART HFC -------------------------------------------------*/ /* Set CTSE and RTSE bits according to USART_HardwareFlowControl value */ tmpreg |= USART_InitStruct->USART_HardwareFlowControl; /* Write to USART CR3 */ USARTx->CR3 = (uint16_t)tmpreg; /*---------------------------- USART BRR Configuration -----------------------*/ /* Configure the USART Baud Rate -------------------------------------------*/ RCC_GetClocksFreq(&RCC_ClocksStatus); if (usartxbase == USART1_BASE) { apbclock = RCC_ClocksStatus.PCLK2_Frequency; } else { apbclock = RCC_ClocksStatus.PCLK1_Frequency; } /* Determine the integer part */ if ((USARTx->CR1 & CR1_OVER8_Set) != 0) { /* Integer part computing in case Oversampling mode is 8 Samples */ integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate))); } else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */ { /* Integer part computing in case Oversampling mode is 16 Samples */ integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate))); } tmpreg = (integerdivider / 100) << 4; /* Determine the fractional part */ fractionaldivider = integerdivider - (100 * (tmpreg >> 4)); /* Implement the fractional part in the register */ if ((USARTx->CR1 & CR1_OVER8_Set) != 0) { tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07); } else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */ { tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F); } /* Write to USART BRR */ USARTx->BRR = (uint16_t)tmpreg; } /** * @brief Fills each USART_InitStruct member with its default value. * @param USART_InitStruct: pointer to a USART_InitTypeDef structure * which will be initialized. * @retval None */ void USART_StructInit(USART_InitTypeDef* USART_InitStruct) { /* USART_InitStruct members default value */ USART_InitStruct->USART_BaudRate = 9600; USART_InitStruct->USART_WordLength = USART_WordLength_8b; USART_InitStruct->USART_StopBits = USART_StopBits_1; USART_InitStruct->USART_Parity = USART_Parity_No ; USART_InitStruct->USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStruct->USART_HardwareFlowControl = USART_HardwareFlowControl_None; } /** * @brief Initializes the USARTx peripheral Clock according to the * specified parameters in the USART_ClockInitStruct . * @param USARTx: where x can be 1, 2, 3 to select the USART peripheral. * @param USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef * structure that contains the configuration information for the specified * USART peripheral. * @note The Smart Card and Synchronous modes are not available for UART4 and UART5. * @retval None */ void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct) { uint32_t tmpreg = 0x00; /* Check the parameters */ assert_param(IS_USART_123_PERIPH(USARTx)); assert_param(IS_USART_CLOCK(USART_ClockInitStruct->USART_Clock)); assert_param(IS_USART_CPOL(USART_ClockInitStruct->USART_CPOL)); assert_param(IS_USART_CPHA(USART_ClockInitStruct->USART_CPHA)); assert_param(IS_USART_LASTBIT(USART_ClockInitStruct->USART_LastBit)); /*---------------------------- USART CR2 Configuration -----------------------*/ tmpreg = USARTx->CR2; /* Clear CLKEN, CPOL, CPHA and LBCL bits */ tmpreg &= CR2_CLOCK_CLEAR_Mask; /* Configure the USART Clock, CPOL, CPHA and LastBit ------------*/ /* Set CLKEN bit according to USART_Clock value */ /* Set CPOL bit according to USART_CPOL value */ /* Set CPHA bit according to USART_CPHA value */ /* Set LBCL bit according to USART_LastBit value */ tmpreg |= (uint32_t)USART_ClockInitStruct->USART_Clock | USART_ClockInitStruct->USART_CPOL | USART_ClockInitStruct->USART_CPHA | USART_ClockInitStruct->USART_LastBit; /* Write to USART CR2 */ USARTx->CR2 = (uint16_t)tmpreg; } /** * @brief Fills each USART_ClockInitStruct member with its default value. * @param USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef * structure which will be initialized. * @retval None */ void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct) { /* USART_ClockInitStruct members default value */ USART_ClockInitStruct->USART_Clock = USART_Clock_Disable; USART_ClockInitStruct->USART_CPOL = USART_CPOL_Low; USART_ClockInitStruct->USART_CPHA = USART_CPHA_1Edge; USART_ClockInitStruct->USART_LastBit = USART_LastBit_Disable; } /** * @brief Enables or disables the specified USART peripheral. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param NewState: new state of the USARTx peripheral. * This parameter can be: ENABLE or DISABLE. * @retval None */ void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the selected USART by setting the UE bit in the CR1 register */ USARTx->CR1 |= CR1_UE_Set; } else { /* Disable the selected USART by clearing the UE bit in the CR1 register */ USARTx->CR1 &= CR1_UE_Reset; } } /** * @brief Enables or disables the specified USART interrupts. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_IT: specifies the USART interrupt sources to be enabled or disabled. * This parameter can be one of the following values: * @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) * @arg USART_IT_LBD: LIN Break detection interrupt * @arg USART_IT_TXE: Transmit Data Register empty interrupt * @arg USART_IT_TC: Transmission complete interrupt * @arg USART_IT_RXNE: Receive Data register not empty interrupt * @arg USART_IT_IDLE: Idle line detection interrupt * @arg USART_IT_PE: Parity Error interrupt * @arg USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) * @param NewState: new state of the specified USARTx interrupts. * This parameter can be: ENABLE or DISABLE. * @retval None */ void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState) { uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00; uint32_t usartxbase = 0x00; /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_CONFIG_IT(USART_IT)); assert_param(IS_FUNCTIONAL_STATE(NewState)); /* The CTS interrupt is not available for UART4 and UART5 */ if (USART_IT == USART_IT_CTS) { assert_param(IS_USART_123_PERIPH(USARTx)); } usartxbase = (uint32_t)USARTx; /* Get the USART register index */ usartreg = (((uint8_t)USART_IT) >> 0x05); /* Get the interrupt position */ itpos = USART_IT & IT_Mask; itmask = (((uint32_t)0x01) << itpos); if (usartreg == 0x01) /* The IT is in CR1 register */ { usartxbase += 0x0C; } else if (usartreg == 0x02) /* The IT is in CR2 register */ { usartxbase += 0x10; } else /* The IT is in CR3 register */ { usartxbase += 0x14; } if (NewState != DISABLE) { *(__IO uint32_t*)usartxbase |= itmask; } else { *(__IO uint32_t*)usartxbase &= ~itmask; } } /** * @brief Enables or disables the USART’s DMA interface. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_DMAReq: specifies the DMA request. * This parameter can be any combination of the following values: * @arg USART_DMAReq_Tx: USART DMA transmit request * @arg USART_DMAReq_Rx: USART DMA receive request * @param NewState: new state of the DMA Request sources. * This parameter can be: ENABLE or DISABLE. * @note The DMA mode is not available for UART5 except in the STM32 * High density value line devices(STM32F10X_HD_VL). * @retval None */ void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DMAREQ(USART_DMAReq)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the DMA transfer for selected requests by setting the DMAT and/or DMAR bits in the USART CR3 register */ USARTx->CR3 |= USART_DMAReq; } else { /* Disable the DMA transfer for selected requests by clearing the DMAT and/or DMAR bits in the USART CR3 register */ USARTx->CR3 &= (uint16_t)~USART_DMAReq; } } /** * @brief Sets the address of the USART node. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_Address: Indicates the address of the USART node. * @retval None */ void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_ADDRESS(USART_Address)); /* Clear the USART address */ USARTx->CR2 &= CR2_Address_Mask; /* Set the USART address node */ USARTx->CR2 |= USART_Address; } /** * @brief Selects the USART WakeUp method. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_WakeUp: specifies the USART wakeup method. * This parameter can be one of the following values: * @arg USART_WakeUp_IdleLine: WakeUp by an idle line detection * @arg USART_WakeUp_AddressMark: WakeUp by an address mark * @retval None */ void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_WAKEUP(USART_WakeUp)); USARTx->CR1 &= CR1_WAKE_Mask; USARTx->CR1 |= USART_WakeUp; } /** * @brief Determines if the USART is in mute mode or not. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param NewState: new state of the USART mute mode. * This parameter can be: ENABLE or DISABLE. * @retval None */ void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the USART mute mode by setting the RWU bit in the CR1 register */ USARTx->CR1 |= CR1_RWU_Set; } else { /* Disable the USART mute mode by clearing the RWU bit in the CR1 register */ USARTx->CR1 &= CR1_RWU_Reset; } } /** * @brief Sets the USART LIN Break detection length. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_LINBreakDetectLength: specifies the LIN break detection length. * This parameter can be one of the following values: * @arg USART_LINBreakDetectLength_10b: 10-bit break detection * @arg USART_LINBreakDetectLength_11b: 11-bit break detection * @retval None */ void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_LIN_BREAK_DETECT_LENGTH(USART_LINBreakDetectLength)); USARTx->CR2 &= CR2_LBDL_Mask; USARTx->CR2 |= USART_LINBreakDetectLength; } /** * @brief Enables or disables the USART’s LIN mode. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param NewState: new state of the USART LIN mode. * This parameter can be: ENABLE or DISABLE. * @retval None */ void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the LIN mode by setting the LINEN bit in the CR2 register */ USARTx->CR2 |= CR2_LINEN_Set; } else { /* Disable the LIN mode by clearing the LINEN bit in the CR2 register */ USARTx->CR2 &= CR2_LINEN_Reset; } } /** * @brief Transmits single data through the USARTx peripheral. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param Data: the data to transmit. * @retval None */ void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DATA(Data)); /* Transmit Data */ USARTx->DR = (Data & (uint16_t)0x01FF); } /** * @brief Returns the most recent received data by the USARTx peripheral. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @retval The received data. */ uint16_t USART_ReceiveData(USART_TypeDef* USARTx) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); /* Receive Data */ return (uint16_t)(USARTx->DR & (uint16_t)0x01FF); } /** * @brief Transmits break characters. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @retval None */ void USART_SendBreak(USART_TypeDef* USARTx) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); /* Send break characters */ USARTx->CR1 |= CR1_SBK_Set; } /** * @brief Sets the specified USART guard time. * @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral. * @param USART_GuardTime: specifies the guard time. * @note The guard time bits are not available for UART4 and UART5. * @retval None */ void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime) { /* Check the parameters */ assert_param(IS_USART_123_PERIPH(USARTx)); /* Clear the USART Guard time */ USARTx->GTPR &= GTPR_LSB_Mask; /* Set the USART guard time */ USARTx->GTPR |= (uint16_t)((uint16_t)USART_GuardTime << 0x08); } /** * @brief Sets the system clock prescaler. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_Prescaler: specifies the prescaler clock. * @note The function is used for IrDA mode with UART4 and UART5. * @retval None */ void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); /* Clear the USART prescaler */ USARTx->GTPR &= GTPR_MSB_Mask; /* Set the USART prescaler */ USARTx->GTPR |= USART_Prescaler; } /** * @brief Enables or disables the USART’s Smart Card mode. * @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral. * @param NewState: new state of the Smart Card mode. * This parameter can be: ENABLE or DISABLE. * @note The Smart Card mode is not available for UART4 and UART5. * @retval None */ void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_123_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the SC mode by setting the SCEN bit in the CR3 register */ USARTx->CR3 |= CR3_SCEN_Set; } else { /* Disable the SC mode by clearing the SCEN bit in the CR3 register */ USARTx->CR3 &= CR3_SCEN_Reset; } } /** * @brief Enables or disables NACK transmission. * @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral. * @param NewState: new state of the NACK transmission. * This parameter can be: ENABLE or DISABLE. * @note The Smart Card mode is not available for UART4 and UART5. * @retval None */ void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_123_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the NACK transmission by setting the NACK bit in the CR3 register */ USARTx->CR3 |= CR3_NACK_Set; } else { /* Disable the NACK transmission by clearing the NACK bit in the CR3 register */ USARTx->CR3 &= CR3_NACK_Reset; } } /** * @brief Enables or disables the USART’s Half Duplex communication. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param NewState: new state of the USART Communication. * This parameter can be: ENABLE or DISABLE. * @retval None */ void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */ USARTx->CR3 |= CR3_HDSEL_Set; } else { /* Disable the Half-Duplex mode by clearing the HDSEL bit in the CR3 register */ USARTx->CR3 &= CR3_HDSEL_Reset; } } /** * @brief Enables or disables the USART's 8x oversampling mode. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param NewState: new state of the USART one bit sampling method. * This parameter can be: ENABLE or DISABLE. * @note * This function has to be called before calling USART_Init() * function in order to have correct baudrate Divider value. * @retval None */ void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the 8x Oversampling mode by setting the OVER8 bit in the CR1 register */ USARTx->CR1 |= CR1_OVER8_Set; } else { /* Disable the 8x Oversampling mode by clearing the OVER8 bit in the CR1 register */ USARTx->CR1 &= CR1_OVER8_Reset; } } /** * @brief Enables or disables the USART's one bit sampling method. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param NewState: new state of the USART one bit sampling method. * This parameter can be: ENABLE or DISABLE. * @retval None */ void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the one bit method by setting the ONEBITE bit in the CR3 register */ USARTx->CR3 |= CR3_ONEBITE_Set; } else { /* Disable tthe one bit method by clearing the ONEBITE bit in the CR3 register */ USARTx->CR3 &= CR3_ONEBITE_Reset; } } /** * @brief Configures the USART's IrDA interface. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_IrDAMode: specifies the IrDA mode. * This parameter can be one of the following values: * @arg USART_IrDAMode_LowPower * @arg USART_IrDAMode_Normal * @retval None */ void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_IRDA_MODE(USART_IrDAMode)); USARTx->CR3 &= CR3_IRLP_Mask; USARTx->CR3 |= USART_IrDAMode; } /** * @brief Enables or disables the USART's IrDA interface. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param NewState: new state of the IrDA mode. * This parameter can be: ENABLE or DISABLE. * @retval None */ void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_FUNCTIONAL_STATE(NewState)); if (NewState != DISABLE) { /* Enable the IrDA mode by setting the IREN bit in the CR3 register */ USARTx->CR3 |= CR3_IREN_Set; } else { /* Disable the IrDA mode by clearing the IREN bit in the CR3 register */ USARTx->CR3 &= CR3_IREN_Reset; } } /** * @brief Checks whether the specified USART flag is set or not. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_FLAG: specifies the flag to check. * This parameter can be one of the following values: * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) * @arg USART_FLAG_LBD: LIN Break detection flag * @arg USART_FLAG_TXE: Transmit data register empty flag * @arg USART_FLAG_TC: Transmission Complete flag * @arg USART_FLAG_RXNE: Receive data register not empty flag * @arg USART_FLAG_IDLE: Idle Line detection flag * @arg USART_FLAG_ORE: OverRun Error flag * @arg USART_FLAG_NE: Noise Error flag * @arg USART_FLAG_FE: Framing Error flag * @arg USART_FLAG_PE: Parity Error flag * @retval The new state of USART_FLAG (SET or RESET). */ FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG) { FlagStatus bitstatus = RESET; /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_FLAG(USART_FLAG)); /* The CTS flag is not available for UART4 and UART5 */ if (USART_FLAG == USART_FLAG_CTS) { assert_param(IS_USART_123_PERIPH(USARTx)); } if ((USARTx->SR & USART_FLAG) != (uint16_t)RESET) { bitstatus = SET; } else { bitstatus = RESET; } return bitstatus; } /** * @brief Clears the USARTx's pending flags. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_FLAG: specifies the flag to clear. * This parameter can be any combination of the following values: * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5). * @arg USART_FLAG_LBD: LIN Break detection flag. * @arg USART_FLAG_TC: Transmission Complete flag. * @arg USART_FLAG_RXNE: Receive data register not empty flag. * * @note * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun * error) and IDLE (Idle line detected) flags are cleared by software * sequence: a read operation to USART_SR register (USART_GetFlagStatus()) * followed by a read operation to USART_DR register (USART_ReceiveData()). * - RXNE flag can be also cleared by a read to the USART_DR register * (USART_ReceiveData()). * - TC flag can be also cleared by software sequence: a read operation to * USART_SR register (USART_GetFlagStatus()) followed by a write operation * to USART_DR register (USART_SendData()). * - TXE flag is cleared only by a write to the USART_DR register * (USART_SendData()). * @retval None */ void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_CLEAR_FLAG(USART_FLAG)); /* The CTS flag is not available for UART4 and UART5 */ if ((USART_FLAG & USART_FLAG_CTS) == USART_FLAG_CTS) { assert_param(IS_USART_123_PERIPH(USARTx)); } USARTx->SR = (uint16_t)~USART_FLAG; } /** * @brief Checks whether the specified USART interrupt has occurred or not. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_IT: specifies the USART interrupt source to check. * This parameter can be one of the following values: * @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) * @arg USART_IT_LBD: LIN Break detection interrupt * @arg USART_IT_TXE: Tansmit Data Register empty interrupt * @arg USART_IT_TC: Transmission complete interrupt * @arg USART_IT_RXNE: Receive Data register not empty interrupt * @arg USART_IT_IDLE: Idle line detection interrupt * @arg USART_IT_ORE: OverRun Error interrupt * @arg USART_IT_NE: Noise Error interrupt * @arg USART_IT_FE: Framing Error interrupt * @arg USART_IT_PE: Parity Error interrupt * @retval The new state of USART_IT (SET or RESET). */ ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT) { uint32_t bitpos = 0x00, itmask = 0x00, usartreg = 0x00; ITStatus bitstatus = RESET; /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_GET_IT(USART_IT)); /* The CTS interrupt is not available for UART4 and UART5 */ if (USART_IT == USART_IT_CTS) { assert_param(IS_USART_123_PERIPH(USARTx)); } /* Get the USART register index */ usartreg = (((uint8_t)USART_IT) >> 0x05); /* Get the interrupt position */ itmask = USART_IT & IT_Mask; itmask = (uint32_t)0x01 << itmask; if (usartreg == 0x01) /* The IT is in CR1 register */ { itmask &= USARTx->CR1; } else if (usartreg == 0x02) /* The IT is in CR2 register */ { itmask &= USARTx->CR2; } else /* The IT is in CR3 register */ { itmask &= USARTx->CR3; } bitpos = USART_IT >> 0x08; bitpos = (uint32_t)0x01 << bitpos; bitpos &= USARTx->SR; if ((itmask != (uint16_t)RESET)&&(bitpos != (uint16_t)RESET)) { bitstatus = SET; } else { bitstatus = RESET; } return bitstatus; } /** * @brief Clears the USARTx's interrupt pending bits. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param USART_IT: specifies the interrupt pending bit to clear. * This parameter can be one of the following values: * @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5) * @arg USART_IT_LBD: LIN Break detection interrupt * @arg USART_IT_TC: Transmission complete interrupt. * @arg USART_IT_RXNE: Receive Data register not empty interrupt. * * @note * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun * error) and IDLE (Idle line detected) pending bits are cleared by * software sequence: a read operation to USART_SR register * (USART_GetITStatus()) followed by a read operation to USART_DR register * (USART_ReceiveData()). * - RXNE pending bit can be also cleared by a read to the USART_DR register * (USART_ReceiveData()). * - TC pending bit can be also cleared by software sequence: a read * operation to USART_SR register (USART_GetITStatus()) followed by a write * operation to USART_DR register (USART_SendData()). * - TXE pending bit is cleared only by a write to the USART_DR register * (USART_SendData()). * @retval None */ void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT) { uint16_t bitpos = 0x00, itmask = 0x00; /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_CLEAR_IT(USART_IT)); /* The CTS interrupt is not available for UART4 and UART5 */ if (USART_IT == USART_IT_CTS) { assert_param(IS_USART_123_PERIPH(USARTx)); } bitpos = USART_IT >> 0x08; itmask = ((uint16_t)0x01 << (uint16_t)bitpos); USARTx->SR = (uint16_t)~itmask; } /** * @} */ /** * @} */ /** * @} */ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/教我这个代码怎么用
11-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值