From eca1341c7b6fef097ff07b51020a18eac88a9353 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Wed, 8 Oct 2014 11:17:24 +0200
Subject: [PATCH]  Limit SPI max clock speed to 12Mhz

SAMD21G18A doesn't operate correctly with clock dividers lower than 4
---
 libraries/SPI/SPI.cpp |  6 +++++-
 libraries/SPI/SPI.h   | 14 ++++++++++++--
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp
index 4f520a27..29ecbcb6 100644
--- a/libraries/SPI/SPI.cpp
+++ b/libraries/SPI/SPI.cpp
@@ -97,7 +97,11 @@ void SPIClass::setDataMode(uint8_t mode)
 
 void SPIClass::setClockDivider(uint8_t div)
 {
-	_p_sercom->setBaudrateSPI(div);
+  if (div < SPI_MIN_CLOCK_DIVIDER) {
+    _p_sercom->setBaudrateSPI(SPI_MIN_CLOCK_DIVIDER);
+  } else {
+    _p_sercom->setBaudrateSPI(div);
+  }
 }
 
 byte SPIClass::transfer(uint8_t data)
diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h
index 02ac74f3..6473ab23 100644
--- a/libraries/SPI/SPI.h
+++ b/libraries/SPI/SPI.h
@@ -18,6 +18,16 @@
 #define SPI_MODE2 0x03
 #define SPI_MODE3 0x01
 
+#if defined(__SAMD21G18A__)
+  // Even if not specified on the datasheet, the SAMD21G18A MCU
+  // doesn't operate correctly with clock dividers lower than 4.
+  // This allows a theoretical maximum SPI clock speed of 12Mhz
+  #define SPI_MIN_CLOCK_DIVIDER 4
+  // Other SAMD21xxxxx MCU may be affected as well
+#else
+  #define SPI_MIN_CLOCK_DIVIDER 2
+#endif
+
 class SPISettings {
   public:
 	SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
@@ -36,8 +46,8 @@ class SPISettings {
 		uint8_t div;
 		if (clock < (F_CPU / 255)) {
 			div = 255;
-		} else if (clock >= (F_CPU / 2)) {
-			div = 2;
+		} else if (clock >= (F_CPU / SPI_MIN_CLOCK_DIVIDER)) {
+			div = SPI_MIN_CLOCK_DIVIDER;
 		} else {
 			div = (F_CPU / (clock + 1)) + 1;
 		}
-- 
GitLab