uSD loader of Wipom board


The 2nd loader to boot from uSD memory.

Toolkit:STM Development System

Location:/bipom/devtools/STM32/examples/Wipom/usd_loader

Code Example


#include "usd_storage.h"

UBYTE  IAP_Buf[IAP_BUF_SIZE];


//********************************************************************************

void Puts(char* str)
{
#ifdef uSD_LOADER_ENABLE_MESSAGES
	for (;*str;) putChar(*str++);
#endif	
}


//********************************************************************************

static void cmd_run (ULONG run_addr)
{
	PFV fp;
	//

	fp = (PFV)(*(__IO uint32_t*) (run_addr+4));
	#ifdef uSD_LOADER_ENABLE_DEBUG_MESSAGES
	tprintf("\n\rRun applicaiton at 0x%x...", run_addr);
	#endif
	Puts ("\n\r");
	delayMs(50);
	/* Initialize user application's Stack Pointer */
	__set_MSP(*(__IO uint32_t*) run_addr);
    // remap Vector table

	//SCB->VTOR = run_addr | ((uint32_t)&_isr_vectors_offs & (uint32_t)0x1FFFFF80);;

	// Jump to application;

 	(*fp)(); 
}


//********************************************************************************

static void cmd_reset (void)
{
	PFV fp;
	fp = (PFV)(RESET_ADDR+4);
	 __set_MSP(*(__IO uint32_t*) RESET_ADDR);
	(*fp)();
}


//********************************************************************************

static ERRCODE Remove_Update(void)
{
	ERRCODE ec=SUCCESS;
	APP_INFO *pINFO = (APP_INFO *)IAP_Buf;
	// Read the whole sector

	if (ReadMemory_uSD_LOADER(IAP_Buf,0,DATASTORAGEAPI_SECTOR_SIZE))	
	{
		ec = ERROR;
		goto func_end;	
	}
	// Reset the update flag in the buffer

	pINFO->update = 0;
	// Re-calculate the checks

	pINFO->crc16 = Crc16_uSD_LOADER((ULONG)pINFO,sizeof(APP_INFO)-sizeof(USHORT),uC_MEMORY);
	// Copy the RAM buffer back

	ec = WriteMemory_uSD_LOADER(IAP_Buf,0); 
	//

func_end:	
	return ec;		
}


//********************************************************************************

static ULONG APP_Update(ULONG start_addr, ULONG app_size_byte)
{
	ULONG	current_addr;
	ULONG	sector_index;
	ULONG	iap_prog_cnt;
	ULONG	new_sector;
	ULONG	sector_size, sector_size_sum;
	ULONG  update_addr;
	ULONG  retCode;
	ULONG	block_size;
	ULONG	data_cnt;
	//

	FLASH_Unlock();
	//

	iap_prog_cnt = (app_size_byte+IAP_BUF_SIZE-1)  IAP_BUF_SIZE;
	#ifdef uSD_LOADER_ENABLE_DEBUG_MESSAGES
	tprintf("\n\rApp size: %d bytes, iap program number: %d (%d bytes once).\n", 
		app_size_byte, iap_prog_cnt, IAP_BUF_SIZE);
	#endif	
	//

	new_sector = 1;
	update_addr = PROG_ADDR;
	current_addr = start_addr;
	sector_index = update_addr>>IAP_SHIFT_BITS;
	data_cnt = 0;
	while (iap_prog_cnt != 0)
	{
		block_size = app_size_byte - data_cnt;
		if(block_size > IAP_BUF_SIZE) block_size = IAP_BUF_SIZE; 
		// Copy the next data to IAP_Buf

		if(ReadMemory_uSD_LOADER(IAP_Buf,current_addr,block_size)) 
		{
			app_size_byte =0;
			break;
		}
		// Check if we start a new sector

		if (new_sector)
		{
			#ifdef uSD_LOADER_ENABLE_DEBUG_MESSAGES
			tprintf("\n\rPrepare and erase sector %d.\n", sector_index);
			#endif
			if ((retCode =IAP_PrepareErase(sector_index)) != 0)
			{
				#ifdef uSD_LOADER_ENABLE_DEBUG_MESSAGES
				tprintf("\n\rFailed to erase sector %d, ec=%lu\n", 
					sector_index,retCode);
				#endif
				Puts ("\n\rERROR: can't erase Flash sector");	
				return 0;
			}
			sector_size = IAP_BUF_SIZE;
			sector_size_sum = 0;
			new_sector = 0;	
		}
		//

		#ifdef uSD_LOADER_ENABLE_DEBUG_MESSAGES
		tprintf("\n\rProgram at addr 0x%x.\n", update_addr);
		#endif
		if (IAP_Program(sector_index, update_addr) != 0)
		{
			#ifdef uSD_LOADER_ENABLE_DEBUG_MESSAGES
			tprintf("\n\rFailed to program secotr %d.\n", sector_index);
			#endif
			Puts ("\n\rERROR: can't write Flash data");	
			app_size_byte =0;
			break;
		}
		//			

		update_addr += IAP_BUF_SIZE;
		sector_size_sum += 	IAP_BUF_SIZE;
		current_addr += IAP_BUF_SIZE; 
		iap_prog_cnt--;
		data_cnt += block_size;
		if (sector_size_sum	== sector_size)
		{
			sector_index++;
			new_sector = 1;
		}			
	}
	//

	FLASH_Lock();
	return app_size_byte;
}

//********************************************************************************

// prepare and erase sector with specified index,

// if OK, return 0, otherwise return the error code */

//********************************************************************************

ERRCODE IAP_PrepareErase(ULONG sector_index)
{
	ERRCODE ec = SUCCESS;
	if(FLASH_COMPLETE != FLASH_ErasePage(sector_index<<IAP_SHIFT_BITS)) ec = ERROR;
	return ec;	
}


//********************************************************************************

// program content in IAP_Buf to internal flash with address of 

// app_addr, and sector index of sector_index.

// if ok, return 0, otherwise return the error code. */

//********************************************************************************

ERRCODE IAP_Program(ULONG sector_index, ULONG app_addr)
{
	ERRCODE ec = SUCCESS;
	ULONG address = (sector_index<<IAP_SHIFT_BITS);
	ULONG* ramData = (ULONG*)IAP_Buf;
	ULONG ndx; 
	for ( ndx =0 ; ndx < (IAP_BUF_SIZE>>2) ; ndx++)
	{  
		if(FLASH_COMPLETE != FLASH_ProgramWord(address,ramData[ndx]))
		{
			ec = ERROR;
			break;
		}
		if( (*((ULONG*)address)) != ramData[ndx] )
		{
			ec = ERROR;
			break;
		}
		address += 4;
	}
	//

	return ec;	
}


//********************************************************************************

int main (void) 
{
	APP_INFO info;
	ULONG address;
	ULONG size;
	ERRCODE ec = SUCCESS;
	//

	Init_uSD_LOADER();
	//

	Puts ("\n\ruSD Boot Loader ");
	Puts (uSD_LOADER_REVISION);
	Puts ("\n\rDate: ");
	Puts (__DATE__);
	Puts (" Time: ");
	Puts (__TIME__);
	// Test uSD and Virtual memory

	#ifdef LOCAL_uSD_TEST
		Local_uSD_Test();
	#endif	
	// Read uSD to get the APP INFO structure

	if (ReadMemory_uSD_LOADER((UBYTE *)&info,0,sizeof(APP_INFO)))	info.update =0;
	//

	address	= sizeof(APP_INFO);
	size		= info.size;
	//

	//Check if we need to update the application code

	if(UPDATE_FLAG == info.update)
	{ 
		// Check the application size

		if(MAX_APP_SIZE > info.size)
		{	
			// Check if Crc16 of header is OK

			if(info.crc16 == Crc16_uSD_LOADER((ULONG)&info,sizeof(APP_INFO)-sizeof(USHORT),uC_MEMORY))
			{
				//

				if(info.checkSum == Crc16_uSD_LOADER(address,size,uSD_MEMORY))
				{
					ec = ERROR;
					//

					if(APP_Update(address,size)==size)  
					{
						Puts ("\n\rSUCCEES: new image is copied");
						if(info.checkSum == Crc16_uSD_LOADER(PROG_ADDR,size,uC_MEMORY)) 
						{
							ec = SUCCESS;
							Puts("\n\rSUCCEES: new application is updated");
							if(Remove_Update()) 
							{
								Puts("\n\rWARNING: can't remove update status");	
							}
						} else	Puts("\n\rERROR: invalid data check sum");
					}else 		Puts("\n\rERROR: can't update the image");
				} else 			Puts("\n\rERROR: invalid image check sum");
			} else 				Puts("\n\rERROR: invalid header check sum");
		} else 					Puts("\n\rERROR: too big image size");
 	}
 	Puts ("\n\rRun the application at 0x08010000 address");
 	Puts ("\n\r");
	// Run the application 

  	if(ec)	cmd_reset();
  	else	cmd_run(RUN_ADDR);
  	// We should never reach that code 

  	Puts ("\n\rERROR: can't run the application");
 	for (;;) cmd_reset();
	return 0; 	
}