2014-12-30 19:47:44 +01:00
|
|
|
/******************************************************************************
|
|
|
|
* Flash api for NodeMCU
|
2014-12-31 01:08:31 +01:00
|
|
|
* NodeMCU Team
|
|
|
|
* 2014-12-31
|
2014-12-30 19:47:44 +01:00
|
|
|
*******************************************************************************/
|
|
|
|
#include "user_config.h"
|
|
|
|
#include "flash_api.h"
|
|
|
|
#include "spi_flash.h"
|
2019-07-21 23:58:21 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2014-12-30 19:47:44 +01:00
|
|
|
|
2015-03-15 17:48:28 +01:00
|
|
|
uint32_t flash_detect_size_byte(void)
|
|
|
|
{
|
2017-05-16 16:50:36 +02:00
|
|
|
// enable operations on whole physical flash, SDK might have restricted
|
|
|
|
// the flash size already
|
|
|
|
extern SpiFlashChip * flashchip;
|
|
|
|
uint32 orig_chip_size = flashchip->chip_size;
|
|
|
|
flashchip->chip_size = FLASH_SIZE_16MBYTE;
|
|
|
|
|
2015-03-15 17:51:47 +01:00
|
|
|
#define FLASH_BUFFER_SIZE_DETECT 32
|
2015-03-15 17:48:28 +01:00
|
|
|
uint32_t dummy_size = FLASH_SIZE_256KBYTE;
|
2015-03-15 17:51:47 +01:00
|
|
|
uint8_t data_orig[FLASH_BUFFER_SIZE_DETECT] ICACHE_STORE_ATTR = {0};
|
|
|
|
uint8_t data_new[FLASH_BUFFER_SIZE_DETECT] ICACHE_STORE_ATTR = {0};
|
2017-05-16 16:50:36 +02:00
|
|
|
if (SPI_FLASH_RESULT_OK == flash_read(0, (uint32 *)data_orig, FLASH_BUFFER_SIZE_DETECT))
|
2015-03-15 17:48:28 +01:00
|
|
|
{
|
|
|
|
dummy_size = FLASH_SIZE_256KBYTE;
|
|
|
|
while ((dummy_size < FLASH_SIZE_16MBYTE) &&
|
2017-05-16 16:50:36 +02:00
|
|
|
(SPI_FLASH_RESULT_OK == flash_read(dummy_size, (uint32 *)data_new, FLASH_BUFFER_SIZE_DETECT)) &&
|
2019-07-21 23:58:21 +02:00
|
|
|
(0 != memcmp(data_orig, data_new, FLASH_BUFFER_SIZE_DETECT))
|
2015-03-15 17:51:47 +01:00
|
|
|
)
|
2015-03-15 17:48:28 +01:00
|
|
|
{
|
|
|
|
dummy_size *= 2;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-16 16:50:36 +02:00
|
|
|
// revert temporary setting
|
|
|
|
flashchip->chip_size = orig_chip_size;
|
2015-03-15 17:48:28 +01:00
|
|
|
|
2017-05-16 16:50:36 +02:00
|
|
|
return dummy_size;
|
|
|
|
#undef FLASH_BUFFER_SIZE_DETECT
|
2015-03-15 17:48:28 +01:00
|
|
|
}
|
|
|
|
|
2019-04-05 17:01:45 +02:00
|
|
|
static SPIFlashInfo spi_flash_info = {0};
|
|
|
|
|
|
|
|
SPIFlashInfo *flash_rom_getinfo(void)
|
2015-01-05 03:09:51 +01:00
|
|
|
{
|
2019-04-05 17:01:45 +02:00
|
|
|
if (spi_flash_info.entry_point == 0) {
|
|
|
|
spi_flash_read(0, (uint32 *)(& spi_flash_info), sizeof(spi_flash_info));
|
|
|
|
}
|
|
|
|
return &spi_flash_info;
|
2014-12-30 19:47:44 +01:00
|
|
|
}
|
|
|
|
|
2015-03-15 17:48:28 +01:00
|
|
|
uint8_t flash_rom_get_size_type(void)
|
2014-12-31 01:08:31 +01:00
|
|
|
{
|
2019-04-05 17:01:45 +02:00
|
|
|
return flash_rom_getinfo()->size;
|
2014-12-31 01:08:31 +01:00
|
|
|
}
|
|
|
|
|
2015-03-15 17:48:28 +01:00
|
|
|
uint32_t flash_rom_get_size_byte(void)
|
2014-12-30 19:47:44 +01:00
|
|
|
{
|
2015-03-15 17:51:47 +01:00
|
|
|
static uint32_t flash_size = 0;
|
|
|
|
if (flash_size == 0)
|
2014-12-30 19:47:44 +01:00
|
|
|
{
|
2019-04-05 17:01:45 +02:00
|
|
|
switch (flash_rom_getinfo()->size)
|
2015-03-15 17:51:47 +01:00
|
|
|
{
|
|
|
|
case SIZE_2MBIT:
|
|
|
|
// 2Mbit, 256kByte
|
|
|
|
flash_size = 256 * 1024;
|
|
|
|
break;
|
|
|
|
case SIZE_4MBIT:
|
|
|
|
// 4Mbit, 512kByte
|
|
|
|
flash_size = 512 * 1024;
|
|
|
|
break;
|
|
|
|
case SIZE_8MBIT:
|
|
|
|
// 8Mbit, 1MByte
|
|
|
|
flash_size = 1 * 1024 * 1024;
|
|
|
|
break;
|
|
|
|
case SIZE_16MBIT:
|
|
|
|
// 16Mbit, 2MByte
|
|
|
|
flash_size = 2 * 1024 * 1024;
|
|
|
|
break;
|
|
|
|
case SIZE_32MBIT:
|
|
|
|
// 32Mbit, 4MByte
|
|
|
|
flash_size = 4 * 1024 * 1024;
|
|
|
|
break;
|
2015-12-30 02:49:01 +01:00
|
|
|
case SIZE_16MBIT_8M_8M:
|
|
|
|
// 16Mbit, 2MByte
|
|
|
|
flash_size = 2 * 1024 * 1024;
|
2015-03-15 17:51:47 +01:00
|
|
|
break;
|
2015-12-30 02:49:01 +01:00
|
|
|
case SIZE_32MBIT_8M_8M:
|
|
|
|
// 32Mbit, 4MByte
|
|
|
|
flash_size = 4 * 1024 * 1024;
|
2015-03-15 17:51:47 +01:00
|
|
|
break;
|
2016-06-26 14:16:39 +02:00
|
|
|
case SIZE_32MBIT_16M_16M:
|
|
|
|
// 32Mbit, 4MByte
|
|
|
|
flash_size = 4 * 1024 * 1024;
|
|
|
|
break;
|
|
|
|
case SIZE_64MBIT:
|
|
|
|
// 64Mbit, 8MByte
|
|
|
|
flash_size = 8 * 1024 * 1024;
|
|
|
|
break;
|
|
|
|
case SIZE_128MBIT:
|
|
|
|
// 128Mbit, 16MByte
|
|
|
|
flash_size = 16 * 1024 * 1024;
|
|
|
|
break;
|
2015-03-15 17:51:47 +01:00
|
|
|
default:
|
|
|
|
// Unknown flash size, fall back mode.
|
|
|
|
flash_size = 512 * 1024;
|
|
|
|
break;
|
|
|
|
}
|
2014-12-30 19:47:44 +01:00
|
|
|
}
|
|
|
|
return flash_size;
|
|
|
|
}
|
|
|
|
|
2015-03-15 17:48:28 +01:00
|
|
|
uint16_t flash_rom_get_sec_num(void)
|
2014-12-30 19:47:44 +01:00
|
|
|
{
|
2015-03-15 17:48:28 +01:00
|
|
|
return ( flash_rom_get_size_byte() / (SPI_FLASH_SEC_SIZE) );
|
2014-12-30 19:51:36 +01:00
|
|
|
}
|
2014-12-31 01:08:31 +01:00
|
|
|
|
2015-03-15 17:48:28 +01:00
|
|
|
uint8_t flash_rom_get_mode(void)
|
2014-12-31 01:08:31 +01:00
|
|
|
{
|
2019-04-05 17:01:45 +02:00
|
|
|
uint8_t mode = flash_rom_getinfo()->mode;
|
|
|
|
switch (mode)
|
2014-12-31 01:08:31 +01:00
|
|
|
{
|
|
|
|
// Reserved for future use
|
|
|
|
case MODE_QIO:
|
|
|
|
break;
|
|
|
|
case MODE_QOUT:
|
|
|
|
break;
|
|
|
|
case MODE_DIO:
|
|
|
|
break;
|
|
|
|
case MODE_DOUT:
|
|
|
|
break;
|
|
|
|
}
|
2019-04-05 17:01:45 +02:00
|
|
|
return mode;
|
2014-12-31 01:08:31 +01:00
|
|
|
}
|
|
|
|
|
2015-03-15 17:48:28 +01:00
|
|
|
uint32_t flash_rom_get_speed(void)
|
2014-12-31 01:08:31 +01:00
|
|
|
{
|
|
|
|
uint32_t speed = 0;
|
2019-04-05 17:01:45 +02:00
|
|
|
uint8_t spi_speed = flash_rom_getinfo()->speed;
|
|
|
|
switch (spi_speed)
|
2014-12-31 01:08:31 +01:00
|
|
|
{
|
|
|
|
case SPEED_40MHZ:
|
|
|
|
// 40MHz
|
|
|
|
speed = 40000000;
|
|
|
|
break;
|
|
|
|
case SPEED_26MHZ:
|
|
|
|
//26.7MHz
|
|
|
|
speed = 26700000;
|
|
|
|
break;
|
|
|
|
case SPEED_20MHZ:
|
|
|
|
// 20MHz
|
|
|
|
speed = 20000000;
|
|
|
|
break;
|
|
|
|
case SPEED_80MHZ:
|
|
|
|
//80MHz
|
|
|
|
speed = 80000000;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return speed;
|
|
|
|
}
|
|
|
|
|
2015-02-14 17:02:53 +01:00
|
|
|
uint8_t byte_of_aligned_array(const uint8_t *aligned_array, uint32_t index)
|
2015-01-06 18:15:38 +01:00
|
|
|
{
|
2015-02-14 17:02:53 +01:00
|
|
|
if ( (((uint32_t)aligned_array) % 4) != 0 )
|
|
|
|
{
|
2015-01-06 18:15:38 +01:00
|
|
|
NODE_DBG("aligned_array is not 4-byte aligned.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2015-05-05 17:59:30 +02:00
|
|
|
volatile uint32_t v = ((uint32_t *)aligned_array)[ index / 4 ];
|
2015-01-06 18:15:38 +01:00
|
|
|
uint8_t *p = (uint8_t *) (&v);
|
2015-02-14 17:02:53 +01:00
|
|
|
return p[ (index % 4) ];
|
2015-01-06 18:15:38 +01:00
|
|
|
}
|
2015-03-15 22:40:43 +01:00
|
|
|
|
2015-05-05 17:59:30 +02:00
|
|
|
uint16_t word_of_aligned_array(const uint16_t *aligned_array, uint32_t index)
|
|
|
|
{
|
|
|
|
if ( (((uint32_t)aligned_array) % 4) != 0 )
|
|
|
|
{
|
|
|
|
NODE_DBG("aligned_array is not 4-byte aligned.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
volatile uint32_t v = ((uint32_t *)aligned_array)[ index / 2 ];
|
|
|
|
uint16_t *p = (uint16_t *) (&v);
|
|
|
|
return (index % 2 == 0) ? p[ 0 ] : p[ 1 ];
|
|
|
|
}
|
|
|
|
|