/* * ESPRSSIF MIT License * * Copyright (c) 2016 * * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, * it is 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 "driver/spi.h" #include "driver/spi_overlap.h" #define CACHE_FLASH_CTRL_REG 0x3ff0000C #define CACHE_FLUSH_START_BIT BIT0 #define CACHE_EMPTY_FLAG_BIT BIT1 /****************************************************************************** * FunctionName : cache_flush * Description : clear all the cpu cache data for stability test. *******************************************************************************/ void cache_flush(void) { while(READ_PERI_REG(CACHE_FLASH_CTRL_REG)&CACHE_EMPTY_FLAG_BIT) { CLEAR_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT); SET_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT); } while(!(READ_PERI_REG(CACHE_FLASH_CTRL_REG)&CACHE_EMPTY_FLAG_BIT)); CLEAR_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT); } /****************************************************************************** * FunctionName : spi_master_init * Description : SPI master initial function for common byte units transmission * Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid *******************************************************************************/ void ICACHE_FLASH_ATTR spi_master_init(uint8 spi_no) { uint32 regvalue; if(spi_no>1) return; //handle invalid input number SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE); WRITE_PERI_REG(SPI_CLOCK(spi_no), ((3&SPI_CLKCNT_N)<1) return; //handle invalid input number if(high_bit) bytetemp=(low_8bit>>1)|0x80; else bytetemp=(low_8bit>>1)&0x7f; regvalue= ((8&SPI_USR_COMMAND_BITLEN)<1) return; //handle invalid input number while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI|SPI_USR_MISO); //SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1, // bit15-0 is cmd value. WRITE_PERI_REG(SPI_USER2(spi_no), ((7&SPI_USR_COMMAND_BITLEN)<1) return; //handle invalid input number while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR); SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO|SPI_USR_ADDR|SPI_USR_DUMMY); //SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1, // bit15-0 is cmd value. //0x70000000 is for 8bits cmd, 0x04 is eps8266 slave write cmd value WRITE_PERI_REG(SPI_USER2(spi_no), ((7&SPI_USR_COMMAND_BITLEN)<1) return; //handle invalid input number while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR); SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI|SPI_USR_ADDR|SPI_USR_DUMMY); //SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1, // bit15-0 is cmd value. //0x70000000 is for 8bits cmd, 0x06 is eps8266 slave read cmd value WRITE_PERI_REG(SPI_USER2(spi_no), ((7&SPI_USR_COMMAND_BITLEN)<1) return; //handle invalid input number if(data_len<=1) data_bit_len=7; else if(data_len>=32) data_bit_len=0xff; else data_bit_len=(data_len<<3)-1; //clear bit9,bit8 of reg PERIPHS_IO_MUX //bit9 should be cleared when HSPI clock doesn't equal CPU clock //bit8 should be cleared when SPI clock doesn't equal CPU clock ////WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9//TEST if(spi_no==SPI){ PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode }else if(spi_no==HSPI){ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode } //regvalue=READ_PERI_REG(SPI_FLASH_SLAVE(spi_no)); //slave mode,slave use buffers which are register "SPI_FLASH_C0~C15", enable trans done isr //set bit 30 bit 29 bit9,bit9 is trans done isr mask SET_PERI_REG_MASK( SPI_SLAVE(spi_no), SPI_SLAVE_MODE|SPI_SLV_WR_RD_BUF_EN| SPI_SLV_WR_BUF_DONE_EN|SPI_SLV_RD_BUF_DONE_EN| SPI_SLV_WR_STA_DONE_EN|SPI_SLV_RD_STA_DONE_EN| SPI_TRANS_DONE_EN); //disable general trans intr //CLEAR_PERI_REG_MASK(SPI_SLAVE(spi_no),SPI_TRANS_DONE_EN); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);//disable flash operation mode SET_PERI_REG_MASK(SPI_USER(spi_no),SPI_USR_MISO_HIGHPART);//SLAVE SEND DATA BUFFER IN C8-C15 //////**************RUN WHEN SLAVE RECIEVE*******************/////// //tow lines below is to configure spi timing. SET_PERI_REG_MASK(SPI_CTRL2(spi_no),(0x2&SPI_MOSI_DELAY_NUM)<>8)&0xff; spi_data[(idx<<2)+2] = (recv_data>>16)&0xff; spi_data[(idx<<2)+3] = (recv_data>>24)&0xff; idx++; } //add system_os_post here GPIO_OUTPUT_SET(0, 1); } if(regvalue&SPI_SLV_RD_BUF_DONE){ //it is necessary to call GPIO_OUTPUT_SET(2, 1), when new data is preped in SPI_W8-15 and needs to be sended. GPIO_OUTPUT_SET(2, 0); //add system_os_post here //system_os_post(USER_TASK_PRIO_1,WR_RD,regvalue); } }else if(READ_PERI_REG(0x3ff00020)&BIT9){ //bit7 is for i2s isr, } } #ifdef SPI_SLAVE_DEBUG void ICACHE_FLASH_ATTR set_miso_data() { if(GPIO_INPUT_GET(2)==0){ WRITE_PERI_REG(SPI_W8(HSPI),0x05040302); WRITE_PERI_REG(SPI_W9(HSPI),0x09080706); WRITE_PERI_REG(SPI_W10(HSPI),0x0d0c0b0a); WRITE_PERI_REG(SPI_W11(HSPI),0x11100f0e); WRITE_PERI_REG(SPI_W12(HSPI),0x15141312); WRITE_PERI_REG(SPI_W13(HSPI),0x19181716); WRITE_PERI_REG(SPI_W14(HSPI),0x1d1c1b1a); WRITE_PERI_REG(SPI_W15(HSPI),0x21201f1e); GPIO_OUTPUT_SET(2, 1); } } void ICACHE_FLASH_ATTR disp_spi_data() { uint8 i = 0; for(i=0;i<32;i++){ os_printf("data %d : 0x%02x\n\r",i,spi_data[i]); } //os_printf("d31:0x%02x\n\r",spi_data[31]); } void ICACHE_FLASH_ATTR spi_task(os_event_t *e) { uint8 data; switch(e->sig){ case MOSI: disp_spi_data(); break; case STATUS_R_IN_WR : os_printf("SR ERR in WRPR,Reg:%08x \n",e->par); break; case STATUS_W: os_printf("SW ERR,Reg:%08x\n",e->par); break; case TR_DONE_ALONE: os_printf("TD ALO ERR,Reg:%08x\n",e->par); break; case WR_RD: os_printf("WR&RD ERR,Reg:%08x\n",e->par); break; case DATA_ERROR: os_printf("Data ERR,Reg:%08x\n",e->par); break; case STATUS_R_IN_RD : os_printf("SR ERR in RDPR,Reg:%08x\n",e->par); break; default: break; } } void ICACHE_FLASH_ATTR spi_task_init(void) { spiQueue = (os_event_t*)os_malloc(sizeof(os_event_t)*SPI_QUEUE_LEN); system_os_task(spi_task,USER_TASK_PRIO_1,spiQueue,SPI_QUEUE_LEN); } os_timer_t spi_timer_test; void ICACHE_FLASH_ATTR spi_test_init() { os_printf("spi init\n\r"); spi_slave_init(HSPI); os_printf("gpio init\n\r"); gpio_init(); os_printf("spi task init \n\r"); spi_task_init(); #ifdef SPI_MISO os_printf("spi miso init\n\r"); set_miso_data(); #endif //os_timer_disarm(&spi_timer_test); //os_timer_setfn(&spi_timer_test, (os_timer_func_t *)set_miso_data, NULL);//wjl //os_timer_arm(&spi_timer_test,50,1); } #endif