Arduino Zero - accessing registers on the Atmel SAMD21

Looking at the spec sheet for Atmel's SAMD21 it describes a register named CTRLA, of which I want to play around with reading and setting Bit[25:24]. The Arduino IDE doesn't recognize this register name, and many others I tested.

Is there a library I should be including, or somewhere I can read the correct names of the registers recognized by the Arduino IDE?

Disclaimer: I'm new to Arduino, and a bit rusty with embedded projects.

A big thank you to Mr. Rowberg for laying the ground work for communicating with the MPU6050! I write this to help others, and hopefully find a solution to my (apparently) randomly occurring problem.

I'm doing this on an old 2007 Macbook Pro USB->Arduino debug port, with the GY-521 break out board wired as follows to the Arduino Zero:
INT -> D0
ADO->GND
VCC->3v3
GND->GND
SDA->SDA
SCL->SCL
Both SDA and SCL have a 4k7 pull up to 3v3.

Copied the following folders from jrowberg-i2cdevlib-aab2381 into my Ardunio->libraries folder:
I2Cdev
MPU6050

Opened MPU6050_DMP6 in the Arduino IDE 1.6.5.
Compile had an error for 'TWBR' as it isn't called TWBR for this Arduino board (I assume). TWBR is for ATMega chips?
Commented out the TWBR line.
Compile had errors 'min' not declared in I2Cdev.cpp.
Wrote a definition for min in I2Cdev.cpp.
Compile completed, and uploaded.
Opened Serial Monitor, set baud to 115200, and was getting data breifly before it froze.
Found that min (max and others) bug was fixed in the current SAMD hourly build.
Installed the hourly build for the SAMD https://github.com/a...d#hourly-builds and removed the defininition I wrote for min in I2Cdev.cpp.
Complied and get data out for a bit, but then it stops putting out data to the serial monitor and the arduino freezes with the debug LED lit.

Freeze Notes:

  • The debug LED is lit, as if it's stuck in a Serial.println(). ??
  • Nothing is tied to pin 13, and the LED attached to this pin is lit during the running state and frozen state.
  • Sometimes it will run for minutes before freezing, other times seconds. Seldom it will run for a long time >30mins.
  • Sometimes while it runs in the background and I have another application open on the computer, the debug light stops blinking and stays lit (frozen) until I tab back over to the Arduino sketch, when it starts blinking again (and sending serial data) with no intervention.
  • Haven't yet found anything I'm doing that will repeatedly cause it to freeze, other than pulling and reconnecting the wire connecting INT->D0 while it is outputing data.
  • Longest runs happen when following these steps:
    -- Unplug the USB cable for at least 10 minutes (to let the board caps discharge??)
    -- Restart the Arduino sketch
    -- Start the Arduino sketch
    -- Connect the USB cable
    -- Run sketch

Does it have to do with the fact that the TWBR line was commented out?
Does it have to do with the debug port serial communication?
Is it a bug with the Arduino Zero?
Could it be my Macbook?
It is mild weather temps, is it solar flares? (:
What am I not understanding here?

Would like to better understand TWBR as it pertains to the Arduino Zero. Looking at page 536-537 of the spec sheet for the SAMD21 it is Bit[25:24] of CTRLA that changes the bit rate of the I2C port. Haven't figured out how to do this yet, and not sure if this is even the right track toward quelling this freeze issue. Will read more and post a solution when it becomes known.

T

Update:
I notice the LED tied to pin 13 looks partially lit. When tying pin 13 to ground it goes off, when tying it to 3v3 it becomes brighter. Checking it with a DMM it shows 1.7V

I have to repeatedly restart the program before getting a long run.

The register definitions for the SAMD21 are contained in two Atmel directories. On my windows machine they're located (buried) at:

C:\Username\Computer\AppData\Roaming\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\instance\

and

C:\Username\Computer\AppData\Roaming\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\component\

The "instance" directory holds the definitions specific for each instance of a particular peripheral, e.g. the timer TCC0 definitions are stored in "tcc0.h", TCC1 in "tcc1.h", etc.. The "component" directory holds the generic definitions for each common peripheral group, in this case TCC definitions are stored in "tcc.h", TC in "tc.h", etc...

The registers can be accessed in a number of different ways, for example to print TCC0's CTRLA register, you can either call on the register directly:

Serial.println(REG_TCC0_CTRLA, HEX);

or use a pointer:

Serial.println(TCC0->CTRLA.reg, HEX);

It's also possible to access the registers using a pointer to the bit fields:

Serial.println(TCC0->CTRLA.bit.ENABLE, HEX);

MartinL:
The register definitions for the SAMD21 are contained in two Atmel directories. On my windows machine they're located (buried) at:

C:\Username\Computer\AppData\Roaming\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\instance\

and

C:\Username\Computer\AppData\Roaming\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\component\

Are these source files in an Arduino github repo somewhere? I couldn't find them in the ArduinoCore-samd repo.

Are these source files in an Arduino github repo somewhere? I couldn't find them in the ArduinoCore-samd repo.

I presume that the Arduino IDE 1.6.5 Boards Manager installs these files when you download the installation for the Arduino Zero, currently at version 1.6.1.

These are Atmel files so they may not be part of the Arduino core itself, but they're certainly used by the Arduino core. If you look in, say for example the core file "startup.c", located at:

C:\Username\Computer\AppData\Roaming\Arduino15\packages\arduino\hardware\samd\1.6.1\cores\arduino\startup.c

...you'll see the definitions being used.

Yes, these files appear if installed. But where is the source for the install package?

It seems that Arduino.cc is no longer an Open Source company... whereas arduino.org have all the source online and available.

Rubbish. The v1.6.5 IDE installs "software packs" for "extra" Arduinos at "C:\Users\David Prentice\AppData\Roaming\Arduino15\packages\arduino"

You will find all the necessary components for the "Zero". e.g. ARM compiler and CMSIS headers in /tools and core, libraries, variants etc under /hardware e.g.
"C:\Users\David Prentice\AppData\Roaming\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include"

I am sure that this is all documented somewhere. Of course the /Users/username/Appdata directory is hidden from general search. This makes it difficult to find. However, you can open up an Explorer window by clicking on File->Preferences->preferences.txt from the IDE.

Just like with the regular AVR sketches, you can access all the system "special function registers" via the Atmel names. i.e. the Arduino build system has automatically included the system headers.

Yes, I agree that the arduino.org directory tree puts everything into "/Program Files" rather than the "pack" arrangement.

I am also sure that you can obtain the source code to the GCC ARM compiler if you really want to. I am happy to use it "as-is".

Before I get flamed. It is unlikely that your user name is "David Prentice". Substitute your own "username"

David.

bobcousins:
Yes, these files appear if installed. But where is the source for the install package?

It seems that Arduino.cc is no longer an Open Source company... whereas arduino.org have all the source online and available.

As David says you find the files under AppData... whats not that bad IMHO its there if you use different versiond of the main IDE you don't need to install it seperate for all so you waste less space on the HD and no need to edit some parts for all versions.

And you can find the files for the Zero there on Github

Sorry, but it is you guys who are talking rubbish.

The SAM core files are not on github. The Zero files on github are clearly not the ones used to create the Zero package.

How do I raise issues in the SAM core ?
How do I fork the SAM core?
How do I modify the SAM core?
How do I submit change requests?

An Open Source project must be OPEN.

As far as I can see, Arduino are keeping things secret and not openly publishing ALL the source. This is a basic requirement for Open Source projects. The hardware files for Zero are not published either. Every other Open Source project allows you to download the source, why not Arduino?

An installed package is NOT the same thing.

I guess they are doing this because they don't want arduino.org to get anything. However, arduino.org have openly published all their source, hardware and software.

I am not inclined to participate further in Arduino.cc development.

bobcousins:
I am not inclined to participate further in Arduino.cc development.

bye bye.

noticed the same for the Due.. the samlib seems to be a binary lib, no sources. for me, this really doesn't help with debugging. is the ASF sam source code available from atmel somewhere or is it only possible to get it via an install of AtmelStudio?

How to find the source files on a Mac (Yosimite).

I found the source files on a Mac for the IDE from Arduino.org 1.7.6.

  1. Open Finder and select Applications under menu "Go".
  2. Right click on the Arduino app.
  3. Cilck on "Show package contents".
  4. The files are at /Java/hardware/arduino/smad/cores/arduino

The sam(i.e. Due) and avr core files can also be found there.

I hope somebody finds this useful - I did!

Harry J. Whitlow

@bobcousins

I believe the files in question are developed by Atmel to make the SAMD series processors compatible with the ARM CMSIS (Cortex Microcontroller Software Interface Standard).

I believe CMSIS 4.0.0 is installed when the Zero board is installed.

The source code can be found in the AppData folder.
Unfortunately, I cannot find a publicly accessible repository.

I think I found it!

GabrielNotman was right! After an hour or so of searching I found the definition files for the SAM21d.
These have files for each peripheral e.g. adc.h, ac.h etc. these seem to be a missing-link (no pun intended) needed to get at the full power of the Zero/M0 PRO by register twiddling.

On my (Yosimite) Mac they are located in:
/Applications/Arduino.app/Contents/Java/hardware/tools/CMSIS/Device/ATMEL/samd21/include
There are three sub-directories; component instance and pio. The first has most of the register details.

Harry J. Whitlow

yeah, the discussions of the registers and the CMSIS and their file locations we got here already:
--> Faster Pin I/O on Zero? - #19 by Dirk67 - Arduino Zero - Arduino Forum

"..After an hour or so of searching.."
I just use the notepad++ editor with the "search in files" (whole (sub)directories) function,
and you can find all expressions, defines and registers in seconds ...

It seems the register access is not so straightforward. On a M0 Pro I was able to read and write the GCLK registers but not the analogue comparator (AC) registers. (See code attached.)

I am using a mac (not in the same place on a Windows machine) and as noted above I traced manually to the definition files to get the definitions of the registers. The name definitions were taken from ac.h and gclk.h

Maybe I just made a mistake - but as the register writing/reading worked for the GCLK case - but not the AC case I don't think so. Does anybody have any good ideas or workaround?

Harry J. Whitlow

//##############################################################
//  Preamble definitions 
//
//##############################################################
#include "Arduino.h"
#include "wiring_private.h"
#include "variant.h"
#include "wiring_digital.h"
#include "wiring.h"

// Synch AC
static __inline__ void ACsync() __attribute__((always_inline, unused));
static void   ACsync() {
  while (AC->STATUSB.bit.SYNCBUSY == 1); 
}
// Synch GCLK
static __inline__ void syncADC() __attribute__((always_inline, unused));
static void syncGCLK() {
  while (GCLK->STATUS.bit.SYNCBUSY == 1); 
}


void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
 // Set up the AC clocks
  syncGCLK();
  GCLK->CLKCTRL.reg = 0x4120; //enable GGCLK for AC_ana, CLKGEN1 = 32 kHz Xtal
  syncGCLK();  
  REG_GCLK_CLKCTRL = 0x401F; //enable GGCLK for AC_dig, CLKGEN0 = 48 MHz PLL
  syncGCLK();
}

void loop() {
  // put your main code here, to run repeatedly: 
 // This prints out register contents
Serial.println("...................");

//This worked OK
uint32_t apbcMask=0;
apbcMask = PM->APBCMASK.reg;
Serial.print("APBCMASK: ");
Serial.println(apbcMask, HEX);

// This works too
uint32_t ctrla = 0;
ctrla = REG_GCLK_CLKCTRL;
Serial.print("GCLKCTRL: ");
Serial.println(ctrla, HEX);


// The following does not work
REG_AC_CTRLA = 0x02;
ACsync();
ctrla = REG_AC_CTRLA;
Serial.print("AC_CTRLA: ");
Serial.println(ctrla, HEX);

//This did not work either
ACsync();
REG_AC_CTRLA = 0x00;
REG_AC_COMPCTRL0 = 0x001524; 
ACsync();
uint32_t compcntrl0 = REG_AC_COMPCTRL0;
ACsync();
Serial.print("COMPCTRL0: ");
Serial.println(compcntrl0,HEX);

delay(500);   // Wait 500 ms
}

Here are the registers you need:

REG_AC_CTRLA = AC->CTRLA.reg
REG_AC_COMPCTRL0 = AC->COMPCTRL[0].reg

Most of the registers seem to follow that naming pattern.

I'm curious if anyone has found a good documentation source for
direct register access to the SAMD21.

Both REG_AC_CTRLA and AC->CTRLA.reg are correct.

There are actually two ac.h files.

The first is stored in the "instance" directory. This defines the analog comparator's register definitions. It contains the REG_AC_CTRLA definition.

The second is stored in the "component" directory and contains bit mask definitions for each AC register, as well the structures/unions that allow the AC->CTRLA.reg (pointer to the register) to be used. It's also possible to access the structures' individual bit fields, for example AC->CTRLA.bit.ENABLE. The pointer definitions themselves are stored in the "samd21g18a.h" file.

So for example you could write:

REG_AC_CTRLA |= AC_CTRLA_ENABLE;
while (AC->STATUSB.bit.SYNCBUSY);

or

AC->CTRLA.reg |= AC_CTRLA_ENABLE;
while (REG_AC_STATUSB & AC_STATUSB_SYNCBUSY);

Both set the enable bit in the AC's CTRLA register.

As to why the AC registers are not working? The problem could be further up stream. I guess from your code that you've checked that the AC bit in the power management APBC mask register has been set. There's also the PAC2 write protection register that also has an AC bit field.

Thanks Gabriel Notman and MartinL,

I just tried by adding clearing of the peripheral write-protect bit for the Analogue Comparator by including:

PAC2->WPCLR.reg |= 0x20000;

in void setup. It still does not work to write to the AC registers. I tried reassigning the register names - but this did not work. i have been stuck on this point for a while. Has anybody got any ideas?

Harry J. Whitlow