嵌入式开发之bootloader

本文详细介绍了Bootloader在嵌入式系统中的重要性,从CPU启动、中断跳转到内核加载的过程。文中还提供了MCU启动代码的示例,展示如何设置堆栈、全局指针,并执行初始化。此外,文章提到了C语言实现的Bootloader主程序,包括数据加载、异常处理和闪存编程的细节。
摘要由CSDN通过智能技术生成

      bootloader开发在嵌入式开发中是一个不可或缺的存在,就像bios /pc ,uboot/linux ,虽然现在的软件组件都是很成熟发达了。但是要深入嵌入式的本质还是需要从裸机开始,知道cpu是怎么启动,怎么中断跳转,怎么实现内核加载的,bootloader的编写基本上就可以覆盖这些内容。

以下是嵌入式程序在flash中分布的地址分配图,mcu在启动时会从0地址开始(也可能是一个其他什么固定地址,)运行第一行代码,这个代码一般是cpu自带的,她负责设置初始化并跳转指令将控制权交给程序员,程序员通过启动代码(汇编语言),设置堆栈以及中断向量表,然后将控制权跳转到c语言的man函数,在从里面我们就可以编写逻辑实现跟上位机交互获取固件文件并写入flash对应的地址区域,在每次启动时bootlaod先判断固件所在的区域程序是否完整,如果完整就将固件装载到ram中,然后跳转到内存的固件起始地址,并将控制权交由固件,如果没有发现固件就就进入shell等待交互,这一过程适用于所有的操作系统启动,只是复杂程度,外设驱动初始化不一样,其原理都差不多。

//片内flash为512k bytes 4k*128page 
//0x9D07FFFF--0x9D000000 Program Flash
//
// PFM KERNEL AND USER MODE MAPPING
//  Virtual Address                     Physical Address
//  ---------------                     ----------------
//  0xBFC0_2FEF or  *****************   0x1FC0_2FEF
//  0X9FC0_2FEF     *               *
//                  *               *
//                  *  Boot Flash   *
//  0xBFC0_0000 or  *               *
//  0x9FC0_0000     *****************   0x1FC0_0000


//  0xBD07_FFFF or  *****************   0x1D07_FFFF
//  0x9D07_FFFF     *               *  BL_CSUM_ADDR    0x1D07_FFF4
//                  *               *  BL_PROGSZ_ADDR  0x1D07_FFF0
//  0xBD07_E000 or  *****************  0x1D07_E000 
//  0x9D07_E000     *               *
//                  *  User App     *  500k User app
//                  *               *
//                  *  Program      *
//                  *  Flash        *
//                  *               *
//  0x9D00_1000     *****************  0x1D00_1000//4k bootloader
//                  *  BootLoader   *
//  0xBD00_0000 or  *               *
//  0x9D00_0000     *****************   0x1D00_0000
 **********************************************************************/

 启动代码是mcu厂家提供的demo,我们可以在这个里面进行按需更改,比如加上一些特殊的处理代码,一般bootloader类的代码直接可以采用原厂的代码,这个汇编语言也跟mcu采用的内核及指令集密切相关,但功能都相差无几,当你想了解一款mcu时从读懂他的启动代码是最快的一种方式,汇编语言难懂,主要是在于你记性好不好,就像想在网络流行的很多简写体,你没有功略可能就是天书,所以不清楚的差芯片指令手则就好了,无他为手熟尔,我相信隔一段时间你又会搞忘的,所以不要纠结这个,也没必要去背他,当然你是学霸除外。

#include <p32xxxx.h>
#ifdef __LIBBUILD__
   .file 1 "crt0.S"
   .loc 1 0
#endif
        ##################################################################
        # Entry point of the entire application
        ##################################################################
        .section .reset,"ax",@progbits
        .set noreorder
        .ent _reset
_reset:
        la      k0, _startup
        jr      k0                      # Jump to startup code
        nop
  
        .end _reset
        .globl _reset

        ##################################################################
        # Startup code
        ##################################################################
        .section .startup,"ax",@progbits
        .set noreorder
        .ent _startup
_startup:
        ##################################################################
        # If entered because of an NMI, jump to the NMI handler.
        ##################################################################
        mfc0    k0,_CP0_STATUS
        ext     k0,k0,19,1              # Extract NMI bit
        beqz    k0,_no_nmi
        nop
        la      k0,_nmi_handler
        jr      k0
        nop
_no_nmi:

        ##################################################################
        # Initialize Stack Pointer
        #   _stack is initialized by the linker script to point to the
        #    starting location of the stack in DRM
        ##################################################################
        la      sp,_stack

        ##################################################################
        # Initialize Global Pointer
        #   _gp is initialized by the linker script to point to "middle"
        #   of the small variables region
        ##################################################################
        la      gp,_gp
        
        ##################################################################
        # Initialize Global Pointer in Shadow Set
        #   The SRSCtl's PSS field must be set to the shadow set in which
        #   to initialize the global pointer.  Since we only have a
        #   single shadow set (besides the normal), we will initialize
        #   SRSCtl<PSS> to SRSCtl<HSS>.  We then write the global pointer
        #   to the previous shadow set to ensure that on interrupt, the
        #   global pointer has been initialized.
        ##################################################################
        mfc0    t1,_CP0_SRSCTL          # Read SRSCtl register
        add     t3,t1,zero              # Save off current SRSCtl
        ext     t2,t1,26,4              # to obtain HSS field
        ins     t1,t2,6,4               # Put HSS field
        mtc0    t1,_CP0_SRSCTL          # into SRSCtl<PSS>
        wrpgpr  gp,gp                   # Set global pointer in PSS
        mtc0    t3,_CP0_SRSCTL          # Restore SRSCtl

        ##################################################################
        # Call the "on reset" procedure
        ##################################################################
        la      t0,_on_reset
        jalr    t0
        nop

        ##################################################################
        # Clear uninitialized data sections
        ##################################################################
        la      t0,_bss_begin
        la      t1,_bss_end
        b       _bss_check
        nop

_bss_init:      
        sw      zero,0x0(t0)
        sw      zero,0x4(t0)
        sw      zero,0x8(t0)
        sw      zero,0xc(t0)
        addu    t0,16
_bss_check:
        bltu    t0,t1,_bss_init
        nop
        
        ##################################################################
        # Copy initialized data from program flash to data memory
        #   src=_data_image_begin dst=_data_begin stop=_data_end
        ##################################################################
        la      t0,_data_image_begin
        la      t1,_data_begin
        la      t2,_data_end
        b       _init_check
        nop

_init_data:     
        lw      t3,(t0)
        sw      t3,(t1)
        addu    t0,4
        addu    t1,4
_init_check:
        bltu    t1,t2,_init_data
        nop

        ##################################################################
        # If there are no RAM functions, skip the next two sections --
        # copying RAM functions from program flash to data memory and
        # initializing bus matrix registers.
        ##################################################################
        la      t1,_ramfunc_length
        beqz    t1,_ramfunc_done
        nop

        ##################################################################
        # Copy RAM functions from program flash to data memory
        #   src=_ramfunc_image_begin dst=_ramfunc_begin stop=_ramfunc_end
        ##################################################################
        la      t0,_ramfunc_image_begin
        la      t1,_ramfunc_begin
        la      t2,_ramfunc_end

_init_ramfunc:  
        lw      t3,(t0)
        sw      t3,(t1)
        addu    t0,4
        addu    t1,4
_ramfunc_check:
        bltu    t1,t2,_init_ramfunc
        nop

        ##################################################################
        # Initialize bus matrix registers if RAM functions exist in the
        # application
        ##################################################################
        la      t1,_bmxdkpba_address
        la      t2,BMXDKPBA
        sw      t1,0(t2)
        la      t1,_bmxdudba_address
        la      t2,BMXDUDBA
        sw      t1,0(t2)
        la      t1,_bmxdupba_address
        la      t2,BMXDUPBA
        sw      t1,0(t2)
_ramfunc_done:

        ##################################################################
        # Initialize CP0 registers
        ##################################################################
        # Initialize Count register
        ##################################################################
        mtc0    zero,_CP0_COUNT

        ##################################################################
        # Initialize Compare register
        ##################################################################
        li      t2,-1
        mtc0    t2,_CP0_COMPARE

        ##################################################################
        # Initialize EBase register
        ##################################################################
        la      t1,_ebase_address
        mtc0    t1,_CP0_EBASE

        ##################################################################
        # Initialize IntCtl register
        ##################################################################
        la      t1,_vector_spacing
        li      t2,0                    # Clear t2 and
        ins     t2,t1,5,5               # shift value to VS field
        mtc0    t2,_CP0_INTCTL

        ##################################################################
        # Initialize CAUSE registers
        # - Enable counting of Count register <DC = 0>
        # - Use special exception vector <IV = 1>
        # - Clear pending software interrupts <IP1:IP0 = 0>
        ##################################################################
        li      t1,0x00800000
        mtc0    t1,_CP0_CAUSE

        ##################################################################
        # Initialize STATUS register
        # - Access to Coprocessor 0 not allowed in user mode <CU0 = 0>
        # - User mode uses configured endianness <RE = 0>
        # - Preserve Bootstrap Exception vectors <BEV>
        # - Preserve soft reset <SR> and non-maskable interrupt <NMI>
        # - CorExtend enabled based on whether CorExtend User Defined
        #   Instructions have been implemented <CEE = Config<UDI>>
        # - Disable any pending interrups <IM7..IM2 = 0, IM1..IM0 = 0>
        # - Disable hardware interrupts <IPL7:IPL2 = 0>
        # - Base mode is Kernel mode <UM = 0>
        # - Error level is normal <ERL = 0>
        # - Exception level is normal <EXL = 0>
        # - Interrupts are disabled <IE = 0>
        ##################################################################
        mfc0    t0,_CP0_CONFIG
        ext     t1,t0,22,1              # Extract UDI from Config register
        sll     t1,t1,17                # Move UDI to Status.CEE location
        mfc0    t0,_CP0_STATUS
        and     t0,t0,0x00580000        # Preserve SR, NMI, and BEV
        or      t0,t1,t0                # Include Status.CEE (from UDI)
        mtc0    t0,_CP0_STATUS

        ##################################################################
        # Call the "on bootstrap" procedure
        ##################################################################
        la      t0,_on_bootstrap
        jalr    t0
        nop

        ##################################################################
        # Initialize Status<BEV> for normal exception vectors
        ##################################################################
        mfc0    t0,_CP0_STATUS
        and     t0,t0,0xffbfffff        # Clear BEV
        mtc0    t0,_CP0_STATUS

        ##################################################################
        # Call main. We do this via a thunk in the text section so that
        # a normal jump and link can be used, enabling the startup code
        # to work properly whether main is written in MIPS16 or MIPS32
        # code. I.e., the linker will correctly adjust the JAL to JALX if
        # necessary
        ##################################################################
        and     a0,a0,0
        and     a1,a1,0
        la      t0,_main_entry
        jr      t0
        nop

        
        .end _startup

        ##################################################################
        # Boot Exception Vector Handler
        # Jumps to _bootstrap_exception_handler
        ##################################################################
        .section .bev_handler,"ax",@progbits
        .set noreorder
        .ent _bev_exception
_bev_exception:
        la      k0,_bootstrap_exception_handler
        jr      k0
        nop

        .end _bev_exception
                        
        ##################################################################
        # General Exception Vector Handler
        # Jumps to _general_exception_handler
        ##################################################################
        .section .gen_handler,"ax",@progbits
        .set noreorder
        .ent _gen_exception
_gen_exception:
        la      k0,_general_exception_context
        jr      k0
        nop

        .end _gen_exception


        .text
        .ent _main_entry
_main_entry:
        ##################################################################
        # Call main
        ##################################################################
        jal main
        nop

        ##################################################################
        # Call exit
        ##################################################################
        jal    exit
        nop

        ##################################################################
        # Just in case, go into infinite loop
        ##################################################################
1:
        b       1b
        nop
        .end _main_entry
 

 下面是bootlaoder的main主场了,这是你可能就顺眼多了,因为c里面你可以自己用拼音表达你的意思,当然你是英语学习委员也可以用英语,但我反对用123来表示,那是霸权行为,只有当时的你可以明白,我一直觉得代码没必要自己从头开始,快速掌握一门语言或者一款mcu从她自带的demo开始,一通ctl c v后你的kpi就完成了,所以人生苦短,不要太在意那么多,知识层出不穷,只有掌握了快速学习的要义你在能在有限的生命里,畅想无限的事情,当然,买块板子自己亲自跑一跑,那跑板子后面吃灰也是很有必要的,最后祝你顺利毕业找到好工作!

/*********************************************************************
 *
 *                  PIC32 Boot Loader
 *
 *********************************************************************
 * FileName:        main.c
 * Dependencies:
 * Processor:       PIC32
 *
 * Complier:        MPLAB C32
 *                  MPLAB IDE
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the 揅ompany? for its PIC32 Microcontroller is intended
 * and supplied to you, the Company抯 customer, for use solely and
 * exclusively on Microchip PIC32 Microcontroller products.
 * The software is owned by the Company and/or its supplier, and is
 * protected under applicable copyright laws. All rights are reserved.
 * Any use in violation of the foregoing restrictions may subject the
 * user to criminal sanctions under applicable laws, as well as to
 * civil liability for the breach of the terms and conditions of this
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN 揂S IS?CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *
 * $Id:  $
 * $Name: $
 *
//片内flash为512k bytes 4k*128page 
//0x9D07FFFF--0x9D000000 Program Flash
//
// PFM KERNEL AND USER MODE MAPPING
//  Virtual Address                     Physical Address
//  ---------------                     ----------------
//  0xBFC0_2FEF or  *****************   0x1FC0_2FEF
//  0X9FC0_2FEF     *               *
//                  *               *
//                  *  Boot Flash   *
//  0xBFC0_0000 or  *               *
//  0x9FC0_0000     *****************   0x1FC0_0000


//  0xBD07_FFFF or  *****************   0x1D07_FFFF
//  0x9D07_FFFF     *               *  BL_CSUM_ADDR    0x1D07_FFF4
//                  *               *  BL_PROGSZ_ADDR  0x1D07_FFF0
//  0xBD07_E000 or  *****************  0x1D07_E000 
//  0x9D07_E000     *               *
//                  *  User App     *  500k User app
//                  *               *
//                  *  Program      *
//                  *  Flash        *
//                  *               *
//  0x9D00_1000     *****************  0x1D00_1000//4k bootloader
//                  *  BootLoader   *
//  0xBD00_0000 or  *               *
//  0x9D00_0000     *****************   0x1D00_0000
 **********************************************************************/
#include <stdlib.h>
#include <plib.h>
#include "GenericTypeDefs.h"
#include "msg_cmd.h"
//#include "utils.h"
#include <stdarg.h>
// 80Mhz Core/Periph, Pri Osc w/PLL, Write protect Boot Flash
//#pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FWDTEN = OFF, FPBDIV = DIV_1, POSCMOD = XT, FNOSC = PRIPLL, CP = OFF
//#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
//#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
//#pragma config ICESEL = ICS_PGx2, BWP = ON
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
#pragma config POSCMOD = XT, FNOSC = PRIPLL, FPBDIV = DIV_1
#pragma config ICESEL = ICS_PGx2, BWP = ON,CP = OFF


#define SHELL_CMD    0

#define BL_CSUM_ADDR 		0x9D07FFF4
#define BL_PROGSZ_ADDR 		0x9D07FFF0
#define FLASH_PROG_BASE		0x9D000000
#define USER_APP_ADDR 		0x9D001000
#define FLASH_PAGE_SIZE		4096
#define __ROM_SIZE          BL_PROGSZ_ADDR-FLASH_PROG_BASE     
#define BIOS_LOAD           USER_APP_ADDR
#define BL_MINOR_VERSION 1
#define BL_MAJOR_VERSION 0

#define	MAX_CMD_LEN	 30
#define	MAX_ARGS	 MAX_CMD_LEN/4

#define UART1_RXREG_IS_NOTNULL    (U1ASTAbits.URXDA==1)

#define	ENTER_KEY	0x0d
#define	BACK_KEY	0x08
#define	ESC_KEY		0x1b

#define dog()
#define SYS_FREQ 				(80000000L)

#define mLED_1              LATBbits.LATB0
#define mLED_2              LATBbits.LATB1
#define mLED_3              LATBbits.LATB2

#define SECONDS	(SYS_FREQ/2)
#define MILLI_SECONDS	(SECONDS/1000)

#define MAX_DATA_BFR 4096

unsigned char gBuffer[MAX_DATA_BFR];
//unsigned int pagebuff[1024];

#define  DFT_DOWNLOAD_ADDR ((int)&gBuffer[0])
void PutChar(BYTE txChar);
void HandleCommand();
BYTE gRxData;
void PutResponse(WORD responseLen);
void VerifyFlashOK(int filesize,WORD csum);
int SectorProg(unsigned int begin, unsigned short *data, unsigned int size);
unsigned char read_byte(unsigned char *recchar);
void Puts(char *s);
void Printf(char *fmt, ...);
#define	next_line()	Puts("\r\n")
#define prompt()	Puts("\\>")
//#define	DFT_DOWNLOAD_ADDR
#if SHELL_CMD==1
int LoadFromUart(int argc, char *argv[])
#else
int LoadFromUart()
#endif
{
	unsigned int start, fileSize;
	unsigned int write_addr,writedsize=0;
	unsigned int load_addr =(int) DFT_DOWNLOAD_ADDR;		
    WORD checksum=0,mychecksum=0;
	int bValue=0;
	
#if SHELL_CMD==1
    if(argc>1)
	{
		start = strtoul(argv[1],0,10);
		if(load_addr>0)
			load_addr = start;						
	}
#endif
	start = load_addr;
	
	while(!kbhit());*((unsigned char *)load_addr++) = getkey();
	while(!kbhit());*((unsigned char *)load_addr++) = getkey();
	while(!kbhit());*((unsigned char *)load_addr++) = getkey();
	while(!kbhit());*((unsigned char *)load_addr++) = getkey();
			 
	fileSize=	
	(*((unsigned char *)DFT_DOWNLOAD_ADDR+0)<<0)+
	(*((unsigned char *)DFT_DOWNLOAD_ADDR+1)<<8)+
	(*((unsigned char *)DFT_DOWNLOAD_ADDR+2)<<16)+
	(*((unsigned char *)DFT_DOWNLOAD_ADDR+3)<<24);
	
    fileSize=fileSize-6;
   	if(fileSize>=__ROM_SIZE) 
	{//Puts("Flash size overflow!!!\r\n");
	return -1;
	}
	
	load_addr  = (int)DFT_DOWNLOAD_ADDR;	
	write_addr = (int)FLASH_PROG_BASE;
	writedsize=0;
	while(writedsize <fileSize)
    {
        if(kbhit())
		{
            bValue=1-bValue;
            mLED_1=bValue;                    
	    	mychecksum+=*((unsigned char *)load_addr++) = getkey();
  			writedsize++;dog();
			if( writedsize%0x1000==0 )
			{

			  SectorProg(write_addr,(unsigned short*)DFT_DOWNLOAD_ADDR,0x1000);
			  write_addr=write_addr+0x1000;
	     	  load_addr  = (int)DFT_DOWNLOAD_ADDR;	
		      PutChar('.');dog();
		    }
	   }
	}
	
	if(load_addr%0x1000!=0)
	{
	  SectorProg(write_addr,(unsigned short*)DFT_DOWNLOAD_ADDR,fileSize - (write_addr-BIOS_LOAD));
	  PutChar('.');dog();
	}
    load_addr  = (int)DFT_DOWNLOAD_ADDR;
    //check sum

    while(!kbhit());*((unsigned char *)load_addr++) = getkey();
	while(!kbhit());*((unsigned char *)load_addr++) = getkey();
    //while(!kbhit());*((unsigned char *)load_addr++) = getkey();
	//while(!kbhit());*((unsigned char *)load_addr++) = getkey();
    checksum=
	(*((unsigned char *)DFT_DOWNLOAD_ADDR+0)<<0)+
	(*((unsigned char *)DFT_DOWNLOAD_ADDR+1)<<8);
	//(*((unsigned char *)DFT_DOWNLOAD_ADDR+1)<<16)+
	//(*((unsigned char *)DFT_DOWNLOAD_ADDR+1)<<24);
    if(checksum==mychecksum)
	 VerifyFlashOK(fileSize,checksum);
	
    //FILESIZE1 = fileSize;
	
	return 0;
	
}

void VerifyFlashOK(int filesize,WORD csum)
{
			//gBuffer[1] contains the prog size in bytes.  must be on DWORD boundry
			int temp;
			//DWORD* fptr;
			
            NVMErasePage( (void*)(BL_CSUM_ADDR&0xFFFFF000));
			if( !((*(DWORD*)BL_CSUM_ADDR) == 0xFFFFFFFF && 
				(*(DWORD*)BL_PROGSZ_ADDR) == 0xFFFFFFFF) )
			{
				//send the error response
				Puts("Flash not Erase\r\n");
				return;
			}	
			
			//fptr = (DWORD*)FLASH_PROG_BASE;
        
			NVMWriteWord((DWORD*)(BL_PROGSZ_ADDR), filesize); //write flash prog size in bytes


			NVMWriteWord((WORD*)(BL_CSUM_ADDR), csum); //write checksum


			if( !((*(WORD*)BL_CSUM_ADDR) == csum && 
				(*(DWORD*)BL_PROGSZ_ADDR) ==filesize ) )
			{
                Puts("Flash Check sum Erro\r\n");
			}	
}

int SectorProg(unsigned int begin, unsigned short *data, unsigned int size)
{		
/*
	unsigned int tmp = 0x200;//0x1000-(begin&0xfff);
	
	//if(tmp>size)
	//	tmp = size;
	//SectorErase(begin&0xfffff000);
	for(; size;)
	{	
        mLED_3=0;
        if((begin&0xFFF)==0)
	      NVMErasePage((void*)(begin&0xfffff000));
		//FlashProg(begin, data, tmp/2);
        // Write the pagebuff data to NVM_PROGRAM_PAGE + NVM_PAGE_SIZE
        //NVMProgram((void *)begin, (const void *)data, size, (void*) pagebuff);
        NVMWriteRow((DWORD*)begin, (DWORD*)data);
	
		//Puts("Program ok\r\n");
		size  -= tmp;
		begin += tmp;
		data  += tmp/2;
		tmp = (size>0x1000)?0x1000:size;				
	}
*/
			int RowCount, nRow;
			unsigned char* ptr=(unsigned char*)data;
			RowCount = size / 512;
			
			if( size % 512 )
				RowCount++;
				
			nRow = 0;
			
			while(nRow < RowCount)
			{
				int RowAddr;
				
				RowAddr = nRow*512;
				
				if( ((begin+RowAddr) & 0xFFF) == 0 )
					NVMErasePage( (void*)(begin+RowAddr) );
				
				// Write 128 words 
				NVMWriteRow((void*)(begin+RowAddr), (void*)&ptr[RowAddr]);
				nRow++;
			}	

	return 0;			
}




void JumpToApp()
{	
	void (*fptr)(void);
	fptr = (void (*)(void))USER_APP_ADDR;
	fptr();
}	


BOOL VerifyFlash()
{
	DWORD temp, ProgSz;
	DWORD* fptr;
    BYTE*  fbptr;
	WORD csum = 0,mycsum=0;

	fptr = (DWORD*)BL_PROGSZ_ADDR;
   
	ProgSz = *fptr;
    mycsum = *(WORD*)BL_CSUM_ADDR; 

	if( ProgSz > BMXPFMSZ )
		return FALSE;

	fbptr = (BYTE*)FLASH_PROG_BASE;

	for( temp = 0; temp < ProgSz; temp++ )
		csum += fbptr[temp];
		
	//csum = ~csum + 1;

	return (csum == mycsum);
}

/*********************************************************/
	#if SHELL_CMD==1

int Help(int argc, char *argv[]);
int Auto(int argc, char *argv[]);

typedef int (*cmdproc)(int argc, char *argv[]);
typedef struct {
	char *cmd;
	char *hlp;
	cmdproc proc;
}CMD_STRUC;

CMD_STRUC CMD_INNER[] =
				{ 	{"?", "help", Help},
				    {"load", "load bin file from console", LoadFromUart},
				//	{"prog", "program from sdram to flash", ProgFlash},
				//	{"boot", "boot from flash", BootLoader},
				//	{"copy", "copy from flash to flash", CopyFlash},
				//	{"run", "run from sdram", RunProgram},
					{"auto", "auto download and program",Auto},
					{NULL, NULL, NULL}
				};
/*
int Help(int argc, char *argv[])
{
	int i;	
	
	for(i=0; CMD_INNER[i].cmd!=NULL; i++)
	{
		if(CMD_INNER[i].hlp!=NULL)
		{
			Puts(CMD_INNER[i].cmd);
			Puts(" -----> ");
			Puts(CMD_INNER[i].hlp);
			Puts("\r\n");
		}
	}
	
	return 0;
}
*/
//int Auto(void);
int Auto(int argc, char *argv[])
{

//1.download to sdram
char *para_ptr[4];
//char temp[10];	
argc=argc;

LoadFromUart(0, para_ptr);

//2.program to flash
/*		
para_ptr[1]="8000";	
para_ptr[2]="44000000";
para_ptr[3]=temp;
ultostr(temp,FILESIZE1);

ProgFlash1(4, para_ptr);
*/
//3.boot

JumpToApp();

return 0;

}
/*********************************************************/

static void ParseArgs(char *cmdline, int *argc, char **argv)
{
#define STATE_WHITESPACE	0
#define STATE_WORD			1

	char *c;
	int state = STATE_WHITESPACE;
	int i;
        
	*argc = 0;

	if(strlen(cmdline) == 0)
		return;

	// convert all tabs into single spaces 
	c = cmdline;
	while(*c != '\0')
	{
		if(*c == '\t')
			*c = ' ';
		c++;
	}
	
	c = cmdline;
	i = 0;

	// now find all words on the command line 
	while(*c != '\0')
	{
		if(state == STATE_WHITESPACE)
		{
			if(*c != ' ')
			{
				argv[i] = c;		//将argv[i]指向c
				i++;
				state = STATE_WORD;
			}
		}
		else
		{ // state == STATE_WORD 
			if(*c == ' ')
			{
				*c = '\0';
				state = STATE_WHITESPACE;
			}
		}
		c++;
	}
	
	*argc = i;
#undef STATE_WHITESPACE
#undef STATE_WORD
}

static int GetCmdMatche(char *cmdline)
{
	int i;	
	
	for(i=0; CMD_INNER[i].cmd!=NULL; i++)
	{
		if(strncmp(CMD_INNER[i].cmd, cmdline, strlen(CMD_INNER[i].cmd))==0)
			return i;
	}
	
	return -1;
}

static int ParseCmd(char *cmdline, int cmd_len)
{
	int argc, num_commands;
	char *argv[MAX_ARGS];

	ParseArgs(cmdline, &argc, argv);
	
//	 only whitespace 
	if(argc == 0) 
		return -1;
	
	num_commands = GetCmdMatche(argv[0]);
		
	if(num_commands<0)
		return -1;
		
	if(CMD_INNER[num_commands].proc!=NULL)	
	    {
	    CMD_INNER[num_commands].proc(argc, argv);
		}		
	return 0;			
}
#endif
/*********************************************************/

#define BlinkLED() {mLED_1 = ((ReadCoreTimer() & 0x0200000) != 0);}
#define BlinkLED2() {mLED_2 = ((ReadCoreTimer() & 0x0200000) != 0);}
#define BlinkLED3() {mLED_1 = ((ReadCoreTimer() & 0x2000000) != 0);}

BOOL PutMyDLChar() 
{
  if(ReadCoreTimer()>=SECONDS )
  { 
   PutChar('>');
   
   WriteCoreTimer(0); 
   return TRUE;
  }
  else return FALSE;
}

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

int main (void)
{
    //int s = DFT_DOWNLOAD_ADDR;
    int i, key;
	int time_out0;
	char command[MAX_CMD_LEN];	
	unsigned int pb_clock;
	
	SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

	mCTClearIntFlag();
    OpenCoreTimer(SECONDS);

	//setup LED ports
	TRISBbits.TRISB0 = 0;
	TRISBbits.TRISB1 = 0;
	TRISBbits.TRISB2 = 0;

	BOOL FlashGood = FALSE;
	
	// SETUP UART COMMS: No parity, one stop bit, autobaud, polled
//	OpenUART1(UART_EN|UART_EN_ABAUD|UART_BRGH_FOUR, UART_RX_ENABLE | UART_TX_ENABLE, 0 );	
	//OpenUART1(UART_EN|UART_EN_ABAUD|UART_BRGH_FOUR, UART_RX_ENABLE | UART_TX_ENABLE, 0 );	
//    OpenUART1(UART_EN | UART_BRGH_FOUR,  UART_RX_ENABLE | UART_TX_ENABLE, mUARTBRG(80000000, 115200));	

    UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY);
    UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
    UARTSetLineControl(UART1,UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
    UARTSetDataRate(UART1, 80000000, 115200);//UART1_BAUDRATE);
    UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

    //U1MODEbits.ABAUD = 1;		//set autobaud mode
  
    mLED_3=0;mLED_2=0;
/*	
 	while(U1MODEbits.ABAUD  )		//wait for sync character U	
	{
		if( FlashGood && mCTGetIntFlag() )
		{
			//timeout while waiting for sync from pc - jump to user app
			JumpToApp();
		}
			
		BlinkLED();		
	} 		
*/
 /*************************************/
/*
    PutChar(0x0c);PutChar(0x0c);  
    next_line();
    Puts("********************************************\r\n");
	Puts("*          VDC300 BIOS BOOT                *\r\n");
	Puts("*         GT-BIOS GT-SS1-V1.0              *\r\n");
	Puts("*VDC300 Design By XXD(xiang_xudong@163.com)*\r\n");
    Puts("********************************************\r\n");
	Puts("Build Date:");
	Puts(__DATE__);
	Puts("  Time:");
	Puts(__TIME__);
	next_line();
*/
	//check flash contents
	FlashGood = VerifyFlash();
    if(FlashGood)
     Puts("Program OK\r\n");
   else
     Puts("Program Not Complete\r\n");
   //	while(U1MODEbits.ABAUD  )		//wait for sync character U	
   		


//#define WAIT_TIME0	0x20000	
	time_out0 = 10;//WAIT_TIME0;	
	do{
	
	    dog();

	if(kbhit())
		{
			key = getkey();
			if (key == ENTER_KEY) break;
			//else if(key == '<') mLED_3=1;
           
		}

	  BlinkLED2();
     // PutMyDLChar();
      
     if(PutMyDLChar())
     {
       if((--time_out0==0)&&FlashGood)
          //timeout while waiting for sync from pc - jump to user app
		 JumpToApp();
 	 }
    
		
	}while(1);

#if SHELL_CMD==1

	next_line();
	

	prompt();		
	
	i = 0;
	time_out0=0;
	for(;;)
	{dog();
		if(kbhit())
		{
			key = getkey();
			if(key == BACK_KEY)
			{			
				i -= i?1:0;
				PutChar(key);
			}
			else
			if(key == ENTER_KEY)
			{
				int tmp;
				command[i] = 0;
				next_line();
				tmp = ParseCmd(command, i);
				if(tmp<0)
				{
					Puts("Bad command\r\n");
				    //Boot();
				}
				else
				   time_out0=0;	
				prompt();
				
				i = 0;
			}
			else
			{
				if(i<MAX_CMD_LEN-1)
				{
					command[i++] = key;
					PutChar(key);
				}
			}				
		}
		else
		{
         BlinkLED3();
		  //if(time_out0++>=0x20000) Boot();
		}
		
	}
#else
	next_line();
	

	prompt();		
	
	i = 0;
	time_out0=0;
	for(;;)
	{dog();
		if(kbhit())
		{
			key = getkey();
			if(key == BACK_KEY)
			{			
				i -= i?1:0;
				PutChar(key);
			}
			else
			if(key == ENTER_KEY)
			{
				int tmp;
				command[i] = 0;
				next_line();
				//tmp = ParseCmd(command, i);
				if(strstr(command,"auto")!=NULL)
                {
                   LoadFromUart();
                   JumpToApp();
                }
/*
                if(tmp<0)
				{
					Puts("Bad command\r\n");
				    //Boot();
				}
				else
				   time_out0=0;	
				prompt();
*/				
				i = 0;
			}
			else
			{
				if(i<MAX_CMD_LEN-1)
				{
					command[i++] = key;
					PutChar(key);
				}
			}				
		}
		else
		{
         BlinkLED3();
		  //if(time_out0++>=0x20000) Boot();
		}
		
	}
#endif
}





/********************************************************************
* Function: 	void PutChar(BYTE Char)
*
* Precondition: UART Setup
*
* Input: 		Char - Character to transmit
*
* Output: 		None
*
* Side Effects:	Puts character into destination pointed to by ptrChar.
*
* Overview: 	Transmits a character on UART2. 
*	 			Waits for an empty spot in TXREG FIFO.
*
* Note:		 	None
********************************************************************/
void PutChar(BYTE txChar)
{
	while( BusyUART1() );
	putcUART1(txChar);
}



void Puts(char *s)
{
	while ( *s )
 	{
    PutChar(*s++);
	}
   return;
	    
} 
/*
int vsprintf(char * , const char * , __va_list );
void Printf(char *fmt, ...)
{
	va_list ap;
    char string[256];    

    va_start(ap, fmt);
    vsprintf(string, fmt, ap);
    Puts(string);         //UartSendString(CONSOLE_UART, string);
    va_end(ap);
}
*/
int kbhit()
{   
    if(UART1_RXREG_IS_NOTNULL) return 1;
    else return 0;
}

int getkey()
{
    unsigned char recchar;
	if(read_byte(&recchar))     //UartReceive(CONSOLE_UART);
      return recchar;
    else
      return 0; 
}
unsigned char read_byte(unsigned char *recchar)
{

	BYTE dummy;
	/*
	//check for receive errors
	if((U1STA & 0x000E) != 0x0000)
	{
		dummy = U1RXREG; 			//dummy read to clear FERR/PERR
		U1STAbits.OERR = 0;			//clear OERR to keep receiving
	}
	*/
	//get the data
	if(UART1_RXREG_IS_NOTNULL)
	{
		*recchar= U1RXREG;		//get data from UART RX FIFO
		return TRUE;
	}
	else
		return FALSE;

} /* end read_serial_byte() */

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值