commit
2d933cf0e4
4 changed files with 238 additions and 5 deletions
|
@ -27,6 +27,7 @@
|
||||||
#define _SPI1_FUNC IOMUX_FUNC(2)
|
#define _SPI1_FUNC IOMUX_FUNC(2)
|
||||||
|
|
||||||
#define _SPI_BUF_SIZE 64
|
#define _SPI_BUF_SIZE 64
|
||||||
|
#define __min(a,b) ((a > b) ? (b):(a))
|
||||||
|
|
||||||
static bool _minimal_pins[2] = {false, false};
|
static bool _minimal_pins[2] = {false, false};
|
||||||
|
|
||||||
|
@ -244,3 +245,36 @@ size_t spi_transfer(uint8_t bus, const void *out_data, void *in_data, size_t len
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _repeat_send(uint8_t bus, uint32_t* dword,int32_t* repeats,spi_word_size_t size)
|
||||||
|
{
|
||||||
|
uint8_t i = 0 ;
|
||||||
|
while(*repeats > 0)
|
||||||
|
{
|
||||||
|
uint16_t bytes_to_transfer = __min(*repeats * size , _SPI_BUF_SIZE);
|
||||||
|
_wait(bus);
|
||||||
|
_set_size(bus,bytes_to_transfer);
|
||||||
|
for(i = 0; i < (bytes_to_transfer + 3) / 4;i++)
|
||||||
|
SPI(bus).W[i] = *dword; //need test with memcpy !
|
||||||
|
_start(bus);
|
||||||
|
*repeats -= (bytes_to_transfer / size ) ;
|
||||||
|
}
|
||||||
|
_wait(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_repeat_send_8(uint8_t bus, uint8_t data,int32_t repeats)
|
||||||
|
{
|
||||||
|
uint32_t dword = data << 24 | data << 16 | data << 8 | data;
|
||||||
|
_repeat_send(bus,&dword,&repeats, SPI_8BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_repeat_send_16(uint8_t bus, uint16_t data,int32_t repeats)
|
||||||
|
{
|
||||||
|
uint32_t dword = data << 16 | data;
|
||||||
|
_repeat_send(bus,&dword,&repeats, SPI_16BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_repeat_send_32(uint8_t bus, uint32_t data,int32_t repeats)
|
||||||
|
{
|
||||||
|
_repeat_send(bus,&data,&repeats, SPI_32BIT);
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,15 @@
|
||||||
#define SPI_FREQ_DIV_40M SPI_GET_FREQ_DIV(1, 2) ///< 40MHz
|
#define SPI_FREQ_DIV_40M SPI_GET_FREQ_DIV(1, 2) ///< 40MHz
|
||||||
#define SPI_FREQ_DIV_80M SPI_GET_FREQ_DIV(1, 1) ///< 80MHz
|
#define SPI_FREQ_DIV_80M SPI_GET_FREQ_DIV(1, 1) ///< 80MHz
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible Data Structure of SPI Transaction
|
||||||
|
*
|
||||||
|
* [COMMAND]+[ADDRESS]+[DataOUT]+[DUMMYBITS]+[DataIN]
|
||||||
|
*
|
||||||
|
* [COMMAND]+[ADDRESS]+[DUMMYBITS]+[DataOUT]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -265,6 +274,129 @@ uint32_t spi_transfer_32(uint8_t bus, uint32_t data);
|
||||||
*/
|
*/
|
||||||
size_t spi_transfer(uint8_t bus, const void *out_data, void *in_data, size_t len, spi_word_size_t word_size);
|
size_t spi_transfer(uint8_t bus, const void *out_data, void *in_data, size_t len, spi_word_size_t word_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add permanent command bits when transfert data over SPI
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* spi_set_command(1,1,0x01); // Set one command bit to 1
|
||||||
|
* for (uint8_t i = 0 ; i < x ; i++ ) {
|
||||||
|
* spi_transfer_8(1,0x55); // Send 1 bit command + 8 bits data x times
|
||||||
|
* }
|
||||||
|
* spi_clear_command(1); // Clear command
|
||||||
|
* spi_transfer_8(1,0x55); // Send 8 bits data
|
||||||
|
*
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
* \param bits Number of bits (max: 16).
|
||||||
|
* \param data Command to send for each transfert.
|
||||||
|
*/
|
||||||
|
static inline void spi_set_command(uint8_t bus,uint8_t bits, uint16_t data)
|
||||||
|
{
|
||||||
|
if(!bits) return ;
|
||||||
|
SPI(bus).USER0 |= SPI_USER0_COMMAND ; //enable COMMAND function in SPI module
|
||||||
|
uint16_t command = data << (16-bits); //align command data to high bits
|
||||||
|
command = ((command>>8)&0xff) | ((command<<8)&0xff00); //swap byte order
|
||||||
|
SPI(bus).USER2 = SET_FIELD(SPI(bus).USER2, SPI_USER2_COMMAND_BITLEN, --bits);
|
||||||
|
SPI(bus).USER2 = SET_FIELD(SPI(bus).USER2, SPI_USER2_COMMAND_VALUE, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add permanent address bits when transfert data over SPI
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* spi_set_address(1,8,0x45); // Set one address byte to 0x45
|
||||||
|
* for (uint8_t i = 0 ; i < x ; i++ ) {
|
||||||
|
* spi_transfer_16(1,0xC584); // Send 16 bits address + 16 bits data x times
|
||||||
|
* }
|
||||||
|
* spi_clear_address(1); // Clear command
|
||||||
|
* spi_transfer_16(1,0x55); // Send 16 bits data
|
||||||
|
*
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
* \param bits Number of bits (max: 32).
|
||||||
|
* \param data Address to send for each transfert.
|
||||||
|
*/
|
||||||
|
static inline void spi_set_address(uint8_t bus,uint8_t bits, uint32_t data)
|
||||||
|
{
|
||||||
|
if(!bits) return ;
|
||||||
|
SPI(bus).USER1 = SET_FIELD(SPI(bus).USER1, SPI_USER1_ADDR_BITLEN, --bits);
|
||||||
|
SPI(bus).USER0 |= SPI_USER0_ADDR ; //enable ADDRess function in SPI module
|
||||||
|
SPI(bus).ADDR = data<<(32-bits) ; //align address data to high bits
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Add permanent dummy bits when transfert data over SPI
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* spi_set_dummy_bits(1,4,false); // Set 4 dummy bit before Dout
|
||||||
|
* for (uint8_t i = 0 ; i < x ; i++ ) {
|
||||||
|
* spi_transfer_16(1,0xC584); // Send 4 bits dummy + 16 bits Dout x times
|
||||||
|
* }
|
||||||
|
* spi_set_dummy_bits(1,4,true); // Set 4 dummy bit between Dout and Din
|
||||||
|
* spi_transfer_8(1,0x55); // Send 8 bits Dout + 4 bits dummy + 8 bits Din
|
||||||
|
*
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
* \param bits Number of bits
|
||||||
|
* \param pos Position of dummy bit, between Dout and Din if true.
|
||||||
|
*/
|
||||||
|
static inline void spi_set_dummy_bits(uint8_t bus, uint8_t bits, bool pos)
|
||||||
|
{
|
||||||
|
if(!bits) return ;
|
||||||
|
if(pos) { SPI(bus).USER0 |= SPI_USER0_MISO; } // Dummy bit will be between Dout and Din data if set
|
||||||
|
SPI(bus).USER0 |= SPI_USER0_DUMMY; //enable dummy bits
|
||||||
|
SPI(bus).USER1 = SET_FIELD(SPI(bus).USER1, SPI_USER1_DUMMY_CYCLELEN, --bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Clear adress Bits
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
*/
|
||||||
|
static inline void spi_clear_address(uint8_t bus)
|
||||||
|
{
|
||||||
|
SPI(bus).USER0 &= ~(SPI_USER0_ADDR) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Clear command Bits
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline void spi_clear_command(uint8_t bus)
|
||||||
|
{
|
||||||
|
SPI(bus).USER0 &= ~(SPI_USER0_COMMAND) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Clear dummy Bits
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
*/
|
||||||
|
static inline void spi_clear_dummy(uint8_t bus)
|
||||||
|
{
|
||||||
|
SPI(bus).USER0 &= ~(SPI_USER0_DUMMY | SPI_USER0_MISO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Send many 8 bits template over SPI
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
* \param data Byte template (8 bits)
|
||||||
|
* \param repeats Copy byte number
|
||||||
|
*/
|
||||||
|
void spi_repeat_send_8(uint8_t bus, uint8_t data, int32_t repeats);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Send many 16 bits template over SPI
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
* \param data Word template (16 bits)
|
||||||
|
* \param repeats Copy word number
|
||||||
|
*/
|
||||||
|
void spi_repeat_send_16(uint8_t bus, uint16_t data, int32_t repeats);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Send many 32 bits template over SPI
|
||||||
|
* \param bus Bus ID: 0 - system, 1 - user
|
||||||
|
* \param data Dualword template (32 bits)
|
||||||
|
* \param repeats Copy dword number
|
||||||
|
*/
|
||||||
|
void spi_repeat_send_32(uint8_t bus, uint32_t data, int32_t repeats);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
3
examples/spi_test/Makefile
Normal file
3
examples/spi_test/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Simple makefile for simple example
|
||||||
|
PROGRAM=spi_test
|
||||||
|
include ../../common.mk
|
64
examples/spi_test/spi_test.c
Normal file
64
examples/spi_test/spi_test.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/* Example SPI transfert
|
||||||
|
*
|
||||||
|
* This sample code is in the public domain.
|
||||||
|
*/
|
||||||
|
#include "espressif/esp_common.h"
|
||||||
|
#include "esp/uart.h"
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "esp8266.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp/spi.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible Data Structure of SPI Transaction
|
||||||
|
*
|
||||||
|
* [COMMAND]+[ADDRESS]+[DataOUT]+[DUMMYBITS]+[DataIN]
|
||||||
|
*
|
||||||
|
* [COMMAND]+[ADDRESS]+[DUMMYBITS]+[DataOUT]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void loop(void *pvParameters)
|
||||||
|
{
|
||||||
|
uint32_t time = 0 ; // SPI transmission time
|
||||||
|
float avr_time = 0 ; // Average of SPI transmission
|
||||||
|
float u = 0 ;
|
||||||
|
|
||||||
|
spi_init(1, SPI_MODE0, SPI_FREQ_DIV_1M, 1, SPI_LITTLE_ENDIAN, false); // init SPI module
|
||||||
|
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
time = sdk_system_get_time();
|
||||||
|
|
||||||
|
spi_set_command(1,1,1) ; // Set one command bit to 1
|
||||||
|
spi_set_address(1,4,8) ; // Set 4 address bits to 8
|
||||||
|
spi_set_dummy_bits(1,4,false); // Set 4 dummy bit before Dout
|
||||||
|
|
||||||
|
spi_repeat_send_16(1,0xC584,10); // Send 1 bit command + 4 bits address + 4 bits dummy + 160 bits data
|
||||||
|
|
||||||
|
spi_clear_address(1); // remove address
|
||||||
|
spi_clear_command(1); // remove command
|
||||||
|
spi_clear_dummy(1); // remove dummy
|
||||||
|
|
||||||
|
|
||||||
|
time = sdk_system_get_time() -time ;
|
||||||
|
avr_time = ((avr_time * (float)u ) + (float)time)/((float)u+1.0) ; // compute average
|
||||||
|
u++;
|
||||||
|
if (u==100) {
|
||||||
|
u=0 ;
|
||||||
|
printf("Time: %f\n",avr_time);
|
||||||
|
}
|
||||||
|
vTaskDelay(100/portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void user_init(void)
|
||||||
|
{
|
||||||
|
uart_set_baud(0, 115200);
|
||||||
|
printf("SDK version:%s\n", sdk_system_get_sdk_version());
|
||||||
|
xTaskCreate(loop, "loop", 1024, NULL, 2, NULL);
|
||||||
|
}
|
Loading…
Reference in a new issue