ATSAMR21XPro-Board intialization stuck in system_gclk_chan_disable:415 and does not return out of system_init().

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

All,

I'm a newbie learning ATSAMR21XPro. Currently I'm stuck and appreciate if more experienced folks can help with the problem which appears to be related to clocks.

 

Have created a bare minimal program to set GPIO EXT1_PIN_3 to out and used delay service for attaining blink. When  observed in debugger, the code execution always get stuck in gclk.c

Stack:

  GccBoardProject2.elf! system_gclk_chan_disable:415(channel=<optimized out>) 
  GccBoardProject2.elf! system_gclk_chan_set_config:362(channel=<optimized out>, config=<optimized out>) 
  GccBoardProject2.elf! _switch_peripheral_gclk:755() 
  GccBoardProject2.elf! system_clock_init:780() 
  GccBoardProject2.elf! system_init:94() 
  GccBoardProject2.elf! main:38() 
Registers :

  R00 = 0x00000002 R01 = 0x40000C00 R02 = 0x00004000 R03 = 0x0000C203 R04 = 0x00000003 R05 = 0x00000669 R06 = 0x00000005 R07 = 0xFBFFFFFF R08 = 0xFBFFFFFF R09 = 0x7FFFFBFF R10 = 0xFFEFFBB7 R11 = 0xFFFFF6AB R12 = 0xFFFFFBFF

 

Tested and confirmed that the same program works on other board which I have.

 

int main (void)

{

system_init();

delay_init();

while (1) {

delay_s(1);

port_pin_set_output_level(EXT1_PIN_3, LED_0_ACTIVE);

delay_s(1);

port_pin_set_output_level(EXT1_PIN_3, !LED_0_ACTIVE);

}

in board_init.c in function void system_board_init(void)

/* Configure PA06 to be output only pin */

 pin_conf.direction  = PORT_PIN_DIR_OUTPUT;
 port_pin_set_config(EXT1_PIN_3, &pin_conf);
 port_pin_set_output_level(EXT1_PIN_3, LED_0_INACTIVE);

 

Is there a configuration that I'm missing? or worse is my XPro board is beyond repair?. The XPro board is a new one and this is the first program that was flashed.

 

Thanks

Ramya

 

Attachment(s): 

This topic has a solution.

Last Edited: Tue. Aug 23, 2016 - 09:13 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

6 hours of debugging but have found no solution. As a temporary work around,     in  system_clock_init() commented _switch_peripheral_gclk() which is documented for disabling all peripheral clock to  save power.  Hope this commenting of line doesn't cascade into other problem. For the time being it seems to be working and unblocked my development for now. Appreciate if anyone can help me with hints to resolve the clock issue.

 

I'm using ASF 3.24.2

Last Edited: Sat. Jul 4, 2015 - 04:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you setting a too-high CPU clock speed without setting the necessary Flash Wait States?

 

Or are you clocking something else beyond its specification?

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

ramya, I know, one year passed, but still... :)
Did you found any solution for this problem?

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

I had this problem and found a solution that worked for me. The cause was that when I set up my Watchdog timer I enabled .always_on. I didn't think anything of it, but it turns out that setting write-locks the watchdog register, and when you do a software reset, that bit is still set and the watchdog is still running.

 

The ASF initializes the clock channels of all peripherals by attempting to turn them off and switch them over to an inactive GCLK generator. What I found in my situation was that it would go through each of the channels and disable them in the system_gclk_chan_disable() function, but once it reached the channel dedicated to the watchdog timer, it would try to turn it off and then enter an infinite loop waiting for it to be disabled.

 

This seems to be an issue with the ASF framework. It doesn't check to see if the register of the channel is write-locked, it just tries to write to it. I added a quick check to the system_gclk_chan_set_config() function which checks the register for a write-lock, and, if found, skips it. Here is the code:

 

// User added check for write-lock on this channel.
int write_locked = false;
system_interrupt_enter_critical_section();

/* Select the requested generator channel */
*((uint8_t*)&GCLK->CLKCTRL.reg) = channel;
if(GCLK->CLKCTRL.bit.WRTLOCK) {
    write_locked = true;
}
system_interrupt_leave_critical_section();
if(write_locked){ 
    return;
}

I added that to the beginning of the system_gclk_chan_set_config() function in gclk.c. Now it works great and it no longer tries to modify a write-locked register.

 

Hope this helps someone.