Looking for SAM D11's external interrupt bare metal code driver - Page 1
Forum section: electronics / general

author: muthukural001
author_rank: Regular Contributor
timestamp: December 22, 2017, 08:56:10 am
content: Hello All,I am looking for SAM D series external interrupt bare metal code driver. Please suggest.Regards,Muthu

author: ataradov
author_rank: Super Contributor
timestamp: December 22, 2017, 05:53:30 pm
content: Here is a sample code:Code:void eic_init(void){HAL_GPIO_XXX_in();HAL_GPIO_XXX_pmuxen(PORT_PMUX_PMUXE_A_Val);GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(EIC_GCLK_ID) |GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);EIC->CTRL.reg = EIC_CTRL_ENABLE;EIC->CONFIG.reg = EIC_CONFIG_SENSE7_RISE;EIC->INTENSET.reg = EIC_INTENSET_EXTINT7;NVIC_EnableIRQ(EIC_IRQn);}void irq_handler_eic(void){EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT7;}

author: muthukural001
author_rank: Regular Contributor
timestamp: December 25, 2017, 07:16:33 am
content: Hi ataradov,Thank you very much. U always support newbies.Regards,Muthu

author: muthukural001
author_rank: Regular Contributor
timestamp: December 28, 2017, 08:13:30 am
content: Hi Ataradov,I have just seen your support onhttps://www.eevblog.com/forum/microcontrollers/samd21-standby-current-draw-increases-after-interrupt-never-returns-to-lowest/msg1380718/#msg1380718] https://www.eevblog.com/forum/microcontrollers/samd21-standby-current-draw-increases-after-interrupt-never-returns-to-lowest/msg1380718/#msg1380718.In our case, I am using external RTC which is used to wake up Microcontroller at evening 6'O clock and send MCU to sleep when Morning 7'O clock. And using external 8 MHZ oscillator as system clock.Your code:Code:int main(void){sys_init();uart_init(115200);eic_init();uart_puts("\r\nHello, world!\r\n");HAL_GPIO_LED_out();HAL_GPIO_LED_clr();for (int j = 0; j < 5; j++){for (int i = 0; i < 500000; i++)asm("nop");HAL_GPIO_LED_toggle();}PM->SLEEP.reg = PM_SLEEP_IDLE(2); // Stop CPU, AHB and APB clocksSCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;while (1){HAL_GPIO_LED_set();__WFI();for (int j = 0; j < 9; j++){for (int i = 0; i < 100000; i++)asm("nop");HAL_GPIO_LED_toggle();}}return 0;}Questions:1. Can I run My external oscillator 8 MHZ even in IDLE sleep mode. For this, should I set XOSC.ONDEMAND=1 ?2. Please make sure me in the code execution flow1.After reset device:Code:sys_init();uart_init(115200);eic_init();uart_puts("\r\nHello, world!\r\n");HAL_GPIO_LED_out();HAL_GPIO_LED_clr();for (int j = 0; j < 5; j++){for (int i = 0; i < 500000; i++)asm("nop");HAL_GPIO_LED_toggle();}2. Send to sleep:Code:PM->SLEEP.reg = PM_SLEEP_IDLE(2); // Stop CPU, AHB and APB clocksSCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;3. Wait for interrupt4. Resume code executionCode:while (1){HAL_GPIO_LED_set();__WFI(); // Send to sleep mode5. Wait for interrupt6. Resume code executionCode:for (int j = 0; j < 9; j++){for (int i = 0; i < 100000; i++)asm("nop");HAL_GPIO_LED_toggle();}6. while(1) repeats3. Can I use Edge detection interrupt method instead level method to wake up Microcontroller.Please let me know.

author: ataradov
author_rank: Super Contributor
timestamp: December 28, 2017, 05:13:05 pm
content: I don't really understand the question about clocks. You can configure any clock to run or not run in any mode. Which ones you need and don't need is up to your application. If you want to keep the clock always running, then you need to set RUNSTDBY. If you want the clock to run only when there is a peripheral to use it, then configure ONDEMAND.The item "2. Send to sleep:" is actually just a configuration of the sleep mode, nothing sleeps at this point. The actual sleep is __WFI(); instruction.Yes, edge detect can be used for wake-up.

author: muthukural001
author_rank: Regular Contributor
timestamp: December 29, 2017, 05:19:49 am
content: Hi Ataradov,Thanks. I am using SAM D11.Case 1:I tried both edge and level wakeup while EIC peripheral clock set to GCLK_GENERATOR_0 which has External 8MHZ crystal oscillator with Prescalar 1.External 8MHZ crystal oscillator set to run in sleep mode by setting ONDEMAND bit.In the above case, Level wake up is working fine but not Edge wake up.Case 2:Edge wake up seems to be working when EIC clock set to OSCULP32K (through GCLK_GENERATOR_1).Code:static void eic_init(void){HAL_GPIO_PIRSEN_in();HAL_GPIO_PIRSEN_pmuxen(PORT_PMUX_PMUXE_A_Val);GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(EIC_GCLK_ID) |GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(1);EIC->CONFIG.reg =EIC_CONFIG_SENSE0_RISE; //EIC_CONFIG_SENSE0_HIGH;EIC->WAKEUP.reg = EIC_WAKEUP_WAKEUPEN0;EIC->INTENSET.reg = EIC_INTENSET_EXTINT0;EIC->CTRL.reg = EIC_CTRL_ENABLE;while(EIC->STATUS.reg & EIC_STATUS_MASK);NVIC_EnableIRQ(EIC_IRQn);}clocks.hCode:/* SYSTEM_CLOCK_SOURCE_XOSC configuration - External clock/oscillator */# define CONF_CLOCK_XOSC_ENABLE true//false# define CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL SYSTEM_CLOCK_EXTERNAL_CRYSTAL# define CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY 8000000UL# define CONF_CLOCK_XOSC_STARTUP_TIME SYSTEM_XOSC_STARTUP_32768# define CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL true# define CONF_CLOCK_XOSC_ON_DEMAND true# define CONF_CLOCK_XOSC_RUN_IN_STANDBY false/* Configure GCLK generator 0 (Main Clock) */# define CONF_CLOCK_GCLK_0_ENABLE true# define CONF_CLOCK_GCLK_0_RUN_IN_STANDBY false# define CONF_CLOCK_GCLK_0_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_XOSC//SYSTEM_CLOCK_SOURCE_OSC8M# define CONF_CLOCK_GCLK_0_PRESCALER 1# define CONF_CLOCK_GCLK_0_OUTPUT_ENABLE false/* Configure GCLK generator 1 */# define CONF_CLOCK_GCLK_1_ENABLE true//false# define CONF_CLOCK_GCLK_1_RUN_IN_STANDBY false# define CONF_CLOCK_GCLK_1_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_ULP32K//SYSTEM_CLOCK_SOURCE_XOSC32K# define CONF_CLOCK_GCLK_1_PRESCALER 1# define CONF_CLOCK_GCLK_1_OUTPUT_ENABLE falsePlease suggest.

author: ataradov
author_rank: Super Contributor
timestamp: December 29, 2017, 05:23:48 am
content: For edge wake-up, EIC has to be clocked. How else it would detect an edge? And I don't know if setting an edge trigger will request the clock, probably not.So if you need the edge detect to work, just clock the EIC with an always running clock. There is no point in trying to use on demand system here, when clock is always going to be in demand.If you want to save power and don't mind slower reaction time, then clocking from ULP32K is a good solution.

author: muthukural001
author_rank: Regular Contributor
timestamp: December 29, 2017, 07:04:41 am
content: Hi Ataradov,Edge detection is working fine with XOSC.RUNSTDBY=1 and XOSC.ONDEMAND=0.Page 151 in the datasheet says that this is the configuration for "Always run in IDLE and STANDBY sleep modes."Thank you very much for pointing the things out .Regards,Muthu

author: ataradov
author_rank: Super Contributor
timestamp: December 29, 2017, 07:06:41 am
content: Quote from: muthukural001 on December 29, 2017, 07:04:41 amBut this will keep oscillator running, and that's not great if you are trying to conserve power. ULP32K runs all the time anyway, so it is better to use it if you don't have a requirement for really fast wake-up detection.

author: muthukural001
author_rank: Regular Contributor
timestamp: January 08, 2018, 12:58:33 pm
content: Hi Ataradov,My system is waking up properly through external interrupt unless I do external reset or Power On reset.This external reset and Power on reset gives problem in waking up micro controller.I have read the below "SAMD20 Problem waking from system_sleep()" in atmel forum.QuoteSo, should I add NVMCTRL - CTRLB.bit.SLEEPPRM = 3 in my code . Please suggest.Regards,Muthu

author: ataradov
author_rank: Super Contributor
timestamp: January 08, 2018, 08:00:25 pm
content: What exactly happens in your case? Especially with external reset. External reset should wake up device from any mode, even according to this errata.

author: muthukural001
author_rank: Regular Contributor
timestamp: January 09, 2018, 03:15:09 am
content: Hi ataradov,I have two RTC interrupts, one for evening 6'O clock which will wake up MCU from sleep and other at morning 11'O clock which is used to put MCU in to sleep mode. Both interrupts generates on the same pin.Problem:When power is always there for module, System wakes up at 6'O clock and goes to sleep at 11'O clock. But, when I do switch OFF and ON and external reset, wake up is not happening.External interrupt config:Code:static void eic_init(void){HAL_GPIO_ALARM_PIN_in();HAL_GPIO_ALARM_PIN_pmuxen(PORT_PMUX_PMUXE_A_Val); //PORT_PMUX_PMUXE_A_ValGCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(EIC_GCLK_ID) |GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(1); //GCLK_CLKCTRL_GEN(1) for using OSCULP32K to clock EICEIC->CONFIG.reg =EIC_CONFIG_SENSE3_RISE; //EIC_CONFIG_SENSE0_HIGH;EIC->WAKEUP.reg = EIC_WAKEUP_WAKEUPEN3;EIC->INTENSET.reg = EIC_INTENSET_EXTINT3;EIC->CTRL.reg = EIC_CTRL_ENABLE;while(EIC->STATUS.reg & EIC_STATUS_MASK);NVIC_EnableIRQ(EIC_IRQn);}//RTC interruptsvoid EIC_Handler(void){if (EIC->INTFLAG.reg & EIC_INTFLAG_EXTINT3){EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT3;clock_check=true;}}main:Code:int main (void){system_init();i2c_init();ret=isl29029_reset();if (ret < 0)return ret;configure_GPIO_peripherals();uart_init(38400);timer_init();eic_init();if(MCP79410_IsRunning()) //If clock is already running stop it{rtc_running=true;}if (!rtc_running){MCP79410_Initialize();EEPROM_SetBlockProtection(NO_PROTECTION);EEPROM_Write(EEPROM_START,0);while(uart_getc()!=0x41);MCP79410_SetTime(&current_time); // 11:11:00 AM (21/12/2017) (Standard time)MCP79410_EnableOscillator();rtc_running=true;MCP79410_SetAlarmMatch(HOURS_MATCH,ZERO); //Alarm ZERO will trigger on minutes matchMCP79410_SetAlarmMatch(HOURS_MATCH,ONE);MCP79410_SetAlarmMFPPolarity(HIGHPOL,ZERO); //Configure Alarm pin polarity as HIGHMCP79410_SetAlarmMFPPolarity(HIGHPOL,ONE);MCP79410_ClearInterruptFlag(ZERO);MCP79410_ClearInterruptFlag(ONE);MCP79410_SetAlarmTime(&alarm_time,ZERO); //Set alarm timealarm_time.hour=11;MCP79410_SetAlarmTime(&alarm_time,ONE);MCP79410_SetMFP_Functionality(ALARM_INTERRUPT); //Set alarm interruptuart_putc('S');}PM->SLEEP.reg = PM_SLEEP_IDLE(2); // Stop CPU, AHB and APB clocksSCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;while(1){switch(moduleState){case CHECK_TIME_FIRST:{MCP79410_GetTime(&current_time);if ((current_time.hour >= MORNING_SEVENO_CLOCK) && (current_time.hour < EVENING_SIXO_CLOCK)){moduleState=MORNING_SEVEN_AM;}else{moduleState=EVENING_SIX_PM;}}break;case CHECK_LUX_BELOW_FOURTHY:{ret=check_lux_below_fourthy(&brightness);if(ret < 0)return ret;lux_limit=(brightness < LUX_FOURTHY ? true : false);if(clock_check){moduleState=CHECK_CLOCK;}else if(lux_limit){moduleState=LED_STRIPS_FOR_LUX;lux_limit=false;}else{moduleState=TURN_OFF_ALL_STRIPS;}}break;case LED_STRIPS_FOR_LUX:{// Turn on 2 strips and Turn off 3rd and 4th strips if already ONHAL_GPIO_LED1_set();HAL_GPIO_LED2_set();moduleState=CHECK_HUMAN_MOMENT;}break;case TURN_OFF_ALL_STRIPS:{// Turn off all the strips either lux above 40 or RTC time is morning 7'O clockHAL_GPIO_LED1_clr();HAL_GPIO_LED2_clr();HAL_GPIO_LED3_clr();HAL_GPIO_LED4_clr();HAL_GPIO_LED7_clr();HAL_GPIO_LED8_clr();MCP79410_GetTime(&current_time);if((current_time.hour >= EVENING_SIXO_CLOCK) || (current_time.hour < MORNING_SEVENO_CLOCK)){moduleState=CHECK_LUX_BELOW_FOURTHY;}else{ret=isl_power_down();if(ret < 0)return ret;__WFI(); //Go to sleep for 11'O clock interruptmoduleState=CHECK_CLOCK; //wake up from sleep for 6'O clock interrupt}}break;case CHECK_HUMAN_MOMENT:{if (HAL_GPIO_PIRSEN_read()){timer_set_period(ONE_SECOND_INTERVAL); //20 second intervalEight_strips=true;moduleState=LED_STRIPS_FOR_PIR;}else if (twenty_second){twenty_second=false;moduleState=TURN_OFF_PIR_LED_STRIPS;}elsemoduleState=CHECK_LUX_BELOW_FOURTHY;}break;case LED_STRIPS_FOR_PIR:{// Turn on other strips if human moment is thereHAL_GPIO_LED3_set();HAL_GPIO_LED4_set();HAL_GPIO_LED7_set();HAL_GPIO_LED8_set();Eight_strips=true;moduleState=CHECK_LUX_BELOW_FOURTHY;}break;case TURN_OFF_PIR_LED_STRIPS:{//Turn off after timer reaches 20 secondsHAL_GPIO_LED3_clr();HAL_GPIO_LED4_clr();HAL_GPIO_LED7_clr();HAL_GPIO_LED8_clr();moduleState=CHECK_LUX_BELOW_FOURTHY;}break;case CHECK_CLOCK:{if (clock_check){if (MCP79410_Read(ALM1WDAY) & ALMx_IF) //7'O clock interrupt{MCP79410_ClearInterruptFlag(ONE);EEPROM_Write(0,MORNING_SEVENO_CLOCK);moduleState=MORNING_SEVEN_AM;}if (MCP79410_Read(ALM0WDAY) & ALMx_IF) //6'O clock interrupt{MCP79410_ClearInterruptFlag(ZERO);EEPROM_Write(0,EVENING_SIXO_CLOCK);moduleState=EVENING_SIX_PM;}clock_check=false;}}break;case EVENING_SIX_PM:{ret=isl29029_setup();if (ret < 0)return ret;ret=set_lsensor_range(ALS_IR_LOW_THRESHOLD,ALS_IR_HIGHT_THRESHOLD);if (ret < 0)return ret;moduleState=CHECK_LUX_BELOW_FOURTHY;}break;case MORNING_SEVEN_AM:{moduleState=TURN_OFF_ALL_STRIPS;}break;default:break;}}/* Insert application code here, after the board has been initialized. */}ThanksMuthu

author: ataradov
author_rank: Super Contributor
timestamp: January 09, 2018, 03:23:07 am
content: Well, that's a lot of code. Have you tried to run it nuder the debugger ans actually check what's going on?You are also returning from main in a lot of places. This is a very bad way of handling errors, main() should never return. Debug and see if one of those error conditions becomes true.Also have you checked that you do not wake up, or you just assume it by the lack of desired reaction? Put wake up status on a pin (or LED) and set it high before the sleep and low after. This way you will know for sure that device is sleeping.

author: muthukural001
author_rank: Regular Contributor
timestamp: April 02, 2018, 03:29:32 pm
content: Hi Alex,As I said, RTC generate two interrupts, one at Morning 7'O clock and other at evening 6'O clock.My code is like following:1. Read RTC time registers and check Whether time is between Morning 7'O clock and Evening 6'O clock(18'O clock for 24 hours mode) or Evening 6'O clock and Morning 7'O clock.2. If it is between Morning 7'o clock and Evening 6'o clock, configure EIC with wake up enable to detect Evening 6'O clock interrupt and go to sleep.3.If it is between Evening 6' O clock and Morning 7'o clock, configure EIC without wake up to detect Morning 7'O clock interrupt.4. Doing the above step 3 and step 4 whenever the respective interrupt occurs.Things were working fine for last 30 days where our board is always powered on.But, yesterday I switched off and On the board while it was sleeping.Then, it didn't come out from the sleep mode and flash our LEDs when Evening 6'O clock interrupt occurs.The same is happening when I switched off and on the board while MCU is active.In this case, MCU doesn't go to sleep mode (By means of LEDs are always On).I have no clue at all. Please suggest.Regards,Muthu

author: ataradov
author_rank: Super Contributor
timestamp: April 02, 2018, 04:36:40 pm
content: I can't debug complex problems like this remotely. This also involves some RTC chip I know nothing about.Set up a debugging environment and debug your stuff. If you think that your problem happens after power cycles, then power cycle it a lot. Don't wait 30 days for it to fail.