MeterLogger
Functions
spi.c File Reference
#include "driver/spi.h"
Include dependency graph for spi.c:

Go to the source code of this file.

Functions

ICACHE_FLASH_ATTR void spi_init (uint8 spi_no)
 
ICACHE_FLASH_ATTR void spi_mode (uint8 spi_no, uint8 spi_cpha, uint8 spi_cpol)
 
ICACHE_FLASH_ATTR void spi_init_gpio (uint8 spi_no, uint8 sysclk_as_spiclk)
 
ICACHE_FLASH_ATTR void spi_clock (uint8 spi_no, uint16 prediv, uint8 cntdiv)
 
ICACHE_FLASH_ATTR void spi_tx_byte_order (uint8 spi_no, uint8 byte_order)
 
ICACHE_FLASH_ATTR void spi_rx_byte_order (uint8 spi_no, uint8 byte_order)
 
ICACHE_FLASH_ATTR uint32 spi_transaction (uint8 spi_no, uint8 cmd_bits, uint16 cmd_data, uint32 addr_bits, uint32 addr_data, uint32 dout_bits, uint32 dout_data, uint32 din_bits, uint32 dummy_bits)
 

Function Documentation

◆ spi_clock()

ICACHE_FLASH_ATTR void spi_clock ( uint8  spi_no,
uint16  prediv,
uint8  cntdiv 
)

Definition at line 136 of file spi.c.

References ICACHE_FLASH_ATTR, SPI_CLK_EQU_SYSCLK, SPI_CLKCNT_H, SPI_CLKCNT_H_S, SPI_CLKCNT_L, SPI_CLKCNT_L_S, SPI_CLKCNT_N, SPI_CLKCNT_N_S, SPI_CLKDIV_PRE, SPI_CLKDIV_PRE_S, SPI_CLOCK, and WRITE_PERI_REG.

Referenced by ext_spi_init(), and spi_init().

136  {
137 
138  if(spi_no > 1) return;
139 
140  if((prediv==0)|(cntdiv==0)){
141 
143 
144  } else {
145 
146  WRITE_PERI_REG(SPI_CLOCK(spi_no),
147  (((prediv-1)&SPI_CLKDIV_PRE)<<SPI_CLKDIV_PRE_S)|
148  (((cntdiv-1)&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)|
149  (((cntdiv>>1)&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)|
151  }
152 
153 }
#define SPI_CLKDIV_PRE_S
Definition: spi_register.h:99
#define SPI_CLKCNT_L
Definition: spi_register.h:104
#define SPI_CLKCNT_N_S
Definition: spi_register.h:101
#define SPI_CLK_EQU_SYSCLK
Definition: spi_register.h:97
#define WRITE_PERI_REG(addr, val)
Definition: eagle_soc.h:69
#define SPI_CLKCNT_N
Definition: spi_register.h:100
#define SPI_CLKCNT_H_S
Definition: spi_register.h:103
#define SPI_CLOCK(i)
Definition: spi_register.h:96
#define SPI_CLKDIV_PRE
Definition: spi_register.h:98
#define SPI_CLKCNT_H
Definition: spi_register.h:102
#define SPI_CLKCNT_L_S
Definition: spi_register.h:105
Here is the caller graph for this function:

◆ spi_init()

ICACHE_FLASH_ATTR void spi_init ( uint8  spi_no)

Definition at line 38 of file spi.c.

References CLEAR_PERI_REG_MASK, ICACHE_FLASH_ATTR, SET_PERI_REG_MASK, SPI_BYTE_ORDER_HIGH_TO_LOW, SPI_CLK_CNTDIV, SPI_CLK_PREDIV, SPI_CLK_USE_DIV, spi_clock(), SPI_CS_HOLD, SPI_CS_SETUP, SPI_FLASH_MODE, spi_init_gpio(), spi_rx_byte_order(), spi_tx_byte_order(), and SPI_USER.

38  {
39 
40  if(spi_no > 1) return; //Only SPI and HSPI are valid spi modules.
41 
46 
49 
50 }
#define SPI_CLK_PREDIV
Definition: spi.h:49
#define SPI_USER(i)
Definition: spi_register.h:107
#define SPI_FLASH_MODE
Definition: spi_register.h:137
ICACHE_FLASH_ATTR void spi_init_gpio(uint8 spi_no, uint8 sysclk_as_spiclk)
Definition: spi.c:97
ICACHE_FLASH_ATTR void spi_tx_byte_order(uint8 spi_no, uint8 byte_order)
Definition: spi.c:176
#define SPI_CS_SETUP
Definition: spi_register.h:134
#define CLEAR_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:70
#define SPI_CLK_USE_DIV
Definition: spi.h:38
ICACHE_FLASH_ATTR void spi_clock(uint8 spi_no, uint16 prediv, uint8 cntdiv)
Definition: spi.c:136
#define SPI_CS_HOLD
Definition: spi_register.h:135
#define SPI_CLK_CNTDIV
Definition: spi.h:50
#define SPI_BYTE_ORDER_HIGH_TO_LOW
Definition: spi.h:41
#define SET_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:71
ICACHE_FLASH_ATTR void spi_rx_byte_order(uint8 spi_no, uint8 byte_order)
Definition: spi.c:207
Here is the call graph for this function:

◆ spi_init_gpio()

ICACHE_FLASH_ATTR void spi_init_gpio ( uint8  spi_no,
uint8  sysclk_as_spiclk 
)

Definition at line 97 of file spi.c.

References HSPI, ICACHE_FLASH_ATTR, PERIPHS_IO_MUX, PERIPHS_IO_MUX_MTCK_U, PERIPHS_IO_MUX_MTDI_U, PERIPHS_IO_MUX_MTDO_U, PERIPHS_IO_MUX_MTMS_U, PERIPHS_IO_MUX_SD_CLK_U, PERIPHS_IO_MUX_SD_CMD_U, PERIPHS_IO_MUX_SD_DATA0_U, PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_SELECT, SPI, and WRITE_PERI_REG.

Referenced by ext_spi_init(), and spi_init().

97  {
98 
99 // if(spi_no > 1) return; //Not required. Valid spi_no is checked with if/elif below.
100 
101  uint32 clock_div_flag = 0;
102  if(sysclk_as_spiclk){
103  clock_div_flag = 0x0001;
104  }
105 
106  if(spi_no==SPI){
107  WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005|(clock_div_flag<<8)); //Set bit 8 if 80MHz sysclock required
112  }else if(spi_no==HSPI){
113  WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105|(clock_div_flag<<9)); //Set bit 9 if 80MHz sysclock required
114  PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); //GPIO12 is HSPI MISO pin (Master Data In)
115  PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); //GPIO13 is HSPI MOSI pin (Master Data Out)
116  PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); //GPIO14 is HSPI CLK pin (Clock)
117  PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); //GPIO15 is HSPI CS pin (Chip Select / Slave Select)
118  }
119 
120 }
#define PIN_FUNC_SELECT(PIN_NAME, FUNC)
Definition: eagle_soc.h:270
#define SPI
Definition: spi.h:35
#define PERIPHS_IO_MUX
Definition: eagle_soc.h:87
#define PERIPHS_IO_MUX_MTDI_U
Definition: eagle_soc.h:219
#define PERIPHS_IO_MUX_MTCK_U
Definition: eagle_soc.h:221
#define HSPI
Definition: spi.h:36
#define PERIPHS_IO_MUX_SD_DATA0_U
Definition: eagle_soc.h:236
#define WRITE_PERI_REG(addr, val)
Definition: eagle_soc.h:69
#define PERIPHS_IO_MUX_SD_CLK_U
Definition: eagle_soc.h:233
#define PERIPHS_IO_MUX_MTDO_U
Definition: eagle_soc.h:225
unsigned int uint32
Definition: c_types.h:54
#define PERIPHS_IO_MUX_SD_DATA1_U
Definition: eagle_soc.h:240
#define PERIPHS_IO_MUX_MTMS_U
Definition: eagle_soc.h:223
#define PERIPHS_IO_MUX_SD_CMD_U
Definition: eagle_soc.h:253
Here is the caller graph for this function:

◆ spi_mode()

ICACHE_FLASH_ATTR void spi_mode ( uint8  spi_no,
uint8  spi_cpha,
uint8  spi_cpol 
)

Definition at line 67 of file spi.c.

References CLEAR_PERI_REG_MASK, ICACHE_FLASH_ATTR, SET_PERI_REG_MASK, SPI_CK_OUT_EDGE, SPI_IDLE_EDGE, SPI_PIN, and SPI_USER.

67  {
68  if(spi_cpha) {
70  } else {
72  }
73 
74  if (spi_cpol) {
76  } else {
78  }
79 }
#define SPI_IDLE_EDGE
Definition: spi_register.h:164
#define SPI_USER(i)
Definition: spi_register.h:107
#define CLEAR_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:70
#define SPI_PIN(i)
Definition: spi_register.h:163
#define SPI_CK_OUT_EDGE
Definition: spi_register.h:132
#define SET_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:71

◆ spi_rx_byte_order()

ICACHE_FLASH_ATTR void spi_rx_byte_order ( uint8  spi_no,
uint8  byte_order 
)

Definition at line 207 of file spi.c.

References CLEAR_PERI_REG_MASK, ICACHE_FLASH_ATTR, SET_PERI_REG_MASK, SPI_RD_BYTE_ORDER, and SPI_USER.

Referenced by ext_spi_init(), and spi_init().

207  {
208 
209  if(spi_no > 1) return;
210 
211  if(byte_order){
213  } else {
215  }
216 }
#define SPI_USER(i)
Definition: spi_register.h:107
#define CLEAR_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:70
#define SPI_RD_BYTE_ORDER
Definition: spi_register.h:129
#define SET_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:71
Here is the caller graph for this function:

◆ spi_transaction()

ICACHE_FLASH_ATTR uint32 spi_transaction ( uint8  spi_no,
uint8  cmd_bits,
uint16  cmd_data,
uint32  addr_bits,
uint32  addr_data,
uint32  dout_bits,
uint32  dout_data,
uint32  din_bits,
uint32  dummy_bits 
)

Definition at line 241 of file spi.c.

References CLEAR_PERI_REG_MASK, READ_PERI_REG, SET_PERI_REG_MASK, SPI_ADDR, spi_busy, SPI_CMD, SPI_RD_BYTE_ORDER, SPI_USER, SPI_USER1, SPI_USER2, SPI_USR, SPI_USR_ADDR, SPI_USR_ADDR_BITLEN, SPI_USR_ADDR_BITLEN_S, SPI_USR_COMMAND, SPI_USR_COMMAND_BITLEN, SPI_USR_COMMAND_BITLEN_S, SPI_USR_COMMAND_VALUE, SPI_USR_DUMMY, SPI_USR_DUMMY_CYCLELEN, SPI_USR_DUMMY_CYCLELEN_S, SPI_USR_MISO, SPI_USR_MISO_BITLEN, SPI_USR_MISO_BITLEN_S, SPI_USR_MOSI, SPI_USR_MOSI_BITLEN, SPI_USR_MOSI_BITLEN_S, SPI_W0, SPI_WR_BYTE_ORDER, and WRITE_PERI_REG.

Referenced by ext_spi_flash_erase_sector(), ext_spi_flash_id(), ext_spi_flash_read(), and ext_spi_flash_write().

242  {
243 
244  if(spi_no > 1) return 0; //Check for a valid SPI
245 
246  //code for custom Chip Select as GPIO PIN here
247 
248  while(spi_busy(spi_no)); //wait for SPI to be ready
249 
250 //########## Enable SPI Functions ##########//
251  //disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
253 
254  //enable functions based on number of bits. 0 bits = disabled.
255  //This is rather inefficient but allows for a very generic function.
256  //CMD ADDR and MOSI are set below to save on an extra if statement.
257 // if(cmd_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND);}
258 // if(addr_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR);}
259  if(din_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);}
260  if(dummy_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);}
261 //########## END SECTION ##########//
262 
263 //########## Setup Bitlengths ##########//
264  WRITE_PERI_REG(SPI_USER1(spi_no), ((addr_bits-1)&SPI_USR_ADDR_BITLEN)<<SPI_USR_ADDR_BITLEN_S | //Number of bits in Address
265  ((dout_bits-1)&SPI_USR_MOSI_BITLEN)<<SPI_USR_MOSI_BITLEN_S | //Number of bits to Send
266  ((din_bits-1)&SPI_USR_MISO_BITLEN)<<SPI_USR_MISO_BITLEN_S | //Number of bits to receive
267  ((dummy_bits-1)&SPI_USR_DUMMY_CYCLELEN)<<SPI_USR_DUMMY_CYCLELEN_S); //Number of Dummy bits to insert
268 //########## END SECTION ##########//
269 
270 //########## Setup Command Data ##########//
271  if(cmd_bits) {
272  SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND); //enable COMMAND function in SPI module
273  uint16 command = cmd_data << (16-cmd_bits); //align command data to high bits
274  command = ((command>>8)&0xff) | ((command<<8)&0xff00); //swap byte order
276  }
277 //########## END SECTION ##########//
278 
279 //########## Setup Address Data ##########//
280  if(addr_bits){
281  SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR); //enable ADDRess function in SPI module
282  WRITE_PERI_REG(SPI_ADDR(spi_no), addr_data<<(32-addr_bits)); //align address data to high bits
283  }
284 
285 
286 //########## END SECTION ##########//
287 
288 //########## Setup DOUT data ##########//
289  if(dout_bits) {
290  SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI); //enable MOSI function in SPI module
291  //copy data to W0
293  WRITE_PERI_REG(SPI_W0(spi_no), dout_data<<(32-dout_bits));
294  } else {
295 
296  uint8 dout_extra_bits = dout_bits%8;
297 
298  if(dout_extra_bits){
299  //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
300  //not sure if there's even a use case for this, but it's here if you need it...
301  //for example, 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output as if it were 0x0DA4,
302  //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).
303  //The code below shifts it out as 0xA4 followed by 0xD as you might require.
304  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));
305  } else {
306  WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
307  }
308  }
309  }
310 //########## END SECTION ##########//
311 
312 //########## Begin SPI Transaction ##########//
314 //########## END SECTION ##########//
315 
316 //########## Return DIN data ##########//
317  if(din_bits) {
318  while(spi_busy(spi_no)); //wait for SPI transaction to complete
319 
321  return READ_PERI_REG(SPI_W0(spi_no)) >> (32-din_bits); //Assuming data in is written to MSB. TBC
322  } else {
323  return READ_PERI_REG(SPI_W0(spi_no)); //Read in the same way as DOUT is sent. Note existing contents of SPI_W0 remain unless overwritten!
324  }
325 
326  return 0; //something went wrong
327  }
328 //########## END SECTION ##########//
329 
330  //Transaction completed
331  return 1; //success
332 }
#define SPI_USR_COMMAND_VALUE
Definition: spi_register.h:157
#define SPI_USER(i)
Definition: spi_register.h:107
#define READ_PERI_REG(addr)
Definition: eagle_soc.h:68
#define SPI_USR_MOSI
Definition: spi_register.h:112
#define SPI_USR_ADDR
Definition: spi_register.h:109
#define SPI_USR_MISO_BITLEN_S
Definition: spi_register.h:150
#define SPI_USR_MISO
Definition: spi_register.h:111
unsigned short uint16
Definition: c_types.h:50
#define SPI_USR_ADDR_BITLEN_S
Definition: spi_register.h:146
#define SPI_USR_MOSI_BITLEN_S
Definition: spi_register.h:148
#define SPI_WR_BYTE_ORDER
Definition: spi_register.h:128
#define SPI_W0(i)
Definition: spi_register.h:236
#define WRITE_PERI_REG(addr, val)
Definition: eagle_soc.h:69
#define SPI_USR_DUMMY
Definition: spi_register.h:110
#define CLEAR_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:70
#define SPI_USR_MISO_BITLEN
Definition: spi_register.h:149
unsigned char uint8
Definition: c_types.h:45
#define SPI_USR_COMMAND_BITLEN_S
Definition: spi_register.h:156
#define SPI_USR_COMMAND
Definition: spi_register.h:108
#define SPI_USER2(i)
Definition: spi_register.h:154
#define SPI_ADDR(i)
Definition: spi_register.h:32
#define SPI_USR_MOSI_BITLEN
Definition: spi_register.h:147
#define SPI_RD_BYTE_ORDER
Definition: spi_register.h:129
#define SPI_CMD(i)
Definition: spi_register.h:16
#define SPI_USR_ADDR_BITLEN
Definition: spi_register.h:145
#define SPI_USR_DUMMY_CYCLELEN_S
Definition: spi_register.h:152
#define SPI_USR
Definition: spi_register.h:30
#define SET_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:71
#define SPI_USER1(i)
Definition: spi_register.h:144
#define SPI_USR_COMMAND_BITLEN
Definition: spi_register.h:155
#define spi_busy(spi_no)
Definition: spi.h:66
#define SPI_USR_DUMMY_CYCLELEN
Definition: spi_register.h:151
Here is the caller graph for this function:

◆ spi_tx_byte_order()

ICACHE_FLASH_ATTR void spi_tx_byte_order ( uint8  spi_no,
uint8  byte_order 
)

Definition at line 176 of file spi.c.

References CLEAR_PERI_REG_MASK, ICACHE_FLASH_ATTR, SET_PERI_REG_MASK, SPI_USER, and SPI_WR_BYTE_ORDER.

Referenced by ext_spi_init(), and spi_init().

176  {
177 
178  if(spi_no > 1) return;
179 
180  if(byte_order){
182  } else {
184  }
185 }
#define SPI_USER(i)
Definition: spi_register.h:107
#define SPI_WR_BYTE_ORDER
Definition: spi_register.h:128
#define CLEAR_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:70
#define SET_PERI_REG_MASK(reg, mask)
Definition: eagle_soc.h:71
Here is the caller graph for this function: