Go Down

Topic: Arduino.h and wiring_digital.c problem. (Read 7 times) previous topic - next topic

alvesjc

Nov 04, 2012, 08:39 pm Last Edit: Nov 04, 2012, 08:42 pm by alvesjc Reason: 1
Hi.

While trying to blink the led with this program:

Code: [Select]

#include "Arduino.h"

void setup()
{
 pinMode(13,OUTPUT);
 //REG_PIOB_OWER=g_APinDescription[13].ulPin;
}
void loop()
{
 portOutputRegister(digitalPinToPort(13)) = 0xffffffff & g_APinDescription[13].ulPin;
 delay(1000);
 portOutputRegister(digitalPinToPort(13)) = 0x0 & g_APinDescription[13].ulPin;
 delay(1000);
}


I've found two problems.

The first one, it wouldn't compile unless I would change the sintaxe in Arduino.h in lines 56 and 57.

After replacing this:
Code: [Select]
#define digitalPinToPort(P)        ( g_APinDescription[P]->pPort )
#define digitalPinToBitMask(P)     ( g_APinDescription[P]->ulPin )


with this:
Code: [Select]
#define digitalPinToPort(P)        ( g_APinDescription[P].pPort )
#define digitalPinToBitMask(P)     ( g_APinDescription[P].ulPin )


It compiled without errors.

But even after this, the led wouldn't blink.

I've found that after enabling the OWER register int setup it works.

To avoid setting pinMode and also OWER, I've added this to wiring_digital.c in pinMode function for case OUTPUT:

Code: [Select]

g_APinDescription[ulPin].pPort -> PIO_OWER = g_APinDescription[ulPin].ulPin;


The functions ends up like this:

Code: [Select]
extern void pinMode( uint32_t ulPin, uint32_t ulMode )
{
if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN )
   {
       return ;
   }

switch ( ulMode )
   {
       case INPUT:
           /* Enable peripheral for clocking input */
           pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
           PIO_Configure(
            g_APinDescription[ulPin].pPort,
            PIO_INPUT,
            g_APinDescription[ulPin].ulPin,
            0 ) ;
       break ;

       case INPUT_PULLUP:
           /* Enable peripheral for clocking input */
           pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
           PIO_Configure(
            g_APinDescription[ulPin].pPort,
            PIO_INPUT,
            g_APinDescription[ulPin].ulPin,
            PIO_PULLUP ) ;
       break ;

       case OUTPUT:
           PIO_Configure(
            g_APinDescription[ulPin].pPort,
            PIO_OUTPUT_1,
            g_APinDescription[ulPin].ulPin,
            g_APinDescription[ulPin].ulPinConfiguration ) ;
g_APinDescription[ulPin].pPort -> PIO_OWER = g_APinDescription[ulPin].ulPin;

           /* if all pins are output, disable PIO Controller clocking, reduce power consumption */
           if ( g_APinDescription[ulPin].pPort->PIO_OSR == 0xffffffff )
           {
               pmc_disable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
           }
       break ;

       default:
       break ;
   }
}


Is there any inconvenient to have the pinMode function also setting the OWER register?

cmaglie

alvesjc,

your patch to the macros digitalPinToPort and digitalPinToBitMask are correct, I fixed it upstream:

https://github.com/arduino/Arduino/commit/73649c2f60d0a006061382b0966a06e6d0fda7fe

Also your use of OWER register is correct. I guess we can set it to 0xFFFFFFFF during board initialization in all PIO{A,B,C} without side effects. I'll check this tomorrow, hope to do it in time to include it in 1.5.1.

C
C.

alvesjc


Baltasar

Yes, I also had see that on Arduino.h, but the problem now is on the portOutputRegister and portInputRegister, since I can't use what it returns if this is correct.


I have this definition as a test sketch:

#define sbi(reg, bitmask) reg = 0xffffffff & bitmask

and the folowing vars:

volatile RwReg P_LED;
uint32_t B_LED;
P_LED = portOutputRegister(digitalPinToPort(13));
B_LED = digitalPinToBitMask(13);

using this test sketch to light the led on the pin 13 is not working:


  sbi(P_LED,B_LED);
  delay(1000);
  cbi(P_LED,B_LED);
  delay(1000);

Only if I go directly like this it works:

  portOutputRegister(digitalPinToPort(13)) = 0xffffffff & digitalPinToBitMask(13);
  delay(1000);
  portOutputRegister(digitalPinToPort(13)) = 0x0 & digitalPinToBitMask(13);
  delay(1000);
 
 
  Looks like thar reg on sbi or cbi is not passed correct, any help, coments on this?
 
  What sort of var should I declared so it works?
Check all my projects based on Atmel/Arduino -> www.aqualed-light.com

cmaglie

Baltasar,

what are you missing is to enable Synchronous Data Output (look at page 646 of SAM3X datasheet for more info on that).
The following snippet of code should solve your issue (warning: totally untested :))

Code: [Select]

REG_PIOA_OWER = 0xFFFFFFFF;
REG_PIOB_OWER = 0xFFFFFFFF;
REG_PIOC_OWER = 0xFFFFFFFF;


I'm thinking about adding this as a default initialization in Arduino Core.
C.

Go Up