⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bootloader.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
字号:
/*************************************************************************** *             __________               __   ___. *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  / *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  < *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \ *                     \/            \/     \/    \/            \/ * $Id: bootloader.c,v 1.1 2003/11/30 11:37:42 hohensoh Exp $ * * Copyright (C) 2003 by J鰎g Hohensohn  *  * Second-level bootloader, with dual-boot feature by holding F1/Menu * This is the image being descrambled and executed by the boot ROM. * It's task is to copy Rockbox from Flash to DRAM. * The image(s) in flash may optionally be compressed with UCL 2e * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/#include "sh7034.h"#include "bootloader.h"#ifdef NO_ROM// start with the vector tableUINT32 vectors[] __attribute__ ((section (".vectors"))) = {	(UINT32)_main, // entry point, the copy routine	(UINT32)(end_stack - 1), // initial stack pointer	FLASH_BASE + 0x200, // source of image in flash	(UINT32)total_size, // size of image	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	0x03020080 // mask and version (just as a suggestion)};#else// our binary has to start with a vector to the entry pointtpMain start_vector[] __attribute__ ((section (".startvector"))) = {main};#endif#ifdef NO_ROM // some code which is only needed for the romless variantvoid _main(void){	UINT32* pSrc;	UINT32* pDest;	UINT32* pEnd;/*	asm volatile ("ldc %0,sr" : : "r"(0xF0)); // disable interrupts	asm volatile ("mov.l @%0,r15" : : "r"(4)); // load stack	asm volatile ("ldc %0,vbr" : : "r"(0)); // load vector base*/	// copy everything to IRAM and continue there	pSrc = begin_iramcopy;	pDest = begin_text;	pEnd = pDest + (begin_stack - begin_text);	do	{		*pDest++ = *pSrc++;	}	while (pDest < pEnd);	main(); // jump to the real main()}void BootInit(void){	// inits from the boot ROM, whether they make sense or not	PBDR &= 0xFFBF; // LED off (0x131E)	PBCR2 = 0; // all GPIO	PBIOR |= 0x40; // LED output	PBIOR &= 0xFFF1; // LCD lines input	// init DRAM like the boot ROM does	PACR2 &= 0xFFFB;	PACR2 |= 0x0008;	CASCR  = 0xAF;	BCR   |= 0x8000;	WCR1  &= 0xFDFD;	DCR    = 0x0E00;	RCR    = 0x5AB0;	RTCOR  = 0x9605;	RTCSR  = 0xA518;}#endif // #ifdef NO_ROMint main(void){	int nButton;	PlatformInit(); // model-specific inits	nButton = ButtonPressed();	if (nButton == 3)	{	// F3 means start monitor		MiniMon();	}	else	{		tImage* pImage;		pImage = GetStartImage(nButton); // which image		DecompressStart(pImage); // move into place and start it	}	return 0; // I guess we won't return  ;-)}// init code that is specific to certain platformvoid PlatformInit(void){#ifdef NO_ROM	BootInit(); // if not started by boot ROM, we need to init what it did#endif#if defined PLATFORM_PLAYER	BRR1  =  0x0019; // 14400 Baud for monitor	if (FW_VERSION > 451) // "new" Player?	{		PBDR &= ~0x10; // set PB4 to 0 to power-up the harddisk early		PBIOR |= 0x10; // make PB4 an output	}#elif defined PLATFORM_RECORDER	BRR1  =  0x0002; // 115200 Baud for monitor	if (ReadADC(7) > 0x100) // charger plugged?	{	// switch off the HD, else a flat battery may not start		PACR2 &= 0xFBFF; // GPIO for PA5		PAIOR |= 0x20;	 // make PA5 an output (low by default)	}#elif defined PLATFORM_FM	BRR1  =  0x0002; // 115200 Baud for monitor	PBDR |= 0x20; // set PB5 to keep power (fixes the ON-holding problem)	PBIOR |= 0x20; // make PB5 an output	if (ReadADC(0) < 0x1FF) // charger plugged?	{		// how do we switch this off?	}#endif	// platform-independent inits	DCR |= 0x1000; // enable burst mode on DRAM	BCR |= 0x2000; // activate Warp mode (simultaneous internal and external mem access)}// Thinned out version of the UCL 2e decompression sourcecode// Original (C) Markus F.X.J Oberhumer under GNU GPL license#define GETBIT(bb, src, ilen) \	(((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1) int ucl_nrv2e_decompress_8(	const UINT8 *src, UINT8 *dst, UINT32* dst_len){ 	UINT32 bb = 0;	unsigned ilen = 0, olen = 0, last_m_off = 1;	for (;;)	{		unsigned m_off, m_len;		while (GETBIT(bb,src,ilen))		{			dst[olen++] = src[ilen++];		}		m_off = 1;		for (;;)		{			m_off = m_off*2 + GETBIT(bb,src,ilen);			if (GETBIT(bb,src,ilen)) break;			m_off = (m_off-1)*2 + GETBIT(bb,src,ilen);		}		if (m_off == 2)		{			m_off = last_m_off;			m_len = GETBIT(bb,src,ilen);		}		else		{			m_off = (m_off-3)*256 + src[ilen++];			if (m_off == 0xffffffff)				break;			m_len = (m_off ^ 0xffffffff) & 1;			m_off >>= 1;			last_m_off = ++m_off;		}		if (m_len)			m_len = 1 + GETBIT(bb,src,ilen);		else if (GETBIT(bb,src,ilen))			m_len = 3 + GETBIT(bb,src,ilen);		else		{			m_len++;			do {				m_len = m_len*2 + GETBIT(bb,src,ilen);			} while (!GETBIT(bb,src,ilen));			m_len += 3;		}		m_len += (m_off > 0x500);		{			const UINT8 *m_pos;			m_pos = dst + olen - m_off;			dst[olen++] = *m_pos++;			do dst[olen++] = *m_pos++; while (--m_len > 0);		}	}	*dst_len = olen;	return ilen;}// move the image into place and start itvoid DecompressStart(tImage* pImage){	UINT32* pSrc;	UINT32* pDest;	pSrc = pImage->image;	pDest = pImage->pDestination;	if (pSrc != pDest) // if not linked to that flash address	{		if (pImage->flags & IF_UCL_2E)		{	// UCL compressed, algorithm 2e			UINT32 dst_len; // dummy			ucl_nrv2e_decompress_8((UINT8*)pSrc, (UINT8*)pDest, &dst_len);		}		else		{	// uncompressed, copy it			UINT32 size = pImage->size;			UINT32* pEnd;			size = (size + 3) / 4; // round up to 32bit-words			pEnd = pDest + size;			do			{				*pDest++ = *pSrc++;			}			while (pDest < pEnd);		}	}	pImage->pExecute();}int ReadADC(int channel){	// after channel 3, the ports wrap and get re-used	volatile UINT16* pResult = (UINT16*)(ADDRAH_ADDR + 2 * (channel & 0x03)); 	int timeout = 266; // conversion takes 266 clock cycles	ADCSR = 0x20 | channel; // start single conversion	while (((ADCSR & 0x80) == 0) && (--timeout)); // 6 instructions per round	return (timeout == 0) ? -1 : *pResult>>6;}// This function is platform-dependent, //	until I figure out how to distinguish at runtime.int ButtonPressed(void) // return 1,2,3 for F1,F2,F3, 0 if none pressed{	int value = ReadADC(CHANNEL);	if (value >= F1_LOWER && value <= F1_UPPER) // in range		return 1;	else if (value >= F2_LOWER && value <= F2_UPPER) // in range		return 2;	else if (value >= F3_LOWER && value <= F3_UPPER) // in range		return 3;		return 0;}// Determine the image to be startedtImage* GetStartImage(int nPreferred){	tImage* pImage1;	tImage* pImage2 = NULL; // default to not present	UINT32 pos;	UINT32* pFlash = (UINT32*)FLASH_BASE;	// determine the first image position	pos = pFlash[2] + pFlash[3]; // position + size of the bootloader = after it	pos = (pos + 3) & ~3; // be shure it's 32 bit aligned	pImage1 = (tImage*)pos;	if (pImage1->size != 0)	{	// check for second image		pos = (UINT32)(&pImage1->image) + pImage1->size;		pImage2 = (tImage*)pos;		// does it make sense? (not in FF or 00 erazed space)		if (pImage2->pDestination == (void*)0xFFFFFFFF		 || pImage2->size == 0xFFFFFFFF		 || pImage2->pExecute == (void*)0xFFFFFFFF		 || pImage2->flags == 0xFFFFFFFF		 || pImage2->pDestination == NULL) // size, execute and flags can legally be 0				{			pImage2 = NULL; // invalidate		}	}	if (pImage2 == NULL || nPreferred == 1)	{	// no second image or overridden: return the first		return pImage1;	}	return pImage2; // return second image}// diagnostic functionsvoid SetLed(BOOL bOn){	if (bOn)		PBDR |= 0x40;	else		PBDR &= ~0x40;}void UartInit(void){	PBIOR &= 0xFBFF; // input: RXD1 remote pin	PBCR1 |= 0x00A0; // set PB3+PB2 to UART	PBCR1 &= 0xFFAF; // clear bits 6, 4 -> UART	SMR1  =  0x0000; // async format 8N1, baud generator input is CPU clock	SCR1  =  0x0030; // transmit+receive enable	PBCR1 &= 0x00FF; // set bit 12...15 as GPIO	SSR1  &= 0x00BF; // clear bit 6 (RDRF, receive data register full)}UINT8 UartRead(void){	UINT8 byte;	while (!(SSR1 & SCI_RDRF)); // wait for char to be available	byte = RDR1;	SSR1 &= ~SCI_RDRF;	return byte;}void UartWrite(UINT8 byte){	while (!(SSR1 & SCI_TDRE)); // wait for transmit buffer empty	TDR1 = byte;	SSR1 &= ~SCI_TDRE;}// include the mini monitor as a rescue feature, started with F3void MiniMon(void){	UINT8 cmd;	UINT32 addr;	UINT32 size;	UINT32 content;	volatile UINT8* paddr = NULL;	volatile UINT8* pflash = NULL; // flash base address	UartInit();	while (1)	{		cmd = UartRead();		switch (cmd)		{		case BAUDRATE:			content = UartRead();			UartWrite(cmd); // acknowledge by returning the command value			while (!(SSR1 & SCI_TEND)); // wait for empty shift register, before changing baudrate			BRR1 = content;			break;		case ADDRESS:			addr = (UartRead() << 24) | (UartRead() << 16) | (UartRead() << 8) | UartRead();			paddr = (UINT8*)addr;			pflash = (UINT8*)(addr & 0xFFF80000); // round down to 512k align			UartWrite(cmd); // acknowledge by returning the command value			break;		case BYTE_READ:			content = *paddr++;			UartWrite(content); // the content is the ack				break;		case BYTE_WRITE:			content = UartRead();			*paddr++ = content;			UartWrite(cmd); // acknowledge by returning the command value			break;		case BYTE_READ16:			size = 16;			while (size--)			{				content = *paddr++;				UartWrite(content); // the content is the ack			}			break;		case BYTE_WRITE16:			size = 16;			while (size--)			{				content = UartRead();				*paddr++ = content;			}			UartWrite(cmd); // acknowledge by returning the command value			break;		case BYTE_FLASH:			content = UartRead();			pflash[0x5555] = 0xAA; // set flash to command mode			pflash[0x2AAA] = 0x55;			pflash[0x5555] = 0xA0; // byte program command			*paddr++ = content;			UartWrite(cmd); // acknowledge by returning the command value			break;		case BYTE_FLASH16:			size = 16;			while (size--)			{				content = UartRead();				pflash[0x5555] = 0xAA; // set flash to command mode				pflash[0x2AAA] = 0x55;				pflash[0x5555] = 0xA0; // byte program command				*paddr++ = content;			}			UartWrite(cmd); // acknowledge by returning the command value			break;		case HALFWORD_READ:			content = *(UINT16*)paddr;			paddr += 2;			UartWrite(content >> 8); // highbyte			UartWrite(content & 0xFF); // lowbyte			break;				case HALFWORD_WRITE:			content = UartRead() << 8 | UartRead();			*(UINT16*)paddr = content;			paddr += 2;			UartWrite(cmd); // acknowledge by returning the command value			break;				case EXECUTE:			{				tpFunc pFunc = (tpFunc)paddr;				pFunc();				UartWrite(cmd); // acknowledge by returning the command value			}			break;		case VERSION:			UartWrite(1); // return our version number			break;		default:			{				SetLed(TRUE);				UartWrite(~cmd); // error acknowledge			}		} // case	} // while (1)}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -