Atmel Studio 7, Button cb only allows 1 press

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using a basic default application from microsoft studio, assuming same as atmel studio at this point. I can enter the callback, and the system still continues to run, it just appears to not allow more than 1 entry. i output running in a loop in the main file and it will continue to print loop but it will only ever print 1 "B" no matter how many times I hit the button

 

static void button_cb(void)
{
	printf("B");
	/* Add button callback functionality here */
	//oper_mode = (oper_mode) ? 0x00 : 0x01;
}

All I want to do is flip the bit every time I push a button. It appears to only ever see 1 button press. I have tried setting the button pull_up and pull down, but nothing seems to work for it. 

void button_init(void)
{
	struct gpio_config config_gpio_pin;

	gpio_get_config_defaults(&config_gpio_pin);

	config_gpio_pin.direction  = GPIO_PIN_DIR_INPUT;
	config_gpio_pin.input_pull = GPIO_PIN_PULL_NONE;

	gpio_pin_set_config(BUTTON_0_PIN, &config_gpio_pin);
}

Per request, her is the callback information. I am also using an old SAMB11-ZR dev kit 


int main(void)
{
	gpio_init();
	button_init();
	button_register_callback(button_cb);
}

void button_register_callback(button_callback_t callback)
{
	
	wakeup_int_register_callback(PORT_WAKEUP_SOURCE_AON_GPIO_0, callback);
	gpio_register_callback(BUTTON_0_PIN, aon_gpio0_cb_handler, GPIO_CALLBACK_RISING);
}

enum port_status_code wakeup_int_register_callback(enum port_wakeup_source wakeup_source,
	portint_callback_t fp)
{
	enum port_status_code status = PORT_STATUS_OK;
	if((fp != NULL) && ((wakeup_source == PORT_WAKEUP_SOURCE_AON_GPIO_0)
	|| (wakeup_source == PORT_WAKEUP_SOURCE_AON_GPIO_1)
	|| (wakeup_source == PORT_WAKEUP_SOURCE_AON_GPIO_2))) {
		wakeup_source_callback[wakeup_source] = fp;
	}
	else {
		status = PORT_STATUS_ERR_INVALID_ARG;
	}
	return status;
}

void gpio_register_callback(uint8_t gpio_pin, gpio_callback_t callback_func,
				enum gpio_callback callback_type)
{
	/* Sanity check arguments */
	Assert(callback_func);
	Assert(gpio_pin < 48);

	uint8_t gpio_port = 0;

	if (gpio_pin < 16) {
		gpio_port = 0;
	} else if (gpio_pin < 32) {
		gpio_port = 1;
	} else {
		gpio_port = 2;
	}
	switch (callback_type) {
	case GPIO_CALLBACK_LOW:
		_gpio_instances[gpio_port].hw->INTTYPECLR.reg = 1 << (gpio_pin % 16);
		_gpio_instances[gpio_port].hw->INTPOLCLR.reg = 1 << (gpio_pin % 16);
		break;

	case GPIO_CALLBACK_HIGH:
		_gpio_instances[gpio_port].hw->INTTYPECLR.reg = 1 << (gpio_pin % 16);
		_gpio_instances[gpio_port].hw->INTPOLSET.reg = 1 << (gpio_pin % 16);
		break;

	case GPIO_CALLBACK_RISING:
		_gpio_instances[gpio_port].hw->INTTYPESET.reg = 1 << (gpio_pin % 16);
		_gpio_instances[gpio_port].hw->INTPOLSET.reg = 1 << (gpio_pin % 16);
		break;

	case GPIO_CALLBACK_FALLING:
		_gpio_instances[gpio_port].hw->INTTYPESET.reg = 1 << (gpio_pin % 16);
		_gpio_instances[gpio_port].hw->INTPOLCLR.reg = (1 << (gpio_pin % 16));
		break;

	case GPIO_CALLBACK_N:
		break;
	}
	/* Register callback function */
	_gpio_instances[gpio_port].callback[gpio_pin % 16] = callback_func;
	/* Set the bit corresponding to the gpio pin */
	_gpio_instances[gpio_port].callback_reg_mask |= (1 << (gpio_pin % 16));
}

 

Last Edited: Mon. Jul 4, 2022 - 10:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you assuming we're all pyschic here?

 

You haven't shown the code that attaches the callback to the event

You haven't shown the code the responds to the event that then invokes that callback

You haven't even shown the code that directs execution to the to the event handler when the input changes

 

Cut your issue down to the smallest COMPLETE program that demonstrates your problem and post that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you want to execute any task every time you press a button, you have to write your code inside a  while(1) loop. Otherwise, the task will be performed only once.  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Don't think you are psychic, but not sure how deep down that rabbit hole you want to go. This is a pretty much a sample code from starting up a new project. I updated the post though per request. I was honestly hoping it was something simple like you have to CLR an interrupt flag or something in the callback. Maybe that is why you want to see the info though.
 

As far as Id understand this baseline code, it should be operating as a type of ISR every time I press the button. And it operates 1 time but no more after that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When main ends (due to no while(1) loop), the compiler jumps to an exit routine which does a cli and then a forever loop.

You need to keep main from exiting...

 

avrdmlfreak wrote:

int main(void)
{
	gpio_init();
	button_init();
	button_register_callback(button_cb);
        while (1){};   // <-- Insert this and you should see interrupts continuing to operate...
}

David

Last Edited: Mon. Jul 4, 2022 - 12:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

my main has a giant while loop. Because i cant seem to get the ISR type callabck to work i added a button check i nthe main loop to solve for now. just not ideal or what i am looking for.

int main(void)
{
	platform_driver_init();
	acquire_sleep_lock();

	/* Initialize serial console */
	serial_console_init();
	
	/* Hardware timer */
	hw_timer_init();
	
	/* button initialization */
	gpio_init();
	button_init();
	button_register_callback(button_cb);
	
	hw_timer_register_callback(timer_callback_fn);
	//Enable_global_interrupt();
	
	DBG_LOG("Initializing BLE Application");
	
	/* initialize the BLE chip  and Set the Device Address */
	ble_device_init(NULL);
	
	/* Start Advertising process */
	start_advertisement();


	register_resume_callback(platform_resume_cb);
	/* Set ULP mode */
	ble_set_ulp_mode(BLE_ULP_MODE_SET);
	
	oper_mode = 0x00;
	
	while(true)
	{	
		if(gpio_pin_get_input_level(PIN_AO_GPIO_0) && oper_mode == 0x00){
			oper_mode = 0x01;
			manuf_adv_data[13] = (manuf_adv_data[13] > 0x00) ? 0x00 : 0x01;
			at_ble_adv_stop();
			start_advertisement();
		}else if(!gpio_pin_get_input_level(PIN_AO_GPIO_0) && oper_mode == 0x01){
			oper_mode = 0x00;
		}
		/* BLE Event task */
		ble_event_task(BLE_EVENT_TIMEOUT);

		//delay_ms(500);
		//printf("Running\r\n");
	}
}