/**
 * \brief Main application
 */
int main(void)
{
	uint32_t len;
	uint32_t curr_prog_addr;
	uint32_t tmp_len;
	uint8_t buff[NVMCTRL_PAGE_SIZE];
	struct nvm_config config;

	/* Check switch state to enter boot mode or application mode */
	check_boot_mode();

	/*
	 * Application to be programmed from APP_START_ADDRESS defined in
	 * conf_bootloader.h
	 */
	curr_prog_addr = APP_START_ADDRESS;

	/* Initialize system */
	system_init();


	/* Configure the SPI slave module */
	configure_spi();

	/* Get NVM default configuration and load the same */
	nvm_get_config_defaults(&config);
	config.manual_page_write = false;
	nvm_set_config(&config);

	/* Turn on LED */
	port_pin_set_output_level(BOOT_LED, false);
	/* Get the length to be programmed */
	len = get_length();

	do {
		/* Get remaining or NVMCTRL_PAGE_SIZE as block length */
		tmp_len = min(NVMCTRL_PAGE_SIZE, len);

		/* Acknowledge last received data */
		send_ack();

		/* Read data from SPI master */
		fetch_data(buff, tmp_len);

		/* Program the data into Flash */
		program_memory(curr_prog_addr, buff, tmp_len);

		/* Increment the current programming address */
		curr_prog_addr += tmp_len;

		/* Update the length to remaining length to be programmed */
		len -= tmp_len;

		/* Do this for entire length */
	} while (len != 0);

	/* Acknowledge last block */
	send_ack();

	/* Reset module and boot into application */
	NVIC_SystemReset();

	while (1) {
		/* Inf loop */
	}

}
/**
 * \brief Main application
 */
int main(void)
{
	char test_file_name[] = "0:sd_image.bin";
	FRESULT res;
	FATFS fs;
	FIL file_object;
	uint32_t len=0;
	uint32_t curr_prog_addr=APP_START_ADDRESS;
	struct nvm_config config;
	UINT iRead=0;
    
	check_boot_mode();
	system_init();
	delay_init();

	irq_initialize_vectors();
	cpu_irq_enable();

	/* Initialize SD MMC stack */
	sd_mmc_init();
	
	nvm_get_config_defaults(&config);
	nvm_set_config(&config);
		/* Turn ON  LED */
	port_pin_set_output_level(BOOT_LED, false);
#ifdef __DEBUG_PRINT__	
    serial_port_init();
	printf("\x0C\n\r-- SD/MMC Card FatFs Boot Loader --\n\r");
	printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
	printf("Please plug an SD/MMC card in slot.\n\r");
#endif	

		/* Wait card present and ready */
	sd_mmc_ready();
	memset(&fs, 0, sizeof(FATFS));
	res = f_mount(LUN_ID_SD_MMC_0_MEM, &fs);
	if (FR_INVALID_DRIVE == res) {
		#ifdef __DEBUG_PRINT__	
		printf("[FAIL] Mounting SD card failed result= %d\r\n", res);
		#endif
			
	}
	#ifdef __DEBUG_PRINT__	
	printf("Mounting the SD card successful...\r\n");
	#endif
   
	res =f_open(&file_object,(const char *)test_file_name,FA_READ);
	if(res != FR_OK) error_fatal(FILE_OPEN_ERROR);
	do {
		if(file_object.fsize > MAX_CODE_SIZE) error_fatal(MAX_SIZE_ERROR);
		res = f_read(&file_object, (void *) buff, MAX_BUF_SIZE, &iRead);
		if(res != FR_OK) error_fatal(FILE_READ_ERROR);
	
		/* Program the read data into Flash */
		if(iRead)
		{
			program_memory(curr_prog_addr, buff,iRead);
			#ifdef __DEBUG_PRINT__
			printf("*");
			#endif
		}

		/* Increment the current programming address */
		curr_prog_addr += iRead;
		len += iRead;
	
		if(len > MAX_CODE_SIZE)
		error_fatal(MAX_SIZE_ERROR);

		/* Do this till end of file */
	} while (iRead != 0);

#ifdef __DEBUG_PRINT__		
printf("\r\n[PROGRAMMING COMPLETED]..Resetting !!!!\r\n");
#endif
		// Intentionally not closing the file object to reduce code size !!!.
		start_application();
		while(1);
		 // Should have reset by now !!!.		
}