Beispiel #1
0
void ICACHE_FLASH_ATTR erase_user_config(void)
{
    user_config.valid=0x00;
    memset(user_config.ssid, 0, sizeof(user_config.ssid));
    memset(user_config.pwd, 0, sizeof(user_config.pwd));
    spi_flash_erase_sector(PRIV_PARAM_START_SEC);
    //wifi_init();
   // config_wifi_new();

}
void  
light_save_target_duty()
{
    printf("light_save_duty\n");
#if SAVE_LIGHT_PARAM
    spi_flash_erase_sector(PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE);
    spi_flash_write((PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE) * SPI_FLASH_SEC_SIZE,
                (uint32 *)&light_param, sizeof(struct light_saved_param));
#endif
}
Beispiel #3
0
ICACHE_FLASH_ATTR int
save_user_config(user_config_t *config)
{
	config->valid = CONFIG_VALID;
    spi_flash_erase_sector(PRIV_PARAM_START_SEC);
    uint32* data=(uint32*)config; 
    spi_flash_write((PRIV_PARAM_START_SEC) * SPI_FLASH_SEC_SIZE,
                        data, sizeof(user_config_t));
	return 0;
}
LOCAL void ICACHE_FLASH_ATTR user_esp_platform_save_param(struct esp_platform_saved_param *param) {
	struct esp_platform_sec_flag_param flag;

	spi_flash_read((ESP_PARAM_START_SEC + ESP_PARAM_FLAG) * SPI_FLASH_SEC_SIZE, (uint32 *) &flag, sizeof(struct esp_platform_sec_flag_param));

	if (flag.flag == 0) {
		spi_flash_erase_sector(ESP_PARAM_START_SEC + ESP_PARAM_SAVE_1);
		spi_flash_write((ESP_PARAM_START_SEC + ESP_PARAM_SAVE_1) * SPI_FLASH_SEC_SIZE, (uint32 *) param, sizeof(struct esp_platform_saved_param));
		flag.flag = 1;
		spi_flash_erase_sector(ESP_PARAM_START_SEC + ESP_PARAM_FLAG);
		spi_flash_write((ESP_PARAM_START_SEC + ESP_PARAM_FLAG) * SPI_FLASH_SEC_SIZE, (uint32 *) &flag, sizeof(struct esp_platform_sec_flag_param));
	} else {
		spi_flash_erase_sector(ESP_PARAM_START_SEC + ESP_PARAM_SAVE_0);
		spi_flash_write((ESP_PARAM_START_SEC + ESP_PARAM_SAVE_0) * SPI_FLASH_SEC_SIZE, (uint32 *) param, sizeof(struct esp_platform_saved_param));
		flag.flag = 0;
		spi_flash_erase_sector(ESP_PARAM_START_SEC + ESP_PARAM_FLAG);
		spi_flash_write((ESP_PARAM_START_SEC + ESP_PARAM_FLAG) * SPI_FLASH_SEC_SIZE, (uint32 *) &flag, sizeof(struct esp_platform_sec_flag_param));
	}
}
Beispiel #5
0
// function to do the actual writing to flash
// call repeatedly with more data (max len per write is the flash sector size (4k))
bool ICACHE_FLASH_ATTR rboot_write_flash(rboot_write_status *status, uint8 *data, uint16 len) {
	
	bool ret = false;
	uint8 *buffer;
	
	if (data == NULL || len == 0) {
		return true;
	}
	
	// get a buffer
	buffer = (uint8 *)os_malloc(len + status->extra_count);
	if (!buffer) {
		//os_printf("No ram!\r\n");
		return false;
	}

	// copy in any remaining bytes from last chunk
	memcpy(buffer, status->extra_bytes, status->extra_count);
	// copy in new data
	memcpy(buffer + status->extra_count, data, len);

	// calculate length, must be multiple of 4
	// save any remaining bytes for next go
	len += status->extra_count;
	status->extra_count = len % 4;
	len -= status->extra_count;
	memcpy(status->extra_bytes, buffer + len, status->extra_count);

	// check data will fit
	//if (status->start_addr + len < (status->start_sector + status->max_sector_count) * SECTOR_SIZE) {

		if (len > SECTOR_SIZE) {
			// to support larger writes we would need to erase current
			// (if not already done), next and possibly later sectors too
		} else {
			// check if the sector the write finishes in has been erased yet,
			// this is fine as long as data len < sector size
			if (status->last_sector_erased != (status->start_addr + len) / SECTOR_SIZE) {
				status->last_sector_erased = (status->start_addr + len) / SECTOR_SIZE;
				spi_flash_erase_sector(status->last_sector_erased);
			}
		}

		// write current chunk
		//os_printf("write addr: 0x%08x, len: 0x%04x\r\n", status->start_addr, len);
		if (spi_flash_write(status->start_addr, (uint32 *)((void*)buffer), len) == SPI_FLASH_RESULT_OK) {
			ret = true;
			status->start_addr += len;
		}
	//}

	os_free(buffer);
	return ret;
}
Beispiel #6
0
bool flash_init_data_blank(void)
{
    // FLASH SEC - 2
    // Dangerous, here are dinosaur infested!!!!!
    // Reboot required!!!
    // It will init system config to blank!
    bool result = false;
#if defined(FLASH_SAFE_API)
    if ((SPI_FLASH_RESULT_OK == flash_safe_erase_sector((flash_safe_get_sec_num() - 2))) &&
            (SPI_FLASH_RESULT_OK == flash_safe_erase_sector((flash_safe_get_sec_num() - 1))))
#else
    if ((SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_rom_get_sec_num() - 2))) &&
            (SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_rom_get_sec_num() - 1))))
#endif // defined(FLASH_SAFE_API)
    {
        result = true;
    }

    return result ;
}
Beispiel #7
0
void EEPROMClass::commit()
{
    if (!_size || !_dirty)
        return;

    ETS_UART_INTR_DISABLE();
    spi_flash_erase_sector(CONFIG_SECTOR);
    spi_flash_write(CONFIG_ADDR, reinterpret_cast<uint32_t*>(_data), _size);
    ETS_UART_INTR_ENABLE();
    _dirty = false;
}
Beispiel #8
0
//=============================================================================
void ICACHE_FLASH_ATTR saveConfigs(void) {
	int result = -1;
	os_delay_us(100000);
	result = spi_flash_erase_sector(PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE);
	result = -1;
	os_delay_us(100000);
	result = spi_flash_write(
			(PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE) * SPI_FLASH_SEC_SIZE,
			(uint32 *) &configs, sizeof(u_CONFIG));

	ets_uart_printf("Write W = %d\r\n", result);
}
Beispiel #9
0
void env_save(void)
{
#ifndef CONFIG_ENV_NOWRITE
	current_env->crc = crc16((const unsigned char*)&current_env->occupied, current_env_size + sizeof(uint16_t) );
	spi_flash_erase_sector(current_env_flash_addr / SPI_FLASH_SEC_SIZE);
	spi_flash_write(current_env_flash_addr, (uint32*)current_env, 
			current_env_size + sizeof(uint16_t));
#else
	console_printf("Saving environment to flash disabled by config\n");
	console_printf("Recompile with CONFIG_ENV_NOWRITE=n\n");
#endif	
}
Beispiel #10
0
/* erase_block */
void ICACHE_FLASH_ATTR erase_block(int iAddress)
{
	if (0 == (iAddress % SPI_FLASH_SEC_SIZE))
	{
		/* erase block */

#ifdef FLASH_DEBUG
		os_printf("erase_block: erasing flash at 0x%x\n", iAddress / SPI_FLASH_SEC_SIZE);
#endif

		spi_flash_erase_sector(iAddress / SPI_FLASH_SEC_SIZE);
	}
}
Beispiel #11
0
static s32_t esp_spiffs_erase(u32_t addr, u32_t size) {
  /*
   * With proper configurarion spiffs always
   * provides here sector address & sector size
   */
  if (size != FLASH_BLOCK_SIZE || addr % FLASH_BLOCK_SIZE != 0) {
    LOG(LL_ERROR, ("Invalid size provided to esp_spiffs_erase (%d, %d)",
                   (int) addr, (int) size));
    return SPIFFS_ERR_NOT_CONFIGURED;
  }

  return spi_flash_erase_sector(addr / FLASH_BLOCK_SIZE);
}
Beispiel #12
0
//Init function 
void ICACHE_FLASH_ATTR
user_init() {
	uint8 data[] = "Hello World";
	uint8 hello[0x1000] = "1111111111";
	uint32_t i;
  extern void ets_wdt_disable(void);


  uart_init(BIT_RATE_115200, BIT_RATE_115200);
  uart_tx_one_char(system_update_cpu_freq(SYS_CPU_160MHZ));
  os_install_putc1(uart_tx_one_char);
  spi_flash_erase_sector(0x12);
/*  if ( spi_flash_write( 0x12000, (uint32 *)data, 10 ) != 0 ){

	  ets_uart_printf("Error");

  } else {
	  ets_uart_printf("Write done");
	  if ( spi_flash_read( 0x12000, (uint32 *)hello, 10 ) != 0 ){

	 	  ets_uart_printf("Error");

	   } else {
		   ets_uart_printf("Read done");
	  uart_tx_one_char(hello[0]);
	  uart_tx_one_char(hello[1]);
	  uart_tx_one_char(hello[2]);
	  uart_tx_one_char(hello[3]);
	  uart_tx_one_char(hello[4]);
	  uart_tx_one_char(hello[5]);
	  uart_tx_one_char(hello[6]);
	  uart_tx_one_char(hello[7]);
	  uart_tx_one_char(hello[8]);
	  uart_tx_one_char(hello[9]);
	  ets_uart_printf("done");
	   }

  }

  */

  spi_flash_write( 0x12000 + 501, (uint32 *)data, 5 );
  spi_flash_read( 0x12000 , (uint32 *)hello, 0x1000 );
  for (  i = 0; i < 0x1000; i++ ){
	  uart_tx_one_char(hello[i]);
  }
/*  spi_flash_read( 0x13000, (uint32 *)hello, 0x1000 );
  for (  i = 0; i < 0x1000; i++ ){
	  uart_tx_one_char(hello[i]);
  }*/
}
void ICACHE_FLASH_ATTR 
peri_rgb_light_param_set( struct LIGHT_PARAM light_param)
{
    pwm_set_freq(light_param.pwm_freq);
    pwm_set_duty(light_param.pwm_duty[0], 0); // red colour.
    pwm_set_duty(light_param.pwm_duty[1], 1); // green colour.
    pwm_set_duty(light_param.pwm_duty[2], 2); // blue colour.
    
    pwm_start();
    
    spi_flash_erase_sector(PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE);
	spi_flash_write((PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE) * SPI_FLASH_SEC_SIZE,
	    (uint32 *)&light_param, sizeof(struct LIGHT_PARAM));
}
void ICACHE_FLASH_ATTR
light_save_target_duty() {
	extern struct light_saved_param light_param;

	os_memcpy(light_param.pwm_duty, current_duty, sizeof(light_param.pwm_duty));
	light_param.pwm_period = pwm_get_period();

#if SAVE_LIGHT_PARAM
	spi_flash_erase_sector(PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE);
	spi_flash_write((PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE) * SPI_FLASH_SEC_SIZE,
			(uint32 *)&light_param, sizeof(struct light_saved_param));
#endif

}
Beispiel #15
0
// function to do the actual writing to flash
// call repeatedly with more data (max len per write is the flash sector size (4k))
bool ICACHE_FLASH_ATTR rboot_write_flash(rboot_write_status *status, uint8 *data, uint16 len) {
	
	bool ret = false;
	uint8 *buffer;
	int32 lastsect;
	
	if (data == NULL || len == 0) {
		return true;
	}
	
	// get a buffer
	buffer = (uint8 *)os_malloc(len + status->extra_count);
	if (!buffer) {
		//os_printf("No ram!\r\n");
		return false;
	}

	// copy in any remaining bytes from last chunk
	memcpy(buffer, status->extra_bytes, status->extra_count);
	// copy in new data
	memcpy(buffer + status->extra_count, data, len);

	// calculate length, must be multiple of 4
	// save any remaining bytes for next go
	len += status->extra_count;
	status->extra_count = len % 4;
	len -= status->extra_count;
	memcpy(status->extra_bytes, buffer + len, status->extra_count);

	// check data will fit
	//if (status->start_addr + len < (status->start_sector + status->max_sector_count) * SECTOR_SIZE) {

		// erase any additional sectors needed by this chunk
		lastsect = ((status->start_addr + len) - 1) / SECTOR_SIZE;
		while (lastsect > status->last_sector_erased) {
			status->last_sector_erased++;
			spi_flash_erase_sector(status->last_sector_erased);
		}

		// write current chunk
		//os_printf("write addr: 0x%08x, len: 0x%04x\r\n", status->start_addr, len);
		if (spi_flash_write(status->start_addr, (uint32 *)((void*)buffer), len) == SPI_FLASH_RESULT_OK) {
			ret = true;
			status->start_addr += len;
		}
	//}

	os_free(buffer);
	return ret;
}
Beispiel #16
0
void ICACHE_FLASH_ATTR
CFG_Save() {
	spi_flash_read((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, (uint32 *) &saveFlag,
			sizeof(SAVE_FLAG));

	if (saveFlag.flag == 0) {
		spi_flash_erase_sector(CFG_LOCATION + 1);
		spi_flash_write((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, (uint32 *) &sysCfg,
				sizeof(SYSCFG));
		saveFlag.flag = 1;
		spi_flash_erase_sector(CFG_LOCATION + 3);
		spi_flash_write((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, (uint32 *) &saveFlag,
				sizeof(SAVE_FLAG));
	} else {
		spi_flash_erase_sector(CFG_LOCATION + 0);
		spi_flash_write((CFG_LOCATION + 0) * SPI_FLASH_SEC_SIZE, (uint32 *) &sysCfg,
				sizeof(SYSCFG));
		saveFlag.flag = 0;
		spi_flash_erase_sector(CFG_LOCATION + 3);
		spi_flash_write((CFG_LOCATION + 3) * SPI_FLASH_SEC_SIZE, (uint32 *) &saveFlag,
				sizeof(SAVE_FLAG));
	}
}
Beispiel #17
0
//////////////////////////////////////////////////////////////////////////////////
// page1: set function.
//////////////////////////////////////////////////////////////////////////////////
void ICACHE_FLASH_ATTR flash_param_set_dev_uuid(int index, char *buffer, int len)
{
    if ((len < DEV_UUID_LEN) || (index >= 4))
    {
        return;
    }
    
    read_all(rbuffer, 256);
    os_memcpy(&rbuffer[index*DEV_UUID_LEN], buffer, DEV_UUID_LEN);

    spi_flash_erase_sector(BASIC_PARAM_SEC + USER_PARAM_BASIC);
    spi_flash_write((BASIC_PARAM_SEC + USER_PARAM_BASIC) * SPI_FLASH_SEC_SIZE,
            	     (unsigned int *)rbuffer, 256);
}
Beispiel #18
0
void ICACHE_FLASH_ATTR flash_write() {
    os_printf("flashWrite() size-%d\n", sizeof(FlashData));
    ETS_UART_INTR_DISABLE();

    spi_flash_erase_sector(PRIV_PARAM_START_SEC + PRIV_PARAM_SAVE);
    spi_flash_write(0x3c000, (uint32 *)flashData, sizeof(FlashData));

    ETS_UART_INTR_ENABLE();

  // spi_flash_read(0x3C000, (uint32 *) settings, 1024);
 
  // spi_flash_erase_sector(0x3C);
  // spi_flash_write(0x3C000,(uint32 *)settings,1024);
 
}
Beispiel #19
0
bool ICACHE_FLASH_ATTR otb_conf_save(otb_conf_struct *conf)
{
  bool rc;

  DEBUG("CONF: otb_conf_save entry");

  spi_flash_erase_sector(OTB_CONF_LOCATION/0x1000);
  rc = otb_util_flash_write((uint32)OTB_CONF_LOCATION,
                            (uint32 *)conf,
                            sizeof(otb_conf_struct));

  DEBUG("CONF: otb_conf_save exit");

  return rc;
}
bool flash_set_size(uint8_t size)
{
    // Dangerous, here are dinosaur infested!!!!!
    // Reboot required!!!
    // If you don't know what you're doing, your nodemcu may turn into stone ...
    uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR;
    spi_flash_read(0, (uint32 *)data, sizeof(data));
    SPIFlashInfo *p_spi_flash_info = (SPIFlashInfo *)(data);
    p_spi_flash_info->size = size;
    spi_flash_erase_sector(0);
    spi_flash_write(0, (uint32 *)data, sizeof(data));
    //p_spi_flash_info = flash_get_info();
    //p_spi_flash_info->size = size;
    return true;
}
Beispiel #21
0
void ICACHE_FLASH_ATTR user_params_set(char *valbuf, int buflen)
{
	spi_flash_erase_sector(0x10000 / (SPI_FLASH_SEC_SIZE) - 1);
	SpiFlashOpResult succ = spi_flash_write(0x10000-(SPI_FLASH_SEC_SIZE), (uint32 *)valbuf, buflen);
	if (succ == SPI_FLASH_RESULT_OK)
	{
		DEBUG_MSG("user_params_set: (len=%d) %s\n", buflen, valbuf);
		os_memset(valbuf, 0x00, buflen);
		user_params_get(valbuf, buflen);
	}
	else
	{
		__printf("failed to set user params! %d\n", succ);
	}
}
/**
 * Erase sectors in given range.
 *
 * @param startAddress Start address.
 * @param endAddress End address.
 * @return None.
 */
void flash_erase(uint32 startAddress, uint32 endAddress)
{

	uint32 currentAddress = startAddress & ~(0x00000FFF);

	do
	{
		if (spi_flash_erase_sector(currentAddress / 0x1000)
				!= SPI_FLASH_RESULT_OK)
		{
			return;
		}

		currentAddress += 0x1000;
	} while (currentAddress <= endAddress);
}
bool flash_init_data_default(void)
{
    // FLASH SEC - 4
    // Dangerous, here are dinosaur infested!!!!!
    // Reboot required!!!
    // It will init system data to default!
    bool result = false;
    if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_get_sec_num() - 4)))
    {
        if (SPI_FLASH_RESULT_OK == spi_flash_write((flash_get_sec_num() - 4) * SPI_FLASH_SEC_SIZE, (uint32 *)flash_init_data, 128))
        {
            result = true;
        }
    }
    return result;
}
//write string to flash
void ICACHE_FLASH_ATTR
debug_DumpToFlash(uint8* data, uint16 len)
{
    if(len%4 != 0){
        ESP_DBG("4Bytes ...\r\n");
        return;
    }
    
    if(FlashDumpBufParam.InPos % 0x1000 ==0)
        spi_flash_erase_sector(FlashDumpBufParam.InPos / 0x1000);

    if(FlashDumpBufParam.InPos+len <  FlashDumpBufParam.StartAddr+FlashDumpBufParam.Size ){
        spi_flash_write(FlashDumpBufParam.InPos,(uint32 *)data,len);
		ESP_DBG("addr: 0x%08x :  %d \r\n",FlashDumpBufParam.InPos,len);
        FlashDumpBufParam.InPos+=len;
    }
}
Beispiel #25
0
static void flash_test_task(void *arg)
{
    struct flash_test_ctx *ctx = (struct flash_test_ctx *) arg;
    vTaskDelay(100 / portTICK_PERIOD_MS);
    const uint32_t sector = ctx->offset;
    printf("t%d\n", sector);
    printf("es%d\n", sector);
    if (spi_flash_erase_sector(sector) != ESP_OK) {
        ctx->fail = true;
        printf("Erase failed\r\n");
        xSemaphoreGive(ctx->done);
        vTaskDelete(NULL);
    }
    printf("ed%d\n", sector);

    vTaskDelay(0 / portTICK_PERIOD_MS);

    uint32_t val = 0xabcd1234;
    for (uint32_t offset = 0; offset < SPI_FLASH_SEC_SIZE; offset += 4) {
        if (spi_flash_write(sector * SPI_FLASH_SEC_SIZE + offset, (const uint8_t *) &val, 4) != ESP_OK) {
            printf("Write failed at offset=%d\r\n", offset);
            ctx->fail = true;
            break;
        }
    }
    printf("wd%d\n", sector);

    vTaskDelay(0 / portTICK_PERIOD_MS);

    uint32_t val_read;
    for (uint32_t offset = 0; offset < SPI_FLASH_SEC_SIZE; offset += 4) {
        if (spi_flash_read(sector * SPI_FLASH_SEC_SIZE + offset, (uint8_t *) &val_read, 4) != ESP_OK) {
            printf("Read failed at offset=%d\r\n", offset);
            ctx->fail = true;
            break;
        }
        if (val_read != val) {
            printf("Read invalid value=%08x at offset=%d\r\n", val_read, offset);
            ctx->fail = true;
            break;
        }
    }
    printf("td%d\n", sector);
    xSemaphoreGive(ctx->done);
    vTaskDelete(NULL);
}
app_action_t application_function_flash_erase(string_t *src, string_t *dst)
{
	unsigned int address, length;
	int sector_offset, sector_count, erased;
	uint32_t time_start, time_finish;

	if(parse_uint(1, src, &address, 0, ' ') != parse_ok)
	{
		string_append(dst, "ERROR flash-erase: offset required\n");
		return(app_action_error);
	}

	if(parse_uint(2, src, &length, 0, ' ') != parse_ok)
	{
		string_append(dst, "ERROR flash-erase: length required\n");
		return(app_action_error);
	}

	sector_offset = address / SPI_FLASH_SEC_SIZE;
	sector_count = length / SPI_FLASH_SEC_SIZE;

	if((address % SPI_FLASH_SEC_SIZE) != 0)
	{
		sector_offset--;
		sector_count++;
	}

	if((length % SPI_FLASH_SEC_SIZE) != 0)
		sector_count++;

	time_start = system_get_time();

	for(erased = 0; erased < sector_count; erased++)
	{
		system_soft_wdt_feed();
		if(spi_flash_erase_sector(sector_offset + erased) != SPI_FLASH_RESULT_OK)
			break;
	}

	time_finish = system_get_time();

	string_format(dst, "OK flash-erase: erased %d sectors from sector %d, in %lu milliseconds\n", erased - 1, sector_offset, (time_finish - time_start) / 1000);

	return(app_action_normal);
}
Beispiel #27
0
bool EEPROMClass::commit()
{
    bool ret = false;
    if (!_size)
        return false;
    if(!_dirty)
        return true;

    ETS_UART_INTR_DISABLE();
    if(spi_flash_erase_sector(CONFIG_SECTOR) == SPI_FLASH_RESULT_OK) {
        if(spi_flash_write(CONFIG_ADDR, reinterpret_cast<uint32_t*>(_data), _size) == SPI_FLASH_RESULT_OK) {
            _dirty = false;
            ret = true;
        }
    }
    ETS_UART_INTR_ENABLE();
    return ret;
}
uint8 ICACHE_FLASH_ATTR write_cfg_flash(rw_info* prw)
{
	//写入前,需要擦除
	if (spi_flash_erase_sector(FLASH_HEAD_ADDR / (4 * 1024))
			!= SPI_FLASH_RESULT_OK) {
		os_printf("SPI FLASH ERASE ERROR\n");
		return -1;
	}
	os_printf("SPI FLASH ERASE SUCCESS\n");

	//写入
	if (spi_flash_write(FLASH_HEAD_ADDR, (uint32*) prw, sizeof(rw_info))
			!= SPI_FLASH_RESULT_OK) {
		os_printf("SPI FLASH WRITE ERROR\n");
	}
	os_printf("SPI FLASH WRITE SUCCESS\n");

	return 0;
}
irom static app_action_t flash_write_verify(const string_t *src, string_t *dst)
{
	char *verify_buffer = string_to_ptr(dst);
	char *write_buffer = string_to_ptr(&buffer_4k);
	int write_buffer_length = string_length(&buffer_4k);

	if(string_size(dst) < 0x1000)
	{
		string_format(dst, "OTA: string verify buffer too small: %d\n", string_size(dst));
		return(app_action_error);
	}

	if(ota_state == state_write)
	{
		spi_flash_read(flash_sector * 0x1000, (void *)verify_buffer, write_buffer_length);

		if(ets_memcmp(write_buffer, verify_buffer, write_buffer_length))
		{
			spi_flash_erase_sector(flash_sector);
			spi_flash_write(flash_sector * 0x1000, (void *)write_buffer, write_buffer_length);
			written++;
		}
		else
			skipped++;
	}

	spi_flash_read(flash_sector * 0x1000, (void *)verify_buffer, write_buffer_length);
	MD5Update(&md5, verify_buffer, write_buffer_length);

	if(ets_memcmp(write_buffer, verify_buffer, write_buffer_length))
	{
		string_copy(dst, "OTA: verify mismatch\n");
		return(app_action_error);
	}

	flash_sector++;
	received += write_buffer_length;

	string_clear(&buffer_4k);
	string_clear(dst);

	return(app_action_normal);
}
/******************************************************************************
 * FunctionName : peri_jdq_set
 * Description  : set jdq on or off
 * Parameters   : uint8 on_off
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
peri_jdq_set(uint8 on_off)
{
	if(on_off==1)
	{
		 GPIO_OUTPUT_SET(jdq_pin, 1);
	     PRINTF("jdq ON\n");
	}
	else
	{
		 GPIO_OUTPUT_SET(jdq_pin, 0);
		 PRINTF("jdq OFF\n");
	}
    spi_flash_erase_sector(PRIV_PARAM_START_SEC + JDQ_FLASH_PRIV_SAVE);
	spi_flash_write((PRIV_PARAM_START_SEC + JDQ_FLASH_PRIV_SAVE) * SPI_FLASH_SEC_SIZE,
	    (uint32 *)&on_off, sizeof(uint8));


}