/******************************************************************************* * Function Name : EXTI_Init * Description : Initializes the EXTI peripheral according to the specified * parameters in the EXTI_InitStruct. * Input : - EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure * that contains the configuration information for the EXTI * peripheral. * Output : None * Return : None *******************************************************************************/ void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) { /* Check the parameters */ assert(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode)); assert(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger)); assert(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line)); assert(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd)); if (EXTI_InitStruct->EXTI_LineCmd != DISABLE) { *(u32 *)(EXTI_BASE + (u32)EXTI_InitStruct->EXTI_Mode)|= 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 { *(u32 *)(EXTI_BASE + (u32)EXTI_InitStruct->EXTI_Trigger)|= EXTI_InitStruct->EXTI_Line; } } else { /* Disable the selected external lines */ *(u32 *)(EXTI_BASE + (u32)EXTI_InitStruct->EXTI_Mode)&= ~EXTI_InitStruct->EXTI_Line; } }
/** * @brief Sets the external interrupt sensitivity of the selected port. * @note * - The modification of external interrupt sensitivity is only possible when * the interrupts are disabled. * - The normal behavior is to disable the interrupts before calling this * function, and re-enable them after. * @param EXTI_Port : The port number to access. * This parameter can be a value of @ref EXTI_Port_TypeDef * @param EXTI_Trigger : The external interrupt sensitivity value to set. * This parameter can be a value of @ref EXTI_Trigger_TypeDef * @retval None * @par Required preconditions: * - Global interrupts must be disabled before calling this function. */ void EXTI_SetPortSensitivity(EXTI_Port_TypeDef EXTI_Port, EXTI_Trigger_TypeDef EXTI_Trigger) { /* Check function parameters */ assert_param(IS_EXTI_PORT(EXTI_Port)); assert_param(IS_EXTI_TRIGGER(EXTI_Trigger)); /* Clear EXTI port sensitivity */ if (EXTI_Port == EXTI_Port_B) { EXTI->CR3 &= (uint8_t)(~EXTI_CR3_PBIS); } else if (EXTI_Port == EXTI_Port_D) { EXTI->CR3 &= (uint8_t)(~EXTI_CR3_PDIS); } else if (EXTI_Port == EXTI_Port_E) { EXTI->CR3 &= (uint8_t)(~EXTI_CR3_PEIS); } else /* EXTI_Port == EXTI_Port_PF */ { EXTI->CR3 &= (uint8_t)(~EXTI_CR3_PFIS); } /* Write EXTI port sensitivity */ EXTI->CR3 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Port); }
/** * @brief Initializes the EXTI peripheral according to the specified * parameters in the EXTI_InitStruct. * @param EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure * that contains the configuration information for the EXTI peripheral. * @retval None */ void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) { uint32_t tmp = 0; uint32_t irq_flag; irq_flag = local_irq_save(); /* 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)); 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; } local_irq_restore(irq_flag); }
/** * @brief Sets the external interrupt sensitivity of the selected pin. * @note - Global interrupts must be disabled before calling this function. * @note - The modification of external interrupt sensitivity is only possible * when he interrupts are disabled. * - The normal behavior is to disable the interrupts before calling this * function, and re-enable them after. * @param EXTI_Pin : The pin to configure. * This parameter can be a value of @ref EXTI_Pin_TypeDef * @param EXTI_Trigger : The external interrupt sensitivity value to set. * This parameter can be a value of @ref EXTI_Trigger_TypeDef * @retval None */ void EXTI_SetPinSensitivity(EXTI_Pin_TypeDef EXTI_Pin, EXTI_Trigger_TypeDef EXTI_Trigger) { /* Check function parameters */ assert_param(IS_EXTI_PINNUM(EXTI_Pin)); assert_param(IS_EXTI_TRIGGER(EXTI_Trigger)); /* Clear port sensitivity bits */ switch (EXTI_Pin) { case EXTI_Pin_0: EXTI->CR1 &= (uint8_t)(~EXTI_CR1_P0IS); EXTI->CR1 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Pin); break; case EXTI_Pin_1: EXTI->CR1 &= (uint8_t)(~EXTI_CR1_P1IS); EXTI->CR1 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Pin); break; case EXTI_Pin_2: EXTI->CR1 &= (uint8_t)(~EXTI_CR1_P2IS); EXTI->CR1 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Pin); break; case EXTI_Pin_3: EXTI->CR1 &= (uint8_t)(~EXTI_CR1_P3IS); EXTI->CR1 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Pin); break; case EXTI_Pin_4: EXTI->CR2 &= (uint8_t)(~EXTI_CR2_P4IS); EXTI->CR2 |= (uint8_t)((uint8_t)(EXTI_Trigger) << ((uint8_t)EXTI_Pin & (uint8_t)0xEF)); break; case EXTI_Pin_5: EXTI->CR2 &= (uint8_t)(~EXTI_CR2_P5IS); EXTI->CR2 |= (uint8_t)((uint8_t)(EXTI_Trigger) << ((uint8_t)EXTI_Pin & (uint8_t)0xEF)); break; case EXTI_Pin_6: EXTI->CR2 &= (uint8_t)(~EXTI_CR2_P6IS); EXTI->CR2 |= (uint8_t)((uint8_t)(EXTI_Trigger) << ((uint8_t)EXTI_Pin & (uint8_t)0xEF)); break; case EXTI_Pin_7: EXTI->CR2 &= (uint8_t)(~EXTI_CR2_P7IS); EXTI->CR2 |= (uint8_t)((uint8_t)(EXTI_Trigger) << ((uint8_t)EXTI_Pin & (uint8_t)0xEF)); break; default: break; } }
/** * @brief Sets the external interrupt sensitivity of the selected port. * @note - Global interrupts must be disabled before calling this function. * @note - The modification of external interrupt sensitivity is only possible * when the interrupts are disabled. * - The normal behavior is to disable the interrupts before calling this * function, and re-enable them after. * @param EXTI_Port : The port number to access. * This parameter can be a value of @ref EXTI_Port_TypeDef * @param EXTI_Trigger : The external interrupt sensitivity value to set. * This parameter can be a value of @ref EXTI_Trigger_TypeDef * @retval None */ void EXTI_SetPortSensitivity(EXTI_Port_TypeDef EXTI_Port, EXTI_Trigger_TypeDef EXTI_Trigger) { /* Check function parameters */ assert_param(IS_EXTI_PORT(EXTI_Port)); assert_param(IS_EXTI_TRIGGER(EXTI_Trigger)); /* Ceck if selected port is in EXTI_CR3 register */ if ((EXTI_Port & 0xF0) == 0x00) { /* Reset the trigger bits corresponding to EXTI_Port */ EXTI->CR3 &= (uint8_t) (~(uint8_t)((uint8_t)0x03 << EXTI_Port)); /* Write EXTI port trigger */ EXTI->CR3 |= (uint8_t)((uint8_t)(EXTI_Trigger) << EXTI_Port); } else /* selected port is in EXTI_CR4 register */ { /* Reset the trigger bits corresponding to EXTI_Port */ EXTI->CR4 &= (uint8_t) (~(uint8_t)((uint8_t)0x03 << (EXTI_Port & 0x0F))); /* Write EXTI port trigger */ EXTI->CR4 |= (uint8_t)(EXTI_Trigger << (EXTI_Port & 0x0F)); } }
// NOTE: param is for C callers. Python can use closure to get an object bound // with the function. uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t trigger_obj, mp_obj_t callback_obj, void *param) { const pin_obj_t *pin = NULL; uint v_line; if (MP_OBJ_IS_INT(pin_obj)) { // If an integer is passed in, then use it to identify lines 16 thru 22 // We expect lines 0 thru 15 to be passed in as a pin, so that we can // get both the port number and line number. v_line = mp_obj_get_int(pin_obj); if (v_line < 16) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d < 16, use a Pin object", v_line)); } if (v_line >= EXTI_NUM_VECTORS) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d >= max of %d", v_line, EXTI_NUM_VECTORS)); } } else { pin = pin_map_user_obj(pin_obj); v_line = pin->pin; } int mode = mp_obj_get_int(mode_obj); if (!IS_EXTI_MODE(mode)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Mode: %d", mode)); } int trigger = mp_obj_get_int(trigger_obj); if (!IS_EXTI_TRIGGER(trigger)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Trigger: %d", trigger)); } exti_vector_t *v = &exti_vector[v_line]; if (v->callback_obj != mp_const_none && callback_obj != mp_const_none) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d is already in use", v_line)); } // We need to update callback and param atomically, so we disable the line // before we update anything. exti_disable(v_line); if (pin && callback_obj) { // Enable SYSCFG clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // For EXTI lines 0 thru 15, we need to configure which port controls // the line. SYSCFG_EXTILineConfig(pin->port, v_line); } v->callback_obj = callback_obj; v->param = param; v->mode = mode; if (v->callback_obj != mp_const_none) { // The EXTI_Init function isn't atomic. It uses |= and &=. // We use bit band operations to make it atomic. EXTI_EDGE_BB(EXTI_Trigger_Rising, v_line) = trigger == EXTI_Trigger_Rising || trigger == EXTI_Trigger_Rising_Falling; EXTI_EDGE_BB(EXTI_Trigger_Falling, v_line) = trigger == EXTI_Trigger_Falling || trigger == EXTI_Trigger_Rising_Falling; exti_enable(v_line); /* Enable and set NVIC Interrupt to the lowest priority */ NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = nvic_irq_channel[v_line]; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } return v_line; }