void hspi_init(void) { spi_fifo = (uint32_t*)SPI_FLASH_C0(HSPI); WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9 //PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); // HSPIQ MISO GPIO12 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); // HSPID MOSI GPIO13 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); // CLK GPIO14 PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); // CS GPIO15 // SPI clock = CPU clock / 10 / 4 // time length HIGHT level = (CPU clock / 10 / 2) ^ -1, // time length LOW level = (CPU clock / 10 / 2) ^ -1 WRITE_PERI_REG(SPI_FLASH_CLOCK(HSPI), (((HSPI_PRESCALER - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) | ((1 & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) | ((0 & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) | ((1 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)); WRITE_PERI_REG(SPI_FLASH_CTRL1(HSPI), 0); uint32_t regvalue = SPI_FLASH_DOUT; regvalue &= ~(BIT2 | SPI_FLASH_USR_ADDR | SPI_FLASH_USR_DUMMY | SPI_FLASH_USR_DIN | SPI_USR_COMMAND | SPI_DOUTDIN); //clear bit 2 see example IoT_Demo WRITE_PERI_REG(SPI_FLASH_USER(HSPI), regvalue); }
/// @brief HSPI FIFO write in units of 32 bits (4 byte words) /// @param[in] write_data: write buffer /// @param[in] bytes: bytes to write /// @return void static void hspi_writeFIFO(uint8_t *write_data, int bytes) { uint8_t word_ind = 0; if(bytes > HSPI_FIFO_SIZE) // TODO set error status return; hspi_setBits(bytes); // Update FIFO with number of bits we will send // First do a fast write with 32 bit chunks at a time while(bytes >= 4) { // Cast both source and destination to 4 byte word pointers ((uint32_t *)SPI_FLASH_C0(HSPI)) [word_ind] = \ ((uint32_t *)write_data) [word_ind]; bytes -= 4; word_ind++; } // Next write remaining bytes (if any) to FIFO as a single word // Note: We follow the good practice of avoiding access past the end of an array. // (ie. protected memory, PIC using retw from flash ... could crash some CPU's) if(bytes) // Valid counts are now: 3,2,1 bytes { uint32_t last_word = 0; // Last word to send uint16_t byte_ind = word_ind << 2; // Convert to Byte index // Working MSB to LSB allows assigment to LSB without shifting // Compiler can optimize powers of 8 into byte swaps, etc... (on some CPU's) while(bytes--) // index is now 2,1,0 matching required storage offset { last_word <<= 8; // 2,1,0 last_word |= ((uint32_t) 0xffU & write_data[byte_ind + bytes ]); } // Send last partial word ((uint32_t *)SPI_FLASH_C0(HSPI)) [word_ind] = last_word; } }
/// @brief HSPI FIFO Read in units of 32 bits (4 byte words) /// @param[in] read_data: read buffer /// @param[in] bytes: bytes to write /// @return void static void hspi_readFIFO(uint8_t *read_data, int bytes) { uint8_t word_ind = 0; if(bytes > HSPI_FIFO_SIZE) // TODO set error status return; // Update FIFO with number of bits to read ? hspi_setBits(bytes); // First do a fast read 32 bit chunks at a time while(bytes >= 4) { // Cast both source and destination to 4 byte word pointers ((uint32_t *)read_data) [word_ind] = \ ((uint32_t *)SPI_FLASH_C0(HSPI)) [word_ind]; bytes -= 4; word_ind++; } // Next read remaining bytes (if any) from FIFO as a single word // Note: We follow the good practice of avoiding access past the end of an array. // (ie. protected memory, PIC using retw from flash ... could crash some CPU's) if(bytes) // Valid counts are now: 3,2,1 bytes { uint32_t last_word = ((uint32_t *)SPI_FLASH_C0(HSPI)) [word_ind]; uint16_t byte_ind = word_ind << 2; // Convert to Byte index while(bytes--) // index is now 2,1,0 matching required storage offset { // 2,1,0 order read_data[byte_ind++] = (uint8_t) 0xff & last_word; last_word >>= 8; } // Send last partial word } }
void spi_reinit(spi_config *config) { current_spi_port = config->spi_port; spi_fifo = (uint32_t*)SPI_FLASH_C0(current_spi_port); uint32_t regvalue = SPI_FLASH_DOUT; WRITE_PERI_REG(SPI_FLASH_CLOCK(current_spi_port), config->clock_reg_val); WRITE_PERI_REG(SPI_FLASH_CTRL1(current_spi_port), 0); switch(config->mode) { case spi_mode_tx: regvalue &= ~(BIT2 | SPI_FLASH_USR_ADDR | SPI_FLASH_USR_DUMMY | SPI_FLASH_USR_DIN | SPI_USR_COMMAND | SPI_DOUTDIN); break; case spi_mode_txrx: regvalue |= SPI_DOUTDIN | SPI_CK_I_EDGE; regvalue &= ~(BIT2 | SPI_FLASH_USR_ADDR | SPI_FLASH_USR_DUMMY | SPI_FLASH_USR_DIN | SPI_USR_COMMAND); break; } WRITE_PERI_REG(SPI_FLASH_USER(current_spi_port), regvalue); }