Register names for direct register manipulation

Hello all,

I'm trying to find a key that maps all the different registers on the Due for direct manipulation. I've been able to piece together that let say you want to output to a specific pin by directly writing to a register, you would do something like this:

REG_PIOB_ODSR = 1 << 27;

This will set pin B27 (Due pin which will light up the yellow LED) to high. My question is, where is this mapping defined? There are minor tweaks I'd like to make to some registers in the MCU that using the base Arduino language won't allow me to do.

I'm going to want to do this at some point because I want to be able to change the frequency of one of my PWM signals. To do that, I need to be able to access the PWM peripheral registers. What are the mappings for those?

Thanks,

I figured it out!

You need to download the Atmel Software Framework (stand alone):

Then you can navigate to:
asf-standalone-archive-3.7.3.69\asf-3.7.3\sam\utils\cmsis\sam3x\include\instance

You can see a bunch of .h files which list out the names for all the registers.

Dear AndiJay,

It seems that I have exactly the same needs. I would be pleased to join our efforts together to reach our goals.

My aim is to use the PWM macrocell described in section 39 of the AT91SAM3X datasheet, to control a power switch.
For this I would like to use one channel (let's say PWM0), rated at 8 kHz, with a resolution of at least 10 bits.
As far as I understand, the instructions for this are given in section 39.6.5.1.
Here is a very first version of my code :

// Using the PWM macrocell on the arduino due
// F. Auger, may 2013

// power management controller : see section 29 of the AT91SAM3X datasheet
#include <F:\ActivitesRecherche\ShiZhihaoPerle2\NdeyeCamara\ArduinoDueProgs\PwmMacroCellV1\instance_pmc.h>

// PWN macrocell : see section 39 of the AT91SAM3X datasheet
#include <F:\ActivitesRecherche\ShiZhihaoPerle2\NdeyeCamara\ArduinoDueProgs\PwmMacroCellV1\instance_pwm.h>

void setup() {
// PWM initialization (see 39.6.5.1)


// set the PWM macrocell on (see 39.5.2)
// configure the master clock (MCK)
REG_PMC_MCKR

// enable PWM channel (see 39.7.2)
REG_PWM_ENA 

// configure the PWM clock generator (see 39.6.1 and 39.7.1)
REG_PWM_CLK

// configure the PWM channel mode register (see 39.6.2.2 and 39.7.37)
REG_PWM_CMR0

}

void loop() {
  // put your main code here, to run repeatedly: 
  
}

Can we share our understanding of the datasheet to make this work ?
Thank you very much in advance, best regards,

By the way, why is the PWM frequency at 1 kHz on the PWM5 and PWM6 pins, instead of 490 Hz on the other PWM pins ?

Hi fog44,

I don't mind sharing what I've found, the only thing is, I still haven't reviewed the PWM information in the datasheet. In fact, I still do not have my Arduino Due board. Currently, I'm just doing research on how to do some of the things I think I will need to do once I finally get my hardware. I will certainly post back here when I learn more about the PWM peripheral in this part, but that will not be for a while, as there are other things I'm trying to figure out too.

Hi fog44,

(i am a beginner on DUE too, so i share what i came up with so far)
your sketch look right, you just have to fill the parts with life (->register manipulation);
this requires a lot of datasheet studies to get things working:
Registers can be accesed in different ways. I found the best way for me is to use the predefined structures, which you access like this:
PER -> PER_REGNAME = val;

  • PER: peripheral name, i.e. PWM, TC0, PMC, PIOA, ADC, DACC...
  • PER_REGNAME: Register, see Datasheet i.e. PWM_ENA -> PWM Enable Register (bits 0-7 -> PWM 0-7)
    Example: PMW -> PWM_ENA = 0x00000040; // enable PWM 6
    The example sketch shows all ways i found to manipulate registers, maybe this helps you getting started.
    The sketch starts a peripheral (ADC) in PMC and shows the change of the status register bit.
#define ULP  unsigned long*   // minimize code
#define UL   unsigned long
#define  ADC_ID     37    //  peripheral ADC
#define  PWM_ID    36    //  PWM

void setup() { Serial.begin(9600); }

void loop() {
ULP pmcreg;
ULP pmcsreg;
UL value, stat;
  pmcreg = (ULP)0x400E0700; //Address = PMC enable register PCER1
  pmcsreg =(ULP)0x400E0708; //Address = PMC status register PCSR1
  value = 0x00000020;           //  bit 5(+32) = ADC
  
  // way 1: use predefined routines (internet or ...)
  Peripheral_On(ADC_ID);       // Turns peripheral (here ADC) ON
  // way 2A: use ATMEL defined registers
  REG_PMC_PCER1 = value;    // does the same, just more basic!
  // way 2B: use ATMEL defined data structures for registers
  PMC->PMC_PCER1 = value;   // does the same, just more systematic!
  // way 3: take Adresses vom data sheet
  *pmcreg = value;                // dito, as basic as it gets!
  
  stat = *pmcsreg;                 // read status
  Serial.print("Statusreg = 0x");  Serial.print(stat); Show_BITS(stat);
  PMC->PMC_PCDR1 = value;   // turns ADC OFF!
  stat = PMC->PMC_PCSR1;     // read status again
  Serial.print("Statusreg = 0x");  Serial.print(stat); Show_BITS(stat);
  while(1==1) ;                     // done!
}

void Peripheral_On(int ID)  
{  //******** activate peripheral ********
   // ID of peripheral (see ATMEL91sam.pdf section 11.1,page 47)
UL  val, regbit;
ULP Reg;   // (Manipulation) Register
ULP SReg;  // corresponding Statusregister
  if(ID<32)
    { Reg = (ULP) &PMC->PMC_PCER0;  SReg = (ULP) &PMC->PMC_PCSR0;  regbit = ID; }
  else 
    { Reg = (ULP) &PMC->PMC_PCER1;  SReg = (ULP) &PMC->PMC_PCSR1;  regbit = ID-32; }
  *Reg = 1<<regbit;  // enable peripheral
  while( (val = (*SReg) & (1<<regbit))==0) ;  // wait until on!
} 

void Show_BITS (UL reg)
{
  unsigned long w,a;
  int i,k,s;
  Serial.print(" = b");
  for(i=3; i>=0; i--) {
    if(i<3) Serial.print(".");
    a = 255;  s = i*8;  a = a << s;  w = reg & a;   w = w >> s;
    for(k=128; k>0; k=k/2) if(w&k) Serial.print("1");  else Serial.print("o");
    }
  Serial.println();
}

Hi MSClaude,

Do you know where all the predefined structures are actually defined?

Hi AndiJay,

well, thats actually an secret, but after some searches you can find 'em for example in the subdir
arduino-1.5.2\hardware\arduino\sam\system\CMSIS\Device\ATMEL\sam3xa\include\instance

  • there you can find all the predefined registers for each peripheral like
    instance_pmc.h

But as far as i am concerned, i don't need to find em, 'cause all i need is the ATMEL datasheet.
All those registers or structures are named like the datasheet register names.
(Well one thing i had to search for, was the substructure for the timer counter sub-channels
which are accessed via TCn->TC_CHANNEL[ch].TC_REGNAME (Timer Counter n, sub channel ch).)
This way i got TC0-2, DACC, ADC, PWM, PMC and PIOA-D running (thats all i need so far).

Another thing i had to search for are the peripheral interrupts, which i now got running (for DMA),
but this is another story...

My way: learning by doing, because the documentation of the software is bad.
On the other side, the hardware is well described in the datasheet.

Would the unique identifier of the processor be accessible this way?
http://www.atmel.com/Images/doc11057.pdf (p39)

hi
How do I make a quick on-off digital port?

digitalwrite(1,HIGT);
digitalwrite(1,LOW);
140 kHz

I need 5 MHz

thank you