From 060c1e766c6ed33afe0b87db28548914a6bdc474 Mon Sep 17 00:00:00 2001 From: Arturo Guadalupi Date: Mon, 24 Nov 2014 09:37:20 +0100 Subject: [PATCH 1/7] Updated description It reads the state of a potentiometer (an analog input) and turns on an LED only if the LED goes above a certain threshold level. It prints the analog value regardless of the level. updated to It reads the state of a potentiometer (an analog input) and turns on an LED only if the potentiometer goes above a certain threshold level. It prints the analog value regardless of the level. --- .../IfStatementConditional/IfStatementConditional.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/shared/examples/05.Control/IfStatementConditional/IfStatementConditional.ino b/build/shared/examples/05.Control/IfStatementConditional/IfStatementConditional.ino index e6c18017a37..9f1b309e2cd 100644 --- a/build/shared/examples/05.Control/IfStatementConditional/IfStatementConditional.ino +++ b/build/shared/examples/05.Control/IfStatementConditional/IfStatementConditional.ino @@ -3,7 +3,7 @@ This example demonstrates the use of if() statements. It reads the state of a potentiometer (an analog input) and turns on an LED - only if the LED goes above a certain threshold level. It prints the analog value + only if the potentiometer goes above a certain threshold level. It prints the analog value regardless of the level. The circuit: From 042fa0c3f20cd654115de955f75a35de5d86aabd Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 14 Oct 2014 17:41:59 +0200 Subject: [PATCH 2/7] Backported SPI Transcations from 1.5.x --- libraries/SPI/SPI.cpp | 201 +++++++++--- libraries/SPI/SPI.h | 306 ++++++++++++++++-- .../BarometricPressureSensor.ino | 10 +- .../DigitalPotControl/DigitalPotControl.ino | 26 +- 4 files changed, 462 insertions(+), 81 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 5e48073f731..077b6a38db8 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -1,5 +1,8 @@ /* * Copyright (c) 2010 by Cristian Maglie + * Copyright (c) 2014 by Paul Stoffregen (Transaction API) + * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) + * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) * SPI Master library for arduino. * * This file is free software; you can redistribute it and/or modify @@ -8,59 +11,183 @@ * published by the Free Software Foundation. */ -#include "pins_arduino.h" #include "SPI.h" SPIClass SPI; -void SPIClass::begin() { +uint8_t SPIClass::initialized = 0; +uint8_t SPIClass::interruptMode = 0; +uint8_t SPIClass::interruptMask = 0; +uint8_t SPIClass::interruptSave = 0; +#ifdef SPI_TRANSACTION_MISMATCH_LED +uint8_t SPIClass::inTransactionFlag = 0; +#endif - // Set SS to high so a connected chip will be "deselected" by default - digitalWrite(SS, HIGH); +void SPIClass::begin() +{ + uint8_t sreg = SREG; + noInterrupts(); // Protect from a scheduler and prevent transactionBegin + if (!initialized) { + // Set SS to high so a connected chip will be "deselected" by default + digitalWrite(SS, HIGH); - // When the SS pin is set as OUTPUT, it can be used as - // a general purpose output port (it doesn't influence - // SPI operations). - pinMode(SS, OUTPUT); + // When the SS pin is set as OUTPUT, it can be used as + // a general purpose output port (it doesn't influence + // SPI operations). + pinMode(SS, OUTPUT); - // Warning: if the SS pin ever becomes a LOW INPUT then SPI - // automatically switches to Slave, so the data direction of - // the SS pin MUST be kept as OUTPUT. - SPCR |= _BV(MSTR); - SPCR |= _BV(SPE); + // Warning: if the SS pin ever becomes a LOW INPUT then SPI + // automatically switches to Slave, so the data direction of + // the SS pin MUST be kept as OUTPUT. + SPCR |= _BV(MSTR); + SPCR |= _BV(SPE); - // Set direction register for SCK and MOSI pin. - // MISO pin automatically overrides to INPUT. - // By doing this AFTER enabling SPI, we avoid accidentally - // clocking in a single bit since the lines go directly - // from "input" to SPI control. - // http://code.google.com/p/arduino/issues/detail?id=888 - pinMode(SCK, OUTPUT); - pinMode(MOSI, OUTPUT); + // Set direction register for SCK and MOSI pin. + // MISO pin automatically overrides to INPUT. + // By doing this AFTER enabling SPI, we avoid accidentally + // clocking in a single bit since the lines go directly + // from "input" to SPI control. + // http://code.google.com/p/arduino/issues/detail?id=888 + pinMode(SCK, OUTPUT); + pinMode(MOSI, OUTPUT); + } + initialized++; // reference count + SREG = sreg; } - void SPIClass::end() { - SPCR &= ~_BV(SPE); -} - -void SPIClass::setBitOrder(uint8_t bitOrder) -{ - if(bitOrder == LSBFIRST) { - SPCR |= _BV(DORD); - } else { - SPCR &= ~(_BV(DORD)); + uint8_t sreg = SREG; + noInterrupts(); // Protect from a scheduler and prevent transactionBegin + // Decrease the reference counter + if (initialized) + initialized--; + // If there are no more references disable SPI + if (!initialized) { + SPCR &= ~_BV(SPE); + interruptMode = 0; + #ifdef SPI_TRANSACTION_MISMATCH_LED + inTransactionFlag = 0; + #endif } + SREG = sreg; } -void SPIClass::setDataMode(uint8_t mode) +// mapping of interrupt numbers to bits within SPI_AVR_EIMSK +#if defined(__AVR_ATmega32U4__) + #define SPI_INT0_MASK (1<> 2) & SPI_2XCLOCK_MASK); + // Once in mode 2 we can't go back to 0 without a proper reference count + if (interruptMode == 2) + return; + uint8_t mask = 0; + uint8_t sreg = SREG; + noInterrupts(); // Protect from a scheduler and prevent transactionBegin + switch (interruptNumber) { + #ifdef SPI_INT0_MASK + case 0: mask = SPI_INT0_MASK; break; + #endif + #ifdef SPI_INT1_MASK + case 1: mask = SPI_INT1_MASK; break; + #endif + #ifdef SPI_INT2_MASK + case 2: mask = SPI_INT2_MASK; break; + #endif + #ifdef SPI_INT3_MASK + case 3: mask = SPI_INT3_MASK; break; + #endif + #ifdef SPI_INT4_MASK + case 4: mask = SPI_INT4_MASK; break; + #endif + #ifdef SPI_INT5_MASK + case 5: mask = SPI_INT5_MASK; break; + #endif + #ifdef SPI_INT6_MASK + case 6: mask = SPI_INT6_MASK; break; + #endif + #ifdef SPI_INT7_MASK + case 7: mask = SPI_INT7_MASK; break; + #endif + default: + break; + // this case can't be reached + } + interruptMask &= ~mask; + if (!interruptMask) + interruptMode = 0; + SREG = sreg; } - diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index f647d5c8918..cee618c80db 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -1,5 +1,8 @@ /* * Copyright (c) 2010 by Cristian Maglie + * Copyright (c) 2014 by Paul Stoffregen (Transaction API) + * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) + * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) * SPI Master library for arduino. * * This file is free software; you can redistribute it and/or modify @@ -11,9 +14,34 @@ #ifndef _SPI_H_INCLUDED #define _SPI_H_INCLUDED -#include #include -#include + +// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(), +// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode) +#define SPI_HAS_TRANSACTION 1 + +// SPI_HAS_NOTUSINGINTERRUPT means that SPI has notUsingInterrupt() method +#define SPI_HAS_NOTUSINGINTERRUPT 1 + +// SPI_ATOMIC_VERSION means that SPI has atomicity fixes and what version. +// This way when there is a bug fix you can check this define to alert users +// of your code if it uses better version of this library. +// This also implies everything that SPI_HAS_TRANSACTION as documented above is +// available too. +#define SPI_ATOMIC_VERSION 1 + +// Uncomment this line to add detection of mismatched begin/end transactions. +// A mismatch occurs if other libraries fail to use SPI.endTransaction() for +// each SPI.beginTransaction(). Connect an LED to this pin. The LED will turn +// on if any mismatch is ever detected. +//#define SPI_TRANSACTION_MISMATCH_LED 5 + +#ifndef LSBFIRST +#define LSBFIRST 0 +#endif +#ifndef MSBFIRST +#define MSBFIRST 1 +#endif #define SPI_CLOCK_DIV4 0x00 #define SPI_CLOCK_DIV16 0x01 @@ -22,7 +50,6 @@ #define SPI_CLOCK_DIV2 0x04 #define SPI_CLOCK_DIV8 0x05 #define SPI_CLOCK_DIV32 0x06 -//#define SPI_CLOCK_DIV64 0x07 #define SPI_MODE0 0x00 #define SPI_MODE1 0x04 @@ -33,38 +60,265 @@ #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR -class SPIClass { +// define SPI_AVR_EIMSK for AVR boards with external interrupt pins +#if defined(EIMSK) + #define SPI_AVR_EIMSK EIMSK +#elif defined(GICR) + #define SPI_AVR_EIMSK GICR +#elif defined(GIMSK) + #define SPI_AVR_EIMSK GIMSK +#endif + +class SPISettings { public: - inline static byte transfer(byte _data); + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, bitOrder, dataMode); + } else { + init_MightInline(clock, bitOrder, dataMode); + } + } + SPISettings() { + init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); + } +private: + void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { + init_AlwaysInline(clock, bitOrder, dataMode); + } + void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) + __attribute__((__always_inline__)) { + // Clock settings are defined as follows. Note that this shows SPI2X + // inverted, so the bits form increasing numbers. Also note that + // fosc/64 appears twice + // SPR1 SPR0 ~SPI2X Freq + // 0 0 0 fosc/2 + // 0 0 1 fosc/4 + // 0 1 0 fosc/8 + // 0 1 1 fosc/16 + // 1 0 0 fosc/32 + // 1 0 1 fosc/64 + // 1 1 0 fosc/64 + // 1 1 1 fosc/128 - // SPI Configuration methods + // We find the fastest clock that is less than or equal to the + // given clock rate. The clock divider that results in clock_setting + // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the + // slowest (128 == 2 ^^ 7, so clock_div = 6). + uint8_t clockDiv; - inline static void attachInterrupt(); - inline static void detachInterrupt(); // Default + // When the clock is known at compiletime, use this if-then-else + // cascade, which the compiler knows how to completely optimize + // away. When clock is not known, use a loop instead, which generates + // shorter code. + if (__builtin_constant_p(clock)) { + if (clock >= F_CPU / 2) { + clockDiv = 0; + } else if (clock >= F_CPU / 4) { + clockDiv = 1; + } else if (clock >= F_CPU / 8) { + clockDiv = 2; + } else if (clock >= F_CPU / 16) { + clockDiv = 3; + } else if (clock >= F_CPU / 32) { + clockDiv = 4; + } else if (clock >= F_CPU / 64) { + clockDiv = 5; + } else { + clockDiv = 6; + } + } else { + uint32_t clockSetting = F_CPU / 2; + clockDiv = 0; + while (clockDiv < 6 && clock < clockSetting) { + clockSetting /= 2; + clockDiv++; + } + } - static void begin(); // Default - static void end(); + // Compensate for the duplicate fosc/64 + if (clockDiv == 6) + clockDiv = 7; - static void setBitOrder(uint8_t); - static void setDataMode(uint8_t); - static void setClockDivider(uint8_t); + // Invert the SPI2X bit + clockDiv ^= 0x1; + + // Pack into the SPISettings class + spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) | + (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK); + spsr = clockDiv & SPI_2XCLOCK_MASK; + } + uint8_t spcr; + uint8_t spsr; + friend class SPIClass; }; -extern SPIClass SPI; -byte SPIClass::transfer(byte _data) { - SPDR = _data; - while (!(SPSR & _BV(SPIF))) - ; - return SPDR; -} +class SPIClass { +public: + // Initialize the SPI library + static void begin(); + + // If SPI is used from within an interrupt, this function registers + // that interrupt with the SPI library, so beginTransaction() can + // prevent conflicts. The input interruptNumber is the number used + // with attachInterrupt. If SPI is used from a different interrupt + // (eg, a timer), interruptNumber should be 255. + static void usingInterrupt(uint8_t interruptNumber); + // And this does the opposite. + static void notUsingInterrupt(uint8_t interruptNumber); + // Note: the usingInterrupt and notUsingInterrupt functions should + // not to be called from ISR context or inside a transaction. + // For details see: + // https://github.com/arduino/Arduino/pull/2381 + // https://github.com/arduino/Arduino/pull/2449 + + // Before using SPI.transfer() or asserting chip select pins, + // this function is used to gain exclusive access to the SPI bus + // and configure the correct settings. + inline static void beginTransaction(SPISettings settings) { + if (interruptMode > 0) { + uint8_t sreg = SREG; + noInterrupts(); + + #ifdef SPI_AVR_EIMSK + if (interruptMode == 1) { + interruptSave = SPI_AVR_EIMSK; + SPI_AVR_EIMSK &= ~interruptMask; + SREG = sreg; + } else + #endif + { + interruptSave = sreg; + } + } + + #ifdef SPI_TRANSACTION_MISMATCH_LED + if (inTransactionFlag) { + pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); + digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); + } + inTransactionFlag = 1; + #endif + + SPCR = settings.spcr; + SPSR = settings.spsr; + } + + // Write to the SPI bus (MOSI pin) and also receive (MISO pin) + inline static uint8_t transfer(uint8_t data) { + SPDR = data; + /* + * The following NOP introduces a small delay that can prevent the wait + * loop form iterating when running at the maximum speed. This gives + * about 10% more speed, even if it seems counter-intuitive. At lower + * speeds it is unnoticed. + */ + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; // wait + return SPDR; + } + inline static uint16_t transfer16(uint16_t data) { + union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out; + in.val = data; + if (!(SPCR & _BV(DORD))) { + SPDR = in.msb; + asm volatile("nop"); // See transfer(uint8_t) function + while (!(SPSR & _BV(SPIF))) ; + out.msb = SPDR; + SPDR = in.lsb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.lsb = SPDR; + } else { + SPDR = in.lsb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.lsb = SPDR; + SPDR = in.msb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.msb = SPDR; + } + return out.val; + } + inline static void transfer(void *buf, size_t count) { + if (count == 0) return; + uint8_t *p = (uint8_t *)buf; + SPDR = *p; + while (--count > 0) { + uint8_t out = *(p + 1); + while (!(SPSR & _BV(SPIF))) ; + uint8_t in = SPDR; + SPDR = out; + *p++ = in; + } + while (!(SPSR & _BV(SPIF))) ; + *p = SPDR; + } + // After performing a group of transfers and releasing the chip select + // signal, this function allows others to access the SPI bus + inline static void endTransaction(void) { + #ifdef SPI_TRANSACTION_MISMATCH_LED + if (!inTransactionFlag) { + pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); + digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); + } + inTransactionFlag = 0; + #endif -void SPIClass::attachInterrupt() { - SPCR |= _BV(SPIE); -} + if (interruptMode > 0) { + #ifdef SPI_AVR_EIMSK + uint8_t sreg = SREG; + #endif + noInterrupts(); + #ifdef SPI_AVR_EIMSK + if (interruptMode == 1) { + SPI_AVR_EIMSK = interruptSave; + SREG = sreg; + } else + #endif + { + SREG = interruptSave; + } + } + } -void SPIClass::detachInterrupt() { - SPCR &= ~_BV(SPIE); -} + // Disable the SPI bus + static void end(); + + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setBitOrder(uint8_t bitOrder) { + if (bitOrder == LSBFIRST) SPCR |= _BV(DORD); + else SPCR &= ~(_BV(DORD)); + } + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setDataMode(uint8_t dataMode) { + SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode; + } + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setClockDivider(uint8_t clockDiv) { + SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK); + SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK); + } + // These undocumented functions should not be used. SPI.transfer() + // polls the hardware flag which is automatically cleared as the + // AVR responds to SPI's interrupt + inline static void attachInterrupt() { SPCR |= _BV(SPIE); } + inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); } + +private: + static uint8_t initialized; + static uint8_t interruptMode; // 0=none, 1=mask, 2=global + static uint8_t interruptMask; // which interrupts to mask + static uint8_t interruptSave; // temp storage, to restore state + #ifdef SPI_TRANSACTION_MISMATCH_LED + static uint8_t inTransactionFlag; + #endif +}; + +extern SPIClass SPI; #endif diff --git a/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino b/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino index 9d77a426179..8104fcbc252 100644 --- a/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino +++ b/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino @@ -1,14 +1,14 @@ /* SCP1000 Barometric Pressure Sensor Display - + Shows the output of a Barometric Pressure Sensor on a Uses the SPI library. For details on the sensor, see: http://www.sparkfun.com/commerce/product_info.php?products_id=8161 http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ - + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip - + Circuit: SCP1000 sensor attached to pins 6, 7, 10 - 13: DRDY: pin 6 @@ -16,7 +16,7 @@ MOSI: pin 11 MISO: pin 12 SCK: pin 13 - + created 31 July 2010 modified 14 August 2010 by Tom Igoe @@ -77,7 +77,7 @@ void loop() { //Read the pressure data lower 16 bits: unsigned int pressure_data_low = readRegister(0x20, 2); //combine the two parts into one 19-bit number: - long pressure = ((pressure_data_high << 16) | pressure_data_low)/4; + long pressure = ((pressure_data_high << 16) | pressure_data_low) / 4; // display the temperature: Serial.println("\tPressure [Pa]=" + String(pressure)); diff --git a/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino b/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino index adf93a2c18f..b135a74f4ed 100644 --- a/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino +++ b/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino @@ -1,16 +1,16 @@ /* Digital Pot Control - + This example controls an Analog Devices AD5206 digital potentiometer. The AD5206 has 6 potentiometer channels. Each channel's pins are labeled A - connect this to voltage W - this is the pot's wiper, which changes when you set it B - connect this to ground. - - The AD5206 is SPI-compatible,and to command it, you send two bytes, + + The AD5206 is SPI-compatible,and to command it, you send two bytes, one with the channel number (0 - 5) and one with the resistance value for the - channel (0 - 255). - + channel (0 - 255). + The circuit: * All A pins of AD5206 connected to +5V * All B pins of AD5206 connected to ground @@ -18,12 +18,12 @@ * CS - to digital pin 10 (SS pin) * SDI - to digital pin 11 (MOSI pin) * CLK - to digital pin 13 (SCK pin) - - created 10 Aug 2010 + + created 10 Aug 2010 by Tom Igoe - + Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 - + */ @@ -38,12 +38,12 @@ void setup() { // set the slaveSelectPin as an output: pinMode (slaveSelectPin, OUTPUT); // initialize SPI: - SPI.begin(); + SPI.begin(); } void loop() { // go through the six channels of the digital pot: - for (int channel = 0; channel < 6; channel++) { + for (int channel = 0; channel < 6; channel++) { // change the resistance on this channel from min to max: for (int level = 0; level < 255; level++) { digitalPotWrite(channel, level); @@ -62,10 +62,10 @@ void loop() { void digitalPotWrite(int address, int value) { // take the SS pin low to select the chip: - digitalWrite(slaveSelectPin,LOW); + digitalWrite(slaveSelectPin, LOW); // send in the address and value via SPI: SPI.transfer(address); SPI.transfer(value); // take the SS pin high to de-select the chip: - digitalWrite(slaveSelectPin,HIGH); + digitalWrite(slaveSelectPin, HIGH); } From 6ecb174c40fb880ac555182f918048b0050b3c98 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 15 Oct 2014 11:26:09 +0200 Subject: [PATCH 3/7] Backported 'yield()' hook from 1.5.x --- hardware/arduino/cores/arduino/Arduino.h | 2 ++ hardware/arduino/cores/arduino/hooks.c | 31 ++++++++++++++++++++++++ hardware/arduino/cores/arduino/wiring.c | 1 + 3 files changed, 34 insertions(+) create mode 100644 hardware/arduino/cores/arduino/hooks.c diff --git a/hardware/arduino/cores/arduino/Arduino.h b/hardware/arduino/cores/arduino/Arduino.h index d4a22a69cdc..f03c2bc3bd7 100755 --- a/hardware/arduino/cores/arduino/Arduino.h +++ b/hardware/arduino/cores/arduino/Arduino.h @@ -34,6 +34,8 @@ extern "C"{ #endif +void yield(void); + #define HIGH 0x1 #define LOW 0x0 diff --git a/hardware/arduino/cores/arduino/hooks.c b/hardware/arduino/cores/arduino/hooks.c new file mode 100644 index 00000000000..641eabc7376 --- /dev/null +++ b/hardware/arduino/cores/arduino/hooks.c @@ -0,0 +1,31 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * Empty yield() hook. + * + * This function is intended to be used by library writers to build + * libraries or sketches that supports cooperative threads. + * + * Its defined as a weak symbol and it can be redefined to implement a + * real cooperative scheduler. + */ +static void __empty() { + // Empty +} +void yield(void) __attribute__ ((weak, alias("__empty"))); diff --git a/hardware/arduino/cores/arduino/wiring.c b/hardware/arduino/cores/arduino/wiring.c index a3c4390e3c8..5cbe241956d 100644 --- a/hardware/arduino/cores/arduino/wiring.c +++ b/hardware/arduino/cores/arduino/wiring.c @@ -111,6 +111,7 @@ void delay(unsigned long ms) uint16_t start = (uint16_t)micros(); while (ms > 0) { + yield(); if (((uint16_t)micros() - start) >= 1000) { ms--; start += 1000; From b9b0fcdadc04a6a2d6954611b49aa1f7a6422e80 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 17 Oct 2014 12:20:30 +0200 Subject: [PATCH 4/7] Backported Ethernet library from 1.5.x --- libraries/Ethernet/Dhcp.cpp | 4 +- libraries/Ethernet/Dhcp.h | 0 libraries/Ethernet/Dns.cpp | 4 +- libraries/Ethernet/Ethernet.cpp | 22 ++++- libraries/Ethernet/EthernetClient.cpp | 13 ++- libraries/Ethernet/EthernetServer.cpp | 4 +- libraries/Ethernet/EthernetUdp.cpp | 8 +- .../BarometricPressureWebServer.ino | 61 ++++++------ .../examples/ChatServer/ChatServer.ino | 29 +++--- .../DhcpAddressPrinter/DhcpAddressPrinter.ino | 25 ++--- .../DhcpChatServer/DhcpChatServer.ino | 29 +++--- .../examples/TelnetClient/TelnetClient.ino | 37 ++++---- .../UDPSendReceiveString.ino | 55 +++++------ .../examples/UdpNtpClient/UdpNtpClient.ino | 84 ++++++++-------- .../Ethernet/examples/WebClient/WebClient.ino | 24 ++--- .../WebClientRepeating/WebClientRepeating.ino | 64 ++++++------- .../Ethernet/examples/WebServer/WebServer.ino | 29 +++--- libraries/Ethernet/utility/socket.cpp | 95 ++++++++++++++++--- libraries/Ethernet/utility/socket.h | 5 +- libraries/Ethernet/{ => utility}/util.h | 3 +- libraries/Ethernet/utility/w5100.cpp | 12 +-- libraries/Ethernet/utility/w5100.h | 6 +- 22 files changed, 348 insertions(+), 265 deletions(-) mode change 100755 => 100644 libraries/Ethernet/Dhcp.cpp mode change 100755 => 100644 libraries/Ethernet/Dhcp.h mode change 100755 => 100644 libraries/Ethernet/utility/socket.h rename libraries/Ethernet/{ => utility}/util.h (77%) mode change 100755 => 100644 libraries/Ethernet/utility/w5100.h diff --git a/libraries/Ethernet/Dhcp.cpp b/libraries/Ethernet/Dhcp.cpp old mode 100755 new mode 100644 index 56d5b69516e..94ab18270d4 --- a/libraries/Ethernet/Dhcp.cpp +++ b/libraries/Ethernet/Dhcp.cpp @@ -1,13 +1,13 @@ // DHCP Library v0.3 - April 25, 2009 // Author: Jordan Terrell - blog.jordanterrell.com -#include "w5100.h" +#include "utility/w5100.h" #include #include #include "Dhcp.h" #include "Arduino.h" -#include "util.h" +#include "utility/util.h" int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { diff --git a/libraries/Ethernet/Dhcp.h b/libraries/Ethernet/Dhcp.h old mode 100755 new mode 100644 diff --git a/libraries/Ethernet/Dns.cpp b/libraries/Ethernet/Dns.cpp index b3c1a9dc148..62e36f8a335 100644 --- a/libraries/Ethernet/Dns.cpp +++ b/libraries/Ethernet/Dns.cpp @@ -2,9 +2,9 @@ // (c) Copyright 2009-2010 MCQN Ltd. // Released under Apache License, version 2.0 -#include "w5100.h" +#include "utility/w5100.h" #include "EthernetUdp.h" -#include "util.h" +#include "utility/util.h" #include "Dns.h" #include diff --git a/libraries/Ethernet/Ethernet.cpp b/libraries/Ethernet/Ethernet.cpp index c31a85f0936..3eea69a2a85 100644 --- a/libraries/Ethernet/Ethernet.cpp +++ b/libraries/Ethernet/Ethernet.cpp @@ -1,4 +1,4 @@ -#include "w5100.h" +#include "utility/w5100.h" #include "Ethernet.h" #include "Dhcp.h" @@ -16,8 +16,10 @@ int EthernetClass::begin(uint8_t *mac_address) // Initialise the basic info W5100.init(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.setMACAddress(mac_address); W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); + SPI.endTransaction(); // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP(mac_address); @@ -25,9 +27,11 @@ int EthernetClass::begin(uint8_t *mac_address) { // We've successfully found a DHCP server and got our configuration info, so set things // accordingly + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); _dnsServerAddress = _dhcp->getDnsServerIp(); } @@ -61,10 +65,12 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dn void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) { W5100.init(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.setMACAddress(mac); - W5100.setIPAddress(local_ip._address); - W5100.setGatewayIp(gateway._address); - W5100.setSubnetMask(subnet._address); + W5100.setIPAddress(local_ip.raw_address()); + W5100.setGatewayIp(gateway.raw_address()); + W5100.setSubnetMask(subnet.raw_address()); + SPI.endTransaction(); _dnsServerAddress = dns_server; } @@ -80,9 +86,11 @@ int EthernetClass::maintain(){ case DHCP_CHECK_RENEW_OK: case DHCP_CHECK_REBIND_OK: //we might have got a new IP. + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); _dnsServerAddress = _dhcp->getDnsServerIp(); break; default: @@ -96,21 +104,27 @@ int EthernetClass::maintain(){ IPAddress EthernetClass::localIP() { IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.getIPAddress(ret.raw_address()); + SPI.endTransaction(); return ret; } IPAddress EthernetClass::subnetMask() { IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.getSubnetMask(ret.raw_address()); + SPI.endTransaction(); return ret; } IPAddress EthernetClass::gatewayIP() { IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.getGatewayIp(ret.raw_address()); + SPI.endTransaction(); return ret; } diff --git a/libraries/Ethernet/EthernetClient.cpp b/libraries/Ethernet/EthernetClient.cpp index 1e89c4e87c4..a592bfdc956 100644 --- a/libraries/Ethernet/EthernetClient.cpp +++ b/libraries/Ethernet/EthernetClient.cpp @@ -1,5 +1,5 @@ -#include "w5100.h" -#include "socket.h" +#include "utility/w5100.h" +#include "utility/socket.h" extern "C" { #include "string.h" @@ -40,7 +40,7 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) { return 0; for (int i = 0; i < MAX_SOCK_NUM; i++) { - uint8_t s = W5100.readSnSR(i); + uint8_t s = socketStatus(i); if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) { _sock = i; break; @@ -88,7 +88,7 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) { int EthernetClient::available() { if (_sock != MAX_SOCK_NUM) - return W5100.getRXReceivedSize(_sock); + return recvAvailable(_sock); return 0; } @@ -120,8 +120,7 @@ int EthernetClient::peek() { } void EthernetClient::flush() { - while (available()) - read(); + ::flush(_sock); } void EthernetClient::stop() { @@ -154,7 +153,7 @@ uint8_t EthernetClient::connected() { uint8_t EthernetClient::status() { if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED; - return W5100.readSnSR(_sock); + return socketStatus(_sock); } // the next function allows us to use the client returned by diff --git a/libraries/Ethernet/EthernetServer.cpp b/libraries/Ethernet/EthernetServer.cpp index 0308b92619f..6d6ce8c8027 100644 --- a/libraries/Ethernet/EthernetServer.cpp +++ b/libraries/Ethernet/EthernetServer.cpp @@ -1,5 +1,5 @@ -#include "w5100.h" -#include "socket.h" +#include "utility/w5100.h" +#include "utility/socket.h" extern "C" { #include "string.h" } diff --git a/libraries/Ethernet/EthernetUdp.cpp b/libraries/Ethernet/EthernetUdp.cpp index 37600529f8b..b5dcb78ccf7 100644 --- a/libraries/Ethernet/EthernetUdp.cpp +++ b/libraries/Ethernet/EthernetUdp.cpp @@ -26,8 +26,8 @@ * bjoern@cs.stanford.edu 12/30/2008 */ -#include "w5100.h" -#include "socket.h" +#include "utility/w5100.h" +#include "utility/socket.h" #include "Ethernet.h" #include "Udp.h" #include "Dns.h" @@ -41,7 +41,7 @@ uint8_t EthernetUDP::begin(uint16_t port) { return 0; for (int i = 0; i < MAX_SOCK_NUM; i++) { - uint8_t s = W5100.readSnSR(i); + uint8_t s = socketStatus(i); if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { _sock = i; break; @@ -120,7 +120,7 @@ int EthernetUDP::parsePacket() // discard any remaining bytes in the last packet flush(); - if (W5100.getRXReceivedSize(_sock) > 0) + if (recvAvailable(_sock) > 0) { //HACK - hand-parse the UDP packet using TCP recv method uint8_t tmpBuf[8]; diff --git a/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino b/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino index bfbcb6d4a8b..2c85ddd78af 100644 --- a/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino +++ b/libraries/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino @@ -1,14 +1,14 @@ /* SCP1000 Barometric Pressure Sensor Display - + Serves the output of a Barometric Pressure Sensor as a web page. Uses the SPI library. For details on the sensor, see: http://www.sparkfun.com/commerce/product_info.php?products_id=8161 http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ - + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip - + Circuit: SCP1000 sensor attached to pins 6,7, and 11 - 13: DRDY: pin 6 @@ -16,7 +16,7 @@ MOSI: pin 11 MISO: pin 12 SCK: pin 13 - + created 31 July 2010 by Tom Igoe */ @@ -28,16 +28,17 @@ // assign a MAC address for the ethernet controller. // fill in your address here: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; // assign an IP address for the controller: -IPAddress ip(192,168,1,20); -IPAddress gateway(192,168,1,1); +IPAddress ip(192, 168, 1, 20); +IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); // Initialize the Ethernet server library -// with the IP address and port you want to use +// with the IP address and port you want to use // (port 80 is default for HTTP): EthernetServer server(80); @@ -49,7 +50,7 @@ const int TEMPERATURE = 0x21; //16 bit temperature reading // pins used for the connection with the sensor // the others you need are controlled by the SPI library): -const int dataReadyPin = 6; +const int dataReadyPin = 6; const int chipSelectPin = 7; float temperature = 0.0; @@ -83,9 +84,9 @@ void setup() { } -void loop() { +void loop() { // check for a reading no more than once a second. - if (millis() - lastReadingTime > 1000){ + if (millis() - lastReadingTime > 1000) { // if there's a reading ready, read it: // don't do anything until the data ready pin is high: if (digitalRead(dataReadyPin) == HIGH) { @@ -109,13 +110,13 @@ void getData() { temperature = (float)tempData / 20.0; //Read the pressure data highest 3 bits: - byte pressureDataHigh = readRegister(0x1F, 1); + byte pressureDataHigh = readRegister(0x1F, 1); pressureDataHigh &= 0b00000111; //you only needs bits 2 to 0 //Read the pressure data lower 16 bits: - unsigned int pressureDataLow = readRegister(0x20, 2); + unsigned int pressureDataLow = readRegister(0x20, 2); //combine the two parts into one 19-bit number: - pressure = ((pressureDataHigh << 16) | pressureDataLow)/4; + pressure = ((pressureDataHigh << 16) | pressureDataLow) / 4; Serial.print("Temperature: "); Serial.print(temperature); @@ -149,13 +150,13 @@ void listenForEthernetClients() { client.println("
"); client.print("Pressure: " + String(pressure)); client.print(" Pa"); - client.println("
"); + client.println("
"); break; } if (c == '\n') { // you're starting a new line currentLineIsBlank = true; - } + } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; @@ -167,7 +168,7 @@ void listenForEthernetClients() { // close the connection: client.stop(); } -} +} //Send a write command to SCP1000 @@ -179,20 +180,20 @@ void writeRegister(byte registerName, byte registerValue) { registerName |= 0b00000010; //Write command // take the chip select low to select the device: - digitalWrite(chipSelectPin, LOW); + digitalWrite(chipSelectPin, LOW); SPI.transfer(registerName); //Send register location SPI.transfer(registerValue); //Send value to record into register // take the chip select high to de-select: - digitalWrite(chipSelectPin, HIGH); + digitalWrite(chipSelectPin, HIGH); } //Read register from the SCP1000: unsigned int readRegister(byte registerName, int numBytes) { byte inByte = 0; // incoming from the SPI read - unsigned int result = 0; // result to return + unsigned int result = 0; // result to return // SCP1000 expects the register name in the upper 6 bits // of the byte: @@ -201,22 +202,22 @@ unsigned int readRegister(byte registerName, int numBytes) { registerName &= 0b11111100; //Read command // take the chip select low to select the device: - digitalWrite(chipSelectPin, LOW); + digitalWrite(chipSelectPin, LOW); // send the device the register you want to read: - int command = SPI.transfer(registerName); + int command = SPI.transfer(registerName); // send a value of 0 to read the first byte returned: - inByte = SPI.transfer(0x00); - + inByte = SPI.transfer(0x00); + result = inByte; - // if there's more than one byte returned, + // if there's more than one byte returned, // shift the first byte then get the second byte: - if (numBytes > 1){ + if (numBytes > 1) { result = inByte << 8; - inByte = SPI.transfer(0x00); - result = result |inByte; + inByte = SPI.transfer(0x00); + result = result | inByte; } // take the chip select high to de-select: - digitalWrite(chipSelectPin, HIGH); + digitalWrite(chipSelectPin, HIGH); // return the result: return(result); } diff --git a/libraries/Ethernet/examples/ChatServer/ChatServer.ino b/libraries/Ethernet/examples/ChatServer/ChatServer.ino index d50e5a65798..927a60e1be2 100644 --- a/libraries/Ethernet/examples/ChatServer/ChatServer.ino +++ b/libraries/Ethernet/examples/ChatServer/ChatServer.ino @@ -1,20 +1,20 @@ /* Chat Server - + A simple server that distributes any incoming messages to all connected clients. To use telnet to your device's IP address and type. You can see the client's input in the serial monitor as well. - Using an Arduino Wiznet Ethernet shield. - + Using an Arduino Wiznet Ethernet shield. + Circuit: * Ethernet shield attached to pins 10, 11, 12, 13 * Analog inputs attached to pins A0 through A5 (optional) - + created 18 Dec 2009 by David A. Mellis modified 9 Apr 2012 by Tom Igoe - + */ #include @@ -23,10 +23,11 @@ // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network. // gateway and subnet are optional: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; -IPAddress ip(192,168,1, 177); -IPAddress gateway(192,168,1, 1); +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +IPAddress ip(192, 168, 1, 177); +IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 0, 0); @@ -39,9 +40,9 @@ void setup() { Ethernet.begin(mac, ip, gateway, subnet); // start listening for clients server.begin(); - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -58,11 +59,11 @@ void loop() { if (client) { if (!alreadyConnected) { // clead out the input buffer: - client.flush(); + client.flush(); Serial.println("We have a new client"); - client.println("Hello, client!"); + client.println("Hello, client!"); alreadyConnected = true; - } + } if (client.available() > 0) { // read the bytes incoming from the client: diff --git a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino index 5eaaf24d15b..a41b774039e 100644 --- a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino +++ b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino @@ -1,17 +1,17 @@ /* DHCP-based IP printer - + This sketch uses the DHCP extensions to the Ethernet library to get an IP address via DHCP and print the address obtained. - using an Arduino Wiznet Ethernet shield. - + using an Arduino Wiznet Ethernet shield. + Circuit: * Ethernet shield attached to pins 10, 11, 12, 13 - + created 12 April 2011 modified 9 Apr 2012 by Tom Igoe - + */ #include @@ -19,19 +19,20 @@ // Enter a MAC address for your controller below. // Newer Ethernet shields have a MAC address printed on a sticker on the shield -byte mac[] = { - 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; +byte mac[] = { + 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 +}; // Initialize the Ethernet client library -// with the IP address and port of the server +// with the IP address and port of the server // that you want to connect to (port 80 is default for HTTP): EthernetClient client; void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); // this check is only needed on the Leonardo: - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -39,7 +40,7 @@ void setup() { if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // no point in carrying on, so do nothing forevermore: - for(;;) + for (;;) ; } // print your local IP address: @@ -47,7 +48,7 @@ void setup() { for (byte thisByte = 0; thisByte < 4; thisByte++) { // print the value of each byte of the IP address: Serial.print(Ethernet.localIP()[thisByte], DEC); - Serial.print("."); + Serial.print("."); } Serial.println(); } diff --git a/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino b/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino index 09cbd435470..73cde4bbbbe 100644 --- a/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino +++ b/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino @@ -1,21 +1,21 @@ /* DHCP Chat Server - + A simple server that distributes any incoming messages to all connected clients. To use telnet to your device's IP address and type. You can see the client's input in the serial monitor as well. - Using an Arduino Wiznet Ethernet shield. - + Using an Arduino Wiznet Ethernet shield. + THis version attempts to get an IP address using DHCP - + Circuit: * Ethernet shield attached to pins 10, 11, 12, 13 - + created 21 May 2011 modified 9 Apr 2012 by Tom Igoe Based on ChatServer example by David A. Mellis - + */ #include @@ -24,10 +24,11 @@ // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network. // gateway and subnet are optional: -byte mac[] = { - 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 }; -IPAddress ip(192,168,1, 177); -IPAddress gateway(192,168,1, 1); +byte mac[] = { + 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 +}; +IPAddress ip(192, 168, 1, 177); +IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 0, 0); // telnet defaults to port 23 @@ -38,7 +39,7 @@ void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); // this check is only needed on the Leonardo: - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -56,12 +57,12 @@ void setup() { for (byte thisByte = 0; thisByte < 4; thisByte++) { // print the value of each byte of the IP address: Serial.print(ip[thisByte], DEC); - Serial.print("."); + Serial.print("."); } Serial.println(); // start listening for clients server.begin(); - + } void loop() { @@ -72,7 +73,7 @@ void loop() { if (client) { if (!gotAMessage) { Serial.println("We have a new client"); - client.println("Hello, client!"); + client.println("Hello, client!"); gotAMessage = true; } diff --git a/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino index 345712564c0..dcf3e8aa99f 100644 --- a/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino +++ b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino @@ -1,21 +1,21 @@ /* Telnet client - + This sketch connects to a a telnet server (http://www.google.com) - using an Arduino Wiznet Ethernet shield. You'll need a telnet server + using an Arduino Wiznet Ethernet shield. You'll need a telnet server to test this with. - Processing's ChatServer example (part of the network library) works well, + Processing's ChatServer example (part of the network library) works well, running on port 10002. It can be found as part of the examples - in the Processing application, available at + in the Processing application, available at http://processing.org/ - + Circuit: * Ethernet shield attached to pins 10, 11, 12, 13 - + created 14 Sep 2010 modified 9 Apr 2012 by Tom Igoe - + */ #include @@ -23,15 +23,16 @@ // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; -IPAddress ip(192,168,1,177); +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +IPAddress ip(192, 168, 1, 177); // Enter the IP address of the server you're connecting to: -IPAddress server(1,1,1,1); +IPAddress server(1, 1, 1, 1); // Initialize the Ethernet client library -// with the IP address and port of the server +// with the IP address and port of the server // that you want to connect to (port 23 is default for telnet; // if you're using Processing's ChatServer, use port 10002): EthernetClient client; @@ -39,9 +40,9 @@ EthernetClient client; void setup() { // start the Ethernet connection: Ethernet.begin(mac, ip); - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -53,7 +54,7 @@ void setup() { // if you get a connection, report back via serial: if (client.connect(server, 10002)) { Serial.println("connected"); - } + } else { // if you didn't get a connection to the server: Serial.println("connection failed"); @@ -62,7 +63,7 @@ void setup() { void loop() { - // if there are incoming bytes available + // if there are incoming bytes available // from the server, read them and print them: if (client.available()) { char c = client.read(); @@ -74,7 +75,7 @@ void loop() while (Serial.available() > 0) { char inChar = Serial.read(); if (client.connected()) { - client.print(inChar); + client.print(inChar); } } @@ -84,7 +85,7 @@ void loop() Serial.println("disconnecting."); client.stop(); // do nothing: - while(true); + while (true); } } diff --git a/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino b/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino index 4d4045cac6d..99de7650cc1 100644 --- a/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino +++ b/libraries/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino @@ -2,13 +2,13 @@ UDPSendReceive.pde: This sketch receives UDP message strings, prints them to the serial port and sends an "acknowledge" string back to the sender - - A Processing sketch is included at the end of file that can be used to send + + A Processing sketch is included at the end of file that can be used to send and received messages for testing with a computer. - + created 21 Aug 2010 by Michael Margolis - + This code is in the public domain. */ @@ -20,8 +20,9 @@ // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; IPAddress ip(192, 168, 1, 177); unsigned int localPort = 8888; // local port to listen on @@ -35,7 +36,7 @@ EthernetUDP Udp; void setup() { // start the Ethernet and UDP: - Ethernet.begin(mac,ip); + Ethernet.begin(mac, ip); Udp.begin(localPort); Serial.begin(9600); @@ -44,13 +45,13 @@ void setup() { void loop() { // if there's data available, read a packet int packetSize = Udp.parsePacket(); - if(packetSize) + if (packetSize) { Serial.print("Received packet of size "); Serial.println(packetSize); Serial.print("From "); IPAddress remote = Udp.remoteIP(); - for (int i =0; i < 4; i++) + for (int i = 0; i < 4; i++) { Serial.print(remote[i], DEC); if (i < 3) @@ -62,7 +63,7 @@ void loop() { Serial.println(Udp.remotePort()); // read the packet into packetBufffer - Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE); + Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); Serial.println("Contents:"); Serial.println(packetBuffer); @@ -78,40 +79,40 @@ void loop() { /* Processing sketch to run with this example ===================================================== - - // Processing UDP example to send and receive string data from Arduino + + // Processing UDP example to send and receive string data from Arduino // press any key to send the "Hello Arduino" message - - + + import hypermedia.net.*; - + UDP udp; // define the UDP object - - + + void setup() { udp = new UDP( this, 6000 ); // create a new datagram connection on port 6000 //udp.log( true ); // <-- printout the connection activity - udp.listen( true ); // and wait for incoming message + udp.listen( true ); // and wait for incoming message } - + void draw() { } - + void keyPressed() { String ip = "192.168.1.177"; // the remote IP address int port = 8888; // the destination port - + udp.send("Hello World", ip, port ); // the message to send - + } - + void receive( byte[] data ) { // <-- default handler //void receive( byte[] data, String ip, int port ) { // <-- extended handler - - for(int i=0; i < data.length; i++) - print(char(data[i])); - println(); + + for(int i=0; i < data.length; i++) + print(char(data[i])); + println(); } */ diff --git a/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino index 6b3b53d1305..25c71c402f5 100644 --- a/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino +++ b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino @@ -1,55 +1,47 @@ /* Udp NTP Client - + Get the time from a Network Time Protocol (NTP) time server - Demonstrates use of UDP sendPacket and ReceivePacket - For more on NTP time servers and the messages needed to communicate with them, + Demonstrates use of UDP sendPacket and ReceivePacket + For more on NTP time servers and the messages needed to communicate with them, see http://en.wikipedia.org/wiki/Network_Time_Protocol - - Warning: NTP Servers are subject to temporary failure or IP address change. - Plese check - - http://tf.nist.gov/tf-cgi/servers.cgi - if the time server used in the example didn't work. - - created 4 Sep 2010 + created 4 Sep 2010 by Michael Margolis modified 9 Apr 2012 by Tom Igoe - + This code is in the public domain. */ -#include +#include #include #include // Enter a MAC address for your controller below. // Newer Ethernet shields have a MAC address printed on a sticker on the shield -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; -unsigned int localPort = 8888; // local port to listen for UDP packets +unsigned int localPort = 8888; // local port to listen for UDP packets -IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server -// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server -// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server +char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server -const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message +const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message -byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets +byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets // A UDP instance to let us send and receive packets over UDP EthernetUDP Udp; -void setup() +void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -58,7 +50,7 @@ void setup() if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // no point in carrying on, so do nothing forevermore: - for(;;) + for (;;) ; } Udp.begin(localPort); @@ -68,58 +60,58 @@ void loop() { sendNTPpacket(timeServer); // send an NTP packet to a time server - // wait to see if a reply is available - delay(1000); - if ( Udp.parsePacket() ) { + // wait to see if a reply is available + delay(1000); + if ( Udp.parsePacket() ) { // We've received a packet, read the data from it - Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer + Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer //the timestamp starts at byte 40 of the received packet and is four bytes, // or two words, long. First, esxtract the two words: unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); - unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); + unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); // combine the four bytes (two words) into a long integer // this is NTP time (seconds since Jan 1 1900): - unsigned long secsSince1900 = highWord << 16 | lowWord; + unsigned long secsSince1900 = highWord << 16 | lowWord; Serial.print("Seconds since Jan 1 1900 = " ); - Serial.println(secsSince1900); + Serial.println(secsSince1900); // now convert NTP time into everyday time: Serial.print("Unix time = "); // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: - const unsigned long seventyYears = 2208988800UL; + const unsigned long seventyYears = 2208988800UL; // subtract seventy years: - unsigned long epoch = secsSince1900 - seventyYears; + unsigned long epoch = secsSince1900 - seventyYears; // print Unix time: - Serial.println(epoch); + Serial.println(epoch); // print the hour, minute and second: Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) - Serial.print(':'); + Serial.print(':'); if ( ((epoch % 3600) / 60) < 10 ) { // In the first 10 minutes of each hour, we'll want a leading '0' Serial.print('0'); } Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) - Serial.print(':'); + Serial.print(':'); if ( (epoch % 60) < 10 ) { // In the first 10 seconds of each minute, we'll want a leading '0' Serial.print('0'); } - Serial.println(epoch %60); // print the second + Serial.println(epoch % 60); // print the second } // wait ten seconds before asking for the time again - delay(10000); + delay(10000); } -// send an NTP request to the time server at the given address -unsigned long sendNTPpacket(IPAddress& address) +// send an NTP request to the time server at the given address +unsigned long sendNTPpacket(char* address) { // set all bytes in the buffer to 0 - memset(packetBuffer, 0, NTP_PACKET_SIZE); + memset(packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request // (see URL above for details on the packets) packetBuffer[0] = 0b11100011; // LI, Version, Mode @@ -127,16 +119,16 @@ unsigned long sendNTPpacket(IPAddress& address) packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion - packetBuffer[12] = 49; + packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now - // you can send a packet requesting a timestamp: + // you can send a packet requesting a timestamp: Udp.beginPacket(address, 123); //NTP requests are to port 123 - Udp.write(packetBuffer,NTP_PACKET_SIZE); - Udp.endPacket(); + Udp.write(packetBuffer, NTP_PACKET_SIZE); + Udp.endPacket(); } diff --git a/libraries/Ethernet/examples/WebClient/WebClient.ino b/libraries/Ethernet/examples/WebClient/WebClient.ino index 40523a4d9df..9afd40eae31 100644 --- a/libraries/Ethernet/examples/WebClient/WebClient.ino +++ b/libraries/Ethernet/examples/WebClient/WebClient.ino @@ -1,17 +1,17 @@ /* Web client - + This sketch connects to a website (http://www.google.com) - using an Arduino Wiznet Ethernet shield. - + using an Arduino Wiznet Ethernet shield. + Circuit: * Ethernet shield attached to pins 10, 11, 12, 13 - + created 18 Dec 2009 by David A. Mellis modified 9 Apr 2012 by Tom Igoe, based on work by Adrian McEwen - + */ #include @@ -26,17 +26,17 @@ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; char server[] = "www.google.com"; // name address for Google (using DNS) // Set the static IP address to use if the DHCP fails to assign -IPAddress ip(192,168,0,177); +IPAddress ip(192, 168, 0, 177); // Initialize the Ethernet client library -// with the IP address and port of the server +// with the IP address and port of the server // that you want to connect to (port 80 is default for HTTP): EthernetClient client; void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -59,7 +59,7 @@ void setup() { client.println("Host: www.google.com"); client.println("Connection: close"); client.println(); - } + } else { // kf you didn't get a connection to the server: Serial.println("connection failed"); @@ -68,7 +68,7 @@ void setup() { void loop() { - // if there are incoming bytes available + // if there are incoming bytes available // from the server, read them and print them: if (client.available()) { char c = client.read(); @@ -82,7 +82,7 @@ void loop() client.stop(); // do nothing forevermore: - while(true); + while (true); } } diff --git a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino index e0f06c43935..a0ae8b7828f 100644 --- a/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino +++ b/libraries/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino @@ -1,23 +1,25 @@ /* Repeating Web client - + This sketch connects to a a web server and makes a request using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or the Adafruit Ethernet shield, either one will work, as long as it's got a Wiznet Ethernet module on board. - + This example uses DNS, by assigning the Ethernet client with a MAC address, IP address, and DNS address. - + Circuit: * Ethernet shield attached to pins 10, 11, 12, 13 - + created 19 Apr 2012 by Tom Igoe - + modified 21 Jan 2014 + by Federico Vanzati + http://arduino.cc/en/Tutorial/WebClientRepeating This code is in the public domain. - + */ #include @@ -25,27 +27,33 @@ // assign a MAC address for the ethernet controller. // fill in your address here: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; // fill in an available IP address on your network here, // for manual configuration: -IPAddress ip(10,0,0,20); +IPAddress ip(192, 168, 1, 177); // fill in your Domain Name Server address here: -IPAddress myDns(1,1,1,1); +IPAddress myDns(1, 1, 1, 1); // initialize the library instance: EthernetClient client; char server[] = "www.arduino.cc"; +//IPAddress server(64,131,82,241); -unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds -boolean lastConnected = false; // state of the connection last time through the main loop -const unsigned long postingInterval = 60*1000; // delay between updates, in milliseconds +unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds +const unsigned long postingInterval = 10L * 1000L; // delay between updates, in milliseconds +// the "L" is needed to use long type numbers void setup() { // start serial port: Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + // give the ethernet module time to boot up: delay(1000); // start the Ethernet connection using a fixed IP address and DNS server: @@ -61,29 +69,23 @@ void loop() { // purposes only: if (client.available()) { char c = client.read(); - Serial.print(c); + Serial.write(c); } - // if there's no net connection, but there was one last time - // through the loop, then stop the client: - if (!client.connected() && lastConnected) { - Serial.println(); - Serial.println("disconnecting."); - client.stop(); - } - - // if you're not connected, and ten seconds have passed since - // your last connection, then connect again and send data: - if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) { + // if ten seconds have passed since your last connection, + // then connect again and send data: + if (millis() - lastConnectionTime > postingInterval) { httpRequest(); } - // store the state of the connection for next time through - // the loop: - lastConnected = client.connected(); + } // this method makes a HTTP connection to the server: void httpRequest() { + // close any connection before send a new request. + // This will free the socket on the WiFi shield + client.stop(); + // if there's a successful connection: if (client.connect(server, 80)) { Serial.println("connecting..."); @@ -96,15 +98,11 @@ void httpRequest() { // note the time that the connection was made: lastConnectionTime = millis(); - } + } else { // if you couldn't make a connection: Serial.println("connection failed"); - Serial.println("disconnecting."); - client.stop(); } } - - diff --git a/libraries/Ethernet/examples/WebServer/WebServer.ino b/libraries/Ethernet/examples/WebServer/WebServer.ino index 689eb7d393d..d0c585d07e5 100644 --- a/libraries/Ethernet/examples/WebServer/WebServer.ino +++ b/libraries/Ethernet/examples/WebServer/WebServer.ino @@ -1,18 +1,18 @@ /* Web Server - + A simple web server that shows the value of the analog input pins. - using an Arduino Wiznet Ethernet shield. - + using an Arduino Wiznet Ethernet shield. + Circuit: * Ethernet shield attached to pins 10, 11, 12, 13 * Analog inputs attached to pins A0 through A5 (optional) - + created 18 Dec 2009 by David A. Mellis modified 9 Apr 2012 by Tom Igoe - + */ #include @@ -20,19 +20,20 @@ // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; -IPAddress ip(192,168,1,177); +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +IPAddress ip(192, 168, 1, 177); // Initialize the Ethernet server library -// with the IP address and port you want to use +// with the IP address and port you want to use // (port 80 is default for HTTP): EthernetServer server(80); void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -64,7 +65,7 @@ void loop() { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response - client.println("Refresh: 5"); // refresh the page automatically every 5 sec + client.println("Refresh: 5"); // refresh the page automatically every 5 sec client.println(); client.println(""); client.println(""); @@ -75,7 +76,7 @@ void loop() { client.print(analogChannel); client.print(" is "); client.print(sensorReading); - client.println("
"); + client.println("
"); } client.println(""); break; @@ -83,7 +84,7 @@ void loop() { if (c == '\n') { // you're starting a new line currentLineIsBlank = true; - } + } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; diff --git a/libraries/Ethernet/utility/socket.cpp b/libraries/Ethernet/utility/socket.cpp index fd3e4426ab6..4ed4317ea5b 100644 --- a/libraries/Ethernet/utility/socket.cpp +++ b/libraries/Ethernet/utility/socket.cpp @@ -1,5 +1,5 @@ -#include "w5100.h" -#include "socket.h" +#include "utility/w5100.h" +#include "utility/socket.h" static uint16_t local_port; @@ -12,6 +12,7 @@ uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE)) { close(s); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.writeSnMR(s, protocol | flag); if (port != 0) { W5100.writeSnPORT(s, port); @@ -22,7 +23,7 @@ uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) } W5100.execCmdSn(s, Sock_OPEN); - + SPI.endTransaction(); return 1; } @@ -30,13 +31,24 @@ uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) } +uint8_t socketStatus(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + uint8_t status = W5100.readSnSR(s); + SPI.endTransaction(); + return status; +} + + /** * @brief This function close the socket and parameter is "s" which represent the socket number */ void close(SOCKET s) { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.execCmdSn(s, Sock_CLOSE); W5100.writeSnIR(s, 0xFF); + SPI.endTransaction(); } @@ -46,9 +58,13 @@ void close(SOCKET s) */ uint8_t listen(SOCKET s) { - if (W5100.readSnSR(s) != SnSR::INIT) + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + if (W5100.readSnSR(s) != SnSR::INIT) { + SPI.endTransaction(); return 0; + } W5100.execCmdSn(s, Sock_LISTEN); + SPI.endTransaction(); return 1; } @@ -70,9 +86,11 @@ uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port) return 0; // set destination IP + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.writeSnDIPR(s, addr); W5100.writeSnDPORT(s, port); W5100.execCmdSn(s, Sock_CONNECT); + SPI.endTransaction(); return 1; } @@ -85,7 +103,9 @@ uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port) */ void disconnect(SOCKET s) { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.execCmdSn(s, Sock_DISCON); + SPI.endTransaction(); } @@ -107,17 +127,21 @@ uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len) // if freebuf is available, start. do { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); freesize = W5100.getTXFreeSize(s); status = W5100.readSnSR(s); + SPI.endTransaction(); if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT)) { ret = 0; break; } + yield(); } while (freesize < ret); // copy data + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.send_data_processing(s, (uint8_t *)buf, ret); W5100.execCmdSn(s, Sock_SEND); @@ -127,12 +151,17 @@ uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len) /* m2008.01 [bj] : reduce code */ if ( W5100.readSnSR(s) == SnSR::CLOSED ) { + SPI.endTransaction(); close(s); return 0; } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); } /* +2008.01 bj */ W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); return ret; } @@ -146,6 +175,7 @@ uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len) int16_t recv(SOCKET s, uint8_t *buf, int16_t len) { // Check how much data is available + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); int16_t ret = W5100.getRXReceivedSize(s); if ( ret == 0 ) { @@ -172,6 +202,16 @@ int16_t recv(SOCKET s, uint8_t *buf, int16_t len) W5100.recv_data_processing(s, buf, ret); W5100.execCmdSn(s, Sock_RECV); } + SPI.endTransaction(); + return ret; +} + + +int16_t recvAvailable(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + int16_t ret = W5100.getRXReceivedSize(s); + SPI.endTransaction(); return ret; } @@ -183,8 +223,9 @@ int16_t recv(SOCKET s, uint8_t *buf, int16_t len) */ uint16_t peek(SOCKET s, uint8_t *buf) { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.recv_data_processing(s, buf, 1, 1); - + SPI.endTransaction(); return 1; } @@ -213,6 +254,7 @@ uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint1 } else { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.writeSnDIPR(s, addr); W5100.writeSnDPORT(s, port); @@ -227,12 +269,17 @@ uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint1 { /* +2008.01 [bj]: clear interrupt */ W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */ + SPI.endTransaction(); return 0; } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); } /* +2008.01 bj */ W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); } return ret; } @@ -252,11 +299,12 @@ uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t if ( len > 0 ) { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); ptr = W5100.readSnRX_RD(s); switch (W5100.readSnMR(s) & 0x07) { case SnMR::UDP : - W5100.read_data(s, (uint8_t *)ptr, head, 0x08); + W5100.read_data(s, ptr, head, 0x08); ptr += 8; // read peer's IP address, port number. addr[0] = head[0]; @@ -268,14 +316,14 @@ uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t data_len = head[6]; data_len = (data_len << 8) + head[7]; - W5100.read_data(s, (uint8_t *)ptr, buf, data_len); // data copy. + W5100.read_data(s, ptr, buf, data_len); // data copy. ptr += data_len; W5100.writeSnRX_RD(s, ptr); break; case SnMR::IPRAW : - W5100.read_data(s, (uint8_t *)ptr, head, 0x06); + W5100.read_data(s, ptr, head, 0x06); ptr += 6; addr[0] = head[0]; @@ -285,19 +333,19 @@ uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t data_len = head[4]; data_len = (data_len << 8) + head[5]; - W5100.read_data(s, (uint8_t *)ptr, buf, data_len); // data copy. + W5100.read_data(s, ptr, buf, data_len); // data copy. ptr += data_len; W5100.writeSnRX_RD(s, ptr); break; case SnMR::MACRAW: - W5100.read_data(s,(uint8_t*)ptr,head,2); + W5100.read_data(s, ptr, head, 2); ptr+=2; data_len = head[0]; data_len = (data_len<<8) + head[1] - 2; - W5100.read_data(s,(uint8_t*) ptr,buf,data_len); + W5100.read_data(s, ptr, buf, data_len); ptr += data_len; W5100.writeSnRX_RD(s, ptr); break; @@ -306,14 +354,20 @@ uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t break; } W5100.execCmdSn(s, Sock_RECV); + SPI.endTransaction(); } return data_len; } +/** + * @brief Wait for buffered transmission to complete. + */ +void flush(SOCKET s) { + // TODO +} uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len) { - uint8_t status=0; uint16_t ret=0; if (len > W5100.SSIZE) @@ -324,28 +378,34 @@ uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len) if (ret == 0) return 0; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.send_data_processing(s, (uint8_t *)buf, ret); W5100.execCmdSn(s, Sock_SEND); while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) { - status = W5100.readSnSR(s); if (W5100.readSnIR(s) & SnIR::TIMEOUT) { /* in case of igmp, if send fails, then socket closed */ /* if you want change, remove this code. */ + SPI.endTransaction(); close(s); return 0; } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); } W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); return ret; } uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len) { uint16_t ret =0; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); if (len > W5100.getTXFreeSize(s)) { ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size. @@ -355,6 +415,7 @@ uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len) ret = len; } W5100.send_data_processing_offset(s, offset, buf, ret); + SPI.endTransaction(); return ret; } @@ -370,14 +431,17 @@ int startUDP(SOCKET s, uint8_t* addr, uint16_t port) } else { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.writeSnDIPR(s, addr); W5100.writeSnDPORT(s, port); + SPI.endTransaction(); return 1; } } int sendUDP(SOCKET s) { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); W5100.execCmdSn(s, Sock_SEND); /* +2008.01 bj */ @@ -387,12 +451,17 @@ int sendUDP(SOCKET s) { /* +2008.01 [bj]: clear interrupt */ W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT)); + SPI.endTransaction(); return 0; } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); } /* +2008.01 bj */ W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); /* Sent ok */ return 1; diff --git a/libraries/Ethernet/utility/socket.h b/libraries/Ethernet/utility/socket.h old mode 100755 new mode 100644 index 45e0fb3e8e0..37ba8542471 --- a/libraries/Ethernet/utility/socket.h +++ b/libraries/Ethernet/utility/socket.h @@ -1,18 +1,21 @@ #ifndef _SOCKET_H_ #define _SOCKET_H_ -#include "w5100.h" +#include "utility/w5100.h" extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode) +extern uint8_t socketStatus(SOCKET s); extern void close(SOCKET s); // Close socket extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection) extern void disconnect(SOCKET s); // disconnect the connection extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection) extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP) extern int16_t recv(SOCKET s, uint8_t * buf, int16_t len); // Receive data (TCP) +extern int16_t recvAvailable(SOCKET s); extern uint16_t peek(SOCKET s, uint8_t *buf); extern uint16_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); // Send data (UDP/IP RAW) extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); // Receive data (UDP/IP RAW) +extern void flush(SOCKET s); // Wait for transmission to complete extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len); diff --git a/libraries/Ethernet/util.h b/libraries/Ethernet/utility/util.h similarity index 77% rename from libraries/Ethernet/util.h rename to libraries/Ethernet/utility/util.h index 5042e82e37f..33d32a97e7f 100644 --- a/libraries/Ethernet/util.h +++ b/libraries/Ethernet/utility/util.h @@ -1,7 +1,8 @@ #ifndef UTIL_H #define UTIL_H -#define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) ) +#define htons(x) ( ((x)<< 8 & 0xFF00) | \ + ((x)>> 8 & 0x00FF) ) #define ntohs(x) htons(x) #define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ diff --git a/libraries/Ethernet/utility/w5100.cpp b/libraries/Ethernet/utility/w5100.cpp index 9c748fd201d..c01f7612510 100644 --- a/libraries/Ethernet/utility/w5100.cpp +++ b/libraries/Ethernet/utility/w5100.cpp @@ -9,9 +9,8 @@ #include #include -#include -#include "w5100.h" +#include "utility/w5100.h" // W5100 controller instance W5100Class W5100; @@ -29,10 +28,11 @@ void W5100Class::init(void) SPI.begin(); initSS(); - + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); writeMR(1< RSIZE ) diff --git a/libraries/Ethernet/utility/w5100.h b/libraries/Ethernet/utility/w5100.h old mode 100755 new mode 100644 index 8dccd9f29a0..9f1de2a980a --- a/libraries/Ethernet/utility/w5100.h +++ b/libraries/Ethernet/utility/w5100.h @@ -10,9 +10,10 @@ #ifndef W5100_H_INCLUDED #define W5100_H_INCLUDED -#include #include +#define SPI_ETHERNET_SETTINGS SPISettings(4000000, MSBFIRST, SPI_MODE0) + #define MAX_SOCK_NUM 4 typedef uint8_t SOCKET; @@ -138,7 +139,7 @@ class W5100Class { * the data from Receive buffer. Here also take care of the condition while it exceed * the Rx memory uper-bound of socket. */ - void read_data(SOCKET s, volatile uint8_t * src, volatile uint8_t * dst, uint16_t len); + void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); /** * @brief This function is being called by send() and sendto() function also. @@ -340,7 +341,6 @@ class W5100Class { inline static void setSS() { PORTB &= ~_BV(2); }; inline static void resetSS() { PORTB |= _BV(2); }; #endif - }; extern W5100Class W5100; From 37115d03ef71f2cb74b9f18907e79cbcb7a989ec Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 15 Oct 2014 11:53:19 +0200 Subject: [PATCH 5/7] Backported SD library from 1.5.x --- libraries/SD/SD.cpp | 4 +- libraries/SD/examples/CardInfo/CardInfo.ino | 39 +++++----- .../SD/examples/Datalogger/Datalogger.ino | 25 +++--- libraries/SD/examples/DumpFile/DumpFile.ino | 23 +++--- libraries/SD/examples/Files/Files.ino | 29 +++---- libraries/SD/examples/ReadWrite/ReadWrite.ino | 43 +++++----- libraries/SD/examples/listfiles/listfiles.ino | 17 ++-- libraries/SD/utility/FatStructs.h | 10 +-- libraries/SD/utility/Sd2Card.cpp | 78 ++++++++++++++++--- libraries/SD/utility/Sd2Card.h | 7 ++ libraries/SD/utility/Sd2PinMap.h | 20 +++++ libraries/SD/utility/SdFat.h | 4 + libraries/SD/utility/SdFatUtil.h | 4 + libraries/SD/utility/SdFile.cpp | 14 +++- libraries/SD/utility/SdVolume.cpp | 2 +- 15 files changed, 212 insertions(+), 107 deletions(-) diff --git a/libraries/SD/SD.cpp b/libraries/SD/SD.cpp index c746809b6ec..65d32741c2c 100644 --- a/libraries/SD/SD.cpp +++ b/libraries/SD/SD.cpp @@ -550,9 +550,9 @@ boolean SDClass::mkdir(char *filepath) { boolean SDClass::rmdir(char *filepath) { /* - Makes a single directory or a heirarchy of directories. + Remove a single directory or a heirarchy of directories. - A rough equivalent to `mkdir -p`. + A rough equivalent to `rm -rf`. */ return walkPath(filepath, root, callback_rmdir); diff --git a/libraries/SD/examples/CardInfo/CardInfo.ino b/libraries/SD/examples/CardInfo/CardInfo.ino index 0c2dfc5e276..03bab2fd609 100644 --- a/libraries/SD/examples/CardInfo/CardInfo.ino +++ b/libraries/SD/examples/CardInfo/CardInfo.ino @@ -1,25 +1,26 @@ /* - SD card test - + SD card test + This example shows how use the utility libraries on which the' SD library is based in order to get info about your SD card. Very useful for testing a card when you're not sure whether its working or not. - + The circuit: * SD card attached to SPI bus as follows: ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila - ** CS - depends on your SD card shield or module. + ** CS - depends on your SD card shield or module. Pin 4 used here for consistency with other Arduino examples - + created 28 Mar 2011 - by Limor Fried + by Limor Fried modified 9 Apr 2012 by Tom Igoe */ - // include the SD library: +// include the SD library: +#include #include // set up variables using the SD utility library functions: @@ -31,22 +32,22 @@ SdFile root; // Arduino Ethernet shield: pin 4 // Adafruit SD shields and modules: pin 10 // Sparkfun SD shield: pin 8 -const int chipSelect = 4; +const int chipSelect = 4; void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("\nInitializing SD card..."); // On the Ethernet Shield, CS is pin 4. It's set as an output by default. - // Note that even if it's not used as the CS pin, the hardware SS pin - // (10 on most Arduino boards, 53 on the Mega) must be left as an output - // or the SD library functions will not work. + // Note that even if it's not used as the CS pin, the hardware SS pin + // (10 on most Arduino boards, 53 on the Mega) must be left as an output + // or the SD library functions will not work. pinMode(10, OUTPUT); // change this to 53 on a mega @@ -59,12 +60,12 @@ void setup() Serial.println("* did you change the chipSelect pin to match your shield or module?"); return; } else { - Serial.println("Wiring is correct and a card is present."); + Serial.println("Wiring is correct and a card is present."); } // print the type of card Serial.print("\nCard type: "); - switch(card.type()) { + switch (card.type()) { case SD_CARD_TYPE_SD1: Serial.println("SD1"); break; @@ -90,7 +91,7 @@ void setup() Serial.print("\nVolume type is FAT"); Serial.println(volume.fatType(), DEC); Serial.println(); - + volumesize = volume.blocksPerCluster(); // clusters are collections of blocks volumesize *= volume.clusterCount(); // we'll have a lot of clusters volumesize *= 512; // SD card blocks are always 512 bytes @@ -103,15 +104,15 @@ void setup() volumesize /= 1024; Serial.println(volumesize); - + Serial.println("\nFiles found on the card (name, date and size in bytes): "); root.openRoot(volume); - + // list all files in the card with date and size root.ls(LS_R | LS_DATE | LS_SIZE); } void loop(void) { - + } diff --git a/libraries/SD/examples/Datalogger/Datalogger.ino b/libraries/SD/examples/Datalogger/Datalogger.ino index a7f85eeaf84..70e8f70517e 100644 --- a/libraries/SD/examples/Datalogger/Datalogger.ino +++ b/libraries/SD/examples/Datalogger/Datalogger.ino @@ -1,9 +1,9 @@ /* SD card datalogger - - This example shows how to log data from three analog sensors + + This example shows how to log data from three analog sensors to an SD card using the SD library. - + The circuit: * analog sensors on analog ins 0, 1, and 2 * SD card attached to SPI bus as follows: @@ -11,15 +11,16 @@ ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 4 - + created 24 Nov 2010 modified 9 Apr 2012 by Tom Igoe - + This example code is in the public domain. - + */ +#include #include // On the Ethernet Shield, CS is pin 4. Note that even if it's not @@ -30,9 +31,9 @@ const int chipSelect = 4; void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -41,7 +42,7 @@ void setup() // make sure that the default chip select pin is set to // output, even if you don't use it: pinMode(10, OUTPUT); - + // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); @@ -61,7 +62,7 @@ void loop() int sensor = analogRead(analogPin); dataString += String(sensor); if (analogPin < 2) { - dataString += ","; + dataString += ","; } } @@ -75,11 +76,11 @@ void loop() dataFile.close(); // print to the serial port too: Serial.println(dataString); - } + } // if the file isn't open, pop up an error: else { Serial.println("error opening datalog.txt"); - } + } } diff --git a/libraries/SD/examples/DumpFile/DumpFile.ino b/libraries/SD/examples/DumpFile/DumpFile.ino index d83089af6c8..b2f510f58d7 100644 --- a/libraries/SD/examples/DumpFile/DumpFile.ino +++ b/libraries/SD/examples/DumpFile/DumpFile.ino @@ -1,25 +1,26 @@ /* SD card file dump - + This example shows how to read a file from the SD card using the SD library and send it over the serial port. - + The circuit: * SD card attached to SPI bus as follows: ** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 4 - + created 22 December 2010 by Limor Fried modified 9 Apr 2012 by Tom Igoe - + This example code is in the public domain. - + */ +#include #include // On the Ethernet Shield, CS is pin 4. Note that even if it's not @@ -30,9 +31,9 @@ const int chipSelect = 4; void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } @@ -41,7 +42,7 @@ void setup() // make sure that the default chip select pin is set to // output, even if you don't use it: pinMode(10, OUTPUT); - + // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); @@ -49,7 +50,7 @@ void setup() return; } Serial.println("card initialized."); - + // open the file. note that only one file can be open at a time, // so you have to close this one before opening another. File dataFile = SD.open("datalog.txt"); @@ -60,11 +61,11 @@ void setup() Serial.write(dataFile.read()); } dataFile.close(); - } + } // if the file isn't open, pop up an error: else { Serial.println("error opening datalog.txt"); - } + } } void loop() diff --git a/libraries/SD/examples/Files/Files.ino b/libraries/SD/examples/Files/Files.ino index a15b8626db2..d49539f38fb 100644 --- a/libraries/SD/examples/Files/Files.ino +++ b/libraries/SD/examples/Files/Files.ino @@ -1,40 +1,41 @@ /* SD card basic file example - - This example shows how to create and destroy an SD card file + + This example shows how to create and destroy an SD card file The circuit: * SD card attached to SPI bus as follows: ** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 4 - + created Nov 2010 by David A. Mellis modified 9 Apr 2012 by Tom Igoe - + This example code is in the public domain. - + */ +#include #include File myFile; void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); // On the Ethernet Shield, CS is pin 4. It's set as an output by default. - // Note that even if it's not used as the CS pin, the hardware SS pin - // (10 on most Arduino boards, 53 on the Mega) must be left as an output - // or the SD library functions will not work. + // Note that even if it's not used as the CS pin, the hardware SS pin + // (10 on most Arduino boards, 53 on the Mega) must be left as an output + // or the SD library functions will not work. pinMode(10, OUTPUT); if (!SD.begin(4)) { @@ -55,23 +56,23 @@ void setup() myFile = SD.open("example.txt", FILE_WRITE); myFile.close(); - // Check to see if the file exists: + // Check to see if the file exists: if (SD.exists("example.txt")) { Serial.println("example.txt exists."); } else { - Serial.println("example.txt doesn't exist."); + Serial.println("example.txt doesn't exist."); } // delete the file: Serial.println("Removing example.txt..."); SD.remove("example.txt"); - if (SD.exists("example.txt")){ + if (SD.exists("example.txt")) { Serial.println("example.txt exists."); } else { - Serial.println("example.txt doesn't exist."); + Serial.println("example.txt doesn't exist."); } } diff --git a/libraries/SD/examples/ReadWrite/ReadWrite.ino b/libraries/SD/examples/ReadWrite/ReadWrite.ino index 5805fc8d662..42d1de388c5 100644 --- a/libraries/SD/examples/ReadWrite/ReadWrite.ino +++ b/libraries/SD/examples/ReadWrite/ReadWrite.ino @@ -1,85 +1,86 @@ /* SD card read/write - - This example shows how to read and write data to and from an SD card file + + This example shows how to read and write data to and from an SD card file The circuit: * SD card attached to SPI bus as follows: ** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 4 - + created Nov 2010 by David A. Mellis modified 9 Apr 2012 by Tom Igoe - + This example code is in the public domain. - + */ - + +#include #include File myFile; void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); // On the Ethernet Shield, CS is pin 4. It's set as an output by default. - // Note that even if it's not used as the CS pin, the hardware SS pin - // (10 on most Arduino boards, 53 on the Mega) must be left as an output - // or the SD library functions will not work. - pinMode(10, OUTPUT); - + // Note that even if it's not used as the CS pin, the hardware SS pin + // (10 on most Arduino boards, 53 on the Mega) must be left as an output + // or the SD library functions will not work. + pinMode(10, OUTPUT); + if (!SD.begin(4)) { Serial.println("initialization failed!"); return; } Serial.println("initialization done."); - + // open the file. note that only one file can be open at a time, // so you have to close this one before opening another. myFile = SD.open("test.txt", FILE_WRITE); - + // if the file opened okay, write to it: if (myFile) { Serial.print("Writing to test.txt..."); myFile.println("testing 1, 2, 3."); - // close the file: + // close the file: myFile.close(); Serial.println("done."); } else { // if the file didn't open, print an error: Serial.println("error opening test.txt"); } - + // re-open the file for reading: myFile = SD.open("test.txt"); if (myFile) { Serial.println("test.txt:"); - + // read from the file until there's nothing else in it: while (myFile.available()) { - Serial.write(myFile.read()); + Serial.write(myFile.read()); } // close the file: myFile.close(); } else { - // if the file didn't open, print an error: + // if the file didn't open, print an error: Serial.println("error opening test.txt"); } } void loop() { - // nothing happens after setup + // nothing happens after setup } diff --git a/libraries/SD/examples/listfiles/listfiles.ino b/libraries/SD/examples/listfiles/listfiles.ino index 2bf8e68713c..22a79dd15f7 100644 --- a/libraries/SD/examples/listfiles/listfiles.ino +++ b/libraries/SD/examples/listfiles/listfiles.ino @@ -10,7 +10,7 @@ ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 4 - + created Nov 2010 by David A. Mellis modified 9 Apr 2012 @@ -19,8 +19,9 @@ by Scott Fitzgerald This example code is in the public domain. - + */ +#include #include File root; @@ -29,15 +30,15 @@ void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial) { + while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); // On the Ethernet Shield, CS is pin 4. It's set as an output by default. - // Note that even if it's not used as the CS pin, the hardware SS pin - // (10 on most Arduino boards, 53 on the Mega) must be left as an output - // or the SD library functions will not work. + // Note that even if it's not used as the CS pin, the hardware SS pin + // (10 on most Arduino boards, 53 on the Mega) must be left as an output + // or the SD library functions will not work. pinMode(10, OUTPUT); if (!SD.begin(4)) { @@ -47,9 +48,9 @@ void setup() Serial.println("initialization done."); root = SD.open("/"); - + printDirectory(root, 0); - + Serial.println("done!"); } diff --git a/libraries/SD/utility/FatStructs.h b/libraries/SD/utility/FatStructs.h index f5bdaa59466..8a2d9ebcc1c 100644 --- a/libraries/SD/utility/FatStructs.h +++ b/libraries/SD/utility/FatStructs.h @@ -90,7 +90,7 @@ struct partitionTable { uint32_t firstSector; /** Length of the partition, in blocks. */ uint32_t totalSectors; -}; +} __attribute__((packed)); /** Type name for partitionTable */ typedef struct partitionTable part_t; //------------------------------------------------------------------------------ @@ -114,7 +114,7 @@ struct masterBootRecord { uint8_t mbrSig0; /** Second MBR signature byte. Must be 0XAA */ uint8_t mbrSig1; -}; +} __attribute__((packed)); /** Type name for masterBootRecord */ typedef struct masterBootRecord mbr_t; //------------------------------------------------------------------------------ @@ -236,7 +236,7 @@ struct biosParmBlock { * should always set all of the bytes of this field to 0. */ uint8_t fat32Reserved[12]; -}; +} __attribute__((packed)); /** Type name for biosParmBlock */ typedef struct biosParmBlock bpb_t; //------------------------------------------------------------------------------ @@ -271,7 +271,7 @@ struct fat32BootSector { uint8_t bootSectorSig0; /** must be 0XAA */ uint8_t bootSectorSig1; -}; +} __attribute__((packed)); //------------------------------------------------------------------------------ // End Of Chain values for FAT entries /** FAT16 end of chain value used by Microsoft. */ @@ -366,7 +366,7 @@ struct directoryEntry { uint16_t firstClusterLow; /** 32-bit unsigned holding this file's size in bytes. */ uint32_t fileSize; -}; +} __attribute__((packed)); //------------------------------------------------------------------------------ // Definitions for directory entries // diff --git a/libraries/SD/utility/Sd2Card.cpp b/libraries/SD/utility/Sd2Card.cpp index 361cd0a06db..7e7cbf8ac48 100644 --- a/libraries/SD/utility/Sd2Card.cpp +++ b/libraries/SD/utility/Sd2Card.cpp @@ -17,20 +17,34 @@ * along with the Arduino Sd2Card Library. If not, see * . */ +#define USE_SPI_LIB #include #include "Sd2Card.h" //------------------------------------------------------------------------------ #ifndef SOFTWARE_SPI +#ifdef USE_SPI_LIB +#include +static SPISettings settings; +#endif // functions for hardware SPI /** Send a byte to the card */ static void spiSend(uint8_t b) { +#ifndef USE_SPI_LIB SPDR = b; - while (!(SPSR & (1 << SPIF))); + while (!(SPSR & (1 << SPIF))) + ; +#else + SPI.transfer(b); +#endif } /** Receive a byte from the card */ static uint8_t spiRec(void) { +#ifndef USE_SPI_LIB spiSend(0XFF); return SPDR; +#else + return SPI.transfer(0xFF); +#endif } #else // SOFTWARE_SPI //------------------------------------------------------------------------------ @@ -112,7 +126,8 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { spiSend(crc); // wait for response - for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++); + for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++) + ; return status_; } //------------------------------------------------------------------------------ @@ -144,9 +159,15 @@ uint32_t Sd2Card::cardSize(void) { //------------------------------------------------------------------------------ void Sd2Card::chipSelectHigh(void) { digitalWrite(chipSelectPin_, HIGH); +#ifdef USE_SPI_LIB + SPI.endTransaction(); +#endif } //------------------------------------------------------------------------------ void Sd2Card::chipSelectLow(void) { +#ifdef USE_SPI_LIB + SPI.beginTransaction(settings); +#endif digitalWrite(chipSelectPin_, LOW); } //------------------------------------------------------------------------------ @@ -219,12 +240,15 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { // set pin modes pinMode(chipSelectPin_, OUTPUT); - chipSelectHigh(); + digitalWrite(chipSelectPin_, HIGH); +#ifndef USE_SPI_LIB pinMode(SPI_MISO_PIN, INPUT); pinMode(SPI_MOSI_PIN, OUTPUT); pinMode(SPI_SCK_PIN, OUTPUT); +#endif #ifndef SOFTWARE_SPI +#ifndef USE_SPI_LIB // SS must be in output mode even it is not chip select pinMode(SS_PIN, OUTPUT); digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin @@ -232,10 +256,20 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // clear double speed SPSR &= ~(1 << SPI2X); -#endif // SOFTWARE_SPI +#else // USE_SPI_LIB + SPI.begin(); + settings = SPISettings(250000, MSBFIRST, SPI_MODE0); +#endif // USE_SPI_LIB +#endif // SOFTWARE_SPI // must supply min of 74 clock cycles with CS high. +#ifdef USE_SPI_LIB + SPI.beginTransaction(settings); +#endif for (uint8_t i = 0; i < 10; i++) spiSend(0XFF); +#ifdef USE_SPI_LIB + SPI.endTransaction(); +#endif chipSelectLow(); @@ -360,18 +394,21 @@ uint8_t Sd2Card::readData(uint32_t block, // skip data before offset for (;offset_ < offset; offset_++) { - while (!(SPSR & (1 << SPIF))); + while (!(SPSR & (1 << SPIF))) + ; SPDR = 0XFF; } // transfer data n = count - 1; for (uint16_t i = 0; i < n; i++) { - while (!(SPSR & (1 << SPIF))); + while (!(SPSR & (1 << SPIF))) + ; dst[i] = SPDR; SPDR = 0XFF; } // wait for last byte - while (!(SPSR & (1 << SPIF))); + while (!(SPSR & (1 << SPIF))) + ; dst[n] = SPDR; #else // OPTIMIZE_HARDWARE_SPI @@ -406,11 +443,13 @@ void Sd2Card::readEnd(void) { // optimize skip for hardware SPDR = 0XFF; while (offset_++ < 513) { - while (!(SPSR & (1 << SPIF))); + while (!(SPSR & (1 << SPIF))) + ; SPDR = 0XFF; } // wait for last crc byte - while (!(SPSR & (1 << SPIF))); + while (!(SPSR & (1 << SPIF))) + ; #else // OPTIMIZE_HARDWARE_SPI while (offset_++ < 514) spiRec(); #endif // OPTIMIZE_HARDWARE_SPI @@ -456,6 +495,7 @@ uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { error(SD_CARD_ERROR_SCK_RATE); return false; } +#ifndef USE_SPI_LIB // see avr processor datasheet for SPI register bit definitions if ((sckRateID & 1) || sckRateID == 6) { SPSR &= ~(1 << SPI2X); @@ -465,6 +505,17 @@ uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { SPCR &= ~((1 <. */ +#if defined(__arm__) // Arduino Due Board follows + +#ifndef Sd2PinMap_h +#define Sd2PinMap_h + +#include + +uint8_t const SS_PIN = SS; +uint8_t const MOSI_PIN = MOSI; +uint8_t const MISO_PIN = MISO; +uint8_t const SCK_PIN = SCK; + +#endif // Sd2PinMap_h + +#elif defined(__AVR__) // Other AVR based Boards follows + // Warning this file was generated by a program. #ifndef Sd2PinMap_h #define Sd2PinMap_h @@ -350,3 +366,7 @@ static inline __attribute__((always_inline)) } } #endif // Sd2PinMap_h + +#else +#error Architecture or board not supported. +#endif diff --git a/libraries/SD/utility/SdFat.h b/libraries/SD/utility/SdFat.h index 344326f982e..89c244418a6 100644 --- a/libraries/SD/utility/SdFat.h +++ b/libraries/SD/utility/SdFat.h @@ -23,7 +23,9 @@ * \file * SdFile and SdVolume classes */ +#ifdef __AVR__ #include +#endif #include "Sd2Card.h" #include "FatStructs.h" #include "Print.h" @@ -286,8 +288,10 @@ class SdFile : public Print { size_t write(uint8_t b); size_t write(const void* buf, uint16_t nbyte); size_t write(const char* str); +#ifdef __AVR__ void write_P(PGM_P str); void writeln_P(PGM_P str); +#endif //------------------------------------------------------------------------------ #if ALLOW_DEPRECATED_FUNCTIONS // Deprecated functions - suppress cpplint warnings with NOLINT comment diff --git a/libraries/SD/utility/SdFatUtil.h b/libraries/SD/utility/SdFatUtil.h index 7d6b4104f8d..d1b4d538f69 100644 --- a/libraries/SD/utility/SdFatUtil.h +++ b/libraries/SD/utility/SdFatUtil.h @@ -24,12 +24,14 @@ * Useful utility functions. */ #include +#ifdef __AVR__ #include /** Store and print a string in flash memory.*/ #define PgmPrint(x) SerialPrint_P(PSTR(x)) /** Store and print a string in flash memory followed by a CR/LF.*/ #define PgmPrintln(x) SerialPrintln_P(PSTR(x)) /** Defined so doxygen works for function definitions. */ +#endif #define NOINLINE __attribute__((noinline,unused)) #define UNUSEDOK __attribute__((unused)) //------------------------------------------------------------------------------ @@ -49,6 +51,7 @@ static UNUSEDOK int FreeRam(void) { } return free_memory; } +#ifdef __AVR__ //------------------------------------------------------------------------------ /** * %Print a string in flash memory to the serial port. @@ -68,4 +71,5 @@ static NOINLINE void SerialPrintln_P(PGM_P str) { SerialPrint_P(str); Serial.println(); } +#endif // __AVR__ #endif // #define SdFatUtil_h diff --git a/libraries/SD/utility/SdFile.cpp b/libraries/SD/utility/SdFile.cpp index e786f56bb94..e7b6f0971ce 100644 --- a/libraries/SD/utility/SdFile.cpp +++ b/libraries/SD/utility/SdFile.cpp @@ -17,8 +17,10 @@ * along with the Arduino SdFat Library. If not, see * . */ -#include +#include "SdFat.h" +#ifdef __AVR__ #include +#endif #include //------------------------------------------------------------------------------ // callback function for date/time @@ -256,9 +258,15 @@ uint8_t SdFile::make83Name(const char* str, uint8_t* name) { i = 8; // place for extension } else { // illegal FAT characters - PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); uint8_t b; +#if defined(__AVR__) + PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); while ((b = pgm_read_byte(p++))) if (b == c) return false; +#elif defined(__arm__) + const uint8_t valid[] = "|<>^+=?/[];,*\"\\"; + const uint8_t *p = valid; + while ((b = *p++)) if (b == c) return false; +#endif // check size and only allow ASCII printable characters if (i > n || c < 0X21 || c > 0X7E)return false; // only upper case allowed in 8.3 names - convert lower to upper @@ -1232,6 +1240,7 @@ size_t SdFile::write(uint8_t b) { size_t SdFile::write(const char* str) { return write(str, strlen(str)); } +#ifdef __AVR__ //------------------------------------------------------------------------------ /** * Write a PROGMEM string to a file. @@ -1251,3 +1260,4 @@ void SdFile::writeln_P(PGM_P str) { write_P(str); println(); } +#endif diff --git a/libraries/SD/utility/SdVolume.cpp b/libraries/SD/utility/SdVolume.cpp index ece4acbac4e..2fbb8100b9b 100644 --- a/libraries/SD/utility/SdVolume.cpp +++ b/libraries/SD/utility/SdVolume.cpp @@ -17,7 +17,7 @@ * along with the Arduino SdFat Library. If not, see * . */ -#include +#include "SdFat.h" //------------------------------------------------------------------------------ // raw block cache // init cacheBlockNumber_to invalid SD block number From 20ca43646aa871dd6083f112989048dc7c702d60 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Thu, 20 Nov 2014 18:54:04 -0800 Subject: [PATCH 6/7] Fix SPI transaction mismatch errors --- libraries/SD/utility/Sd2Card.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libraries/SD/utility/Sd2Card.cpp b/libraries/SD/utility/Sd2Card.cpp index 7e7cbf8ac48..a72d3d2712d 100644 --- a/libraries/SD/utility/Sd2Card.cpp +++ b/libraries/SD/utility/Sd2Card.cpp @@ -157,16 +157,24 @@ uint32_t Sd2Card::cardSize(void) { } } //------------------------------------------------------------------------------ +static uint8_t chip_select_asserted = 0; + void Sd2Card::chipSelectHigh(void) { digitalWrite(chipSelectPin_, HIGH); #ifdef USE_SPI_LIB - SPI.endTransaction(); + if (chip_select_asserted) { + chip_select_asserted = 0; + SPI.endTransaction(); + } #endif } //------------------------------------------------------------------------------ void Sd2Card::chipSelectLow(void) { #ifdef USE_SPI_LIB - SPI.beginTransaction(settings); + if (!chip_select_asserted) { + chip_select_asserted = 1; + SPI.beginTransaction(settings); + } #endif digitalWrite(chipSelectPin_, LOW); } From ae402c29073433db34afd0440b68f8b3ebc91141 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 15 Oct 2014 13:23:45 +0200 Subject: [PATCH 7/7] Update revision log --- build/shared/revisions.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/build/shared/revisions.txt b/build/shared/revisions.txt index c3e3eab45be..e960fd3725f 100644 --- a/build/shared/revisions.txt +++ b/build/shared/revisions.txt @@ -2,12 +2,16 @@ ARDUINO 1.0.7 [libraries] -* Backported GSM from IDE 1.5.x -* EthernetClien: use IANA recommended ephemeral port range, 49152-65535 (Jack Christensen, cifer-lee) +* Backported SPI Transaction API from IDE 1.5.x (Paul Stoffregen) +* Backported GSM from IDE 1.5.x: fix build regression +* Backported Ethernet from IDE 1.5.x +* Backported SD from IDE 1.5.x +* Backported SPI from IDE 1.5.x +* EthernetClient: use IANA recommended ephemeral port range, 49152-65535 (Jack Christensen, cifer-lee) [core] * Fixed missing NOT_AN_INTERRUPT constant in digitalPinToInterrupt() macro -* Fixed regression in HardwareSerial::available() introduced with https://github.com/arduino/Arduino/pull/2057 +* Fixed performance regression in HardwareSerial::available() introduced with https://github.com/arduino/Arduino/pull/2057 ARDUINO 1.0.6 - 2014.09.16