Maple STM32F1 added
This commit is contained in:
parent
c092796599
commit
fe80cc35c4
3 changed files with 214 additions and 37 deletions
|
|
@ -27,7 +27,7 @@
|
|||
#include "utility/FatLib.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** SdFat version YYYYMMDD */
|
||||
#define SD_FAT_VERSION 20150321
|
||||
#define SD_FAT_VERSION 20150324
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdBaseFile
|
||||
|
|
|
|||
171
SdFat/SdSpiSTM32F1.cpp
Normal file
171
SdFat/SdSpiSTM32F1.cpp
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue