Browse Source

Maple STM32F1 added

Bill Greiman 10 years ago
parent
commit
fe80cc35c4
3 changed files with 214 additions and 37 deletions
  1. 1 1
      SdFat/SdFat.h
  2. 171 0
      SdFat/SdSpiSTM32F1.cpp
  3. 42 36
      SdFat/utility/DigitalPin.h

+ 1 - 1
SdFat/SdFat.h

@@ -27,7 +27,7 @@
 #include "utility/FatLib.h"
 //------------------------------------------------------------------------------
 /** SdFat version YYYYMMDD */
-#define SD_FAT_VERSION 20150321
+#define SD_FAT_VERSION 20150324
 //==============================================================================
 /**
  * \class SdBaseFile

+ 171 - 0
SdFat/SdSpiSTM32F1.cpp

@@ -0,0 +1,171 @@
+/* Arduino SdSpi Library
+ * Copyright (C) 2013 by William Greiman
+ *
+ * STM32F1 code for Maple and Maple Mini support, 2015 by Victor Perez
+ *
+ * This file is part of the Arduino SdSpi Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdSpi Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#if defined(__STM32F1__)
+#include "SdSpi.h"
+#include <SPI.h>
+#include <libmaple/dma.h>
+/** Use STM32 DMAC if nonzero */
+#define USE_STM32F1_DMAC 1
+/** Time in ms for DMA receive timeout */
+#define STM32F1_DMA_TIMEOUT 100
+/** DMAC receive channel */
+#define SPI1_DMAC_RX_CH  DMA_CH2
+/** DMAC transmit channel */
+#define SPI1_DMAC_TX_CH  DMA_CH3
+
+volatile bool SPI_DMA_TX_Active = false;
+volatile bool SPI_DMA_RX_Active = false;
+
+/** ISR for DMA TX event. */
+inline void SPI_DMA_TX_Event() {
+  SPI_DMA_TX_Active = false;
+  dma_disable(DMA1, SPI_DMAC_TX_CH);
+}
+
+/** ISR for DMA RX event. */
+inline void SPI_DMA_RX_Event() {
+  SPI_DMA_RX_Active = false;
+  dma_disable(DMA1, SPI1_DMAC_RX_CH);
+}
+//------------------------------------------------------------------------------
+
+/** Disable DMA Channel. */
+static void dmac_channel_disable(dma_channel ul_num) {
+  dma_disable(DMA1, ul_num);
+}
+/** Enable DMA Channel. */
+static void dmac_channel_enable(dma_channel ul_num) {
+  dma_enable(DMA1, ul_num);
+}
+//------------------------------------------------------------------------------
+void SdSpi::begin() {
+  SPI.begin();
+}
+//------------------------------------------------------------------------------
+// start RX DMA
+
+static void spiDmaRX(uint8_t* dst, uint16_t count) {
+//  spi_rx_dma_enable(SPI1);
+  if (count < 1) return;
+  dma_setup_transfer(DMA1, SPI1_DMAC_RX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS,
+                     dst, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));
+  dma_set_num_transfers(DMA1, SPI1_DMAC_RX_CH, count);  // 2 bytes per pixel
+  SPI_DMA_RX_Active = true;
+  dma_enable(DMA1, SPI1_DMAC_RX_CH);
+}
+//------------------------------------------------------------------------------
+// start TX DMA
+static void spiDmaTX(const uint8_t* src, uint16_t count) {
+  if (count < 1) return;
+  static uint8_t ff = 0XFF;
+
+  if (!src) {
+    src = &ff;
+    dma_setup_transfer(DMA1, SPI1_DMAC_TX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS,
+                       const_cast<uint8_t*>(src), DMA_SIZE_8BITS,
+                      (DMA_FROM_MEM | DMA_TRNS_CMPLT));
+  } else {
+    dma_setup_transfer(DMA1, SPI1_DMAC_TX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS,
+                       const_cast<uint8_t*>(src), DMA_SIZE_8BITS,
+                      (DMA_MINC_MODE  |  DMA_FROM_MEM | DMA_TRNS_CMPLT));
+  }
+  dma_set_num_transfers(DMA1, SPI1_DMAC_TX_CH, count);  // 2 bytes per pixel
+  SPI_DMA_TX_Active = true;
+  dma_enable(DMA1, SPI1_DMAC_TX_CH);
+}
+//------------------------------------------------------------------------------
+//  initialize SPI controller STM32F1
+void SdSpi::init(uint8_t sckDivisor) {
+  if (sckDivisor < SPI_CLOCK_DIV2 || sckDivisor > SPI_CLOCK_DIV256) {
+    sckDivisor = SPI_CLOCK_DIV2;  // may not be needed, testing.
+  }
+  SPI.setClockDivider(sckDivisor);
+  SPI.setBitOrder(MSBFIRST);
+  SPI.setDataMode(SPI_MODE0);
+
+#if USE_STM32F1_DMAC
+  dma_init(DMA1);
+  dma_attach_interrupt(DMA1, SPI1_DMAC_TX_CH, SPI_DMA_TX_Event);
+  dma_attach_interrupt(DMA1, SPI1_DMAC_RX_CH, SPI_DMA_RX_Event);
+  spi_tx_dma_enable(SPI1);
+  spi_rx_dma_enable(SPI1);
+#endif  // USE_STM32F1_DMAC
+}
+//------------------------------------------------------------------------------
+// STM32
+static inline uint8_t spiTransfer(uint8_t b) {
+  return SPI.transfer(b);
+}
+//------------------------------------------------------------------------------
+// should be valid for STM32
+/** SPI receive a byte */
+uint8_t SdSpi::receive() {
+  return spiTransfer(0xFF);
+}
+//------------------------------------------------------------------------------
+/** SPI receive multiple bytes */
+// check and finish.
+
+uint8_t SdSpi::receive(uint8_t* buf, size_t n) {
+  int rtn = 0;
+
+#if USE_STM32F1_DMAC
+
+  spiDmaRX(buf, n);
+  spiDmaTX(0, n);
+
+  uint32_t m = millis();
+  while (SPI_DMA_RX_Active) {
+    if ((millis() - m) > STM32F1_DMA_TIMEOUT)  {
+      dmac_channel_disable(SPI_DMAC_RX_CH);
+      dmac_channel_disable(SPI_DMAC_TX_CH);
+      rtn = 2;
+      break;
+    }
+  }
+
+#else  // USE_STM32F1_DMAC
+  for (size_t i = 0; i < n; i++) {
+    buf[i] = SPI.transfer(0xFF);
+  }
+#endif  // USE_STM32F1_DMAC
+  return rtn;
+}
+//------------------------------------------------------------------------------
+/** SPI send a byte */
+void SdSpi::send(uint8_t b) {
+  spiTransfer(b);
+}
+//------------------------------------------------------------------------------
+void SdSpi::send(const uint8_t* buf , size_t n) {
+#if USE_STM32F1_DMAC
+  spiDmaTX(buf, n);
+  while (SPI_DMA_TX_Active) {}
+
+#else  // #if USE_STM32F1_DMAC
+  SPI.write(buf, n);
+#endif  // #if USE_STM32F1_DMAC
+  // leave RX register empty
+  //  while (spi_is_rx_nonempty(SPI1))
+  uint8_t b = spi_rx_reg(SPI1);
+}
+#endif  // USE_NATIVE_STM32F1_SPI

+ 42 - 36
SdFat/utility/DigitalPin.h

@@ -213,41 +213,47 @@ static const pin_map_t pinMap[] = {
 
 #ifdef PORT_D0
 // Newer version of 1284P
- static const pin_map_t pinMap[] = { 
-  {PORT_TO_MODE(PORT_D0), PORT_TO_INPUT(PORT_D0), PORT_TO_OUTPUT(PORT_D0),  BIT_D0},
-  {PORT_TO_MODE(PORT_D1), PORT_TO_INPUT(PORT_D1), PORT_TO_OUTPUT(PORT_D1),  BIT_D1},
-  {PORT_TO_MODE(PORT_D2), PORT_TO_INPUT(PORT_D2), PORT_TO_OUTPUT(PORT_D2),  BIT_D2},
-  {PORT_TO_MODE(PORT_D3), PORT_TO_INPUT(PORT_D3), PORT_TO_OUTPUT(PORT_D3),  BIT_D3},
-  {PORT_TO_MODE(PORT_D4), PORT_TO_INPUT(PORT_D4), PORT_TO_OUTPUT(PORT_D4),  BIT_D4},
-  {PORT_TO_MODE(PORT_D5), PORT_TO_INPUT(PORT_D5), PORT_TO_OUTPUT(PORT_D5),  BIT_D5},
-  {PORT_TO_MODE(PORT_D6), PORT_TO_INPUT(PORT_D6), PORT_TO_OUTPUT(PORT_D6),  BIT_D6},
-  {PORT_TO_MODE(PORT_D7), PORT_TO_INPUT(PORT_D7), PORT_TO_OUTPUT(PORT_D7),  BIT_D7},
-  {PORT_TO_MODE(PORT_D8), PORT_TO_INPUT(PORT_D8), PORT_TO_OUTPUT(PORT_D8),  BIT_D8},
-  {PORT_TO_MODE(PORT_D9), PORT_TO_INPUT(PORT_D9), PORT_TO_OUTPUT(PORT_D9),  BIT_D9},
-  {PORT_TO_MODE(PORT_D10), PORT_TO_INPUT(PORT_D10), PORT_TO_OUTPUT(PORT_D10),  BIT_D10},
-  {PORT_TO_MODE(PORT_D11), PORT_TO_INPUT(PORT_D11), PORT_TO_OUTPUT(PORT_D11),  BIT_D11},
-  {PORT_TO_MODE(PORT_D12), PORT_TO_INPUT(PORT_D12), PORT_TO_OUTPUT(PORT_D12),  BIT_D12},
-  {PORT_TO_MODE(PORT_D13), PORT_TO_INPUT(PORT_D13), PORT_TO_OUTPUT(PORT_D13),  BIT_D13},
-  {PORT_TO_MODE(PORT_D14), PORT_TO_INPUT(PORT_D14), PORT_TO_OUTPUT(PORT_D14),  BIT_D14},
-  {PORT_TO_MODE(PORT_D15), PORT_TO_INPUT(PORT_D15), PORT_TO_OUTPUT(PORT_D15),  BIT_D15},
-  {PORT_TO_MODE(PORT_D16), PORT_TO_INPUT(PORT_D16), PORT_TO_OUTPUT(PORT_D16),  BIT_D16},
-  {PORT_TO_MODE(PORT_D17), PORT_TO_INPUT(PORT_D17), PORT_TO_OUTPUT(PORT_D17),  BIT_D17},
-  {PORT_TO_MODE(PORT_D18), PORT_TO_INPUT(PORT_D18), PORT_TO_OUTPUT(PORT_D18),  BIT_D18},
-  {PORT_TO_MODE(PORT_D19), PORT_TO_INPUT(PORT_D19), PORT_TO_OUTPUT(PORT_D19),  BIT_D19},
-  {PORT_TO_MODE(PORT_D20), PORT_TO_INPUT(PORT_D20), PORT_TO_OUTPUT(PORT_D20),  BIT_D20},
-  {PORT_TO_MODE(PORT_D21), PORT_TO_INPUT(PORT_D21), PORT_TO_OUTPUT(PORT_D21),  BIT_D21},
-  {PORT_TO_MODE(PORT_D22), PORT_TO_INPUT(PORT_D22), PORT_TO_OUTPUT(PORT_D22),  BIT_D22},
-  {PORT_TO_MODE(PORT_D23), PORT_TO_INPUT(PORT_D23), PORT_TO_OUTPUT(PORT_D23),  BIT_D23},
-  {PORT_TO_MODE(PORT_D24), PORT_TO_INPUT(PORT_D24), PORT_TO_OUTPUT(PORT_D24),  BIT_D24},
-  {PORT_TO_MODE(PORT_D25), PORT_TO_INPUT(PORT_D25), PORT_TO_OUTPUT(PORT_D25),  BIT_D25},
-  {PORT_TO_MODE(PORT_D26), PORT_TO_INPUT(PORT_D26), PORT_TO_OUTPUT(PORT_D26),  BIT_D26},
-  {PORT_TO_MODE(PORT_D27), PORT_TO_INPUT(PORT_D27), PORT_TO_OUTPUT(PORT_D27),  BIT_D27},
-  {PORT_TO_MODE(PORT_D28), PORT_TO_INPUT(PORT_D28), PORT_TO_OUTPUT(PORT_D28),  BIT_D28},
-  {PORT_TO_MODE(PORT_D29), PORT_TO_INPUT(PORT_D29), PORT_TO_OUTPUT(PORT_D29),  BIT_D29},
-  {PORT_TO_MODE(PORT_D30), PORT_TO_INPUT(PORT_D30), PORT_TO_OUTPUT(PORT_D30),  BIT_D30},
-  {PORT_TO_MODE(PORT_D31), PORT_TO_INPUT(PORT_D31), PORT_TO_OUTPUT(PORT_D31),  BIT_D31}
+#define DPM(x) {PORT_TO_MODE(PORT_D##x), PORT_TO_INPUT(PORT_D##x), \
+                PORT_TO_OUTPUT(PORT_D##x), BIT_D##x}
+
+static const pin_map_t pinMap[] = {
+  DPM(0),
+  DPM(1),
+  DPM(2),
+  DPM(3),
+  DPM(4),
+  DPM(5),
+  DPM(6),
+  DPM(7),
+  DPM(8),
+  DPM(9),
+  DPM(10),
+  DPM(11),
+  DPM(12),
+  DPM(13),
+  DPM(14),
+  DPM(15),
+  DPM(16),
+  DPM(17),
+  DPM(18),
+  DPM(19),
+  DPM(20),
+  DPM(21),
+  DPM(22),
+  DPM(23),
+  DPM(24),
+  DPM(25),
+  DPM(26),
+  DPM(27),
+  DPM(28),
+  DPM(29),
+  DPM(30),
+  DPM(31)
 };
-#elif analogInputToDigitalPin(0)==24
+
+#undef DPM
+
+#elif analogInputToDigitalPin(0) == 24
 // Mighty Layout
 static const pin_map_t pinMap[] = {
   {&DDRB, &PINB, &PORTB, 0},  // B0  0
@@ -283,7 +289,7 @@ static const pin_map_t pinMap[] = {
   {&DDRA, &PINA, &PORTA, 6},  // A6 30
   {&DDRA, &PINA, &PORTA, 7}   // A7 31
 };
-#elif analogInputToDigitalPin(0)==21
+#elif analogInputToDigitalPin(0) == 21
 // Bobuino Layout
 static const pin_map_t pinMap[] = {
   {&DDRD, &PIND, &PORTD, 0},  // D0  0
@@ -319,7 +325,7 @@ static const pin_map_t pinMap[] = {
   {&DDRD, &PIND, &PORTD, 4},  // D4 30
   {&DDRD, &PIND, &PORTD, 7}   // D7 31
 };
-#elif analogInputToDigitalPin(0)==31
+#elif analogInputToDigitalPin(0) == 31
 // Standard Layout
 static const pin_map_t pinMap[] = {
   {&DDRB, &PINB, &PORTB, 0},  // B0  0