1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

fix use SPI.beginTransaction crash

This commit is contained in:
Markus Sattler 2015-05-07 19:25:25 +02:00
parent 8b114a551e
commit 163858dc44
3 changed files with 95 additions and 76 deletions

View File

@ -227,6 +227,13 @@ FlashMode_t EspClass::getFlashChipMode(void)
*/ */
uint32_t EspClass::getFlashChipSizeByChipId(void) { uint32_t EspClass::getFlashChipSizeByChipId(void) {
uint32_t chipId = getFlashChipId(); uint32_t chipId = getFlashChipId();
/**
* Chip ID
* 00 - always 00 (Chip ID use only 3 byte)
* 17 - ? looks like 2^xx is size in Byte ? //todo: find docu to this
* 40 - ? may be Speed ? //todo: find docu to this
* C8 - manufacturer ID
*/
switch(chipId) { switch(chipId) {
// GigaDevice // GigaDevice

View File

@ -1,79 +1,117 @@
/* /*
SPI.cpp - SPI library for esp8266 SPI.cpp - SPI library for esp8266
Copyright (c) 2015 Hristo Gochkov. All rights reserved. Copyright (c) 2015 Hristo Gochkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment. This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. 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, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "SPI.h" #include "SPI.h"
#include "HardwareSerial.h"
typedef struct {
uint32_t divider;
uint32_t regValue;
} spiClockDiv_t;
static const spiClockDiv_t spiClockDiv[] = {
{ 0, (0x80000000) }, ///< @80Mhz = 80 MHz @160Mhz = 160 MHz
{ 2, (0x00001001) }, ///< @80Mhz = 40 MHz @160Mhz = 80 MHz
{ 4, (0x00041001) }, ///< @80Mhz = 20 MHz @160Mhz = 40 MHz
{ 6, (0x000fffc0) }, ///< @80Mhz = 16 MHz @160Mhz = 32 MHz
{ 8, (0x000c1001) }, ///< @80Mhz = 10 MHz @160Mhz = 20 MHz
{ 10, (0x00101001) }, ///< @80Mhz = 8 MHz @160Mhz = 16 MHz
{ 16, (0x001c1001) }, ///< @80Mhz = 5 MHz @160Mhz = 10 MHz
{ 20, (0x00241001) }, ///< @80Mhz = 4 MHz @160Mhz = 8 MHz
{ 40, (0x004c1001) }, ///< @80Mhz = 2 MHz @160Mhz = 4 MHz
{ 80, (0x009c1001) }, ///< @80Mhz = 1 MHz @160Mhz = 2 MHz
{ 160, (0x013c1001) }, ///< @80Mhz = 500 KHz @160Mhz = 1 MHz
{ 320, (0x027c1001) }, ///< @80Mhz = 250 KHz @160Mhz = 500 KHz
{ 640, (0x04fc1001) } ///< @80Mhz = 125 KHz @160Mhz = 250 KHz
};
static const uint8_t spiClockDiv_count = (sizeof(spiClockDiv) / sizeof(spiClockDiv_t));
SPIClass SPI; SPIClass SPI;
SPIClass::SPIClass(){} SPIClass::SPIClass() {
}
void SPIClass::begin(){ void SPIClass::begin() {
pinMode(SCK, SPECIAL); pinMode(SCK, SPECIAL); ///< GPIO14
pinMode(MISO, SPECIAL); pinMode(MISO, SPECIAL); ///< GPIO12
pinMode(MOSI, SPECIAL); pinMode(MOSI, SPECIAL); ///< GPIO13
GPMUX = 0x105; GPMUX = 0x105; // note crash if spi flash Frequency < 40MHz
SPI1C = 0; SPI1C = 0;
SPI1CLK = SPI_CLOCK_DIV16;//1MHz setFrequency(1000000); ///< 1Mhz
SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE;
SPI1U1 = (7 << SPILMOSI) | (7 << SPILMISO); SPI1U1 = (7 << SPILMOSI) | (7 << SPILMISO);
SPI1C1 = 0; SPI1C1 = 0;
} }
void SPIClass::end() { void SPIClass::end() {
pinMode(SCK, INPUT); pinMode(SCK, INPUT);
pinMode(MISO, INPUT); pinMode(MISO, INPUT);
pinMode(MOSI, INPUT); pinMode(MOSI, INPUT);
} }
void SPIClass::beginTransaction(SPISettings settings) { void SPIClass::beginTransaction(SPISettings settings) {
setClockDivider(settings._clock); setFrequency(settings._clock);
setBitOrder(settings._bitOrder); setBitOrder(settings._bitOrder);
setDataMode(settings._dataMode); setDataMode(settings._dataMode);
} }
void SPIClass::endTransaction() {} void SPIClass::endTransaction() {
}
void SPIClass::setDataMode(uint8_t dataMode) { void SPIClass::setDataMode(uint8_t dataMode) {
// todo find way to set
} }
void SPIClass::setBitOrder(uint8_t bitOrder) { void SPIClass::setBitOrder(uint8_t bitOrder) {
if (bitOrder == MSBFIRST) { if(bitOrder == MSBFIRST) {
SPI1C &= ~(SPICWBO | SPICRBO); SPI1C &= ~(SPICWBO | SPICRBO);
} else { } else {
SPI1C |= (SPICWBO | SPICRBO); SPI1C |= (SPICWBO | SPICRBO);
} }
}
void SPIClass::setFrequency(uint32_t freq) {
uint8_t i = 0;
// find the best match
if(freq < F_CPU) {
for(i = 1; i < (spiClockDiv_count-1); i++) {
if(freq >= (F_CPU/spiClockDiv[i].divider)) {
break;
}
}
}
setClockDivider(spiClockDiv[i].regValue);
} }
void SPIClass::setClockDivider(uint32_t clockDiv) { void SPIClass::setClockDivider(uint32_t clockDiv) {
SPI1CLK = clockDiv; SPI1CLK = clockDiv;
} }
uint8_t SPIClass::transfer(uint8_t data) { uint8_t SPIClass::transfer(uint8_t data) {
while(SPI1CMD & SPIBUSY); while(SPI1CMD & SPIBUSY);
SPI1W0 = data; SPI1W0 = data;
SPI1CMD |= SPIBUSY; SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY); while(SPI1CMD & SPIBUSY);
return (uint8_t)(SPI1W0 & 0xff); return (uint8_t) (SPI1W0 & 0xff);
} }
uint16_t SPIClass::transfer16(uint16_t data) { uint16_t SPIClass::transfer16(uint16_t data) {

View File

@ -26,35 +26,8 @@
#define FCPU80 80000000L #define FCPU80 80000000L
#if F_CPU == FCPU80
#define SPI_CLOCK_DIV80M 0x80000000 //80 MHz
#define SPI_CLOCK_DIV40M 0x00001001 //40 MHz
#define SPI_CLOCK_DIV20M 0x00041001 //20 MHz
#define SPI_CLOCK_DIV16M 0x000fffc0 //16 MHz
#define SPI_CLOCK_DIV10M 0x000c1001 //10 MHz
#define SPI_CLOCK_DIV2 0x00101001 //8 MHz
#define SPI_CLOCK_DIV5M 0x001c1001 //5 MHz
#define SPI_CLOCK_DIV4 0x00241001 //4 MHz
#define SPI_CLOCK_DIV8 0x004c1001 //2 MHz
#define SPI_CLOCK_DIV16 0x009c1001 //1 MHz
#define SPI_CLOCK_DIV32 0x013c1001 //500 KHz
#define SPI_CLOCK_DIV64 0x027c1001 //250 KHz
#define SPI_CLOCK_DIV128 0x04fc1001 //125 KHz
#else
#define SPI_CLOCK_DIV160M 0x80000000 //160 MHz
#define SPI_CLOCK_DIV80M 0x00001001 //80 MHz
#define SPI_CLOCK_DIV40M 0x00041001 //40 MHz
#define SPI_CLOCK_DIV32M 0x000fffc0 //32 MHz
#define SPI_CLOCK_DIV20M 0x000c1001 //20 MHz
#define SPI_CLOCK_DIV16M 0x00101001 //16 MHz
#define SPI_CLOCK_DIV10M 0x001c1001 //10 MHz
#define SPI_CLOCK_DIV2 0x00241001 //8 MHz
#define SPI_CLOCK_DIV4 0x004c1001 //4 MHz
#define SPI_CLOCK_DIV8 0x009c1001 //2 MHz
#define SPI_CLOCK_DIV16 0x013c1001 //1 MHz
#define SPI_CLOCK_DIV32 0x027c1001 //500 KHz
#define SPI_CLOCK_DIV64 0x04fc1001 //250 KHz
#endif
const uint8_t SPI_MODE0 = 0x00; const uint8_t SPI_MODE0 = 0x00;
const uint8_t SPI_MODE1 = 0x04; const uint8_t SPI_MODE1 = 0x04;
@ -63,7 +36,7 @@ const uint8_t SPI_MODE3 = 0x0C;
class SPISettings { class SPISettings {
public: public:
SPISettings() :_clock(SPI_CLOCK_DIV16), _bitOrder(LSBFIRST), _dataMode(SPI_MODE0){} SPISettings() :_clock(1000000), _bitOrder(LSBFIRST), _dataMode(SPI_MODE0){}
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) :_clock(clock), _bitOrder(bitOrder), _dataMode(dataMode){} SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) :_clock(clock), _bitOrder(bitOrder), _dataMode(dataMode){}
uint32_t _clock; uint32_t _clock;
uint8_t _bitOrder; uint8_t _bitOrder;
@ -77,6 +50,7 @@ public:
void end(); void end();
void setBitOrder(uint8_t bitOrder); void setBitOrder(uint8_t bitOrder);
void setDataMode(uint8_t dataMode); void setDataMode(uint8_t dataMode);
void setFrequency(uint32_t freq);
void setClockDivider(uint32_t clockDiv); void setClockDivider(uint32_t clockDiv);
void beginTransaction(SPISettings settings); void beginTransaction(SPISettings settings);
uint8_t transfer(uint8_t data); uint8_t transfer(uint8_t data);