esp8266/modpybhspi: Add a HSPI module for hardware SPI support

This module uses ESP8266's SPI hardware, which allows much higher
speeds. It uses a library from
https://github.com/MetalPhreak/ESP8266_SPI_Driver
pull/2172/merge
Radomir Dopieralski 2016-06-07 21:40:56 +02:00 zatwierdzone przez Paul Sokolovsky
rodzic 49dd532180
commit 8e7dfea803
9 zmienionych plików z 962 dodań i 0 usunięć

Wyświetl plik

@ -189,6 +189,20 @@ The SPI driver is implemented in software and works on all pins::
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf
Hardware SPI
------------
The hardware SPI is faster (up to 80Mhz), but only works on following pins:
``MISO`` is gpio2, ``MOSI`` is gpio13, and ``SCK`` is gpio14. It has the same
methods as SPI, except for the pin parameters for the constructor and init
(as those are fixed).
from machine import Pin, HSPI
hspi = HSPI(baudrate=800000000, polarity=0, phase=0)
I2C bus
-------

Wyświetl plik

@ -79,6 +79,7 @@ SRC_C = \
modpybadc.c \
modpybuart.c \
modpybspi.c \
modpybhspi.c \
modesp.c \
modnetwork.c \
modutime.c \
@ -89,6 +90,7 @@ SRC_C = \
$(BUILD)/frozen.c \
fatfs_port.c \
axtls_helpers.c \
hspi.c \
$(SRC_MOD)
STM_SRC_C = $(addprefix stmhal/,\

Wyświetl plik

@ -142,6 +142,8 @@ SECTIONS
*modpybuart.o(.literal*, .text*)
*modpybi2c.o(.literal*, .text*)
*modpybspi.o(.literal*, .text*)
*modpybhspi.o(.literal*, .text*)
*hspi.o(.literal*, .text*)
*modesp.o(.literal* .text*)
*modnetwork.o(.literal* .text*)
*moduos.o(.literal* .text*)

327
esp8266/hspi.c 100644
Wyświetl plik

@ -0,0 +1,327 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 David Ogilvy (MetalPhreak)
* Modified 2016 by Radomir Dopieralski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "hspi.h"
/*
Wrapper to setup HSPI/SPI GPIO pins and default SPI clock
spi_no - SPI (0) or HSPI (1)
Not used in Micropython.
*/
void spi_init(uint8_t spi_no) {
spi_init_gpio(spi_no, SPI_CLK_USE_DIV);
spi_clock(spi_no, SPI_CLK_PREDIV, SPI_CLK_CNTDIV);
spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD);
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);
}
/*
Configures SPI mode parameters for clock edge and clock polarity.
spi_no - SPI (0) or HSPI (1)
spi_cpha - (0) Data is valid on clock leading edge
(1) Data is valid on clock trailing edge
spi_cpol - (0) Clock is low when inactive
(1) Clock is high when inactive
For Micropython this version is different from original.
*/
void spi_mode(uint8_t spi_no, uint8_t spi_cpha, uint8_t spi_cpol) {
if (spi_cpol) {
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
} else {
CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
}
if (spi_cpha == spi_cpol) {
// Mode 3 - MOSI is set on falling edge of clock
// Mode 0 - MOSI is set on falling edge of clock
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
} else {
// Mode 2 - MOSI is set on rising edge of clock
// Mode 1 - MOSI is set on rising edge of clock
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
}
}
/*
Initialise the GPIO pins for use as SPI pins.
spi_no - SPI (0) or HSPI (1)
sysclk_as_spiclk -
SPI_CLK_80MHZ_NODIV (1) if using 80MHz for SPI clock.
SPI_CLK_USE_DIV (0) if using divider for lower speed.
*/
void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk) {
uint32_t clock_div_flag = 0;
if (sysclk_as_spiclk) {
clock_div_flag = 0x0001;
}
if (spi_no == SPI) {
// Set bit 8 if 80MHz sysclock required
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div_flag<<8));
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);
} else if (spi_no == HSPI) {
// Set bit 9 if 80MHz sysclock required
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div_flag<<9));
// GPIO12 is HSPI MISO pin (Master Data In)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
// GPIO13 is HSPI MOSI pin (Master Data Out)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
// GPIO14 is HSPI CLK pin (Clock)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
// GPIO15 is HSPI CS pin (Chip Select / Slave Select)
// In Micropython, we are handling CS ourself in drivers.
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
}
}
/*
Set up the control registers for the SPI clock
spi_no - SPI (0) or HSPI (1)
prediv - predivider value (actual division value)
cntdiv - postdivider value (actual division value)
Set either divider to 0 to disable all division (80MHz sysclock)
*/
void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv) {
if (prediv == 0 || cntdiv == 0) {
WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK);
} else {
WRITE_PERI_REG(SPI_CLOCK(spi_no),
(((prediv - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
(((cntdiv - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
(((cntdiv >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)
);
}
}
/*
Setup the byte order for shifting data out of buffer
spi_no - SPI (0) or HSPI (1)
byte_order -
SPI_BYTE_ORDER_HIGH_TO_LOW (1)
Data is sent out starting with Bit31 and down to Bit0
SPI_BYTE_ORDER_LOW_TO_HIGH (0)
Data is sent out starting with the lowest BYTE, from MSB to LSB,
followed by the second lowest BYTE, from MSB to LSB, followed by
the second highest BYTE, from MSB to LSB, followed by the highest
BYTE, from MSB to LSB 0xABCDEFGH would be sent as 0xGHEFCDAB.
*/
void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order) {
if (byte_order) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
} else {
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
}
}
/*
Setup the byte order for shifting data into buffer
spi_no - SPI (0) or HSPI (1)
byte_order -
SPI_BYTE_ORDER_HIGH_TO_LOW (1)
Data is read in starting with Bit31 and down to Bit0
SPI_BYTE_ORDER_LOW_TO_HIGH (0)
Data is read in starting with the lowest BYTE, from MSB to LSB,
followed by the second lowest BYTE, from MSB to LSB, followed by
the second highest BYTE, from MSB to LSB, followed by the highest
BYTE, from MSB to LSB 0xABCDEFGH would be read as 0xGHEFCDAB
*/
void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order) {
if (byte_order) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
} else {
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
}
}
/*
SPI transaction function
spi_no - SPI (0) or HSPI (1)
cmd_bits - actual number of bits to transmit
cmd_data - command data
addr_bits - actual number of bits to transmit
addr_data - address data
dout_bits - actual number of bits to transmit
dout_data - output data
din_bits - actual number of bits to receive
Returns: read data - uint32_t containing read in data only if RX was set
0 - something went wrong (or actual read data was 0)
1 - data sent ok (or actual read data is 1)
Note: all data is assumed to be stored in the lower bits of the data variables
(for anything <32 bits).
*/
uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
uint32_t addr_bits, uint32_t addr_data,
uint32_t dout_bits, uint32_t dout_data,
uint32_t din_bits, uint32_t dummy_bits) {
while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
// Enable SPI Functions
// Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
// Enable functions based on number of bits. 0 bits = disabled.
// This is rather inefficient but allows for a very generic function.
// CMD ADDR and MOSI are set below to save on an extra if statement.
if (din_bits) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
}
if (dummy_bits) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);
}
// Setup Bitlengths
WRITE_PERI_REG(SPI_USER1(spi_no),
// Number of bits in Address
((addr_bits - 1) & SPI_USR_ADDR_BITLEN) << SPI_USR_ADDR_BITLEN_S |
// Number of bits to Send
((dout_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
// Number of bits to receive
((din_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S |
// Number of Dummy bits to insert
((dummy_bits - 1) & SPI_USR_DUMMY_CYCLELEN) << SPI_USR_DUMMY_CYCLELEN_S);
// Setup Command Data
if (cmd_bits) {
// Enable COMMAND function in SPI module
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND);
// Align command data to high bits
uint16_t command = cmd_data << (16-cmd_bits);
// Swap byte order
command = ((command>>8)&0xff) | ((command<<8)&0xff00);
WRITE_PERI_REG(SPI_USER2(spi_no), (
(((cmd_bits - 1) & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) |
(command & SPI_USR_COMMAND_VALUE)
));
}
// Setup Address Data
if (addr_bits) {
// Enable ADDRess function in SPI module
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR);
// Align address data to high bits
WRITE_PERI_REG(SPI_ADDR(spi_no), addr_data << (32 - addr_bits));
}
// Setup DOUT data
if (dout_bits) {
// Enable MOSI function in SPI module
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
// Copy data to W0
if (READ_PERI_REG(SPI_USER(spi_no))&SPI_WR_BYTE_ORDER) {
WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - dout_bits));
} else {
uint8_t dout_extra_bits = dout_bits%8;
if (dout_extra_bits) {
// If your data isn't a byte multiple (8/16/24/32 bits) and you
// don't have SPI_WR_BYTE_ORDER set, you need this to move the
// non-8bit remainder to the MSBs. Not sure if there's even a use
// case for this, but it's here if you need it... For example,
// 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output
// as if it were 0x0DA4, of which 0xA4, and then 0x0 would be
// shifted out (first 8 bits of low byte, then 4 MSB bits of high
// byte - ie reverse byte order).
// The code below shifts it out as 0xA4 followed by 0xD as you
// might require.
WRITE_PERI_REG(SPI_W0(spi_no), (
(0xFFFFFFFF << (dout_bits - dout_extra_bits) & dout_data)
<< (8-dout_extra_bits) |
((0xFFFFFFFF >> (32 - (dout_bits - dout_extra_bits)))
& dout_data)
));
} else {
WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
}
}
}
// Begin SPI Transaction
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
// Return DIN data
if (din_bits) {
while (spi_busy(spi_no)) {}; // Wait for SPI transaction to complete
if (READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) {
// Assuming data in is written to MSB. TBC
return READ_PERI_REG(SPI_W0(spi_no)) >> (32 - din_bits);
} else {
// Read in the same way as DOUT is sent. Note existing contents of
// SPI_W0 remain unless overwritten!
return READ_PERI_REG(SPI_W0(spi_no));
}
return 0; // Something went wrong
}
// Transaction completed
return 1; // Success
}
/*
Just do minimal work needed to send 8 bits.
*/
inline void spi_tx8fast(uint8_t spi_no, uint8_t dout_data) {
while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
// Enable SPI Functions
// Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
// Setup Bitlengths
WRITE_PERI_REG(SPI_USER1(spi_no),
// Number of bits to Send
((8 - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
// Number of bits to receive
((8 - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S);
// Setup DOUT data
// Enable MOSI function in SPI module
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
// Copy data to W0
if (READ_PERI_REG(SPI_USER(spi_no)) & SPI_WR_BYTE_ORDER) {
WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - 8));
} else {
WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
}
// Begin SPI Transaction
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
}

79
esp8266/hspi.h 100644
Wyświetl plik

@ -0,0 +1,79 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 David Ogilvy (MetalPhreak)
* Modified 2016 by Radomir Dopieralski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SPI_APP_H
#define SPI_APP_H
#include "hspi_register.h"
#include "ets_sys.h"
#include "osapi.h"
#include "os_type.h"
// Define SPI hardware modules
#define SPI 0
#define HSPI 1
#define SPI_CLK_USE_DIV 0
#define SPI_CLK_80MHZ_NODIV 1
#define SPI_BYTE_ORDER_HIGH_TO_LOW 1
#define SPI_BYTE_ORDER_LOW_TO_HIGH 0
#ifndef CPU_CLK_FREQ //Should already be defined in eagle_soc.h
#define CPU_CLK_FREQ (80 * 1000000)
#endif
// Define some default SPI clock settings
#define SPI_CLK_PREDIV 10
#define SPI_CLK_CNTDIV 2
#define SPI_CLK_FREQ (CPU_CLK_FREQ / (SPI_CLK_PREDIV * SPI_CLK_CNTDIV))
// 80 / 20 = 4 MHz
void spi_init(uint8_t spi_no);
void spi_mode(uint8_t spi_no, uint8_t spi_cpha,uint8_t spi_cpol);
void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk);
void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv);
void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order);
void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order);
uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
uint32_t addr_bits, uint32_t addr_data,
uint32_t dout_bits, uint32_t dout_data,
uint32_t din_bits, uint32_t dummy_bits);
void spi_tx8fast(uint8_t spi_no, uint8_t dout_data);
// Expansion Macros
#define spi_busy(spi_no) READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR
#define spi_txd(spi_no, bits, data) spi_transaction(spi_no, 0, 0, 0, 0, bits, (uint32_t) data, 0, 0)
#define spi_tx8(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 8, (uint32_t) data, 0, 0)
#define spi_tx16(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 16, (uint32_t) data, 0, 0)
#define spi_tx32(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 32, (uint32_t) data, 0, 0)
#define spi_rxd(spi_no, bits) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, bits, 0)
#define spi_rx8(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 8, 0)
#define spi_rx16(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 16, 0)
#define spi_rx32(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 32, 0)
#endif

Wyświetl plik

@ -0,0 +1,278 @@
/*
* Copyright (c) 2010 - 2011 Espressif System
* Modified by David Ogilvy (MetalPhreak)
* Based on original file included in SDK 1.0.0
*
* Missing defines from previous SDK versions have
* been added and are noted with comments. The
* names of these defines are likely to change.
*/
#ifndef SPI_REGISTER_H_INCLUDED
#define SPI_REGISTER_H_INCLUDED
#define REG_SPI_BASE(i) (0x60000200-i*0x100)
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
#define SPI_FLASH_READ (BIT(31)) //From previous SDK
#define SPI_FLASH_WREN (BIT(30)) //From previous SDK
#define SPI_FLASH_WRDI (BIT(29)) //From previous SDK
#define SPI_FLASH_RDID (BIT(28)) //From previous SDK
#define SPI_FLASH_RDSR (BIT(27)) //From previous SDK
#define SPI_FLASH_WRSR (BIT(26)) //From previous SDK
#define SPI_FLASH_PP (BIT(25)) //From previous SDK
#define SPI_FLASH_SE (BIT(24)) //From previous SDK
#define SPI_FLASH_BE (BIT(23)) //From previous SDK
#define SPI_FLASH_CE (BIT(22)) //From previous SDK
#define SPI_FLASH_DP (BIT(21)) //From previous SDK
#define SPI_FLASH_RES (BIT(20)) //From previous SDK
#define SPI_FLASH_HPM (BIT(19)) //From previous SDK
#define SPI_USR (BIT(18))
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
#define SPI_WR_BIT_ORDER (BIT(26))
#define SPI_RD_BIT_ORDER (BIT(25))
#define SPI_QIO_MODE (BIT(24))
#define SPI_DIO_MODE (BIT(23))
#define SPI_TWO_BYTE_STATUS_EN (BIT(22)) //From previous SDK
#define SPI_WP_REG (BIT(21)) //From previous SDK
#define SPI_QOUT_MODE (BIT(20))
#define SPI_SHARE_BUS (BIT(19)) //From previous SDK
#define SPI_HOLD_MODE (BIT(18)) //From previous SDK
#define SPI_ENABLE_AHB (BIT(17)) //From previous SDK
#define SPI_SST_AAI (BIT(16)) //From previous SDK
#define SPI_RESANDRES (BIT(15)) //From previous SDK
#define SPI_DOUT_MODE (BIT(14))
#define SPI_FASTRD_MODE (BIT(13))
#define SPI_CTRL1(i) (REG_SPI_BASE (i) + 0xC) //From previous SDK. Removed _FLASH_ from name to match other registers.
#define SPI_CS_HOLD_DELAY 0x0000000F //Espressif BBS
#define SPI_CS_HOLD_DELAY_S 28 //Espressif BBS
#define SPI_CS_HOLD_DELAY_RES 0x00000FFF //Espressif BBS
#define SPI_CS_HOLD_DELAY_RES_S 16 //Espressif BBS
#define SPI_BUS_TIMER_LIMIT 0x0000FFFF //From previous SDK
#define SPI_BUS_TIMER_LIMIT_S 0 //From previous SDK
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
#define SPI_STATUS_EXT 0x000000FF //From previous SDK
#define SPI_STATUS_EXT_S 24 //From previous SDK
#define SPI_WB_MODE 0x000000FF //From previous SDK
#define SPI_WB_MODE_S 16 //From previous SDK
#define SPI_FLASH_STATUS_PRO_FLAG (BIT(7)) //From previous SDK
#define SPI_FLASH_TOP_BOT_PRO_FLAG (BIT(5)) //From previous SDK
#define SPI_FLASH_BP2 (BIT(4)) //From previous SDK
#define SPI_FLASH_BP1 (BIT(3)) //From previous SDK
#define SPI_FLASH_BP0 (BIT(2)) //From previous SDK
#define SPI_FLASH_WRENABLE_FLAG (BIT(1)) //From previous SDK
#define SPI_FLASH_BUSY_FLAG (BIT(0)) //From previous SDK
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
#define SPI_CS_DELAY_NUM 0x0000000F
#define SPI_CS_DELAY_NUM_S 28
#define SPI_CS_DELAY_MODE 0x00000003
#define SPI_CS_DELAY_MODE_S 26
#define SPI_MOSI_DELAY_NUM 0x00000007
#define SPI_MOSI_DELAY_NUM_S 23
#define SPI_MOSI_DELAY_MODE 0x00000003 //mode 0 : posedge; data set at positive edge of clk
//mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk
//mode 2 : Do not use this mode.
#define SPI_MOSI_DELAY_MODE_S 21
#define SPI_MISO_DELAY_NUM 0x00000007
#define SPI_MISO_DELAY_NUM_S 18
#define SPI_MISO_DELAY_MODE 0x00000003
#define SPI_MISO_DELAY_MODE_S 16
#define SPI_CK_OUT_HIGH_MODE 0x0000000F
#define SPI_CK_OUT_HIGH_MODE_S 12
#define SPI_CK_OUT_LOW_MODE 0x0000000F
#define SPI_CK_OUT_LOW_MODE_S 8
#define SPI_HOLD_TIME 0x0000000F
#define SPI_HOLD_TIME_S 4
#define SPI_SETUP_TIME 0x0000000F
#define SPI_SETUP_TIME_S 0
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
#define SPI_CLK_EQU_SYSCLK (BIT(31))
#define SPI_CLKDIV_PRE 0x00001FFF
#define SPI_CLKDIV_PRE_S 18
#define SPI_CLKCNT_N 0x0000003F
#define SPI_CLKCNT_N_S 12
#define SPI_CLKCNT_H 0x0000003F
#define SPI_CLKCNT_H_S 6
#define SPI_CLKCNT_L 0x0000003F
#define SPI_CLKCNT_L_S 0
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
#define SPI_USR_COMMAND (BIT(31))
#define SPI_USR_ADDR (BIT(30))
#define SPI_USR_DUMMY (BIT(29))
#define SPI_USR_MISO (BIT(28))
#define SPI_USR_MOSI (BIT(27))
#define SPI_USR_DUMMY_IDLE (BIT(26)) //From previous SDK
#define SPI_USR_MOSI_HIGHPART (BIT(25))
#define SPI_USR_MISO_HIGHPART (BIT(24))
#define SPI_USR_PREP_HOLD (BIT(23)) //From previous SDK
#define SPI_USR_CMD_HOLD (BIT(22)) //From previous SDK
#define SPI_USR_ADDR_HOLD (BIT(21)) //From previous SDK
#define SPI_USR_DUMMY_HOLD (BIT(20)) //From previous SDK
#define SPI_USR_DIN_HOLD (BIT(19)) //From previous SDK
#define SPI_USR_DOUT_HOLD (BIT(18)) //From previous SDK
#define SPI_USR_HOLD_POL (BIT(17)) //From previous SDK
#define SPI_SIO (BIT(16))
#define SPI_FWRITE_QIO (BIT(15))
#define SPI_FWRITE_DIO (BIT(14))
#define SPI_FWRITE_QUAD (BIT(13))
#define SPI_FWRITE_DUAL (BIT(12))
#define SPI_WR_BYTE_ORDER (BIT(11))
#define SPI_RD_BYTE_ORDER (BIT(10))
#define SPI_AHB_ENDIAN_MODE 0x00000003 //From previous SDK
#define SPI_AHB_ENDIAN_MODE_S 8 //From previous SDK
#define SPI_CK_OUT_EDGE (BIT(7))
#define SPI_CK_I_EDGE (BIT(6))
#define SPI_CS_SETUP (BIT(5))
#define SPI_CS_HOLD (BIT(4))
#define SPI_AHB_USR_COMMAND (BIT(3)) //From previous SDK
#define SPI_FLASH_MODE (BIT(2))
#define SPI_AHB_USR_COMMAND_4BYTE (BIT(1)) //From previous SDK
#define SPI_DOUTDIN (BIT(0)) //From previous SDK
//AHB = http://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture ?
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
#define SPI_USR_ADDR_BITLEN 0x0000003F
#define SPI_USR_ADDR_BITLEN_S 26
#define SPI_USR_MOSI_BITLEN 0x000001FF
#define SPI_USR_MOSI_BITLEN_S 17
#define SPI_USR_MISO_BITLEN 0x000001FF
#define SPI_USR_MISO_BITLEN_S 8
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
#define SPI_USR_DUMMY_CYCLELEN_S 0
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
#define SPI_USR_COMMAND_BITLEN 0x0000000F
#define SPI_USR_COMMAND_BITLEN_S 28
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
#define SPI_USR_COMMAND_VALUE_S 0
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
//previously defined as SPI_FLASH_USER3. No further info available.
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
#define SPI_IDLE_EDGE (BIT(29))
#define SPI_CS2_DIS (BIT(2))
#define SPI_CS1_DIS (BIT(1))
#define SPI_CS0_DIS (BIT(0))
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
#define SPI_SYNC_RESET (BIT(31))
#define SPI_SLAVE_MODE (BIT(30))
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
#define SPI_SLV_CMD_DEFINE (BIT(27))
#define SPI_TRANS_CNT 0x0000000F
#define SPI_TRANS_CNT_S 23
#define SPI_SLV_LAST_STATE 0x00000007 //From previous SDK
#define SPI_SLV_LAST_STATE_S 20 //From previous SDK
#define SPI_SLV_LAST_COMMAND 0x00000007 //From previous SDK
#define SPI_SLV_LAST_COMMAND_S 17 //From previous SDK
#define SPI_CS_I_MODE 0x00000003 //From previous SDK
#define SPI_CS_I_MODE_S 10 //From previous SDK
#define SPI_TRANS_DONE_EN (BIT(9))
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
#define SLV_SPI_INT_EN 0x0000001f
#define SLV_SPI_INT_EN_S 5
#define SPI_TRANS_DONE (BIT(4))
#define SPI_SLV_WR_STA_DONE (BIT(3))
#define SPI_SLV_RD_STA_DONE (BIT(2))
#define SPI_SLV_WR_BUF_DONE (BIT(1))
#define SPI_SLV_RD_BUF_DONE (BIT(0))
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
#define SPI_SLV_STATUS_BITLEN 0x0000001F
#define SPI_SLV_STATUS_BITLEN_S 27
#define SPI_SLV_STATUS_FAST_EN (BIT(26)) //From previous SDK
#define SPI_SLV_STATUS_READBACK (BIT(25)) //From previous SDK
#define SPI_SLV_BUF_BITLEN 0x000001FF
#define SPI_SLV_BUF_BITLEN_S 16
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
#define SPI_SLV_RD_ADDR_BITLEN_S 10
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
#define SPI_SLV_WR_ADDR_BITLEN_S 4
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
//Previous SDKs referred to these following registers as SPI_C0 etc.
#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
// +0x80 to +0xBC could be SPI_W16 through SPI_W31?
// +0xC0 to +0xEC not currently defined.
#define SPI_EXT0(i) (REG_SPI_BASE(i) + 0xF0) //From previous SDK. Removed _FLASH_ from name to match other registers.
#define SPI_T_PP_ENA (BIT(31)) //From previous SDK
#define SPI_T_PP_SHIFT 0x0000000F //From previous SDK
#define SPI_T_PP_SHIFT_S 16 //From previous SDK
#define SPI_T_PP_TIME 0x00000FFF //From previous SDK
#define SPI_T_PP_TIME_S 0 //From previous SDK
#define SPI_EXT1(i) (REG_SPI_BASE(i) + 0xF4) //From previous SDK. Removed _FLASH_ from name to match other registers.
#define SPI_T_ERASE_ENA (BIT(31)) //From previous SDK
#define SPI_T_ERASE_SHIFT 0x0000000F //From previous SDK
#define SPI_T_ERASE_SHIFT_S 16 //From previous SDK
#define SPI_T_ERASE_TIME 0x00000FFF //From previous SDK
#define SPI_T_ERASE_TIME_S 0 //From previous SDK
#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) //From previous SDK. Removed _FLASH_ from name to match other registers.
#define SPI_ST 0x00000007 //From previous SDK
#define SPI_ST_S 0 //From previous SDK
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
#define SPI_INT_HOLD_ENA 0x00000003
#define SPI_INT_HOLD_ENA_S 0
#endif // SPI_REGISTER_H_INCLUDED

Wyświetl plik

@ -252,6 +252,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_HSPI), MP_ROM_PTR(&pyb_hspi_type) },
// wake abilities
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },

Wyświetl plik

@ -10,6 +10,7 @@ extern const mp_obj_type_t pyb_rtc_type;
extern const mp_obj_type_t pyb_uart_type;
extern const mp_obj_type_t pyb_i2c_type;
extern const mp_obj_type_t pyb_spi_type;
extern const mp_obj_type_t pyb_hspi_type;
MP_DECLARE_CONST_FUN_OBJ(pyb_info_obj);

Wyświetl plik

@ -0,0 +1,258 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "ets_sys.h"
#include "etshal.h"
#include "ets_alt_task.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mphal.h"
#include "hspi.h"
typedef struct _pyb_hspi_obj_t {
mp_obj_base_t base;
uint32_t baudrate;
uint8_t polarity;
uint8_t phase;
} pyb_hspi_obj_t;
/******************************************************************************/
// MicroPython bindings for HSPI
STATIC void pyb_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "HSPI(baudrate=%u, polarity=%u, phase=%u)",
self->baudrate, self->polarity, self->phase);
}
STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_polarity, ARG_phase };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
allowed_args, args);
if (args[ARG_baudrate].u_int != -1) {
self->baudrate = args[ARG_baudrate].u_int;
}
if (args[ARG_polarity].u_int != -1) {
self->polarity = args[ARG_polarity].u_int;
}
if (args[ARG_phase].u_int != -1) {
self->phase = args[ARG_phase].u_int;
}
if (self->baudrate == 80000000L) {
// Special case for full speed.
spi_init_gpio(HSPI, SPI_CLK_80MHZ_NODIV);
spi_clock(HSPI, 0, 0);
} else if (self->baudrate > 40000000L) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"impossible baudrate"));
} else {
uint32_t divider = 40000000L / self->baudrate;
uint16_t prediv = MIN(divider, SPI_CLKDIV_PRE + 1);
uint16_t cntdiv = (divider / prediv) * 2; // cntdiv has to be even
if (cntdiv > SPI_CLKCNT_N + 1 || cntdiv == 0 || prediv == 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"impossible baudrate"));
}
self->baudrate = 80000000L / (prediv * cntdiv);
spi_init_gpio(HSPI, SPI_CLK_USE_DIV);
spi_clock(HSPI, prediv, cntdiv);
}
// TODO: Make the byte order configurable too (discuss param names)
spi_tx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
spi_rx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE | SPI_USR_MISO |
SPI_USR_ADDR | SPI_USR_COMMAND | SPI_USR_DUMMY);
// Clear Dual or Quad lines transmission mode
CLEAR_PERI_REG_MASK(SPI_CTRL(HSPI), SPI_QIO_MODE | SPI_DIO_MODE |
SPI_DOUT_MODE | SPI_QOUT_MODE);
spi_mode(HSPI, self->phase, self->polarity);
}
STATIC mp_obj_t pyb_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
pyb_hspi_obj_t *self = m_new_obj(pyb_hspi_obj_t);
self->base.type = &pyb_hspi_type;
// set defaults
self->baudrate = 80000000L;
self->polarity = 0;
self->phase = 0;
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_hspi_init_helper(self, n_args, args, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t pyb_hspi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_hspi_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_hspi_init_obj, 1, pyb_hspi_init);
STATIC mp_obj_t pyb_hspi_read(size_t n_args, const mp_obj_t *args) {
vstr_t dest_buf;
vstr_init_len(&dest_buf, mp_obj_get_int(args[1]));
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
// Process data in chunks, let the pending tasks run in between
size_t chunk_size = 1024; // TODO this should depend on baudrate
size_t count = dest_buf.len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)write_byte, 8, 0);
++i;
}
ets_loop_iter();
}
while (i < dest_buf.len) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)write_byte, 8, 0);
++i;
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &dest_buf);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_hspi_read_obj, 2, 3, pyb_hspi_read);
STATIC mp_obj_t pyb_hspi_readinto(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t dest_buf;
mp_get_buffer_raise(args[1], &dest_buf, MP_BUFFER_WRITE);
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
size_t chunk_size = 1024;
size_t count = dest_buf.len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)write_byte, 8, 0);
++i;
}
ets_loop_iter();
}
while (i < dest_buf.len) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)write_byte, 8, 0);
++i;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_hspi_readinto_obj, 2, 3, pyb_hspi_readinto);
STATIC mp_obj_t pyb_hspi_write(mp_obj_t self_in, mp_obj_t wr_buf_in) {
mp_buffer_info_t src_buf;
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
size_t chunk_size = 1024;
size_t count = src_buf.len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
spi_tx8fast(HSPI, ((const uint8_t*)src_buf.buf)[i]);
++i;
}
ets_loop_iter();
}
while (i < src_buf.len) {
spi_tx8fast(HSPI, ((const uint8_t*)src_buf.buf)[i]);
++i;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(pyb_hspi_write_obj, pyb_hspi_write);
STATIC mp_obj_t pyb_hspi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf_in, mp_obj_t rd_buf_in) {
mp_buffer_info_t src_buf;
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
mp_buffer_info_t dest_buf;
mp_get_buffer_raise(rd_buf_in, &dest_buf, MP_BUFFER_WRITE);
if (src_buf.len != dest_buf.len) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"buffers must be the same length"));
}
size_t chunk_size = 1024;
size_t count = src_buf.len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)(((const uint8_t*)src_buf.buf)[i]), 8, 0);
++i;
}
ets_loop_iter();
}
while (i < src_buf.len) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)(((const uint8_t*)src_buf.buf)[i]), 8, 0);
++i;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(pyb_hspi_write_readinto_obj, pyb_hspi_write_readinto);
STATIC const mp_rom_map_elem_t pyb_hspi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_hspi_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_hspi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&pyb_hspi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_hspi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&pyb_hspi_write_readinto_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_hspi_locals_dict, pyb_hspi_locals_dict_table);
const mp_obj_type_t pyb_hspi_type = {
{ &mp_type_type },
.name = MP_QSTR_HSPI,
.print = pyb_hspi_print,
.make_new = pyb_hspi_make_new,
.locals_dict = (mp_obj_dict_t*)&pyb_hspi_locals_dict,
};