commit
						2d933cf0e4
					
				
					 4 changed files with 238 additions and 5 deletions
				
			
		|  | @ -27,6 +27,7 @@ | |||
| #define _SPI1_FUNC IOMUX_FUNC(2) | ||||
| 
 | ||||
| #define _SPI_BUF_SIZE 64 | ||||
| #define __min(a,b) ((a > b) ? (b):(a)) | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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_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 | ||||
| extern "C" | ||||
| { | ||||
|  | @ -177,7 +186,7 @@ void spi_set_frequency_div(uint8_t bus, uint32_t divider); | |||
| inline uint32_t spi_get_frequency_div(uint8_t bus) | ||||
| { | ||||
|     return (FIELD2VAL(SPI_CLOCK_DIV_PRE, SPI(bus).CLOCK) + 1) | | ||||
|            (FIELD2VAL(SPI_CLOCK_COUNT_NUM, SPI(bus).CLOCK) + 1); | ||||
|             (FIELD2VAL(SPI_CLOCK_COUNT_NUM, SPI(bus).CLOCK) + 1); | ||||
| } | ||||
| /**
 | ||||
|  * \brief Get SPI bus frequency in Hz | ||||
|  | @ -187,8 +196,8 @@ inline uint32_t spi_get_frequency_div(uint8_t bus) | |||
| inline uint32_t spi_get_frequency_hz(uint8_t bus) | ||||
| { | ||||
|     return APB_CLK_FREQ / | ||||
|         (FIELD2VAL(SPI_CLOCK_DIV_PRE, SPI(bus).CLOCK) + 1) / | ||||
|         (FIELD2VAL(SPI_CLOCK_COUNT_NUM, SPI(bus).CLOCK) + 1); | ||||
|             (FIELD2VAL(SPI_CLOCK_DIV_PRE, SPI(bus).CLOCK) + 1) / | ||||
|             (FIELD2VAL(SPI_CLOCK_COUNT_NUM, SPI(bus).CLOCK) + 1); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -221,8 +230,8 @@ void spi_set_endianness(uint8_t bus, spi_endianness_t endianness); | |||
| inline spi_endianness_t spi_get_endianness(uint8_t bus) | ||||
| { | ||||
|     return SPI(bus).USER0 & (SPI_USER0_WR_BYTE_ORDER | SPI_USER0_RD_BYTE_ORDER) | ||||
|         ? SPI_BIG_ENDIAN | ||||
|         : SPI_LITTLE_ENDIAN; | ||||
|             ? SPI_BIG_ENDIAN | ||||
|                     : SPI_LITTLE_ENDIAN; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -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); | ||||
| 
 | ||||
| /**
 | ||||
|  * \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 | ||||
| } | ||||
| #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…
	
	Add table
		Add a link
		
	
		Reference in a new issue