Go Down

Topic: Arduino Due - Access to registers for timers, interrupts. etc... (Read 744 times) previous topic - next topic

alirazaviarduino

Hello

I am new to Arduino. I have a well understanding of AVR MCUs, working with its timers and interrupts.

I have a Arduino Due board, which is based on Atmel AT91SAM3X8E MCU.
Based on hardware page of the Due, the MCU runs at 84MHz clock frequency.
I want to generate a PWM pulse with the frequency of - for example - 21MHz (1/4 of the MCU clock).

In my opinion and experience with AVR, this this requires access to Timer/Counter registers in the C code.
Also I want to know what exactly happens in the ISR (interrupt service routine).
I search and download some Timer libraries for Due, but they do not support frequencies higher than 1MHz.

The examples of Arduino IDE is also frequency limited, and provide no access to registers...

Can anyone help me to solve my problem?

Thanks a lot.

ard_newbie

Graynomad pinout diagram plus Sam3x datasheet are a good starting point to learn how to access timers, interrupts,etc...

Search in the DUE sub forum for example sketches and/or relevent libraries, e.g.:

https://forum.arduino.cc/index.php?topic=537586.0

ik2ihz

Good morning everybody, I have a subtle problem with this registry access and maybe I can join this topic.
I have written te attached program to test register access to Timers
#include <DueTimer.h>
#include "instance_tc0.h"
#include "TC0def.h"

#define PMC_SCSR 0x400E0608U
#define PMC_PCSR0 0x400E0618U
#define PMC_PCER0 0x400E0610U
#define UL unsigned long
UL pippo = 0, RA_Count, RC_Count, Clock_freq, pulse_duration;

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
Clock_freq = 84000000;
RA_Count = 2;    //giusto per avere margine da 0
//Set Waveform Mode
// F / 128, Wavemode,Salita,stoopa si RC, alza su RA e termina su RC
REG_TC0_CMR0 = TIMER_CLOCK4|WAVE|WAVSEL_UP|CPCSTOP|ACPA_SET|ACPC_CLEAR; 
REG_TC0_RA0 = RA_Count;   //set pulse start delay

//set pulse data
pulse_duration = 200;//msec
RC_Count = (UL) 200/1000*Clock_freq/128;

REG_TC0_RC0 = RC_Count;   //set count val
//start
REG_TC0_CCR0 =  SWTRG;
pippo = PMC_PCSR0;
Serial.print("Status reg = ");Serial.println(pippo,BIN);
pippo = PMC_PCSR0|(1<<27);
PMC_PCER0 = pippo;  <--------------------------------------FAILING POINT

Serial.print("Status reg = ");Serial.println(pippo,BIN);
pippo = PMC_PCSR0;
Serial.print("Status reg = ");Serial.println(pippo,BIN);
delay(1000);
}
void loop(){
delay(10);
pippo = REG_TC0_SR0;
Serial.println(pippo,BIN);
}

I also have a file with definitions of registers (part is below)
#define REG_TC0_RA0   (*(RwReg*)0x40080014U) /**< \brief (TC0) Register A (channel = 0) */
#define REG_TC0_RB0   (*(RwReg*)0x40080018U) /**< \brief (TC0) Register B (channel = 0) */
#define REG_TC0_RC0   (*(RwReg*)0x4008001CU) /**< \brief (TC0) Register C (channel = 0) */
#define REG_TC0_SR0   (*(RoReg*)0x40080020U) /**< \brief (TC0) Status Register (channel = 0) */
#define REG_TC0_IER0  (*(WoReg*)0x40080024U) /**< \brief (TC0) Interrupt Enable Register (channel = 0) */
#define REG_TC0_IDR0  (*(WoReg*)0x40080028U) /**< \brief (TC0) Interrupt Disable Register (channel = 0) */
#define REG_TC0_IMR0  (*(RoReg*)0x4008002CU) /**< \brief (TC0) Interrupt Mask Register (channel = 0) */


I've added similar definitions to the top of my program
All the reads work ok

at compilation time I get this error


sketch_jul16a.ino: In function 'void setup()':
sketch_jul16a.ino:31:11: error: lvalue required as left operand of assignment
lvalue required as left operand of assignment


Write instruction to registers worked well with Counter Registers
why it fails with PMC_PCER0 that is a Write register as well??

Many thanks for any support.
Esperanto

 

antodom

Hi there @alirazaviarduino,


If what you want is just to generate a PWM signal with the DUE, you have library pwm_lib (https://github.com/antodom/pwm_lib), a library that was designed and developed specifically for that using the DUE. Have a look to the examples coming with the library and its document to start with.

As to timers you have another library, tc_lib (https://github.com/antodom/tc_lib), available for the DUE. Here the same, have a look to the library's documentation and examples.

I hope it helps.
------------
antodom

alirazaviarduino

#4
Jul 20, 2019, 10:15 am Last Edit: Jul 20, 2019, 10:19 am by alirazaviarduino
Graynomad pinout diagram plus Sam3x datasheet are a good starting point to learn how to access timers, interrupts,etc...

Search in the DUE sub forum for example sketches and/or relevent libraries, e.g.:

https://forum.arduino.cc/index.php?topic=537586.0
Thanks a lot ard_newbie.

In the topic that you mentioned, I found an example that solved my problem.

Also, the example provided by ik2ihz guided me to find the register names.

In summary, the registers listed in the AT91SAM3X8E  datasheet is available in the Arduino IDE by the same datasheet name, only the REG_ should be added to it.

For example, the register TC_CMR0 for the timer/counter2 can be accessed in the IDE by the name REG_TC2_CMR0.

ard_newbie

For example, the register TC_CMR0 for the timer/counter2 can be accessed in the IDE by the name REG_TC2_CMR0.
It's better to write it this way:

TC2->TC_CHANNEL[0].TC_CMR = ......  // Timer Counter 2 channel 0


You can find all header files here:

https://android.googlesource.com/platform/external/arduino-ide/+/f876b2abdebd02acfa4ba21e607327be4f9668d4/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/component

alirazaviarduino

Hi there @alirazaviarduino,


If what you want is just to generate a PWM signal with the DUE, you have library pwm_lib (https://github.com/antodom/pwm_lib), a library that was designed and developed specifically for that using the DUE. Have a look to the examples coming with the library and its document to start with.

As to timers you have another library, tc_lib (https://github.com/antodom/tc_lib), available for the DUE. Here the same, have a look to the library's documentation and examples.

I hope it helps.
Thanks antodom.

Go Up