mp_obj_t pyb_gpio(uint n_args, mp_obj_t *args) { const pin_obj_t *pin = pin_map_user_obj(args[0]); if (n_args == 1) { // get pin return MP_OBJ_NEW_SMALL_INT(HAL_GPIO_ReadPin(pin->gpio, pin->pin_mask)); } // set pin HAL_GPIO_WritePin(pin->gpio, pin->pin_mask, rt_is_true(args[1])); return mp_const_none; }
mp_obj_t pyb_gpio_input(uint n_args, mp_obj_t *args) { const pin_obj_t *pin = pin_map_user_obj(args[0]); uint32_t pull = GPIO_NOPULL; if (n_args > 1) { pull = mp_obj_get_int(args[1]); } GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = pin->pin_mask; GPIO_InitStructure.Mode = GPIO_MODE_INPUT; GPIO_InitStructure.Pull = pull; HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure); return mp_const_none; }
static mp_obj_t pin_map_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { pin_map_obj_t *self = self_in; mp_check_nargs(n_args, 1, 2, n_kw, false); if (n_args > 1) { if (!self->map_dict) { self->map_dict = mp_obj_new_dict(1); } mp_obj_dict_store(self->map_dict, args[0], args[1]); return mp_const_none; } // Run an argument through the mapper and return the result. return (mp_obj_t)pin_map_user_obj(args[0]); }
mp_obj_t pyb_gpio_output(uint n_args, mp_obj_t *args) { const pin_obj_t *pin = pin_map_user_obj(args[0]); uint32_t mode = GPIO_MODE_OUTPUT_PP; if (n_args > 1) { mode = mp_obj_get_int(args[1]) == GPIO_MODE_OUTPUT_OD ? GPIO_MODE_OUTPUT_OD: GPIO_MODE_OUTPUT_PP; } GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pin = pin->pin_mask; GPIO_InitStructure.Mode = mode; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; GPIO_InitStructure.Pull = GPIO_NOPULL; HAL_GPIO_Init(pin->gpio, &GPIO_InitStructure); return mp_const_none; }
// 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; }