/**
 ****************************************************************************************
 * @brief Write data to flash across page boundaries and at any starting address
 *
 * @param[in] *wr_data_ptr:  Pointer to the data to be written
 * @param[in] address:       Starting address of page to be written (must be a multiple of SPI Flash page size)
 * @param[in] size:          Size of the data to be written (can be larger than SPI Flash page size)
 * 
 * @return  Number of bytes actually written
 ****************************************************************************************
 */
int32_t spi_flash_write_data (uint8_t *wr_data_ptr, uint32_t address, uint32_t size)
{
	uint32_t bytes_written; 
	uint32_t feasible_size = size;
	uint32_t currentAddress = address;
	uint32_t currentEndOfPage = (currentAddress / spi_flash_page_size + 1) * spi_flash_page_size - 1;
	uint32_t bytes_left_to_send;

	spi_set_bitmode(SPI_MODE_8BIT);
    
  	// limit to the maximum count of bytes that can be written to a (SPI_FLASH_SIZE x 8) flash
	if (size > spi_flash_size - address)
		feasible_size = spi_flash_size - address;
 
	bytes_left_to_send = feasible_size;
	bytes_written = 0;
	
	while (bytes_written < feasible_size)
	{
		// limit the transaction to the upper limit of the current page
		if (currentAddress + bytes_left_to_send > currentEndOfPage)
			bytes_left_to_send = currentEndOfPage - currentAddress + 1;             
		if (spi_flash_page_program(wr_data_ptr + bytes_written, currentAddress, bytes_left_to_send) != ERR_OK) //write the current page data
			return ERR_TIMEOUT;
		bytes_written += bytes_left_to_send;                                                     
		currentAddress = currentEndOfPage + 1;  //address points to the first memory position of the next page
		currentEndOfPage += spi_flash_page_size;
		bytes_left_to_send = feasible_size - bytes_written;
	}
	return bytes_written;
}
/**
*	@fn			spi_flash_pp
*	@brief		Program data of size less than a page (256 bytes) at the SPI flash
*	@param[IN]	u32Offset
*					Address to write to at the SPI flash
*	@param[IN]	pu8Buf
*					Pointer to data buffer
*	@param[IN]	u32Sz
*					Data size
*	@return		Status of execution
*/
static sint8 spi_flash_pp(uint32 u32Offset, uint8 *pu8Buf, uint16 u16Sz)
{
	sint8 ret = M2M_SUCCESS;
	uint8 tmp;
	spi_flash_write_enable();
	/* use shared packet memory as temp mem */
	ret += nm_write_block(HOST_SHARE_MEM_BASE, pu8Buf, u16Sz);
	ret += spi_flash_page_program(HOST_SHARE_MEM_BASE, u32Offset, u16Sz);
	ret += spi_flash_read_status_reg(&tmp);
	do
	{
		if(ret != M2M_SUCCESS) goto ERR;
		ret += spi_flash_read_status_reg(&tmp);
	}while(tmp & 0x01);
	ret += spi_flash_write_disable();
ERR:
	return ret;
}