当前位置:首页 > 芯闻号 > 充电吧
[导读]这几天晚上一直折腾S3C6410的裸机SD卡启动,不大想使用UBOOT,我是搞硬件的,对底层非常感兴趣,不喜欢已经写好的,因此自己一直在尝试,其实很早之前就试过SD卡启动,也就是ARM11上电后会把S

这几天晚上一直折腾S3C6410的裸机SD卡启动,不大想使用UBOOT,我是搞硬件的,对底层非常感兴趣,不喜欢已经写好的,因此自己一直在尝试,其实很早之前就试过SD卡启动,也就是ARM11上电后会把SD卡倒数第9KB开始的8KB(倒数0x2400B偏移量)复制到内部SRAM中执行,这个比较简单,但是代码量只有8K,不能像STM32一样玩,因此查阅相关资料,得知启动方式为L0加载L1,L1加载L2,简单来说,就是上电启动后,固化在S3C6410内部的L0代码启动,将NAND,SD卡等外部存储器映射或者复制到内部SRAM,这个从SD卡或者flash复制过去的代码称之为L1,也就是用户的启动代码,在电脑上相当于硬盘主分区的启动代码和BIOS,用来初始化外时钟以及外设,并启动系统,,这部分代码只有8KB因此完成的工作有限,因此可以使用这段代码完成初始化并复制操作系统或者更大的代码到内存,这部分代码就是L2了,只有L1将内存初始化后才能使用内存,再此之前内存只有8KB,就是内部SRAM,从SD卡启动的时候映射到0x0c000000,从NAND可以是0,也可以是0x0c000000.

目前只实现了L1,无需uboot,只需要烧写到SD卡的指定位置即可,需要将开发板选择为SD卡启动.


启动代码,完成了关闭看门狗,初始化时钟,SDRAM内存,堆栈,VIC,中断等操作(启动代码来自互联网)


	INCLUDE S3C6410.inc
	PRESERVE8
	AREA Init, CODE, READONLY
STACK_BASEADDRESS EQU  0x0c000400;0x52000000

SVCStack	EQU	(STACK_BASEADDRESS)	;管理模式
UndefStack	EQU	(STACK_BASEADDRESS - 0x300)	;指令终止模式
AbortStack	EQU	(STACK_BASEADDRESS - 0x300)	;数据访问终止模式
IRQStack	EQU	(STACK_BASEADDRESS - 0x200)	;中断模式
FIQStack	EQU	(STACK_BASEADDRESS - 0x100)	;快速中断模式	
	
;---------------------------
; CPSR Mode Bit Definition
;---------------------------
Mode_USR    EQU    (0x10)
Mode_FIQ    EQU    (0x11)
Mode_IRQ    EQU    (0x12)
Mode_SVC    EQU    (0x13)
Mode_ABT    EQU    (0x17)
Mode_UND    EQU    (0x1B)
Mode_SYS    EQU    (0x1F)
Mode_MASK    EQU    (0x1F)
NOINT        EQU    (0xC0)
I_Bit        EQU    (0x80)
F_Bit        EQU    (0x40)	
	

	
	
;异常处理函数	 
;---------------------------------------------------------------------------------------------------	
	IMPORT main
	EXPORT	ResetHandler
	
ResetHandler
    ldr        r0, =0x70000013        ; Base Addres : 0x70000000, Size : 256 MB (0x13)
	mcr        p15,0,r0,c15,c2,4      ;告诉CPU外设寄存器的基地址和地址空间 重要
;设置为SVC模式
	MRS		R0,CPSR
	BIC		R0,R0,#0x1F
	ORR		R0,R0,#0xD3
	MSR		CPSR_cxsf,R0



;未知模式堆栈
		mrs	r0,cpsr
		bic	r0,r0,#Mode_MASK
		orr	r1,r0,#Mode_UND|NOINT
		msr	cpsr_cxsf,r1		;UndefMode
		ldr	sp,=UndefStack	

		;异常模式堆栈
		orr	r1,r0,#Mode_ABT|NOINT
		msr	cpsr_cxsf,r1		;AbortMode
		ldr	sp,=AbortStack	

		;中断模式堆栈
		orr	r1,r0,#Mode_IRQ|NOINT
		msr	cpsr_cxsf,r1		;IRQMode
		ldr	sp,=IRQStack	

		;管理模式堆栈
		bic	r0,r0,#Mode_MASK|NOINT
		orr	r1,r0,#Mode_SVC
		msr	cpsr_cxsf,r1		;SVCMode
		ldr	sp,=SVCStack
		
;禁止看门狗
	LDR		R0,=rWTCON
	LDR		R1,=0x0
	STR		R1,[R0]
;禁止cache和mmu	
	
	LDR		R0,=0x0
	MRC		p15,0,R0,c1,c0,0
	LDR		R1,=0xFFFF
	BIC		R0,R0,R1
	MCR		p15,0,R0,c1,c0,0
		
	
;禁止所有中断

	LDR		R0,=rVIC0INTENCLEAR 
	LDR		R1,=0xFFFFFFFF
	STR		R1,[R0]
	
	LDR		R0,=rVIC1INTENCLEAR 
	LDR		R1,=0xFFFFFFFF
	STR		R1,[R0]
;---------------------------------------------------------------------------------------------------	

;设置时钟源
	LDR		R0,=rOTHERS
	LDR		R1,[R0]
	ORR		R1,R1,#(1<<6)
	
	LDR		R0,=rCLK_SRC
	LDR		R1,=(1<<13)|7
	STR		R1,[R0]

	LDR		R0,=rCLK_SRC2
	LDR		R1,=0x0
	STR		R1,[R0]
	
;设置时钟分频
	LDR		R0,=rCLK_DIV0
	LDR		R1,=0x01043310
	STR		R1,[R0]
	
	LDR		R0,=rCLK_DIV1
	LDR		R1,=0x0
	STR		R1,[R0]

	LDR		R0,=rCLK_DIV2
	LDR		R1,=3<<16
	STR		R1,[R0]
				
	
;使能时钟
	LDR		R0,=rHCLK_GATE
	LDR		R1,=0xFFFFFFFF
	STR		R1,[R0]
	
	LDR		R0,=rPCLK_GATE
	STR		R1,[R0]
	
	LDR		R0,=rSCLK_GATE
	STR		R1,[R0]
	
;设置系统时钟	
;设置APLL 532MHz
	LDR		R0,=rAPLL_LOCK
	LDR		R1,=0xFFFF
	STR		R1,[R0]
	
	LDR		R0,=rAPLL_CON
	LDR		R1,=(1<<31)|(266<<16)|(3<<8)|(1)	
	STR		R1,[R0]

;设置MPLL 532MHz
	LDR		R0,=rMPLL_LOCK
	LDR		R1,=0xFFFF
	STR		R1,[R0]
	
	LDR		R0,=rMPLL_CON
	LDR		R1,=(1<<31)|(266<<16)|(3<<8)|(1)	
	STR		R1,[R0]
	
;设置EPLL	96MHz
	LDR		R0,=rEPLL_LOCK
	LDR		R1,=0xFFFF
	STR		R1,[R0]
	
	LDR		R0,=rEPLL_CON0
	LDR		R1,=(1<<31)|(32<<16)|(1<<8)|(2)
	STR		R1,[R0]
	
	LDR		R0,=rEPLL_CON1
	LDR		R1,=0x0
	STR		R1,[R0] 
;=================
;选择同步工作模式
;=================
    ldr     r4, =rOTHERS
    ldr     r5, [r4]
    bic     r5, r5, #0xC0
    orr     r5, r5, #0x40           ; SyncReq = Async, SyncMUX = Sync
    str     r5, [r4]
    
_wait_for_async                     ;确认工作到同步模式
    ldr     r5, [r4]                ; Read OTHERS
    and     r5, r5, #0xF00          ; Wait SYNCMODEACK = 0x0
    cmp     r5, #0x0
    bne     _wait_for_async

    ldr     r4, =rOTHERS
    ldr     r5, [r4]
    bic     r5, r5, #0x40           ;SyncMUX = Async
    str     r5, [r4]

    nop
    nop
    nop
    nop
    nop  	
;---------------------------------------------------------------------------------------------------	
;设置DRAM
	LDR		R0,=0x7E00F120  
	LDR		R1,=0xD
	STR		R1,[R0]
		
	LDR		R0,=rP1MEMCCMD
	LDR		R1,=0x4
	STR		R1,[R0]
	
	LDR		R0,=rP1REFRESH		
	LDR		R1,=0x40D
	STR		R1,[R0]
	

	LDR		R0,=rP1CASLAT		
	LDR		R1,=0x6
	STR		R1,[R0]	
	
	LDR		R0,=rP1T_DQSS
	LDR		R1,=0x1
	STR		R1,[R0]
	
	LDR		R0,=rP1T_MRD
	LDR		R1,=0x2
	STR		R1,[R0]
	LDR		R0,=rP1T_RAS
	LDR		R1,=0x6
	STR		R1,[R0]

	LDR		R0,=rP1T_RC
	LDR		R1,=0xA
	STR		R1,[R0]

	LDR		R0,=rP1T_RCD
	LDR		R1,=0xB
	STR		R1,[R0]
	
	LDR		R0,=rP1T_RFC
	LDR		R1,=0x10B
	STR		R1,[R0]

	LDR		R0,=rP1T_RP
	LDR		R1,=0xB
	STR		R1,[R0]
	
	LDR		R0,=rP1T_RRD
	LDR		R1,=0x2
	STR		R1,[R0]
	
	LDR		R0,=rP1T_WR
	LDR		R1,=0x2
	STR		R1,[R0]
	
	LDR		R0,=rP1T_WTR
	LDR		R1,=0x2
	STR		R1,[R0]
	
	LDR		R0,=rP1T_XP
	LDR		R1,=0x2
	STR		R1,[R0]
	
	LDR		R0,=rP1T_XSR
	LDR		R1,=0x10
	STR		R1,[R0]
	
	LDR		R0,=rP1T_ESR
	LDR		R1,=0x10
	STR		R1,[R0]
	
	LDR		R0,=rP1MEMCFG
	LDR		R1,=0x1001A
	STR		R1,[R0]
	
	LDR		R0,=rP1MEMCFG2
	LDR		R1,=0xB45
	STR		R1,[R0]	
	
	LDR		R0,=rP1_chip_0_cfg
	LDR		R1,=0x150F0
	STR		R1,[R0]
	
	LDR		R0,=rP1_user_cfg
	LDR		R1,=0x0
	STR		R1,[R0]
	
	LDR		R0,=rP1_DIRECTCMD
	LDR		R1,=0xC0000
	STR		R1,[R0]
	
	LDR		R0,=rP1_DIRECTCMD
	LDR		R1,=0x00000
	STR		R1,[R0]
	
	LDR		R0,=rP1_DIRECTCMD
	LDR		R1,=0x40000
	STR		R1,[R0]
	STR		R1,[R0]
	
	LDR		R0,=rP1_DIRECTCMD
	LDR		R1,=0xA0000
	STR		R1,[R0]
	
	LDR		R0,=rP1_DIRECTCMD
	LDR		R1,=0x80032
	STR		R1,[R0]
	
	LDR		R0,=rP1MEMCCMD
	LDR		R1,=0x0
	STR		R1,[R0]

	LDR		R0,=rP1MEMSTAT	
DRAM_WAIT
	LDR		R1,[R0]
	AND		R1,R1,#0x3
	CMP		R1,#0x1
	BNE		DRAM_WAIT
;---------------------------------------------------------------------------------------------------	


	

;设置堆栈
;STACK_TOP	EQU	0x52000000;0x0c000400	
;	LDR		SP,=STACK_TOP

;---------------------------------------------------------------------------------------------------
;使能VIC
	mrc 	p15,0,r0,c1,c0,0
	orr 	r0,r0,#(1<<24)
	mcr 	p15,0,r0,c1,c0,0
;---------------------------------------------------------------------------------------------------
;使能VFP
	MRC        p15, 0, r0, c1, c0, 2 
 	ORR        r0, r0, #0x00F00000 
 	MCR        p15, 0, r0, c1, c0, 2 
 	
 	MOV        r1, #0 
 	MCR        p15, 0, r1, c7, c5, 4 
 	MOV        r0,#0x40000000 
 	FMXR       FPEXC, r0       ; FPEXC = r0 
 	nop 
	nop 
;---------------------------------------------------------------------------------------------------
	LDR		R0,=rGPMCON
	LDR		R1,=0x11111
	STR		R1,[R0]
	
	LDR		R0,=rGPMPUD
	LDR		R1,=0x0
	STR		R1,[R0]
	
	LDR		R0,=rGPMDAT
	LDR		R1,=0
	STR		R1,[R0]

	B		main

		

		
	
	END


//主要的函数



#include "system.h"
#include "uart.h"
#include "other.h"
#include "SDCARD.h"


//简单的延时
void Delay_Ms(u32 n)
{
	u32 i;
	
	while(n --)
	{
		for(i = 0;i < 0xfff;i ++)
		{
			nop;
		}
			 
	}
	
}



//跳转到指定位置执行
__asm jump()
{
	LDR PC,=0x52000000;
}



//按键检测
bool Key_Test(void)
{
	static u8 i = 0;
	
	if((rGPNDAT & 0x3f) != 0x3f )
	{
		i ++;
		if(i > 10)
		{
			i = 0;
			
			return TRUE;
		}
	}
	return FALSE;
}


//主函数
int main(void)
{	
	u16 n = 0;
	u32 cnt1 = 0, cnt2 = 0;

	LED_Init();					//初始化LED
	UART0_Init(ENABLE,115200);	//初始化串口
	UARTx_SetRxBuff(UART_CH0, (u8 *)0x52000000, 1024*1024*10);	//设置串口接收缓冲区
	rGPNCON	= 0;				//初始化按键
	UART0_SendString("SD BOOT 启动成功!rn");
	
	Delay_Ms(100);
	
	//按键没有按下从SD卡加载程序
	if((rGPNDAT & 0x3f) == 0x3f)
	{
		Delay_Ms(10);
		if((rGPNDAT & 0x3f) == 0x3f )
		{
			if(SD_Init() == SD_OK)
			{
				UART0_SendString("SD卡初始化成功!rn");
				if(SD_ReadMultiBlocks(1621032, (u32 *)0x52000000, 1000) == SD_OK)
				{
					UART0_SendString("从SD卡读取程序成功,开始从0x52000000执行!rn");
					jump();		//跳转
				}
				else
				{
					UART0_SendString("从SD卡读取程序失败!rn");
					LED0_FLASH();
				}
			}
			else
			{
				UART0_SendString("SD卡初始化失败!rn");
			}
		}
	}
	
	
	while((rGPNDAT & 0x3f) != 0x3f);	//等待按键抬起
	Delay_Ms(100);
	//从串口加载程序
	UART0_SendString("请从串口发送代码!rn");
	while(1)
	{
		n ++;
		if(n == 300)
		{
			LED1_FLASH();
			n = 0;
			cnt1 = cnt2;
			cnt2 = UARTx_GetRxCnt(UART_CH0);
			if(cnt1!=cnt2)
			{
				LED2_FLASH();
			}
			else if(cnt2 == 0)
			{
				
				//UART0_SendString("请从串口发送代码!rn");
				LED3_FLASH();
			}
		}
		
		
		if(Key_Test() == TRUE)
		{
			//测试检查内存
			*((vu32 *)0x59000000) = 0xa55aaa55;
			*((vu32 *)0x59000000)+=1;
			if(*((vu32 *)0x59000000) == (0xa55aaa55+1))
			{
				UART0_SendString("内存0x59000000检查正确!rn");
			}
			else
			{
				UART0_SendString("内存0x59000000检查错误!rn");
			}
			//测试检查内存
			*((vu32 *)0x54000000) = 0xaa5aaa55;
			*((vu32 *)0x54000000)-=1;
			if(*((vu32 *)0x54000000) == (0xaa5aaa55-1))
			{
				UART0_SendString("内存0x54000000检查正确!rn");
			}
			else
			{
				UART0_SendString("内存0x54000000检查错误!rn");
			}
			UART0_SendString("发送完成,开始从0x52000000执行!rn");
			jump();		//跳转
		}
		Delay_Ms(1);	
	}
}


if(SD_ReadMultiBlocks(1621032, (u32 *)0x52000000, 1000)

当没有按键按下的时候,或从SD卡指定位置加载一个比较的程序执行,可以是操作系统,或自己的裸机程序.



1621032:程序在SD卡中的位置,注意是物理扇区,不是逻辑扇区,物理扇区是你写的裸机代码能读的扇区地址,比如1,2,等,逻辑扇区是文件系统提供的扇区,两个位置不一样,要注意了.

0x52000000 程序启动的位置,在编译的时候就要指定好,一般在SDRAM中.
1000:需要加载的扇区数量,每个扇区大小为512B,因此我的程序加载的是512KB.






1.使用串口下载程序

准备好后从串口下载程序,按住随便一个按键,RESET除外,即可使用串口下载程序,波特率115200,我使用的是OK6410开发板,因此按键检测为if((rGPNDAT & 0x3f) != 0x3f );


启动后使用串口把bin发送过去



发送完成后按任意按键(reset除外)即可开始执行


可以看到程序已经开始执行了,刚开始的时候我用串口下载程序,一段时间后CPU就会死掉,还得我折腾一下午,最后发现是CPU主频过高,初始化为633MHZ了,结果不稳定,现在是533MHZ比较稳定了.


2.我已经将要启动的大程序放到SD卡指定位置了,直接复位,不要按下任何按键即可加载,后面将会做上界面,选择启动哪个程序,就行安卓手机SD卡刷机一样,可以选启动程序.



3.启动程序如何写入到SD卡

写入还是比较简单的,看下面的图片

先使用十六进制编辑器打开磁盘,一定要是物理磁盘


指定偏移到倒数第0x2400B,注意:4G以上卡不是在这个位置,找度娘去.

注意框框中的选项



打开SD_BOOT bin文件,全部选中,复制



切换到SD卡的指定位置

右键->编辑->剪贴板数据->写入


一定要在指定的扇区开始写入,写入之后不要忘记保存


另一个需要启动的程序也可以用这个工具看看他的位置

注意一定要看物理扇区编号


主要由于8K代码中无法添加文件系统,如果这个代码启动后就可以无限制了,界面什么的都可以添加进去,后面将会完善L2的代码,实现更加方便的功能.


附上工程RVDS4.0的设置

L1的代码设置


为了减小代码体积,优化等级开高一点,平时测试可以开最低.





L2代码工程


其他位置设置都是一样的






本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

针对传统类人机器人在控制系统实时性和视觉识别方面的不足,以S3C6410作为主控芯片,设计了具有视觉识别功能的类人机器人控制系统,通过改进和简化视频识别算法取得了良好的目标识别效果。实验表明,基

关键字: s3c6410 机器人 机器视觉

早在今年8月份的时候就将jpeg解码弄好了,但是一直以来非常的不稳定,如果修改了任意地方的代码都会造成解码可能失败,起初我以为是堆栈问题,或者后面有非法指针,但是都没得到结果,最后让我只能怀疑编译器了,而且

关键字: jpeg解码 s3c6410

这几天晚上一直折腾S3C6410的裸机SD卡启动,不大想使用UBOOT,我是搞硬件的,对底层非常感兴趣,不喜欢已经写好的,因此自己一直在尝试,其实很早之前就试过SD卡启动,也就是ARM11上电后会把SD卡倒数第9KB开始...

关键字: s3c6410 sd 裸机启动 boot启动

简单地说,IAR调试S3C6410可以分成以下3个步骤:1)编写mac文件,初始化S3C6410的看门狗、时钟、DDRAM控制器等,为下载代码做准备。2)编写icf文件对S3C6410的内存空间进行分配,配置堆栈段、...

关键字: iar调试 s3c6410

主要过程:. 安装lunux 环境. 安装编译工具. 下载Linux kernel. 安装AndroidSDK. 获得root file system. 修改Linux kernel 源码. 配置Linux kernel...

关键字: Android s3c6410 内核 移植

之前一直不知道如何使能硬件协处理器,刚刚在网上找到了方法,配置好RVDS,选择相应的内核,选择硬件VFP在初始化代码中加入VFPEnable EQU (0x40000000) ;VFP使能...

关键字: s3c6410 vfp 浮点协处理器

         虽然S3C6410出来很多年了,甚至于已经停产了,出货的几乎都有依赖于库存,SE4500也出来很多年了,但是网上依旧不会有调试资料帮助你,一切源于自私。希望本文能帮到你,不必感谢。本

关键字: s3c6410 se4500

/*************************************************************************************************************...

关键字: s3c6410 裸机dma

要确保S3C6410已经初始化,一般是使用UBOOT初始化 //串口寄存器//UART0#defineULCON0                *((vu32*)0x7F005000)       

关键字: s3c6410 uart驱动

这个比较简单,一次成功,没遇到任何问题.GraphRotation.c/****************************************************************

关键字: s3c6410 裸机驱动
关闭
关闭