SAMD21 Timing issues

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

Hi - I am working on a SWI (Single Wire Interface) project. I am having timing issues with a ASF and a SAMD21 xplained pro. The single wire interface performs bit banging and it appears my timing is off. In the below code, I should see the signal go high and low every 1us, however it more like 8us.

 

for(int i = 0; i < 100; i++){
	delay_us(1);	
	REG_PORT_OUTSET1 =  0x40000000;
	delay_us(1);
	REG_PORT_OUTCLR1 =  0x40000000;
		
}

 

I am using the default clock settings set by ASF. Any help is appreciated .

 

 

 

Attachment(s): 

This topic has a solution.

"When all else fails, read the directions"

Last Edited: Sun. Aug 11, 2019 - 11:32 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The instructions take some time (including the loop). It will help to run the CPU as fast as possible (but note you could get some unexpected effects from NVM wait states). You will probably have to look at the generated code.

And use the faster IOBUS access discussed here:

https://community.atmel.com/forum/saml21-fast-deterministic-io-port

/Lars

 

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

Lajon wrote:

The instructions take some time (including the loop). It will help to run the CPU as fast as possible (but note you could get some unexpected effects from NVM wait states). You will probably have to look at the generated code.

And use the faster IOBUS access discussed here:

https://community.atmel.com/forum/saml21-fast-deterministic-io-port

/Lars

 

Thanks for the help. I am now running at 48 MHz and accessing the IOBUS directly. This was the trick! Thanks again.

 

What's odd is I am using the CryptoAuthLib library which has the functions for using the SAMD21 SWI via their HAL implementation. They are calling all the wrapper functions e.g. port_pin_set_output_level(PIN_PB11), which is eating up the cycles and causing the delay (no pun intended). I modified the library and it now works. 

 

In file: swi_bitbang_samd21.c

 

void swi_set_signal_pin(uint8_t is_high)
{
    if (is_high)
    {
        port_pin_set_output_level(device_pin, true); // eats up cycles
    }
    else
    {
        port_pin_set_output_level(device_pin, false); // eats up cycles
    }
}

Changed to:

 

void swi_set_signal_pin(uint8_t is_high)
{
    if (is_high)
    {
        PORT_IOBUS->Group[0].OUT.reg = 0x00000080;
    }
    else
    {
        PORT_IOBUS->Group[0].OUT.reg = 0x00000000;
    }
}

 

I had to do it in several areas. Would you consider this a bug in the HAL CryptoAuthLib library?

 

"When all else fails, read the directions"

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

1) Where does delay_us() come from?  I remember not finding cycle-count-based delay functions for SAM, meaning that timers and clocks may need to be set up "correctly" to get the service working properly.

2) Being off by a factor of 8 perhaps implies that the clock isn't running at the rate that the delay code thinks it is.

3) deterministic timing on SAM is ... difficult.

4) The default clock after reset on SAMD21 is ... 1MHz, so it'd have trouble doing 1us delays, and "loop overhead instructions" are going to be "significant"

 

 

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

westfw wrote:
1) Where does delay_us() come from?  I remember not finding cycle-count-based delay functions for SAM, meaning that timers and clocks may need to be set up "correctly" to get the service working properly.
 

 

ASF 3.xxx

 

westfw wrote:

4) The default clock after reset on SAMD21 is ... 1MHz, so it'd have trouble doing 1us delays, and "loop overhead instructions" are going to be "significant"

 

 

See my solution above. I was running at 8MHz, then I bumped it up to 48 MHz. Accessing the IOBUS directly fixed the issue.

"When all else fails, read the directions"