assert

it2025-04-29  17

assert_param()的使用

zhj失落之地 2018-01-10 21:23:12 1196 收藏 5

分类专栏: stm32相关

最后发布:2018-01-10 21:23:12首次发布:2018-01-10 21:23:12

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/u013216061/article/details/79028425

版权

在STM32的固件库和提供的例程中,到处都可以见到assert_param()的使用。在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数。        所谓有效的参数是指满足规定范围的参数,比如某个参数的取值范围只能是小于3的正整数,如果给出的参数大于3,则这个assert_param()可以在运行的程序调用到这个函数时报告错误,使程序员可以及时发现错误,而不必等到程序运行结果的错误而大费周折。

        这是一种常见的软件技术,可以在调试阶段帮助程序员快速地排除那些明显的错误。         它确实在程序的运行上牺牲了效率(但只是在调试阶段),但在项目的开发上却帮助你提高了效率。         当你的项目开发成功,使用release模式编译之后,或在stm32f10x_conf.h文件中注释掉对USE_FULL_ASSERT的宏定义,所有的assert_param()检验都消失了,不会影响最终程序的运行效率。 摘抄于库函数stm32f0xx_conf.h中:#ifdef  USE_FULL_ASSERT           #define assert_param(expr)   ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) /* Exported functions ------------------------------------------------------- */   void assert_failed(uint8_t* file, uint32_t line); #else           #define assert_param(expr) ((void)0) #endif /* USE_FULL_ASSERT */         如果定义了USE_FULL_ASSERT,就把 assert_param(expr) 定义为((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) 并申明一下assert_failed这个函数。否则把assert_param(expr)定义为空。 __FILE__和__LINE__是IAR定义的宏,指的是当前的编译的文件名和行数。     整个宏作用为:如果expr为真,则什么也不返回,如果expr为假,则调用assert_failed()这个出错程序。  

举例:

#define IS_GPIO_MODE(MODE)     (((MODE) == GPIO_Mode_IN) || ((MODE) ==GPIO_Mode_OUT) ||  ((MODE) == )

                                                          || ((MODE) == GPIO_Mode_AN)) void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) {             /* Check the parameters */           assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); } GPIO_InitStruct->GPIO_Mode是枚举类型,只能是GPIO_Mode_IN、GPIO_Mode_OUT、GPIO_Mode_AF、GPIO_Mode_AN中一个,因此宏定义IS_GPIO_MODE(MODE)能判断是其中一个为真,否则为假。因此达到调试的目的。 assert_failed()函数完成的具体操作,由用户自己定义。 

亲测发现

typedef struct {   uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.                                                    This parameter can be a value of @ref IRQn_Type                                                     (For the complete STM32 Devices IRQ Channels list, please                                                     refer to stm32f10x.h file) */

  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel                                                    specified in NVIC_IRQChannel. This parameter can be a value                                                    between 0 and 15 as described in the table @ref NVIC_Priority_Table */

  uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified                                                    in NVIC_IRQChannel. This parameter can be a value                                                    between 0 and 15 as described in the table @ref NVIC_Priority_Table */

  FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel                                                    will be enabled or disabled.                                                     This parameter can be set either to ENABLE or DISABLE */    } NVIC_InitTypeDef;

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) {   uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;      /* Check the parameters */                                      //没有检查NVIC_IRQChannelCmd参数的函数,经过查资料发现assert_param有没有都可以,只是为了调试方便2020.11.4   assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));   assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));     assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));        if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)   {     /* Compute the Corresponding IRQ Priority --------------------------------*/         tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;     tmppre = (0x4 - tmppriority);     tmpsub = tmpsub >> tmppriority;

    tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;     tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;     tmppriority = tmppriority << 0x04;              NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;          /* Enable the Selected IRQ Channels --------------------------------------*/     NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =       (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);   }   else   {     /* Disable the Selected IRQ Channels -------------------------------------*/     NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =       (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);   } }

另一例是有参数检查

typedef struct {   uint32_t EXTI_Line;               /*!< Specifies the EXTI lines to be enabled or disabled.                                          This parameter can be any combination of @ref EXTI_Lines */       EXTIMode_TypeDef EXTI_Mode;       /*!< Specifies the mode for the EXTI lines.                                          This parameter can be a value of @ref EXTIMode_TypeDef */

  EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines.                                          This parameter can be a value of @ref EXTIMode_TypeDef */

  FunctionalState EXTI_LineCmd;     /*!< Specifies the new state of the selected EXTI lines.                                          This parameter can be set either to ENABLE or DISABLE */  }EXTI_InitTypeDef;

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) {   uint32_t tmp = 0;

  /* Check the parameters */   assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode));   assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger));   assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line));     assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd));//有这个参数检查项目2020.11.4

  tmp = (uint32_t)EXTI_BASE;         if (EXTI_InitStruct->EXTI_LineCmd != DISABLE)   {     /* Clear EXTI line configuration */     EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line;     EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line;          tmp += EXTI_InitStruct->EXTI_Mode;

    *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;

    /* Clear Rising Falling edge configuration */     EXTI->RTSR &= ~EXTI_InitStruct->EXTI_Line;     EXTI->FTSR &= ~EXTI_InitStruct->EXTI_Line;          /* Select the trigger for the selected external interrupts */     if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling)     {       /* Rising Falling edge */       EXTI->RTSR |= EXTI_InitStruct->EXTI_Line;       EXTI->FTSR |= EXTI_InitStruct->EXTI_Line;     }     else     {       tmp = (uint32_t)EXTI_BASE;       tmp += EXTI_InitStruct->EXTI_Trigger;

      *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;     }   }   else   {     tmp += EXTI_InitStruct->EXTI_Mode;

    /* Disable the selected external lines */     *(__IO uint32_t *) tmp &= ~EXTI_InitStruct->EXTI_Line;   } }

最新回复(0)