SPIFFS: Bypass SDK and bootrom for flash access.
Accessing SPI flash using reversed engineered functions.
This commit is contained in:
		
							parent
							
								
									fb187eae08
								
							
						
					
					
						commit
						5d5f28a22f
					
				
					 3 changed files with 356 additions and 148 deletions
				
			
		
							
								
								
									
										336
									
								
								extras/spiffs/esp_spi_flash.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										336
									
								
								extras/spiffs/esp_spi_flash.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,336 @@
 | 
			
		|||
#include "esp_spi_flash.h"
 | 
			
		||||
#include "flashchip.h"
 | 
			
		||||
#include "espressif/spi_flash.h"
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "esp/rom.h"
 | 
			
		||||
#include "esp/spi_regs.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static uint32_t IRAM read_status(sdk_flashchip_t *flashchip, uint32_t *status)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t _status;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        SPI(0).RSTATUS = 0;
 | 
			
		||||
        SPI(0).CMD = SPI_CMD_READ_SR;
 | 
			
		||||
        while (SPI(0).CMD) {}
 | 
			
		||||
        _status = SPI(0).RSTATUS & flashchip->status_mask;
 | 
			
		||||
    } while ( _status & 0b1);
 | 
			
		||||
 | 
			
		||||
    *status = _status;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t IRAM wait_idle(sdk_flashchip_t *flashchip)
 | 
			
		||||
{
 | 
			
		||||
    while (DPORT.SPI_READY & DPORT_SPI_READY_IDLE) {}
 | 
			
		||||
    uint32_t a3;
 | 
			
		||||
    return read_status(flashchip, &a3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t IRAM write_enable(sdk_flashchip_t *flashchip)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t local0 = 0;
 | 
			
		||||
 | 
			
		||||
    wait_idle(flashchip);
 | 
			
		||||
 | 
			
		||||
    SPI(0).CMD = SPI_CMD_WRITE_ENABLE;
 | 
			
		||||
    while (SPI(0).CMD) {}
 | 
			
		||||
 | 
			
		||||
    if (!(local0 & 0b1)) {
 | 
			
		||||
        do {
 | 
			
		||||
            read_status(flashchip, &local0);
 | 
			
		||||
        } while (!(local0 & (1<<1)));
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t IRAM page_program(sdk_flashchip_t *flashchip, uint32_t dest_addr,
 | 
			
		||||
    uint32_t *buf, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (size & 0b11) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // check if block to write doesn't cross page boundary
 | 
			
		||||
    if (flashchip->page_size < size + (dest_addr % flashchip->page_size)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    wait_idle(flashchip);
 | 
			
		||||
    if (size < 1) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // a12 = 0x60000200
 | 
			
		||||
    // a0 =  0x00FFFFFF
 | 
			
		||||
    // a6 = (dest_addr & 0x00FFFFFF) | 0x20000000
 | 
			
		||||
    while (size >= 32) {
 | 
			
		||||
        SPI(0).ADDR = (dest_addr & 0x00FFFFFF) | 0x20000000;
 | 
			
		||||
        // a4 - loop variable += 4
 | 
			
		||||
        // a5 = buf[0]
 | 
			
		||||
        for (uint8_t i = 0; i != 8; i++) {
 | 
			
		||||
            SPI(0).W[i] = buf[i];
 | 
			
		||||
        }
 | 
			
		||||
        size -= 32;
 | 
			
		||||
        dest_addr += 32;
 | 
			
		||||
        buf += 8;
 | 
			
		||||
        if (write_enable(flashchip)) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
        SPI(0).CMD = SPI_CMD_PP;
 | 
			
		||||
        while (SPI(0).CMD) {}   // wait for reg->cmd to be 0
 | 
			
		||||
        wait_idle(flashchip);
 | 
			
		||||
        // a0 = 0x00FFFFFF
 | 
			
		||||
        if (size < 1) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // a7 = 0x00FFFFFF & dest_addr
 | 
			
		||||
    // a4 = size << 24;
 | 
			
		||||
    // a4 = a7 | a4
 | 
			
		||||
    SPI(0).ADDR = (size << 24) | (0x00FFFFFF & dest_addr);
 | 
			
		||||
    // a6 = 0b11 & size
 | 
			
		||||
    // a3 = size >> 2;
 | 
			
		||||
    // a5 = a3 + 1
 | 
			
		||||
    uint32_t words = size >> 2;
 | 
			
		||||
    if (0b11 & size) {
 | 
			
		||||
        words += 1;
 | 
			
		||||
    }
 | 
			
		||||
    words = words & 0xFF;
 | 
			
		||||
    if (words != 0) {
 | 
			
		||||
        // a4 = 0
 | 
			
		||||
        uint8_t i = 0;
 | 
			
		||||
 | 
			
		||||
        if (words & 0b1) {  // bit 0 is set in a3
 | 
			
		||||
            SPI(0).W[0] = buf[0];
 | 
			
		||||
            i++;
 | 
			
		||||
        }
 | 
			
		||||
        // a6 = a3 >> 1;
 | 
			
		||||
        if (words >> 1) {
 | 
			
		||||
            // a6 =  0x600000200
 | 
			
		||||
            // buff[0]
 | 
			
		||||
            for (; i != words; i++) {
 | 
			
		||||
                SPI(0).W[i] = buf[i];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (write_enable(flashchip)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    SPI(0).CMD = SPI_CMD_PP;
 | 
			
		||||
    while (SPI(0).CMD) {}   // wait for reg->cmd to be 0
 | 
			
		||||
    wait_idle(flashchip);
 | 
			
		||||
    // a0 = 0x00FFFFFF
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t IRAM read_data(sdk_flashchip_t *flashchip, uint32_t addr,
 | 
			
		||||
        uint32_t *dst, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    // a12 = dst
 | 
			
		||||
    if ((addr + size) > flashchip->chip_size) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // a14 = addr
 | 
			
		||||
    // a13 = size
 | 
			
		||||
    wait_idle(flashchip);
 | 
			
		||||
    if (size < 1) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    // SPI(0).CMD
 | 
			
		||||
    while (size >= 32) {
 | 
			
		||||
        // a8 = addr | 0x20000000;
 | 
			
		||||
        SPI(0).ADDR = addr | 0x20000000;
 | 
			
		||||
        SPI(0).CMD = SPI_CMD_READ;
 | 
			
		||||
        while (SPI(0).CMD) {};
 | 
			
		||||
        for (uint32_t a2 = 0; a2 < 8; a2++) {
 | 
			
		||||
            *dst = SPI(0).W[a2];
 | 
			
		||||
            dst++;
 | 
			
		||||
        }
 | 
			
		||||
        size -= 32;
 | 
			
		||||
        addr += 32;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (size >= 1) {
 | 
			
		||||
        // a7 = size << 24;
 | 
			
		||||
        // a7 = addr | a7
 | 
			
		||||
        SPI(0).ADDR = addr | (size << 24);
 | 
			
		||||
        SPI(0).CMD = SPI_CMD_READ;
 | 
			
		||||
        while (SPI(0).CMD) {};
 | 
			
		||||
        // a10 = size & 0b11
 | 
			
		||||
        uint8_t a7 = size >> 2;
 | 
			
		||||
        // a9 = a7 + 1
 | 
			
		||||
        if (size & 0b11) {
 | 
			
		||||
           // a7 = a7 + 1
 | 
			
		||||
           a7++;
 | 
			
		||||
        }
 | 
			
		||||
        // a7 = a7 & 0xFF
 | 
			
		||||
        if (!a7) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        uint8_t a2 = 0;
 | 
			
		||||
        if (a7 & 0b1) {
 | 
			
		||||
            a2 = 1;
 | 
			
		||||
            // a11 = SPI(0).W0
 | 
			
		||||
            *dst = SPI(0).W[0];
 | 
			
		||||
            dst += 1;
 | 
			
		||||
        }
 | 
			
		||||
        size = a7 >> 1;
 | 
			
		||||
        if (!size) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        for (; a2 != a7; a2++) {
 | 
			
		||||
            *dst = SPI(0).W[a2];
 | 
			
		||||
            dst += 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_SPIRead
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t IRAM spi_read(uint32_t dest_addr, void *src, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (read_data(&sdk_flashchip, dest_addr, (uint32_t*)src, size)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_spi_flash_read
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM esp_spi_flash_read(uint32_t dest_addr, void *src, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (src) {
 | 
			
		||||
        vPortEnterCritical();
 | 
			
		||||
        Cache_Read_Disable();
 | 
			
		||||
        uint32_t result = spi_read(dest_addr, src, size);
 | 
			
		||||
        Cache_Read_Enable(0, 0, 1);
 | 
			
		||||
        vPortExitCritical();
 | 
			
		||||
        return result;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_SPIWrite
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t IRAM spi_write(uint32_t dest_addr, void *dst, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (sdk_flashchip.chip_size < (dest_addr + size)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t write_bytes_to_page = sdk_flashchip.page_size -
 | 
			
		||||
        (dest_addr % sdk_flashchip.page_size);
 | 
			
		||||
 | 
			
		||||
    if (size < write_bytes_to_page) {
 | 
			
		||||
        if (page_program(&sdk_flashchip, dest_addr, (uint32_t*)dst, size)) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        } else {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (page_program(&sdk_flashchip, dest_addr, (uint32_t*)dst, write_bytes_to_page)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t offset = write_bytes_to_page;
 | 
			
		||||
    uint32_t pages_to_write = (size - offset) / sdk_flashchip.page_size;
 | 
			
		||||
    for (uint8_t i = 0; i != pages_to_write; i++) {
 | 
			
		||||
        if (page_program(&sdk_flashchip, dest_addr + offset,
 | 
			
		||||
                    dst + ((offset>>2)<<2), sdk_flashchip.page_size)) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
        offset += sdk_flashchip.page_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (page_program(&sdk_flashchip, dest_addr + offset,
 | 
			
		||||
                dst + ((offset>>2)<<2), size - offset)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_spi_flash_write
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM esp_spi_flash_write(uint32_t dest_addr, void *dst, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (dst) {
 | 
			
		||||
        if (size & 0b11) {  // not 4-byte aligned
 | 
			
		||||
            size = size >> 2;
 | 
			
		||||
            size = (size << 2) + 1;
 | 
			
		||||
        }
 | 
			
		||||
        vPortEnterCritical();
 | 
			
		||||
        Cache_Read_Disable();
 | 
			
		||||
        uint32_t result = spi_write(dest_addr, dst, size);
 | 
			
		||||
        Cache_Read_Enable(0, 0, 1);
 | 
			
		||||
        vPortExitCritical();
 | 
			
		||||
        return result;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t IRAM sector_erase(sdk_flashchip_t *chip, uint32_t addr)
 | 
			
		||||
{
 | 
			
		||||
    // a12 -> addr
 | 
			
		||||
    // a0 = addr & 0xFFF
 | 
			
		||||
    if (addr & 0xFFF) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wait_idle(chip);
 | 
			
		||||
    SPI(0).ADDR = addr & 0x00FFFFFF;
 | 
			
		||||
    SPI(0).CMD = SPI_CMD_SE;
 | 
			
		||||
    while (SPI(0).CMD) {};
 | 
			
		||||
    wait_idle(chip);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_SPIEraseSector
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t IRAM spi_erase_sector(uint32_t sector)
 | 
			
		||||
{
 | 
			
		||||
    if (sector >= (sdk_flashchip.chip_size / sdk_flashchip.sector_size)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (write_enable(&sdk_flashchip)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sector_erase(&sdk_flashchip, sdk_flashchip.sector_size * sector)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_spi_flash_erase_sector
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM esp_spi_flash_erase(uint32_t sector)
 | 
			
		||||
{
 | 
			
		||||
    vPortEnterCritical();
 | 
			
		||||
    Cache_Read_Disable();
 | 
			
		||||
 | 
			
		||||
    uint32_t result = spi_erase_sector(sector);
 | 
			
		||||
 | 
			
		||||
    Cache_Read_Enable(0, 0, 1);
 | 
			
		||||
    vPortExitCritical();
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								extras/spiffs/esp_spi_flash.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								extras/spiffs/esp_spi_flash.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
#ifndef __ESP_SPI_FLASH_H__
 | 
			
		||||
#define __ESP_SPI_FLASH_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "common_macros.h"
 | 
			
		||||
 | 
			
		||||
uint32_t IRAM esp_spi_flash_read(uint32_t dest_addr, void *src, uint32_t size);
 | 
			
		||||
uint32_t IRAM esp_spi_flash_write(uint32_t dest_addr, void *dst, uint32_t size);
 | 
			
		||||
uint32_t IRAM esp_spi_flash_erase(uint32_t sector);
 | 
			
		||||
 | 
			
		||||
#endif  // __ESP_SPI_FLASH_H__
 | 
			
		||||
| 
						 | 
				
			
			@ -9,11 +9,9 @@
 | 
			
		|||
#include "spiffs.h"
 | 
			
		||||
#include <espressif/spi_flash.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "common_macros.h"
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "esp/rom.h"
 | 
			
		||||
#include <esp/uart.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include "esp_spi_flash.h"
 | 
			
		||||
 | 
			
		||||
spiffs fs;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,143 +32,6 @@ static fs_buf_t cache_buf = {0};
 | 
			
		|||
#define ESP_SPIFFS_CACHE_PAGES     5
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ROM functions
 | 
			
		||||
uint32_t SPI_read_data(sdk_flashchip_t *p, uint32_t dest_addr, void *src,
 | 
			
		||||
        uint32_t size);
 | 
			
		||||
uint32_t SPI_page_program(sdk_flashchip_t *p, uint32_t dest_addr, void *dst,
 | 
			
		||||
        uint32_t size);
 | 
			
		||||
uint32_t SPI_write_enable(sdk_flashchip_t *p);
 | 
			
		||||
uint32_t SPI_sector_erase(sdk_flashchip_t *p, uint32_t sector_addr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_SPIRead
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM spi_read(uint32_t dest_addr, void *src, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (SPI_read_data(&sdk_flashchip, dest_addr, src, size)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_spi_flash_read
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM spi_flash_read(uint32_t dest_addr, void *src, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (src) {
 | 
			
		||||
        vPortEnterCritical();
 | 
			
		||||
        Cache_Read_Disable();
 | 
			
		||||
        uint32_t result = spi_read(dest_addr, src, size);
 | 
			
		||||
        Cache_Read_Enable(0, 0, 1);
 | 
			
		||||
        vPortExitCritical();
 | 
			
		||||
        return result;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_SPIWrite
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM spi_write(uint32_t dest_addr, void *dst, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (sdk_flashchip.chip_size < (dest_addr + size)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t write_bytes_to_page = sdk_flashchip.page_size -
 | 
			
		||||
        (dest_addr % sdk_flashchip.page_size);
 | 
			
		||||
 | 
			
		||||
    if (size < write_bytes_to_page) {
 | 
			
		||||
        if (SPI_page_program(&sdk_flashchip, dest_addr, dst, size)) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        } else {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (SPI_page_program(&sdk_flashchip, dest_addr, dst, write_bytes_to_page)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t offset = write_bytes_to_page;
 | 
			
		||||
    uint32_t pages_to_write = (size - offset) / sdk_flashchip.page_size;
 | 
			
		||||
    for (uint8_t i = 0; i != pages_to_write; i++) {
 | 
			
		||||
        if (SPI_page_program(&sdk_flashchip, dest_addr + offset,
 | 
			
		||||
                    dst + ((offset>>2)<<2), sdk_flashchip.page_size)) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
        offset += sdk_flashchip.page_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (SPI_page_program(&sdk_flashchip, dest_addr + offset,
 | 
			
		||||
                dst + ((offset>>2)<<2), size - offset)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_spi_flash_write
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM spi_flash_write(uint32_t dest_addr, void *dst, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (dst) {
 | 
			
		||||
        if (size & 0b11) {  // not 4-byte aligned
 | 
			
		||||
            size = size >> 2;
 | 
			
		||||
            size = (size << 2) + 1;
 | 
			
		||||
        }
 | 
			
		||||
        vPortEnterCritical();
 | 
			
		||||
        Cache_Read_Disable();
 | 
			
		||||
        uint32_t result = spi_write(dest_addr, dst, size);
 | 
			
		||||
        Cache_Read_Enable(0, 0, 1);
 | 
			
		||||
        vPortExitCritical();
 | 
			
		||||
        return result;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_SPIEraseSector
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM spi_erase_sector(uint32_t sector)
 | 
			
		||||
{
 | 
			
		||||
    if (sector >= (sdk_flashchip.chip_size / sdk_flashchip.sector_size)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (SPI_write_enable(&sdk_flashchip)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (SPI_sector_erase(&sdk_flashchip, sdk_flashchip.sector_size * sector)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse engineered implementation of spi_flash.o:sdk_spi_flash_erase_sector
 | 
			
		||||
 */
 | 
			
		||||
uint32_t IRAM spi_flash_erase_sector(uint32_t sector)
 | 
			
		||||
{
 | 
			
		||||
    vPortEnterCritical();
 | 
			
		||||
    Cache_Read_Disable();
 | 
			
		||||
 | 
			
		||||
    uint32_t result = spi_erase_sector(sector);
 | 
			
		||||
 | 
			
		||||
    Cache_Read_Enable(0, 0, 1);
 | 
			
		||||
    vPortExitCritical();
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Flash addresses and size alignment is a rip-off of Arduino implementation.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -187,7 +48,7 @@ static s32_t esp_spiffs_read(u32_t addr, u32_t size, u8_t *dst)
 | 
			
		|||
    if (addr < alignedBegin) {
 | 
			
		||||
        uint32_t nb = alignedBegin - addr;
 | 
			
		||||
        uint32_t tmp;
 | 
			
		||||
        if (spi_flash_read(alignedEnd - 4, &tmp, 4) != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
        if (esp_spi_flash_read(alignedEnd - 4, &tmp, 4) != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
            printf("spi_flash_read failed\n");
 | 
			
		||||
            return SPIFFS_ERR_INTERNAL;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -195,7 +56,7 @@ static s32_t esp_spiffs_read(u32_t addr, u32_t size, u8_t *dst)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if (alignedEnd != alignedBegin) {
 | 
			
		||||
        if (spi_flash_read(alignedBegin,
 | 
			
		||||
        if (esp_spi_flash_read(alignedBegin,
 | 
			
		||||
                    (uint32_t*) (dst + alignedBegin - addr),
 | 
			
		||||
                    alignedEnd - alignedBegin) != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
            printf("spi_flash_read failed\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -206,7 +67,7 @@ static s32_t esp_spiffs_read(u32_t addr, u32_t size, u8_t *dst)
 | 
			
		|||
    if (addr + size > alignedEnd) {
 | 
			
		||||
        uint32_t nb = addr + size - alignedEnd;
 | 
			
		||||
        uint32_t tmp;
 | 
			
		||||
        if (spi_flash_read(alignedEnd, &tmp, 4) != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
        if (esp_spi_flash_read(alignedEnd, &tmp, 4) != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
            printf("spi_flash_read failed\n");
 | 
			
		||||
            return SPIFFS_ERR_INTERNAL;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -232,7 +93,7 @@ static s32_t esp_spiffs_write(u32_t addr, u32_t size, u8_t *src)
 | 
			
		|||
        uint32_t nb = (size < ofs) ? size : ofs;
 | 
			
		||||
        uint8_t tmp[4] __attribute__((aligned(4))) = {0xff, 0xff, 0xff, 0xff};
 | 
			
		||||
        memcpy(tmp + 4 - ofs, src, nb);
 | 
			
		||||
        if (spi_flash_write(alignedBegin - 4, (uint32_t*) tmp, 4)
 | 
			
		||||
        if (esp_spi_flash_write(alignedBegin - 4, (uint32_t*) tmp, 4)
 | 
			
		||||
                != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
            printf("spi_flash_write failed\n");
 | 
			
		||||
            return SPIFFS_ERR_INTERNAL;
 | 
			
		||||
| 
						 | 
				
			
			@ -243,7 +104,7 @@ static s32_t esp_spiffs_write(u32_t addr, u32_t size, u8_t *src)
 | 
			
		|||
        uint32_t* srcLeftover = (uint32_t*) (src + alignedBegin - addr);
 | 
			
		||||
        uint32_t srcAlign = ((uint32_t) srcLeftover) & 3;
 | 
			
		||||
        if (!srcAlign) {
 | 
			
		||||
            if (spi_flash_write(alignedBegin, (uint32_t*) srcLeftover,
 | 
			
		||||
            if (esp_spi_flash_write(alignedBegin, (uint32_t*) srcLeftover,
 | 
			
		||||
                    alignedEnd - alignedBegin) != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
                printf("spi_flash_write failed\n");
 | 
			
		||||
                return SPIFFS_ERR_INTERNAL;
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +116,7 @@ static s32_t esp_spiffs_write(u32_t addr, u32_t size, u8_t *src)
 | 
			
		|||
                size_t willCopy = sizeLeft < sizeof(buf) ? sizeLeft : sizeof(buf);
 | 
			
		||||
                memcpy(buf, srcLeftover, willCopy);
 | 
			
		||||
 | 
			
		||||
                if (spi_flash_write(alignedBegin, (uint32_t*) buf, willCopy)
 | 
			
		||||
                if (esp_spi_flash_write(alignedBegin, (uint32_t*) buf, willCopy)
 | 
			
		||||
                        != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
                    printf("spi_flash_write failed\n");
 | 
			
		||||
                    return SPIFFS_ERR_INTERNAL;
 | 
			
		||||
| 
						 | 
				
			
			@ -273,7 +134,7 @@ static s32_t esp_spiffs_write(u32_t addr, u32_t size, u8_t *src)
 | 
			
		|||
        uint32_t tmp = 0xffffffff;
 | 
			
		||||
        memcpy(&tmp, src + size - nb, nb);
 | 
			
		||||
 | 
			
		||||
        if (spi_flash_write(alignedEnd, &tmp, 4) != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
        if (esp_spi_flash_write(alignedEnd, &tmp, 4) != SPI_FLASH_RESULT_OK) {
 | 
			
		||||
            printf("spi_flash_write failed\n");
 | 
			
		||||
            return SPIFFS_ERR_INTERNAL;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -295,7 +156,7 @@ static s32_t esp_spiffs_erase(u32_t addr, u32_t size)
 | 
			
		|||
    const uint32_t sectorCount = size / SPI_FLASH_SEC_SIZE;
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < sectorCount; ++i) {
 | 
			
		||||
        spi_flash_erase_sector(sector + i);
 | 
			
		||||
        esp_spi_flash_erase(sector + i);
 | 
			
		||||
    }
 | 
			
		||||
    return SPIFFS_OK;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue