Go Down

Topic: Port manipulation PINx commands with Arduino Due ? (Read 70632 times) previous topic - next topic


Hello, again.
Did any of you know how to start the clock that makes input mode posible in arduino DUE.

I'm doing direct port manipulation, but to be able to read direct from a pin, i'm currently using

pinMode(pin,input), where pin, is a non used pin of the port.

acording to the SAMx documentation, you do need to start this clock for each port. but i couldn't find how to do this, any other way


Why do you not use pinMode(pin, INPUT) for the pins you are actually using? That will set up the port in the correct way.
"The problem is in the code you didn't post."


Hi everyone,
I've been reading lots of forum posts on Due port manipulation and am just looking for some clarification now.  Can somebody confirm that we don't need to worry about overwriting another pin when we set or clear with SODR and CODR?  So there is no need to use bitwise operators to make sure the other pins in the register are preserved?

Also, since these are registers, I would think it's the value in the register that matters.  But, for example, in this code:
Code: [Select]
PIOB->PIO_SODR=1<<27; //lights the LED
PIOB->PIO_CODR=1<<27; //clears it

Now the bit at 1<<27 is set for both SODR and CODR.  So is it the actual setting of the register that sets or clears the pin output, not the value in there itself?  And then if I want to pull the value of an output pin from looking at its register (the way you could, say, by looking at PORTD with other Arduinos), I would look at PDSR?



Apr 13, 2015, 04:15 pm Last Edit: Apr 14, 2015, 03:43 pm by c0rnmuffin
In case anyone is interested, I wrote a quick sketch to test this out.  SODR and CODR seem to always be 0, even after they're "set" to 1 to set or clear a pin.  But the pin value does change as read from PDSR.

Another thing I noticed though is that I can only get pin values from PDSR (for output pins- I didn't try input pins)- from PORTC.  PORTA, PORTB and PORTD always return 0.  I can just use PORTC pins, but if anyone knows what's going on...


The other way of doing direct port manipulation looks like this:
Code: [Select]
long r = PIOx->register;

where x is A,B,C or D and register is as in the data sheet

For example:
Code: [Select]

PIOB->PIO_SODR=1<<27; //lights the LED
PIOB->PIO_CODR=1<<27; //clears it
boolean p12=!!(PIOD->PIO_PDSR & (1<<8)); //read pin 12

I had a go at writing some digitalReadDirect/digitalWriteDirect functions but you might want to give them some more thorough testing as I only checked if it worked with the LED   :)

Code: [Select]

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;

inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);

void setup() {                
  pinMode(13, OUTPUT);    
  pinMode(12, INPUT);    

void loop() {
  digitalWriteDirect(13, HIGH);  
  digitalWriteDirect(13, LOW);    

Hi,im new in this forum, but i'd like to know where do you get this function (g_APinDescription[pin].pPort) from. Because i was looking for in datasheet ATMEL-SAM3X and i haven't found anything. Thanks


//Try this out. It works.

void setup()
  REG_PIOB_OWER = 0xFFFFFFFF;     // Enable PORT B
  REG_PIOB_OER =  0xFFFFFFFF;     // Set PORT B as output port

void loop()
   REG_PIOB_ODSR = 0xFFFFFFFF;   //set all pins of PORT B
   REG_PIOB_ODSR = 0x00000000;  //clear all pins of port B


To "cache" the port info and bitmask for a "fast SPI" function (as was implied in some of the early messages in the thread), you could use code like:

Code: [Select]
  Pio *p = digitalPinToPort(13);
  uint32_t b = digitalPinToBitMask(13);
  while (1) {
    p->PIO_SODR = b;
    p->PIO_CODR = b;

That yields a crappy-looking waveform of about 16MHz on my scope, and produces code like:
Code: [Select]

   80152:       4a04            ldr     r2, [pc, #16]   ;get pin desc array
   80154:       f8d2 316c       ldr.w   r3, [r2, #364]  ; get pio ptr
   80158:       f8d2 2170       ldr.w   r2, [r2, #368]  ; get bitmask
   8015c:       631a            str     r2, [r3, #48]   ; set
   8015e:       635a            str     r2, [r3, #52]   ; clear
   80160:       e7fc            b.n     8015c <setup+0x14> ; loop


This looks like the section I'm looking for, if I wanted to use the PC20 pin which is not in the variant.h or variant.cpp files, how does it get called out in the sketch?  It seems as if the h and .cpp files won't need rewriting if PIOC-PC20 can somehow be declared by using pinMode() or digitalWrite() in the setup and loop.  The examples I've seen of PC20 being utilized by Digistump and Taijiuno both write different versions of the variant.h and variant.cpp files but this should not be required for just one pin correct?


The only way to have a pin available for digitalWrite() and similar arduino functions is to have it defined in the variant files, even if it is "just one pin."   You CAN write to/from it with the direct IO calls being discussed here, regardless of whether it's available to the arduino functions:
Code: [Select]
PIOC->PIO_SODR=1<<20; //Set C20
PIOC->PIO_CODR=1<<20; //clears it

(you'd probably need something similar to do pinMode())


Thank you very much for these function.  So if I want the pin set I probably don't need the line that clears it, is this correct?  I am currently not using pin 33 or PC1, so I changed PC1 to PC20 in the variant.cpp file so now it should have a definition.  Because I don't think I can give it a pin number unless I tack it on the end and call it pin 92.  But replacing it with PC1 hopefully will work easier.  Does it matter where I put these?  Such as before the void setup or in the void loop, everything verifies no matter where it is so it seems they work the same everywhere/

Go Up