Samd21 External Interrupt clock setup

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

Having trouble setting up the clock for the external interrupt controller. Can anybody see what is going wrong with my code. I'm sure there's something missing but this is how I have done for the Sercom3/4 usart.

I get stuck in a loop here, which is called from inside system_gclk_chan_set_config(EIC_GCLK_ID, &eic_gclk);

	while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) {
		/* Wait for clock to become disabled */
	}

Here is my initialization code

void EXT_Int_init(void){

	struct system_gclk_chan_config eic_gclk;

	PM->APBAMASK.reg = PM_APBAMASK_EIC;

	// Turn on Generic Clock
	system_gclk_chan_get_config_defaults(&eic_gclk);
	system_gclk_chan_set_config(EIC_GCLK_ID, &eic_gclk);
	system_gclk_chan_enable(EIC_GCLK_ID);

	EIC->EVCTRL.bit.EXTINTEO10 = 1; //Set PA10 as external interrupt pin
	EIC->CONFIG[1].bit.FILTEN2 = 1; //Turn on filtering
	EIC->CONFIG[1].bit.SENSE2  = 3; //Trigger on both edges

	EIC->CTRL.reg = EIC_CTRL_ENABLE;
	while(EIC->STATUS.bit.SYNCBUSY);
}

 

This topic has a solution.

J-Bones

 

Last Edited: Wed. May 11, 2022 - 10:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know why it fails but is there some reason why you are doing this low level stuff and not just extint_chan_set_config (which will do it for you)? Looks like there is an example project for EXTINT.

/Lars

 

 

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

GiraffeDaddy wrote:

	while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) {
		/* Wait for clock to become disabled */
	}

 

What exactly are you trying to do? I've never used ASF, and I guess your function calls are ASF? ...and, they look like they're trying to enable a clock.

 

This 'offending' bit is set when a clock is enabled, and your while loop will stay there forever whilst the clock is enabled? (which is the problem you're describing).

 

 

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

You have to disable the the generic clock to assign the EIC to it.

J-Bones

 

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

Lajon wrote:
why you are doing this low level stuff and not just extint_chan_set_config

 

Because I am already using 99% of my data memory usage and need to keep this part of the code as small as possible using the least amount of variables possible. 

J-Bones

 

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

GiraffeDaddy wrote:

Lajon wrote:

why you are doing this low level stuff and not just extint_chan_set_config

 

 

Because I am already using 99% of my data memory usage and need to keep this part of the code as small as possible using the least amount of variables possible. 

 

Are you in production yet? Or is this hobby tinkering. Unless you're talking high volume, with next to 0 chance of ever needing to increase functionality - I would recommend strongly against taking the risk of shipping a product at 99% memory capacity.

 

Where are you actually disabling the clock, you don't show it in your code example. 

 

From the datasheet:  15.6.3.2 Disabling a Generic Clock A generic clock is disabled by writing CLKCTRL.CLKEN=0. The SYNCBUSY bit will be cleared when this write synchronization is complete. CLKCTRL.CLKEN will stay in its previous state until the synchronization is complete. The generic clock is gated when disabled.

 

Where are you writing the CLKEN bit to 0? And are you waiting for the relevant SYNCBUSY flag to clear?

Last Edited: Mon. May 9, 2022 - 10:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you in production yet? Or is this hobby tinkering. Unless you're talking high volume, with next to 0 chance of ever needing to increase functionality - I would recommend strongly against taking the risk of shipping a product at 99% memory capacity.

This is for production, thankfully we have it set up with a bootloader to do firmware updates which will allow us to fix any issues down the road. There is some optimization that can still to be done to get down to probably 90%. The reason so much is being used is that I need to use a LUT containing 512 uint32_t's. Its taking up half of my program memory, The stack size is 0x300, which is about 19%.  There's really no way to get around this massive LUT I need to use.

J-Bones

 

Last Edited: Tue. May 10, 2022 - 09:03 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't understand your mixture of ASF and bare-metal code.

Normally, wouldn't you just use the main CPU GCLK for the EIC as well?
The Arduino EIC initialization looks like:

static void __initialize()
{
   :

  NVIC_DisableIRQ(EIC_IRQn);
  NVIC_ClearPendingIRQ(EIC_IRQn);
  NVIC_SetPriority(EIC_IRQn, 0);
  NVIC_EnableIRQ(EIC_IRQn);

  // Enable GCLK for IEC (External Interrupt Controller)
  GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC));

  // Enable EIC
  EIC->CTRL.bit.ENABLE = 1;
  while (EIC->STATUS.bit.SYNCBUSY == 1) { }
}

It takes that one statement to set the EIC GCLK to use GCLK0...

 

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

westfw wrote:

 

 // Enable GCLK for IEC (External Interrupt Controller)
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC));

 

 

It takes that one statement to set the EIC GCLK to use GCLK0...

 

 

This line fixed it!

J-Bones

 

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

GiraffeDaddy wrote:

 

The reason so much is being used is that I need to use a LUT containing 512 uint32_t's. Its taking up half of my program memory, The stack size is 0x300, which is about 19%.  There's really no way to get around this massive LUT I need to use.

 

 

Do you really need 32-bits of range for these variables, or would 24-bits suffice given the expected range of values? If so, you could cut your storage size enormously, and simply require a small amount of code to construct your 24-bit variable from each set of 3 bytes, stuff into a local uint32_t where they're used to do whatever operations you need on them?

 

I've done something similar in the past when storing large arrays of 12-bit data in flash, store 2x 12-bit variables in 3 bytes and pack/unpack where you need it. Trade off speed for space?

Last Edited: Thu. May 12, 2022 - 01:03 AM