From 8631a228a221ab43221bc7f2b1686227eef0387f Mon Sep 17 00:00:00 2001 From: GuaAck <44567678+GuaAck@users.noreply.github.com> Date: Wed, 12 Dec 2018 22:33:34 +0100 Subject: [PATCH 1/4] Update hspi_slave.c I found that SPI communication did not work due te a wrong timing of the MISO signal with respect to SCK. With slower processores like Arduino UNO (and a small delay of sck due to th level converter) it works, but with a faster Arduino DUE (without converter) it did not. Together with Jiri Bilek I found that MISODM_S has to be set. In the documentation for the ESP32 (should have a very similar SPI interface) I found that also MOSIDN_S should be set in SPI1C2. The MISO timing is correct, I tested it for a clock of 4 MHZ and 320 kHz. With experiments I found that also the timing of MOSI is robust. Neither a delay of 70 ns in SCK nor in MOSI did disturb the communication. Some oscillograms are here: http://homepage.o2mail.de/g.ackermann/hspi_slave.htm Jiri Bilek added the ICACHE_RAM_ATTR to the function hspi_slave_setStatus() because this function may be indirect called from an interrupt handler. --- libraries/SPISlave/src/hspi_slave.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/SPISlave/src/hspi_slave.c b/libraries/SPISlave/src/hspi_slave.c index 66199b4070..a48e13eb1c 100644 --- a/libraries/SPISlave/src/hspi_slave.c +++ b/libraries/SPISlave/src/hspi_slave.c @@ -92,7 +92,7 @@ void hspi_slave_begin(uint8_t status_len, void * arg) SPI1S1 = (((status_len * 8) - 1) << SPIS1LSTA) | (0xff << SPIS1LBUF) | (7 << SPIS1LWBA) | (7 << SPIS1LRBA) | SPIS1RSTA; SPI1P = (1 << 19); SPI1CMD = SPIBUSY; - + SPI1C2=(0x2< Date: Sun, 13 Jan 2019 18:21:04 +0100 Subject: [PATCH 2/4] Add files via upload --- libraries/hspi_slave.c | 153 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 libraries/hspi_slave.c diff --git a/libraries/hspi_slave.c b/libraries/hspi_slave.c new file mode 100644 index 0000000000..84329cfa6c --- /dev/null +++ b/libraries/hspi_slave.c @@ -0,0 +1,153 @@ +/* +Changes: +30.10.2018: Ack: Timing for MISO corrected, some comments added. + hspi_slave_setStatus in RAM +13.01.2019: Ack: Comments added + + SPISlave library for esp8266 + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ +#include "hspi_slave.h" +#include "esp8266_peri.h" +#include "ets_sys.h" + +static void (*_hspi_slave_rx_data_cb)(void * arg, uint8_t * data, uint8_t len) = NULL; +static void (*_hspi_slave_tx_data_cb)(void * arg) = NULL; +static void (*_hspi_slave_rx_status_cb)(void * arg, uint32_t data) = NULL; +static void (*_hspi_slave_tx_status_cb)(void * arg) = NULL; +static uint8_t _hspi_slave_buffer[33]; + +void ICACHE_RAM_ATTR _hspi_slave_isr_handler(void *arg) +{ + uint32_t status; + uint32_t istatus; + + istatus = SPIIR; + + if(istatus & (1 << SPII1)) { //SPI1 ISR + status = SPI1S; + SPI1S &= ~(0x3E0);//disable interrupts + SPI1S |= SPISSRES;//reset + SPI1S &= ~(0x1F);//clear interrupts + SPI1S |= (0x3E0);//enable interrupts + + if((status & SPISRBIS) != 0 && (_hspi_slave_tx_data_cb)) { + _hspi_slave_tx_data_cb(arg); + } + if((status & SPISRSIS) != 0 && (_hspi_slave_tx_status_cb)) { + _hspi_slave_tx_status_cb(arg); + } + if((status & SPISWSIS) != 0 && (_hspi_slave_rx_status_cb)) { + uint32_t s = SPI1WS; + _hspi_slave_rx_status_cb(arg, s); + } + if((status & SPISWBIS) != 0 && (_hspi_slave_rx_data_cb)) { + uint8_t i; + uint32_t data; + _hspi_slave_buffer[32] = 0; + for(i=0; i<8; i++) { + data=SPI1W(i); + _hspi_slave_buffer[i<<2] = data & 0xff; + _hspi_slave_buffer[(i<<2)+1] = (data >> 8) & 0xff; + _hspi_slave_buffer[(i<<2)+2] = (data >> 16) & 0xff; + _hspi_slave_buffer[(i<<2)+3] = (data >> 24) & 0xff; + } + _hspi_slave_rx_data_cb(arg, &_hspi_slave_buffer[0], 32); + } + } else if(istatus & (1 << SPII0)) { //SPI0 ISR + SPI0S &= ~(0x3ff);//clear SPI ISR + } else if(istatus & (1 << SPII2)) {} //I2S ISR +} + +void hspi_slave_begin(uint8_t status_len, void * arg) +{ + status_len &= 7; + if(status_len > 4) { + status_len = 4; //max 32 bits + } + if(status_len == 0) { + status_len = 1; //min 8 bits + } + + pinMode(SS, SPECIAL); + pinMode(SCK, SPECIAL); + pinMode(MISO, SPECIAL); + pinMode(MOSI, SPECIAL); + + SPI1S = SPISE | SPISBE | 0x3E0; // SPI_SLAVE_REG + SPI1U = SPIUMISOH | SPIUCOMMAND | SPIUSSE; //SPI_USER_REG + SPI1CLK = 0; + SPI1U2 = (7 << SPILCOMMAND); // SPI_USER2_REG + SPI1S1 = (((status_len * 8) - 1) << SPIS1LSTA) | (0xff << SPIS1LBUF) | (7 << SPIS1LWBA) | (7 << SPIS1LRBA) | SPIS1RSTA; //SPI_SLAVE1_REG + SPI1P = (1 << 19); // not described in ESP32-reference + SPI1CMD = SPIBUSY; // not described in ESP32-reference +// (no settings in SPI1C2 in the original version.) + SPI1C2=(0x2< Date: Sun, 13 Jan 2019 22:13:17 +0100 Subject: [PATCH 3/4] Add files via upload --- libraries/SPISlave/src/hspi_slave.c | 44 +++++++++++++---------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/libraries/SPISlave/src/hspi_slave.c b/libraries/SPISlave/src/hspi_slave.c index a48e13eb1c..84329cfa6c 100644 --- a/libraries/SPISlave/src/hspi_slave.c +++ b/libraries/SPISlave/src/hspi_slave.c @@ -1,4 +1,9 @@ /* +Changes: +30.10.2018: Ack: Timing for MISO corrected, some comments added. + hspi_slave_setStatus in RAM +13.01.2019: Ack: Comments added + SPISlave library for esp8266 Copyright (c) 2015 Hristo Gochkov. All rights reserved. @@ -85,36 +90,25 @@ void hspi_slave_begin(uint8_t status_len, void * arg) pinMode(MISO, SPECIAL); pinMode(MOSI, SPECIAL); - SPI1S = SPISE | SPISBE | 0x3E0; - SPI1U = SPIUMISOH | SPIUCOMMAND | SPIUSSE; + SPI1S = SPISE | SPISBE | 0x3E0; // SPI_SLAVE_REG + SPI1U = SPIUMISOH | SPIUCOMMAND | SPIUSSE; //SPI_USER_REG SPI1CLK = 0; - SPI1U2 = (7 << SPILCOMMAND); - SPI1S1 = (((status_len * 8) - 1) << SPIS1LSTA) | (0xff << SPIS1LBUF) | (7 << SPIS1LWBA) | (7 << SPIS1LRBA) | SPIS1RSTA; - SPI1P = (1 << 19); - SPI1CMD = SPIBUSY; - SPI1C2=(0x2< Date: Sun, 13 Jan 2019 22:16:50 +0100 Subject: [PATCH 4/4] Add files via upload --- libraries/hspi_slave.c | 154 +---------------------------------------- 1 file changed, 1 insertion(+), 153 deletions(-) diff --git a/libraries/hspi_slave.c b/libraries/hspi_slave.c index 84329cfa6c..ec7e5d5a59 100644 --- a/libraries/hspi_slave.c +++ b/libraries/hspi_slave.c @@ -1,153 +1 @@ -/* -Changes: -30.10.2018: Ack: Timing for MISO corrected, some comments added. - hspi_slave_setStatus in RAM -13.01.2019: Ack: Comments added - - SPISlave library for esp8266 - - Copyright (c) 2015 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - 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 -*/ -#include "hspi_slave.h" -#include "esp8266_peri.h" -#include "ets_sys.h" - -static void (*_hspi_slave_rx_data_cb)(void * arg, uint8_t * data, uint8_t len) = NULL; -static void (*_hspi_slave_tx_data_cb)(void * arg) = NULL; -static void (*_hspi_slave_rx_status_cb)(void * arg, uint32_t data) = NULL; -static void (*_hspi_slave_tx_status_cb)(void * arg) = NULL; -static uint8_t _hspi_slave_buffer[33]; - -void ICACHE_RAM_ATTR _hspi_slave_isr_handler(void *arg) -{ - uint32_t status; - uint32_t istatus; - - istatus = SPIIR; - - if(istatus & (1 << SPII1)) { //SPI1 ISR - status = SPI1S; - SPI1S &= ~(0x3E0);//disable interrupts - SPI1S |= SPISSRES;//reset - SPI1S &= ~(0x1F);//clear interrupts - SPI1S |= (0x3E0);//enable interrupts - - if((status & SPISRBIS) != 0 && (_hspi_slave_tx_data_cb)) { - _hspi_slave_tx_data_cb(arg); - } - if((status & SPISRSIS) != 0 && (_hspi_slave_tx_status_cb)) { - _hspi_slave_tx_status_cb(arg); - } - if((status & SPISWSIS) != 0 && (_hspi_slave_rx_status_cb)) { - uint32_t s = SPI1WS; - _hspi_slave_rx_status_cb(arg, s); - } - if((status & SPISWBIS) != 0 && (_hspi_slave_rx_data_cb)) { - uint8_t i; - uint32_t data; - _hspi_slave_buffer[32] = 0; - for(i=0; i<8; i++) { - data=SPI1W(i); - _hspi_slave_buffer[i<<2] = data & 0xff; - _hspi_slave_buffer[(i<<2)+1] = (data >> 8) & 0xff; - _hspi_slave_buffer[(i<<2)+2] = (data >> 16) & 0xff; - _hspi_slave_buffer[(i<<2)+3] = (data >> 24) & 0xff; - } - _hspi_slave_rx_data_cb(arg, &_hspi_slave_buffer[0], 32); - } - } else if(istatus & (1 << SPII0)) { //SPI0 ISR - SPI0S &= ~(0x3ff);//clear SPI ISR - } else if(istatus & (1 << SPII2)) {} //I2S ISR -} - -void hspi_slave_begin(uint8_t status_len, void * arg) -{ - status_len &= 7; - if(status_len > 4) { - status_len = 4; //max 32 bits - } - if(status_len == 0) { - status_len = 1; //min 8 bits - } - - pinMode(SS, SPECIAL); - pinMode(SCK, SPECIAL); - pinMode(MISO, SPECIAL); - pinMode(MOSI, SPECIAL); - - SPI1S = SPISE | SPISBE | 0x3E0; // SPI_SLAVE_REG - SPI1U = SPIUMISOH | SPIUCOMMAND | SPIUSSE; //SPI_USER_REG - SPI1CLK = 0; - SPI1U2 = (7 << SPILCOMMAND); // SPI_USER2_REG - SPI1S1 = (((status_len * 8) - 1) << SPIS1LSTA) | (0xff << SPIS1LBUF) | (7 << SPIS1LWBA) | (7 << SPIS1LRBA) | SPIS1RSTA; //SPI_SLAVE1_REG - SPI1P = (1 << 19); // not described in ESP32-reference - SPI1CMD = SPIBUSY; // not described in ESP32-reference -// (no settings in SPI1C2 in the original version.) - SPI1C2=(0x2<