From 9491c1f30814fff57e66b2e6c150a9eb165a6617 Mon Sep 17 00:00:00 2001 From: Tayler Mulligan Date: Wed, 10 Jun 2015 21:49:19 -0700 Subject: [PATCH 1/5] Defaults output pins to LOW on Due When a pin is designated as an output on the Arduino Due, the pin is set to a HIGH logic level. Changing the default pin state to LOW makes the behaviour correspond with AVR. --- hardware/arduino/sam/cores/arduino/wiring_digital.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/arduino/sam/cores/arduino/wiring_digital.c b/hardware/arduino/sam/cores/arduino/wiring_digital.c index 7c958de8a..56039d03e 100644 --- a/hardware/arduino/sam/cores/arduino/wiring_digital.c +++ b/hardware/arduino/sam/cores/arduino/wiring_digital.c @@ -54,7 +54,7 @@ extern void pinMode( uint32_t ulPin, uint32_t ulMode ) case OUTPUT: PIO_Configure( g_APinDescription[ulPin].pPort, - PIO_OUTPUT_1, + PIO_OUTPUT_0, g_APinDescription[ulPin].ulPin, g_APinDescription[ulPin].ulPinConfiguration ) ; From 8589c792cbc334676f6c8190d4c83f35c9f8fc92 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 23 Mar 2015 10:33:56 +0100 Subject: [PATCH 2/5] Due: modify ADC enable/disable sequence to avoid the bug #2198 simply reconfigure the pin -> no additional overhead if pinMode configuration is performed at the beginning of the sketch, 4 to 25% overhead on all analogRead() due to the additional check --- hardware/arduino/sam/cores/arduino/wiring_analog.c | 4 ++-- hardware/arduino/sam/cores/arduino/wiring_digital.c | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/hardware/arduino/sam/cores/arduino/wiring_analog.c b/hardware/arduino/sam/cores/arduino/wiring_analog.c index 1385f01eb..e358d4666 100644 --- a/hardware/arduino/sam/cores/arduino/wiring_analog.c +++ b/hardware/arduino/sam/cores/arduino/wiring_analog.c @@ -148,9 +148,9 @@ uint32_t analogRead(uint32_t ulPin) case ADC11 : // Enable the corresponding channel - if (ulChannel != latestSelectedChannel) { + if (adc_get_channel_status(ADC, ulChannel) != 1) { adc_enable_channel( ADC, ulChannel ); - if ( latestSelectedChannel != (uint32_t)-1 ) + if ( latestSelectedChannel != (uint32_t)-1 && ulChannel != latestSelectedChannel) adc_disable_channel( ADC, latestSelectedChannel ); latestSelectedChannel = ulChannel; } diff --git a/hardware/arduino/sam/cores/arduino/wiring_digital.c b/hardware/arduino/sam/cores/arduino/wiring_digital.c index 56039d03e..973368f92 100644 --- a/hardware/arduino/sam/cores/arduino/wiring_digital.c +++ b/hardware/arduino/sam/cores/arduino/wiring_digital.c @@ -29,6 +29,13 @@ extern void pinMode( uint32_t ulPin, uint32_t ulMode ) return ; } +#if defined __SAM3X8E__ || defined __SAM3X8H__ + if(g_APinDescription[ulPin].ulPinType != NO_ADC && adc_get_channel_status(ADC, g_APinDescription[ulPin].ulADCChannelNumber)) + { + adc_disable_channel( ADC, g_APinDescription[ulPin].ulADCChannelNumber); + } +#endif + switch ( ulMode ) { case INPUT: From 33255ef46d862c01811603cfc8b95084d946f303 Mon Sep 17 00:00:00 2001 From: Marc-Andre Ferland Date: Sat, 25 Jan 2014 01:06:09 -0500 Subject: [PATCH 3/5] Fix adc_configure_trigger enabling and disabling FreeRun Fix changing trigger type --- .../arduino/sam/system/libsam/source/adc.c | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/hardware/arduino/sam/system/libsam/source/adc.c b/hardware/arduino/sam/system/libsam/source/adc.c index 18a1b4c38..20814a0b1 100644 --- a/hardware/arduino/sam/system/libsam/source/adc.c +++ b/hardware/arduino/sam/system/libsam/source/adc.c @@ -192,18 +192,39 @@ void adc_set_resolution(Adc *p_adc,const enum adc_resolution_t resolution) void adc_configure_trigger(Adc *p_adc, const enum adc_trigger_t trigger, uint8_t uc_freerun) { - p_adc->ADC_MR |= trigger | ((uc_freerun << 7) & ADC_MR_FREERUN); + //Warning ADC_MR_TRGSEL_Msk does not include ADC_MR_TRGEN. + p_adc->ADC_MR &= ~(ADC_MR_TRGEN | ADC_MR_TRGSEL_Msk | ADC_MR_FREERUN); //Clear all bits related to triggers and freerun + + //Configure FreeRun + if(uc_freerun & ADC_MR_FREERUN == ADC_MR_FREERUN_ON) { //FreeRun is enabled + p_adc->ADC_MR |= ADC_MR_FREERUN_ON; + + //Free Run Mode: Never wait for any trigger + //No need to continue and enable hardware triggers + return; + } + + //Configure hardware triggers + if(trigger & ADC_MR_TRGEN == ADC_MR_TRGEN_EN) { //Hardware trigger is enabled + p_adc->ADC_MR |= (trigger & ADC_MR_TRGSEL_Msk) | ADC_MR_TRGEN_EN; //Set trigger selection bits and enable hardware trigger + } } #elif SAM3U_SERIES /** - * \brief Configure conversion trigger and free run mode. + * \brief Configure conversion trigger. * * \param p_adc Pointer to an ADC instance. * \param trigger Conversion trigger. */ void adc_configure_trigger(Adc *p_adc, const enum adc_trigger_t trigger) { - p_adc->ADC_MR |= trigger; + //Warning ADC_MR_TRGSEL_Msk does not include ADC_MR_TRGEN. + p_adc->ADC_MR &= ~(ADC_MR_TRGEN | ADC_MR_TRGSEL_Msk); //Clear all bits related to triggers + + //Configure hardware triggers + if(trigger & ADC_MR_TRGEN == ADC_MR_TRGEN_EN) { //Hardware trigger is enabled + p_adc->ADC_MR |= (trigger & ADC_MR_TRGSEL_Msk) | ADC_MR_TRGEN_EN; //Set trigger selection bits and enable hardware trigger + } } #endif From d1c65ca8fe4fc0a81f6760cc9abcaf140113e214 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 14 Jul 2015 17:29:36 +0200 Subject: [PATCH 4/5] keep track of pin status using g_pinStatus array and act accordingly This commit adds 80 bytes to RAM usage and some overhead in normal operations. --- hardware/arduino/sam/cores/arduino/Arduino.h | 12 +++++++ .../arduino/sam/cores/arduino/wiring_analog.c | 13 +++----- .../sam/cores/arduino/wiring_digital.c | 33 ++++++++++++++++--- .../sam/variants/arduino_due_x/variant.cpp | 3 ++ 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/hardware/arduino/sam/cores/arduino/Arduino.h b/hardware/arduino/sam/cores/arduino/Arduino.h index f074d5b27..4fae76a2a 100644 --- a/hardware/arduino/sam/cores/arduino/Arduino.h +++ b/hardware/arduino/sam/cores/arduino/Arduino.h @@ -155,6 +155,16 @@ typedef enum _ETCChannel #define PIN_ATTR_PWM (1UL<<3) #define PIN_ATTR_TIMER (1UL<<4) +#define PIN_STATUS_DIGITAL_INPUT_PULLUP (0x01) +#define PIN_STATUS_DIGITAL_INPUT (0x02) +#define PIN_STATUS_DIGITAL_OUTPUT (0x03) +#define PIN_STATUS_ANALOG (0x04) +#define PIN_STATUS_PWM (0x05) +#define PIN_STATUS_TIMER (0x06) +#define PIN_STATUS_SERIAL (0x07) +#define PIN_STATUS_DW_LOW (0x10) +#define PIN_STATUS_DW_HIGH (0x11) + /* Types used for the tables below */ typedef struct _PinDescription { @@ -170,6 +180,8 @@ typedef struct _PinDescription ETCChannel ulTCChannel ; } PinDescription ; +extern uint8_t g_pinStatus[]; + /* Pins table to be instanciated into variant.cpp */ extern const PinDescription g_APinDescription[] ; diff --git a/hardware/arduino/sam/cores/arduino/wiring_analog.c b/hardware/arduino/sam/cores/arduino/wiring_analog.c index e358d4666..05029782c 100644 --- a/hardware/arduino/sam/cores/arduino/wiring_analog.c +++ b/hardware/arduino/sam/cores/arduino/wiring_analog.c @@ -153,6 +153,7 @@ uint32_t analogRead(uint32_t ulPin) if ( latestSelectedChannel != (uint32_t)-1 && ulChannel != latestSelectedChannel) adc_disable_channel( ADC, latestSelectedChannel ); latestSelectedChannel = ulChannel; + g_pinStatus[ulPin] = (g_pinStatus[ulPin] & 0xF0) | PIN_STATUS_ANALOG; } // Start the ADC @@ -189,13 +190,9 @@ static void TC_SetCMR_ChannelB(Tc *tc, uint32_t chan, uint32_t v) } static uint8_t PWMEnabled = 0; -static uint8_t pinEnabled[PINS_COUNT]; static uint8_t TCChanEnabled[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; void analogOutputInit(void) { - uint8_t i; - for (i=0; i> 4 ? PIO_OUTPUT_1 : PIO_OUTPUT_0), g_APinDescription[ulPin].ulPin, g_APinDescription[ulPin].ulPinConfiguration ) ; + g_pinStatus[ulPin] = (g_pinStatus[ulPin] & 0xF0) | PIN_STATUS_DIGITAL_OUTPUT; + /* if all pins are output, disable PIO Controller clocking, reduce power consumption */ if ( g_APinDescription[ulPin].pPort->PIO_OSR == 0xffffffff ) { @@ -85,6 +96,12 @@ extern void digitalWrite( uint32_t ulPin, uint32_t ulVal ) return ; } + if ((g_pinStatus[ulPin] & 0xF) == PIN_STATUS_PWM) { + pinMode(ulPin, OUTPUT); + } + + g_pinStatus[ulPin] = (g_pinStatus[ulPin] & 0x0F) | (ulVal << 4) ; + if ( PIO_GetOutputDataStatus( g_APinDescription[ulPin].pPort, g_APinDescription[ulPin].ulPin ) == 0 ) { PIO_PullUp( g_APinDescription[ulPin].pPort, g_APinDescription[ulPin].ulPin, ulVal ) ; @@ -97,6 +114,14 @@ extern void digitalWrite( uint32_t ulPin, uint32_t ulVal ) extern int digitalRead( uint32_t ulPin ) { + if ((g_pinStatus[ulPin] & 0xF) == PIN_STATUS_DIGITAL_OUTPUT) { + return (g_pinStatus[ulPin] & 0xF0) >> 4; + } + + if ((g_pinStatus[ulPin] & 0xF) == PIN_STATUS_ANALOG) { + pinMode(ulPin, INPUT); + } + if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN ) { return LOW ; diff --git a/hardware/arduino/sam/variants/arduino_due_x/variant.cpp b/hardware/arduino/sam/variants/arduino_due_x/variant.cpp index f95d85017..7a0de80a9 100644 --- a/hardware/arduino/sam/variants/arduino_due_x/variant.cpp +++ b/hardware/arduino/sam/variants/arduino_due_x/variant.cpp @@ -291,6 +291,9 @@ extern const PinDescription g_APinDescription[]= { NULL, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER } } ; + +uint8_t g_pinStatus[PINS_COUNT] = {0}; + #ifdef __cplusplus } #endif From 5a37e94788b94004e163917c39c3a10d5e543e04 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 16 Jul 2015 10:44:37 +0200 Subject: [PATCH 5/5] fix leftover on pinMode(OUTPUT) --- hardware/arduino/sam/cores/arduino/wiring_digital.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/arduino/sam/cores/arduino/wiring_digital.c b/hardware/arduino/sam/cores/arduino/wiring_digital.c index e159ff131..f8d6116cf 100644 --- a/hardware/arduino/sam/cores/arduino/wiring_digital.c +++ b/hardware/arduino/sam/cores/arduino/wiring_digital.c @@ -70,7 +70,7 @@ extern void pinMode( uint32_t ulPin, uint32_t ulMode ) case OUTPUT: PIO_Configure( g_APinDescription[ulPin].pPort, - g_pinStatus[ulPin] = ((g_pinStatus[ulPin] & 0xF0) >> 4 ? PIO_OUTPUT_1 : PIO_OUTPUT_0), + (g_pinStatus[ulPin] & 0xF0) >> 4 ? PIO_OUTPUT_1 : PIO_OUTPUT_0, g_APinDescription[ulPin].ulPin, g_APinDescription[ulPin].ulPinConfiguration ) ;