/******************************************************************************* * 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 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); }
// 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; }